pax_global_header00006660000000000000000000000064131051164000014501gustar00rootroot0000000000000052 comment=c80d3321d0f77bef8cfff8b32490a07c1e90a5ad grpc-1.3.2/000077500000000000000000000000001310511640000124375ustar00rootroot00000000000000grpc-1.3.2/.clang-format000066400000000000000000000000641310511640000150120ustar00rootroot00000000000000--- Language: Cpp BasedOnStyle: Google ... grpc-1.3.2/.clang_complete000066400000000000000000000002751310511640000154200ustar00rootroot00000000000000-Ithird_party/googletest/include -Ithird_party/googletest -Iinclude -Igens -I. -Ithird_party/boringssl/include -Ithird_party/benchmark/include -Ithird_party/zlib -Ithird_party/protobuf/src grpc-1.3.2/.editorconfig000066400000000000000000000001611310511640000151120ustar00rootroot00000000000000root = true [**] end_of_line = LF indent_style = space indent_size = 2 insert_final_newline = true tab_width = 8 grpc-1.3.2/.gitignore000066400000000000000000000027241310511640000144340ustar00rootroot00000000000000# C/C++ build outputs .build/ bins gens libs objs # Python items cython_debug/ python_build/ yapf_virtual_environment/ python_pylint_venv/ .coverage* .eggs htmlcov/ dist/ *.egg py27/ py34/ # Node installation output node_modules src/node/extension_binary/ # gcov coverage data reports coverage *.gcno # profiler output *.prof # python compiled objects *.pyc # eclipse project files .cproject .project .settings # cache for run_tests.py .run_tests_cache .preprocessed_build # emacs temp files *~ # vim temp files .*.swp # Makefile's cache cache.mk # Ruby's local gem information Gemfile.lock # Temporary test reports report.xml latency_trace.txt latency_trace.*.txt # port server log portlog.txt # gyp generated make files *-gyp.mk out # YCM config files .ycm_extra_conf.py # XCode ^build/ *.pbxuser !default.pbxuser *.mode1v3 !default.mode1v3 *.mode2v3 !default.mode2v3 *.perspectivev3 !default.perspectivev3 xcuserdata *.xccheckout *.moved-aside DerivedData *.hmap *.ipa *.xcuserstate *.DS_Store # Objective-C generated files *.pbobjc.* *.pbrpc.* # Cocoapods artifacts # Podfile.lock and the workspace file are tracked, to ease deleting them. That's # needed to trigger "pod install" to rerun the preinstall commands. Pods/ # Artifacts directory /artifacts/ # Git generated files for conflicting *.orig # IDE specific folder for JetBrains IDEs .idea/ # Blaze files bazel-bin bazel-genfiles bazel-grpc bazel-out bazel-testlogs # Debug output gdb.txt # ctags file tags grpc-1.3.2/.gitmodules000066400000000000000000000020231310511640000146110ustar00rootroot00000000000000[submodule "third_party/zlib"] path = third_party/zlib url = https://github.com/madler/zlib [submodule "third_party/protobuf"] path = third_party/protobuf url = https://github.com/google/protobuf.git branch = 3.0.x [submodule "third_party/gflags"] path = third_party/gflags url = https://github.com/gflags/gflags.git [submodule "third_party/googletest"] path = third_party/googletest url = https://github.com/google/googletest.git [submodule "third_party/boringssl"] path = third_party/boringssl url = https://github.com/google/boringssl.git [submodule "third_party/thrift"] path = third_party/thrift url = https://github.com/apache/thrift.git [submodule "third_party/benchmark"] path = third_party/benchmark url = https://github.com/google/benchmark [submodule "third_party/boringssl-with-bazel"] path = third_party/boringssl-with-bazel url = https://boringssl.googlesource.com/boringssl [submodule "third_party/cares/cares"] path = third_party/cares/cares url = https://github.com/c-ares/c-ares.git branch = cares-1_12_0 grpc-1.3.2/.istanbul.yml000066400000000000000000000002071310511640000150600ustar00rootroot00000000000000reporting: watermarks: statements: [80, 95] lines: [80, 95] functions: [80, 95] branches: [80, 95] grpc-1.3.2/.pylintrc000066400000000000000000000031171310511640000143060ustar00rootroot00000000000000[VARIABLES] # TODO(https://github.com/PyCQA/pylint/issues/1345): How does the inspection # not include "unused_" and "ignored_" by default? dummy-variables-rgx=^ignored_|^unused_ [DESIGN] # NOTE(nathaniel): Not particularly attached to this value; it just seems to # be what works for us at the moment (excepting the dead-code-walking Beta # API). max-args=6 [MISCELLANEOUS] # NOTE(nathaniel): We are big fans of "TODO(): " and # "NOTE(): ". We do not allow "TODO:", # "TODO():", "FIXME:", or anything else. notes=FIXME,XXX [MESSAGES CONTROL] #TODO: Enable missing-docstring #TODO: Enable too-few-public-methods #TODO: Enable no-init #TODO: Enable duplicate-code #TODO: Enable invalid-name #TODO: Enable locally-disabled #TODO: Enable protected-access #TODO: Enable no-name-in-module #TODO: Enable wrong-import-order # TODO(https://github.com/PyCQA/pylint/issues/59#issuecomment-283774279): # enable cyclic-import after a 1.7-or-later pylint release that recognizes our # disable=cyclic-import suppressions. #TODO: Enable too-many-instance-attributes #TODO: Enable too-many-lines #TODO: Enable redefined-variable-type #TODO: Enable next-method-called #TODO: Enable import-error #TODO: Enable useless-else-on-loop #TODO: Enable too-many-nested-blocks disable=missing-docstring,too-few-public-methods,no-init,duplicate-code,invalid-name,locally-disabled,protected-access,no-name-in-module,wrong-import-order,cyclic-import,too-many-instance-attributes,too-many-lines,redefined-variable-type,next-method-called,import-error,useless-else-on-loop,too-many-nested-blocks grpc-1.3.2/.rspec000077500000000000000000000001371310511640000135600ustar00rootroot00000000000000-Isrc/ruby -Isrc/ruby/pb --backtrace --require spec/spec_helper --format documentation --color grpc-1.3.2/.travis.yml000066400000000000000000000052061310511640000145530ustar00rootroot00000000000000git: depth: 1 language: objective-c osx_image: xcode7.3 env: global: - CONFIG=opt - TEST=objc - JOBS=1 matrix: - SCHEME="RxLibraryUnitTests" WORKSPACE="Tests.xcworkspace" TEST_PATH="src/objective-c/tests" BUILD_ONLY="false" INTEROP_SERVER="false" - SCHEME="InteropTestsLocalSSL" WORKSPACE="Tests.xcworkspace" TEST_PATH="src/objective-c/tests" BUILD_ONLY="false" INTEROP_SERVER="true" - SCHEME="InteropTestsLocalCleartext" WORKSPACE="Tests.xcworkspace" TEST_PATH="src/objective-c/tests" BUILD_ONLY="false" INTEROP_SERVER="true" # TODO(jcanizales): Make tests an app project (instead of library), so the following will work. # - SCHEME="InteropTestsRemote" # WORKSPACE="Tests.xcworkspace" TEST_PATH="src/objective-c/tests" BUILD_ONLY="false" # INTEROP_SERVER="true" - SCHEME="HelloWorld" WORKSPACE="HelloWorld.xcworkspace" TEST_PATH="examples/objective-c/helloworld" BUILD_ONLY="true" INTEROP_SERVER="false" - SCHEME="RouteGuideClient" WORKSPACE="RouteGuideClient.xcworkspace" TEST_PATH="examples/objective-c/route_guide" BUILD_ONLY="true" INTEROP_SERVER="false" - SCHEME="AuthSample" WORKSPACE="AuthSample.xcworkspace" TEST_PATH="examples/objective-c/auth_sample" BUILD_ONLY="true" INTEROP_SERVER="false" - SCHEME="Sample" WORKSPACE="Sample.xcworkspace" TEST_PATH="src/objective-c/examples/Sample" BUILD_ONLY="true" INTEROP_SERVER="false" - SCHEME="Sample" WORKSPACE="Sample.xcworkspace" TEST_PATH="src/objective-c/examples/Sample" BUILD_ONLY="true" INTEROP_SERVER="false" FRAMEWORKS="YES" - SCHEME="SwiftSample" WORKSPACE="SwiftSample.xcworkspace" TEST_PATH="src/objective-c/examples/SwiftSample" BUILD_ONLY="true" INTEROP_SERVER="false" before_install: # Until Travis upgrades from Cocoapods 0.39, we need to do it here. - pod --version - gem uninstall cocoapods -a - gem install cocoapods -v '1.0.1' - pod --version # Recent pods aren't found if we don't explicitly update Cocoapods' repo. - pod repo update - brew install gflags install: - pushd $TEST_PATH - pod install - popd before_script: - if [ "${INTEROP_SERVER}" = "true" ]; then make interop_server; (bins/$CONFIG/interop_server --port=5050 &); (bins/$CONFIG/interop_server --port=5051 --use_tls &); fi script: - if [ "${BUILD_ONLY}" = "true" ]; then xctool -workspace "$TEST_PATH/$WORKSPACE" -scheme "$SCHEME" -sdk iphonesimulator9.3 build; else xctool -workspace "$TEST_PATH/$WORKSPACE" -scheme "$SCHEME" -sdk iphonesimulator9.3 test; fi notifications: email: false grpc-1.3.2/.vscode/000077500000000000000000000000001310511640000140005ustar00rootroot00000000000000grpc-1.3.2/.vscode/launch.json000066400000000000000000000015121310511640000161440ustar00rootroot00000000000000{ "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "Mocha Tests", "cwd": "${workspaceRoot}", "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/mocha", "windows": { "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/mocha.cmd" }, "runtimeArgs": [ "-u", "tdd", "--timeout", "999999", "--colors", "${workspaceRoot}/src/node/test" ], "internalConsoleOptions": "openOnSessionStart" }, { "type": "node", "request": "attach", "name": "Attach to Process", "port": 5858 } ] } grpc-1.3.2/.yardopts000066400000000000000000000000201310511640000142750ustar00rootroot00000000000000src/ruby/**/*.rbgrpc-1.3.2/BUILD000066400000000000000000001426211310511640000132270ustar00rootroot00000000000000# gRPC Bazel BUILD file. # # Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. licenses(["notice"]) # 3-clause BSD exports_files(["LICENSE"]) package(default_visibility = ["//visibility:public"]) load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_proto_plugin") # This should be updated along with build.yaml g_stands_for = "gentle" core_version = "3.0.0" version = "1.3.2" grpc_cc_library( name = "gpr", language = "c", standalone = True, deps = [ "gpr_base", ], ) grpc_cc_library( name = "grpc", srcs = [ "src/core/lib/surface/init.c", "src/core/plugin_registry/grpc_plugin_registry.c", ], language = "c", standalone = True, deps = [ "census", "grpc_base", "grpc_lb_policy_grpclb_secure", "grpc_lb_policy_pick_first", "grpc_lb_policy_round_robin", "grpc_load_reporting", "grpc_max_age_filter", "grpc_resolver_dns_ares", "grpc_resolver_dns_native", "grpc_resolver_sockaddr", "grpc_secure", "grpc_transport_chttp2_client_insecure", "grpc_transport_chttp2_client_secure", "grpc_transport_chttp2_server_insecure", "grpc_transport_chttp2_server_secure", ], ) grpc_cc_library( name = "grpc_cronet", srcs = [ "src/core/lib/surface/init.c", "src/core/plugin_registry/grpc_cronet_plugin_registry.c", ], language = "c", deps = [ "grpc_base", "grpc_transport_chttp2_client_secure", "grpc_transport_cronet_client_secure", ], ) grpc_cc_library( name = "grpc_unsecure", srcs = [ "src/core/lib/surface/init.c", "src/core/lib/surface/init_unsecure.c", "src/core/plugin_registry/grpc_unsecure_plugin_registry.c", ], language = "c", standalone = True, deps = [ "census", "grpc_base", "grpc_lb_policy_grpclb", "grpc_lb_policy_pick_first", "grpc_lb_policy_round_robin", "grpc_load_reporting", "grpc_max_age_filter", "grpc_resolver_dns_native", "grpc_resolver_sockaddr", "grpc_transport_chttp2_client_insecure", "grpc_transport_chttp2_server_insecure", ], ) grpc_cc_library( name = "grpc++", srcs = [ "src/cpp/client/insecure_credentials.cc", "src/cpp/client/secure_credentials.cc", "src/cpp/common/auth_property_iterator.cc", "src/cpp/common/secure_auth_context.cc", "src/cpp/common/secure_channel_arguments.cc", "src/cpp/common/secure_create_auth_context.cc", "src/cpp/server/insecure_server_credentials.cc", "src/cpp/server/secure_server_credentials.cc", ], hdrs = [ "src/cpp/client/secure_credentials.h", "src/cpp/common/secure_auth_context.h", "src/cpp/server/secure_server_credentials.h", ], language = "c++", standalone = True, deps = [ "gpr", "grpc", "grpc++_base", "grpc++_codegen_base", "grpc++_codegen_base_src", "grpc++_codegen_proto", ], ) grpc_cc_library( name = "grpc++_unsecure", srcs = [ "src/cpp/client/insecure_credentials.cc", "src/cpp/common/insecure_create_auth_context.cc", "src/cpp/server/insecure_server_credentials.cc", ], language = "c++", standalone = True, deps = [ "gpr", "grpc++_base", "grpc++_codegen_base", "grpc++_codegen_base_src", "grpc_unsecure", ], ) grpc_cc_library( name = "grpc++_error_details", srcs = [ "src/cpp/util/error_details.cc", ], hdrs = [ "include/grpc++/support/error_details.h", ], language = "c++", standalone = True, deps = [ "grpc++", "//src/proto/grpc/status:status_proto", ], ) grpc_cc_library( name = "grpc_plugin_support", srcs = [ "src/compiler/cpp_generator.cc", "src/compiler/csharp_generator.cc", "src/compiler/node_generator.cc", "src/compiler/objective_c_generator.cc", "src/compiler/php_generator.cc", "src/compiler/python_generator.cc", "src/compiler/ruby_generator.cc", ], hdrs = [ "src/compiler/config.h", "src/compiler/cpp_generator.h", "src/compiler/cpp_generator_helpers.h", "src/compiler/csharp_generator.h", "src/compiler/csharp_generator_helpers.h", "src/compiler/generator_helpers.h", "src/compiler/node_generator.h", "src/compiler/node_generator_helpers.h", "src/compiler/objective_c_generator.h", "src/compiler/objective_c_generator_helpers.h", "src/compiler/php_generator.h", "src/compiler/php_generator_helpers.h", "src/compiler/protobuf_plugin.h", "src/compiler/python_generator.h", "src/compiler/python_generator_helpers.h", "src/compiler/python_private_generator.h", "src/compiler/ruby_generator.h", "src/compiler/ruby_generator_helpers-inl.h", "src/compiler/ruby_generator_map-inl.h", "src/compiler/ruby_generator_string-inl.h", "src/compiler/schema_interface.h", ], external_deps = [ "protobuf_clib", ], language = "c++", deps = [ "grpc++_config_proto", ], ) grpc_proto_plugin( name = "grpc_cpp_plugin", srcs = ["src/compiler/cpp_plugin.cc"], deps = [":grpc_plugin_support"], ) grpc_proto_plugin( name = "grpc_csharp_plugin", srcs = ["src/compiler/csharp_plugin.cc"], deps = [":grpc_plugin_support"], ) grpc_proto_plugin( name = "grpc_node_plugin", srcs = ["src/compiler/node_plugin.cc"], deps = [":grpc_plugin_support"], ) grpc_proto_plugin( name = "grpc_objective_c_plugin", srcs = ["src/compiler/objective_c_plugin.cc"], deps = [":grpc_plugin_support"], ) grpc_proto_plugin( name = "grpc_php_plugin", srcs = ["src/compiler/php_plugin.cc"], deps = [":grpc_plugin_support"], ) grpc_proto_plugin( name = "grpc_python_plugin", srcs = ["src/compiler/python_plugin.cc"], deps = [":grpc_plugin_support"], ) grpc_proto_plugin( name = "grpc_ruby_plugin", srcs = ["src/compiler/ruby_plugin.cc"], deps = [":grpc_plugin_support"], ) grpc_cc_library( name = "grpc_csharp_ext", srcs = [ "src/csharp/ext/grpc_csharp_ext.c", ], language = "csharp", deps = [ "gpr", "grpc", ], ) grpc_cc_library( name = "census", srcs = [ "src/core/ext/census/base_resources.c", "src/core/ext/census/context.c", "src/core/ext/census/gen/census.pb.c", "src/core/ext/census/gen/trace_context.pb.c", "src/core/ext/census/grpc_context.c", "src/core/ext/census/grpc_filter.c", "src/core/ext/census/grpc_plugin.c", "src/core/ext/census/initialize.c", "src/core/ext/census/mlog.c", "src/core/ext/census/operation.c", "src/core/ext/census/placeholders.c", "src/core/ext/census/resource.c", "src/core/ext/census/trace_context.c", "src/core/ext/census/tracing.c", ], hdrs = [ "src/core/ext/census/aggregation.h", "src/core/ext/census/base_resources.h", "src/core/ext/census/census_interface.h", "src/core/ext/census/census_rpc_stats.h", "src/core/ext/census/gen/census.pb.h", "src/core/ext/census/gen/trace_context.pb.h", "src/core/ext/census/grpc_filter.h", "src/core/ext/census/mlog.h", "src/core/ext/census/resource.h", "src/core/ext/census/rpc_metric_id.h", "src/core/ext/census/trace_context.h", "src/core/ext/census/trace_label.h", "src/core/ext/census/trace_propagation.h", "src/core/ext/census/trace_status.h", "src/core/ext/census/trace_string.h", "src/core/ext/census/tracing.h", ], external_deps = [ "nanopb", "libssl", ], language = "c", public_hdrs = [ "include/grpc/census.h", ], deps = [ "grpc_base", ], ) grpc_cc_library( name = "gpr_base", srcs = [ "src/core/lib/profiling/basic_timers.c", "src/core/lib/profiling/stap_timers.c", "src/core/lib/support/alloc.c", "src/core/lib/support/arena.c", "src/core/lib/support/atm.c", "src/core/lib/support/avl.c", "src/core/lib/support/backoff.c", "src/core/lib/support/cmdline.c", "src/core/lib/support/cpu_iphone.c", "src/core/lib/support/cpu_linux.c", "src/core/lib/support/cpu_posix.c", "src/core/lib/support/cpu_windows.c", "src/core/lib/support/env_linux.c", "src/core/lib/support/env_posix.c", "src/core/lib/support/env_windows.c", "src/core/lib/support/histogram.c", "src/core/lib/support/host_port.c", "src/core/lib/support/log.c", "src/core/lib/support/log_android.c", "src/core/lib/support/log_linux.c", "src/core/lib/support/log_posix.c", "src/core/lib/support/log_windows.c", "src/core/lib/support/mpscq.c", "src/core/lib/support/murmur_hash.c", "src/core/lib/support/stack_lockfree.c", "src/core/lib/support/string.c", "src/core/lib/support/string_posix.c", "src/core/lib/support/string_util_windows.c", "src/core/lib/support/string_windows.c", "src/core/lib/support/subprocess_posix.c", "src/core/lib/support/subprocess_windows.c", "src/core/lib/support/sync.c", "src/core/lib/support/sync_posix.c", "src/core/lib/support/sync_windows.c", "src/core/lib/support/thd.c", "src/core/lib/support/thd_posix.c", "src/core/lib/support/thd_windows.c", "src/core/lib/support/time.c", "src/core/lib/support/time_posix.c", "src/core/lib/support/time_precise.c", "src/core/lib/support/time_windows.c", "src/core/lib/support/tls_pthread.c", "src/core/lib/support/tmpfile_msys.c", "src/core/lib/support/tmpfile_posix.c", "src/core/lib/support/tmpfile_windows.c", "src/core/lib/support/wrap_memcpy.c", ], hdrs = [ "src/core/lib/profiling/timers.h", "src/core/lib/support/arena.h", "src/core/lib/support/backoff.h", "src/core/lib/support/block_annotate.h", "src/core/lib/support/env.h", "src/core/lib/support/mpscq.h", "src/core/lib/support/murmur_hash.h", "src/core/lib/support/spinlock.h", "src/core/lib/support/stack_lockfree.h", "src/core/lib/support/string.h", "src/core/lib/support/string_windows.h", "src/core/lib/support/thd_internal.h", "src/core/lib/support/time_precise.h", "src/core/lib/support/tmpfile.h", ], language = "c", public_hdrs = [ "include/grpc/support/alloc.h", "include/grpc/support/atm.h", "include/grpc/support/atm_gcc_atomic.h", "include/grpc/support/atm_gcc_sync.h", "include/grpc/support/atm_windows.h", "include/grpc/support/avl.h", "include/grpc/support/cmdline.h", "include/grpc/support/cpu.h", "include/grpc/support/histogram.h", "include/grpc/support/host_port.h", "include/grpc/support/log.h", "include/grpc/support/log_windows.h", "include/grpc/support/port_platform.h", "include/grpc/support/string_util.h", "include/grpc/support/subprocess.h", "include/grpc/support/sync.h", "include/grpc/support/sync_generic.h", "include/grpc/support/sync_posix.h", "include/grpc/support/sync_windows.h", "include/grpc/support/thd.h", "include/grpc/support/time.h", "include/grpc/support/tls.h", "include/grpc/support/tls_gcc.h", "include/grpc/support/tls_msvc.h", "include/grpc/support/tls_pthread.h", "include/grpc/support/useful.h", ], deps = [ "gpr_codegen", ], ) grpc_cc_library( name = "gpr_codegen", language = "c", public_hdrs = [ "include/grpc/impl/codegen/atm.h", "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.h", "include/grpc/impl/codegen/gpr_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/sync.h", "include/grpc/impl/codegen/sync_generic.h", "include/grpc/impl/codegen/sync_posix.h", "include/grpc/impl/codegen/sync_windows.h", ], ) grpc_cc_library( name = "grpc_base", srcs = [ "src/core/lib/channel/channel_args.c", "src/core/lib/channel/channel_stack.c", "src/core/lib/channel/channel_stack_builder.c", "src/core/lib/channel/compress_filter.c", "src/core/lib/channel/connected_channel.c", "src/core/lib/channel/deadline_filter.c", "src/core/lib/channel/handshaker.c", "src/core/lib/channel/handshaker_factory.c", "src/core/lib/channel/handshaker_registry.c", "src/core/lib/channel/http_client_filter.c", "src/core/lib/channel/http_server_filter.c", "src/core/lib/channel/message_size_filter.c", "src/core/lib/compression/compression.c", "src/core/lib/compression/message_compress.c", "src/core/lib/debug/trace.c", "src/core/lib/http/format_request.c", "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", "src/core/lib/iomgr/closure.c", "src/core/lib/iomgr/combiner.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_uv.c", "src/core/lib/iomgr/endpoint_pair_windows.c", "src/core/lib/iomgr/error.c", "src/core/lib/iomgr/ev_epoll_linux.c", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_posix.c", "src/core/lib/iomgr/exec_ctx.c", "src/core/lib/iomgr/executor.c", "src/core/lib/iomgr/iocp_windows.c", "src/core/lib/iomgr/iomgr.c", "src/core/lib/iomgr/iomgr_posix.c", "src/core/lib/iomgr/iomgr_uv.c", "src/core/lib/iomgr/iomgr_windows.c", "src/core/lib/iomgr/load_file.c", "src/core/lib/iomgr/lockfree_event.c", "src/core/lib/iomgr/network_status_tracker.c", "src/core/lib/iomgr/polling_entity.c", "src/core/lib/iomgr/pollset_set_uv.c", "src/core/lib/iomgr/pollset_set_windows.c", "src/core/lib/iomgr/pollset_uv.c", "src/core/lib/iomgr/pollset_windows.c", "src/core/lib/iomgr/resolve_address_posix.c", "src/core/lib/iomgr/resolve_address_uv.c", "src/core/lib/iomgr/resolve_address_windows.c", "src/core/lib/iomgr/resource_quota.c", "src/core/lib/iomgr/sockaddr_utils.c", "src/core/lib/iomgr/socket_factory_posix.c", "src/core/lib/iomgr/socket_mutator.c", "src/core/lib/iomgr/socket_utils_common_posix.c", "src/core/lib/iomgr/socket_utils_linux.c", "src/core/lib/iomgr/socket_utils_posix.c", "src/core/lib/iomgr/socket_utils_uv.c", "src/core/lib/iomgr/socket_utils_windows.c", "src/core/lib/iomgr/socket_windows.c", "src/core/lib/iomgr/tcp_client_posix.c", "src/core/lib/iomgr/tcp_client_uv.c", "src/core/lib/iomgr/tcp_client_windows.c", "src/core/lib/iomgr/tcp_posix.c", "src/core/lib/iomgr/tcp_server_posix.c", "src/core/lib/iomgr/tcp_server_utils_posix_common.c", "src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c", "src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c", "src/core/lib/iomgr/tcp_server_uv.c", "src/core/lib/iomgr/tcp_server_windows.c", "src/core/lib/iomgr/tcp_uv.c", "src/core/lib/iomgr/tcp_windows.c", "src/core/lib/iomgr/time_averaged_stats.c", "src/core/lib/iomgr/timer_generic.c", "src/core/lib/iomgr/timer_heap.c", "src/core/lib/iomgr/timer_uv.c", "src/core/lib/iomgr/udp_server.c", "src/core/lib/iomgr/unix_sockets_posix.c", "src/core/lib/iomgr/unix_sockets_posix_noop.c", "src/core/lib/iomgr/wakeup_fd_cv.c", "src/core/lib/iomgr/wakeup_fd_eventfd.c", "src/core/lib/iomgr/wakeup_fd_nospecial.c", "src/core/lib/iomgr/wakeup_fd_pipe.c", "src/core/lib/iomgr/wakeup_fd_posix.c", "src/core/lib/iomgr/workqueue_uv.c", "src/core/lib/iomgr/workqueue_windows.c", "src/core/lib/json/json.c", "src/core/lib/json/json_reader.c", "src/core/lib/json/json_string.c", "src/core/lib/json/json_writer.c", "src/core/lib/slice/b64.c", "src/core/lib/slice/percent_encoding.c", "src/core/lib/slice/slice.c", "src/core/lib/slice/slice_buffer.c", "src/core/lib/slice/slice_hash_table.c", "src/core/lib/slice/slice_intern.c", "src/core/lib/slice/slice_string_helpers.c", "src/core/lib/surface/alarm.c", "src/core/lib/surface/api_trace.c", "src/core/lib/surface/byte_buffer.c", "src/core/lib/surface/byte_buffer_reader.c", "src/core/lib/surface/call.c", "src/core/lib/surface/call_details.c", "src/core/lib/surface/call_log_batch.c", "src/core/lib/surface/channel.c", "src/core/lib/surface/channel_init.c", "src/core/lib/surface/channel_ping.c", "src/core/lib/surface/channel_stack_type.c", "src/core/lib/surface/completion_queue.c", "src/core/lib/surface/completion_queue_factory.c", "src/core/lib/surface/event_string.c", "src/core/lib/surface/lame_client.c", "src/core/lib/surface/metadata_array.c", "src/core/lib/surface/server.c", "src/core/lib/surface/validate_metadata.c", "src/core/lib/surface/version.c", "src/core/lib/transport/bdp_estimator.c", "src/core/lib/transport/byte_stream.c", "src/core/lib/transport/connectivity_state.c", "src/core/lib/transport/error_utils.c", "src/core/lib/transport/metadata.c", "src/core/lib/transport/metadata_batch.c", "src/core/lib/transport/pid_controller.c", "src/core/lib/transport/service_config.c", "src/core/lib/transport/static_metadata.c", "src/core/lib/transport/status_conversion.c", "src/core/lib/transport/timeout_encoding.c", "src/core/lib/transport/transport.c", "src/core/lib/transport/transport_op_string.c", ], hdrs = [ "src/core/lib/channel/channel_args.h", "src/core/lib/channel/channel_stack.h", "src/core/lib/channel/channel_stack_builder.h", "src/core/lib/channel/compress_filter.h", "src/core/lib/channel/connected_channel.h", "src/core/lib/channel/context.h", "src/core/lib/channel/deadline_filter.h", "src/core/lib/channel/handshaker.h", "src/core/lib/channel/handshaker_factory.h", "src/core/lib/channel/handshaker_registry.h", "src/core/lib/channel/http_client_filter.h", "src/core/lib/channel/http_server_filter.h", "src/core/lib/channel/message_size_filter.h", "src/core/lib/compression/algorithm_metadata.h", "src/core/lib/compression/message_compress.h", "src/core/lib/debug/trace.h", "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", "src/core/lib/iomgr/closure.h", "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", "src/core/lib/iomgr/error_internal.h", "src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", "src/core/lib/iomgr/executor.h", "src/core/lib/iomgr/iocp_windows.h", "src/core/lib/iomgr/iomgr.h", "src/core/lib/iomgr/iomgr_internal.h", "src/core/lib/iomgr/iomgr_posix.h", "src/core/lib/iomgr/load_file.h", "src/core/lib/iomgr/lockfree_event.h", "src/core/lib/iomgr/network_status_tracker.h", "src/core/lib/iomgr/polling_entity.h", "src/core/lib/iomgr/pollset.h", "src/core/lib/iomgr/pollset_set.h", "src/core/lib/iomgr/pollset_set_windows.h", "src/core/lib/iomgr/pollset_uv.h", "src/core/lib/iomgr/pollset_windows.h", "src/core/lib/iomgr/port.h", "src/core/lib/iomgr/resolve_address.h", "src/core/lib/iomgr/resource_quota.h", "src/core/lib/iomgr/sockaddr.h", "src/core/lib/iomgr/sockaddr_posix.h", "src/core/lib/iomgr/sockaddr_utils.h", "src/core/lib/iomgr/sockaddr_windows.h", "src/core/lib/iomgr/socket_factory_posix.h", "src/core/lib/iomgr/socket_mutator.h", "src/core/lib/iomgr/socket_utils.h", "src/core/lib/iomgr/socket_utils_posix.h", "src/core/lib/iomgr/socket_windows.h", "src/core/lib/iomgr/tcp_client.h", "src/core/lib/iomgr/tcp_client_posix.h", "src/core/lib/iomgr/tcp_posix.h", "src/core/lib/iomgr/tcp_server.h", "src/core/lib/iomgr/tcp_server_utils_posix.h", "src/core/lib/iomgr/tcp_uv.h", "src/core/lib/iomgr/tcp_windows.h", "src/core/lib/iomgr/time_averaged_stats.h", "src/core/lib/iomgr/timer.h", "src/core/lib/iomgr/timer_generic.h", "src/core/lib/iomgr/timer_heap.h", "src/core/lib/iomgr/timer_uv.h", "src/core/lib/iomgr/udp_server.h", "src/core/lib/iomgr/unix_sockets_posix.h", "src/core/lib/iomgr/wakeup_fd_cv.h", "src/core/lib/iomgr/wakeup_fd_pipe.h", "src/core/lib/iomgr/wakeup_fd_posix.h", "src/core/lib/iomgr/workqueue.h", "src/core/lib/iomgr/workqueue_uv.h", "src/core/lib/iomgr/workqueue_windows.h", "src/core/lib/json/json.h", "src/core/lib/json/json_common.h", "src/core/lib/json/json_reader.h", "src/core/lib/json/json_writer.h", "src/core/lib/slice/b64.h", "src/core/lib/slice/percent_encoding.h", "src/core/lib/slice/slice_hash_table.h", "src/core/lib/slice/slice_internal.h", "src/core/lib/slice/slice_string_helpers.h", "src/core/lib/surface/api_trace.h", "src/core/lib/surface/call.h", "src/core/lib/surface/call_test_only.h", "src/core/lib/surface/channel.h", "src/core/lib/surface/channel_init.h", "src/core/lib/surface/channel_stack_type.h", "src/core/lib/surface/completion_queue.h", "src/core/lib/surface/completion_queue_factory.h", "src/core/lib/surface/event_string.h", "src/core/lib/surface/init.h", "src/core/lib/surface/lame_client.h", "src/core/lib/surface/server.h", "src/core/lib/surface/validate_metadata.h", "src/core/lib/transport/bdp_estimator.h", "src/core/lib/transport/byte_stream.h", "src/core/lib/transport/connectivity_state.h", "src/core/lib/transport/error_utils.h", "src/core/lib/transport/http2_errors.h", "src/core/lib/transport/metadata.h", "src/core/lib/transport/metadata_batch.h", "src/core/lib/transport/pid_controller.h", "src/core/lib/transport/service_config.h", "src/core/lib/transport/static_metadata.h", "src/core/lib/transport/status_conversion.h", "src/core/lib/transport/timeout_encoding.h", "src/core/lib/transport/transport.h", "src/core/lib/transport/transport_impl.h", ], external_deps = [ "zlib", ], language = "c", public_hdrs = [ "include/grpc/byte_buffer.h", "include/grpc/byte_buffer_reader.h", "include/grpc/compression.h", "include/grpc/load_reporting.h", "include/grpc/grpc.h", "include/grpc/grpc_posix.h", "include/grpc/grpc_security_constants.h", "include/grpc/slice.h", "include/grpc/slice_buffer.h", "include/grpc/status.h", ], deps = [ "gpr_base", "grpc_codegen", ], ) grpc_cc_library( name = "grpc_client_channel", srcs = [ "src/core/ext/filters/client_channel/channel_connectivity.c", "src/core/ext/filters/client_channel/client_channel.c", "src/core/ext/filters/client_channel/client_channel_factory.c", "src/core/ext/filters/client_channel/client_channel_plugin.c", "src/core/ext/filters/client_channel/connector.c", "src/core/ext/filters/client_channel/http_connect_handshaker.c", "src/core/ext/filters/client_channel/http_proxy.c", "src/core/ext/filters/client_channel/lb_policy.c", "src/core/ext/filters/client_channel/lb_policy_factory.c", "src/core/ext/filters/client_channel/lb_policy_registry.c", "src/core/ext/filters/client_channel/parse_address.c", "src/core/ext/filters/client_channel/proxy_mapper.c", "src/core/ext/filters/client_channel/proxy_mapper_registry.c", "src/core/ext/filters/client_channel/resolver.c", "src/core/ext/filters/client_channel/resolver_factory.c", "src/core/ext/filters/client_channel/resolver_registry.c", "src/core/ext/filters/client_channel/retry_throttle.c", "src/core/ext/filters/client_channel/subchannel.c", "src/core/ext/filters/client_channel/subchannel_index.c", "src/core/ext/filters/client_channel/uri_parser.c", ], hdrs = [ "src/core/ext/filters/client_channel/client_channel.h", "src/core/ext/filters/client_channel/client_channel_factory.h", "src/core/ext/filters/client_channel/connector.h", "src/core/ext/filters/client_channel/http_connect_handshaker.h", "src/core/ext/filters/client_channel/http_proxy.h", "src/core/ext/filters/client_channel/lb_policy.h", "src/core/ext/filters/client_channel/lb_policy_factory.h", "src/core/ext/filters/client_channel/lb_policy_registry.h", "src/core/ext/filters/client_channel/parse_address.h", "src/core/ext/filters/client_channel/proxy_mapper.h", "src/core/ext/filters/client_channel/proxy_mapper_registry.h", "src/core/ext/filters/client_channel/resolver.h", "src/core/ext/filters/client_channel/resolver_factory.h", "src/core/ext/filters/client_channel/resolver_registry.h", "src/core/ext/filters/client_channel/retry_throttle.h", "src/core/ext/filters/client_channel/subchannel.h", "src/core/ext/filters/client_channel/subchannel_index.h", "src/core/ext/filters/client_channel/uri_parser.h", ], language = "c", deps = [ "grpc_base", ], ) grpc_cc_library( name = "grpc_max_age_filter", srcs = [ "src/core/ext/filters/max_age/max_age_filter.c", ], hdrs = [ "src/core/ext/filters/max_age/max_age_filter.h", ], language = "c", deps = [ "grpc_base", ], ) grpc_cc_library( name = "grpc_codegen", language = "c", public_hdrs = [ "include/grpc/impl/codegen/byte_buffer_reader.h", "include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/connectivity_state.h", "include/grpc/impl/codegen/exec_ctx_fwd.h", "include/grpc/impl/codegen/grpc_types.h", "include/grpc/impl/codegen/propagation_bits.h", "include/grpc/impl/codegen/status.h", "include/grpc/impl/codegen/slice.h", ], deps = [ "gpr_codegen", ], ) grpc_cc_library( name = "grpc_lb_policy_grpclb", srcs = [ "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.c", "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c", "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", ], hdrs = [ "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h", ], external_deps = [ "nanopb", ], language = "c", deps = [ "grpc_base", "grpc_client_channel", ], ) grpc_cc_library( name = "grpc_lb_policy_grpclb_secure", srcs = [ "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c", "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c", "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", ], hdrs = [ "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h", ], external_deps = [ "nanopb", ], language = "c", deps = [ "grpc_base", "grpc_client_channel", "grpc_secure", ], ) grpc_cc_library( name = "grpc_lb_policy_pick_first", srcs = [ "src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c", ], language = "c", deps = [ "grpc_base", "grpc_client_channel", ], ) grpc_cc_library( name = "grpc_lb_policy_round_robin", srcs = [ "src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c", ], language = "c", deps = [ "grpc_base", "grpc_client_channel", ], ) grpc_cc_library( name = "grpc_load_reporting", srcs = [ "src/core/ext/filters/load_reporting/load_reporting.c", "src/core/ext/filters/load_reporting/load_reporting_filter.c", ], hdrs = [ "src/core/ext/filters/load_reporting/load_reporting.h", "src/core/ext/filters/load_reporting/load_reporting_filter.h", ], language = "c", deps = [ "grpc_base", ], ) grpc_cc_library( name = "grpc_resolver_dns_native", srcs = [ "src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.c", ], language = "c", deps = [ "grpc_base", "grpc_client_channel", ], ) grpc_cc_library( name = "grpc_resolver_dns_ares", srcs = [ "src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c", ], hdrs = [ "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h", ], external_deps = [ "cares", ], language = "c", deps = [ "grpc_base", "grpc_client_channel", ], ) grpc_cc_library( name = "grpc_resolver_sockaddr", srcs = [ "src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c", ], language = "c", deps = [ "grpc_base", "grpc_client_channel", ], ) grpc_cc_library( name = "grpc_secure", srcs = [ "src/core/lib/http/httpcli_security_connector.c", "src/core/lib/security/context/security_context.c", "src/core/lib/security/credentials/composite/composite_credentials.c", "src/core/lib/security/credentials/credentials.c", "src/core/lib/security/credentials/credentials_metadata.c", "src/core/lib/security/credentials/fake/fake_credentials.c", "src/core/lib/security/credentials/google_default/credentials_generic.c", "src/core/lib/security/credentials/google_default/google_default_credentials.c", "src/core/lib/security/credentials/iam/iam_credentials.c", "src/core/lib/security/credentials/jwt/json_token.c", "src/core/lib/security/credentials/jwt/jwt_credentials.c", "src/core/lib/security/credentials/jwt/jwt_verifier.c", "src/core/lib/security/credentials/oauth2/oauth2_credentials.c", "src/core/lib/security/credentials/plugin/plugin_credentials.c", "src/core/lib/security/credentials/ssl/ssl_credentials.c", "src/core/lib/security/transport/client_auth_filter.c", "src/core/lib/security/transport/lb_targets_info.c", "src/core/lib/security/transport/secure_endpoint.c", "src/core/lib/security/transport/security_connector.c", "src/core/lib/security/transport/security_handshaker.c", "src/core/lib/security/transport/server_auth_filter.c", "src/core/lib/security/transport/tsi_error.c", "src/core/lib/security/util/json_util.c", "src/core/lib/surface/init_secure.c", ], hdrs = [ "src/core/lib/security/context/security_context.h", "src/core/lib/security/credentials/composite/composite_credentials.h", "src/core/lib/security/credentials/credentials.h", "src/core/lib/security/credentials/fake/fake_credentials.h", "src/core/lib/security/credentials/google_default/google_default_credentials.h", "src/core/lib/security/credentials/iam/iam_credentials.h", "src/core/lib/security/credentials/jwt/json_token.h", "src/core/lib/security/credentials/jwt/jwt_credentials.h", "src/core/lib/security/credentials/jwt/jwt_verifier.h", "src/core/lib/security/credentials/oauth2/oauth2_credentials.h", "src/core/lib/security/credentials/plugin/plugin_credentials.h", "src/core/lib/security/credentials/ssl/ssl_credentials.h", "src/core/lib/security/transport/auth_filters.h", "src/core/lib/security/transport/lb_targets_info.h", "src/core/lib/security/transport/secure_endpoint.h", "src/core/lib/security/transport/security_connector.h", "src/core/lib/security/transport/security_handshaker.h", "src/core/lib/security/transport/tsi_error.h", "src/core/lib/security/util/json_util.h", ], language = "c", public_hdrs = [ "include/grpc/grpc_security.h", ], deps = [ "grpc_base", "grpc_transport_chttp2_alpn", "tsi", ], ) grpc_cc_library( name = "grpc_transport_chttp2", srcs = [ "src/core/ext/transport/chttp2/transport/bin_decoder.c", "src/core/ext/transport/chttp2/transport/bin_encoder.c", "src/core/ext/transport/chttp2/transport/chttp2_plugin.c", "src/core/ext/transport/chttp2/transport/chttp2_transport.c", "src/core/ext/transport/chttp2/transport/frame_data.c", "src/core/ext/transport/chttp2/transport/frame_goaway.c", "src/core/ext/transport/chttp2/transport/frame_ping.c", "src/core/ext/transport/chttp2/transport/frame_rst_stream.c", "src/core/ext/transport/chttp2/transport/frame_settings.c", "src/core/ext/transport/chttp2/transport/frame_window_update.c", "src/core/ext/transport/chttp2/transport/hpack_encoder.c", "src/core/ext/transport/chttp2/transport/hpack_parser.c", "src/core/ext/transport/chttp2/transport/hpack_table.c", "src/core/ext/transport/chttp2/transport/http2_settings.c", "src/core/ext/transport/chttp2/transport/huffsyms.c", "src/core/ext/transport/chttp2/transport/incoming_metadata.c", "src/core/ext/transport/chttp2/transport/parsing.c", "src/core/ext/transport/chttp2/transport/stream_lists.c", "src/core/ext/transport/chttp2/transport/stream_map.c", "src/core/ext/transport/chttp2/transport/varint.c", "src/core/ext/transport/chttp2/transport/writing.c", ], hdrs = [ "src/core/ext/transport/chttp2/transport/bin_decoder.h", "src/core/ext/transport/chttp2/transport/bin_encoder.h", "src/core/ext/transport/chttp2/transport/chttp2_transport.h", "src/core/ext/transport/chttp2/transport/frame.h", "src/core/ext/transport/chttp2/transport/frame_data.h", "src/core/ext/transport/chttp2/transport/frame_goaway.h", "src/core/ext/transport/chttp2/transport/frame_ping.h", "src/core/ext/transport/chttp2/transport/frame_rst_stream.h", "src/core/ext/transport/chttp2/transport/frame_settings.h", "src/core/ext/transport/chttp2/transport/frame_window_update.h", "src/core/ext/transport/chttp2/transport/hpack_encoder.h", "src/core/ext/transport/chttp2/transport/hpack_parser.h", "src/core/ext/transport/chttp2/transport/hpack_table.h", "src/core/ext/transport/chttp2/transport/http2_settings.h", "src/core/ext/transport/chttp2/transport/huffsyms.h", "src/core/ext/transport/chttp2/transport/incoming_metadata.h", "src/core/ext/transport/chttp2/transport/internal.h", "src/core/ext/transport/chttp2/transport/stream_map.h", "src/core/ext/transport/chttp2/transport/varint.h", ], language = "c", deps = [ "grpc_base", "grpc_transport_chttp2_alpn", ], ) grpc_cc_library( name = "grpc_transport_chttp2_alpn", srcs = [ "src/core/ext/transport/chttp2/alpn/alpn.c", ], hdrs = [ "src/core/ext/transport/chttp2/alpn/alpn.h", ], language = "c", deps = [ "gpr", ], ) grpc_cc_library( name = "grpc_transport_chttp2_client_connector", srcs = [ "src/core/ext/transport/chttp2/client/chttp2_connector.c", ], hdrs = [ "src/core/ext/transport/chttp2/client/chttp2_connector.h", ], language = "c", deps = [ "grpc_base", "grpc_client_channel", "grpc_transport_chttp2", ], ) grpc_cc_library( name = "grpc_transport_chttp2_client_insecure", srcs = [ "src/core/ext/transport/chttp2/client/insecure/channel_create.c", "src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c", ], language = "c", deps = [ "grpc_base", "grpc_client_channel", "grpc_transport_chttp2", "grpc_transport_chttp2_client_connector", ], ) grpc_cc_library( name = "grpc_transport_chttp2_client_secure", srcs = [ "src/core/ext/transport/chttp2/client/secure/secure_channel_create.c", ], language = "c", deps = [ "grpc_base", "grpc_client_channel", "grpc_secure", "grpc_transport_chttp2", "grpc_transport_chttp2_client_connector", ], ) grpc_cc_library( name = "grpc_transport_chttp2_server", srcs = [ "src/core/ext/transport/chttp2/server/chttp2_server.c", ], hdrs = [ "src/core/ext/transport/chttp2/server/chttp2_server.h", ], language = "c", deps = [ "grpc_base", "grpc_transport_chttp2", ], ) grpc_cc_library( name = "grpc_transport_chttp2_server_insecure", srcs = [ "src/core/ext/transport/chttp2/server/insecure/server_chttp2.c", "src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c", ], language = "c", deps = [ "grpc_base", "grpc_transport_chttp2", "grpc_transport_chttp2_server", ], ) grpc_cc_library( name = "grpc_transport_chttp2_server_secure", srcs = [ "src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c", ], language = "c", deps = [ "grpc_base", "grpc_secure", "grpc_transport_chttp2", "grpc_transport_chttp2_server", ], ) grpc_cc_library( name = "grpc_transport_cronet_client_secure", srcs = [ "src/core/ext/transport/cronet/client/secure/cronet_channel_create.c", "src/core/ext/transport/cronet/transport/cronet_api_dummy.c", "src/core/ext/transport/cronet/transport/cronet_transport.c", ], hdrs = [ "src/core/ext/transport/cronet/transport/cronet_transport.h", "third_party/objective_c/Cronet/bidirectional_stream_c.h", ], language = "c", public_hdrs = [ "include/grpc/grpc_cronet.h", "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", ], deps = [ "grpc_base", "grpc_transport_chttp2", ], ) grpc_cc_library( name = "tsi", srcs = [ "src/core/tsi/fake_transport_security.c", "src/core/tsi/ssl_transport_security.c", "src/core/tsi/transport_security.c", ], hdrs = [ "src/core/tsi/fake_transport_security.h", "src/core/tsi/ssl_transport_security.h", "src/core/tsi/ssl_types.h", "src/core/tsi/transport_security.h", "src/core/tsi/transport_security_interface.h", ], external_deps = [ "libssl", ], language = "c", deps = [ "gpr", ], ) grpc_cc_library( name = "grpc++_base", srcs = [ "src/cpp/client/channel_cc.cc", "src/cpp/client/client_context.cc", "src/cpp/client/create_channel.cc", "src/cpp/client/create_channel_internal.cc", "src/cpp/client/create_channel_posix.cc", "src/cpp/client/credentials_cc.cc", "src/cpp/client/generic_stub.cc", "src/cpp/common/channel_arguments.cc", "src/cpp/common/channel_filter.cc", "src/cpp/common/completion_queue_cc.cc", "src/cpp/common/core_codegen.cc", "src/cpp/common/resource_quota_cc.cc", "src/cpp/common/rpc_method.cc", "src/cpp/common/version_cc.cc", "src/cpp/server/async_generic_service.cc", "src/cpp/server/channel_argument_option.cc", "src/cpp/server/create_default_thread_pool.cc", "src/cpp/server/dynamic_thread_pool.cc", "src/cpp/server/health/default_health_check_service.cc", "src/cpp/server/health/health.pb.c", "src/cpp/server/health/health_check_service.cc", "src/cpp/server/health/health_check_service_server_builder_option.cc", "src/cpp/server/server_builder.cc", "src/cpp/server/server_cc.cc", "src/cpp/server/server_context.cc", "src/cpp/server/server_credentials.cc", "src/cpp/server/server_posix.cc", "src/cpp/thread_manager/thread_manager.cc", "src/cpp/util/byte_buffer_cc.cc", "src/cpp/util/slice_cc.cc", "src/cpp/util/status.cc", "src/cpp/util/string_ref.cc", "src/cpp/util/time_cc.cc", ], hdrs = [ "src/cpp/client/create_channel_internal.h", "src/cpp/common/channel_filter.h", "src/cpp/server/dynamic_thread_pool.h", "src/cpp/server/health/default_health_check_service.h", "src/cpp/server/health/health.pb.h", "src/cpp/server/thread_pool_interface.h", "src/cpp/thread_manager/thread_manager.h", ], language = "c++", public_hdrs = [ "include/grpc++/alarm.h", "include/grpc++/channel.h", "include/grpc++/client_context.h", "include/grpc++/completion_queue.h", "include/grpc++/create_channel.h", "include/grpc++/create_channel_posix.h", "include/grpc++/ext/health_check_service_server_builder_option.h", "include/grpc++/generic/async_generic_service.h", "include/grpc++/generic/generic_stub.h", "include/grpc++/grpc++.h", "include/grpc++/health_check_service_interface.h", "include/grpc++/impl/call.h", "include/grpc++/impl/channel_argument_option.h", "include/grpc++/impl/client_unary_call.h", "include/grpc++/impl/codegen/core_codegen.h", "include/grpc++/impl/grpc_library.h", "include/grpc++/impl/method_handler_impl.h", "include/grpc++/impl/rpc_method.h", "include/grpc++/impl/rpc_service_method.h", "include/grpc++/impl/serialization_traits.h", "include/grpc++/impl/server_builder_option.h", "include/grpc++/impl/server_builder_plugin.h", "include/grpc++/impl/server_initializer.h", "include/grpc++/impl/service_type.h", "include/grpc++/impl/sync_cxx11.h", "include/grpc++/impl/sync_no_cxx11.h", "include/grpc++/resource_quota.h", "include/grpc++/security/auth_context.h", "include/grpc++/security/auth_metadata_processor.h", "include/grpc++/security/credentials.h", "include/grpc++/security/server_credentials.h", "include/grpc++/server.h", "include/grpc++/server_builder.h", "include/grpc++/server_context.h", "include/grpc++/server_posix.h", "include/grpc++/support/async_stream.h", "include/grpc++/support/async_unary_call.h", "include/grpc++/support/byte_buffer.h", "include/grpc++/support/channel_arguments.h", "include/grpc++/support/config.h", "include/grpc++/support/slice.h", "include/grpc++/support/status.h", "include/grpc++/support/status_code_enum.h", "include/grpc++/support/string_ref.h", "include/grpc++/support/stub_options.h", "include/grpc++/support/sync_stream.h", "include/grpc++/support/time.h", ], deps = [ "grpc", "grpc++_codegen_base", ], ) grpc_cc_library( name = "grpc++_codegen_base", language = "c++", public_hdrs = [ "include/grpc++/impl/codegen/async_stream.h", "include/grpc++/impl/codegen/async_unary_call.h", "include/grpc++/impl/codegen/call.h", "include/grpc++/impl/codegen/call_hook.h", "include/grpc++/impl/codegen/channel_interface.h", "include/grpc++/impl/codegen/client_context.h", "include/grpc++/impl/codegen/client_unary_call.h", "include/grpc++/impl/codegen/completion_queue.h", "include/grpc++/impl/codegen/completion_queue_tag.h", "include/grpc++/impl/codegen/config.h", "include/grpc++/impl/codegen/core_codegen_interface.h", "include/grpc++/impl/codegen/create_auth_context.h", "include/grpc++/impl/codegen/grpc_library.h", "include/grpc++/impl/codegen/metadata_map.h", "include/grpc++/impl/codegen/method_handler_impl.h", "include/grpc++/impl/codegen/rpc_method.h", "include/grpc++/impl/codegen/rpc_service_method.h", "include/grpc++/impl/codegen/security/auth_context.h", "include/grpc++/impl/codegen/serialization_traits.h", "include/grpc++/impl/codegen/server_context.h", "include/grpc++/impl/codegen/server_interface.h", "include/grpc++/impl/codegen/service_type.h", "include/grpc++/impl/codegen/slice.h", "include/grpc++/impl/codegen/status.h", "include/grpc++/impl/codegen/status_code_enum.h", "include/grpc++/impl/codegen/status_helper.h", "include/grpc++/impl/codegen/string_ref.h", "include/grpc++/impl/codegen/stub_options.h", "include/grpc++/impl/codegen/sync_stream.h", "include/grpc++/impl/codegen/time.h", ], deps = [ "grpc_codegen", ], ) grpc_cc_library( name = "grpc++_codegen_base_src", srcs = [ "src/cpp/codegen/codegen_init.cc", ], language = "c++", deps = [ "grpc++_codegen_base", ], ) grpc_cc_library( name = "grpc++_codegen_proto", language = "c++", public_hdrs = [ "include/grpc++/impl/codegen/proto_utils.h", ], deps = [ "grpc++_codegen_base", "grpc++_config_proto", ], ) grpc_cc_library( name = "grpc++_config_proto", external_deps = [ "protobuf", ], language = "c++", public_hdrs = [ "include/grpc++/impl/codegen/config_protobuf.h", ], ) grpc_cc_library( name = "thrift_util", language = "c++", public_hdrs = [ "include/grpc++/impl/codegen/thrift_serializer.h", "include/grpc++/impl/codegen/thrift_utils.h", ], deps = [ "grpc++_codegen_base", ], ) grpc_cc_library( name = "grpc++_reflection", srcs = [ "src/cpp/ext/proto_server_reflection.cc", "src/cpp/ext/proto_server_reflection_plugin.cc", ], hdrs = [ "src/cpp/ext/proto_server_reflection.h", ], language = "c++", public_hdrs = [ "include/grpc++/ext/proto_server_reflection_plugin.h", ], deps = [ ":grpc++", "//src/proto/grpc/reflection/v1alpha:reflection_proto", ], ) grpc-1.3.2/CMakeLists.txt000066400000000000000000014753311310511640000152150ustar00rootroot00000000000000# GRPC global cmake file # This currently builds C and C++ code. # This file has been automatically generated from a template file. # Please look at the templates directory instead. # This file can be regenerated from the template by running # tools/buildgen/generate_projects.sh # # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cmake_minimum_required(VERSION 2.8) set(PACKAGE_NAME "grpc") set(PACKAGE_VERSION "1.3.2") set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_TARNAME "${PACKAGE_NAME}-${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/") project(${PACKAGE_NAME} C CXX) # Options option(gRPC_BUILD_TESTS "Build tests" OFF) if (NOT MSVC) set(gRPC_INSTALL ON CACHE BOOL "Generate installation target") else() set(gRPC_INSTALL OFF CACHE BOOL "Generate installation target") endif() set(gRPC_ZLIB_PROVIDER "module" CACHE STRING "Provider of zlib library") set_property(CACHE gRPC_ZLIB_PROVIDER PROPERTY STRINGS "module" "package") set(gRPC_CARES_PROVIDER "module" CACHE STRING "Provider of c-ares library") set_property(CACHE gRPC_CARES_PROVIDER PROPERTY STRINGS "module" "package") set(gRPC_SSL_PROVIDER "module" CACHE STRING "Provider of ssl library") set_property(CACHE gRPC_SSL_PROVIDER PROPERTY STRINGS "module" "package") set(gRPC_PROTOBUF_PROVIDER "module" CACHE STRING "Provider of protobuf library") set_property(CACHE gRPC_PROTOBUF_PROVIDER PROPERTY STRINGS "module" "package") set(gRPC_GFLAGS_PROVIDER "module" CACHE STRING "Provider of gflags library") set_property(CACHE gRPC_GFLAGS_PROVIDER PROPERTY STRINGS "module" "package") set(gRPC_BENCHMARK_PROVIDER "module" CACHE STRING "Provider of benchmark library") set_property(CACHE gRPC_BENCHMARK_PROVIDER PROPERTY STRINGS "module" "package") set(gRPC_USE_PROTO_LITE OFF CACHE BOOL "Use the protobuf-lite library") if(UNIX) if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(_gRPC_PLATFORM_LINUX ON) elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(_gRPC_PLATFORM_MAC ON) else() set(_gRPC_PLATFORM_POSIX ON) endif() endif() if(WIN32) set(_gRPC_PLATFORM_WINDOWS ON) endif() set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) if (MSVC) include(cmake/msvc_static_runtime.cmake) add_definitions(-D_WIN32_WINNT=0x600 -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -D_WINSOCK_DEPRECATED_NO_WARNINGS) # needed to compile protobuf add_definitions(/wd4065 /wd4506) # TODO(jtattermusch): revisit C4267 occurrences throughout the code add_definitions(/wd4267) endif() if (gRPC_USE_PROTO_LITE) set(_gRPC_PROTOBUF_LIBRARY_NAME "libprotobuf-lite") add_definitions("-DGRPC_USE_PROTO_LITE") else() set(_gRPC_PROTOBUF_LIBRARY_NAME "libprotobuf") endif() if("${gRPC_ZLIB_PROVIDER}" STREQUAL "module") if(NOT ZLIB_ROOT_DIR) set(ZLIB_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/zlib) endif() set(ZLIB_INCLUDE_DIR "${ZLIB_ROOT_DIR}") if(EXISTS "${ZLIB_ROOT_DIR}/CMakeLists.txt") add_subdirectory(${ZLIB_ROOT_DIR} third_party/zlib) if(TARGET zlibstatic) set(_gRPC_ZLIB_LIBRARIES zlibstatic) endif() else() message(WARNING "gRPC_ZLIB_PROVIDER is \"module\" but ZLIB_ROOT_DIR is wrong") endif() elseif("${gRPC_ZLIB_PROVIDER}" STREQUAL "package") find_package(ZLIB) if(TARGET ZLIB::ZLIB) set(_gRPC_ZLIB_LIBRARIES ZLIB::ZLIB) endif() set(_gRPC_FIND_ZLIB "if(NOT ZLIB_FOUND)\n find_package(ZLIB)\nendif()") endif() if("${gRPC_CARES_PROVIDER}" STREQUAL "module") if(NOT CARES_ROOT_DIR) set(CARES_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/c-ares) endif() string(TOLOWER ${CMAKE_SYSTEM_NAME} CARES_SYSTEM_NAME) set(CARES_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/cares/cares") set(CARES_BUILD_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/cares") set(CARES_PLATFORM_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/cares/config_${CARES_SYSTEM_NAME}") if(EXISTS "${CARES_ROOT_DIR}/CMakeLists.txt") if("${CARES_SYSTEM_NAME}" MATCHES "windows") add_definitions(-DCARES_STATICLIB=1) add_definitions(-DWIN32_LEAN_AND_MEAN=1) else() add_definitions(-DHAVE_CONFIG_H=1) add_definitions(-D_GNU_SOURCE=1) endif() add_subdirectory(src/c-ares third_party/cares) if(TARGET cares) set(_gRPC_CARES_LIBRARIES cares) endif() else() message(WARNING "gRPC_CARES_PROVIDER is \"module\" but CARES_ROOT_DIR is wrong") endif() elseif("${gRPC_CARES_PROVIDER}" STREQUAL "package") find_package(CARES) if(TARGET CARES::CARES) set(_gRPC_CARES_LIBRARIES CARES::CARES) endif() set(_gRPC_FIND_CARES "if(NOT CARES_FOUND)\n find_package(CARES)\nendif()") endif() if("${gRPC_PROTOBUF_PROVIDER}" STREQUAL "module") # Building the protobuf tests require gmock what is not part of a standard protobuf checkout. # Disable them unless they are explicitly requested from the cmake command line (when we assume # gmock is downloaded to the right location inside protobuf). if(NOT protobuf_BUILD_TESTS) set(protobuf_BUILD_TESTS OFF CACHE BOOL "Build protobuf tests") endif() if(NOT PROTOBUF_ROOT_DIR) set(PROTOBUF_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/protobuf) endif() set(PROTOBUF_WELLKNOWN_IMPORT_DIR ${PROTOBUF_ROOT_DIR}/src) if(EXISTS "${PROTOBUF_ROOT_DIR}/cmake/CMakeLists.txt") set(protobuf_MSVC_STATIC_RUNTIME OFF CACHE BOOL "Link static runtime libraries") add_subdirectory(${PROTOBUF_ROOT_DIR}/cmake third_party/protobuf) if(TARGET ${_gRPC_PROTOBUF_LIBRARY_NAME}) set(_gRPC_PROTOBUF_LIBRARIES ${_gRPC_PROTOBUF_LIBRARY_NAME}) endif() if(TARGET libprotoc) set(_gRPC_PROTOBUF_PROTOC_LIBRARIES libprotoc) endif() if(TARGET protoc) set(_gRPC_PROTOBUF_PROTOC protoc) endif() else() message(WARNING "gRPC_PROTOBUF_PROVIDER is \"module\" but PROTOBUF_ROOT_DIR is wrong") endif() elseif("${gRPC_PROTOBUF_PROVIDER}" STREQUAL "package") find_package(protobuf CONFIG) if(protobuf_FOUND) if(TARGET protobuf::${_gRPC_PROTOBUF_LIBRARY_NAME}) set(_gRPC_PROTOBUF_LIBRARIES protobuf::${_gRPC_PROTOBUF_LIBRARY_NAME}) endif() if(TARGET protobuf::libprotoc) set(_gRPC_PROTOBUF_PROTOC_LIBRARIES protobuf::libprotoc) endif() if(TARGET protobuf::protoc) set(_gRPC_PROTOBUF_PROTOC protobuf::protoc) endif() set(_gRPC_FIND_PROTOBUF "if(NOT protobuf_FOUND)\n find_package(protobuf CONFIG)\nendif()") else() find_package(Protobuf MODULE) set(_gRPC_FIND_PROTOBUF "if(NOT Protobuf_FOUND)\n find_package(Protobuf)\nendif()") endif() set(PROTOBUF_WELLKNOWN_IMPORT_DIR /usr/local/include) endif() if("${gRPC_SSL_PROVIDER}" STREQUAL "module") if(NOT BORINGSSL_ROOT_DIR) set(BORINGSSL_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/boringssl) endif() if(EXISTS "${BORINGSSL_ROOT_DIR}/CMakeLists.txt") set(OPENSSL_NO_ASM ON) # make boringssl buildable with Visual Studio add_subdirectory(${BORINGSSL_ROOT_DIR} third_party/boringssl) if(TARGET ssl) set(_gRPC_SSL_LIBRARIES ssl) endif() else() message(WARNING "gRPC_SSL_PROVIDER is \"module\" but BORINGSSL_ROOT_DIR is wrong") endif() elseif("${gRPC_SSL_PROVIDER}" STREQUAL "package") find_package(OpenSSL) if(TARGET OpenSSL::SSL) set(_gRPC_SSL_LIBRARIES OpenSSL::SSL) endif() set(_gRPC_FIND_SSL "if(NOT OpenSSL_FOUND)\n find_package(OpenSSL)\nendif()") endif() if("${gRPC_GFLAGS_PROVIDER}" STREQUAL "module") if(NOT GFLAGS_ROOT_DIR) set(GFLAGS_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/gflags) endif() if(EXISTS "${GFLAGS_ROOT_DIR}/CMakeLists.txt") add_subdirectory(${GFLAGS_ROOT_DIR} third_party/gflags) if(TARGET gflags_static) set(_gRPC_GFLAGS_LIBRARIES gflags_static) endif() else() message(WARNING "gRPC_GFLAGS_PROVIDER is \"module\" but GFLAGS_ROOT_DIR is wrong") endif() elseif("${gRPC_GFLAGS_PROVIDER}" STREQUAL "package") find_package(gflags) if(TARGET gflags::gflags) set(_gRPC_GFLAGS_LIBRARIES gflags::gflags) endif() set(_gRPC_FIND_GFLAGS "if(NOT gflags_FOUND)\n find_package(gflags)\nendif()") endif() if("${gRPC_BENCHMARK_PROVIDER}" STREQUAL "module") if(NOT BENCHMARK_ROOT_DIR) set(BENCHMARK_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/benchmark) endif() if(EXISTS "${BENCHMARK_ROOT_DIR}/CMakeLists.txt") add_subdirectory(${BENCHMARK_ROOT_DIR} third_party/benchmark) if(TARGET benchmark) set(_gRPC_BENCHMARK_LIBRARIES benchmark) endif() else() message(WARNING "gRPC_BENCHMARK_PROVIDER is \"module\" but BENCHMARK_ROOT_DIR is wrong") endif() elseif("${gRPC_BENCHMARK_PROVIDER}" STREQUAL "package") find_package(benchmark) if(TARGET benchmark::benchmark) set(_gRPC_BENCHMARK_LIBRARIES benchmark::benchmark) endif() set(_gRPC_FIND_BENCHMARK "if(NOT benchmark_FOUND)\n find_package(benchmark)\nendif()") endif() if(NOT MSVC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") endif() if(UNIX) set(_gRPC_ALLTARGETS_LIBRARIES dl rt m pthread) endif() if(WIN32 AND MSVC) set(_gRPC_BASELIB_LIBRARIES wsock32 ws2_32) endif() include(GNUInstallDirs) if(NOT DEFINED CMAKE_INSTALL_CMAKEDIR) set(CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/gRPC") endif() # Create directory for generated .proto files set(_gRPC_PROTO_GENS_DIR ${CMAKE_BINARY_DIR}/gens) file(MAKE_DIRECTORY ${_gRPC_PROTO_GENS_DIR}) # protobuf_generate_grpc_cpp # -------------------------- # # Add custom commands to process ``.proto`` files to C++ using protoc and # GRPC plugin:: # # protobuf_generate_grpc_cpp [...] # # ``ARGN`` # ``.proto`` files # function(protobuf_generate_grpc_cpp) if(NOT ARGN) message(SEND_ERROR "Error: PROTOBUF_GENERATE_GRPC_CPP() called without any proto files") return() endif() set(_protobuf_include_path -I . -I ${PROTOBUF_WELLKNOWN_IMPORT_DIR}) foreach(FIL ${ARGN}) get_filename_component(ABS_FIL ${FIL} ABSOLUTE) get_filename_component(FIL_WE ${FIL} NAME_WE) file(RELATIVE_PATH REL_FIL ${CMAKE_CURRENT_SOURCE_DIR} ${ABS_FIL}) get_filename_component(REL_DIR ${REL_FIL} DIRECTORY) set(RELFIL_WE "${REL_DIR}/${FIL_WE}") add_custom_command( OUTPUT "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.cc" "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.h" "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.cc" "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.h" COMMAND ${_gRPC_PROTOBUF_PROTOC} ARGS --grpc_out=${_gRPC_PROTO_GENS_DIR} --cpp_out=${_gRPC_PROTO_GENS_DIR} --plugin=protoc-gen-grpc=$ ${_protobuf_include_path} ${REL_FIL} DEPENDS ${ABS_FIL} ${_gRPC_PROTOBUF_PROTOC} grpc_cpp_plugin WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Running gRPC C++ protocol buffer compiler on ${FIL}" VERBATIM) set_source_files_properties("${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.cc" "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.h" "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.cc" "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.h" PROPERTIES GENERATED TRUE) endforeach() endfunction() add_custom_target(plugins DEPENDS grpc_cpp_plugin grpc_csharp_plugin grpc_node_plugin grpc_objective_c_plugin grpc_php_plugin grpc_python_plugin grpc_ruby_plugin ) add_custom_target(tools_c DEPENDS gen_hpack_tables gen_legal_metadata_characters gen_percent_encoding_tables grpc_create_jwt grpc_print_google_default_creds_token grpc_verify_jwt ) add_custom_target(tools_cxx DEPENDS ) add_custom_target(tools DEPENDS tools_c tools_cxx) if (gRPC_BUILD_TESTS) add_custom_target(buildtests_c) add_dependencies(buildtests_c alarm_test) add_dependencies(buildtests_c algorithm_test) add_dependencies(buildtests_c alloc_test) add_dependencies(buildtests_c alpn_test) add_dependencies(buildtests_c arena_test) add_dependencies(buildtests_c bad_server_response_test) add_dependencies(buildtests_c bdp_estimator_test) add_dependencies(buildtests_c bin_decoder_test) add_dependencies(buildtests_c bin_encoder_test) add_dependencies(buildtests_c census_context_test) add_dependencies(buildtests_c census_resource_test) add_dependencies(buildtests_c census_trace_context_test) add_dependencies(buildtests_c channel_create_test) add_dependencies(buildtests_c chttp2_hpack_encoder_test) add_dependencies(buildtests_c chttp2_stream_map_test) add_dependencies(buildtests_c chttp2_varint_test) add_dependencies(buildtests_c combiner_test) add_dependencies(buildtests_c compression_test) add_dependencies(buildtests_c concurrent_connectivity_test) add_dependencies(buildtests_c connection_refused_test) add_dependencies(buildtests_c dns_resolver_connectivity_test) add_dependencies(buildtests_c dns_resolver_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c dualstack_socket_test) endif() add_dependencies(buildtests_c endpoint_pair_test) add_dependencies(buildtests_c error_test) if(_gRPC_PLATFORM_LINUX) add_dependencies(buildtests_c ev_epoll_linux_test) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c fd_conservation_posix_test) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c fd_posix_test) endif() add_dependencies(buildtests_c fling_client) add_dependencies(buildtests_c fling_server) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c fling_stream_test) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c fling_test) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c goaway_server_test) endif() add_dependencies(buildtests_c gpr_avl_test) add_dependencies(buildtests_c gpr_backoff_test) add_dependencies(buildtests_c gpr_cmdline_test) add_dependencies(buildtests_c gpr_cpu_test) add_dependencies(buildtests_c gpr_env_test) add_dependencies(buildtests_c gpr_histogram_test) add_dependencies(buildtests_c gpr_host_port_test) add_dependencies(buildtests_c gpr_log_test) add_dependencies(buildtests_c gpr_mpscq_test) add_dependencies(buildtests_c gpr_spinlock_test) add_dependencies(buildtests_c gpr_stack_lockfree_test) add_dependencies(buildtests_c gpr_string_test) add_dependencies(buildtests_c gpr_sync_test) add_dependencies(buildtests_c gpr_thd_test) add_dependencies(buildtests_c gpr_time_test) add_dependencies(buildtests_c gpr_tls_test) add_dependencies(buildtests_c gpr_useful_test) add_dependencies(buildtests_c grpc_auth_context_test) add_dependencies(buildtests_c grpc_b64_test) add_dependencies(buildtests_c grpc_byte_buffer_reader_test) add_dependencies(buildtests_c grpc_channel_args_test) add_dependencies(buildtests_c grpc_channel_stack_test) add_dependencies(buildtests_c grpc_completion_queue_test) add_dependencies(buildtests_c grpc_completion_queue_threading_test) add_dependencies(buildtests_c grpc_credentials_test) add_dependencies(buildtests_c grpc_fetch_oauth2) add_dependencies(buildtests_c grpc_invalid_channel_args_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c grpc_json_token_test) endif() add_dependencies(buildtests_c grpc_jwt_verifier_test) add_dependencies(buildtests_c grpc_security_connector_test) if(_gRPC_PLATFORM_LINUX) add_dependencies(buildtests_c handshake_client) endif() if(_gRPC_PLATFORM_LINUX) add_dependencies(buildtests_c handshake_server) endif() add_dependencies(buildtests_c hpack_parser_test) add_dependencies(buildtests_c hpack_table_test) add_dependencies(buildtests_c http_parser_test) add_dependencies(buildtests_c httpcli_format_request_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c httpcli_test) endif() if(_gRPC_PLATFORM_LINUX) add_dependencies(buildtests_c httpscli_test) endif() add_dependencies(buildtests_c init_test) add_dependencies(buildtests_c invalid_call_argument_test) add_dependencies(buildtests_c json_rewrite) add_dependencies(buildtests_c json_rewrite_test) add_dependencies(buildtests_c json_stream_error_test) add_dependencies(buildtests_c json_test) add_dependencies(buildtests_c lame_client_test) add_dependencies(buildtests_c lb_policies_test) add_dependencies(buildtests_c load_file_test) add_dependencies(buildtests_c memory_profile_client) add_dependencies(buildtests_c memory_profile_server) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c memory_profile_test) endif() add_dependencies(buildtests_c message_compress_test) add_dependencies(buildtests_c mlog_test) add_dependencies(buildtests_c multiple_server_queues_test) add_dependencies(buildtests_c murmur_hash_test) add_dependencies(buildtests_c no_server_test) add_dependencies(buildtests_c parse_address_test) add_dependencies(buildtests_c percent_encoding_test) if(_gRPC_PLATFORM_LINUX) add_dependencies(buildtests_c pollset_set_test) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c resolve_address_posix_test) endif() add_dependencies(buildtests_c resolve_address_test) add_dependencies(buildtests_c resource_quota_test) add_dependencies(buildtests_c secure_channel_create_test) add_dependencies(buildtests_c secure_endpoint_test) add_dependencies(buildtests_c sequential_connectivity_test) add_dependencies(buildtests_c server_chttp2_test) add_dependencies(buildtests_c server_test) add_dependencies(buildtests_c slice_buffer_test) add_dependencies(buildtests_c slice_string_helpers_test) add_dependencies(buildtests_c slice_test) add_dependencies(buildtests_c sockaddr_resolver_test) add_dependencies(buildtests_c sockaddr_utils_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c socket_utils_test) endif() add_dependencies(buildtests_c status_conversion_test) add_dependencies(buildtests_c stream_owned_slice_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c tcp_client_posix_test) endif() add_dependencies(buildtests_c tcp_client_uv_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c tcp_posix_test) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c tcp_server_posix_test) endif() add_dependencies(buildtests_c tcp_server_uv_test) add_dependencies(buildtests_c time_averaged_stats_test) add_dependencies(buildtests_c timeout_encoding_test) add_dependencies(buildtests_c timer_heap_test) add_dependencies(buildtests_c timer_list_test) add_dependencies(buildtests_c transport_connectivity_state_test) add_dependencies(buildtests_c transport_metadata_test) add_dependencies(buildtests_c transport_pid_controller_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c transport_security_test) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c udp_server_test) endif() add_dependencies(buildtests_c uri_parser_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c wakeup_fd_cv_test) endif() add_dependencies(buildtests_c public_headers_must_be_c89) add_dependencies(buildtests_c badreq_bad_client_test) add_dependencies(buildtests_c connection_prefix_bad_client_test) add_dependencies(buildtests_c head_of_line_blocking_bad_client_test) add_dependencies(buildtests_c headers_bad_client_test) add_dependencies(buildtests_c initial_settings_frame_bad_client_test) add_dependencies(buildtests_c large_metadata_bad_client_test) add_dependencies(buildtests_c server_registered_method_bad_client_test) add_dependencies(buildtests_c simple_request_bad_client_test) add_dependencies(buildtests_c unknown_frame_bad_client_test) add_dependencies(buildtests_c window_overflow_bad_client_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c bad_ssl_cert_server) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c bad_ssl_cert_test) endif() add_dependencies(buildtests_c h2_census_test) add_dependencies(buildtests_c h2_compress_test) add_dependencies(buildtests_c h2_fakesec_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c h2_fd_test) endif() add_dependencies(buildtests_c h2_full_test) if(_gRPC_PLATFORM_LINUX) add_dependencies(buildtests_c h2_full+pipe_test) endif() add_dependencies(buildtests_c h2_full+trace_test) add_dependencies(buildtests_c h2_http_proxy_test) add_dependencies(buildtests_c h2_load_reporting_test) add_dependencies(buildtests_c h2_oauth2_test) add_dependencies(buildtests_c h2_proxy_test) add_dependencies(buildtests_c h2_sockpair_test) add_dependencies(buildtests_c h2_sockpair+trace_test) add_dependencies(buildtests_c h2_sockpair_1byte_test) add_dependencies(buildtests_c h2_ssl_test) add_dependencies(buildtests_c h2_ssl_cert_test) add_dependencies(buildtests_c h2_ssl_proxy_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c h2_uds_test) endif() add_dependencies(buildtests_c h2_census_nosec_test) add_dependencies(buildtests_c h2_compress_nosec_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c h2_fd_nosec_test) endif() add_dependencies(buildtests_c h2_full_nosec_test) if(_gRPC_PLATFORM_LINUX) add_dependencies(buildtests_c h2_full+pipe_nosec_test) endif() add_dependencies(buildtests_c h2_full+trace_nosec_test) add_dependencies(buildtests_c h2_http_proxy_nosec_test) add_dependencies(buildtests_c h2_load_reporting_nosec_test) add_dependencies(buildtests_c h2_proxy_nosec_test) add_dependencies(buildtests_c h2_sockpair_nosec_test) add_dependencies(buildtests_c h2_sockpair+trace_nosec_test) add_dependencies(buildtests_c h2_sockpair_1byte_nosec_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c h2_uds_nosec_test) endif() add_dependencies(buildtests_c api_fuzzer_one_entry) add_dependencies(buildtests_c client_fuzzer_one_entry) add_dependencies(buildtests_c hpack_parser_fuzzer_test_one_entry) add_dependencies(buildtests_c http_request_fuzzer_test_one_entry) add_dependencies(buildtests_c http_response_fuzzer_test_one_entry) add_dependencies(buildtests_c json_fuzzer_test_one_entry) add_dependencies(buildtests_c nanopb_fuzzer_response_test_one_entry) add_dependencies(buildtests_c nanopb_fuzzer_serverlist_test_one_entry) add_dependencies(buildtests_c percent_decode_fuzzer_one_entry) add_dependencies(buildtests_c percent_encode_fuzzer_one_entry) add_dependencies(buildtests_c server_fuzzer_one_entry) add_dependencies(buildtests_c ssl_server_fuzzer_one_entry) add_dependencies(buildtests_c uri_fuzzer_test_one_entry) add_custom_target(buildtests_cxx) add_dependencies(buildtests_cxx alarm_cpp_test) add_dependencies(buildtests_cxx async_end2end_test) add_dependencies(buildtests_cxx auth_property_iterator_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx bm_arena) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx bm_call_create) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx bm_chttp2_hpack) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx bm_chttp2_transport) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx bm_closure) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx bm_cq) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx bm_cq_multiple_threads) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx bm_error) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx bm_fullstack_streaming_ping_pong) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx bm_fullstack_streaming_pump) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx bm_fullstack_trickle) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx bm_fullstack_unary_ping_pong) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx bm_metadata) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx bm_pollset) endif() add_dependencies(buildtests_cxx channel_arguments_test) add_dependencies(buildtests_cxx channel_filter_test) add_dependencies(buildtests_cxx cli_call_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx client_crash_test) endif() add_dependencies(buildtests_cxx client_crash_test_server) add_dependencies(buildtests_cxx codegen_test_full) add_dependencies(buildtests_cxx codegen_test_minimal) add_dependencies(buildtests_cxx credentials_test) add_dependencies(buildtests_cxx cxx_byte_buffer_test) add_dependencies(buildtests_cxx cxx_slice_test) add_dependencies(buildtests_cxx cxx_string_ref_test) add_dependencies(buildtests_cxx cxx_time_test) add_dependencies(buildtests_cxx end2end_test) add_dependencies(buildtests_cxx error_details_test) add_dependencies(buildtests_cxx filter_end2end_test) add_dependencies(buildtests_cxx generic_end2end_test) add_dependencies(buildtests_cxx golden_file_test) add_dependencies(buildtests_cxx grpc_cli) add_dependencies(buildtests_cxx grpc_tool_test) add_dependencies(buildtests_cxx grpclb_api_test) add_dependencies(buildtests_cxx grpclb_test) add_dependencies(buildtests_cxx health_service_end2end_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx http2_client) endif() add_dependencies(buildtests_cxx hybrid_end2end_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx interop_client) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx interop_server) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx interop_test) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx json_run_localhost) endif() add_dependencies(buildtests_cxx metrics_client) add_dependencies(buildtests_cxx mock_test) add_dependencies(buildtests_cxx noop-benchmark) add_dependencies(buildtests_cxx proto_server_reflection_test) add_dependencies(buildtests_cxx proto_utils_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx qps_interarrival_test) endif() add_dependencies(buildtests_cxx qps_json_driver) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx qps_openloop_test) endif() add_dependencies(buildtests_cxx qps_worker) add_dependencies(buildtests_cxx reconnect_interop_client) add_dependencies(buildtests_cxx reconnect_interop_server) add_dependencies(buildtests_cxx round_robin_end2end_test) add_dependencies(buildtests_cxx secure_auth_context_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx secure_sync_unary_ping_pong_test) endif() add_dependencies(buildtests_cxx server_builder_plugin_test) add_dependencies(buildtests_cxx server_builder_test) add_dependencies(buildtests_cxx server_context_test_spouse_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx server_crash_test) endif() add_dependencies(buildtests_cxx server_crash_test_client) add_dependencies(buildtests_cxx shutdown_test) add_dependencies(buildtests_cxx status_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx streaming_throughput_test) endif() add_dependencies(buildtests_cxx stress_test) add_dependencies(buildtests_cxx thread_manager_test) add_dependencies(buildtests_cxx thread_stress_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx writes_per_rpc_test) endif() add_custom_target(buildtests DEPENDS buildtests_c buildtests_cxx) endif (gRPC_BUILD_TESTS) add_library(gpr src/core/lib/profiling/basic_timers.c src/core/lib/profiling/stap_timers.c src/core/lib/support/alloc.c src/core/lib/support/arena.c src/core/lib/support/atm.c src/core/lib/support/avl.c src/core/lib/support/backoff.c src/core/lib/support/cmdline.c src/core/lib/support/cpu_iphone.c src/core/lib/support/cpu_linux.c src/core/lib/support/cpu_posix.c src/core/lib/support/cpu_windows.c src/core/lib/support/env_linux.c src/core/lib/support/env_posix.c src/core/lib/support/env_windows.c src/core/lib/support/histogram.c src/core/lib/support/host_port.c src/core/lib/support/log.c src/core/lib/support/log_android.c src/core/lib/support/log_linux.c src/core/lib/support/log_posix.c src/core/lib/support/log_windows.c src/core/lib/support/mpscq.c src/core/lib/support/murmur_hash.c src/core/lib/support/stack_lockfree.c src/core/lib/support/string.c src/core/lib/support/string_posix.c src/core/lib/support/string_util_windows.c src/core/lib/support/string_windows.c src/core/lib/support/subprocess_posix.c src/core/lib/support/subprocess_windows.c src/core/lib/support/sync.c src/core/lib/support/sync_posix.c src/core/lib/support/sync_windows.c src/core/lib/support/thd.c src/core/lib/support/thd_posix.c src/core/lib/support/thd_windows.c src/core/lib/support/time.c src/core/lib/support/time_posix.c src/core/lib/support/time_precise.c src/core/lib/support/time_windows.c src/core/lib/support/tls_pthread.c src/core/lib/support/tmpfile_msys.c src/core/lib/support/tmpfile_posix.c src/core/lib/support/tmpfile_windows.c src/core/lib/support/wrap_memcpy.c ) if(WIN32 AND MSVC) set_target_properties(gpr PROPERTIES COMPILE_PDB_NAME "gpr" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/gpr.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(gpr PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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(gpr ${_gRPC_ALLTARGETS_LIBRARIES} ) foreach(_hdr include/grpc/support/alloc.h include/grpc/support/atm.h include/grpc/support/atm_gcc_atomic.h include/grpc/support/atm_gcc_sync.h include/grpc/support/atm_windows.h include/grpc/support/avl.h include/grpc/support/cmdline.h include/grpc/support/cpu.h include/grpc/support/histogram.h include/grpc/support/host_port.h include/grpc/support/log.h include/grpc/support/log_windows.h include/grpc/support/port_platform.h include/grpc/support/string_util.h include/grpc/support/subprocess.h include/grpc/support/sync.h include/grpc/support/sync_generic.h include/grpc/support/sync_posix.h include/grpc/support/sync_windows.h include/grpc/support/thd.h include/grpc/support/time.h include/grpc/support/tls.h include/grpc/support/tls_gcc.h include/grpc/support/tls_msvc.h include/grpc/support/tls_pthread.h include/grpc/support/useful.h include/grpc/impl/codegen/atm.h include/grpc/impl/codegen/atm_gcc_atomic.h include/grpc/impl/codegen/atm_gcc_sync.h include/grpc/impl/codegen/atm_windows.h include/grpc/impl/codegen/gpr_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/sync.h include/grpc/impl/codegen/sync_generic.h include/grpc/impl/codegen/sync_posix.h include/grpc/impl/codegen/sync_windows.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) install(FILES ${_hdr} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_path}" ) endforeach() if (gRPC_INSTALL) install(TARGETS gpr EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() if (gRPC_BUILD_TESTS) add_library(gpr_test_util test/core/util/test_config.c ) if(WIN32 AND MSVC) set_target_properties(gpr_test_util PROPERTIES COMPILE_PDB_NAME "gpr_test_util" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/gpr_test_util.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(gpr_test_util PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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(gpr_test_util ${_gRPC_ALLTARGETS_LIBRARIES} gpr ) endif (gRPC_BUILD_TESTS) add_library(grpc src/core/lib/surface/init.c src/core/lib/channel/channel_args.c src/core/lib/channel/channel_stack.c src/core/lib/channel/channel_stack_builder.c src/core/lib/channel/compress_filter.c src/core/lib/channel/connected_channel.c src/core/lib/channel/deadline_filter.c src/core/lib/channel/handshaker.c src/core/lib/channel/handshaker_factory.c src/core/lib/channel/handshaker_registry.c src/core/lib/channel/http_client_filter.c src/core/lib/channel/http_server_filter.c src/core/lib/channel/message_size_filter.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c src/core/lib/debug/trace.c src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c src/core/lib/iomgr/closure.c src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_uv.c src/core/lib/iomgr/endpoint_pair_windows.c src/core/lib/iomgr/error.c src/core/lib/iomgr/ev_epoll_linux.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c src/core/lib/iomgr/executor.c src/core/lib/iomgr/iocp_windows.c src/core/lib/iomgr/iomgr.c src/core/lib/iomgr/iomgr_posix.c src/core/lib/iomgr/iomgr_uv.c src/core/lib/iomgr/iomgr_windows.c src/core/lib/iomgr/load_file.c src/core/lib/iomgr/lockfree_event.c src/core/lib/iomgr/network_status_tracker.c src/core/lib/iomgr/polling_entity.c src/core/lib/iomgr/pollset_set_uv.c src/core/lib/iomgr/pollset_set_windows.c src/core/lib/iomgr/pollset_uv.c src/core/lib/iomgr/pollset_windows.c src/core/lib/iomgr/resolve_address_posix.c src/core/lib/iomgr/resolve_address_uv.c src/core/lib/iomgr/resolve_address_windows.c src/core/lib/iomgr/resource_quota.c src/core/lib/iomgr/sockaddr_utils.c src/core/lib/iomgr/socket_factory_posix.c src/core/lib/iomgr/socket_mutator.c src/core/lib/iomgr/socket_utils_common_posix.c src/core/lib/iomgr/socket_utils_linux.c src/core/lib/iomgr/socket_utils_posix.c src/core/lib/iomgr/socket_utils_uv.c src/core/lib/iomgr/socket_utils_windows.c src/core/lib/iomgr/socket_windows.c src/core/lib/iomgr/tcp_client_posix.c src/core/lib/iomgr/tcp_client_uv.c src/core/lib/iomgr/tcp_client_windows.c src/core/lib/iomgr/tcp_posix.c src/core/lib/iomgr/tcp_server_posix.c src/core/lib/iomgr/tcp_server_utils_posix_common.c src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c src/core/lib/iomgr/tcp_server_uv.c src/core/lib/iomgr/tcp_server_windows.c src/core/lib/iomgr/tcp_uv.c src/core/lib/iomgr/tcp_windows.c src/core/lib/iomgr/time_averaged_stats.c src/core/lib/iomgr/timer_generic.c src/core/lib/iomgr/timer_heap.c src/core/lib/iomgr/timer_uv.c src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c src/core/lib/iomgr/unix_sockets_posix_noop.c src/core/lib/iomgr/wakeup_fd_cv.c src/core/lib/iomgr/wakeup_fd_eventfd.c src/core/lib/iomgr/wakeup_fd_nospecial.c src/core/lib/iomgr/wakeup_fd_pipe.c src/core/lib/iomgr/wakeup_fd_posix.c src/core/lib/iomgr/workqueue_uv.c src/core/lib/iomgr/workqueue_windows.c src/core/lib/json/json.c src/core/lib/json/json_reader.c src/core/lib/json/json_string.c src/core/lib/json/json_writer.c src/core/lib/slice/b64.c src/core/lib/slice/percent_encoding.c src/core/lib/slice/slice.c src/core/lib/slice/slice_buffer.c src/core/lib/slice/slice_hash_table.c src/core/lib/slice/slice_intern.c src/core/lib/slice/slice_string_helpers.c src/core/lib/surface/alarm.c src/core/lib/surface/api_trace.c src/core/lib/surface/byte_buffer.c src/core/lib/surface/byte_buffer_reader.c src/core/lib/surface/call.c src/core/lib/surface/call_details.c src/core/lib/surface/call_log_batch.c src/core/lib/surface/channel.c src/core/lib/surface/channel_init.c src/core/lib/surface/channel_ping.c src/core/lib/surface/channel_stack_type.c src/core/lib/surface/completion_queue.c src/core/lib/surface/completion_queue_factory.c src/core/lib/surface/event_string.c src/core/lib/surface/lame_client.c src/core/lib/surface/metadata_array.c src/core/lib/surface/server.c src/core/lib/surface/validate_metadata.c src/core/lib/surface/version.c src/core/lib/transport/bdp_estimator.c src/core/lib/transport/byte_stream.c src/core/lib/transport/connectivity_state.c src/core/lib/transport/error_utils.c src/core/lib/transport/metadata.c src/core/lib/transport/metadata_batch.c src/core/lib/transport/pid_controller.c src/core/lib/transport/service_config.c src/core/lib/transport/static_metadata.c src/core/lib/transport/status_conversion.c src/core/lib/transport/timeout_encoding.c src/core/lib/transport/transport.c src/core/lib/transport/transport_op_string.c src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c src/core/ext/transport/chttp2/transport/bin_decoder.c src/core/ext/transport/chttp2/transport/bin_encoder.c src/core/ext/transport/chttp2/transport/chttp2_plugin.c src/core/ext/transport/chttp2/transport/chttp2_transport.c src/core/ext/transport/chttp2/transport/frame_data.c src/core/ext/transport/chttp2/transport/frame_goaway.c src/core/ext/transport/chttp2/transport/frame_ping.c src/core/ext/transport/chttp2/transport/frame_rst_stream.c src/core/ext/transport/chttp2/transport/frame_settings.c src/core/ext/transport/chttp2/transport/frame_window_update.c src/core/ext/transport/chttp2/transport/hpack_encoder.c src/core/ext/transport/chttp2/transport/hpack_parser.c src/core/ext/transport/chttp2/transport/hpack_table.c src/core/ext/transport/chttp2/transport/http2_settings.c src/core/ext/transport/chttp2/transport/huffsyms.c src/core/ext/transport/chttp2/transport/incoming_metadata.c src/core/ext/transport/chttp2/transport/parsing.c src/core/ext/transport/chttp2/transport/stream_lists.c src/core/ext/transport/chttp2/transport/stream_map.c src/core/ext/transport/chttp2/transport/varint.c src/core/ext/transport/chttp2/transport/writing.c src/core/ext/transport/chttp2/alpn/alpn.c src/core/lib/http/httpcli_security_connector.c src/core/lib/security/context/security_context.c src/core/lib/security/credentials/composite/composite_credentials.c src/core/lib/security/credentials/credentials.c src/core/lib/security/credentials/credentials_metadata.c src/core/lib/security/credentials/fake/fake_credentials.c src/core/lib/security/credentials/google_default/credentials_generic.c src/core/lib/security/credentials/google_default/google_default_credentials.c src/core/lib/security/credentials/iam/iam_credentials.c src/core/lib/security/credentials/jwt/json_token.c src/core/lib/security/credentials/jwt/jwt_credentials.c src/core/lib/security/credentials/jwt/jwt_verifier.c src/core/lib/security/credentials/oauth2/oauth2_credentials.c src/core/lib/security/credentials/plugin/plugin_credentials.c src/core/lib/security/credentials/ssl/ssl_credentials.c src/core/lib/security/transport/client_auth_filter.c src/core/lib/security/transport/lb_targets_info.c src/core/lib/security/transport/secure_endpoint.c src/core/lib/security/transport/security_connector.c src/core/lib/security/transport/security_handshaker.c src/core/lib/security/transport/server_auth_filter.c src/core/lib/security/transport/tsi_error.c src/core/lib/security/util/json_util.c src/core/lib/surface/init_secure.c src/core/tsi/fake_transport_security.c src/core/tsi/ssl_transport_security.c src/core/tsi/transport_security.c src/core/ext/transport/chttp2/server/chttp2_server.c src/core/ext/transport/chttp2/client/secure/secure_channel_create.c src/core/ext/filters/client_channel/channel_connectivity.c src/core/ext/filters/client_channel/client_channel.c src/core/ext/filters/client_channel/client_channel_factory.c src/core/ext/filters/client_channel/client_channel_plugin.c src/core/ext/filters/client_channel/connector.c src/core/ext/filters/client_channel/http_connect_handshaker.c src/core/ext/filters/client_channel/http_proxy.c src/core/ext/filters/client_channel/lb_policy.c src/core/ext/filters/client_channel/lb_policy_factory.c src/core/ext/filters/client_channel/lb_policy_registry.c src/core/ext/filters/client_channel/parse_address.c src/core/ext/filters/client_channel/proxy_mapper.c src/core/ext/filters/client_channel/proxy_mapper_registry.c src/core/ext/filters/client_channel/resolver.c src/core/ext/filters/client_channel/resolver_factory.c src/core/ext/filters/client_channel/resolver_registry.c src/core/ext/filters/client_channel/retry_throttle.c src/core/ext/filters/client_channel/subchannel.c src/core/ext/filters/client_channel/subchannel_index.c src/core/ext/filters/client_channel/uri_parser.c src/core/ext/transport/chttp2/client/chttp2_connector.c src/core/ext/transport/chttp2/server/insecure/server_chttp2.c src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c src/core/ext/transport/chttp2/client/insecure/channel_create.c src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c third_party/nanopb/pb_common.c third_party/nanopb/pb_decode.c third_party/nanopb/pb_encode.c src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.c src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c src/core/ext/filters/load_reporting/load_reporting.c src/core/ext/filters/load_reporting/load_reporting_filter.c src/core/ext/census/base_resources.c src/core/ext/census/context.c src/core/ext/census/gen/census.pb.c src/core/ext/census/gen/trace_context.pb.c src/core/ext/census/grpc_context.c src/core/ext/census/grpc_filter.c src/core/ext/census/grpc_plugin.c src/core/ext/census/initialize.c src/core/ext/census/mlog.c src/core/ext/census/operation.c src/core/ext/census/placeholders.c src/core/ext/census/resource.c src/core/ext/census/trace_context.c src/core/ext/census/tracing.c src/core/ext/filters/max_age/max_age_filter.c src/core/plugin_registry/grpc_plugin_registry.c ) if(WIN32 AND MSVC) set_target_properties(grpc PROPERTIES COMPILE_PDB_NAME "grpc" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(grpc PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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(grpc ${_gRPC_BASELIB_LIBRARIES} ${_gRPC_SSL_LIBRARIES} ${_gRPC_ZLIB_LIBRARIES} ${_gRPC_CARES_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} gpr ) foreach(_hdr include/grpc/byte_buffer.h include/grpc/byte_buffer_reader.h include/grpc/compression.h include/grpc/grpc.h include/grpc/grpc_posix.h include/grpc/grpc_security_constants.h include/grpc/load_reporting.h include/grpc/slice.h include/grpc/slice_buffer.h include/grpc/status.h include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/connectivity_state.h include/grpc/impl/codegen/exec_ctx_fwd.h include/grpc/impl/codegen/grpc_types.h include/grpc/impl/codegen/propagation_bits.h include/grpc/impl/codegen/slice.h include/grpc/impl/codegen/status.h include/grpc/impl/codegen/atm.h include/grpc/impl/codegen/atm_gcc_atomic.h include/grpc/impl/codegen/atm_gcc_sync.h include/grpc/impl/codegen/atm_windows.h include/grpc/impl/codegen/gpr_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/sync.h include/grpc/impl/codegen/sync_generic.h include/grpc/impl/codegen/sync_posix.h include/grpc/impl/codegen/sync_windows.h include/grpc/grpc_security.h include/grpc/census.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) install(FILES ${_hdr} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_path}" ) endforeach() if (gRPC_INSTALL) install(TARGETS grpc EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() add_library(grpc_cronet src/core/lib/surface/init.c src/core/lib/channel/channel_args.c src/core/lib/channel/channel_stack.c src/core/lib/channel/channel_stack_builder.c src/core/lib/channel/compress_filter.c src/core/lib/channel/connected_channel.c src/core/lib/channel/deadline_filter.c src/core/lib/channel/handshaker.c src/core/lib/channel/handshaker_factory.c src/core/lib/channel/handshaker_registry.c src/core/lib/channel/http_client_filter.c src/core/lib/channel/http_server_filter.c src/core/lib/channel/message_size_filter.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c src/core/lib/debug/trace.c src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c src/core/lib/iomgr/closure.c src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_uv.c src/core/lib/iomgr/endpoint_pair_windows.c src/core/lib/iomgr/error.c src/core/lib/iomgr/ev_epoll_linux.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c src/core/lib/iomgr/executor.c src/core/lib/iomgr/iocp_windows.c src/core/lib/iomgr/iomgr.c src/core/lib/iomgr/iomgr_posix.c src/core/lib/iomgr/iomgr_uv.c src/core/lib/iomgr/iomgr_windows.c src/core/lib/iomgr/load_file.c src/core/lib/iomgr/lockfree_event.c src/core/lib/iomgr/network_status_tracker.c src/core/lib/iomgr/polling_entity.c src/core/lib/iomgr/pollset_set_uv.c src/core/lib/iomgr/pollset_set_windows.c src/core/lib/iomgr/pollset_uv.c src/core/lib/iomgr/pollset_windows.c src/core/lib/iomgr/resolve_address_posix.c src/core/lib/iomgr/resolve_address_uv.c src/core/lib/iomgr/resolve_address_windows.c src/core/lib/iomgr/resource_quota.c src/core/lib/iomgr/sockaddr_utils.c src/core/lib/iomgr/socket_factory_posix.c src/core/lib/iomgr/socket_mutator.c src/core/lib/iomgr/socket_utils_common_posix.c src/core/lib/iomgr/socket_utils_linux.c src/core/lib/iomgr/socket_utils_posix.c src/core/lib/iomgr/socket_utils_uv.c src/core/lib/iomgr/socket_utils_windows.c src/core/lib/iomgr/socket_windows.c src/core/lib/iomgr/tcp_client_posix.c src/core/lib/iomgr/tcp_client_uv.c src/core/lib/iomgr/tcp_client_windows.c src/core/lib/iomgr/tcp_posix.c src/core/lib/iomgr/tcp_server_posix.c src/core/lib/iomgr/tcp_server_utils_posix_common.c src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c src/core/lib/iomgr/tcp_server_uv.c src/core/lib/iomgr/tcp_server_windows.c src/core/lib/iomgr/tcp_uv.c src/core/lib/iomgr/tcp_windows.c src/core/lib/iomgr/time_averaged_stats.c src/core/lib/iomgr/timer_generic.c src/core/lib/iomgr/timer_heap.c src/core/lib/iomgr/timer_uv.c src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c src/core/lib/iomgr/unix_sockets_posix_noop.c src/core/lib/iomgr/wakeup_fd_cv.c src/core/lib/iomgr/wakeup_fd_eventfd.c src/core/lib/iomgr/wakeup_fd_nospecial.c src/core/lib/iomgr/wakeup_fd_pipe.c src/core/lib/iomgr/wakeup_fd_posix.c src/core/lib/iomgr/workqueue_uv.c src/core/lib/iomgr/workqueue_windows.c src/core/lib/json/json.c src/core/lib/json/json_reader.c src/core/lib/json/json_string.c src/core/lib/json/json_writer.c src/core/lib/slice/b64.c src/core/lib/slice/percent_encoding.c src/core/lib/slice/slice.c src/core/lib/slice/slice_buffer.c src/core/lib/slice/slice_hash_table.c src/core/lib/slice/slice_intern.c src/core/lib/slice/slice_string_helpers.c src/core/lib/surface/alarm.c src/core/lib/surface/api_trace.c src/core/lib/surface/byte_buffer.c src/core/lib/surface/byte_buffer_reader.c src/core/lib/surface/call.c src/core/lib/surface/call_details.c src/core/lib/surface/call_log_batch.c src/core/lib/surface/channel.c src/core/lib/surface/channel_init.c src/core/lib/surface/channel_ping.c src/core/lib/surface/channel_stack_type.c src/core/lib/surface/completion_queue.c src/core/lib/surface/completion_queue_factory.c src/core/lib/surface/event_string.c src/core/lib/surface/lame_client.c src/core/lib/surface/metadata_array.c src/core/lib/surface/server.c src/core/lib/surface/validate_metadata.c src/core/lib/surface/version.c src/core/lib/transport/bdp_estimator.c src/core/lib/transport/byte_stream.c src/core/lib/transport/connectivity_state.c src/core/lib/transport/error_utils.c src/core/lib/transport/metadata.c src/core/lib/transport/metadata_batch.c src/core/lib/transport/pid_controller.c src/core/lib/transport/service_config.c src/core/lib/transport/static_metadata.c src/core/lib/transport/status_conversion.c src/core/lib/transport/timeout_encoding.c src/core/lib/transport/transport.c src/core/lib/transport/transport_op_string.c src/core/ext/transport/cronet/client/secure/cronet_channel_create.c src/core/ext/transport/cronet/transport/cronet_api_dummy.c src/core/ext/transport/cronet/transport/cronet_transport.c src/core/ext/transport/chttp2/client/secure/secure_channel_create.c src/core/ext/transport/chttp2/transport/bin_decoder.c src/core/ext/transport/chttp2/transport/bin_encoder.c src/core/ext/transport/chttp2/transport/chttp2_plugin.c src/core/ext/transport/chttp2/transport/chttp2_transport.c src/core/ext/transport/chttp2/transport/frame_data.c src/core/ext/transport/chttp2/transport/frame_goaway.c src/core/ext/transport/chttp2/transport/frame_ping.c src/core/ext/transport/chttp2/transport/frame_rst_stream.c src/core/ext/transport/chttp2/transport/frame_settings.c src/core/ext/transport/chttp2/transport/frame_window_update.c src/core/ext/transport/chttp2/transport/hpack_encoder.c src/core/ext/transport/chttp2/transport/hpack_parser.c src/core/ext/transport/chttp2/transport/hpack_table.c src/core/ext/transport/chttp2/transport/http2_settings.c src/core/ext/transport/chttp2/transport/huffsyms.c src/core/ext/transport/chttp2/transport/incoming_metadata.c src/core/ext/transport/chttp2/transport/parsing.c src/core/ext/transport/chttp2/transport/stream_lists.c src/core/ext/transport/chttp2/transport/stream_map.c src/core/ext/transport/chttp2/transport/varint.c src/core/ext/transport/chttp2/transport/writing.c src/core/ext/transport/chttp2/alpn/alpn.c src/core/ext/filters/client_channel/channel_connectivity.c src/core/ext/filters/client_channel/client_channel.c src/core/ext/filters/client_channel/client_channel_factory.c src/core/ext/filters/client_channel/client_channel_plugin.c src/core/ext/filters/client_channel/connector.c src/core/ext/filters/client_channel/http_connect_handshaker.c src/core/ext/filters/client_channel/http_proxy.c src/core/ext/filters/client_channel/lb_policy.c src/core/ext/filters/client_channel/lb_policy_factory.c src/core/ext/filters/client_channel/lb_policy_registry.c src/core/ext/filters/client_channel/parse_address.c src/core/ext/filters/client_channel/proxy_mapper.c src/core/ext/filters/client_channel/proxy_mapper_registry.c src/core/ext/filters/client_channel/resolver.c src/core/ext/filters/client_channel/resolver_factory.c src/core/ext/filters/client_channel/resolver_registry.c src/core/ext/filters/client_channel/retry_throttle.c src/core/ext/filters/client_channel/subchannel.c src/core/ext/filters/client_channel/subchannel_index.c src/core/ext/filters/client_channel/uri_parser.c src/core/lib/http/httpcli_security_connector.c src/core/lib/security/context/security_context.c src/core/lib/security/credentials/composite/composite_credentials.c src/core/lib/security/credentials/credentials.c src/core/lib/security/credentials/credentials_metadata.c src/core/lib/security/credentials/fake/fake_credentials.c src/core/lib/security/credentials/google_default/credentials_generic.c src/core/lib/security/credentials/google_default/google_default_credentials.c src/core/lib/security/credentials/iam/iam_credentials.c src/core/lib/security/credentials/jwt/json_token.c src/core/lib/security/credentials/jwt/jwt_credentials.c src/core/lib/security/credentials/jwt/jwt_verifier.c src/core/lib/security/credentials/oauth2/oauth2_credentials.c src/core/lib/security/credentials/plugin/plugin_credentials.c src/core/lib/security/credentials/ssl/ssl_credentials.c src/core/lib/security/transport/client_auth_filter.c src/core/lib/security/transport/lb_targets_info.c src/core/lib/security/transport/secure_endpoint.c src/core/lib/security/transport/security_connector.c src/core/lib/security/transport/security_handshaker.c src/core/lib/security/transport/server_auth_filter.c src/core/lib/security/transport/tsi_error.c src/core/lib/security/util/json_util.c src/core/lib/surface/init_secure.c src/core/tsi/fake_transport_security.c src/core/tsi/ssl_transport_security.c src/core/tsi/transport_security.c src/core/ext/transport/chttp2/client/chttp2_connector.c src/core/ext/filters/load_reporting/load_reporting.c src/core/ext/filters/load_reporting/load_reporting_filter.c src/core/plugin_registry/grpc_cronet_plugin_registry.c ) if(WIN32 AND MSVC) set_target_properties(grpc_cronet PROPERTIES COMPILE_PDB_NAME "grpc_cronet" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_cronet.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(grpc_cronet PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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(grpc_cronet ${_gRPC_BASELIB_LIBRARIES} ${_gRPC_SSL_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} gpr ) foreach(_hdr include/grpc/byte_buffer.h include/grpc/byte_buffer_reader.h include/grpc/compression.h include/grpc/grpc.h include/grpc/grpc_posix.h include/grpc/grpc_security_constants.h include/grpc/load_reporting.h include/grpc/slice.h include/grpc/slice_buffer.h include/grpc/status.h include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/connectivity_state.h include/grpc/impl/codegen/exec_ctx_fwd.h include/grpc/impl/codegen/grpc_types.h include/grpc/impl/codegen/propagation_bits.h include/grpc/impl/codegen/slice.h include/grpc/impl/codegen/status.h include/grpc/impl/codegen/atm.h include/grpc/impl/codegen/atm_gcc_atomic.h include/grpc/impl/codegen/atm_gcc_sync.h include/grpc/impl/codegen/atm_windows.h include/grpc/impl/codegen/gpr_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/sync.h include/grpc/impl/codegen/sync_generic.h include/grpc/impl/codegen/sync_posix.h include/grpc/impl/codegen/sync_windows.h include/grpc/grpc_cronet.h include/grpc/grpc_security.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) install(FILES ${_hdr} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_path}" ) endforeach() if (gRPC_INSTALL) install(TARGETS grpc_cronet EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() if (gRPC_BUILD_TESTS) add_library(grpc_test_util test/core/end2end/data/client_certs.c test/core/end2end/data/server1_cert.c test/core/end2end/data/server1_key.c test/core/end2end/data/test_root_cert.c test/core/security/oauth2_utils.c test/core/end2end/cq_verifier.c test/core/end2end/fake_resolver.c test/core/end2end/fixtures/http_proxy_fixture.c test/core/end2end/fixtures/proxy.c test/core/iomgr/endpoint_tests.c test/core/util/debugger_macros.c test/core/util/grpc_profiler.c test/core/util/memory_counters.c test/core/util/mock_endpoint.c test/core/util/parse_hexstring.c test/core/util/passthru_endpoint.c test/core/util/port.c test/core/util/port_server_client.c test/core/util/slice_splitter.c test/core/util/trickle_endpoint.c src/core/lib/channel/channel_args.c src/core/lib/channel/channel_stack.c src/core/lib/channel/channel_stack_builder.c src/core/lib/channel/compress_filter.c src/core/lib/channel/connected_channel.c src/core/lib/channel/deadline_filter.c src/core/lib/channel/handshaker.c src/core/lib/channel/handshaker_factory.c src/core/lib/channel/handshaker_registry.c src/core/lib/channel/http_client_filter.c src/core/lib/channel/http_server_filter.c src/core/lib/channel/message_size_filter.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c src/core/lib/debug/trace.c src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c src/core/lib/iomgr/closure.c src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_uv.c src/core/lib/iomgr/endpoint_pair_windows.c src/core/lib/iomgr/error.c src/core/lib/iomgr/ev_epoll_linux.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c src/core/lib/iomgr/executor.c src/core/lib/iomgr/iocp_windows.c src/core/lib/iomgr/iomgr.c src/core/lib/iomgr/iomgr_posix.c src/core/lib/iomgr/iomgr_uv.c src/core/lib/iomgr/iomgr_windows.c src/core/lib/iomgr/load_file.c src/core/lib/iomgr/lockfree_event.c src/core/lib/iomgr/network_status_tracker.c src/core/lib/iomgr/polling_entity.c src/core/lib/iomgr/pollset_set_uv.c src/core/lib/iomgr/pollset_set_windows.c src/core/lib/iomgr/pollset_uv.c src/core/lib/iomgr/pollset_windows.c src/core/lib/iomgr/resolve_address_posix.c src/core/lib/iomgr/resolve_address_uv.c src/core/lib/iomgr/resolve_address_windows.c src/core/lib/iomgr/resource_quota.c src/core/lib/iomgr/sockaddr_utils.c src/core/lib/iomgr/socket_factory_posix.c src/core/lib/iomgr/socket_mutator.c src/core/lib/iomgr/socket_utils_common_posix.c src/core/lib/iomgr/socket_utils_linux.c src/core/lib/iomgr/socket_utils_posix.c src/core/lib/iomgr/socket_utils_uv.c src/core/lib/iomgr/socket_utils_windows.c src/core/lib/iomgr/socket_windows.c src/core/lib/iomgr/tcp_client_posix.c src/core/lib/iomgr/tcp_client_uv.c src/core/lib/iomgr/tcp_client_windows.c src/core/lib/iomgr/tcp_posix.c src/core/lib/iomgr/tcp_server_posix.c src/core/lib/iomgr/tcp_server_utils_posix_common.c src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c src/core/lib/iomgr/tcp_server_uv.c src/core/lib/iomgr/tcp_server_windows.c src/core/lib/iomgr/tcp_uv.c src/core/lib/iomgr/tcp_windows.c src/core/lib/iomgr/time_averaged_stats.c src/core/lib/iomgr/timer_generic.c src/core/lib/iomgr/timer_heap.c src/core/lib/iomgr/timer_uv.c src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c src/core/lib/iomgr/unix_sockets_posix_noop.c src/core/lib/iomgr/wakeup_fd_cv.c src/core/lib/iomgr/wakeup_fd_eventfd.c src/core/lib/iomgr/wakeup_fd_nospecial.c src/core/lib/iomgr/wakeup_fd_pipe.c src/core/lib/iomgr/wakeup_fd_posix.c src/core/lib/iomgr/workqueue_uv.c src/core/lib/iomgr/workqueue_windows.c src/core/lib/json/json.c src/core/lib/json/json_reader.c src/core/lib/json/json_string.c src/core/lib/json/json_writer.c src/core/lib/slice/b64.c src/core/lib/slice/percent_encoding.c src/core/lib/slice/slice.c src/core/lib/slice/slice_buffer.c src/core/lib/slice/slice_hash_table.c src/core/lib/slice/slice_intern.c src/core/lib/slice/slice_string_helpers.c src/core/lib/surface/alarm.c src/core/lib/surface/api_trace.c src/core/lib/surface/byte_buffer.c src/core/lib/surface/byte_buffer_reader.c src/core/lib/surface/call.c src/core/lib/surface/call_details.c src/core/lib/surface/call_log_batch.c src/core/lib/surface/channel.c src/core/lib/surface/channel_init.c src/core/lib/surface/channel_ping.c src/core/lib/surface/channel_stack_type.c src/core/lib/surface/completion_queue.c src/core/lib/surface/completion_queue_factory.c src/core/lib/surface/event_string.c src/core/lib/surface/lame_client.c src/core/lib/surface/metadata_array.c src/core/lib/surface/server.c src/core/lib/surface/validate_metadata.c src/core/lib/surface/version.c src/core/lib/transport/bdp_estimator.c src/core/lib/transport/byte_stream.c src/core/lib/transport/connectivity_state.c src/core/lib/transport/error_utils.c src/core/lib/transport/metadata.c src/core/lib/transport/metadata_batch.c src/core/lib/transport/pid_controller.c src/core/lib/transport/service_config.c src/core/lib/transport/static_metadata.c src/core/lib/transport/status_conversion.c src/core/lib/transport/timeout_encoding.c src/core/lib/transport/transport.c src/core/lib/transport/transport_op_string.c ) if(WIN32 AND MSVC) set_target_properties(grpc_test_util PROPERTIES COMPILE_PDB_NAME "grpc_test_util" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_test_util.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(grpc_test_util PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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(grpc_test_util ${_gRPC_ALLTARGETS_LIBRARIES} gpr_test_util gpr grpc ) foreach(_hdr include/grpc/byte_buffer.h include/grpc/byte_buffer_reader.h include/grpc/compression.h include/grpc/grpc.h include/grpc/grpc_posix.h include/grpc/grpc_security_constants.h include/grpc/load_reporting.h include/grpc/slice.h include/grpc/slice_buffer.h include/grpc/status.h include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/connectivity_state.h include/grpc/impl/codegen/exec_ctx_fwd.h include/grpc/impl/codegen/grpc_types.h include/grpc/impl/codegen/propagation_bits.h include/grpc/impl/codegen/slice.h include/grpc/impl/codegen/status.h include/grpc/impl/codegen/atm.h include/grpc/impl/codegen/atm_gcc_atomic.h include/grpc/impl/codegen/atm_gcc_sync.h include/grpc/impl/codegen/atm_windows.h include/grpc/impl/codegen/gpr_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/sync.h include/grpc/impl/codegen/sync_generic.h include/grpc/impl/codegen/sync_posix.h include/grpc/impl/codegen/sync_windows.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) install(FILES ${_hdr} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_path}" ) endforeach() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_library(grpc_test_util_unsecure test/core/end2end/cq_verifier.c test/core/end2end/fake_resolver.c test/core/end2end/fixtures/http_proxy_fixture.c test/core/end2end/fixtures/proxy.c test/core/iomgr/endpoint_tests.c test/core/util/debugger_macros.c test/core/util/grpc_profiler.c test/core/util/memory_counters.c test/core/util/mock_endpoint.c test/core/util/parse_hexstring.c test/core/util/passthru_endpoint.c test/core/util/port.c test/core/util/port_server_client.c test/core/util/slice_splitter.c test/core/util/trickle_endpoint.c ) if(WIN32 AND MSVC) set_target_properties(grpc_test_util_unsecure PROPERTIES COMPILE_PDB_NAME "grpc_test_util_unsecure" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_test_util_unsecure.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(grpc_test_util_unsecure PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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(grpc_test_util_unsecure ${_gRPC_ALLTARGETS_LIBRARIES} gpr gpr_test_util grpc_unsecure grpc ) endif (gRPC_BUILD_TESTS) add_library(grpc_unsecure src/core/lib/surface/init.c src/core/lib/surface/init_unsecure.c src/core/lib/channel/channel_args.c src/core/lib/channel/channel_stack.c src/core/lib/channel/channel_stack_builder.c src/core/lib/channel/compress_filter.c src/core/lib/channel/connected_channel.c src/core/lib/channel/deadline_filter.c src/core/lib/channel/handshaker.c src/core/lib/channel/handshaker_factory.c src/core/lib/channel/handshaker_registry.c src/core/lib/channel/http_client_filter.c src/core/lib/channel/http_server_filter.c src/core/lib/channel/message_size_filter.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c src/core/lib/debug/trace.c src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c src/core/lib/iomgr/closure.c src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_uv.c src/core/lib/iomgr/endpoint_pair_windows.c src/core/lib/iomgr/error.c src/core/lib/iomgr/ev_epoll_linux.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c src/core/lib/iomgr/executor.c src/core/lib/iomgr/iocp_windows.c src/core/lib/iomgr/iomgr.c src/core/lib/iomgr/iomgr_posix.c src/core/lib/iomgr/iomgr_uv.c src/core/lib/iomgr/iomgr_windows.c src/core/lib/iomgr/load_file.c src/core/lib/iomgr/lockfree_event.c src/core/lib/iomgr/network_status_tracker.c src/core/lib/iomgr/polling_entity.c src/core/lib/iomgr/pollset_set_uv.c src/core/lib/iomgr/pollset_set_windows.c src/core/lib/iomgr/pollset_uv.c src/core/lib/iomgr/pollset_windows.c src/core/lib/iomgr/resolve_address_posix.c src/core/lib/iomgr/resolve_address_uv.c src/core/lib/iomgr/resolve_address_windows.c src/core/lib/iomgr/resource_quota.c src/core/lib/iomgr/sockaddr_utils.c src/core/lib/iomgr/socket_factory_posix.c src/core/lib/iomgr/socket_mutator.c src/core/lib/iomgr/socket_utils_common_posix.c src/core/lib/iomgr/socket_utils_linux.c src/core/lib/iomgr/socket_utils_posix.c src/core/lib/iomgr/socket_utils_uv.c src/core/lib/iomgr/socket_utils_windows.c src/core/lib/iomgr/socket_windows.c src/core/lib/iomgr/tcp_client_posix.c src/core/lib/iomgr/tcp_client_uv.c src/core/lib/iomgr/tcp_client_windows.c src/core/lib/iomgr/tcp_posix.c src/core/lib/iomgr/tcp_server_posix.c src/core/lib/iomgr/tcp_server_utils_posix_common.c src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c src/core/lib/iomgr/tcp_server_uv.c src/core/lib/iomgr/tcp_server_windows.c src/core/lib/iomgr/tcp_uv.c src/core/lib/iomgr/tcp_windows.c src/core/lib/iomgr/time_averaged_stats.c src/core/lib/iomgr/timer_generic.c src/core/lib/iomgr/timer_heap.c src/core/lib/iomgr/timer_uv.c src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c src/core/lib/iomgr/unix_sockets_posix_noop.c src/core/lib/iomgr/wakeup_fd_cv.c src/core/lib/iomgr/wakeup_fd_eventfd.c src/core/lib/iomgr/wakeup_fd_nospecial.c src/core/lib/iomgr/wakeup_fd_pipe.c src/core/lib/iomgr/wakeup_fd_posix.c src/core/lib/iomgr/workqueue_uv.c src/core/lib/iomgr/workqueue_windows.c src/core/lib/json/json.c src/core/lib/json/json_reader.c src/core/lib/json/json_string.c src/core/lib/json/json_writer.c src/core/lib/slice/b64.c src/core/lib/slice/percent_encoding.c src/core/lib/slice/slice.c src/core/lib/slice/slice_buffer.c src/core/lib/slice/slice_hash_table.c src/core/lib/slice/slice_intern.c src/core/lib/slice/slice_string_helpers.c src/core/lib/surface/alarm.c src/core/lib/surface/api_trace.c src/core/lib/surface/byte_buffer.c src/core/lib/surface/byte_buffer_reader.c src/core/lib/surface/call.c src/core/lib/surface/call_details.c src/core/lib/surface/call_log_batch.c src/core/lib/surface/channel.c src/core/lib/surface/channel_init.c src/core/lib/surface/channel_ping.c src/core/lib/surface/channel_stack_type.c src/core/lib/surface/completion_queue.c src/core/lib/surface/completion_queue_factory.c src/core/lib/surface/event_string.c src/core/lib/surface/lame_client.c src/core/lib/surface/metadata_array.c src/core/lib/surface/server.c src/core/lib/surface/validate_metadata.c src/core/lib/surface/version.c src/core/lib/transport/bdp_estimator.c src/core/lib/transport/byte_stream.c src/core/lib/transport/connectivity_state.c src/core/lib/transport/error_utils.c src/core/lib/transport/metadata.c src/core/lib/transport/metadata_batch.c src/core/lib/transport/pid_controller.c src/core/lib/transport/service_config.c src/core/lib/transport/static_metadata.c src/core/lib/transport/status_conversion.c src/core/lib/transport/timeout_encoding.c src/core/lib/transport/transport.c src/core/lib/transport/transport_op_string.c src/core/ext/transport/chttp2/server/insecure/server_chttp2.c src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c src/core/ext/transport/chttp2/transport/bin_decoder.c src/core/ext/transport/chttp2/transport/bin_encoder.c src/core/ext/transport/chttp2/transport/chttp2_plugin.c src/core/ext/transport/chttp2/transport/chttp2_transport.c src/core/ext/transport/chttp2/transport/frame_data.c src/core/ext/transport/chttp2/transport/frame_goaway.c src/core/ext/transport/chttp2/transport/frame_ping.c src/core/ext/transport/chttp2/transport/frame_rst_stream.c src/core/ext/transport/chttp2/transport/frame_settings.c src/core/ext/transport/chttp2/transport/frame_window_update.c src/core/ext/transport/chttp2/transport/hpack_encoder.c src/core/ext/transport/chttp2/transport/hpack_parser.c src/core/ext/transport/chttp2/transport/hpack_table.c src/core/ext/transport/chttp2/transport/http2_settings.c src/core/ext/transport/chttp2/transport/huffsyms.c src/core/ext/transport/chttp2/transport/incoming_metadata.c src/core/ext/transport/chttp2/transport/parsing.c src/core/ext/transport/chttp2/transport/stream_lists.c src/core/ext/transport/chttp2/transport/stream_map.c src/core/ext/transport/chttp2/transport/varint.c src/core/ext/transport/chttp2/transport/writing.c src/core/ext/transport/chttp2/alpn/alpn.c src/core/ext/transport/chttp2/server/chttp2_server.c src/core/ext/transport/chttp2/client/insecure/channel_create.c src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c src/core/ext/transport/chttp2/client/chttp2_connector.c src/core/ext/filters/client_channel/channel_connectivity.c src/core/ext/filters/client_channel/client_channel.c src/core/ext/filters/client_channel/client_channel_factory.c src/core/ext/filters/client_channel/client_channel_plugin.c src/core/ext/filters/client_channel/connector.c src/core/ext/filters/client_channel/http_connect_handshaker.c src/core/ext/filters/client_channel/http_proxy.c src/core/ext/filters/client_channel/lb_policy.c src/core/ext/filters/client_channel/lb_policy_factory.c src/core/ext/filters/client_channel/lb_policy_registry.c src/core/ext/filters/client_channel/parse_address.c src/core/ext/filters/client_channel/proxy_mapper.c src/core/ext/filters/client_channel/proxy_mapper_registry.c src/core/ext/filters/client_channel/resolver.c src/core/ext/filters/client_channel/resolver_factory.c src/core/ext/filters/client_channel/resolver_registry.c src/core/ext/filters/client_channel/retry_throttle.c src/core/ext/filters/client_channel/subchannel.c src/core/ext/filters/client_channel/subchannel_index.c src/core/ext/filters/client_channel/uri_parser.c src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.c src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c src/core/ext/filters/load_reporting/load_reporting.c src/core/ext/filters/load_reporting/load_reporting_filter.c src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.c src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c third_party/nanopb/pb_common.c third_party/nanopb/pb_decode.c third_party/nanopb/pb_encode.c src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c src/core/ext/census/base_resources.c src/core/ext/census/context.c src/core/ext/census/gen/census.pb.c src/core/ext/census/gen/trace_context.pb.c src/core/ext/census/grpc_context.c src/core/ext/census/grpc_filter.c src/core/ext/census/grpc_plugin.c src/core/ext/census/initialize.c src/core/ext/census/mlog.c src/core/ext/census/operation.c src/core/ext/census/placeholders.c src/core/ext/census/resource.c src/core/ext/census/trace_context.c src/core/ext/census/tracing.c src/core/ext/filters/max_age/max_age_filter.c src/core/plugin_registry/grpc_unsecure_plugin_registry.c ) if(WIN32 AND MSVC) set_target_properties(grpc_unsecure PROPERTIES COMPILE_PDB_NAME "grpc_unsecure" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_unsecure.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(grpc_unsecure PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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(grpc_unsecure ${_gRPC_BASELIB_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} gpr ) foreach(_hdr include/grpc/byte_buffer.h include/grpc/byte_buffer_reader.h include/grpc/compression.h include/grpc/grpc.h include/grpc/grpc_posix.h include/grpc/grpc_security_constants.h include/grpc/load_reporting.h include/grpc/slice.h include/grpc/slice_buffer.h include/grpc/status.h include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/connectivity_state.h include/grpc/impl/codegen/exec_ctx_fwd.h include/grpc/impl/codegen/grpc_types.h include/grpc/impl/codegen/propagation_bits.h include/grpc/impl/codegen/slice.h include/grpc/impl/codegen/status.h include/grpc/impl/codegen/atm.h include/grpc/impl/codegen/atm_gcc_atomic.h include/grpc/impl/codegen/atm_gcc_sync.h include/grpc/impl/codegen/atm_windows.h include/grpc/impl/codegen/gpr_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/sync.h include/grpc/impl/codegen/sync_generic.h include/grpc/impl/codegen/sync_posix.h include/grpc/impl/codegen/sync_windows.h include/grpc/census.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) install(FILES ${_hdr} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_path}" ) endforeach() if (gRPC_INSTALL) install(TARGETS grpc_unsecure EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() if (gRPC_BUILD_TESTS) add_library(reconnect_server test/core/util/reconnect_server.c ) if(WIN32 AND MSVC) set_target_properties(reconnect_server PROPERTIES COMPILE_PDB_NAME "reconnect_server" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/reconnect_server.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(reconnect_server PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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(reconnect_server ${_gRPC_ALLTARGETS_LIBRARIES} test_tcp_server grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_library(test_tcp_server test/core/util/test_tcp_server.c ) if(WIN32 AND MSVC) set_target_properties(test_tcp_server PROPERTIES COMPILE_PDB_NAME "test_tcp_server" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/test_tcp_server.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(test_tcp_server PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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(test_tcp_server ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) add_library(grpc++ src/cpp/client/insecure_credentials.cc src/cpp/client/secure_credentials.cc src/cpp/common/auth_property_iterator.cc src/cpp/common/secure_auth_context.cc src/cpp/common/secure_channel_arguments.cc src/cpp/common/secure_create_auth_context.cc src/cpp/server/insecure_server_credentials.cc src/cpp/server/secure_server_credentials.cc src/cpp/client/channel_cc.cc src/cpp/client/client_context.cc src/cpp/client/create_channel.cc src/cpp/client/create_channel_internal.cc src/cpp/client/create_channel_posix.cc src/cpp/client/credentials_cc.cc src/cpp/client/generic_stub.cc src/cpp/common/channel_arguments.cc src/cpp/common/channel_filter.cc src/cpp/common/completion_queue_cc.cc src/cpp/common/core_codegen.cc src/cpp/common/resource_quota_cc.cc src/cpp/common/rpc_method.cc src/cpp/common/version_cc.cc src/cpp/server/async_generic_service.cc src/cpp/server/channel_argument_option.cc src/cpp/server/create_default_thread_pool.cc src/cpp/server/dynamic_thread_pool.cc src/cpp/server/health/default_health_check_service.cc src/cpp/server/health/health.pb.c src/cpp/server/health/health_check_service.cc src/cpp/server/health/health_check_service_server_builder_option.cc src/cpp/server/server_builder.cc src/cpp/server/server_cc.cc src/cpp/server/server_context.cc src/cpp/server/server_credentials.cc src/cpp/server/server_posix.cc src/cpp/thread_manager/thread_manager.cc src/cpp/util/byte_buffer_cc.cc src/cpp/util/slice_cc.cc src/cpp/util/status.cc src/cpp/util/string_ref.cc src/cpp/util/time_cc.cc src/core/lib/channel/channel_args.c src/core/lib/channel/channel_stack.c src/core/lib/channel/channel_stack_builder.c src/core/lib/channel/compress_filter.c src/core/lib/channel/connected_channel.c src/core/lib/channel/deadline_filter.c src/core/lib/channel/handshaker.c src/core/lib/channel/handshaker_factory.c src/core/lib/channel/handshaker_registry.c src/core/lib/channel/http_client_filter.c src/core/lib/channel/http_server_filter.c src/core/lib/channel/message_size_filter.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c src/core/lib/debug/trace.c src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c src/core/lib/iomgr/closure.c src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_uv.c src/core/lib/iomgr/endpoint_pair_windows.c src/core/lib/iomgr/error.c src/core/lib/iomgr/ev_epoll_linux.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c src/core/lib/iomgr/executor.c src/core/lib/iomgr/iocp_windows.c src/core/lib/iomgr/iomgr.c src/core/lib/iomgr/iomgr_posix.c src/core/lib/iomgr/iomgr_uv.c src/core/lib/iomgr/iomgr_windows.c src/core/lib/iomgr/load_file.c src/core/lib/iomgr/lockfree_event.c src/core/lib/iomgr/network_status_tracker.c src/core/lib/iomgr/polling_entity.c src/core/lib/iomgr/pollset_set_uv.c src/core/lib/iomgr/pollset_set_windows.c src/core/lib/iomgr/pollset_uv.c src/core/lib/iomgr/pollset_windows.c src/core/lib/iomgr/resolve_address_posix.c src/core/lib/iomgr/resolve_address_uv.c src/core/lib/iomgr/resolve_address_windows.c src/core/lib/iomgr/resource_quota.c src/core/lib/iomgr/sockaddr_utils.c src/core/lib/iomgr/socket_factory_posix.c src/core/lib/iomgr/socket_mutator.c src/core/lib/iomgr/socket_utils_common_posix.c src/core/lib/iomgr/socket_utils_linux.c src/core/lib/iomgr/socket_utils_posix.c src/core/lib/iomgr/socket_utils_uv.c src/core/lib/iomgr/socket_utils_windows.c src/core/lib/iomgr/socket_windows.c src/core/lib/iomgr/tcp_client_posix.c src/core/lib/iomgr/tcp_client_uv.c src/core/lib/iomgr/tcp_client_windows.c src/core/lib/iomgr/tcp_posix.c src/core/lib/iomgr/tcp_server_posix.c src/core/lib/iomgr/tcp_server_utils_posix_common.c src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c src/core/lib/iomgr/tcp_server_uv.c src/core/lib/iomgr/tcp_server_windows.c src/core/lib/iomgr/tcp_uv.c src/core/lib/iomgr/tcp_windows.c src/core/lib/iomgr/time_averaged_stats.c src/core/lib/iomgr/timer_generic.c src/core/lib/iomgr/timer_heap.c src/core/lib/iomgr/timer_uv.c src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c src/core/lib/iomgr/unix_sockets_posix_noop.c src/core/lib/iomgr/wakeup_fd_cv.c src/core/lib/iomgr/wakeup_fd_eventfd.c src/core/lib/iomgr/wakeup_fd_nospecial.c src/core/lib/iomgr/wakeup_fd_pipe.c src/core/lib/iomgr/wakeup_fd_posix.c src/core/lib/iomgr/workqueue_uv.c src/core/lib/iomgr/workqueue_windows.c src/core/lib/json/json.c src/core/lib/json/json_reader.c src/core/lib/json/json_string.c src/core/lib/json/json_writer.c src/core/lib/slice/b64.c src/core/lib/slice/percent_encoding.c src/core/lib/slice/slice.c src/core/lib/slice/slice_buffer.c src/core/lib/slice/slice_hash_table.c src/core/lib/slice/slice_intern.c src/core/lib/slice/slice_string_helpers.c src/core/lib/surface/alarm.c src/core/lib/surface/api_trace.c src/core/lib/surface/byte_buffer.c src/core/lib/surface/byte_buffer_reader.c src/core/lib/surface/call.c src/core/lib/surface/call_details.c src/core/lib/surface/call_log_batch.c src/core/lib/surface/channel.c src/core/lib/surface/channel_init.c src/core/lib/surface/channel_ping.c src/core/lib/surface/channel_stack_type.c src/core/lib/surface/completion_queue.c src/core/lib/surface/completion_queue_factory.c src/core/lib/surface/event_string.c src/core/lib/surface/lame_client.c src/core/lib/surface/metadata_array.c src/core/lib/surface/server.c src/core/lib/surface/validate_metadata.c src/core/lib/surface/version.c src/core/lib/transport/bdp_estimator.c src/core/lib/transport/byte_stream.c src/core/lib/transport/connectivity_state.c src/core/lib/transport/error_utils.c src/core/lib/transport/metadata.c src/core/lib/transport/metadata_batch.c src/core/lib/transport/pid_controller.c src/core/lib/transport/service_config.c src/core/lib/transport/static_metadata.c src/core/lib/transport/status_conversion.c src/core/lib/transport/timeout_encoding.c src/core/lib/transport/transport.c src/core/lib/transport/transport_op_string.c third_party/nanopb/pb_common.c third_party/nanopb/pb_decode.c third_party/nanopb/pb_encode.c src/cpp/codegen/codegen_init.cc ) if(WIN32 AND MSVC) set_target_properties(grpc++ PROPERTIES COMPILE_PDB_NAME "grpc++" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(grpc++ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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 PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpc++ ${_gRPC_BASELIB_LIBRARIES} ${_gRPC_SSL_LIBRARIES} ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc gpr ) foreach(_hdr include/grpc++/alarm.h include/grpc++/channel.h include/grpc++/client_context.h include/grpc++/completion_queue.h include/grpc++/create_channel.h include/grpc++/create_channel_posix.h include/grpc++/ext/health_check_service_server_builder_option.h include/grpc++/generic/async_generic_service.h include/grpc++/generic/generic_stub.h include/grpc++/grpc++.h include/grpc++/health_check_service_interface.h include/grpc++/impl/call.h include/grpc++/impl/channel_argument_option.h include/grpc++/impl/client_unary_call.h include/grpc++/impl/codegen/core_codegen.h include/grpc++/impl/grpc_library.h include/grpc++/impl/method_handler_impl.h include/grpc++/impl/rpc_method.h include/grpc++/impl/rpc_service_method.h include/grpc++/impl/serialization_traits.h include/grpc++/impl/server_builder_option.h include/grpc++/impl/server_builder_plugin.h include/grpc++/impl/server_initializer.h include/grpc++/impl/service_type.h include/grpc++/resource_quota.h include/grpc++/security/auth_context.h include/grpc++/security/auth_metadata_processor.h include/grpc++/security/credentials.h include/grpc++/security/server_credentials.h include/grpc++/server.h include/grpc++/server_builder.h include/grpc++/server_context.h include/grpc++/server_posix.h include/grpc++/support/async_stream.h include/grpc++/support/async_unary_call.h include/grpc++/support/byte_buffer.h include/grpc++/support/channel_arguments.h include/grpc++/support/config.h include/grpc++/support/slice.h include/grpc++/support/status.h include/grpc++/support/status_code_enum.h include/grpc++/support/string_ref.h include/grpc++/support/stub_options.h include/grpc++/support/sync_stream.h include/grpc++/support/time.h include/grpc++/impl/codegen/async_stream.h include/grpc++/impl/codegen/async_unary_call.h include/grpc++/impl/codegen/call.h include/grpc++/impl/codegen/call_hook.h include/grpc++/impl/codegen/channel_interface.h include/grpc++/impl/codegen/client_context.h include/grpc++/impl/codegen/client_unary_call.h include/grpc++/impl/codegen/completion_queue.h include/grpc++/impl/codegen/completion_queue_tag.h include/grpc++/impl/codegen/config.h include/grpc++/impl/codegen/core_codegen_interface.h include/grpc++/impl/codegen/create_auth_context.h include/grpc++/impl/codegen/grpc_library.h include/grpc++/impl/codegen/metadata_map.h include/grpc++/impl/codegen/method_handler_impl.h include/grpc++/impl/codegen/rpc_method.h include/grpc++/impl/codegen/rpc_service_method.h include/grpc++/impl/codegen/security/auth_context.h include/grpc++/impl/codegen/serialization_traits.h include/grpc++/impl/codegen/server_context.h include/grpc++/impl/codegen/server_interface.h include/grpc++/impl/codegen/service_type.h include/grpc++/impl/codegen/slice.h include/grpc++/impl/codegen/status.h include/grpc++/impl/codegen/status_code_enum.h include/grpc++/impl/codegen/status_helper.h include/grpc++/impl/codegen/string_ref.h include/grpc++/impl/codegen/stub_options.h include/grpc++/impl/codegen/sync_stream.h include/grpc++/impl/codegen/time.h include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/connectivity_state.h include/grpc/impl/codegen/exec_ctx_fwd.h include/grpc/impl/codegen/grpc_types.h include/grpc/impl/codegen/propagation_bits.h include/grpc/impl/codegen/slice.h include/grpc/impl/codegen/status.h include/grpc/impl/codegen/atm.h include/grpc/impl/codegen/atm_gcc_atomic.h include/grpc/impl/codegen/atm_gcc_sync.h include/grpc/impl/codegen/atm_windows.h include/grpc/impl/codegen/gpr_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/sync.h include/grpc/impl/codegen/sync_generic.h include/grpc/impl/codegen/sync_posix.h include/grpc/impl/codegen/sync_windows.h include/grpc/byte_buffer.h include/grpc/byte_buffer_reader.h include/grpc/compression.h include/grpc/grpc.h include/grpc/grpc_posix.h include/grpc/grpc_security_constants.h include/grpc/load_reporting.h include/grpc/slice.h include/grpc/slice_buffer.h include/grpc/status.h include/grpc++/impl/codegen/proto_utils.h include/grpc++/impl/codegen/config_protobuf.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) install(FILES ${_hdr} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_path}" ) endforeach() if (gRPC_INSTALL) install(TARGETS grpc++ EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() add_library(grpc++_cronet src/cpp/client/cronet_credentials.cc src/cpp/client/insecure_credentials.cc src/cpp/common/insecure_create_auth_context.cc src/cpp/server/insecure_server_credentials.cc src/cpp/client/channel_cc.cc src/cpp/client/client_context.cc src/cpp/client/create_channel.cc src/cpp/client/create_channel_internal.cc src/cpp/client/create_channel_posix.cc src/cpp/client/credentials_cc.cc src/cpp/client/generic_stub.cc src/cpp/common/channel_arguments.cc src/cpp/common/channel_filter.cc src/cpp/common/completion_queue_cc.cc src/cpp/common/core_codegen.cc src/cpp/common/resource_quota_cc.cc src/cpp/common/rpc_method.cc src/cpp/common/version_cc.cc src/cpp/server/async_generic_service.cc src/cpp/server/channel_argument_option.cc src/cpp/server/create_default_thread_pool.cc src/cpp/server/dynamic_thread_pool.cc src/cpp/server/health/default_health_check_service.cc src/cpp/server/health/health.pb.c src/cpp/server/health/health_check_service.cc src/cpp/server/health/health_check_service_server_builder_option.cc src/cpp/server/server_builder.cc src/cpp/server/server_cc.cc src/cpp/server/server_context.cc src/cpp/server/server_credentials.cc src/cpp/server/server_posix.cc src/cpp/thread_manager/thread_manager.cc src/cpp/util/byte_buffer_cc.cc src/cpp/util/slice_cc.cc src/cpp/util/status.cc src/cpp/util/string_ref.cc src/cpp/util/time_cc.cc src/core/lib/channel/channel_args.c src/core/lib/channel/channel_stack.c src/core/lib/channel/channel_stack_builder.c src/core/lib/channel/compress_filter.c src/core/lib/channel/connected_channel.c src/core/lib/channel/deadline_filter.c src/core/lib/channel/handshaker.c src/core/lib/channel/handshaker_factory.c src/core/lib/channel/handshaker_registry.c src/core/lib/channel/http_client_filter.c src/core/lib/channel/http_server_filter.c src/core/lib/channel/message_size_filter.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c src/core/lib/debug/trace.c src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c src/core/lib/iomgr/closure.c src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_uv.c src/core/lib/iomgr/endpoint_pair_windows.c src/core/lib/iomgr/error.c src/core/lib/iomgr/ev_epoll_linux.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c src/core/lib/iomgr/executor.c src/core/lib/iomgr/iocp_windows.c src/core/lib/iomgr/iomgr.c src/core/lib/iomgr/iomgr_posix.c src/core/lib/iomgr/iomgr_uv.c src/core/lib/iomgr/iomgr_windows.c src/core/lib/iomgr/load_file.c src/core/lib/iomgr/lockfree_event.c src/core/lib/iomgr/network_status_tracker.c src/core/lib/iomgr/polling_entity.c src/core/lib/iomgr/pollset_set_uv.c src/core/lib/iomgr/pollset_set_windows.c src/core/lib/iomgr/pollset_uv.c src/core/lib/iomgr/pollset_windows.c src/core/lib/iomgr/resolve_address_posix.c src/core/lib/iomgr/resolve_address_uv.c src/core/lib/iomgr/resolve_address_windows.c src/core/lib/iomgr/resource_quota.c src/core/lib/iomgr/sockaddr_utils.c src/core/lib/iomgr/socket_factory_posix.c src/core/lib/iomgr/socket_mutator.c src/core/lib/iomgr/socket_utils_common_posix.c src/core/lib/iomgr/socket_utils_linux.c src/core/lib/iomgr/socket_utils_posix.c src/core/lib/iomgr/socket_utils_uv.c src/core/lib/iomgr/socket_utils_windows.c src/core/lib/iomgr/socket_windows.c src/core/lib/iomgr/tcp_client_posix.c src/core/lib/iomgr/tcp_client_uv.c src/core/lib/iomgr/tcp_client_windows.c src/core/lib/iomgr/tcp_posix.c src/core/lib/iomgr/tcp_server_posix.c src/core/lib/iomgr/tcp_server_utils_posix_common.c src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c src/core/lib/iomgr/tcp_server_uv.c src/core/lib/iomgr/tcp_server_windows.c src/core/lib/iomgr/tcp_uv.c src/core/lib/iomgr/tcp_windows.c src/core/lib/iomgr/time_averaged_stats.c src/core/lib/iomgr/timer_generic.c src/core/lib/iomgr/timer_heap.c src/core/lib/iomgr/timer_uv.c src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c src/core/lib/iomgr/unix_sockets_posix_noop.c src/core/lib/iomgr/wakeup_fd_cv.c src/core/lib/iomgr/wakeup_fd_eventfd.c src/core/lib/iomgr/wakeup_fd_nospecial.c src/core/lib/iomgr/wakeup_fd_pipe.c src/core/lib/iomgr/wakeup_fd_posix.c src/core/lib/iomgr/workqueue_uv.c src/core/lib/iomgr/workqueue_windows.c src/core/lib/json/json.c src/core/lib/json/json_reader.c src/core/lib/json/json_string.c src/core/lib/json/json_writer.c src/core/lib/slice/b64.c src/core/lib/slice/percent_encoding.c src/core/lib/slice/slice.c src/core/lib/slice/slice_buffer.c src/core/lib/slice/slice_hash_table.c src/core/lib/slice/slice_intern.c src/core/lib/slice/slice_string_helpers.c src/core/lib/surface/alarm.c src/core/lib/surface/api_trace.c src/core/lib/surface/byte_buffer.c src/core/lib/surface/byte_buffer_reader.c src/core/lib/surface/call.c src/core/lib/surface/call_details.c src/core/lib/surface/call_log_batch.c src/core/lib/surface/channel.c src/core/lib/surface/channel_init.c src/core/lib/surface/channel_ping.c src/core/lib/surface/channel_stack_type.c src/core/lib/surface/completion_queue.c src/core/lib/surface/completion_queue_factory.c src/core/lib/surface/event_string.c src/core/lib/surface/lame_client.c src/core/lib/surface/metadata_array.c src/core/lib/surface/server.c src/core/lib/surface/validate_metadata.c src/core/lib/surface/version.c src/core/lib/transport/bdp_estimator.c src/core/lib/transport/byte_stream.c src/core/lib/transport/connectivity_state.c src/core/lib/transport/error_utils.c src/core/lib/transport/metadata.c src/core/lib/transport/metadata_batch.c src/core/lib/transport/pid_controller.c src/core/lib/transport/service_config.c src/core/lib/transport/static_metadata.c src/core/lib/transport/status_conversion.c src/core/lib/transport/timeout_encoding.c src/core/lib/transport/transport.c src/core/lib/transport/transport_op_string.c third_party/nanopb/pb_common.c third_party/nanopb/pb_decode.c third_party/nanopb/pb_encode.c src/cpp/codegen/codegen_init.cc src/core/ext/transport/chttp2/client/insecure/channel_create.c src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c src/core/ext/transport/chttp2/client/chttp2_connector.c src/core/ext/transport/chttp2/transport/bin_decoder.c src/core/ext/transport/chttp2/transport/bin_encoder.c src/core/ext/transport/chttp2/transport/chttp2_plugin.c src/core/ext/transport/chttp2/transport/chttp2_transport.c src/core/ext/transport/chttp2/transport/frame_data.c src/core/ext/transport/chttp2/transport/frame_goaway.c src/core/ext/transport/chttp2/transport/frame_ping.c src/core/ext/transport/chttp2/transport/frame_rst_stream.c src/core/ext/transport/chttp2/transport/frame_settings.c src/core/ext/transport/chttp2/transport/frame_window_update.c src/core/ext/transport/chttp2/transport/hpack_encoder.c src/core/ext/transport/chttp2/transport/hpack_parser.c src/core/ext/transport/chttp2/transport/hpack_table.c src/core/ext/transport/chttp2/transport/http2_settings.c src/core/ext/transport/chttp2/transport/huffsyms.c src/core/ext/transport/chttp2/transport/incoming_metadata.c src/core/ext/transport/chttp2/transport/parsing.c src/core/ext/transport/chttp2/transport/stream_lists.c src/core/ext/transport/chttp2/transport/stream_map.c src/core/ext/transport/chttp2/transport/varint.c src/core/ext/transport/chttp2/transport/writing.c src/core/ext/transport/chttp2/alpn/alpn.c src/core/ext/filters/client_channel/channel_connectivity.c src/core/ext/filters/client_channel/client_channel.c src/core/ext/filters/client_channel/client_channel_factory.c src/core/ext/filters/client_channel/client_channel_plugin.c src/core/ext/filters/client_channel/connector.c src/core/ext/filters/client_channel/http_connect_handshaker.c src/core/ext/filters/client_channel/http_proxy.c src/core/ext/filters/client_channel/lb_policy.c src/core/ext/filters/client_channel/lb_policy_factory.c src/core/ext/filters/client_channel/lb_policy_registry.c src/core/ext/filters/client_channel/parse_address.c src/core/ext/filters/client_channel/proxy_mapper.c src/core/ext/filters/client_channel/proxy_mapper_registry.c src/core/ext/filters/client_channel/resolver.c src/core/ext/filters/client_channel/resolver_factory.c src/core/ext/filters/client_channel/resolver_registry.c src/core/ext/filters/client_channel/retry_throttle.c src/core/ext/filters/client_channel/subchannel.c src/core/ext/filters/client_channel/subchannel_index.c src/core/ext/filters/client_channel/uri_parser.c src/core/ext/transport/chttp2/server/insecure/server_chttp2.c src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c src/core/ext/transport/chttp2/server/chttp2_server.c src/core/ext/census/base_resources.c src/core/ext/census/context.c src/core/ext/census/gen/census.pb.c src/core/ext/census/gen/trace_context.pb.c src/core/ext/census/grpc_context.c src/core/ext/census/grpc_filter.c src/core/ext/census/grpc_plugin.c src/core/ext/census/initialize.c src/core/ext/census/mlog.c src/core/ext/census/operation.c src/core/ext/census/placeholders.c src/core/ext/census/resource.c src/core/ext/census/trace_context.c src/core/ext/census/tracing.c ) if(WIN32 AND MSVC) set_target_properties(grpc++_cronet PROPERTIES COMPILE_PDB_NAME "grpc++_cronet" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_cronet.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(grpc++_cronet PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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 PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpc++_cronet ${_gRPC_BASELIB_LIBRARIES} ${_gRPC_SSL_LIBRARIES} ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} gpr grpc_cronet ) foreach(_hdr include/grpc++/alarm.h include/grpc++/channel.h include/grpc++/client_context.h include/grpc++/completion_queue.h include/grpc++/create_channel.h include/grpc++/create_channel_posix.h include/grpc++/ext/health_check_service_server_builder_option.h include/grpc++/generic/async_generic_service.h include/grpc++/generic/generic_stub.h include/grpc++/grpc++.h include/grpc++/health_check_service_interface.h include/grpc++/impl/call.h include/grpc++/impl/channel_argument_option.h include/grpc++/impl/client_unary_call.h include/grpc++/impl/codegen/core_codegen.h include/grpc++/impl/grpc_library.h include/grpc++/impl/method_handler_impl.h include/grpc++/impl/rpc_method.h include/grpc++/impl/rpc_service_method.h include/grpc++/impl/serialization_traits.h include/grpc++/impl/server_builder_option.h include/grpc++/impl/server_builder_plugin.h include/grpc++/impl/server_initializer.h include/grpc++/impl/service_type.h include/grpc++/resource_quota.h include/grpc++/security/auth_context.h include/grpc++/security/auth_metadata_processor.h include/grpc++/security/credentials.h include/grpc++/security/server_credentials.h include/grpc++/server.h include/grpc++/server_builder.h include/grpc++/server_context.h include/grpc++/server_posix.h include/grpc++/support/async_stream.h include/grpc++/support/async_unary_call.h include/grpc++/support/byte_buffer.h include/grpc++/support/channel_arguments.h include/grpc++/support/config.h include/grpc++/support/slice.h include/grpc++/support/status.h include/grpc++/support/status_code_enum.h include/grpc++/support/string_ref.h include/grpc++/support/stub_options.h include/grpc++/support/sync_stream.h include/grpc++/support/time.h include/grpc++/impl/codegen/async_stream.h include/grpc++/impl/codegen/async_unary_call.h include/grpc++/impl/codegen/call.h include/grpc++/impl/codegen/call_hook.h include/grpc++/impl/codegen/channel_interface.h include/grpc++/impl/codegen/client_context.h include/grpc++/impl/codegen/client_unary_call.h include/grpc++/impl/codegen/completion_queue.h include/grpc++/impl/codegen/completion_queue_tag.h include/grpc++/impl/codegen/config.h include/grpc++/impl/codegen/core_codegen_interface.h include/grpc++/impl/codegen/create_auth_context.h include/grpc++/impl/codegen/grpc_library.h include/grpc++/impl/codegen/metadata_map.h include/grpc++/impl/codegen/method_handler_impl.h include/grpc++/impl/codegen/rpc_method.h include/grpc++/impl/codegen/rpc_service_method.h include/grpc++/impl/codegen/security/auth_context.h include/grpc++/impl/codegen/serialization_traits.h include/grpc++/impl/codegen/server_context.h include/grpc++/impl/codegen/server_interface.h include/grpc++/impl/codegen/service_type.h include/grpc++/impl/codegen/slice.h include/grpc++/impl/codegen/status.h include/grpc++/impl/codegen/status_code_enum.h include/grpc++/impl/codegen/status_helper.h include/grpc++/impl/codegen/string_ref.h include/grpc++/impl/codegen/stub_options.h include/grpc++/impl/codegen/sync_stream.h include/grpc++/impl/codegen/time.h include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/connectivity_state.h include/grpc/impl/codegen/exec_ctx_fwd.h include/grpc/impl/codegen/grpc_types.h include/grpc/impl/codegen/propagation_bits.h include/grpc/impl/codegen/slice.h include/grpc/impl/codegen/status.h include/grpc/impl/codegen/atm.h include/grpc/impl/codegen/atm_gcc_atomic.h include/grpc/impl/codegen/atm_gcc_sync.h include/grpc/impl/codegen/atm_windows.h include/grpc/impl/codegen/gpr_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/sync.h include/grpc/impl/codegen/sync_generic.h include/grpc/impl/codegen/sync_posix.h include/grpc/impl/codegen/sync_windows.h include/grpc/byte_buffer.h include/grpc/byte_buffer_reader.h include/grpc/compression.h include/grpc/grpc.h include/grpc/grpc_posix.h include/grpc/grpc_security_constants.h include/grpc/load_reporting.h include/grpc/slice.h include/grpc/slice_buffer.h include/grpc/status.h include/grpc/census.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) install(FILES ${_hdr} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_path}" ) endforeach() if (gRPC_INSTALL) install(TARGETS grpc++_cronet EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() add_library(grpc++_error_details ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/status/status.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/status/status.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/status/status.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/status/status.grpc.pb.h src/cpp/util/error_details.cc ) if(WIN32 AND MSVC) set_target_properties(grpc++_error_details PROPERTIES COMPILE_PDB_NAME "grpc++_error_details" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_error_details.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() protobuf_generate_grpc_cpp( src/proto/grpc/status/status.proto ) target_include_directories(grpc++_error_details PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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 PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpc++_error_details ${_gRPC_BASELIB_LIBRARIES} ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++ ) foreach(_hdr include/grpc++/support/error_details.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) install(FILES ${_hdr} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_path}" ) endforeach() if (gRPC_INSTALL) install(TARGETS grpc++_error_details EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() if (gRPC_BUILD_TESTS) add_library(grpc++_proto_reflection_desc_db test/cpp/util/proto_reflection_descriptor_database.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h ) if(WIN32 AND MSVC) set_target_properties(grpc++_proto_reflection_desc_db PROPERTIES COMPILE_PDB_NAME "grpc++_proto_reflection_desc_db" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_proto_reflection_desc_db.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() protobuf_generate_grpc_cpp( src/proto/grpc/reflection/v1alpha/reflection.proto ) target_include_directories(grpc++_proto_reflection_desc_db PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpc++_proto_reflection_desc_db ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++ ) foreach(_hdr include/grpc++/impl/codegen/config_protobuf.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) install(FILES ${_hdr} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_path}" ) endforeach() endif (gRPC_BUILD_TESTS) add_library(grpc++_reflection src/cpp/ext/proto_server_reflection.cc src/cpp/ext/proto_server_reflection_plugin.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h ) if(WIN32 AND MSVC) set_target_properties(grpc++_reflection PROPERTIES COMPILE_PDB_NAME "grpc++_reflection" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_reflection.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() protobuf_generate_grpc_cpp( src/proto/grpc/reflection/v1alpha/reflection.proto ) target_include_directories(grpc++_reflection PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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 PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpc++_reflection ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++ ) foreach(_hdr include/grpc++/ext/proto_server_reflection_plugin.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) install(FILES ${_hdr} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_path}" ) endforeach() if (gRPC_INSTALL) install(TARGETS grpc++_reflection EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() if (gRPC_BUILD_TESTS) add_library(grpc++_test_config test/cpp/util/test_config_cc.cc ) if(WIN32 AND MSVC) set_target_properties(grpc++_test_config PROPERTIES COMPILE_PDB_NAME "grpc++_test_config" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_test_config.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(grpc++_test_config PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpc++_test_config ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_library(grpc++_test_util ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h test/cpp/end2end/test_service_impl.cc test/cpp/util/byte_buffer_proto_helper.cc test/cpp/util/create_test_channel.cc test/cpp/util/string_ref_helper.cc test/cpp/util/subprocess.cc test/cpp/util/test_credentials_provider.cc src/cpp/codegen/codegen_init.cc ) if(WIN32 AND MSVC) set_target_properties(grpc++_test_util PROPERTIES COMPILE_PDB_NAME "grpc++_test_util" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_test_util.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() protobuf_generate_grpc_cpp( src/proto/grpc/health/v1/health.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/echo_messages.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/echo.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/duplicate/echo_duplicate.proto ) target_include_directories(grpc++_test_util PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpc++_test_util ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++ grpc_test_util ) foreach(_hdr include/grpc++/impl/codegen/async_stream.h include/grpc++/impl/codegen/async_unary_call.h include/grpc++/impl/codegen/call.h include/grpc++/impl/codegen/call_hook.h include/grpc++/impl/codegen/channel_interface.h include/grpc++/impl/codegen/client_context.h include/grpc++/impl/codegen/client_unary_call.h include/grpc++/impl/codegen/completion_queue.h include/grpc++/impl/codegen/completion_queue_tag.h include/grpc++/impl/codegen/config.h include/grpc++/impl/codegen/core_codegen_interface.h include/grpc++/impl/codegen/create_auth_context.h include/grpc++/impl/codegen/grpc_library.h include/grpc++/impl/codegen/metadata_map.h include/grpc++/impl/codegen/method_handler_impl.h include/grpc++/impl/codegen/rpc_method.h include/grpc++/impl/codegen/rpc_service_method.h include/grpc++/impl/codegen/security/auth_context.h include/grpc++/impl/codegen/serialization_traits.h include/grpc++/impl/codegen/server_context.h include/grpc++/impl/codegen/server_interface.h include/grpc++/impl/codegen/service_type.h include/grpc++/impl/codegen/slice.h include/grpc++/impl/codegen/status.h include/grpc++/impl/codegen/status_code_enum.h include/grpc++/impl/codegen/status_helper.h include/grpc++/impl/codegen/string_ref.h include/grpc++/impl/codegen/stub_options.h include/grpc++/impl/codegen/sync_stream.h include/grpc++/impl/codegen/time.h include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/connectivity_state.h include/grpc/impl/codegen/exec_ctx_fwd.h include/grpc/impl/codegen/grpc_types.h include/grpc/impl/codegen/propagation_bits.h include/grpc/impl/codegen/slice.h include/grpc/impl/codegen/status.h include/grpc/impl/codegen/atm.h include/grpc/impl/codegen/atm_gcc_atomic.h include/grpc/impl/codegen/atm_gcc_sync.h include/grpc/impl/codegen/atm_windows.h include/grpc/impl/codegen/gpr_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/sync.h include/grpc/impl/codegen/sync_generic.h include/grpc/impl/codegen/sync_posix.h include/grpc/impl/codegen/sync_windows.h include/grpc++/impl/codegen/proto_utils.h include/grpc++/impl/codegen/config_protobuf.h include/grpc++/impl/codegen/thrift_serializer.h include/grpc++/impl/codegen/thrift_utils.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) install(FILES ${_hdr} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_path}" ) endforeach() endif (gRPC_BUILD_TESTS) add_library(grpc++_unsecure src/cpp/client/insecure_credentials.cc src/cpp/common/insecure_create_auth_context.cc src/cpp/server/insecure_server_credentials.cc src/cpp/client/channel_cc.cc src/cpp/client/client_context.cc src/cpp/client/create_channel.cc src/cpp/client/create_channel_internal.cc src/cpp/client/create_channel_posix.cc src/cpp/client/credentials_cc.cc src/cpp/client/generic_stub.cc src/cpp/common/channel_arguments.cc src/cpp/common/channel_filter.cc src/cpp/common/completion_queue_cc.cc src/cpp/common/core_codegen.cc src/cpp/common/resource_quota_cc.cc src/cpp/common/rpc_method.cc src/cpp/common/version_cc.cc src/cpp/server/async_generic_service.cc src/cpp/server/channel_argument_option.cc src/cpp/server/create_default_thread_pool.cc src/cpp/server/dynamic_thread_pool.cc src/cpp/server/health/default_health_check_service.cc src/cpp/server/health/health.pb.c src/cpp/server/health/health_check_service.cc src/cpp/server/health/health_check_service_server_builder_option.cc src/cpp/server/server_builder.cc src/cpp/server/server_cc.cc src/cpp/server/server_context.cc src/cpp/server/server_credentials.cc src/cpp/server/server_posix.cc src/cpp/thread_manager/thread_manager.cc src/cpp/util/byte_buffer_cc.cc src/cpp/util/slice_cc.cc src/cpp/util/status.cc src/cpp/util/string_ref.cc src/cpp/util/time_cc.cc src/core/lib/channel/channel_args.c src/core/lib/channel/channel_stack.c src/core/lib/channel/channel_stack_builder.c src/core/lib/channel/compress_filter.c src/core/lib/channel/connected_channel.c src/core/lib/channel/deadline_filter.c src/core/lib/channel/handshaker.c src/core/lib/channel/handshaker_factory.c src/core/lib/channel/handshaker_registry.c src/core/lib/channel/http_client_filter.c src/core/lib/channel/http_server_filter.c src/core/lib/channel/message_size_filter.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c src/core/lib/debug/trace.c src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c src/core/lib/iomgr/closure.c src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_uv.c src/core/lib/iomgr/endpoint_pair_windows.c src/core/lib/iomgr/error.c src/core/lib/iomgr/ev_epoll_linux.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c src/core/lib/iomgr/executor.c src/core/lib/iomgr/iocp_windows.c src/core/lib/iomgr/iomgr.c src/core/lib/iomgr/iomgr_posix.c src/core/lib/iomgr/iomgr_uv.c src/core/lib/iomgr/iomgr_windows.c src/core/lib/iomgr/load_file.c src/core/lib/iomgr/lockfree_event.c src/core/lib/iomgr/network_status_tracker.c src/core/lib/iomgr/polling_entity.c src/core/lib/iomgr/pollset_set_uv.c src/core/lib/iomgr/pollset_set_windows.c src/core/lib/iomgr/pollset_uv.c src/core/lib/iomgr/pollset_windows.c src/core/lib/iomgr/resolve_address_posix.c src/core/lib/iomgr/resolve_address_uv.c src/core/lib/iomgr/resolve_address_windows.c src/core/lib/iomgr/resource_quota.c src/core/lib/iomgr/sockaddr_utils.c src/core/lib/iomgr/socket_factory_posix.c src/core/lib/iomgr/socket_mutator.c src/core/lib/iomgr/socket_utils_common_posix.c src/core/lib/iomgr/socket_utils_linux.c src/core/lib/iomgr/socket_utils_posix.c src/core/lib/iomgr/socket_utils_uv.c src/core/lib/iomgr/socket_utils_windows.c src/core/lib/iomgr/socket_windows.c src/core/lib/iomgr/tcp_client_posix.c src/core/lib/iomgr/tcp_client_uv.c src/core/lib/iomgr/tcp_client_windows.c src/core/lib/iomgr/tcp_posix.c src/core/lib/iomgr/tcp_server_posix.c src/core/lib/iomgr/tcp_server_utils_posix_common.c src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c src/core/lib/iomgr/tcp_server_uv.c src/core/lib/iomgr/tcp_server_windows.c src/core/lib/iomgr/tcp_uv.c src/core/lib/iomgr/tcp_windows.c src/core/lib/iomgr/time_averaged_stats.c src/core/lib/iomgr/timer_generic.c src/core/lib/iomgr/timer_heap.c src/core/lib/iomgr/timer_uv.c src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c src/core/lib/iomgr/unix_sockets_posix_noop.c src/core/lib/iomgr/wakeup_fd_cv.c src/core/lib/iomgr/wakeup_fd_eventfd.c src/core/lib/iomgr/wakeup_fd_nospecial.c src/core/lib/iomgr/wakeup_fd_pipe.c src/core/lib/iomgr/wakeup_fd_posix.c src/core/lib/iomgr/workqueue_uv.c src/core/lib/iomgr/workqueue_windows.c src/core/lib/json/json.c src/core/lib/json/json_reader.c src/core/lib/json/json_string.c src/core/lib/json/json_writer.c src/core/lib/slice/b64.c src/core/lib/slice/percent_encoding.c src/core/lib/slice/slice.c src/core/lib/slice/slice_buffer.c src/core/lib/slice/slice_hash_table.c src/core/lib/slice/slice_intern.c src/core/lib/slice/slice_string_helpers.c src/core/lib/surface/alarm.c src/core/lib/surface/api_trace.c src/core/lib/surface/byte_buffer.c src/core/lib/surface/byte_buffer_reader.c src/core/lib/surface/call.c src/core/lib/surface/call_details.c src/core/lib/surface/call_log_batch.c src/core/lib/surface/channel.c src/core/lib/surface/channel_init.c src/core/lib/surface/channel_ping.c src/core/lib/surface/channel_stack_type.c src/core/lib/surface/completion_queue.c src/core/lib/surface/completion_queue_factory.c src/core/lib/surface/event_string.c src/core/lib/surface/lame_client.c src/core/lib/surface/metadata_array.c src/core/lib/surface/server.c src/core/lib/surface/validate_metadata.c src/core/lib/surface/version.c src/core/lib/transport/bdp_estimator.c src/core/lib/transport/byte_stream.c src/core/lib/transport/connectivity_state.c src/core/lib/transport/error_utils.c src/core/lib/transport/metadata.c src/core/lib/transport/metadata_batch.c src/core/lib/transport/pid_controller.c src/core/lib/transport/service_config.c src/core/lib/transport/static_metadata.c src/core/lib/transport/status_conversion.c src/core/lib/transport/timeout_encoding.c src/core/lib/transport/transport.c src/core/lib/transport/transport_op_string.c third_party/nanopb/pb_common.c third_party/nanopb/pb_decode.c third_party/nanopb/pb_encode.c src/cpp/codegen/codegen_init.cc ) if(WIN32 AND MSVC) set_target_properties(grpc++_unsecure PROPERTIES COMPILE_PDB_NAME "grpc++_unsecure" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_unsecure.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(grpc++_unsecure PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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 PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpc++_unsecure ${_gRPC_BASELIB_LIBRARIES} ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} gpr grpc_unsecure ) foreach(_hdr include/grpc++/alarm.h include/grpc++/channel.h include/grpc++/client_context.h include/grpc++/completion_queue.h include/grpc++/create_channel.h include/grpc++/create_channel_posix.h include/grpc++/ext/health_check_service_server_builder_option.h include/grpc++/generic/async_generic_service.h include/grpc++/generic/generic_stub.h include/grpc++/grpc++.h include/grpc++/health_check_service_interface.h include/grpc++/impl/call.h include/grpc++/impl/channel_argument_option.h include/grpc++/impl/client_unary_call.h include/grpc++/impl/codegen/core_codegen.h include/grpc++/impl/grpc_library.h include/grpc++/impl/method_handler_impl.h include/grpc++/impl/rpc_method.h include/grpc++/impl/rpc_service_method.h include/grpc++/impl/serialization_traits.h include/grpc++/impl/server_builder_option.h include/grpc++/impl/server_builder_plugin.h include/grpc++/impl/server_initializer.h include/grpc++/impl/service_type.h include/grpc++/resource_quota.h include/grpc++/security/auth_context.h include/grpc++/security/auth_metadata_processor.h include/grpc++/security/credentials.h include/grpc++/security/server_credentials.h include/grpc++/server.h include/grpc++/server_builder.h include/grpc++/server_context.h include/grpc++/server_posix.h include/grpc++/support/async_stream.h include/grpc++/support/async_unary_call.h include/grpc++/support/byte_buffer.h include/grpc++/support/channel_arguments.h include/grpc++/support/config.h include/grpc++/support/slice.h include/grpc++/support/status.h include/grpc++/support/status_code_enum.h include/grpc++/support/string_ref.h include/grpc++/support/stub_options.h include/grpc++/support/sync_stream.h include/grpc++/support/time.h include/grpc++/impl/codegen/async_stream.h include/grpc++/impl/codegen/async_unary_call.h include/grpc++/impl/codegen/call.h include/grpc++/impl/codegen/call_hook.h include/grpc++/impl/codegen/channel_interface.h include/grpc++/impl/codegen/client_context.h include/grpc++/impl/codegen/client_unary_call.h include/grpc++/impl/codegen/completion_queue.h include/grpc++/impl/codegen/completion_queue_tag.h include/grpc++/impl/codegen/config.h include/grpc++/impl/codegen/core_codegen_interface.h include/grpc++/impl/codegen/create_auth_context.h include/grpc++/impl/codegen/grpc_library.h include/grpc++/impl/codegen/metadata_map.h include/grpc++/impl/codegen/method_handler_impl.h include/grpc++/impl/codegen/rpc_method.h include/grpc++/impl/codegen/rpc_service_method.h include/grpc++/impl/codegen/security/auth_context.h include/grpc++/impl/codegen/serialization_traits.h include/grpc++/impl/codegen/server_context.h include/grpc++/impl/codegen/server_interface.h include/grpc++/impl/codegen/service_type.h include/grpc++/impl/codegen/slice.h include/grpc++/impl/codegen/status.h include/grpc++/impl/codegen/status_code_enum.h include/grpc++/impl/codegen/status_helper.h include/grpc++/impl/codegen/string_ref.h include/grpc++/impl/codegen/stub_options.h include/grpc++/impl/codegen/sync_stream.h include/grpc++/impl/codegen/time.h include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/connectivity_state.h include/grpc/impl/codegen/exec_ctx_fwd.h include/grpc/impl/codegen/grpc_types.h include/grpc/impl/codegen/propagation_bits.h include/grpc/impl/codegen/slice.h include/grpc/impl/codegen/status.h include/grpc/impl/codegen/atm.h include/grpc/impl/codegen/atm_gcc_atomic.h include/grpc/impl/codegen/atm_gcc_sync.h include/grpc/impl/codegen/atm_windows.h include/grpc/impl/codegen/gpr_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/sync.h include/grpc/impl/codegen/sync_generic.h include/grpc/impl/codegen/sync_posix.h include/grpc/impl/codegen/sync_windows.h include/grpc/byte_buffer.h include/grpc/byte_buffer_reader.h include/grpc/compression.h include/grpc/grpc.h include/grpc/grpc_posix.h include/grpc/grpc_security_constants.h include/grpc/load_reporting.h include/grpc/slice.h include/grpc/slice_buffer.h include/grpc/status.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) install(FILES ${_hdr} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_path}" ) endforeach() if (gRPC_INSTALL) install(TARGETS grpc++_unsecure EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() if (gRPC_BUILD_TESTS) add_library(grpc_benchmark test/cpp/microbenchmarks/helpers.cc ) if(WIN32 AND MSVC) set_target_properties(grpc_benchmark PROPERTIES COMPILE_PDB_NAME "grpc_benchmark" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_benchmark.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(grpc_benchmark PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpc_benchmark ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark grpc++ grpc_test_util grpc ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_library(grpc_cli_libs test/cpp/util/cli_call.cc test/cpp/util/cli_credentials.cc test/cpp/util/grpc_tool.cc test/cpp/util/proto_file_parser.cc test/cpp/util/service_describer.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h ) if(WIN32 AND MSVC) set_target_properties(grpc_cli_libs PROPERTIES COMPILE_PDB_NAME "grpc_cli_libs" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_cli_libs.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() protobuf_generate_grpc_cpp( src/proto/grpc/reflection/v1alpha/reflection.proto ) target_include_directories(grpc_cli_libs PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpc_cli_libs ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_proto_reflection_desc_db grpc++ ) foreach(_hdr include/grpc++/impl/codegen/config_protobuf.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) install(FILES ${_hdr} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_path}" ) endforeach() endif (gRPC_BUILD_TESTS) add_library(grpc_plugin_support src/compiler/cpp_generator.cc src/compiler/csharp_generator.cc src/compiler/node_generator.cc src/compiler/objective_c_generator.cc src/compiler/php_generator.cc src/compiler/python_generator.cc src/compiler/ruby_generator.cc ) if(WIN32 AND MSVC) set_target_properties(grpc_plugin_support PROPERTIES COMPILE_PDB_NAME "grpc_plugin_support" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_plugin_support.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(grpc_plugin_support PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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 PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpc_plugin_support ${_gRPC_PROTOBUF_PROTOC_LIBRARIES} ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} ) foreach(_hdr include/grpc++/impl/codegen/config_protobuf.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) install(FILES ${_hdr} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_path}" ) endforeach() if (gRPC_INSTALL) install(TARGETS grpc_plugin_support EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() if (gRPC_BUILD_TESTS) add_library(http2_client_main ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.h test/cpp/interop/http2_client.cc ) if(WIN32 AND MSVC) set_target_properties(http2_client_main PROPERTIES COMPILE_PDB_NAME "http2_client_main" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/http2_client_main.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() protobuf_generate_grpc_cpp( src/proto/grpc/testing/empty.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/messages.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/test.proto ) target_include_directories(http2_client_main PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(http2_client_main ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc grpc++_test_config ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_library(interop_client_helper ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h test/cpp/interop/client_helper.cc ) if(WIN32 AND MSVC) set_target_properties(interop_client_helper PROPERTIES COMPILE_PDB_NAME "interop_client_helper" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/interop_client_helper.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() protobuf_generate_grpc_cpp( src/proto/grpc/testing/messages.proto ) target_include_directories(interop_client_helper PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(interop_client_helper ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_library(interop_client_main ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.h test/cpp/interop/client.cc test/cpp/interop/interop_client.cc ) if(WIN32 AND MSVC) set_target_properties(interop_client_main PROPERTIES COMPILE_PDB_NAME "interop_client_main" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/interop_client_main.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() protobuf_generate_grpc_cpp( src/proto/grpc/testing/empty.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/messages.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/test.proto ) target_include_directories(interop_client_main PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(interop_client_main ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} interop_client_helper grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr grpc++_test_config ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_library(interop_server_helper test/cpp/interop/server_helper.cc ) if(WIN32 AND MSVC) set_target_properties(interop_server_helper PROPERTIES COMPILE_PDB_NAME "interop_server_helper" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/interop_server_helper.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(interop_server_helper PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(interop_server_helper ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_library(interop_server_lib ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.h test/cpp/interop/interop_server.cc ) if(WIN32 AND MSVC) set_target_properties(interop_server_lib PROPERTIES COMPILE_PDB_NAME "interop_server_lib" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/interop_server_lib.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() protobuf_generate_grpc_cpp( src/proto/grpc/testing/empty.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/messages.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/test.proto ) target_include_directories(interop_server_lib PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(interop_server_lib ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} interop_server_helper grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr grpc++_test_config ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_library(interop_server_main test/cpp/interop/interop_server_bootstrap.cc ) if(WIN32 AND MSVC) set_target_properties(interop_server_main PROPERTIES COMPILE_PDB_NAME "interop_server_main" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/interop_server_main.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(interop_server_main PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(interop_server_main ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} interop_server_lib ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_library(qps ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.grpc.pb.h test/cpp/qps/benchmark_config.cc test/cpp/qps/client_async.cc test/cpp/qps/client_sync.cc test/cpp/qps/driver.cc test/cpp/qps/parse_json.cc test/cpp/qps/qps_worker.cc test/cpp/qps/report.cc test/cpp/qps/server_async.cc test/cpp/qps/server_sync.cc test/cpp/qps/usage_timer.cc ) if(WIN32 AND MSVC) set_target_properties(qps PROPERTIES COMPILE_PDB_NAME "qps" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qps.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() protobuf_generate_grpc_cpp( src/proto/grpc/testing/messages.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/payloads.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/stats.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/control.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/services.proto ) target_include_directories(qps PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(qps ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc++_test_util grpc++ ) endif (gRPC_BUILD_TESTS) add_library(grpc_csharp_ext SHARED src/csharp/ext/grpc_csharp_ext.c ) if(WIN32 AND MSVC) set_target_properties(grpc_csharp_ext PROPERTIES COMPILE_PDB_NAME "grpc_csharp_ext" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_csharp_ext.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(grpc_csharp_ext PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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(grpc_csharp_ext ${_gRPC_ALLTARGETS_LIBRARIES} grpc gpr ) if (gRPC_INSTALL) install(TARGETS grpc_csharp_ext EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() if (gRPC_BUILD_TESTS) add_library(ares third_party/cares/cares/ares__close_sockets.c third_party/cares/cares/ares__get_hostent.c third_party/cares/cares/ares__read_line.c third_party/cares/cares/ares__timeval.c third_party/cares/cares/ares_cancel.c third_party/cares/cares/ares_create_query.c third_party/cares/cares/ares_data.c third_party/cares/cares/ares_destroy.c third_party/cares/cares/ares_expand_name.c third_party/cares/cares/ares_expand_string.c third_party/cares/cares/ares_fds.c third_party/cares/cares/ares_free_hostent.c third_party/cares/cares/ares_free_string.c third_party/cares/cares/ares_getenv.c third_party/cares/cares/ares_gethostbyaddr.c third_party/cares/cares/ares_gethostbyname.c third_party/cares/cares/ares_getnameinfo.c third_party/cares/cares/ares_getopt.c third_party/cares/cares/ares_getsock.c third_party/cares/cares/ares_init.c third_party/cares/cares/ares_library_init.c third_party/cares/cares/ares_llist.c third_party/cares/cares/ares_mkquery.c third_party/cares/cares/ares_nowarn.c third_party/cares/cares/ares_options.c third_party/cares/cares/ares_parse_a_reply.c third_party/cares/cares/ares_parse_aaaa_reply.c third_party/cares/cares/ares_parse_mx_reply.c third_party/cares/cares/ares_parse_naptr_reply.c third_party/cares/cares/ares_parse_ns_reply.c third_party/cares/cares/ares_parse_ptr_reply.c third_party/cares/cares/ares_parse_soa_reply.c third_party/cares/cares/ares_parse_srv_reply.c third_party/cares/cares/ares_parse_txt_reply.c third_party/cares/cares/ares_platform.c third_party/cares/cares/ares_process.c third_party/cares/cares/ares_query.c third_party/cares/cares/ares_search.c third_party/cares/cares/ares_send.c third_party/cares/cares/ares_strcasecmp.c third_party/cares/cares/ares_strdup.c third_party/cares/cares/ares_strerror.c third_party/cares/cares/ares_timeout.c third_party/cares/cares/ares_version.c third_party/cares/cares/ares_writev.c third_party/cares/cares/bitncmp.c third_party/cares/cares/inet_net_pton.c third_party/cares/cares/inet_ntop.c third_party/cares/cares/windows_port.c ) if(WIN32 AND MSVC) set_target_properties(ares PROPERTIES COMPILE_PDB_NAME "ares" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ares.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(ares PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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(ares ${_gRPC_SSL_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_library(bad_client_test test/core/bad_client/bad_client.c ) if(WIN32 AND MSVC) set_target_properties(bad_client_test PROPERTIES COMPILE_PDB_NAME "bad_client_test" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/bad_client_test.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(bad_client_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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(bad_client_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_library(bad_ssl_test_server test/core/bad_ssl/server_common.c ) if(WIN32 AND MSVC) set_target_properties(bad_ssl_test_server PROPERTIES COMPILE_PDB_NAME "bad_ssl_test_server" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/bad_ssl_test_server.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(bad_ssl_test_server PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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(bad_ssl_test_server ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_library(end2end_tests test/core/end2end/end2end_tests.c test/core/end2end/end2end_test_utils.c test/core/end2end/tests/authority_not_supported.c test/core/end2end/tests/bad_hostname.c test/core/end2end/tests/bad_ping.c test/core/end2end/tests/binary_metadata.c test/core/end2end/tests/call_creds.c test/core/end2end/tests/cancel_after_accept.c test/core/end2end/tests/cancel_after_client_done.c test/core/end2end/tests/cancel_after_invoke.c test/core/end2end/tests/cancel_before_invoke.c test/core/end2end/tests/cancel_in_a_vacuum.c test/core/end2end/tests/cancel_with_status.c test/core/end2end/tests/compressed_payload.c test/core/end2end/tests/connectivity.c test/core/end2end/tests/default_host.c test/core/end2end/tests/disappearing_server.c test/core/end2end/tests/empty_batch.c test/core/end2end/tests/filter_call_init_fails.c test/core/end2end/tests/filter_causes_close.c test/core/end2end/tests/filter_latency.c test/core/end2end/tests/graceful_server_shutdown.c test/core/end2end/tests/high_initial_seqno.c test/core/end2end/tests/hpack_size.c test/core/end2end/tests/idempotent_request.c test/core/end2end/tests/invoke_large_request.c test/core/end2end/tests/keepalive_timeout.c test/core/end2end/tests/large_metadata.c test/core/end2end/tests/load_reporting_hook.c test/core/end2end/tests/max_concurrent_streams.c test/core/end2end/tests/max_connection_age.c test/core/end2end/tests/max_connection_idle.c test/core/end2end/tests/max_message_length.c test/core/end2end/tests/negative_deadline.c test/core/end2end/tests/network_status_change.c test/core/end2end/tests/no_logging.c test/core/end2end/tests/no_op.c test/core/end2end/tests/payload.c test/core/end2end/tests/ping.c test/core/end2end/tests/ping_pong_streaming.c test/core/end2end/tests/registered_call.c test/core/end2end/tests/request_with_flags.c test/core/end2end/tests/request_with_payload.c test/core/end2end/tests/resource_quota_server.c test/core/end2end/tests/server_finishes_request.c test/core/end2end/tests/shutdown_finishes_calls.c test/core/end2end/tests/shutdown_finishes_tags.c test/core/end2end/tests/simple_cacheable_request.c test/core/end2end/tests/simple_delayed_request.c test/core/end2end/tests/simple_metadata.c test/core/end2end/tests/simple_request.c test/core/end2end/tests/streaming_error_response.c test/core/end2end/tests/trailing_metadata.c test/core/end2end/tests/write_buffering.c test/core/end2end/tests/write_buffering_at_end.c ) if(WIN32 AND MSVC) set_target_properties(end2end_tests PROPERTIES COMPILE_PDB_NAME "end2end_tests" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/end2end_tests.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(end2end_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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(end2end_tests ${_gRPC_SSL_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_library(end2end_nosec_tests test/core/end2end/end2end_nosec_tests.c test/core/end2end/end2end_test_utils.c test/core/end2end/tests/authority_not_supported.c test/core/end2end/tests/bad_hostname.c test/core/end2end/tests/bad_ping.c test/core/end2end/tests/binary_metadata.c test/core/end2end/tests/cancel_after_accept.c test/core/end2end/tests/cancel_after_client_done.c test/core/end2end/tests/cancel_after_invoke.c test/core/end2end/tests/cancel_before_invoke.c test/core/end2end/tests/cancel_in_a_vacuum.c test/core/end2end/tests/cancel_with_status.c test/core/end2end/tests/compressed_payload.c test/core/end2end/tests/connectivity.c test/core/end2end/tests/default_host.c test/core/end2end/tests/disappearing_server.c test/core/end2end/tests/empty_batch.c test/core/end2end/tests/filter_call_init_fails.c test/core/end2end/tests/filter_causes_close.c test/core/end2end/tests/filter_latency.c test/core/end2end/tests/graceful_server_shutdown.c test/core/end2end/tests/high_initial_seqno.c test/core/end2end/tests/hpack_size.c test/core/end2end/tests/idempotent_request.c test/core/end2end/tests/invoke_large_request.c test/core/end2end/tests/keepalive_timeout.c test/core/end2end/tests/large_metadata.c test/core/end2end/tests/load_reporting_hook.c test/core/end2end/tests/max_concurrent_streams.c test/core/end2end/tests/max_connection_age.c test/core/end2end/tests/max_connection_idle.c test/core/end2end/tests/max_message_length.c test/core/end2end/tests/negative_deadline.c test/core/end2end/tests/network_status_change.c test/core/end2end/tests/no_logging.c test/core/end2end/tests/no_op.c test/core/end2end/tests/payload.c test/core/end2end/tests/ping.c test/core/end2end/tests/ping_pong_streaming.c test/core/end2end/tests/registered_call.c test/core/end2end/tests/request_with_flags.c test/core/end2end/tests/request_with_payload.c test/core/end2end/tests/resource_quota_server.c test/core/end2end/tests/server_finishes_request.c test/core/end2end/tests/shutdown_finishes_calls.c test/core/end2end/tests/shutdown_finishes_tags.c test/core/end2end/tests/simple_cacheable_request.c test/core/end2end/tests/simple_delayed_request.c test/core/end2end/tests/simple_metadata.c test/core/end2end/tests/simple_request.c test/core/end2end/tests/streaming_error_response.c test/core/end2end/tests/trailing_metadata.c test/core/end2end/tests/write_buffering.c test/core/end2end/tests/write_buffering_at_end.c ) if(WIN32 AND MSVC) set_target_properties(end2end_nosec_tests PROPERTIES COMPILE_PDB_NAME "end2end_nosec_tests" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) if (gRPC_INSTALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/end2end_nosec_tests.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL ) endif() endif() target_include_directories(end2end_nosec_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${ZLIB_INCLUDE_DIR} PRIVATE ${BENCHMARK}/include 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(end2end_nosec_tests ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(alarm_test test/core/surface/alarm_test.c ) target_include_directories(alarm_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(alarm_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(algorithm_test test/core/compression/algorithm_test.c ) target_include_directories(algorithm_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(algorithm_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(alloc_test test/core/support/alloc_test.c ) target_include_directories(alloc_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(alloc_test ${_gRPC_ALLTARGETS_LIBRARIES} gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(alpn_test test/core/transport/chttp2/alpn_test.c ) target_include_directories(alpn_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(alpn_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(arena_test test/core/support/arena_test.c ) target_include_directories(arena_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(arena_test ${_gRPC_ALLTARGETS_LIBRARIES} gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(bad_server_response_test test/core/end2end/bad_server_response_test.c ) target_include_directories(bad_server_response_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(bad_server_response_test ${_gRPC_ALLTARGETS_LIBRARIES} test_tcp_server grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(bdp_estimator_test test/core/transport/bdp_estimator_test.c ) target_include_directories(bdp_estimator_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(bdp_estimator_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(bin_decoder_test test/core/transport/chttp2/bin_decoder_test.c ) target_include_directories(bin_decoder_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(bin_decoder_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(bin_encoder_test test/core/transport/chttp2/bin_encoder_test.c ) target_include_directories(bin_encoder_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(bin_encoder_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(census_context_test test/core/census/context_test.c ) target_include_directories(census_context_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_context_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 test/core/census/resource_test.c ) target_include_directories(census_resource_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_resource_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(census_trace_context_test test/core/census/trace_context_test.c ) target_include_directories(census_trace_context_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_trace_context_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(channel_create_test test/core/surface/channel_create_test.c ) target_include_directories(channel_create_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(channel_create_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(chttp2_hpack_encoder_test test/core/transport/chttp2/hpack_encoder_test.c ) target_include_directories(chttp2_hpack_encoder_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(chttp2_hpack_encoder_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(chttp2_stream_map_test test/core/transport/chttp2/stream_map_test.c ) target_include_directories(chttp2_stream_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(chttp2_stream_map_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(chttp2_varint_test test/core/transport/chttp2/varint_test.c ) target_include_directories(chttp2_varint_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(chttp2_varint_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(combiner_test test/core/iomgr/combiner_test.c ) target_include_directories(combiner_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(combiner_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(compression_test test/core/compression/compression_test.c ) target_include_directories(compression_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(compression_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(concurrent_connectivity_test test/core/surface/concurrent_connectivity_test.c ) target_include_directories(concurrent_connectivity_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(concurrent_connectivity_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(connection_refused_test test/core/end2end/connection_refused_test.c ) target_include_directories(connection_refused_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(connection_refused_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(dns_resolver_connectivity_test test/core/client_channel/resolvers/dns_resolver_connectivity_test.c ) target_include_directories(dns_resolver_connectivity_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(dns_resolver_connectivity_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(dns_resolver_test test/core/client_channel/resolvers/dns_resolver_test.c ) target_include_directories(dns_resolver_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(dns_resolver_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(dualstack_socket_test test/core/end2end/dualstack_socket_test.c ) target_include_directories(dualstack_socket_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(dualstack_socket_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(endpoint_pair_test test/core/iomgr/endpoint_pair_test.c ) target_include_directories(endpoint_pair_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(endpoint_pair_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(error_test test/core/iomgr/error_test.c ) target_include_directories(error_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(error_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX) add_executable(ev_epoll_linux_test test/core/iomgr/ev_epoll_linux_test.c ) target_include_directories(ev_epoll_linux_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(ev_epoll_linux_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(fd_conservation_posix_test test/core/iomgr/fd_conservation_posix_test.c ) target_include_directories(fd_conservation_posix_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(fd_conservation_posix_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(fd_posix_test test/core/iomgr/fd_posix_test.c ) target_include_directories(fd_posix_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(fd_posix_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(fling_client test/core/fling/client.c ) target_include_directories(fling_client 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(fling_client ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(fling_server test/core/fling/server.c ) target_include_directories(fling_server 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(fling_server ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(fling_stream_test test/core/fling/fling_stream_test.c ) target_include_directories(fling_stream_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(fling_stream_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(fling_test test/core/fling/fling_test.c ) target_include_directories(fling_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(fling_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) add_executable(gen_hpack_tables tools/codegen/core/gen_hpack_tables.c ) target_include_directories(gen_hpack_tables 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(gen_hpack_tables ${_gRPC_ALLTARGETS_LIBRARIES} gpr grpc ) if (gRPC_INSTALL) install(TARGETS gen_hpack_tables EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() add_executable(gen_legal_metadata_characters tools/codegen/core/gen_legal_metadata_characters.c ) target_include_directories(gen_legal_metadata_characters 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(gen_legal_metadata_characters ${_gRPC_ALLTARGETS_LIBRARIES} ) if (gRPC_INSTALL) install(TARGETS gen_legal_metadata_characters EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() add_executable(gen_percent_encoding_tables tools/codegen/core/gen_percent_encoding_tables.c ) target_include_directories(gen_percent_encoding_tables 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(gen_percent_encoding_tables ${_gRPC_ALLTARGETS_LIBRARIES} ) if (gRPC_INSTALL) install(TARGETS gen_percent_encoding_tables EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(goaway_server_test test/core/end2end/goaway_server_test.c ) target_include_directories(goaway_server_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(goaway_server_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_avl_test test/core/support/avl_test.c ) target_include_directories(gpr_avl_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(gpr_avl_test ${_gRPC_ALLTARGETS_LIBRARIES} gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_backoff_test test/core/support/backoff_test.c ) target_include_directories(gpr_backoff_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(gpr_backoff_test ${_gRPC_ALLTARGETS_LIBRARIES} gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_cmdline_test test/core/support/cmdline_test.c ) target_include_directories(gpr_cmdline_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(gpr_cmdline_test ${_gRPC_ALLTARGETS_LIBRARIES} gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_cpu_test test/core/support/cpu_test.c ) target_include_directories(gpr_cpu_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(gpr_cpu_test ${_gRPC_ALLTARGETS_LIBRARIES} gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_env_test test/core/support/env_test.c ) target_include_directories(gpr_env_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(gpr_env_test ${_gRPC_ALLTARGETS_LIBRARIES} gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_histogram_test test/core/support/histogram_test.c ) target_include_directories(gpr_histogram_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(gpr_histogram_test ${_gRPC_ALLTARGETS_LIBRARIES} gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_host_port_test test/core/support/host_port_test.c ) target_include_directories(gpr_host_port_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(gpr_host_port_test ${_gRPC_ALLTARGETS_LIBRARIES} gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_log_test test/core/support/log_test.c ) target_include_directories(gpr_log_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(gpr_log_test ${_gRPC_ALLTARGETS_LIBRARIES} gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_mpscq_test test/core/support/mpscq_test.c ) target_include_directories(gpr_mpscq_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(gpr_mpscq_test ${_gRPC_ALLTARGETS_LIBRARIES} gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_spinlock_test test/core/support/spinlock_test.c ) target_include_directories(gpr_spinlock_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(gpr_spinlock_test ${_gRPC_ALLTARGETS_LIBRARIES} gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_stack_lockfree_test test/core/support/stack_lockfree_test.c ) target_include_directories(gpr_stack_lockfree_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(gpr_stack_lockfree_test ${_gRPC_ALLTARGETS_LIBRARIES} gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_string_test test/core/support/string_test.c ) target_include_directories(gpr_string_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(gpr_string_test ${_gRPC_ALLTARGETS_LIBRARIES} gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_sync_test test/core/support/sync_test.c ) target_include_directories(gpr_sync_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(gpr_sync_test ${_gRPC_ALLTARGETS_LIBRARIES} gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_thd_test test/core/support/thd_test.c ) target_include_directories(gpr_thd_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(gpr_thd_test ${_gRPC_ALLTARGETS_LIBRARIES} gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_time_test test/core/support/time_test.c ) target_include_directories(gpr_time_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(gpr_time_test ${_gRPC_ALLTARGETS_LIBRARIES} gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_tls_test test/core/support/tls_test.c ) target_include_directories(gpr_tls_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(gpr_tls_test ${_gRPC_ALLTARGETS_LIBRARIES} gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(gpr_useful_test test/core/support/useful_test.c ) target_include_directories(gpr_useful_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(gpr_useful_test ${_gRPC_ALLTARGETS_LIBRARIES} gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_auth_context_test test/core/security/auth_context_test.c ) target_include_directories(grpc_auth_context_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(grpc_auth_context_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_b64_test test/core/slice/b64_test.c ) target_include_directories(grpc_b64_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(grpc_b64_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_byte_buffer_reader_test test/core/surface/byte_buffer_reader_test.c ) target_include_directories(grpc_byte_buffer_reader_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(grpc_byte_buffer_reader_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_channel_args_test test/core/channel/channel_args_test.c ) target_include_directories(grpc_channel_args_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(grpc_channel_args_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_channel_stack_test test/core/channel/channel_stack_test.c ) target_include_directories(grpc_channel_stack_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(grpc_channel_stack_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_completion_queue_test test/core/surface/completion_queue_test.c ) target_include_directories(grpc_completion_queue_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(grpc_completion_queue_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_completion_queue_threading_test test/core/surface/completion_queue_threading_test.c ) target_include_directories(grpc_completion_queue_threading_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(grpc_completion_queue_threading_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) add_executable(grpc_create_jwt test/core/security/create_jwt.c ) target_include_directories(grpc_create_jwt 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(grpc_create_jwt ${_gRPC_SSL_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc gpr ) if (gRPC_INSTALL) install(TARGETS grpc_create_jwt EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() if (gRPC_BUILD_TESTS) add_executable(grpc_credentials_test test/core/security/credentials_test.c ) target_include_directories(grpc_credentials_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(grpc_credentials_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_fetch_oauth2 test/core/security/fetch_oauth2.c ) target_include_directories(grpc_fetch_oauth2 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(grpc_fetch_oauth2 ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_invalid_channel_args_test test/core/surface/invalid_channel_args_test.c ) target_include_directories(grpc_invalid_channel_args_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(grpc_invalid_channel_args_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(grpc_json_token_test test/core/security/json_token_test.c ) target_include_directories(grpc_json_token_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(grpc_json_token_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_jwt_verifier_test test/core/security/jwt_verifier_test.c ) target_include_directories(grpc_jwt_verifier_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(grpc_jwt_verifier_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) add_executable(grpc_print_google_default_creds_token test/core/security/print_google_default_creds_token.c ) target_include_directories(grpc_print_google_default_creds_token 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(grpc_print_google_default_creds_token ${_gRPC_ALLTARGETS_LIBRARIES} grpc gpr ) if (gRPC_INSTALL) install(TARGETS grpc_print_google_default_creds_token EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() if (gRPC_BUILD_TESTS) add_executable(grpc_security_connector_test test/core/security/security_connector_test.c ) target_include_directories(grpc_security_connector_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(grpc_security_connector_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) add_executable(grpc_verify_jwt test/core/security/verify_jwt.c ) target_include_directories(grpc_verify_jwt 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(grpc_verify_jwt ${_gRPC_ALLTARGETS_LIBRARIES} grpc gpr ) if (gRPC_INSTALL) install(TARGETS grpc_verify_jwt EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX) add_executable(handshake_client test/core/handshake/client_ssl.c ) target_include_directories(handshake_client 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(handshake_client ${_gRPC_SSL_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX) add_executable(handshake_server test/core/handshake/server_ssl.c ) target_include_directories(handshake_server 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(handshake_server ${_gRPC_SSL_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(hpack_parser_test test/core/transport/chttp2/hpack_parser_test.c ) target_include_directories(hpack_parser_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(hpack_parser_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(hpack_table_test test/core/transport/chttp2/hpack_table_test.c ) target_include_directories(hpack_table_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(hpack_table_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(http_parser_test test/core/http/parser_test.c ) target_include_directories(http_parser_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(http_parser_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(httpcli_format_request_test test/core/http/format_request_test.c ) target_include_directories(httpcli_format_request_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(httpcli_format_request_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(httpcli_test test/core/http/httpcli_test.c ) target_include_directories(httpcli_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(httpcli_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX) add_executable(httpscli_test test/core/http/httpscli_test.c ) target_include_directories(httpscli_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(httpscli_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(init_test test/core/surface/init_test.c ) target_include_directories(init_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(init_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(invalid_call_argument_test test/core/end2end/invalid_call_argument_test.c ) target_include_directories(invalid_call_argument_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(invalid_call_argument_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(json_rewrite test/core/json/json_rewrite.c ) target_include_directories(json_rewrite 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(json_rewrite ${_gRPC_ALLTARGETS_LIBRARIES} grpc gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(json_rewrite_test test/core/json/json_rewrite_test.c ) target_include_directories(json_rewrite_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(json_rewrite_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(json_stream_error_test test/core/json/json_stream_error_test.c ) target_include_directories(json_stream_error_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(json_stream_error_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(json_test test/core/json/json_test.c ) target_include_directories(json_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(json_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(lame_client_test test/core/surface/lame_client_test.c ) target_include_directories(lame_client_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(lame_client_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(lb_policies_test test/core/client_channel/lb_policies_test.c ) target_include_directories(lb_policies_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(lb_policies_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(load_file_test test/core/iomgr/load_file_test.c ) target_include_directories(load_file_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(load_file_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(memory_profile_client test/core/memory_usage/client.c ) target_include_directories(memory_profile_client 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(memory_profile_client ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(memory_profile_server test/core/memory_usage/server.c ) target_include_directories(memory_profile_server 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(memory_profile_server ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(memory_profile_test test/core/memory_usage/memory_usage_test.c ) target_include_directories(memory_profile_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(memory_profile_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(message_compress_test test/core/compression/message_compress_test.c ) target_include_directories(message_compress_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(message_compress_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(mlog_test test/core/census/mlog_test.c ) target_include_directories(mlog_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(mlog_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(multiple_server_queues_test test/core/end2end/multiple_server_queues_test.c ) target_include_directories(multiple_server_queues_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(multiple_server_queues_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(murmur_hash_test test/core/support/murmur_hash_test.c ) target_include_directories(murmur_hash_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(murmur_hash_test ${_gRPC_ALLTARGETS_LIBRARIES} gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(no_server_test test/core/end2end/no_server_test.c ) target_include_directories(no_server_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(no_server_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(parse_address_test test/core/client_channel/parse_address_test.c ) target_include_directories(parse_address_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(parse_address_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(percent_encoding_test test/core/slice/percent_encoding_test.c ) target_include_directories(percent_encoding_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(percent_encoding_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX) add_executable(pollset_set_test test/core/iomgr/pollset_set_test.c ) target_include_directories(pollset_set_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(pollset_set_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(resolve_address_posix_test test/core/iomgr/resolve_address_posix_test.c ) target_include_directories(resolve_address_posix_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(resolve_address_posix_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(resolve_address_test test/core/iomgr/resolve_address_test.c ) target_include_directories(resolve_address_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(resolve_address_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(resource_quota_test test/core/iomgr/resource_quota_test.c ) target_include_directories(resource_quota_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(resource_quota_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(secure_channel_create_test test/core/surface/secure_channel_create_test.c ) target_include_directories(secure_channel_create_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(secure_channel_create_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(secure_endpoint_test test/core/security/secure_endpoint_test.c ) target_include_directories(secure_endpoint_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(secure_endpoint_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(sequential_connectivity_test test/core/surface/sequential_connectivity_test.c ) target_include_directories(sequential_connectivity_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(sequential_connectivity_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(server_chttp2_test test/core/surface/server_chttp2_test.c ) target_include_directories(server_chttp2_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(server_chttp2_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(server_test test/core/surface/server_test.c ) target_include_directories(server_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(server_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(slice_buffer_test test/core/slice/slice_buffer_test.c ) target_include_directories(slice_buffer_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(slice_buffer_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(slice_string_helpers_test test/core/slice/slice_string_helpers_test.c ) target_include_directories(slice_string_helpers_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(slice_string_helpers_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(slice_test test/core/slice/slice_test.c ) target_include_directories(slice_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(slice_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(sockaddr_resolver_test test/core/client_channel/resolvers/sockaddr_resolver_test.c ) target_include_directories(sockaddr_resolver_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(sockaddr_resolver_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(sockaddr_utils_test test/core/iomgr/sockaddr_utils_test.c ) target_include_directories(sockaddr_utils_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(sockaddr_utils_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(socket_utils_test test/core/iomgr/socket_utils_test.c ) target_include_directories(socket_utils_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(socket_utils_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(status_conversion_test test/core/transport/status_conversion_test.c ) target_include_directories(status_conversion_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(status_conversion_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(stream_owned_slice_test test/core/transport/stream_owned_slice_test.c ) target_include_directories(stream_owned_slice_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(stream_owned_slice_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(tcp_client_posix_test test/core/iomgr/tcp_client_posix_test.c ) target_include_directories(tcp_client_posix_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(tcp_client_posix_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(tcp_client_uv_test test/core/iomgr/tcp_client_uv_test.c ) target_include_directories(tcp_client_uv_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(tcp_client_uv_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(tcp_posix_test test/core/iomgr/tcp_posix_test.c ) target_include_directories(tcp_posix_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(tcp_posix_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(tcp_server_posix_test test/core/iomgr/tcp_server_posix_test.c ) target_include_directories(tcp_server_posix_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(tcp_server_posix_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(tcp_server_uv_test test/core/iomgr/tcp_server_uv_test.c ) target_include_directories(tcp_server_uv_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(tcp_server_uv_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(time_averaged_stats_test test/core/iomgr/time_averaged_stats_test.c ) target_include_directories(time_averaged_stats_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(time_averaged_stats_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(timeout_encoding_test test/core/transport/timeout_encoding_test.c ) target_include_directories(timeout_encoding_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(timeout_encoding_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(timer_heap_test test/core/iomgr/timer_heap_test.c ) target_include_directories(timer_heap_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(timer_heap_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(timer_list_test test/core/iomgr/timer_list_test.c ) target_include_directories(timer_list_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(timer_list_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(transport_connectivity_state_test test/core/transport/connectivity_state_test.c ) target_include_directories(transport_connectivity_state_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(transport_connectivity_state_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(transport_metadata_test test/core/transport/metadata_test.c ) target_include_directories(transport_metadata_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(transport_metadata_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(transport_pid_controller_test test/core/transport/pid_controller_test.c ) target_include_directories(transport_pid_controller_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(transport_pid_controller_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(transport_security_test test/core/tsi/transport_security_test.c ) target_include_directories(transport_security_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(transport_security_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(udp_server_test test/core/iomgr/udp_server_test.c ) target_include_directories(udp_server_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(udp_server_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(uri_parser_test test/core/client_channel/uri_parser_test.c ) target_include_directories(uri_parser_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(uri_parser_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(wakeup_fd_cv_test test/core/iomgr/wakeup_fd_cv_test.c ) target_include_directories(wakeup_fd_cv_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(wakeup_fd_cv_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(alarm_cpp_test test/cpp/common/alarm_cpp_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(alarm_cpp_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(alarm_cpp_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(async_end2end_test test/cpp/end2end/async_end2end_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(async_end2end_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(async_end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(auth_property_iterator_test test/cpp/common/auth_property_iterator_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(auth_property_iterator_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(auth_property_iterator_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(bm_arena test/cpp/microbenchmarks/bm_arena.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(bm_arena 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(bm_arena ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_benchmark benchmark grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(bm_call_create test/cpp/microbenchmarks/bm_call_create.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(bm_call_create 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(bm_call_create ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_benchmark benchmark grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(bm_chttp2_hpack test/cpp/microbenchmarks/bm_chttp2_hpack.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(bm_chttp2_hpack 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(bm_chttp2_hpack ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_benchmark benchmark grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(bm_chttp2_transport test/cpp/microbenchmarks/bm_chttp2_transport.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(bm_chttp2_transport 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(bm_chttp2_transport ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_benchmark benchmark grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(bm_closure test/cpp/microbenchmarks/bm_closure.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(bm_closure 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(bm_closure ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_benchmark benchmark grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(bm_cq test/cpp/microbenchmarks/bm_cq.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(bm_cq 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(bm_cq ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_benchmark benchmark grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(bm_cq_multiple_threads test/cpp/microbenchmarks/bm_cq_multiple_threads.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(bm_cq_multiple_threads 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(bm_cq_multiple_threads ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_benchmark benchmark grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(bm_error test/cpp/microbenchmarks/bm_error.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(bm_error 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(bm_error ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_benchmark benchmark grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(bm_fullstack_streaming_ping_pong test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(bm_fullstack_streaming_ping_pong 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(bm_fullstack_streaming_ping_pong ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_benchmark benchmark grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(bm_fullstack_streaming_pump test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(bm_fullstack_streaming_pump 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(bm_fullstack_streaming_pump ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_benchmark benchmark grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(bm_fullstack_trickle test/cpp/microbenchmarks/bm_fullstack_trickle.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(bm_fullstack_trickle 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(bm_fullstack_trickle ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_benchmark benchmark grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(bm_fullstack_unary_ping_pong test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(bm_fullstack_unary_ping_pong 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(bm_fullstack_unary_ping_pong ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_benchmark benchmark grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(bm_metadata test/cpp/microbenchmarks/bm_metadata.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(bm_metadata 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(bm_metadata ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_benchmark benchmark grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(bm_pollset test/cpp/microbenchmarks/bm_pollset.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(bm_pollset 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(bm_pollset ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_benchmark benchmark grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(channel_arguments_test test/cpp/common/channel_arguments_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(channel_arguments_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(channel_arguments_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++ grpc gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(channel_filter_test test/cpp/common/channel_filter_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(channel_filter_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(channel_filter_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++ grpc gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(cli_call_test test/cpp/util/cli_call_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(cli_call_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(cli_call_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_cli_libs grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(client_crash_test test/cpp/end2end/client_crash_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(client_crash_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(client_crash_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(client_crash_test_server test/cpp/end2end/client_crash_test_server.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(client_crash_test_server 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(client_crash_test_server ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(codegen_test_full ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.grpc.pb.h test/cpp/codegen/codegen_test_full.cc third_party/googletest/googletest/src/gtest-all.cc ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/control.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/messages.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/payloads.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/services.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/stats.proto ) target_include_directories(codegen_test_full 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(codegen_test_full ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++ grpc gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(codegen_test_minimal ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.grpc.pb.h test/cpp/codegen/codegen_test_minimal.cc src/cpp/codegen/codegen_init.cc third_party/googletest/googletest/src/gtest-all.cc ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/control.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/messages.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/payloads.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/services.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/stats.proto ) target_include_directories(codegen_test_minimal 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(codegen_test_minimal ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(credentials_test test/cpp/client/credentials_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(credentials_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(credentials_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++ grpc gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(cxx_byte_buffer_test test/cpp/util/byte_buffer_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(cxx_byte_buffer_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(cxx_byte_buffer_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(cxx_slice_test test/cpp/util/slice_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(cxx_slice_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(cxx_slice_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(cxx_string_ref_test test/cpp/util/string_ref_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(cxx_string_ref_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(cxx_string_ref_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++ ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(cxx_time_test test/cpp/util/time_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(cxx_time_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(cxx_time_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(end2end_test test/cpp/end2end/end2end_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(end2end_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(error_details_test ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h test/cpp/util/error_details_test.cc third_party/googletest/googletest/src/gtest-all.cc ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/echo_messages.proto ) target_include_directories(error_details_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(error_details_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_error_details grpc++ ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(filter_end2end_test test/cpp/end2end/filter_end2end_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(filter_end2end_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(filter_end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(generic_end2end_test test/cpp/end2end/generic_end2end_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(generic_end2end_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(generic_end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(golden_file_test ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/compiler_test.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/compiler_test.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/compiler_test.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/compiler_test.grpc.pb.h test/cpp/codegen/golden_file_test.cc third_party/googletest/googletest/src/gtest-all.cc ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/compiler_test.proto ) target_include_directories(golden_file_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(golden_file_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++ grpc gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpc_cli test/cpp/util/grpc_cli.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(grpc_cli 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpc_cli ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_cli_libs grpc++_proto_reflection_desc_db grpc++ grpc gpr grpc++_test_config ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) add_executable(grpc_cpp_plugin src/compiler/cpp_plugin.cc ) target_include_directories(grpc_cpp_plugin 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 PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpc_cpp_plugin ${_gRPC_PROTOBUF_PROTOC_LIBRARIES} ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_plugin_support ) if (gRPC_INSTALL) install(TARGETS grpc_cpp_plugin EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() add_executable(grpc_csharp_plugin src/compiler/csharp_plugin.cc ) target_include_directories(grpc_csharp_plugin 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 PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpc_csharp_plugin ${_gRPC_PROTOBUF_PROTOC_LIBRARIES} ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_plugin_support ) if (gRPC_INSTALL) install(TARGETS grpc_csharp_plugin EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() add_executable(grpc_node_plugin src/compiler/node_plugin.cc ) target_include_directories(grpc_node_plugin 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 PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpc_node_plugin ${_gRPC_PROTOBUF_PROTOC_LIBRARIES} ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_plugin_support ) if (gRPC_INSTALL) install(TARGETS grpc_node_plugin EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() add_executable(grpc_objective_c_plugin src/compiler/objective_c_plugin.cc ) target_include_directories(grpc_objective_c_plugin 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 PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpc_objective_c_plugin ${_gRPC_PROTOBUF_PROTOC_LIBRARIES} ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_plugin_support ) if (gRPC_INSTALL) install(TARGETS grpc_objective_c_plugin EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() add_executable(grpc_php_plugin src/compiler/php_plugin.cc ) target_include_directories(grpc_php_plugin 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 PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpc_php_plugin ${_gRPC_PROTOBUF_PROTOC_LIBRARIES} ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_plugin_support ) if (gRPC_INSTALL) install(TARGETS grpc_php_plugin EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() add_executable(grpc_python_plugin src/compiler/python_plugin.cc ) target_include_directories(grpc_python_plugin 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 PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpc_python_plugin ${_gRPC_PROTOBUF_PROTOC_LIBRARIES} ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_plugin_support ) if (gRPC_INSTALL) install(TARGETS grpc_python_plugin EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() add_executable(grpc_ruby_plugin src/compiler/ruby_plugin.cc ) target_include_directories(grpc_ruby_plugin 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 PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpc_ruby_plugin ${_gRPC_PROTOBUF_PROTOC_LIBRARIES} ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_plugin_support ) if (gRPC_INSTALL) install(TARGETS grpc_ruby_plugin EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() if (gRPC_BUILD_TESTS) add_executable(grpc_tool_test ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h test/cpp/util/grpc_tool_test.cc third_party/googletest/googletest/src/gtest-all.cc ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/echo.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/echo_messages.proto ) target_include_directories(grpc_tool_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpc_tool_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_cli_libs grpc++_proto_reflection_desc_db grpc++_reflection grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpclb_api_test ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.grpc.pb.h test/cpp/grpclb/grpclb_api_test.cc third_party/googletest/googletest/src/gtest-all.cc ) protobuf_generate_grpc_cpp( src/proto/grpc/lb/v1/load_balancer.proto ) target_include_directories(grpclb_api_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpclb_api_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(grpclb_test ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.grpc.pb.h test/cpp/grpclb/grpclb_test.cc third_party/googletest/googletest/src/gtest-all.cc ) protobuf_generate_grpc_cpp( src/proto/grpc/lb/v1/load_balancer.proto ) target_include_directories(grpclb_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(grpclb_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(health_service_end2end_test test/cpp/end2end/health_service_end2end_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(health_service_end2end_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(health_service_end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(http2_client third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(http2_client 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(http2_client ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} http2_client_main grpc++_test_util grpc_test_util grpc++ grpc grpc++_test_config ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(hybrid_end2end_test test/cpp/end2end/hybrid_end2end_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(hybrid_end2end_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(hybrid_end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(interop_client third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(interop_client 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(interop_client ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} interop_client_main interop_client_helper grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr grpc++_test_config ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(interop_server third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(interop_server 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(interop_server ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} interop_server_main interop_server_helper interop_server_lib grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr grpc++_test_config ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(interop_test test/cpp/interop/interop_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(interop_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(interop_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr grpc++_test_config ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(json_run_localhost test/cpp/qps/json_run_localhost.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(json_run_localhost 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(json_run_localhost ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr grpc++_test_config ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(metrics_client ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/metrics.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/metrics.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/metrics.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/metrics.grpc.pb.h test/cpp/interop/metrics_client.cc third_party/googletest/googletest/src/gtest-all.cc ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/metrics.proto ) target_include_directories(metrics_client 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(metrics_client ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++ grpc gpr grpc++_test_config ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(mock_test test/cpp/end2end/mock_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(mock_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(mock_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(noop-benchmark test/cpp/microbenchmarks/noop-benchmark.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(noop-benchmark 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(noop-benchmark ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(proto_server_reflection_test test/cpp/end2end/proto_server_reflection_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(proto_server_reflection_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(proto_server_reflection_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_proto_reflection_desc_db grpc++_reflection grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(proto_utils_test test/cpp/codegen/proto_utils_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(proto_utils_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(proto_utils_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++ grpc ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(qps_interarrival_test test/cpp/qps/qps_interarrival_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(qps_interarrival_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(qps_interarrival_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} qps grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(qps_json_driver test/cpp/qps/qps_json_driver.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(qps_json_driver 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(qps_json_driver ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} qps grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr grpc++_test_config ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(qps_openloop_test test/cpp/qps/qps_openloop_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(qps_openloop_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(qps_openloop_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} qps grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr grpc++_test_config ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(qps_worker test/cpp/qps/worker.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(qps_worker 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(qps_worker ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} qps grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr grpc++_test_config ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(reconnect_interop_client ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.h test/cpp/interop/reconnect_interop_client.cc third_party/googletest/googletest/src/gtest-all.cc ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/empty.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/messages.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/test.proto ) target_include_directories(reconnect_interop_client 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(reconnect_interop_client ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr grpc++_test_config ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(reconnect_interop_server ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.h test/cpp/interop/reconnect_interop_server.cc third_party/googletest/googletest/src/gtest-all.cc ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/empty.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/messages.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/test.proto ) target_include_directories(reconnect_interop_server 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(reconnect_interop_server ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} reconnect_server test_tcp_server grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr grpc++_test_config ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(round_robin_end2end_test test/cpp/end2end/round_robin_end2end_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(round_robin_end2end_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(round_robin_end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(secure_auth_context_test test/cpp/common/secure_auth_context_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(secure_auth_context_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(secure_auth_context_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(secure_sync_unary_ping_pong_test test/cpp/qps/secure_sync_unary_ping_pong_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(secure_sync_unary_ping_pong_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(secure_sync_unary_ping_pong_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} qps grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(server_builder_plugin_test test/cpp/end2end/server_builder_plugin_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(server_builder_plugin_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(server_builder_plugin_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(server_builder_test ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h test/cpp/server/server_builder_test.cc third_party/googletest/googletest/src/gtest-all.cc ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/echo_messages.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/echo.proto ) target_include_directories(server_builder_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(server_builder_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util gpr_test_util grpc++ grpc gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(server_context_test_spouse_test test/cpp/test/server_context_test_spouse_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(server_context_test_spouse_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(server_context_test_spouse_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(server_crash_test test/cpp/end2end/server_crash_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(server_crash_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(server_crash_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(server_crash_test_client test/cpp/end2end/server_crash_test_client.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(server_crash_test_client 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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(server_crash_test_client ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(shutdown_test test/cpp/end2end/shutdown_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(shutdown_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(shutdown_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(status_test test/cpp/util/status_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(status_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(status_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(streaming_throughput_test test/cpp/end2end/streaming_throughput_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(streaming_throughput_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(streaming_throughput_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(stress_test ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/metrics.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/metrics.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/metrics.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/metrics.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.h test/cpp/interop/interop_client.cc test/cpp/interop/stress_interop_client.cc test/cpp/interop/stress_test.cc test/cpp/util/metrics_server.cc third_party/googletest/googletest/src/gtest-all.cc ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/empty.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/messages.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/metrics.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/test.proto ) target_include_directories(stress_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(stress_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr grpc++_test_config ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(thread_manager_test test/cpp/thread_manager/thread_manager_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(thread_manager_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(thread_manager_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++ grpc gpr grpc++_test_config ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(thread_stress_test test/cpp/end2end/thread_stress_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(thread_stress_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(thread_stress_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(writes_per_rpc_test test/cpp/performance/writes_per_rpc_test.cc third_party/googletest/googletest/src/gtest-all.cc ) target_include_directories(writes_per_rpc_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 PRIVATE third_party/googletest/googletest/include PRIVATE third_party/googletest/googletest PRIVATE ${_gRPC_PROTO_GENS_DIR} ) target_link_libraries(writes_per_rpc_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util grpc_test_util grpc++ grpc gpr_test_util gpr ${_gRPC_GFLAGS_LIBRARIES} ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(public_headers_must_be_c89 test/core/surface/public_headers_must_be_c89.c ) target_include_directories(public_headers_must_be_c89 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(public_headers_must_be_c89 ${_gRPC_ALLTARGETS_LIBRARIES} grpc gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(badreq_bad_client_test test/core/bad_client/tests/badreq.c ) target_include_directories(badreq_bad_client_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(badreq_bad_client_test ${_gRPC_SSL_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} bad_client_test grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(connection_prefix_bad_client_test test/core/bad_client/tests/connection_prefix.c ) target_include_directories(connection_prefix_bad_client_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(connection_prefix_bad_client_test ${_gRPC_SSL_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} bad_client_test grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(head_of_line_blocking_bad_client_test test/core/bad_client/tests/head_of_line_blocking.c ) target_include_directories(head_of_line_blocking_bad_client_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(head_of_line_blocking_bad_client_test ${_gRPC_SSL_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} bad_client_test grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(headers_bad_client_test test/core/bad_client/tests/headers.c ) target_include_directories(headers_bad_client_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(headers_bad_client_test ${_gRPC_SSL_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} bad_client_test grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(initial_settings_frame_bad_client_test test/core/bad_client/tests/initial_settings_frame.c ) target_include_directories(initial_settings_frame_bad_client_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(initial_settings_frame_bad_client_test ${_gRPC_SSL_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} bad_client_test grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(large_metadata_bad_client_test test/core/bad_client/tests/large_metadata.c ) target_include_directories(large_metadata_bad_client_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(large_metadata_bad_client_test ${_gRPC_SSL_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} bad_client_test grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(server_registered_method_bad_client_test test/core/bad_client/tests/server_registered_method.c ) target_include_directories(server_registered_method_bad_client_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(server_registered_method_bad_client_test ${_gRPC_SSL_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} bad_client_test grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(simple_request_bad_client_test test/core/bad_client/tests/simple_request.c ) target_include_directories(simple_request_bad_client_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(simple_request_bad_client_test ${_gRPC_SSL_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} bad_client_test grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(unknown_frame_bad_client_test test/core/bad_client/tests/unknown_frame.c ) target_include_directories(unknown_frame_bad_client_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(unknown_frame_bad_client_test ${_gRPC_SSL_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} bad_client_test grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(window_overflow_bad_client_test test/core/bad_client/tests/window_overflow.c ) target_include_directories(window_overflow_bad_client_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(window_overflow_bad_client_test ${_gRPC_SSL_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} bad_client_test grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(bad_ssl_cert_server test/core/bad_ssl/servers/cert.c ) target_include_directories(bad_ssl_cert_server 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(bad_ssl_cert_server ${_gRPC_ALLTARGETS_LIBRARIES} bad_ssl_test_server grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(bad_ssl_cert_test test/core/bad_ssl/bad_ssl_test.c ) target_include_directories(bad_ssl_cert_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(bad_ssl_cert_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_census_test test/core/end2end/fixtures/h2_census.c ) target_include_directories(h2_census_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(h2_census_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_tests grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_compress_test test/core/end2end/fixtures/h2_compress.c ) target_include_directories(h2_compress_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(h2_compress_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_tests grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_fakesec_test test/core/end2end/fixtures/h2_fakesec.c ) target_include_directories(h2_fakesec_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(h2_fakesec_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_tests grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(h2_fd_test test/core/end2end/fixtures/h2_fd.c ) target_include_directories(h2_fd_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(h2_fd_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_tests grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_full_test test/core/end2end/fixtures/h2_full.c ) target_include_directories(h2_full_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(h2_full_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_tests grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX) add_executable(h2_full+pipe_test test/core/end2end/fixtures/h2_full+pipe.c ) target_include_directories(h2_full+pipe_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(h2_full+pipe_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_tests grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_full+trace_test test/core/end2end/fixtures/h2_full+trace.c ) target_include_directories(h2_full+trace_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(h2_full+trace_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_tests grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_http_proxy_test test/core/end2end/fixtures/h2_http_proxy.c ) target_include_directories(h2_http_proxy_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(h2_http_proxy_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_tests grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_load_reporting_test test/core/end2end/fixtures/h2_load_reporting.c ) target_include_directories(h2_load_reporting_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(h2_load_reporting_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_tests grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_oauth2_test test/core/end2end/fixtures/h2_oauth2.c ) target_include_directories(h2_oauth2_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(h2_oauth2_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_tests grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_proxy_test test/core/end2end/fixtures/h2_proxy.c ) target_include_directories(h2_proxy_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(h2_proxy_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_tests grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_sockpair_test test/core/end2end/fixtures/h2_sockpair.c ) target_include_directories(h2_sockpair_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(h2_sockpair_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_tests grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_sockpair+trace_test test/core/end2end/fixtures/h2_sockpair+trace.c ) target_include_directories(h2_sockpair+trace_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(h2_sockpair+trace_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_tests grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_sockpair_1byte_test test/core/end2end/fixtures/h2_sockpair_1byte.c ) target_include_directories(h2_sockpair_1byte_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(h2_sockpair_1byte_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_tests grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_ssl_test test/core/end2end/fixtures/h2_ssl.c ) target_include_directories(h2_ssl_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(h2_ssl_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_tests grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_ssl_cert_test test/core/end2end/fixtures/h2_ssl_cert.c ) target_include_directories(h2_ssl_cert_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(h2_ssl_cert_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_tests grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_ssl_proxy_test test/core/end2end/fixtures/h2_ssl_proxy.c ) target_include_directories(h2_ssl_proxy_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(h2_ssl_proxy_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_tests grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(h2_uds_test test/core/end2end/fixtures/h2_uds.c ) target_include_directories(h2_uds_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(h2_uds_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_tests grpc_test_util grpc gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_census_nosec_test test/core/end2end/fixtures/h2_census.c ) target_include_directories(h2_census_nosec_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(h2_census_nosec_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_nosec_tests grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_compress_nosec_test test/core/end2end/fixtures/h2_compress.c ) target_include_directories(h2_compress_nosec_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(h2_compress_nosec_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_nosec_tests grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(h2_fd_nosec_test test/core/end2end/fixtures/h2_fd.c ) target_include_directories(h2_fd_nosec_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(h2_fd_nosec_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_nosec_tests grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_full_nosec_test test/core/end2end/fixtures/h2_full.c ) target_include_directories(h2_full_nosec_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(h2_full_nosec_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_nosec_tests grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX) add_executable(h2_full+pipe_nosec_test test/core/end2end/fixtures/h2_full+pipe.c ) target_include_directories(h2_full+pipe_nosec_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(h2_full+pipe_nosec_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_nosec_tests grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_full+trace_nosec_test test/core/end2end/fixtures/h2_full+trace.c ) target_include_directories(h2_full+trace_nosec_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(h2_full+trace_nosec_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_nosec_tests grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_http_proxy_nosec_test test/core/end2end/fixtures/h2_http_proxy.c ) target_include_directories(h2_http_proxy_nosec_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(h2_http_proxy_nosec_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_nosec_tests grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_load_reporting_nosec_test test/core/end2end/fixtures/h2_load_reporting.c ) target_include_directories(h2_load_reporting_nosec_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(h2_load_reporting_nosec_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_nosec_tests grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_proxy_nosec_test test/core/end2end/fixtures/h2_proxy.c ) target_include_directories(h2_proxy_nosec_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(h2_proxy_nosec_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_nosec_tests grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_sockpair_nosec_test test/core/end2end/fixtures/h2_sockpair.c ) target_include_directories(h2_sockpair_nosec_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(h2_sockpair_nosec_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_nosec_tests grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_sockpair+trace_nosec_test test/core/end2end/fixtures/h2_sockpair+trace.c ) target_include_directories(h2_sockpair+trace_nosec_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(h2_sockpair+trace_nosec_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_nosec_tests grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(h2_sockpair_1byte_nosec_test test/core/end2end/fixtures/h2_sockpair_1byte.c ) target_include_directories(h2_sockpair_1byte_nosec_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(h2_sockpair_1byte_nosec_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_nosec_tests grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(h2_uds_nosec_test test/core/end2end/fixtures/h2_uds.c ) target_include_directories(h2_uds_nosec_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(h2_uds_nosec_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_nosec_tests grpc_test_util_unsecure grpc_unsecure gpr_test_util gpr ) endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(api_fuzzer_one_entry test/core/end2end/fuzzers/api_fuzzer.c test/core/util/one_corpus_entry_fuzzer.c ) target_include_directories(api_fuzzer_one_entry 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(api_fuzzer_one_entry ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(client_fuzzer_one_entry test/core/end2end/fuzzers/client_fuzzer.c test/core/util/one_corpus_entry_fuzzer.c ) target_include_directories(client_fuzzer_one_entry 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(client_fuzzer_one_entry ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(hpack_parser_fuzzer_test_one_entry test/core/transport/chttp2/hpack_parser_fuzzer_test.c test/core/util/one_corpus_entry_fuzzer.c ) target_include_directories(hpack_parser_fuzzer_test_one_entry 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(hpack_parser_fuzzer_test_one_entry ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(http_request_fuzzer_test_one_entry test/core/http/request_fuzzer.c test/core/util/one_corpus_entry_fuzzer.c ) target_include_directories(http_request_fuzzer_test_one_entry 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(http_request_fuzzer_test_one_entry ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(http_response_fuzzer_test_one_entry test/core/http/response_fuzzer.c test/core/util/one_corpus_entry_fuzzer.c ) target_include_directories(http_response_fuzzer_test_one_entry 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(http_response_fuzzer_test_one_entry ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(json_fuzzer_test_one_entry test/core/json/fuzzer.c test/core/util/one_corpus_entry_fuzzer.c ) target_include_directories(json_fuzzer_test_one_entry 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(json_fuzzer_test_one_entry ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(nanopb_fuzzer_response_test_one_entry test/core/nanopb/fuzzer_response.c test/core/util/one_corpus_entry_fuzzer.c ) target_include_directories(nanopb_fuzzer_response_test_one_entry 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(nanopb_fuzzer_response_test_one_entry ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(nanopb_fuzzer_serverlist_test_one_entry test/core/nanopb/fuzzer_serverlist.c test/core/util/one_corpus_entry_fuzzer.c ) target_include_directories(nanopb_fuzzer_serverlist_test_one_entry 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(nanopb_fuzzer_serverlist_test_one_entry ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(percent_decode_fuzzer_one_entry test/core/slice/percent_decode_fuzzer.c test/core/util/one_corpus_entry_fuzzer.c ) target_include_directories(percent_decode_fuzzer_one_entry 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(percent_decode_fuzzer_one_entry ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(percent_encode_fuzzer_one_entry test/core/slice/percent_encode_fuzzer.c test/core/util/one_corpus_entry_fuzzer.c ) target_include_directories(percent_encode_fuzzer_one_entry 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(percent_encode_fuzzer_one_entry ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(server_fuzzer_one_entry test/core/end2end/fuzzers/server_fuzzer.c test/core/util/one_corpus_entry_fuzzer.c ) target_include_directories(server_fuzzer_one_entry 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(server_fuzzer_one_entry ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(ssl_server_fuzzer_one_entry test/core/security/ssl_server_fuzzer.c test/core/util/one_corpus_entry_fuzzer.c ) target_include_directories(ssl_server_fuzzer_one_entry 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(ssl_server_fuzzer_one_entry ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) add_executable(uri_fuzzer_test_one_entry test/core/client_channel/uri_fuzzer_test.c test/core/util/one_corpus_entry_fuzzer.c ) target_include_directories(uri_fuzzer_test_one_entry 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(uri_fuzzer_test_one_entry ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc gpr_test_util gpr ) endif (gRPC_BUILD_TESTS) foreach(_config gRPCConfig gRPCConfigVersion) configure_file(tools/cmake/${_config}.cmake.in ${_config}.cmake @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${_config}.cmake DESTINATION ${CMAKE_INSTALL_CMAKEDIR} ) endforeach() grpc-1.3.2/CONTRIBUTING.md000066400000000000000000000060201310511640000146660ustar00rootroot00000000000000# How to contribute We definitely welcome patches and contribution to grpc! Here is some guideline and information about how to do so. ## Getting started ### Legal requirements In order to protect both you and ourselves, you will need to sign the [Contributor License Agreement](https://cla.developers.google.com/clas). ### Technical requirements You will need several tools to work with this repository. In addition to all of the packages described in the [INSTALL](INSTALL.md) file, you will also need python, and the mako template renderer. To install the latter, using pip, one should simply be able to do `pip install mako`. In order to run all of the tests we provide, you will need valgrind and clang. More specifically, under debian, you will need the package libc++-dev to properly run all the tests. Compiling and running grpc C++ tests depend on protobuf 3.0.0, gtest and gflags. Although gflags is provided in third_party, you will need to manually install that dependency on your system to run these tests. Under a Debian or Ubuntu system, you can install the gtests and gflags packages using apt-get: ```sh $ [sudo] apt-get install libgflags-dev libgtest-dev ``` If you are planning to work on any of the languages other than C and C++, you will also need their appropriate development environments. If you want to work under Windows, we recommend the use of Visual Studio 2013. The [Community or Express editions](http://www.visualstudio.com/en-us/downloads/download-visual-studio-vs.aspx) are free and suitable for developing with grpc. Note however that our test environment and tools are available for Unix environments only at the moment. ## Testing your changes We provide a tool to help run the suite of tests in various environments. In order to run most of the available tests, one would need to run: `./tools/run_tests/run_tests.py` If you want to run tests for any of the languages {c, c++, csharp, node, objc, php, python, ruby}, do this: `./tools/run_tests/run_tests.py -l ` To know about the list of available commands, do this: `./tools/run_tests/run_tests.py -h` If you are running tests for ObjC on osx, follow these steps before running tests: * install Xcode command-line tools by running `sudo xcode-select --install` * install macports from https://www.macports.org/install.php * install autoconf, automake, libtool, gflags, cmake using macports * restart your terminal window or run source ~/.bash_profile to pick up the new PATH changes. ## Adding or removing source code Each language uses its own build system to work. Currently, the root's Makefile and the Visual Studio project files are building only the C and C++ source code. In order to ease the maintenance of these files, we have a template system. Please do not contribute manual changes to any of the generated files. Instead, modify the template files, or the build.yaml file, and re-generate the project files using the following command: `./tools/buildgen/generate_projects.sh` You'll find more information about this in the [templates](templates) folder. grpc-1.3.2/Gemfile000077500000000000000000000001311310511640000137300ustar00rootroot00000000000000source 'https://rubygems.org' # Specify your gem's dependencies in grpc.gemspec gemspec grpc-1.3.2/INSTALL.md000066400000000000000000000066531310511640000141010ustar00rootroot00000000000000# If you are in a hurry For language-specific installation instructions for gRPC runtime, please refer to these documents * [C++](examples/cpp): Currently to install gRPC for C++, you need to build from source as described below. * [C#](src/csharp): NuGet package `Grpc` * [Go](https://github.com/grpc/grpc-go): `go get google.golang.org/grpc` * [Java](https://github.com/grpc/grpc-java) * [Node](src/node): `npm install grpc` * [Objective-C](src/objective-c) * [PHP](src/php): `pecl install grpc` * [Python](src/python/grpcio): `pip install grpcio` * [Ruby](src/ruby): `gem install grpc` # Pre-requisites ## Linux ```sh $ [sudo] apt-get install build-essential autoconf libtool ``` If you plan to build from source and run tests, install the following as well: ```sh $ [sudo] apt-get install libgflags-dev libgtest-dev $ [sudo] apt-get install clang libc++-dev ``` ## Mac OSX For a Mac system, git is not available by default. You will first need to install Xcode from the Mac AppStore and then run the following command from a terminal: ```sh $ [sudo] xcode-select --install ``` ## Protoc By default gRPC uses [protocol buffers](https://github.com/google/protobuf), you will need the `protoc` compiler to generate stub server and client code. If you compile gRPC from source, as described below, the Makefile will automatically try and compile the `protoc` in third_party if you cloned the repository recursively and it detects that you don't already have it installed. # Build from Source For developers who are interested to contribute, here is how to compile the gRPC C Core library. ```sh $ git clone -b $(curl -L http://grpc.io/release) https://github.com/grpc/grpc $ cd grpc $ git submodule update --init $ make $ [sudo] make install ``` ## Windows There are several ways to build under Windows, of varying complexity depending on experience with the tools involved. ### Pre-generated Visual Studio solution The pre-generated VS projects & solution are checked into the repository under the [vsprojects](/vsprojects) directory. ### Building using CMake (with BoringSSL) - Install [CMake](https://cmake.org/download/). - Install [Active State Perl](http://www.activestate.com/activeperl/) (`choco install activeperl`) - Install [Ninja](https://ninja-build.org/) (`choco install ninja`) - Install [Go](https://golang.org/dl/) (`choco install golang`) - Install [yasm](http://yasm.tortall.net/) and add it to `PATH` (`choco install yasm`) - Run these commands in the repo root directory ``` > md .build > cd .build > call "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" x64 > cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release > cmake --build . ``` NOTE: Currently you can only use Ninja to build using cmake on Windows (because of the boringssl dependency). ### msys2 (with mingw) The Makefile (and source code) should support msys2's mingw32 and mingw64 compilers. Building with msys2's native compiler is also possible, but difficult. This approach requires having [msys2](https://msys2.github.io/) installed. ``` # Install prerequisites MSYS2$ pacman -S autoconf automake gcc libtool mingw-w64-x86_64-toolchain perl pkg-config zlib MSYS2$ pacman -S mingw-w64-x86_64-gflags ``` ``` # From mingw shell MINGW64$ export CPPFLAGS="-D_WIN32_WINNT=0x0600" MINGW64$ make ``` NOTE: While most of the make targets are buildable under Mingw, some haven't been ported to Windows yet and may fail to build (mostly trying to include POSIX headers not available on Mingw). grpc-1.3.2/LICENSE000066400000000000000000000027031310511640000134460ustar00rootroot00000000000000Copyright 2015, Google Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/MANIFEST.md000066400000000000000000000007631310511640000141750ustar00rootroot00000000000000# Top-level Items by language ## Bazel * [grpc.bzl](grpc.bzl) ## Node * [binding.gyp](binding.gyp) * [package.json](package.json) ## Objective-C * [gRPC.podspec](gRPC.podspec) ## PHP * [composer.json](composer.json) * [config.m4](config.m4) * [package.xml](package.xml) ## Python * [requirements.txt](requirements.txt) * [setup.cfg](setup.cfg) * [setup.py](setup.py) * [PYTHON-MANIFEST.in](PYTHON-MANIFEST.in) ## Ruby * [Gemfile](Gemfile) * [grpc.gemspec](grpc.gemspec) * [Rakefile](Rakefile) grpc-1.3.2/Makefile000066400000000000000000032164021310511640000141070ustar00rootroot00000000000000# GRPC global makefile # This currently builds C and C++ code. # This file has been automatically generated from a template file. # Please look at the templates directory instead. # This file can be regenerated from the template by running # tools/buildgen/generate_projects.sh # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. comma := , # Basic platform detection HOST_SYSTEM = $(shell uname | cut -f 1 -d_) SYSTEM ?= $(HOST_SYSTEM) ifeq ($(SYSTEM),MSYS) SYSTEM = MINGW32 endif ifeq ($(SYSTEM),MINGW64) SYSTEM = MINGW32 endif MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) ifndef BUILDDIR BUILDDIR_ABSOLUTE = $(patsubst %/,%,$(dir $(MAKEFILE_PATH))) else BUILDDIR_ABSOLUTE = $(abspath $(BUILDDIR)) endif HAS_GCC = $(shell which gcc > /dev/null 2> /dev/null && echo true || echo false) HAS_CC = $(shell which cc > /dev/null 2> /dev/null && echo true || echo false) HAS_CLANG = $(shell which clang > /dev/null 2> /dev/null && echo true || echo false) ifeq ($(HAS_CC),true) DEFAULT_CC = cc DEFAULT_CXX = c++ else ifeq ($(HAS_GCC),true) DEFAULT_CC = gcc DEFAULT_CXX = g++ else ifeq ($(HAS_CLANG),true) DEFAULT_CC = clang DEFAULT_CXX = clang++ else DEFAULT_CC = no_c_compiler DEFAULT_CXX = no_c++_compiler endif endif endif BINDIR = $(BUILDDIR_ABSOLUTE)/bins OBJDIR = $(BUILDDIR_ABSOLUTE)/objs LIBDIR = $(BUILDDIR_ABSOLUTE)/libs GENDIR = $(BUILDDIR_ABSOLUTE)/gens # Configurations VALID_CONFIG_opt = 1 CC_opt = $(DEFAULT_CC) CXX_opt = $(DEFAULT_CXX) LD_opt = $(DEFAULT_CC) LDXX_opt = $(DEFAULT_CXX) CPPFLAGS_opt = -O2 DEFINES_opt = NDEBUG VALID_CONFIG_asan-trace-cmp = 1 REQUIRE_CUSTOM_LIBRARIES_asan-trace-cmp = 1 CC_asan-trace-cmp = clang CXX_asan-trace-cmp = clang++ LD_asan-trace-cmp = clang LDXX_asan-trace-cmp = clang++ CPPFLAGS_asan-trace-cmp = -O0 -fsanitize-coverage=edge -fsanitize-coverage=trace-cmp -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS LDFLAGS_asan-trace-cmp = -fsanitize=address VALID_CONFIG_dbg = 1 CC_dbg = $(DEFAULT_CC) CXX_dbg = $(DEFAULT_CXX) LD_dbg = $(DEFAULT_CC) LDXX_dbg = $(DEFAULT_CXX) CPPFLAGS_dbg = -O0 DEFINES_dbg = _DEBUG DEBUG VALID_CONFIG_asan = 1 REQUIRE_CUSTOM_LIBRARIES_asan = 1 CC_asan = clang CXX_asan = clang++ LD_asan = clang LDXX_asan = clang++ CPPFLAGS_asan = -O0 -fsanitize-coverage=edge -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS LDFLAGS_asan = -fsanitize=address VALID_CONFIG_msan = 1 REQUIRE_CUSTOM_LIBRARIES_msan = 1 CC_msan = clang CXX_msan = clang++ LD_msan = clang LDXX_msan = clang++ CPPFLAGS_msan = -O0 -fsanitize-coverage=edge -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1 -Wno-unused-command-line-argument -fPIE -pie -DGPR_NO_DIRECT_SYSCALLS LDFLAGS_msan = -fsanitize=memory -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1 -fPIE -pie $(if $(JENKINS_BUILD),-Wl$(comma)-Ttext-segment=0x7e0000000000,) DEFINES_msan = NDEBUG VALID_CONFIG_basicprof = 1 CC_basicprof = $(DEFAULT_CC) CXX_basicprof = $(DEFAULT_CXX) LD_basicprof = $(DEFAULT_CC) LDXX_basicprof = $(DEFAULT_CXX) CPPFLAGS_basicprof = -O2 -DGRPC_BASIC_PROFILER -DGRPC_TIMERS_RDTSC DEFINES_basicprof = NDEBUG VALID_CONFIG_helgrind = 1 CC_helgrind = $(DEFAULT_CC) CXX_helgrind = $(DEFAULT_CXX) LD_helgrind = $(DEFAULT_CC) LDXX_helgrind = $(DEFAULT_CXX) CPPFLAGS_helgrind = -O0 LDFLAGS_helgrind = -rdynamic DEFINES_helgrind = _DEBUG DEBUG VALID_CONFIG_asan-noleaks = 1 REQUIRE_CUSTOM_LIBRARIES_asan-noleaks = 1 CC_asan-noleaks = clang CXX_asan-noleaks = clang++ LD_asan-noleaks = clang LDXX_asan-noleaks = clang++ CPPFLAGS_asan-noleaks = -O0 -fsanitize-coverage=edge -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS LDFLAGS_asan-noleaks = -fsanitize=address VALID_CONFIG_ubsan = 1 REQUIRE_CUSTOM_LIBRARIES_ubsan = 1 CC_ubsan = clang CXX_ubsan = clang++ LD_ubsan = clang LDXX_ubsan = clang++ CPPFLAGS_ubsan = -O0 -fsanitize-coverage=edge -fsanitize=undefined -fno-omit-frame-pointer -Wno-unused-command-line-argument -Wvarargs LDFLAGS_ubsan = -fsanitize=undefined,unsigned-integer-overflow DEFINES_ubsan = NDEBUG VALID_CONFIG_tsan = 1 REQUIRE_CUSTOM_LIBRARIES_tsan = 1 CC_tsan = clang CXX_tsan = clang++ LD_tsan = clang LDXX_tsan = clang++ CPPFLAGS_tsan = -O0 -fsanitize=thread -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS LDFLAGS_tsan = -fsanitize=thread DEFINES_tsan = GRPC_TSAN VALID_CONFIG_stapprof = 1 CC_stapprof = $(DEFAULT_CC) CXX_stapprof = $(DEFAULT_CXX) LD_stapprof = $(DEFAULT_CC) LDXX_stapprof = $(DEFAULT_CXX) CPPFLAGS_stapprof = -O2 -DGRPC_STAP_PROFILER DEFINES_stapprof = NDEBUG VALID_CONFIG_gcov = 1 CC_gcov = gcc CXX_gcov = g++ LD_gcov = gcc LDXX_gcov = g++ CPPFLAGS_gcov = -O0 -fprofile-arcs -ftest-coverage -Wno-return-type LDFLAGS_gcov = -fprofile-arcs -ftest-coverage -rdynamic DEFINES_gcov = _DEBUG DEBUG GPR_GCOV VALID_CONFIG_memcheck = 1 CC_memcheck = $(DEFAULT_CC) CXX_memcheck = $(DEFAULT_CXX) LD_memcheck = $(DEFAULT_CC) LDXX_memcheck = $(DEFAULT_CXX) CPPFLAGS_memcheck = -O0 LDFLAGS_memcheck = -rdynamic DEFINES_memcheck = _DEBUG DEBUG VALID_CONFIG_lto = 1 CC_lto = $(DEFAULT_CC) CXX_lto = $(DEFAULT_CXX) LD_lto = $(DEFAULT_CC) LDXX_lto = $(DEFAULT_CXX) CPPFLAGS_lto = -O2 DEFINES_lto = NDEBUG VALID_CONFIG_mutrace = 1 CC_mutrace = $(DEFAULT_CC) CXX_mutrace = $(DEFAULT_CXX) LD_mutrace = $(DEFAULT_CC) LDXX_mutrace = $(DEFAULT_CXX) CPPFLAGS_mutrace = -O3 -fno-omit-frame-pointer LDFLAGS_mutrace = -rdynamic DEFINES_mutrace = NDEBUG VALID_CONFIG_counters = 1 CC_counters = $(DEFAULT_CC) CXX_counters = $(DEFAULT_CXX) LD_counters = $(DEFAULT_CC) LDXX_counters = $(DEFAULT_CXX) CPPFLAGS_counters = -O2 -DGPR_LOW_LEVEL_COUNTERS DEFINES_counters = NDEBUG # General settings. # You may want to change these depending on your system. prefix ?= /usr/local PROTOC ?= protoc DTRACE ?= dtrace CONFIG ?= opt # Doing X ?= Y is the same as: # ifeq ($(origin X), undefined) # X = Y # endif # but some variables, such as CC, CXX, LD or AR, have defaults. # So instead of using ?= on them, we need to check their origin. # See: # https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html # https://www.gnu.org/software/make/manual/html_node/Flavors.html#index-_003f_003d # https://www.gnu.org/software/make/manual/html_node/Origin-Function.html ifeq ($(origin CC), default) CC = $(CC_$(CONFIG)) endif ifeq ($(origin CXX), default) CXX = $(CXX_$(CONFIG)) endif ifeq ($(origin LD), default) LD = $(LD_$(CONFIG)) endif LDXX ?= $(LDXX_$(CONFIG)) ifeq ($(SYSTEM),Linux) ifeq ($(origin AR), default) AR = ar rcs endif STRIP ?= strip --strip-unneeded else ifeq ($(SYSTEM),Darwin) ifeq ($(origin AR), default) AR = libtool -no_warning_for_no_symbols -o endif STRIP ?= strip -x else ifeq ($(SYSTEM),MINGW32) ifeq ($(origin AR), default) AR = ar rcs endif STRIP ?= strip --strip-unneeded else ifeq ($(origin AR), default) AR = ar rcs endif STRIP ?= strip endif endif endif INSTALL ?= install RM ?= rm -f PKG_CONFIG ?= pkg-config ifndef VALID_CONFIG_$(CONFIG) $(error Invalid CONFIG value '$(CONFIG)') endif ifeq ($(SYSTEM),Linux) TMPOUT = /dev/null else TMPOUT = `mktemp /tmp/test-out-XXXXXX` endif # Detect if we can use C++11 CXX11_CHECK_CMD = $(CXX) -std=c++11 -o $(TMPOUT) -c test/build/c++11.cc HAS_CXX11 = $(shell $(CXX11_CHECK_CMD) 2> /dev/null && echo true || echo false) CHECK_SHADOW_WORKS_CMD = $(CC) -std=c99 -Werror -Wshadow -o $(TMPOUT) -c test/build/shadow.c HAS_WORKING_SHADOW = $(shell $(CHECK_SHADOW_WORKS_CMD) 2> /dev/null && echo true || echo false) ifeq ($(HAS_WORKING_SHADOW),true) W_SHADOW=-Wshadow NO_W_SHADOW=-Wno-shadow endif CHECK_EXTRA_SEMI_WORKS_CMD = $(CC) -std=c99 -Werror -Wextra-semi -o $(TMPOUT) -c test/build/extra-semi.c HAS_WORKING_EXTRA_SEMI = $(shell $(CHECK_EXTRA_SEMI_WORKS_CMD) 2> /dev/null && echo true || echo false) ifeq ($(HAS_WORKING_EXTRA_SEMI),true) W_EXTRA_SEMI=-Wextra-semi NO_W_EXTRA_SEMI=-Wno-extra-semi endif CHECK_NO_SHIFT_NEGATIVE_VALUE_WORKS_CMD = $(CC) -std=c99 -Werror -Wno-shift-negative-value -o $(TMPOUT) -c test/build/no-shift-negative-value.c HAS_WORKING_NO_SHIFT_NEGATIVE_VALUE = $(shell $(CHECK_NO_SHIFT_NEGATIVE_VALUE_WORKS_CMD) 2> /dev/null && echo true || echo false) ifeq ($(HAS_WORKING_NO_SHIFT_NEGATIVE_VALUE),true) W_NO_SHIFT_NEGATIVE_VALUE=-Wno-shift-negative-value NO_W_NO_SHIFT_NEGATIVE_VALUE=-Wshift-negative-value endif # The HOST compiler settings are used to compile the protoc plugins. # In most cases, you won't have to change anything, but if you are # cross-compiling, you can override these variables from GNU make's # command line: make CC=cross-gcc HOST_CC=gcc HOST_CC ?= $(CC) HOST_CXX ?= $(CXX) HOST_LD ?= $(LD) HOST_LDXX ?= $(LDXX) CFLAGS += -std=c99 -Wsign-conversion -Wconversion $(W_SHADOW) $(W_EXTRA_SEMI) ifeq ($(HAS_CXX11),true) CXXFLAGS += -std=c++11 else CXXFLAGS += -std=c++0x endif CPPFLAGS += -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter -DOSATOMIC_USE_INLINED=1 LDFLAGS += -g CPPFLAGS += $(CPPFLAGS_$(CONFIG)) CFLAGS += $(CFLAGS_$(CONFIG)) CXXFLAGS += $(CXXFLAGS_$(CONFIG)) DEFINES += $(DEFINES_$(CONFIG)) INSTALL_PREFIX=\"$(prefix)\" LDFLAGS += $(LDFLAGS_$(CONFIG)) ifneq ($(SYSTEM),MINGW32) PIC_CPPFLAGS = -fPIC CPPFLAGS += -fPIC LDFLAGS += -fPIC endif INCLUDES = . include $(GENDIR) LDFLAGS += -Llibs/$(CONFIG) ifeq ($(SYSTEM),Darwin) ifneq ($(wildcard /usr/local/ssl/include),) INCLUDES += /usr/local/ssl/include endif ifneq ($(wildcard /opt/local/include),) INCLUDES += /opt/local/include endif ifneq ($(wildcard /usr/local/include),) INCLUDES += /usr/local/include endif LIBS = m z ifneq ($(wildcard /usr/local/ssl/lib),) LDFLAGS += -L/usr/local/ssl/lib endif ifneq ($(wildcard /opt/local/lib),) LDFLAGS += -L/opt/local/lib endif ifneq ($(wildcard /usr/local/lib),) LDFLAGS += -L/usr/local/lib endif endif ifeq ($(SYSTEM),Linux) LIBS = dl rt m pthread LDFLAGS += -pthread endif ifeq ($(SYSTEM),MINGW32) LIBS = m pthread ws2_32 LDFLAGS += -pthread endif # # The steps for cross-compiling are as follows: # First, clone and make install of grpc using the native compilers for the host. # Also, install protoc (e.g., from a package like apt-get) # Then clone a fresh grpc for the actual cross-compiled build # Set the environment variable GRPC_CROSS_COMPILE to true # Set CC, CXX, LD, LDXX, AR, and STRIP to the cross-compiling binaries # Also set PROTOBUF_CONFIG_OPTS to indicate cross-compilation to protobuf (e.g., # PROTOBUF_CONFIG_OPTS="--host=arm-linux --with-protoc=/usr/local/bin/protoc" ) # Set HAS_PKG_CONFIG=false # To build tests, go to third_party/gflags and follow its ccmake instructions # Make sure that you enable building shared libraries and set your prefix to # something useful like /usr/local/cross # You will also need to set GRPC_CROSS_LDOPTS and GRPC_CROSS_AROPTS to hold # additional required arguments for LD and AR (examples below) # Then you can do a make from the cross-compiling fresh clone! # ifeq ($(GRPC_CROSS_COMPILE),true) LDFLAGS += $(GRPC_CROSS_LDOPTS) # e.g. -L/usr/local/lib -L/usr/local/cross/lib AROPTS = $(GRPC_CROSS_AROPTS) # e.g., rc --target=elf32-little USE_BUILT_PROTOC = false endif GTEST_LIB = -Ithird_party/googletest/googletest/include -Ithird_party/googletest/googletest third_party/googletest/googletest/src/gtest-all.cc GTEST_LIB += -lgflags ifeq ($(V),1) E = @: Q = else E = @echo Q = @ endif CORE_VERSION = 3.0.0 CPP_VERSION = 1.3.2 CSHARP_VERSION = 1.3.2 CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES)) CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS) LDFLAGS += $(ARCH_FLAGS) LDLIBS += $(addprefix -l, $(LIBS)) LDLIBSXX += $(addprefix -l, $(LIBSXX)) CFLAGS += $(EXTRA_CFLAGS) CXXFLAGS += $(EXTRA_CXXFLAGS) CPPFLAGS += $(EXTRA_CPPFLAGS) LDFLAGS += $(EXTRA_LDFLAGS) DEFINES += $(EXTRA_DEFINES) LDLIBS += $(EXTRA_LDLIBS) HOST_CPPFLAGS = $(CPPFLAGS) HOST_CFLAGS = $(CFLAGS) HOST_CXXFLAGS = $(CXXFLAGS) HOST_LDFLAGS = $(LDFLAGS) HOST_LDLIBS = $(LDLIBS) # These are automatically computed variables. # There shouldn't be any need to change anything from now on. -include cache.mk CACHE_MK = HAS_PKG_CONFIG ?= $(shell command -v $(PKG_CONFIG) >/dev/null 2>&1 && echo true || echo false) ifeq ($(HAS_PKG_CONFIG), true) CACHE_MK += HAS_PKG_CONFIG = true, endif CORE_PC_TEMPLATE = prefix=$(prefix),exec_prefix=\$${prefix},includedir=\$${prefix}/include,libdir=\$${exec_prefix}/lib,,Name: $(PC_NAME),Description: $(PC_DESCRIPTION),Version: $(CORE_VERSION),Cflags: -I\$${includedir} $(PC_CFLAGS),Requires.private: $(PC_REQUIRES_PRIVATE),Libs: -L\$${libdir} $(PC_LIB),Libs.private: $(PC_LIBS_PRIVATE) CPP_PC_TEMPLATE = prefix=$(prefix),exec_prefix=\$${prefix},includedir=\$${prefix}/include,libdir=\$${exec_prefix}/lib,,Name: $(PC_NAME),Description: $(PC_DESCRIPTION),Version: $(CPP_VERSION),Cflags: -I\$${includedir} $(PC_CFLAGS),Requires.private: $(PC_REQUIRES_PRIVATE),Libs: -L\$${libdir} $(PC_LIB),Libs.private: $(PC_LIBS_PRIVATE) CSHARP_PC_TEMPLATE = prefix=$(prefix),exec_prefix=\$${prefix},includedir=\$${prefix}/include,libdir=\$${exec_prefix}/lib,,Name: $(PC_NAME),Description: $(PC_DESCRIPTION),Version: $(CSHARP_VERSION),Cflags: -I\$${includedir} $(PC_CFLAGS),Requires.private: $(PC_REQUIRES_PRIVATE),Libs: -L\$${libdir} $(PC_LIB),Libs.private: $(PC_LIBS_PRIVATE) ifeq ($(SYSTEM),MINGW32) EXECUTABLE_SUFFIX = .exe SHARED_EXT_CORE = dll SHARED_EXT_CPP = dll SHARED_EXT_CSHARP = dll SHARED_PREFIX = SHARED_VERSION_CORE = -3 SHARED_VERSION_CPP = -1 SHARED_VERSION_CSHARP = -1 else ifeq ($(SYSTEM),Darwin) EXECUTABLE_SUFFIX = SHARED_EXT_CORE = dylib SHARED_EXT_CPP = dylib SHARED_EXT_CSHARP = dylib SHARED_PREFIX = lib SHARED_VERSION_CORE = SHARED_VERSION_CPP = SHARED_VERSION_CSHARP = else EXECUTABLE_SUFFIX = SHARED_EXT_CORE = so.$(CORE_VERSION) SHARED_EXT_CPP = so.$(CPP_VERSION) SHARED_EXT_CSHARP = so.$(CSHARP_VERSION) SHARED_PREFIX = lib SHARED_VERSION_CORE = SHARED_VERSION_CPP = SHARED_VERSION_CSHARP = endif ifeq ($(wildcard .git),) IS_GIT_FOLDER = false else IS_GIT_FOLDER = true endif ifeq ($(HAS_PKG_CONFIG),true) OPENSSL_ALPN_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.0.2 openssl OPENSSL_NPN_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.0.1 openssl ZLIB_CHECK_CMD = $(PKG_CONFIG) --exists zlib PROTOBUF_CHECK_CMD = $(PKG_CONFIG) --atleast-version=3.0.0 protobuf CARES_CHECK_CMD = $(PKG_CONFIG) --exists libcares else # HAS_PKG_CONFIG ifeq ($(SYSTEM),MINGW32) OPENSSL_LIBS = ssl32 eay32 else OPENSSL_LIBS = ssl crypto endif OPENSSL_ALPN_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/openssl-alpn.c $(addprefix -l, $(OPENSSL_LIBS)) $(LDFLAGS) OPENSSL_NPN_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/openssl-npn.c $(addprefix -l, $(OPENSSL_LIBS)) $(LDFLAGS) BORINGSSL_COMPILE_CHECK_CMD = $(CC) $(CPPFLAGS) -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) -o $(TMPOUT) test/build/boringssl.c $(LDFLAGS) ZLIB_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/zlib.c -lz $(LDFLAGS) PROTOBUF_CHECK_CMD = $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $(TMPOUT) test/build/protobuf.cc -lprotobuf $(LDFLAGS) CARES_CHECK_CMD = $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $(TMPOUT) test/build/c-ares.c -lcares $(LDFLAGS) endif # HAS_PKG_CONFIG PERFTOOLS_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/perftools.c -lprofiler $(LDFLAGS) PROTOC_CHECK_CMD = which protoc > /dev/null PROTOC_CHECK_VERSION_CMD = protoc --version | grep -q libprotoc.3 DTRACE_CHECK_CMD = which dtrace > /dev/null SYSTEMTAP_HEADERS_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/systemtap.c $(LDFLAGS) ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG) HAS_SYSTEM_PERFTOOLS ?= $(shell $(PERFTOOLS_CHECK_CMD) 2> /dev/null && echo true || echo false) ifeq ($(HAS_SYSTEM_PERFTOOLS),true) DEFINES += GRPC_HAVE_PERFTOOLS LIBS += profiler CACHE_MK += HAS_SYSTEM_PERFTOOLS = true, endif endif HAS_SYSTEM_PROTOBUF_VERIFY = $(shell $(PROTOBUF_CHECK_CMD) 2> /dev/null && echo true || echo false) ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG) HAS_SYSTEM_OPENSSL_ALPN ?= $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false) ifeq ($(HAS_SYSTEM_OPENSSL_ALPN),true) HAS_SYSTEM_OPENSSL_NPN = true CACHE_MK += HAS_SYSTEM_OPENSSL_ALPN = true, else HAS_SYSTEM_OPENSSL_NPN ?= $(shell $(OPENSSL_NPN_CHECK_CMD) 2> /dev/null && echo true || echo false) endif ifeq ($(HAS_SYSTEM_OPENSSL_NPN),true) CACHE_MK += HAS_SYSTEM_OPENSSL_NPN = true, endif HAS_SYSTEM_ZLIB ?= $(shell $(ZLIB_CHECK_CMD) 2> /dev/null && echo true || echo false) ifeq ($(HAS_SYSTEM_ZLIB),true) CACHE_MK += HAS_SYSTEM_ZLIB = true, endif HAS_SYSTEM_PROTOBUF ?= $(HAS_SYSTEM_PROTOBUF_VERIFY) ifeq ($(HAS_SYSTEM_PROTOBUF),true) CACHE_MK += HAS_SYSTEM_PROTOBUF = true, endif HAS_SYSTEM_CARES ?= $(shell $(CARES_CHECK_CMD) 2> /dev/null && echo true || echo false) ifeq ($(HAS_SYSTEM_CARES),true) CACHE_MK += HAS_SYSTEM_CARES = true, endif else # override system libraries if the config requires a custom compiled library HAS_SYSTEM_OPENSSL_ALPN = false HAS_SYSTEM_OPENSSL_NPN = false HAS_SYSTEM_ZLIB = false HAS_SYSTEM_PROTOBUF = false HAS_SYSTEM_CARES = false endif HAS_PROTOC ?= $(shell $(PROTOC_CHECK_CMD) 2> /dev/null && echo true || echo false) ifeq ($(HAS_PROTOC),true) CACHE_MK += HAS_PROTOC = true, HAS_VALID_PROTOC ?= $(shell $(PROTOC_CHECK_VERSION_CMD) 2> /dev/null && echo true || echo false) ifeq ($(HAS_VALID_PROTOC),true) CACHE_MK += HAS_VALID_PROTOC = true, endif else HAS_VALID_PROTOC = false endif # Check for Systemtap (https://sourceware.org/systemtap/), first by making sure is present # in the system and secondly by checking for the "dtrace" binary (on Linux, this is part of the Systemtap # distribution. It's part of the base system on BSD/Solaris machines). ifndef HAS_SYSTEMTAP HAS_SYSTEMTAP_HEADERS = $(shell $(SYSTEMTAP_HEADERS_CHECK_CMD) 2> /dev/null && echo true || echo false) HAS_DTRACE = $(shell $(DTRACE_CHECK_CMD) 2> /dev/null && echo true || echo false) HAS_SYSTEMTAP = false ifeq ($(HAS_SYSTEMTAP_HEADERS),true) ifeq ($(HAS_DTRACE),true) HAS_SYSTEMTAP = true endif endif endif ifeq ($(HAS_SYSTEMTAP),true) CACHE_MK += HAS_SYSTEMTAP = true, endif # Note that for testing purposes, one can do: # make HAS_EMBEDDED_OPENSSL_ALPN=false # to emulate the fact we do not have OpenSSL in the third_party folder. ifneq ($(wildcard third_party/openssl-1.0.2f/libssl.a),) HAS_EMBEDDED_OPENSSL_ALPN = third_party/openssl-1.0.2f else ifeq ($(wildcard third_party/boringssl/include/openssl/ssl.h),) HAS_EMBEDDED_OPENSSL_ALPN = false else CAN_COMPILE_EMBEDDED_OPENSSL ?= $(shell $(BORINGSSL_COMPILE_CHECK_CMD) 2> /dev/null && echo true || echo false) HAS_EMBEDDED_OPENSSL_ALPN = $(CAN_COMPILE_EMBEDDED_OPENSSL) endif ifeq ($(wildcard third_party/zlib/zlib.h),) HAS_EMBEDDED_ZLIB = false else HAS_EMBEDDED_ZLIB = true endif ifeq ($(wildcard third_party/protobuf/src/google/protobuf/descriptor.pb.h),) HAS_EMBEDDED_PROTOBUF = false ifneq ($(HAS_VALID_PROTOC),true) NO_PROTOC = true endif else HAS_EMBEDDED_PROTOBUF = true endif ifeq ($(wildcard third_party/cares/cares/ares.h),) HAS_EMBEDDED_CARES = false else HAS_EMBEDDED_CARES = true endif PC_REQUIRES_GRPC = PC_LIBS_GRPC = ifeq ($(HAS_SYSTEM_ZLIB),false) ifeq ($(HAS_EMBEDDED_ZLIB), true) EMBED_ZLIB ?= true else DEP_MISSING += zlib EMBED_ZLIB ?= broken endif else EMBED_ZLIB ?= false endif ifeq ($(EMBED_ZLIB),true) ZLIB_DEP = $(LIBDIR)/$(CONFIG)/libz.a ZLIB_MERGE_LIBS = $(LIBDIR)/$(CONFIG)/libz.a ZLIB_MERGE_OBJS = $(LIBZ_OBJS) CPPFLAGS += -Ithird_party/zlib LDFLAGS += -L$(LIBDIR)/$(CONFIG)/zlib else ifeq ($(HAS_PKG_CONFIG),true) CPPFLAGS += $(shell $(PKG_CONFIG) --cflags zlib) LDFLAGS += $(shell $(PKG_CONFIG) --libs-only-L zlib) LIBS += $(patsubst -l%,%,$(shell $(PKG_CONFIG) --libs-only-l zlib)) PC_REQUIRES_GRPC += zlib else PC_LIBS_GRPC += -lz LIBS += z endif endif CARES_PKG_CONFIG = false ifeq ($(HAS_SYSTEM_CARES),false) ifeq ($(HAS_EMBEDDED_CARES), true) EMBED_CARES ?= true else DEP_MISSING += cares EMBED_CARES ?= broken endif else EMBED_CARES ?= false endif ifeq ($(EMBED_CARES),true) CARES_DEP = $(LIBDIR)/$(CONFIG)/libares.a CARES_MERGE_OBJS = $(LIBARES_OBJS) CARES_MERGE_LIBS = $(LIBDIR)/$(CONFIG)/libares.a CPPFLAGS := -Ithird_party/cares -Ithird_party/cares/cares $(CPPFLAGS) LDFLAGS := -L$(LIBDIR)/$(CONFIG)/c-ares $(LDFLAGS) else ifeq ($(HAS_PKG_CONFIG),true) PC_REQUIRES_GRPC += libcares CPPFLAGS += $(shell $(PKG_CONFIG) --cflags libcares) LDFLAGS += $(shell $(PKG_CONFIG) --libs-only-L libcares) LIBS += $(patsubst -l%,%,$(shell $(PKG_CONFIG) --libs-only-l libcares)) else PC_LIBS_GRPC += -lcares LIBS += cares endif endif OPENSSL_PKG_CONFIG = false PC_REQUIRES_SECURE = PC_LIBS_SECURE = ifeq ($(HAS_SYSTEM_OPENSSL_ALPN),true) EMBED_OPENSSL ?= false NO_SECURE ?= false else # HAS_SYSTEM_OPENSSL_ALPN=false ifneq ($(HAS_EMBEDDED_OPENSSL_ALPN),false) EMBED_OPENSSL ?= $(HAS_EMBEDDED_OPENSSL_ALPN) NO_SECURE ?= false else # HAS_EMBEDDED_OPENSSL_ALPN=false ifeq ($(HAS_SYSTEM_OPENSSL_NPN),true) EMBED_OPENSSL ?= false NO_SECURE ?= false else NO_SECURE ?= true endif # HAS_SYSTEM_OPENSSL_NPN=true endif # HAS_EMBEDDED_OPENSSL_ALPN endif # HAS_SYSTEM_OPENSSL_ALPN OPENSSL_DEP := OPENSSL_MERGE_LIBS := ifeq ($(NO_SECURE),false) ifeq ($(EMBED_OPENSSL),true) OPENSSL_DEP += $(LIBDIR)/$(CONFIG)/libboringssl.a OPENSSL_MERGE_LIBS += $(LIBDIR)/$(CONFIG)/libboringssl.a OPENSSL_MERGE_OBJS += $(LIBBORINGSSL_OBJS) # need to prefix these to ensure overriding system libraries CPPFLAGS := -Ithird_party/boringssl/include $(CPPFLAGS) else ifneq ($(EMBED_OPENSSL),false) OPENSSL_DEP += $(EMBED_OPENSSL)/libssl.a $(EMBED_OPENSSL)/libcrypto.a OPENSSL_MERGE_LIBS += $(EMBED_OPENSSL)/libssl.a $(EMBED_OPENSSL)/libcrypto.a OPENSSL_MERGE_OBJS += $(wildcard $(EMBED_OPENSSL)/grpc_obj/*.o) # need to prefix these to ensure overriding system libraries CPPFLAGS := -I$(EMBED_OPENSSL)/include $(CPPFLAGS) else # EMBED_OPENSSL=false ifeq ($(HAS_PKG_CONFIG),true) OPENSSL_PKG_CONFIG = true PC_REQUIRES_SECURE = openssl CPPFLAGS := $(shell $(PKG_CONFIG) --cflags openssl) $(CPPFLAGS) LDFLAGS_OPENSSL_PKG_CONFIG = $(shell $(PKG_CONFIG) --libs-only-L openssl) ifeq ($(SYSTEM),Linux) ifneq ($(LDFLAGS_OPENSSL_PKG_CONFIG),) LDFLAGS_OPENSSL_PKG_CONFIG += $(shell $(PKG_CONFIG) --libs-only-L openssl | sed s/L/Wl,-rpath,/) endif # LDFLAGS_OPENSSL_PKG_CONFIG='' endif # System=Linux LDFLAGS := $(LDFLAGS_OPENSSL_PKG_CONFIG) $(LDFLAGS) else # HAS_PKG_CONFIG=false LIBS_SECURE = $(OPENSSL_LIBS) endif # HAS_PKG_CONFIG ifeq ($(HAS_SYSTEM_OPENSSL_NPN),true) CPPFLAGS += -DTSI_OPENSSL_ALPN_SUPPORT=0 LIBS_SECURE = $(OPENSSL_LIBS) endif # HAS_SYSTEM_OPENSSL_NPN PC_LIBS_SECURE = $(addprefix -l, $(LIBS_SECURE)) endif # EMBED_OPENSSL endif # NO_SECURE ifeq ($(OPENSSL_PKG_CONFIG),true) LDLIBS_SECURE += $(shell $(PKG_CONFIG) --libs-only-l openssl) else LDLIBS_SECURE += $(addprefix -l, $(LIBS_SECURE)) endif # grpc .pc file PC_NAME = gRPC PC_DESCRIPTION = high performance general RPC framework PC_CFLAGS = PC_REQUIRES_PRIVATE = $(PC_REQUIRES_GRPC) $(PC_REQUIRES_SECURE) PC_LIBS_PRIVATE = $(PC_LIBS_GRPC) $(PC_LIBS_SECURE) PC_LIB = -lgrpc GRPC_PC_FILE := $(CORE_PC_TEMPLATE) # grpc_unsecure .pc file PC_NAME = gRPC unsecure PC_DESCRIPTION = high performance general RPC framework without SSL PC_CFLAGS = PC_REQUIRES_PRIVATE = $(PC_REQUIRES_GRPC) PC_LIBS_PRIVATE = $(PC_LIBS_GRPC) PC_LIB = -lgrpc GRPC_UNSECURE_PC_FILE := $(CORE_PC_TEMPLATE) PROTOBUF_PKG_CONFIG = false PC_REQUIRES_GRPCXX = PC_LIBS_GRPCXX = CPPFLAGS := -Ithird_party/googletest/googletest/include $(CPPFLAGS) PROTOC_PLUGINS_ALL = $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(BINDIR)/$(CONFIG)/grpc_csharp_plugin $(BINDIR)/$(CONFIG)/grpc_node_plugin $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin $(BINDIR)/$(CONFIG)/grpc_php_plugin $(BINDIR)/$(CONFIG)/grpc_python_plugin $(BINDIR)/$(CONFIG)/grpc_ruby_plugin PROTOC_PLUGINS_DIR = $(BINDIR)/$(CONFIG) ifeq ($(HAS_SYSTEM_PROTOBUF),true) ifeq ($(HAS_PKG_CONFIG),true) PROTOBUF_PKG_CONFIG = true PC_REQUIRES_GRPCXX = protobuf CPPFLAGS := $(shell $(PKG_CONFIG) --cflags protobuf) $(CPPFLAGS) LDFLAGS_PROTOBUF_PKG_CONFIG = $(shell $(PKG_CONFIG) --libs-only-L protobuf) ifeq ($(SYSTEM),Linux) ifneq ($(LDFLAGS_PROTOBUF_PKG_CONFIG),) LDFLAGS_PROTOBUF_PKG_CONFIG += $(shell $(PKG_CONFIG) --libs-only-L protobuf | sed s/L/Wl,-rpath,/) endif endif else PC_LIBS_GRPCXX = -lprotobuf endif PROTOC_PLUGINS = $(PROTOC_PLUGINS_ALL) else ifeq ($(HAS_EMBEDDED_PROTOBUF),true) PROTOBUF_DEP = $(LIBDIR)/$(CONFIG)/protobuf/libprotobuf.a CPPFLAGS := -Ithird_party/protobuf/src $(CPPFLAGS) LDFLAGS := -L$(LIBDIR)/$(CONFIG)/protobuf $(LDFLAGS) ifneq ($(USE_BUILT_PROTOC),false) PROTOC = $(BINDIR)/$(CONFIG)/protobuf/protoc PROTOC_PLUGINS = $(PROTOC_PLUGINS_ALL) else PROTOC_PLUGINS = PROTOC_PLUGINS_DIR = $(prefix)/bin endif else NO_PROTOBUF = true endif endif LIBS_PROTOBUF = protobuf LIBS_PROTOC = protoc protobuf HOST_LDLIBS_PROTOC += $(addprefix -l, $(LIBS_PROTOC)) ifeq ($(PROTOBUF_PKG_CONFIG),true) LDLIBS_PROTOBUF += $(shell $(PKG_CONFIG) --libs-only-l protobuf) else LDLIBS_PROTOBUF += $(addprefix -l, $(LIBS_PROTOBUF)) endif # grpc++ .pc file PC_NAME = gRPC++ PC_DESCRIPTION = C++ wrapper for gRPC PC_CFLAGS = PC_REQUIRES_PRIVATE = grpc $(PC_REQUIRES_GRPCXX) PC_LIBS_PRIVATE = $(PC_LIBS_GRPCXX) PC_LIB = -lgrpc++ GRPCXX_PC_FILE := $(CPP_PC_TEMPLATE) # grpc++_unsecure .pc file PC_NAME = gRPC++ unsecure PC_DESCRIPTION = C++ wrapper for gRPC without SSL PC_CFLAGS = PC_REQUIRES_PRIVATE = grpc_unsecure $(PC_REQUIRES_GRPCXX) PC_LIBS_PRIVATE = $(PC_LIBS_GRPCXX) PC_LIB = -lgrpc++ GRPCXX_UNSECURE_PC_FILE := $(CPP_PC_TEMPLATE) ifeq ($(MAKECMDGOALS),clean) NO_DEPS = true endif .SECONDARY = %.pb.h %.pb.cc ifeq ($(DEP_MISSING),) all: static shared plugins dep_error: @echo "You shouldn't see this message - all of your dependencies are correct." else all: dep_error git_update stop dep_error: @echo @echo "DEPENDENCY ERROR" @echo @echo "You are missing system dependencies that are essential to build grpc," @echo "and the third_party directory doesn't have them:" @echo @echo " $(DEP_MISSING)" @echo @echo "Installing the development packages for your system will solve" @echo "this issue. Please consult INSTALL to get more information." @echo @echo "If you need information about why these tests failed, run:" @echo @echo " make run_dep_checks" @echo endif git_update: ifeq ($(IS_GIT_FOLDER),true) @echo "Additionally, since you are in a git clone, you can download the" @echo "missing dependencies in third_party by running the following command:" @echo @echo " git submodule update --init" @echo endif openssl_dep_error: openssl_dep_message git_update stop protobuf_dep_error: protobuf_dep_message git_update stop protoc_dep_error: protoc_dep_message git_update stop openssl_dep_message: @echo @echo "DEPENDENCY ERROR" @echo @echo "The target you are trying to run requires an OpenSSL implementation." @echo "Your system doesn't have one, and either the third_party directory" @echo "doesn't have it, or your compiler can't build BoringSSL." @echo @echo "Please consult INSTALL to get more information." @echo @echo "If you need information about why these tests failed, run:" @echo @echo " make run_dep_checks" @echo protobuf_dep_message: @echo @echo "DEPENDENCY ERROR" @echo @echo "The target you are trying to run requires protobuf 3.0.0+" @echo "Your system doesn't have it, and neither does the third_party directory." @echo @echo "Please consult INSTALL to get more information." @echo @echo "If you need information about why these tests failed, run:" @echo @echo " make run_dep_checks" @echo protoc_dep_message: @echo @echo "DEPENDENCY ERROR" @echo @echo "The target you are trying to run requires protobuf-compiler 3.0.0+" @echo "Your system doesn't have it, and neither does the third_party directory." @echo @echo "Please consult INSTALL to get more information." @echo @echo "If you need information about why these tests failed, run:" @echo @echo " make run_dep_checks" @echo systemtap_dep_error: @echo @echo "DEPENDENCY ERROR" @echo @echo "Under the '$(CONFIG)' configutation, the target you are trying " @echo "to build requires systemtap 2.7+ (on Linux) or dtrace (on other " @echo "platforms such as Solaris and *BSD). " @echo @echo "Please consult INSTALL to get more information." @echo stop: @false alarm_test: $(BINDIR)/$(CONFIG)/alarm_test algorithm_test: $(BINDIR)/$(CONFIG)/algorithm_test alloc_test: $(BINDIR)/$(CONFIG)/alloc_test alpn_test: $(BINDIR)/$(CONFIG)/alpn_test api_fuzzer: $(BINDIR)/$(CONFIG)/api_fuzzer arena_test: $(BINDIR)/$(CONFIG)/arena_test bad_server_response_test: $(BINDIR)/$(CONFIG)/bad_server_response_test bdp_estimator_test: $(BINDIR)/$(CONFIG)/bdp_estimator_test bin_decoder_test: $(BINDIR)/$(CONFIG)/bin_decoder_test bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test census_context_test: $(BINDIR)/$(CONFIG)/census_context_test census_resource_test: $(BINDIR)/$(CONFIG)/census_resource_test census_trace_context_test: $(BINDIR)/$(CONFIG)/census_trace_context_test channel_create_test: $(BINDIR)/$(CONFIG)/channel_create_test chttp2_hpack_encoder_test: $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test chttp2_stream_map_test: $(BINDIR)/$(CONFIG)/chttp2_stream_map_test chttp2_varint_test: $(BINDIR)/$(CONFIG)/chttp2_varint_test client_fuzzer: $(BINDIR)/$(CONFIG)/client_fuzzer combiner_test: $(BINDIR)/$(CONFIG)/combiner_test compression_test: $(BINDIR)/$(CONFIG)/compression_test concurrent_connectivity_test: $(BINDIR)/$(CONFIG)/concurrent_connectivity_test connection_refused_test: $(BINDIR)/$(CONFIG)/connection_refused_test dns_resolver_connectivity_test: $(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test dns_resolver_test: $(BINDIR)/$(CONFIG)/dns_resolver_test dualstack_socket_test: $(BINDIR)/$(CONFIG)/dualstack_socket_test endpoint_pair_test: $(BINDIR)/$(CONFIG)/endpoint_pair_test error_test: $(BINDIR)/$(CONFIG)/error_test ev_epoll_linux_test: $(BINDIR)/$(CONFIG)/ev_epoll_linux_test fd_conservation_posix_test: $(BINDIR)/$(CONFIG)/fd_conservation_posix_test fd_posix_test: $(BINDIR)/$(CONFIG)/fd_posix_test fling_client: $(BINDIR)/$(CONFIG)/fling_client fling_server: $(BINDIR)/$(CONFIG)/fling_server fling_stream_test: $(BINDIR)/$(CONFIG)/fling_stream_test fling_test: $(BINDIR)/$(CONFIG)/fling_test gen_hpack_tables: $(BINDIR)/$(CONFIG)/gen_hpack_tables gen_legal_metadata_characters: $(BINDIR)/$(CONFIG)/gen_legal_metadata_characters gen_percent_encoding_tables: $(BINDIR)/$(CONFIG)/gen_percent_encoding_tables goaway_server_test: $(BINDIR)/$(CONFIG)/goaway_server_test gpr_avl_test: $(BINDIR)/$(CONFIG)/gpr_avl_test gpr_backoff_test: $(BINDIR)/$(CONFIG)/gpr_backoff_test gpr_cmdline_test: $(BINDIR)/$(CONFIG)/gpr_cmdline_test gpr_cpu_test: $(BINDIR)/$(CONFIG)/gpr_cpu_test gpr_env_test: $(BINDIR)/$(CONFIG)/gpr_env_test gpr_histogram_test: $(BINDIR)/$(CONFIG)/gpr_histogram_test gpr_host_port_test: $(BINDIR)/$(CONFIG)/gpr_host_port_test gpr_log_test: $(BINDIR)/$(CONFIG)/gpr_log_test gpr_mpscq_test: $(BINDIR)/$(CONFIG)/gpr_mpscq_test gpr_spinlock_test: $(BINDIR)/$(CONFIG)/gpr_spinlock_test gpr_stack_lockfree_test: $(BINDIR)/$(CONFIG)/gpr_stack_lockfree_test gpr_string_test: $(BINDIR)/$(CONFIG)/gpr_string_test gpr_sync_test: $(BINDIR)/$(CONFIG)/gpr_sync_test gpr_thd_test: $(BINDIR)/$(CONFIG)/gpr_thd_test gpr_time_test: $(BINDIR)/$(CONFIG)/gpr_time_test gpr_tls_test: $(BINDIR)/$(CONFIG)/gpr_tls_test gpr_useful_test: $(BINDIR)/$(CONFIG)/gpr_useful_test grpc_auth_context_test: $(BINDIR)/$(CONFIG)/grpc_auth_context_test grpc_b64_test: $(BINDIR)/$(CONFIG)/grpc_b64_test grpc_byte_buffer_reader_test: $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test grpc_channel_args_test: $(BINDIR)/$(CONFIG)/grpc_channel_args_test grpc_channel_stack_test: $(BINDIR)/$(CONFIG)/grpc_channel_stack_test grpc_completion_queue_test: $(BINDIR)/$(CONFIG)/grpc_completion_queue_test grpc_completion_queue_threading_test: $(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test grpc_create_jwt: $(BINDIR)/$(CONFIG)/grpc_create_jwt grpc_credentials_test: $(BINDIR)/$(CONFIG)/grpc_credentials_test grpc_fetch_oauth2: $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 grpc_invalid_channel_args_test: $(BINDIR)/$(CONFIG)/grpc_invalid_channel_args_test grpc_json_token_test: $(BINDIR)/$(CONFIG)/grpc_json_token_test grpc_jwt_verifier_test: $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test grpc_print_google_default_creds_token: $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token grpc_security_connector_test: $(BINDIR)/$(CONFIG)/grpc_security_connector_test grpc_verify_jwt: $(BINDIR)/$(CONFIG)/grpc_verify_jwt handshake_client: $(BINDIR)/$(CONFIG)/handshake_client handshake_server: $(BINDIR)/$(CONFIG)/handshake_server hpack_parser_fuzzer_test: $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test hpack_parser_test: $(BINDIR)/$(CONFIG)/hpack_parser_test hpack_table_test: $(BINDIR)/$(CONFIG)/hpack_table_test http_parser_test: $(BINDIR)/$(CONFIG)/http_parser_test http_request_fuzzer_test: $(BINDIR)/$(CONFIG)/http_request_fuzzer_test http_response_fuzzer_test: $(BINDIR)/$(CONFIG)/http_response_fuzzer_test httpcli_format_request_test: $(BINDIR)/$(CONFIG)/httpcli_format_request_test httpcli_test: $(BINDIR)/$(CONFIG)/httpcli_test httpscli_test: $(BINDIR)/$(CONFIG)/httpscli_test init_test: $(BINDIR)/$(CONFIG)/init_test invalid_call_argument_test: $(BINDIR)/$(CONFIG)/invalid_call_argument_test json_fuzzer_test: $(BINDIR)/$(CONFIG)/json_fuzzer_test json_rewrite: $(BINDIR)/$(CONFIG)/json_rewrite json_rewrite_test: $(BINDIR)/$(CONFIG)/json_rewrite_test json_stream_error_test: $(BINDIR)/$(CONFIG)/json_stream_error_test json_test: $(BINDIR)/$(CONFIG)/json_test lame_client_test: $(BINDIR)/$(CONFIG)/lame_client_test lb_policies_test: $(BINDIR)/$(CONFIG)/lb_policies_test load_file_test: $(BINDIR)/$(CONFIG)/load_file_test low_level_ping_pong_benchmark: $(BINDIR)/$(CONFIG)/low_level_ping_pong_benchmark memory_profile_client: $(BINDIR)/$(CONFIG)/memory_profile_client memory_profile_server: $(BINDIR)/$(CONFIG)/memory_profile_server memory_profile_test: $(BINDIR)/$(CONFIG)/memory_profile_test message_compress_test: $(BINDIR)/$(CONFIG)/message_compress_test mlog_test: $(BINDIR)/$(CONFIG)/mlog_test multiple_server_queues_test: $(BINDIR)/$(CONFIG)/multiple_server_queues_test murmur_hash_test: $(BINDIR)/$(CONFIG)/murmur_hash_test nanopb_fuzzer_response_test: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test nanopb_fuzzer_serverlist_test: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test no_server_test: $(BINDIR)/$(CONFIG)/no_server_test parse_address_test: $(BINDIR)/$(CONFIG)/parse_address_test percent_decode_fuzzer: $(BINDIR)/$(CONFIG)/percent_decode_fuzzer percent_encode_fuzzer: $(BINDIR)/$(CONFIG)/percent_encode_fuzzer percent_encoding_test: $(BINDIR)/$(CONFIG)/percent_encoding_test pollset_set_test: $(BINDIR)/$(CONFIG)/pollset_set_test resolve_address_posix_test: $(BINDIR)/$(CONFIG)/resolve_address_posix_test resolve_address_test: $(BINDIR)/$(CONFIG)/resolve_address_test resource_quota_test: $(BINDIR)/$(CONFIG)/resource_quota_test secure_channel_create_test: $(BINDIR)/$(CONFIG)/secure_channel_create_test secure_endpoint_test: $(BINDIR)/$(CONFIG)/secure_endpoint_test sequential_connectivity_test: $(BINDIR)/$(CONFIG)/sequential_connectivity_test server_chttp2_test: $(BINDIR)/$(CONFIG)/server_chttp2_test server_fuzzer: $(BINDIR)/$(CONFIG)/server_fuzzer server_test: $(BINDIR)/$(CONFIG)/server_test slice_buffer_test: $(BINDIR)/$(CONFIG)/slice_buffer_test slice_string_helpers_test: $(BINDIR)/$(CONFIG)/slice_string_helpers_test slice_test: $(BINDIR)/$(CONFIG)/slice_test sockaddr_resolver_test: $(BINDIR)/$(CONFIG)/sockaddr_resolver_test sockaddr_utils_test: $(BINDIR)/$(CONFIG)/sockaddr_utils_test socket_utils_test: $(BINDIR)/$(CONFIG)/socket_utils_test ssl_server_fuzzer: $(BINDIR)/$(CONFIG)/ssl_server_fuzzer status_conversion_test: $(BINDIR)/$(CONFIG)/status_conversion_test stream_owned_slice_test: $(BINDIR)/$(CONFIG)/stream_owned_slice_test tcp_client_posix_test: $(BINDIR)/$(CONFIG)/tcp_client_posix_test tcp_client_uv_test: $(BINDIR)/$(CONFIG)/tcp_client_uv_test tcp_posix_test: $(BINDIR)/$(CONFIG)/tcp_posix_test tcp_server_posix_test: $(BINDIR)/$(CONFIG)/tcp_server_posix_test tcp_server_uv_test: $(BINDIR)/$(CONFIG)/tcp_server_uv_test time_averaged_stats_test: $(BINDIR)/$(CONFIG)/time_averaged_stats_test timeout_encoding_test: $(BINDIR)/$(CONFIG)/timeout_encoding_test timer_heap_test: $(BINDIR)/$(CONFIG)/timer_heap_test timer_list_test: $(BINDIR)/$(CONFIG)/timer_list_test transport_connectivity_state_test: $(BINDIR)/$(CONFIG)/transport_connectivity_state_test transport_metadata_test: $(BINDIR)/$(CONFIG)/transport_metadata_test transport_pid_controller_test: $(BINDIR)/$(CONFIG)/transport_pid_controller_test transport_security_test: $(BINDIR)/$(CONFIG)/transport_security_test udp_server_test: $(BINDIR)/$(CONFIG)/udp_server_test uri_fuzzer_test: $(BINDIR)/$(CONFIG)/uri_fuzzer_test uri_parser_test: $(BINDIR)/$(CONFIG)/uri_parser_test wakeup_fd_cv_test: $(BINDIR)/$(CONFIG)/wakeup_fd_cv_test alarm_cpp_test: $(BINDIR)/$(CONFIG)/alarm_cpp_test async_end2end_test: $(BINDIR)/$(CONFIG)/async_end2end_test auth_property_iterator_test: $(BINDIR)/$(CONFIG)/auth_property_iterator_test bm_arena: $(BINDIR)/$(CONFIG)/bm_arena bm_call_create: $(BINDIR)/$(CONFIG)/bm_call_create bm_chttp2_hpack: $(BINDIR)/$(CONFIG)/bm_chttp2_hpack bm_chttp2_transport: $(BINDIR)/$(CONFIG)/bm_chttp2_transport bm_closure: $(BINDIR)/$(CONFIG)/bm_closure bm_cq: $(BINDIR)/$(CONFIG)/bm_cq bm_cq_multiple_threads: $(BINDIR)/$(CONFIG)/bm_cq_multiple_threads bm_error: $(BINDIR)/$(CONFIG)/bm_error bm_fullstack_streaming_ping_pong: $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_ping_pong bm_fullstack_streaming_pump: $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_pump bm_fullstack_trickle: $(BINDIR)/$(CONFIG)/bm_fullstack_trickle bm_fullstack_unary_ping_pong: $(BINDIR)/$(CONFIG)/bm_fullstack_unary_ping_pong bm_metadata: $(BINDIR)/$(CONFIG)/bm_metadata bm_pollset: $(BINDIR)/$(CONFIG)/bm_pollset channel_arguments_test: $(BINDIR)/$(CONFIG)/channel_arguments_test channel_filter_test: $(BINDIR)/$(CONFIG)/channel_filter_test cli_call_test: $(BINDIR)/$(CONFIG)/cli_call_test client_crash_test: $(BINDIR)/$(CONFIG)/client_crash_test client_crash_test_server: $(BINDIR)/$(CONFIG)/client_crash_test_server codegen_test_full: $(BINDIR)/$(CONFIG)/codegen_test_full codegen_test_minimal: $(BINDIR)/$(CONFIG)/codegen_test_minimal credentials_test: $(BINDIR)/$(CONFIG)/credentials_test cxx_byte_buffer_test: $(BINDIR)/$(CONFIG)/cxx_byte_buffer_test cxx_slice_test: $(BINDIR)/$(CONFIG)/cxx_slice_test cxx_string_ref_test: $(BINDIR)/$(CONFIG)/cxx_string_ref_test cxx_time_test: $(BINDIR)/$(CONFIG)/cxx_time_test end2end_test: $(BINDIR)/$(CONFIG)/end2end_test error_details_test: $(BINDIR)/$(CONFIG)/error_details_test filter_end2end_test: $(BINDIR)/$(CONFIG)/filter_end2end_test generic_end2end_test: $(BINDIR)/$(CONFIG)/generic_end2end_test golden_file_test: $(BINDIR)/$(CONFIG)/golden_file_test grpc_cli: $(BINDIR)/$(CONFIG)/grpc_cli grpc_cpp_plugin: $(BINDIR)/$(CONFIG)/grpc_cpp_plugin grpc_csharp_plugin: $(BINDIR)/$(CONFIG)/grpc_csharp_plugin grpc_node_plugin: $(BINDIR)/$(CONFIG)/grpc_node_plugin grpc_objective_c_plugin: $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin grpc_php_plugin: $(BINDIR)/$(CONFIG)/grpc_php_plugin grpc_python_plugin: $(BINDIR)/$(CONFIG)/grpc_python_plugin grpc_ruby_plugin: $(BINDIR)/$(CONFIG)/grpc_ruby_plugin grpc_tool_test: $(BINDIR)/$(CONFIG)/grpc_tool_test grpclb_api_test: $(BINDIR)/$(CONFIG)/grpclb_api_test grpclb_test: $(BINDIR)/$(CONFIG)/grpclb_test health_service_end2end_test: $(BINDIR)/$(CONFIG)/health_service_end2end_test http2_client: $(BINDIR)/$(CONFIG)/http2_client hybrid_end2end_test: $(BINDIR)/$(CONFIG)/hybrid_end2end_test interop_client: $(BINDIR)/$(CONFIG)/interop_client interop_server: $(BINDIR)/$(CONFIG)/interop_server interop_test: $(BINDIR)/$(CONFIG)/interop_test json_run_localhost: $(BINDIR)/$(CONFIG)/json_run_localhost metrics_client: $(BINDIR)/$(CONFIG)/metrics_client mock_test: $(BINDIR)/$(CONFIG)/mock_test noop-benchmark: $(BINDIR)/$(CONFIG)/noop-benchmark proto_server_reflection_test: $(BINDIR)/$(CONFIG)/proto_server_reflection_test proto_utils_test: $(BINDIR)/$(CONFIG)/proto_utils_test qps_interarrival_test: $(BINDIR)/$(CONFIG)/qps_interarrival_test qps_json_driver: $(BINDIR)/$(CONFIG)/qps_json_driver qps_openloop_test: $(BINDIR)/$(CONFIG)/qps_openloop_test qps_worker: $(BINDIR)/$(CONFIG)/qps_worker reconnect_interop_client: $(BINDIR)/$(CONFIG)/reconnect_interop_client reconnect_interop_server: $(BINDIR)/$(CONFIG)/reconnect_interop_server round_robin_end2end_test: $(BINDIR)/$(CONFIG)/round_robin_end2end_test secure_auth_context_test: $(BINDIR)/$(CONFIG)/secure_auth_context_test secure_sync_unary_ping_pong_test: $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test server_builder_plugin_test: $(BINDIR)/$(CONFIG)/server_builder_plugin_test server_builder_test: $(BINDIR)/$(CONFIG)/server_builder_test server_context_test_spouse_test: $(BINDIR)/$(CONFIG)/server_context_test_spouse_test server_crash_test: $(BINDIR)/$(CONFIG)/server_crash_test server_crash_test_client: $(BINDIR)/$(CONFIG)/server_crash_test_client shutdown_test: $(BINDIR)/$(CONFIG)/shutdown_test status_test: $(BINDIR)/$(CONFIG)/status_test streaming_throughput_test: $(BINDIR)/$(CONFIG)/streaming_throughput_test stress_test: $(BINDIR)/$(CONFIG)/stress_test thread_manager_test: $(BINDIR)/$(CONFIG)/thread_manager_test thread_stress_test: $(BINDIR)/$(CONFIG)/thread_stress_test writes_per_rpc_test: $(BINDIR)/$(CONFIG)/writes_per_rpc_test public_headers_must_be_c89: $(BINDIR)/$(CONFIG)/public_headers_must_be_c89 boringssl_aes_test: $(BINDIR)/$(CONFIG)/boringssl_aes_test boringssl_asn1_test: $(BINDIR)/$(CONFIG)/boringssl_asn1_test boringssl_base64_test: $(BINDIR)/$(CONFIG)/boringssl_base64_test boringssl_bio_test: $(BINDIR)/$(CONFIG)/boringssl_bio_test boringssl_bn_test: $(BINDIR)/$(CONFIG)/boringssl_bn_test boringssl_bytestring_test: $(BINDIR)/$(CONFIG)/boringssl_bytestring_test boringssl_chacha_test: $(BINDIR)/$(CONFIG)/boringssl_chacha_test boringssl_aead_test: $(BINDIR)/$(CONFIG)/boringssl_aead_test boringssl_cipher_test: $(BINDIR)/$(CONFIG)/boringssl_cipher_test boringssl_cmac_test: $(BINDIR)/$(CONFIG)/boringssl_cmac_test boringssl_constant_time_test: $(BINDIR)/$(CONFIG)/boringssl_constant_time_test boringssl_ed25519_test: $(BINDIR)/$(CONFIG)/boringssl_ed25519_test boringssl_spake25519_test: $(BINDIR)/$(CONFIG)/boringssl_spake25519_test boringssl_x25519_test: $(BINDIR)/$(CONFIG)/boringssl_x25519_test boringssl_dh_test: $(BINDIR)/$(CONFIG)/boringssl_dh_test boringssl_digest_test: $(BINDIR)/$(CONFIG)/boringssl_digest_test boringssl_dsa_test: $(BINDIR)/$(CONFIG)/boringssl_dsa_test boringssl_ec_test: $(BINDIR)/$(CONFIG)/boringssl_ec_test boringssl_example_mul: $(BINDIR)/$(CONFIG)/boringssl_example_mul boringssl_ecdh_test: $(BINDIR)/$(CONFIG)/boringssl_ecdh_test boringssl_ecdsa_sign_test: $(BINDIR)/$(CONFIG)/boringssl_ecdsa_sign_test boringssl_ecdsa_test: $(BINDIR)/$(CONFIG)/boringssl_ecdsa_test boringssl_ecdsa_verify_test: $(BINDIR)/$(CONFIG)/boringssl_ecdsa_verify_test boringssl_err_test: $(BINDIR)/$(CONFIG)/boringssl_err_test boringssl_evp_extra_test: $(BINDIR)/$(CONFIG)/boringssl_evp_extra_test boringssl_evp_test: $(BINDIR)/$(CONFIG)/boringssl_evp_test boringssl_pbkdf_test: $(BINDIR)/$(CONFIG)/boringssl_pbkdf_test boringssl_hkdf_test: $(BINDIR)/$(CONFIG)/boringssl_hkdf_test boringssl_hmac_test: $(BINDIR)/$(CONFIG)/boringssl_hmac_test boringssl_lhash_test: $(BINDIR)/$(CONFIG)/boringssl_lhash_test boringssl_gcm_test: $(BINDIR)/$(CONFIG)/boringssl_gcm_test boringssl_newhope_statistical_test: $(BINDIR)/$(CONFIG)/boringssl_newhope_statistical_test boringssl_newhope_test: $(BINDIR)/$(CONFIG)/boringssl_newhope_test boringssl_newhope_vectors_test: $(BINDIR)/$(CONFIG)/boringssl_newhope_vectors_test boringssl_obj_test: $(BINDIR)/$(CONFIG)/boringssl_obj_test boringssl_pkcs12_test: $(BINDIR)/$(CONFIG)/boringssl_pkcs12_test boringssl_pkcs8_test: $(BINDIR)/$(CONFIG)/boringssl_pkcs8_test boringssl_poly1305_test: $(BINDIR)/$(CONFIG)/boringssl_poly1305_test boringssl_refcount_test: $(BINDIR)/$(CONFIG)/boringssl_refcount_test boringssl_rsa_test: $(BINDIR)/$(CONFIG)/boringssl_rsa_test boringssl_thread_test: $(BINDIR)/$(CONFIG)/boringssl_thread_test boringssl_pkcs7_test: $(BINDIR)/$(CONFIG)/boringssl_pkcs7_test boringssl_x509_test: $(BINDIR)/$(CONFIG)/boringssl_x509_test boringssl_tab_test: $(BINDIR)/$(CONFIG)/boringssl_tab_test boringssl_v3name_test: $(BINDIR)/$(CONFIG)/boringssl_v3name_test boringssl_ssl_test: $(BINDIR)/$(CONFIG)/boringssl_ssl_test badreq_bad_client_test: $(BINDIR)/$(CONFIG)/badreq_bad_client_test connection_prefix_bad_client_test: $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test head_of_line_blocking_bad_client_test: $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test headers_bad_client_test: $(BINDIR)/$(CONFIG)/headers_bad_client_test initial_settings_frame_bad_client_test: $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test large_metadata_bad_client_test: $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test server_registered_method_bad_client_test: $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test simple_request_bad_client_test: $(BINDIR)/$(CONFIG)/simple_request_bad_client_test unknown_frame_bad_client_test: $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test window_overflow_bad_client_test: $(BINDIR)/$(CONFIG)/window_overflow_bad_client_test bad_ssl_cert_server: $(BINDIR)/$(CONFIG)/bad_ssl_cert_server bad_ssl_cert_test: $(BINDIR)/$(CONFIG)/bad_ssl_cert_test h2_census_test: $(BINDIR)/$(CONFIG)/h2_census_test h2_compress_test: $(BINDIR)/$(CONFIG)/h2_compress_test h2_fakesec_test: $(BINDIR)/$(CONFIG)/h2_fakesec_test h2_fd_test: $(BINDIR)/$(CONFIG)/h2_fd_test h2_full_test: $(BINDIR)/$(CONFIG)/h2_full_test h2_full+pipe_test: $(BINDIR)/$(CONFIG)/h2_full+pipe_test h2_full+trace_test: $(BINDIR)/$(CONFIG)/h2_full+trace_test h2_http_proxy_test: $(BINDIR)/$(CONFIG)/h2_http_proxy_test h2_load_reporting_test: $(BINDIR)/$(CONFIG)/h2_load_reporting_test h2_oauth2_test: $(BINDIR)/$(CONFIG)/h2_oauth2_test h2_proxy_test: $(BINDIR)/$(CONFIG)/h2_proxy_test h2_sockpair_test: $(BINDIR)/$(CONFIG)/h2_sockpair_test h2_sockpair+trace_test: $(BINDIR)/$(CONFIG)/h2_sockpair+trace_test h2_sockpair_1byte_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_test h2_ssl_test: $(BINDIR)/$(CONFIG)/h2_ssl_test h2_ssl_cert_test: $(BINDIR)/$(CONFIG)/h2_ssl_cert_test h2_ssl_proxy_test: $(BINDIR)/$(CONFIG)/h2_ssl_proxy_test h2_uds_test: $(BINDIR)/$(CONFIG)/h2_uds_test h2_census_nosec_test: $(BINDIR)/$(CONFIG)/h2_census_nosec_test h2_compress_nosec_test: $(BINDIR)/$(CONFIG)/h2_compress_nosec_test h2_fd_nosec_test: $(BINDIR)/$(CONFIG)/h2_fd_nosec_test h2_full_nosec_test: $(BINDIR)/$(CONFIG)/h2_full_nosec_test h2_full+pipe_nosec_test: $(BINDIR)/$(CONFIG)/h2_full+pipe_nosec_test h2_full+trace_nosec_test: $(BINDIR)/$(CONFIG)/h2_full+trace_nosec_test h2_http_proxy_nosec_test: $(BINDIR)/$(CONFIG)/h2_http_proxy_nosec_test h2_load_reporting_nosec_test: $(BINDIR)/$(CONFIG)/h2_load_reporting_nosec_test h2_proxy_nosec_test: $(BINDIR)/$(CONFIG)/h2_proxy_nosec_test h2_sockpair_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_nosec_test h2_sockpair+trace_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair+trace_nosec_test h2_sockpair_1byte_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_nosec_test h2_uds_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds_nosec_test api_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/api_fuzzer_one_entry client_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/client_fuzzer_one_entry hpack_parser_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry http_request_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/http_request_fuzzer_test_one_entry http_response_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/http_response_fuzzer_test_one_entry json_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/json_fuzzer_test_one_entry nanopb_fuzzer_response_test_one_entry: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test_one_entry nanopb_fuzzer_serverlist_test_one_entry: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test_one_entry percent_decode_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/percent_decode_fuzzer_one_entry percent_encode_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/percent_encode_fuzzer_one_entry server_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/server_fuzzer_one_entry ssl_server_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/ssl_server_fuzzer_one_entry uri_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/uri_fuzzer_test_one_entry run_dep_checks: $(OPENSSL_ALPN_CHECK_CMD) || true $(OPENSSL_NPN_CHECK_CMD) || true $(ZLIB_CHECK_CMD) || true $(PERFTOOLS_CHECK_CMD) || true $(PROTOBUF_CHECK_CMD) || true $(PROTOC_CHECK_VERSION_CMD) || true $(CARES_CHECK_CMD) || true third_party/protobuf/configure: $(E) "[AUTOGEN] Preparing protobuf" $(Q)(cd third_party/protobuf ; autoreconf -f -i -Wall,no-obsolete) $(LIBDIR)/$(CONFIG)/protobuf/libprotobuf.a: third_party/protobuf/configure $(E) "[MAKE] Building protobuf" $(Q)(cd third_party/protobuf ; CC="$(CC)" CXX="$(CXX)" LDFLAGS="$(LDFLAGS_$(CONFIG)) -g $(PROTOBUF_LDFLAGS_EXTRA)" CPPFLAGS="$(PIC_CPPFLAGS) $(CPPFLAGS_$(CONFIG)) -g $(PROTOBUF_CPPFLAGS_EXTRA)" ./configure --disable-shared --enable-static $(PROTOBUF_CONFIG_OPTS)) $(Q)$(MAKE) -C third_party/protobuf clean $(Q)$(MAKE) -C third_party/protobuf $(Q)mkdir -p $(LIBDIR)/$(CONFIG)/protobuf $(Q)mkdir -p $(BINDIR)/$(CONFIG)/protobuf $(Q)cp third_party/protobuf/src/.libs/libprotoc.a $(LIBDIR)/$(CONFIG)/protobuf $(Q)cp third_party/protobuf/src/.libs/libprotobuf.a $(LIBDIR)/$(CONFIG)/protobuf $(Q)cp third_party/protobuf/src/protoc $(BINDIR)/$(CONFIG)/protobuf static: static_c static_cxx static_c: pc_c pc_c_unsecure cache.mk $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc_cronet.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a static_cxx: pc_cxx pc_cxx_unsecure cache.mk $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc++_cronet.a $(LIBDIR)/$(CONFIG)/libgrpc++_error_details.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a shared: shared_c shared_cxx shared_c: pc_c pc_c_unsecure cache.mk $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) shared_cxx: pc_cxx pc_cxx_unsecure cache.mk $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) shared_csharp: shared_c $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) grpc_csharp_ext: shared_csharp plugins: $(PROTOC_PLUGINS) privatelibs: privatelibs_c privatelibs_cxx privatelibs_c: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libreconnect_server.a $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(LIBDIR)/$(CONFIG)/libz.a $(LIBDIR)/$(CONFIG)/libares.a $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libbad_ssl_test_server.a $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a pc_c: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc.pc pc_c_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc_unsecure.pc pc_cxx: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++.pc pc_cxx_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc ifeq ($(EMBED_OPENSSL),true) privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_chacha_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_spake25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_sign_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_verify_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_gcm_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_newhope_statistical_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_newhope_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_newhope_vectors_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_obj_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a $(LIBDIR)/$(CONFIG)/libbenchmark.a else privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libbenchmark.a endif buildtests: buildtests_c buildtests_cxx buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/alarm_test \ $(BINDIR)/$(CONFIG)/algorithm_test \ $(BINDIR)/$(CONFIG)/alloc_test \ $(BINDIR)/$(CONFIG)/alpn_test \ $(BINDIR)/$(CONFIG)/arena_test \ $(BINDIR)/$(CONFIG)/bad_server_response_test \ $(BINDIR)/$(CONFIG)/bdp_estimator_test \ $(BINDIR)/$(CONFIG)/bin_decoder_test \ $(BINDIR)/$(CONFIG)/bin_encoder_test \ $(BINDIR)/$(CONFIG)/census_context_test \ $(BINDIR)/$(CONFIG)/census_resource_test \ $(BINDIR)/$(CONFIG)/census_trace_context_test \ $(BINDIR)/$(CONFIG)/channel_create_test \ $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test \ $(BINDIR)/$(CONFIG)/chttp2_stream_map_test \ $(BINDIR)/$(CONFIG)/chttp2_varint_test \ $(BINDIR)/$(CONFIG)/combiner_test \ $(BINDIR)/$(CONFIG)/compression_test \ $(BINDIR)/$(CONFIG)/concurrent_connectivity_test \ $(BINDIR)/$(CONFIG)/connection_refused_test \ $(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test \ $(BINDIR)/$(CONFIG)/dns_resolver_test \ $(BINDIR)/$(CONFIG)/dualstack_socket_test \ $(BINDIR)/$(CONFIG)/endpoint_pair_test \ $(BINDIR)/$(CONFIG)/error_test \ $(BINDIR)/$(CONFIG)/ev_epoll_linux_test \ $(BINDIR)/$(CONFIG)/fd_conservation_posix_test \ $(BINDIR)/$(CONFIG)/fd_posix_test \ $(BINDIR)/$(CONFIG)/fling_client \ $(BINDIR)/$(CONFIG)/fling_server \ $(BINDIR)/$(CONFIG)/fling_stream_test \ $(BINDIR)/$(CONFIG)/fling_test \ $(BINDIR)/$(CONFIG)/goaway_server_test \ $(BINDIR)/$(CONFIG)/gpr_avl_test \ $(BINDIR)/$(CONFIG)/gpr_backoff_test \ $(BINDIR)/$(CONFIG)/gpr_cmdline_test \ $(BINDIR)/$(CONFIG)/gpr_cpu_test \ $(BINDIR)/$(CONFIG)/gpr_env_test \ $(BINDIR)/$(CONFIG)/gpr_histogram_test \ $(BINDIR)/$(CONFIG)/gpr_host_port_test \ $(BINDIR)/$(CONFIG)/gpr_log_test \ $(BINDIR)/$(CONFIG)/gpr_mpscq_test \ $(BINDIR)/$(CONFIG)/gpr_spinlock_test \ $(BINDIR)/$(CONFIG)/gpr_stack_lockfree_test \ $(BINDIR)/$(CONFIG)/gpr_string_test \ $(BINDIR)/$(CONFIG)/gpr_sync_test \ $(BINDIR)/$(CONFIG)/gpr_thd_test \ $(BINDIR)/$(CONFIG)/gpr_time_test \ $(BINDIR)/$(CONFIG)/gpr_tls_test \ $(BINDIR)/$(CONFIG)/gpr_useful_test \ $(BINDIR)/$(CONFIG)/grpc_auth_context_test \ $(BINDIR)/$(CONFIG)/grpc_b64_test \ $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test \ $(BINDIR)/$(CONFIG)/grpc_channel_args_test \ $(BINDIR)/$(CONFIG)/grpc_channel_stack_test \ $(BINDIR)/$(CONFIG)/grpc_completion_queue_test \ $(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test \ $(BINDIR)/$(CONFIG)/grpc_credentials_test \ $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 \ $(BINDIR)/$(CONFIG)/grpc_invalid_channel_args_test \ $(BINDIR)/$(CONFIG)/grpc_json_token_test \ $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test \ $(BINDIR)/$(CONFIG)/grpc_security_connector_test \ $(BINDIR)/$(CONFIG)/handshake_client \ $(BINDIR)/$(CONFIG)/handshake_server \ $(BINDIR)/$(CONFIG)/hpack_parser_test \ $(BINDIR)/$(CONFIG)/hpack_table_test \ $(BINDIR)/$(CONFIG)/http_parser_test \ $(BINDIR)/$(CONFIG)/httpcli_format_request_test \ $(BINDIR)/$(CONFIG)/httpcli_test \ $(BINDIR)/$(CONFIG)/httpscli_test \ $(BINDIR)/$(CONFIG)/init_test \ $(BINDIR)/$(CONFIG)/invalid_call_argument_test \ $(BINDIR)/$(CONFIG)/json_rewrite \ $(BINDIR)/$(CONFIG)/json_rewrite_test \ $(BINDIR)/$(CONFIG)/json_stream_error_test \ $(BINDIR)/$(CONFIG)/json_test \ $(BINDIR)/$(CONFIG)/lame_client_test \ $(BINDIR)/$(CONFIG)/lb_policies_test \ $(BINDIR)/$(CONFIG)/load_file_test \ $(BINDIR)/$(CONFIG)/memory_profile_client \ $(BINDIR)/$(CONFIG)/memory_profile_server \ $(BINDIR)/$(CONFIG)/memory_profile_test \ $(BINDIR)/$(CONFIG)/message_compress_test \ $(BINDIR)/$(CONFIG)/mlog_test \ $(BINDIR)/$(CONFIG)/multiple_server_queues_test \ $(BINDIR)/$(CONFIG)/murmur_hash_test \ $(BINDIR)/$(CONFIG)/no_server_test \ $(BINDIR)/$(CONFIG)/parse_address_test \ $(BINDIR)/$(CONFIG)/percent_encoding_test \ $(BINDIR)/$(CONFIG)/pollset_set_test \ $(BINDIR)/$(CONFIG)/resolve_address_posix_test \ $(BINDIR)/$(CONFIG)/resolve_address_test \ $(BINDIR)/$(CONFIG)/resource_quota_test \ $(BINDIR)/$(CONFIG)/secure_channel_create_test \ $(BINDIR)/$(CONFIG)/secure_endpoint_test \ $(BINDIR)/$(CONFIG)/sequential_connectivity_test \ $(BINDIR)/$(CONFIG)/server_chttp2_test \ $(BINDIR)/$(CONFIG)/server_test \ $(BINDIR)/$(CONFIG)/slice_buffer_test \ $(BINDIR)/$(CONFIG)/slice_string_helpers_test \ $(BINDIR)/$(CONFIG)/slice_test \ $(BINDIR)/$(CONFIG)/sockaddr_resolver_test \ $(BINDIR)/$(CONFIG)/sockaddr_utils_test \ $(BINDIR)/$(CONFIG)/socket_utils_test \ $(BINDIR)/$(CONFIG)/status_conversion_test \ $(BINDIR)/$(CONFIG)/stream_owned_slice_test \ $(BINDIR)/$(CONFIG)/tcp_client_posix_test \ $(BINDIR)/$(CONFIG)/tcp_client_uv_test \ $(BINDIR)/$(CONFIG)/tcp_posix_test \ $(BINDIR)/$(CONFIG)/tcp_server_posix_test \ $(BINDIR)/$(CONFIG)/tcp_server_uv_test \ $(BINDIR)/$(CONFIG)/time_averaged_stats_test \ $(BINDIR)/$(CONFIG)/timeout_encoding_test \ $(BINDIR)/$(CONFIG)/timer_heap_test \ $(BINDIR)/$(CONFIG)/timer_list_test \ $(BINDIR)/$(CONFIG)/transport_connectivity_state_test \ $(BINDIR)/$(CONFIG)/transport_metadata_test \ $(BINDIR)/$(CONFIG)/transport_pid_controller_test \ $(BINDIR)/$(CONFIG)/transport_security_test \ $(BINDIR)/$(CONFIG)/udp_server_test \ $(BINDIR)/$(CONFIG)/uri_parser_test \ $(BINDIR)/$(CONFIG)/wakeup_fd_cv_test \ $(BINDIR)/$(CONFIG)/public_headers_must_be_c89 \ $(BINDIR)/$(CONFIG)/badreq_bad_client_test \ $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test \ $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test \ $(BINDIR)/$(CONFIG)/headers_bad_client_test \ $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test \ $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test \ $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test \ $(BINDIR)/$(CONFIG)/simple_request_bad_client_test \ $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test \ $(BINDIR)/$(CONFIG)/window_overflow_bad_client_test \ $(BINDIR)/$(CONFIG)/bad_ssl_cert_server \ $(BINDIR)/$(CONFIG)/bad_ssl_cert_test \ $(BINDIR)/$(CONFIG)/h2_census_test \ $(BINDIR)/$(CONFIG)/h2_compress_test \ $(BINDIR)/$(CONFIG)/h2_fakesec_test \ $(BINDIR)/$(CONFIG)/h2_fd_test \ $(BINDIR)/$(CONFIG)/h2_full_test \ $(BINDIR)/$(CONFIG)/h2_full+pipe_test \ $(BINDIR)/$(CONFIG)/h2_full+trace_test \ $(BINDIR)/$(CONFIG)/h2_http_proxy_test \ $(BINDIR)/$(CONFIG)/h2_load_reporting_test \ $(BINDIR)/$(CONFIG)/h2_oauth2_test \ $(BINDIR)/$(CONFIG)/h2_proxy_test \ $(BINDIR)/$(CONFIG)/h2_sockpair_test \ $(BINDIR)/$(CONFIG)/h2_sockpair+trace_test \ $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_test \ $(BINDIR)/$(CONFIG)/h2_ssl_test \ $(BINDIR)/$(CONFIG)/h2_ssl_cert_test \ $(BINDIR)/$(CONFIG)/h2_ssl_proxy_test \ $(BINDIR)/$(CONFIG)/h2_uds_test \ $(BINDIR)/$(CONFIG)/h2_census_nosec_test \ $(BINDIR)/$(CONFIG)/h2_compress_nosec_test \ $(BINDIR)/$(CONFIG)/h2_fd_nosec_test \ $(BINDIR)/$(CONFIG)/h2_full_nosec_test \ $(BINDIR)/$(CONFIG)/h2_full+pipe_nosec_test \ $(BINDIR)/$(CONFIG)/h2_full+trace_nosec_test \ $(BINDIR)/$(CONFIG)/h2_http_proxy_nosec_test \ $(BINDIR)/$(CONFIG)/h2_load_reporting_nosec_test \ $(BINDIR)/$(CONFIG)/h2_proxy_nosec_test \ $(BINDIR)/$(CONFIG)/h2_sockpair_nosec_test \ $(BINDIR)/$(CONFIG)/h2_sockpair+trace_nosec_test \ $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_nosec_test \ $(BINDIR)/$(CONFIG)/h2_uds_nosec_test \ $(BINDIR)/$(CONFIG)/api_fuzzer_one_entry \ $(BINDIR)/$(CONFIG)/client_fuzzer_one_entry \ $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry \ $(BINDIR)/$(CONFIG)/http_request_fuzzer_test_one_entry \ $(BINDIR)/$(CONFIG)/http_response_fuzzer_test_one_entry \ $(BINDIR)/$(CONFIG)/json_fuzzer_test_one_entry \ $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test_one_entry \ $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test_one_entry \ $(BINDIR)/$(CONFIG)/percent_decode_fuzzer_one_entry \ $(BINDIR)/$(CONFIG)/percent_encode_fuzzer_one_entry \ $(BINDIR)/$(CONFIG)/server_fuzzer_one_entry \ $(BINDIR)/$(CONFIG)/ssl_server_fuzzer_one_entry \ $(BINDIR)/$(CONFIG)/uri_fuzzer_test_one_entry \ ifeq ($(EMBED_OPENSSL),true) buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/alarm_cpp_test \ $(BINDIR)/$(CONFIG)/async_end2end_test \ $(BINDIR)/$(CONFIG)/auth_property_iterator_test \ $(BINDIR)/$(CONFIG)/bm_arena \ $(BINDIR)/$(CONFIG)/bm_call_create \ $(BINDIR)/$(CONFIG)/bm_chttp2_hpack \ $(BINDIR)/$(CONFIG)/bm_chttp2_transport \ $(BINDIR)/$(CONFIG)/bm_closure \ $(BINDIR)/$(CONFIG)/bm_cq \ $(BINDIR)/$(CONFIG)/bm_cq_multiple_threads \ $(BINDIR)/$(CONFIG)/bm_error \ $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_ping_pong \ $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_pump \ $(BINDIR)/$(CONFIG)/bm_fullstack_trickle \ $(BINDIR)/$(CONFIG)/bm_fullstack_unary_ping_pong \ $(BINDIR)/$(CONFIG)/bm_metadata \ $(BINDIR)/$(CONFIG)/bm_pollset \ $(BINDIR)/$(CONFIG)/channel_arguments_test \ $(BINDIR)/$(CONFIG)/channel_filter_test \ $(BINDIR)/$(CONFIG)/cli_call_test \ $(BINDIR)/$(CONFIG)/client_crash_test \ $(BINDIR)/$(CONFIG)/client_crash_test_server \ $(BINDIR)/$(CONFIG)/codegen_test_full \ $(BINDIR)/$(CONFIG)/codegen_test_minimal \ $(BINDIR)/$(CONFIG)/credentials_test \ $(BINDIR)/$(CONFIG)/cxx_byte_buffer_test \ $(BINDIR)/$(CONFIG)/cxx_slice_test \ $(BINDIR)/$(CONFIG)/cxx_string_ref_test \ $(BINDIR)/$(CONFIG)/cxx_time_test \ $(BINDIR)/$(CONFIG)/end2end_test \ $(BINDIR)/$(CONFIG)/error_details_test \ $(BINDIR)/$(CONFIG)/filter_end2end_test \ $(BINDIR)/$(CONFIG)/generic_end2end_test \ $(BINDIR)/$(CONFIG)/golden_file_test \ $(BINDIR)/$(CONFIG)/grpc_cli \ $(BINDIR)/$(CONFIG)/grpc_tool_test \ $(BINDIR)/$(CONFIG)/grpclb_api_test \ $(BINDIR)/$(CONFIG)/grpclb_test \ $(BINDIR)/$(CONFIG)/health_service_end2end_test \ $(BINDIR)/$(CONFIG)/http2_client \ $(BINDIR)/$(CONFIG)/hybrid_end2end_test \ $(BINDIR)/$(CONFIG)/interop_client \ $(BINDIR)/$(CONFIG)/interop_server \ $(BINDIR)/$(CONFIG)/interop_test \ $(BINDIR)/$(CONFIG)/json_run_localhost \ $(BINDIR)/$(CONFIG)/metrics_client \ $(BINDIR)/$(CONFIG)/mock_test \ $(BINDIR)/$(CONFIG)/noop-benchmark \ $(BINDIR)/$(CONFIG)/proto_server_reflection_test \ $(BINDIR)/$(CONFIG)/proto_utils_test \ $(BINDIR)/$(CONFIG)/qps_interarrival_test \ $(BINDIR)/$(CONFIG)/qps_json_driver \ $(BINDIR)/$(CONFIG)/qps_openloop_test \ $(BINDIR)/$(CONFIG)/qps_worker \ $(BINDIR)/$(CONFIG)/reconnect_interop_client \ $(BINDIR)/$(CONFIG)/reconnect_interop_server \ $(BINDIR)/$(CONFIG)/round_robin_end2end_test \ $(BINDIR)/$(CONFIG)/secure_auth_context_test \ $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test \ $(BINDIR)/$(CONFIG)/server_builder_plugin_test \ $(BINDIR)/$(CONFIG)/server_builder_test \ $(BINDIR)/$(CONFIG)/server_context_test_spouse_test \ $(BINDIR)/$(CONFIG)/server_crash_test \ $(BINDIR)/$(CONFIG)/server_crash_test_client \ $(BINDIR)/$(CONFIG)/shutdown_test \ $(BINDIR)/$(CONFIG)/status_test \ $(BINDIR)/$(CONFIG)/streaming_throughput_test \ $(BINDIR)/$(CONFIG)/stress_test \ $(BINDIR)/$(CONFIG)/thread_manager_test \ $(BINDIR)/$(CONFIG)/thread_stress_test \ $(BINDIR)/$(CONFIG)/writes_per_rpc_test \ $(BINDIR)/$(CONFIG)/boringssl_aes_test \ $(BINDIR)/$(CONFIG)/boringssl_asn1_test \ $(BINDIR)/$(CONFIG)/boringssl_base64_test \ $(BINDIR)/$(CONFIG)/boringssl_bio_test \ $(BINDIR)/$(CONFIG)/boringssl_bn_test \ $(BINDIR)/$(CONFIG)/boringssl_bytestring_test \ $(BINDIR)/$(CONFIG)/boringssl_chacha_test \ $(BINDIR)/$(CONFIG)/boringssl_aead_test \ $(BINDIR)/$(CONFIG)/boringssl_cipher_test \ $(BINDIR)/$(CONFIG)/boringssl_cmac_test \ $(BINDIR)/$(CONFIG)/boringssl_constant_time_test \ $(BINDIR)/$(CONFIG)/boringssl_ed25519_test \ $(BINDIR)/$(CONFIG)/boringssl_spake25519_test \ $(BINDIR)/$(CONFIG)/boringssl_x25519_test \ $(BINDIR)/$(CONFIG)/boringssl_dh_test \ $(BINDIR)/$(CONFIG)/boringssl_digest_test \ $(BINDIR)/$(CONFIG)/boringssl_dsa_test \ $(BINDIR)/$(CONFIG)/boringssl_ec_test \ $(BINDIR)/$(CONFIG)/boringssl_example_mul \ $(BINDIR)/$(CONFIG)/boringssl_ecdh_test \ $(BINDIR)/$(CONFIG)/boringssl_ecdsa_sign_test \ $(BINDIR)/$(CONFIG)/boringssl_ecdsa_test \ $(BINDIR)/$(CONFIG)/boringssl_ecdsa_verify_test \ $(BINDIR)/$(CONFIG)/boringssl_err_test \ $(BINDIR)/$(CONFIG)/boringssl_evp_extra_test \ $(BINDIR)/$(CONFIG)/boringssl_evp_test \ $(BINDIR)/$(CONFIG)/boringssl_pbkdf_test \ $(BINDIR)/$(CONFIG)/boringssl_hkdf_test \ $(BINDIR)/$(CONFIG)/boringssl_hmac_test \ $(BINDIR)/$(CONFIG)/boringssl_lhash_test \ $(BINDIR)/$(CONFIG)/boringssl_gcm_test \ $(BINDIR)/$(CONFIG)/boringssl_newhope_statistical_test \ $(BINDIR)/$(CONFIG)/boringssl_newhope_test \ $(BINDIR)/$(CONFIG)/boringssl_newhope_vectors_test \ $(BINDIR)/$(CONFIG)/boringssl_obj_test \ $(BINDIR)/$(CONFIG)/boringssl_pkcs12_test \ $(BINDIR)/$(CONFIG)/boringssl_pkcs8_test \ $(BINDIR)/$(CONFIG)/boringssl_poly1305_test \ $(BINDIR)/$(CONFIG)/boringssl_refcount_test \ $(BINDIR)/$(CONFIG)/boringssl_rsa_test \ $(BINDIR)/$(CONFIG)/boringssl_thread_test \ $(BINDIR)/$(CONFIG)/boringssl_pkcs7_test \ $(BINDIR)/$(CONFIG)/boringssl_x509_test \ $(BINDIR)/$(CONFIG)/boringssl_tab_test \ $(BINDIR)/$(CONFIG)/boringssl_v3name_test \ $(BINDIR)/$(CONFIG)/boringssl_ssl_test \ else buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/alarm_cpp_test \ $(BINDIR)/$(CONFIG)/async_end2end_test \ $(BINDIR)/$(CONFIG)/auth_property_iterator_test \ $(BINDIR)/$(CONFIG)/bm_arena \ $(BINDIR)/$(CONFIG)/bm_call_create \ $(BINDIR)/$(CONFIG)/bm_chttp2_hpack \ $(BINDIR)/$(CONFIG)/bm_chttp2_transport \ $(BINDIR)/$(CONFIG)/bm_closure \ $(BINDIR)/$(CONFIG)/bm_cq \ $(BINDIR)/$(CONFIG)/bm_cq_multiple_threads \ $(BINDIR)/$(CONFIG)/bm_error \ $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_ping_pong \ $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_pump \ $(BINDIR)/$(CONFIG)/bm_fullstack_trickle \ $(BINDIR)/$(CONFIG)/bm_fullstack_unary_ping_pong \ $(BINDIR)/$(CONFIG)/bm_metadata \ $(BINDIR)/$(CONFIG)/bm_pollset \ $(BINDIR)/$(CONFIG)/channel_arguments_test \ $(BINDIR)/$(CONFIG)/channel_filter_test \ $(BINDIR)/$(CONFIG)/cli_call_test \ $(BINDIR)/$(CONFIG)/client_crash_test \ $(BINDIR)/$(CONFIG)/client_crash_test_server \ $(BINDIR)/$(CONFIG)/codegen_test_full \ $(BINDIR)/$(CONFIG)/codegen_test_minimal \ $(BINDIR)/$(CONFIG)/credentials_test \ $(BINDIR)/$(CONFIG)/cxx_byte_buffer_test \ $(BINDIR)/$(CONFIG)/cxx_slice_test \ $(BINDIR)/$(CONFIG)/cxx_string_ref_test \ $(BINDIR)/$(CONFIG)/cxx_time_test \ $(BINDIR)/$(CONFIG)/end2end_test \ $(BINDIR)/$(CONFIG)/error_details_test \ $(BINDIR)/$(CONFIG)/filter_end2end_test \ $(BINDIR)/$(CONFIG)/generic_end2end_test \ $(BINDIR)/$(CONFIG)/golden_file_test \ $(BINDIR)/$(CONFIG)/grpc_cli \ $(BINDIR)/$(CONFIG)/grpc_tool_test \ $(BINDIR)/$(CONFIG)/grpclb_api_test \ $(BINDIR)/$(CONFIG)/grpclb_test \ $(BINDIR)/$(CONFIG)/health_service_end2end_test \ $(BINDIR)/$(CONFIG)/http2_client \ $(BINDIR)/$(CONFIG)/hybrid_end2end_test \ $(BINDIR)/$(CONFIG)/interop_client \ $(BINDIR)/$(CONFIG)/interop_server \ $(BINDIR)/$(CONFIG)/interop_test \ $(BINDIR)/$(CONFIG)/json_run_localhost \ $(BINDIR)/$(CONFIG)/metrics_client \ $(BINDIR)/$(CONFIG)/mock_test \ $(BINDIR)/$(CONFIG)/noop-benchmark \ $(BINDIR)/$(CONFIG)/proto_server_reflection_test \ $(BINDIR)/$(CONFIG)/proto_utils_test \ $(BINDIR)/$(CONFIG)/qps_interarrival_test \ $(BINDIR)/$(CONFIG)/qps_json_driver \ $(BINDIR)/$(CONFIG)/qps_openloop_test \ $(BINDIR)/$(CONFIG)/qps_worker \ $(BINDIR)/$(CONFIG)/reconnect_interop_client \ $(BINDIR)/$(CONFIG)/reconnect_interop_server \ $(BINDIR)/$(CONFIG)/round_robin_end2end_test \ $(BINDIR)/$(CONFIG)/secure_auth_context_test \ $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test \ $(BINDIR)/$(CONFIG)/server_builder_plugin_test \ $(BINDIR)/$(CONFIG)/server_builder_test \ $(BINDIR)/$(CONFIG)/server_context_test_spouse_test \ $(BINDIR)/$(CONFIG)/server_crash_test \ $(BINDIR)/$(CONFIG)/server_crash_test_client \ $(BINDIR)/$(CONFIG)/shutdown_test \ $(BINDIR)/$(CONFIG)/status_test \ $(BINDIR)/$(CONFIG)/streaming_throughput_test \ $(BINDIR)/$(CONFIG)/stress_test \ $(BINDIR)/$(CONFIG)/thread_manager_test \ $(BINDIR)/$(CONFIG)/thread_stress_test \ $(BINDIR)/$(CONFIG)/writes_per_rpc_test \ endif test: test_c test_cxx flaky_test: flaky_test_c flaky_test_cxx test_c: buildtests_c $(E) "[RUN] Testing alarm_test" $(Q) $(BINDIR)/$(CONFIG)/alarm_test || ( echo test alarm_test failed ; exit 1 ) $(E) "[RUN] Testing algorithm_test" $(Q) $(BINDIR)/$(CONFIG)/algorithm_test || ( echo test algorithm_test failed ; exit 1 ) $(E) "[RUN] Testing alloc_test" $(Q) $(BINDIR)/$(CONFIG)/alloc_test || ( echo test alloc_test failed ; exit 1 ) $(E) "[RUN] Testing alpn_test" $(Q) $(BINDIR)/$(CONFIG)/alpn_test || ( echo test alpn_test failed ; exit 1 ) $(E) "[RUN] Testing arena_test" $(Q) $(BINDIR)/$(CONFIG)/arena_test || ( echo test arena_test failed ; exit 1 ) $(E) "[RUN] Testing bad_server_response_test" $(Q) $(BINDIR)/$(CONFIG)/bad_server_response_test || ( echo test bad_server_response_test failed ; exit 1 ) $(E) "[RUN] Testing bdp_estimator_test" $(Q) $(BINDIR)/$(CONFIG)/bdp_estimator_test || ( echo test bdp_estimator_test failed ; exit 1 ) $(E) "[RUN] Testing bin_decoder_test" $(Q) $(BINDIR)/$(CONFIG)/bin_decoder_test || ( echo test bin_decoder_test failed ; exit 1 ) $(E) "[RUN] Testing bin_encoder_test" $(Q) $(BINDIR)/$(CONFIG)/bin_encoder_test || ( echo test bin_encoder_test failed ; exit 1 ) $(E) "[RUN] Testing census_context_test" $(Q) $(BINDIR)/$(CONFIG)/census_context_test || ( echo test census_context_test failed ; exit 1 ) $(E) "[RUN] Testing census_resource_test" $(Q) $(BINDIR)/$(CONFIG)/census_resource_test || ( echo test census_resource_test failed ; exit 1 ) $(E) "[RUN] Testing census_trace_context_test" $(Q) $(BINDIR)/$(CONFIG)/census_trace_context_test || ( echo test census_trace_context_test failed ; exit 1 ) $(E) "[RUN] Testing channel_create_test" $(Q) $(BINDIR)/$(CONFIG)/channel_create_test || ( echo test channel_create_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_hpack_encoder_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test || ( echo test chttp2_hpack_encoder_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_stream_map_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_stream_map_test || ( echo test chttp2_stream_map_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_varint_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_varint_test || ( echo test chttp2_varint_test failed ; exit 1 ) $(E) "[RUN] Testing combiner_test" $(Q) $(BINDIR)/$(CONFIG)/combiner_test || ( echo test combiner_test failed ; exit 1 ) $(E) "[RUN] Testing compression_test" $(Q) $(BINDIR)/$(CONFIG)/compression_test || ( echo test compression_test failed ; exit 1 ) $(E) "[RUN] Testing concurrent_connectivity_test" $(Q) $(BINDIR)/$(CONFIG)/concurrent_connectivity_test || ( echo test concurrent_connectivity_test failed ; exit 1 ) $(E) "[RUN] Testing connection_refused_test" $(Q) $(BINDIR)/$(CONFIG)/connection_refused_test || ( echo test connection_refused_test failed ; exit 1 ) $(E) "[RUN] Testing dns_resolver_connectivity_test" $(Q) $(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test || ( echo test dns_resolver_connectivity_test failed ; exit 1 ) $(E) "[RUN] Testing dns_resolver_test" $(Q) $(BINDIR)/$(CONFIG)/dns_resolver_test || ( echo test dns_resolver_test failed ; exit 1 ) $(E) "[RUN] Testing dualstack_socket_test" $(Q) $(BINDIR)/$(CONFIG)/dualstack_socket_test || ( echo test dualstack_socket_test failed ; exit 1 ) $(E) "[RUN] Testing endpoint_pair_test" $(Q) $(BINDIR)/$(CONFIG)/endpoint_pair_test || ( echo test endpoint_pair_test failed ; exit 1 ) $(E) "[RUN] Testing error_test" $(Q) $(BINDIR)/$(CONFIG)/error_test || ( echo test error_test failed ; exit 1 ) $(E) "[RUN] Testing ev_epoll_linux_test" $(Q) $(BINDIR)/$(CONFIG)/ev_epoll_linux_test || ( echo test ev_epoll_linux_test failed ; exit 1 ) $(E) "[RUN] Testing fd_conservation_posix_test" $(Q) $(BINDIR)/$(CONFIG)/fd_conservation_posix_test || ( echo test fd_conservation_posix_test failed ; exit 1 ) $(E) "[RUN] Testing fd_posix_test" $(Q) $(BINDIR)/$(CONFIG)/fd_posix_test || ( echo test fd_posix_test failed ; exit 1 ) $(E) "[RUN] Testing fling_stream_test" $(Q) $(BINDIR)/$(CONFIG)/fling_stream_test || ( echo test fling_stream_test failed ; exit 1 ) $(E) "[RUN] Testing fling_test" $(Q) $(BINDIR)/$(CONFIG)/fling_test || ( echo test fling_test failed ; exit 1 ) $(E) "[RUN] Testing goaway_server_test" $(Q) $(BINDIR)/$(CONFIG)/goaway_server_test || ( echo test goaway_server_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_avl_test" $(Q) $(BINDIR)/$(CONFIG)/gpr_avl_test || ( echo test gpr_avl_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_backoff_test" $(Q) $(BINDIR)/$(CONFIG)/gpr_backoff_test || ( echo test gpr_backoff_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_cmdline_test" $(Q) $(BINDIR)/$(CONFIG)/gpr_cmdline_test || ( echo test gpr_cmdline_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_cpu_test" $(Q) $(BINDIR)/$(CONFIG)/gpr_cpu_test || ( echo test gpr_cpu_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_env_test" $(Q) $(BINDIR)/$(CONFIG)/gpr_env_test || ( echo test gpr_env_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_histogram_test" $(Q) $(BINDIR)/$(CONFIG)/gpr_histogram_test || ( echo test gpr_histogram_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_host_port_test" $(Q) $(BINDIR)/$(CONFIG)/gpr_host_port_test || ( echo test gpr_host_port_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_log_test" $(Q) $(BINDIR)/$(CONFIG)/gpr_log_test || ( echo test gpr_log_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_mpscq_test" $(Q) $(BINDIR)/$(CONFIG)/gpr_mpscq_test || ( echo test gpr_mpscq_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_spinlock_test" $(Q) $(BINDIR)/$(CONFIG)/gpr_spinlock_test || ( echo test gpr_spinlock_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_stack_lockfree_test" $(Q) $(BINDIR)/$(CONFIG)/gpr_stack_lockfree_test || ( echo test gpr_stack_lockfree_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_string_test" $(Q) $(BINDIR)/$(CONFIG)/gpr_string_test || ( echo test gpr_string_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_sync_test" $(Q) $(BINDIR)/$(CONFIG)/gpr_sync_test || ( echo test gpr_sync_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_thd_test" $(Q) $(BINDIR)/$(CONFIG)/gpr_thd_test || ( echo test gpr_thd_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_time_test" $(Q) $(BINDIR)/$(CONFIG)/gpr_time_test || ( echo test gpr_time_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_tls_test" $(Q) $(BINDIR)/$(CONFIG)/gpr_tls_test || ( echo test gpr_tls_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_useful_test" $(Q) $(BINDIR)/$(CONFIG)/gpr_useful_test || ( echo test gpr_useful_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_auth_context_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_auth_context_test || ( echo test grpc_auth_context_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_b64_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_b64_test || ( echo test grpc_b64_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_byte_buffer_reader_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test || ( echo test grpc_byte_buffer_reader_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_channel_args_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_channel_args_test || ( echo test grpc_channel_args_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_channel_stack_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_channel_stack_test || ( echo test grpc_channel_stack_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_completion_queue_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_completion_queue_test || ( echo test grpc_completion_queue_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_completion_queue_threading_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test || ( echo test grpc_completion_queue_threading_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_credentials_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_credentials_test || ( echo test grpc_credentials_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_invalid_channel_args_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_invalid_channel_args_test || ( echo test grpc_invalid_channel_args_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_json_token_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_json_token_test || ( echo test grpc_json_token_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_jwt_verifier_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test || ( echo test grpc_jwt_verifier_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_security_connector_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_security_connector_test || ( echo test grpc_security_connector_test failed ; exit 1 ) $(E) "[RUN] Testing handshake_client" $(Q) $(BINDIR)/$(CONFIG)/handshake_client || ( echo test handshake_client failed ; exit 1 ) $(E) "[RUN] Testing handshake_server" $(Q) $(BINDIR)/$(CONFIG)/handshake_server || ( echo test handshake_server failed ; exit 1 ) $(E) "[RUN] Testing hpack_parser_test" $(Q) $(BINDIR)/$(CONFIG)/hpack_parser_test || ( echo test hpack_parser_test failed ; exit 1 ) $(E) "[RUN] Testing hpack_table_test" $(Q) $(BINDIR)/$(CONFIG)/hpack_table_test || ( echo test hpack_table_test failed ; exit 1 ) $(E) "[RUN] Testing http_parser_test" $(Q) $(BINDIR)/$(CONFIG)/http_parser_test || ( echo test http_parser_test failed ; exit 1 ) $(E) "[RUN] Testing httpcli_format_request_test" $(Q) $(BINDIR)/$(CONFIG)/httpcli_format_request_test || ( echo test httpcli_format_request_test failed ; exit 1 ) $(E) "[RUN] Testing httpcli_test" $(Q) $(BINDIR)/$(CONFIG)/httpcli_test || ( echo test httpcli_test failed ; exit 1 ) $(E) "[RUN] Testing httpscli_test" $(Q) $(BINDIR)/$(CONFIG)/httpscli_test || ( echo test httpscli_test failed ; exit 1 ) $(E) "[RUN] Testing init_test" $(Q) $(BINDIR)/$(CONFIG)/init_test || ( echo test init_test failed ; exit 1 ) $(E) "[RUN] Testing invalid_call_argument_test" $(Q) $(BINDIR)/$(CONFIG)/invalid_call_argument_test || ( echo test invalid_call_argument_test failed ; exit 1 ) $(E) "[RUN] Testing json_rewrite_test" $(Q) $(BINDIR)/$(CONFIG)/json_rewrite_test || ( echo test json_rewrite_test failed ; exit 1 ) $(E) "[RUN] Testing json_stream_error_test" $(Q) $(BINDIR)/$(CONFIG)/json_stream_error_test || ( echo test json_stream_error_test failed ; exit 1 ) $(E) "[RUN] Testing json_test" $(Q) $(BINDIR)/$(CONFIG)/json_test || ( echo test json_test failed ; exit 1 ) $(E) "[RUN] Testing lame_client_test" $(Q) $(BINDIR)/$(CONFIG)/lame_client_test || ( echo test lame_client_test failed ; exit 1 ) $(E) "[RUN] Testing load_file_test" $(Q) $(BINDIR)/$(CONFIG)/load_file_test || ( echo test load_file_test failed ; exit 1 ) $(E) "[RUN] Testing memory_profile_test" $(Q) $(BINDIR)/$(CONFIG)/memory_profile_test || ( echo test memory_profile_test failed ; exit 1 ) $(E) "[RUN] Testing message_compress_test" $(Q) $(BINDIR)/$(CONFIG)/message_compress_test || ( echo test message_compress_test failed ; exit 1 ) $(E) "[RUN] Testing multiple_server_queues_test" $(Q) $(BINDIR)/$(CONFIG)/multiple_server_queues_test || ( echo test multiple_server_queues_test failed ; exit 1 ) $(E) "[RUN] Testing murmur_hash_test" $(Q) $(BINDIR)/$(CONFIG)/murmur_hash_test || ( echo test murmur_hash_test failed ; exit 1 ) $(E) "[RUN] Testing no_server_test" $(Q) $(BINDIR)/$(CONFIG)/no_server_test || ( echo test no_server_test failed ; exit 1 ) $(E) "[RUN] Testing parse_address_test" $(Q) $(BINDIR)/$(CONFIG)/parse_address_test || ( echo test parse_address_test failed ; exit 1 ) $(E) "[RUN] Testing percent_encoding_test" $(Q) $(BINDIR)/$(CONFIG)/percent_encoding_test || ( echo test percent_encoding_test failed ; exit 1 ) $(E) "[RUN] Testing pollset_set_test" $(Q) $(BINDIR)/$(CONFIG)/pollset_set_test || ( echo test pollset_set_test failed ; exit 1 ) $(E) "[RUN] Testing resolve_address_posix_test" $(Q) $(BINDIR)/$(CONFIG)/resolve_address_posix_test || ( echo test resolve_address_posix_test failed ; exit 1 ) $(E) "[RUN] Testing resolve_address_test" $(Q) $(BINDIR)/$(CONFIG)/resolve_address_test || ( echo test resolve_address_test failed ; exit 1 ) $(E) "[RUN] Testing resource_quota_test" $(Q) $(BINDIR)/$(CONFIG)/resource_quota_test || ( echo test resource_quota_test failed ; exit 1 ) $(E) "[RUN] Testing secure_channel_create_test" $(Q) $(BINDIR)/$(CONFIG)/secure_channel_create_test || ( echo test secure_channel_create_test failed ; exit 1 ) $(E) "[RUN] Testing secure_endpoint_test" $(Q) $(BINDIR)/$(CONFIG)/secure_endpoint_test || ( echo test secure_endpoint_test failed ; exit 1 ) $(E) "[RUN] Testing sequential_connectivity_test" $(Q) $(BINDIR)/$(CONFIG)/sequential_connectivity_test || ( echo test sequential_connectivity_test failed ; exit 1 ) $(E) "[RUN] Testing server_chttp2_test" $(Q) $(BINDIR)/$(CONFIG)/server_chttp2_test || ( echo test server_chttp2_test failed ; exit 1 ) $(E) "[RUN] Testing server_test" $(Q) $(BINDIR)/$(CONFIG)/server_test || ( echo test server_test failed ; exit 1 ) $(E) "[RUN] Testing slice_buffer_test" $(Q) $(BINDIR)/$(CONFIG)/slice_buffer_test || ( echo test slice_buffer_test failed ; exit 1 ) $(E) "[RUN] Testing slice_string_helpers_test" $(Q) $(BINDIR)/$(CONFIG)/slice_string_helpers_test || ( echo test slice_string_helpers_test failed ; exit 1 ) $(E) "[RUN] Testing slice_test" $(Q) $(BINDIR)/$(CONFIG)/slice_test || ( echo test slice_test failed ; exit 1 ) $(E) "[RUN] Testing sockaddr_resolver_test" $(Q) $(BINDIR)/$(CONFIG)/sockaddr_resolver_test || ( echo test sockaddr_resolver_test failed ; exit 1 ) $(E) "[RUN] Testing sockaddr_utils_test" $(Q) $(BINDIR)/$(CONFIG)/sockaddr_utils_test || ( echo test sockaddr_utils_test failed ; exit 1 ) $(E) "[RUN] Testing socket_utils_test" $(Q) $(BINDIR)/$(CONFIG)/socket_utils_test || ( echo test socket_utils_test failed ; exit 1 ) $(E) "[RUN] Testing status_conversion_test" $(Q) $(BINDIR)/$(CONFIG)/status_conversion_test || ( echo test status_conversion_test failed ; exit 1 ) $(E) "[RUN] Testing stream_owned_slice_test" $(Q) $(BINDIR)/$(CONFIG)/stream_owned_slice_test || ( echo test stream_owned_slice_test failed ; exit 1 ) $(E) "[RUN] Testing tcp_client_posix_test" $(Q) $(BINDIR)/$(CONFIG)/tcp_client_posix_test || ( echo test tcp_client_posix_test failed ; exit 1 ) $(E) "[RUN] Testing tcp_client_uv_test" $(Q) $(BINDIR)/$(CONFIG)/tcp_client_uv_test || ( echo test tcp_client_uv_test failed ; exit 1 ) $(E) "[RUN] Testing tcp_posix_test" $(Q) $(BINDIR)/$(CONFIG)/tcp_posix_test || ( echo test tcp_posix_test failed ; exit 1 ) $(E) "[RUN] Testing tcp_server_posix_test" $(Q) $(BINDIR)/$(CONFIG)/tcp_server_posix_test || ( echo test tcp_server_posix_test failed ; exit 1 ) $(E) "[RUN] Testing tcp_server_uv_test" $(Q) $(BINDIR)/$(CONFIG)/tcp_server_uv_test || ( echo test tcp_server_uv_test failed ; exit 1 ) $(E) "[RUN] Testing time_averaged_stats_test" $(Q) $(BINDIR)/$(CONFIG)/time_averaged_stats_test || ( echo test time_averaged_stats_test failed ; exit 1 ) $(E) "[RUN] Testing timeout_encoding_test" $(Q) $(BINDIR)/$(CONFIG)/timeout_encoding_test || ( echo test timeout_encoding_test failed ; exit 1 ) $(E) "[RUN] Testing timer_heap_test" $(Q) $(BINDIR)/$(CONFIG)/timer_heap_test || ( echo test timer_heap_test failed ; exit 1 ) $(E) "[RUN] Testing timer_list_test" $(Q) $(BINDIR)/$(CONFIG)/timer_list_test || ( echo test timer_list_test failed ; exit 1 ) $(E) "[RUN] Testing transport_connectivity_state_test" $(Q) $(BINDIR)/$(CONFIG)/transport_connectivity_state_test || ( echo test transport_connectivity_state_test failed ; exit 1 ) $(E) "[RUN] Testing transport_metadata_test" $(Q) $(BINDIR)/$(CONFIG)/transport_metadata_test || ( echo test transport_metadata_test failed ; exit 1 ) $(E) "[RUN] Testing transport_pid_controller_test" $(Q) $(BINDIR)/$(CONFIG)/transport_pid_controller_test || ( echo test transport_pid_controller_test failed ; exit 1 ) $(E) "[RUN] Testing transport_security_test" $(Q) $(BINDIR)/$(CONFIG)/transport_security_test || ( echo test transport_security_test failed ; exit 1 ) $(E) "[RUN] Testing udp_server_test" $(Q) $(BINDIR)/$(CONFIG)/udp_server_test || ( echo test udp_server_test failed ; exit 1 ) $(E) "[RUN] Testing uri_parser_test" $(Q) $(BINDIR)/$(CONFIG)/uri_parser_test || ( echo test uri_parser_test failed ; exit 1 ) $(E) "[RUN] Testing wakeup_fd_cv_test" $(Q) $(BINDIR)/$(CONFIG)/wakeup_fd_cv_test || ( echo test wakeup_fd_cv_test failed ; exit 1 ) $(E) "[RUN] Testing public_headers_must_be_c89" $(Q) $(BINDIR)/$(CONFIG)/public_headers_must_be_c89 || ( echo test public_headers_must_be_c89 failed ; exit 1 ) $(E) "[RUN] Testing badreq_bad_client_test" $(Q) $(BINDIR)/$(CONFIG)/badreq_bad_client_test || ( echo test badreq_bad_client_test failed ; exit 1 ) $(E) "[RUN] Testing connection_prefix_bad_client_test" $(Q) $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test || ( echo test connection_prefix_bad_client_test failed ; exit 1 ) $(E) "[RUN] Testing head_of_line_blocking_bad_client_test" $(Q) $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test || ( echo test head_of_line_blocking_bad_client_test failed ; exit 1 ) $(E) "[RUN] Testing headers_bad_client_test" $(Q) $(BINDIR)/$(CONFIG)/headers_bad_client_test || ( echo test headers_bad_client_test failed ; exit 1 ) $(E) "[RUN] Testing initial_settings_frame_bad_client_test" $(Q) $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test || ( echo test initial_settings_frame_bad_client_test failed ; exit 1 ) $(E) "[RUN] Testing large_metadata_bad_client_test" $(Q) $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test || ( echo test large_metadata_bad_client_test failed ; exit 1 ) $(E) "[RUN] Testing server_registered_method_bad_client_test" $(Q) $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test || ( echo test server_registered_method_bad_client_test failed ; exit 1 ) $(E) "[RUN] Testing simple_request_bad_client_test" $(Q) $(BINDIR)/$(CONFIG)/simple_request_bad_client_test || ( echo test simple_request_bad_client_test failed ; exit 1 ) $(E) "[RUN] Testing unknown_frame_bad_client_test" $(Q) $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test || ( echo test unknown_frame_bad_client_test failed ; exit 1 ) $(E) "[RUN] Testing window_overflow_bad_client_test" $(Q) $(BINDIR)/$(CONFIG)/window_overflow_bad_client_test || ( echo test window_overflow_bad_client_test failed ; exit 1 ) $(E) "[RUN] Testing bad_ssl_cert_test" $(Q) $(BINDIR)/$(CONFIG)/bad_ssl_cert_test || ( echo test bad_ssl_cert_test failed ; exit 1 ) flaky_test_c: buildtests_c $(E) "[RUN] Testing mlog_test" $(Q) $(BINDIR)/$(CONFIG)/mlog_test || ( echo test mlog_test failed ; exit 1 ) test_cxx: buildtests_cxx $(E) "[RUN] Testing alarm_cpp_test" $(Q) $(BINDIR)/$(CONFIG)/alarm_cpp_test || ( echo test alarm_cpp_test failed ; exit 1 ) $(E) "[RUN] Testing async_end2end_test" $(Q) $(BINDIR)/$(CONFIG)/async_end2end_test || ( echo test async_end2end_test failed ; exit 1 ) $(E) "[RUN] Testing auth_property_iterator_test" $(Q) $(BINDIR)/$(CONFIG)/auth_property_iterator_test || ( echo test auth_property_iterator_test failed ; exit 1 ) $(E) "[RUN] Testing bm_arena" $(Q) $(BINDIR)/$(CONFIG)/bm_arena || ( echo test bm_arena failed ; exit 1 ) $(E) "[RUN] Testing bm_call_create" $(Q) $(BINDIR)/$(CONFIG)/bm_call_create || ( echo test bm_call_create failed ; exit 1 ) $(E) "[RUN] Testing bm_chttp2_hpack" $(Q) $(BINDIR)/$(CONFIG)/bm_chttp2_hpack || ( echo test bm_chttp2_hpack failed ; exit 1 ) $(E) "[RUN] Testing bm_chttp2_transport" $(Q) $(BINDIR)/$(CONFIG)/bm_chttp2_transport || ( echo test bm_chttp2_transport failed ; exit 1 ) $(E) "[RUN] Testing bm_closure" $(Q) $(BINDIR)/$(CONFIG)/bm_closure || ( echo test bm_closure failed ; exit 1 ) $(E) "[RUN] Testing bm_cq" $(Q) $(BINDIR)/$(CONFIG)/bm_cq || ( echo test bm_cq failed ; exit 1 ) $(E) "[RUN] Testing bm_cq_multiple_threads" $(Q) $(BINDIR)/$(CONFIG)/bm_cq_multiple_threads || ( echo test bm_cq_multiple_threads failed ; exit 1 ) $(E) "[RUN] Testing bm_error" $(Q) $(BINDIR)/$(CONFIG)/bm_error || ( echo test bm_error failed ; exit 1 ) $(E) "[RUN] Testing bm_fullstack_streaming_ping_pong" $(Q) $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_ping_pong || ( echo test bm_fullstack_streaming_ping_pong failed ; exit 1 ) $(E) "[RUN] Testing bm_fullstack_streaming_pump" $(Q) $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_pump || ( echo test bm_fullstack_streaming_pump failed ; exit 1 ) $(E) "[RUN] Testing bm_fullstack_trickle" $(Q) $(BINDIR)/$(CONFIG)/bm_fullstack_trickle || ( echo test bm_fullstack_trickle failed ; exit 1 ) $(E) "[RUN] Testing bm_fullstack_unary_ping_pong" $(Q) $(BINDIR)/$(CONFIG)/bm_fullstack_unary_ping_pong || ( echo test bm_fullstack_unary_ping_pong failed ; exit 1 ) $(E) "[RUN] Testing bm_metadata" $(Q) $(BINDIR)/$(CONFIG)/bm_metadata || ( echo test bm_metadata failed ; exit 1 ) $(E) "[RUN] Testing bm_pollset" $(Q) $(BINDIR)/$(CONFIG)/bm_pollset || ( echo test bm_pollset failed ; exit 1 ) $(E) "[RUN] Testing channel_arguments_test" $(Q) $(BINDIR)/$(CONFIG)/channel_arguments_test || ( echo test channel_arguments_test failed ; exit 1 ) $(E) "[RUN] Testing channel_filter_test" $(Q) $(BINDIR)/$(CONFIG)/channel_filter_test || ( echo test channel_filter_test failed ; exit 1 ) $(E) "[RUN] Testing cli_call_test" $(Q) $(BINDIR)/$(CONFIG)/cli_call_test || ( echo test cli_call_test failed ; exit 1 ) $(E) "[RUN] Testing client_crash_test" $(Q) $(BINDIR)/$(CONFIG)/client_crash_test || ( echo test client_crash_test failed ; exit 1 ) $(E) "[RUN] Testing codegen_test_full" $(Q) $(BINDIR)/$(CONFIG)/codegen_test_full || ( echo test codegen_test_full failed ; exit 1 ) $(E) "[RUN] Testing codegen_test_minimal" $(Q) $(BINDIR)/$(CONFIG)/codegen_test_minimal || ( echo test codegen_test_minimal failed ; exit 1 ) $(E) "[RUN] Testing credentials_test" $(Q) $(BINDIR)/$(CONFIG)/credentials_test || ( echo test credentials_test failed ; exit 1 ) $(E) "[RUN] Testing cxx_byte_buffer_test" $(Q) $(BINDIR)/$(CONFIG)/cxx_byte_buffer_test || ( echo test cxx_byte_buffer_test failed ; exit 1 ) $(E) "[RUN] Testing cxx_slice_test" $(Q) $(BINDIR)/$(CONFIG)/cxx_slice_test || ( echo test cxx_slice_test failed ; exit 1 ) $(E) "[RUN] Testing cxx_string_ref_test" $(Q) $(BINDIR)/$(CONFIG)/cxx_string_ref_test || ( echo test cxx_string_ref_test failed ; exit 1 ) $(E) "[RUN] Testing cxx_time_test" $(Q) $(BINDIR)/$(CONFIG)/cxx_time_test || ( echo test cxx_time_test failed ; exit 1 ) $(E) "[RUN] Testing end2end_test" $(Q) $(BINDIR)/$(CONFIG)/end2end_test || ( echo test end2end_test failed ; exit 1 ) $(E) "[RUN] Testing error_details_test" $(Q) $(BINDIR)/$(CONFIG)/error_details_test || ( echo test error_details_test failed ; exit 1 ) $(E) "[RUN] Testing filter_end2end_test" $(Q) $(BINDIR)/$(CONFIG)/filter_end2end_test || ( echo test filter_end2end_test failed ; exit 1 ) $(E) "[RUN] Testing generic_end2end_test" $(Q) $(BINDIR)/$(CONFIG)/generic_end2end_test || ( echo test generic_end2end_test failed ; exit 1 ) $(E) "[RUN] Testing golden_file_test" $(Q) $(BINDIR)/$(CONFIG)/golden_file_test || ( echo test golden_file_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_tool_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_tool_test || ( echo test grpc_tool_test failed ; exit 1 ) $(E) "[RUN] Testing grpclb_api_test" $(Q) $(BINDIR)/$(CONFIG)/grpclb_api_test || ( echo test grpclb_api_test failed ; exit 1 ) $(E) "[RUN] Testing grpclb_test" $(Q) $(BINDIR)/$(CONFIG)/grpclb_test || ( echo test grpclb_test failed ; exit 1 ) $(E) "[RUN] Testing health_service_end2end_test" $(Q) $(BINDIR)/$(CONFIG)/health_service_end2end_test || ( echo test health_service_end2end_test failed ; exit 1 ) $(E) "[RUN] Testing interop_test" $(Q) $(BINDIR)/$(CONFIG)/interop_test || ( echo test interop_test failed ; exit 1 ) $(E) "[RUN] Testing mock_test" $(Q) $(BINDIR)/$(CONFIG)/mock_test || ( echo test mock_test failed ; exit 1 ) $(E) "[RUN] Testing noop-benchmark" $(Q) $(BINDIR)/$(CONFIG)/noop-benchmark || ( echo test noop-benchmark failed ; exit 1 ) $(E) "[RUN] Testing proto_server_reflection_test" $(Q) $(BINDIR)/$(CONFIG)/proto_server_reflection_test || ( echo test proto_server_reflection_test failed ; exit 1 ) $(E) "[RUN] Testing proto_utils_test" $(Q) $(BINDIR)/$(CONFIG)/proto_utils_test || ( echo test proto_utils_test failed ; exit 1 ) $(E) "[RUN] Testing qps_openloop_test" $(Q) $(BINDIR)/$(CONFIG)/qps_openloop_test || ( echo test qps_openloop_test failed ; exit 1 ) $(E) "[RUN] Testing round_robin_end2end_test" $(Q) $(BINDIR)/$(CONFIG)/round_robin_end2end_test || ( echo test round_robin_end2end_test failed ; exit 1 ) $(E) "[RUN] Testing secure_auth_context_test" $(Q) $(BINDIR)/$(CONFIG)/secure_auth_context_test || ( echo test secure_auth_context_test failed ; exit 1 ) $(E) "[RUN] Testing secure_sync_unary_ping_pong_test" $(Q) $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test || ( echo test secure_sync_unary_ping_pong_test failed ; exit 1 ) $(E) "[RUN] Testing server_builder_plugin_test" $(Q) $(BINDIR)/$(CONFIG)/server_builder_plugin_test || ( echo test server_builder_plugin_test failed ; exit 1 ) $(E) "[RUN] Testing server_builder_test" $(Q) $(BINDIR)/$(CONFIG)/server_builder_test || ( echo test server_builder_test failed ; exit 1 ) $(E) "[RUN] Testing server_context_test_spouse_test" $(Q) $(BINDIR)/$(CONFIG)/server_context_test_spouse_test || ( echo test server_context_test_spouse_test failed ; exit 1 ) $(E) "[RUN] Testing server_crash_test" $(Q) $(BINDIR)/$(CONFIG)/server_crash_test || ( echo test server_crash_test failed ; exit 1 ) $(E) "[RUN] Testing shutdown_test" $(Q) $(BINDIR)/$(CONFIG)/shutdown_test || ( echo test shutdown_test failed ; exit 1 ) $(E) "[RUN] Testing status_test" $(Q) $(BINDIR)/$(CONFIG)/status_test || ( echo test status_test failed ; exit 1 ) $(E) "[RUN] Testing streaming_throughput_test" $(Q) $(BINDIR)/$(CONFIG)/streaming_throughput_test || ( echo test streaming_throughput_test failed ; exit 1 ) $(E) "[RUN] Testing thread_manager_test" $(Q) $(BINDIR)/$(CONFIG)/thread_manager_test || ( echo test thread_manager_test failed ; exit 1 ) $(E) "[RUN] Testing thread_stress_test" $(Q) $(BINDIR)/$(CONFIG)/thread_stress_test || ( echo test thread_stress_test failed ; exit 1 ) $(E) "[RUN] Testing writes_per_rpc_test" $(Q) $(BINDIR)/$(CONFIG)/writes_per_rpc_test || ( echo test writes_per_rpc_test failed ; exit 1 ) flaky_test_cxx: buildtests_cxx $(E) "[RUN] Testing hybrid_end2end_test" $(Q) $(BINDIR)/$(CONFIG)/hybrid_end2end_test || ( echo test hybrid_end2end_test failed ; exit 1 ) test_python: static_c $(E) "[RUN] Testing python code" $(Q) tools/run_tests/run_tests.py -lpython -c$(CONFIG) tools: tools_c tools_cxx tools_c: privatelibs_c $(BINDIR)/$(CONFIG)/gen_hpack_tables $(BINDIR)/$(CONFIG)/gen_legal_metadata_characters $(BINDIR)/$(CONFIG)/gen_percent_encoding_tables $(BINDIR)/$(CONFIG)/grpc_create_jwt $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token $(BINDIR)/$(CONFIG)/grpc_verify_jwt tools_cxx: privatelibs_cxx buildbenchmarks: privatelibs $(BINDIR)/$(CONFIG)/low_level_ping_pong_benchmark benchmarks: buildbenchmarks strip: strip-static strip-shared strip-static: strip-static_c strip-static_cxx strip-shared: strip-shared_c strip-shared_cxx # TODO(nnoble): the strip target is stripping in-place, instead # of copying files in a temporary folder. # This prevents proper debugging after running make install. strip-static_c: static_c ifeq ($(CONFIG),opt) $(E) "[STRIP] Stripping libgpr.a" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[STRIP] Stripping libgrpc.a" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc.a $(E) "[STRIP] Stripping libgrpc_cronet.a" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc_cronet.a $(E) "[STRIP] Stripping libgrpc_unsecure.a" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a endif strip-static_cxx: static_cxx ifeq ($(CONFIG),opt) $(E) "[STRIP] Stripping libgrpc++.a" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(E) "[STRIP] Stripping libgrpc++_cronet.a" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet.a $(E) "[STRIP] Stripping libgrpc++_error_details.a" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc++_error_details.a $(E) "[STRIP] Stripping libgrpc++_reflection.a" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(E) "[STRIP] Stripping libgrpc++_unsecure.a" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a endif strip-shared_c: shared_c ifeq ($(CONFIG),opt) $(E) "[STRIP] Stripping $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(E) "[STRIP] Stripping $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(E) "[STRIP] Stripping $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(E) "[STRIP] Stripping $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) endif strip-shared_cxx: shared_cxx ifeq ($(CONFIG),opt) $(E) "[STRIP] Stripping $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(E) "[STRIP] Stripping $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(E) "[STRIP] Stripping $(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(E) "[STRIP] Stripping $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(E) "[STRIP] Stripping $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) endif strip-shared_csharp: shared_csharp ifeq ($(CONFIG),opt) $(E) "[STRIP] Stripping $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP)" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) endif cache.mk:: $(E) "[MAKE] Generating $@" $(Q) echo "$(CACHE_MK)" | tr , '\n' >$@ $(LIBDIR)/$(CONFIG)/pkgconfig/grpc.pc: $(E) "[MAKE] Generating $@" $(Q) mkdir -p $(@D) $(Q) echo "$(GRPC_PC_FILE)" | tr , '\n' >$@ $(LIBDIR)/$(CONFIG)/pkgconfig/grpc_unsecure.pc: $(E) "[MAKE] Generating $@" $(Q) mkdir -p $(@D) $(Q) echo "$(GRPC_UNSECURE_PC_FILE)" | tr , '\n' >$@ $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++.pc: $(E) "[MAKE] Generating $@" $(Q) mkdir -p $(@D) $(Q) echo "$(GRPCXX_PC_FILE)" | tr , '\n' >$@ $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc: $(E) "[MAKE] Generating $@" $(Q) mkdir -p $(@D) $(Q) echo "$(GRPCXX_UNSECURE_PC_FILE)" | tr , '\n' >$@ ifeq ($(NO_PROTOC),true) $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc: protoc_dep_error $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc: protoc_dep_error else $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc: src/proto/grpc/health/v1/health.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[PROTOC] Generating protobuf CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $< $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc: src/proto/grpc/health/v1/health.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc: protoc_dep_error $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc: protoc_dep_error else $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc: src/proto/grpc/lb/v1/load_balancer.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[PROTOC] Generating protobuf CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $< $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc: src/proto/grpc/lb/v1/load_balancer.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.pb.cc: protoc_dep_error $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc: protoc_dep_error else $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.pb.cc: src/proto/grpc/reflection/v1alpha/reflection.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[PROTOC] Generating protobuf CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $< $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc: src/proto/grpc/reflection/v1alpha/reflection.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) $(GENDIR)/src/proto/grpc/status/status.pb.cc: protoc_dep_error $(GENDIR)/src/proto/grpc/status/status.grpc.pb.cc: protoc_dep_error else $(GENDIR)/src/proto/grpc/status/status.pb.cc: src/proto/grpc/status/status.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[PROTOC] Generating protobuf CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $< $(GENDIR)/src/proto/grpc/status/status.grpc.pb.cc: src/proto/grpc/status/status.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) $(GENDIR)/src/proto/grpc/testing/compiler_test.pb.cc: protoc_dep_error $(GENDIR)/src/proto/grpc/testing/compiler_test.grpc.pb.cc: protoc_dep_error else $(GENDIR)/src/proto/grpc/testing/compiler_test.pb.cc: src/proto/grpc/testing/compiler_test.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[PROTOC] Generating protobuf CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $< $(GENDIR)/src/proto/grpc/testing/compiler_test.grpc.pb.cc: src/proto/grpc/testing/compiler_test.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) $(GENDIR)/src/proto/grpc/testing/control.pb.cc: protoc_dep_error $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc: protoc_dep_error else $(GENDIR)/src/proto/grpc/testing/control.pb.cc: src/proto/grpc/testing/control.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(E) "[PROTOC] Generating protobuf CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $< $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc: src/proto/grpc/testing/control.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc: protoc_dep_error $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc: protoc_dep_error else $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc: src/proto/grpc/testing/duplicate/echo_duplicate.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(E) "[PROTOC] Generating protobuf CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $< $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc: src/proto/grpc/testing/duplicate/echo_duplicate.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) $(GENDIR)/src/proto/grpc/testing/echo.pb.cc: protoc_dep_error $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc: protoc_dep_error else $(GENDIR)/src/proto/grpc/testing/echo.pb.cc: src/proto/grpc/testing/echo.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(E) "[PROTOC] Generating protobuf CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $< $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc: src/proto/grpc/testing/echo.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc: protoc_dep_error $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc: protoc_dep_error else $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc: src/proto/grpc/testing/echo_messages.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[PROTOC] Generating protobuf CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $< $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc: src/proto/grpc/testing/echo_messages.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) $(GENDIR)/src/proto/grpc/testing/empty.pb.cc: protoc_dep_error $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc: protoc_dep_error else $(GENDIR)/src/proto/grpc/testing/empty.pb.cc: src/proto/grpc/testing/empty.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[PROTOC] Generating protobuf CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $< $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc: src/proto/grpc/testing/empty.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) $(GENDIR)/src/proto/grpc/testing/messages.pb.cc: protoc_dep_error $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc: protoc_dep_error else $(GENDIR)/src/proto/grpc/testing/messages.pb.cc: src/proto/grpc/testing/messages.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[PROTOC] Generating protobuf CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $< $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc: src/proto/grpc/testing/messages.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) $(GENDIR)/src/proto/grpc/testing/metrics.pb.cc: protoc_dep_error $(GENDIR)/src/proto/grpc/testing/metrics.grpc.pb.cc: protoc_dep_error else $(GENDIR)/src/proto/grpc/testing/metrics.pb.cc: src/proto/grpc/testing/metrics.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[PROTOC] Generating protobuf CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $< $(GENDIR)/src/proto/grpc/testing/metrics.grpc.pb.cc: src/proto/grpc/testing/metrics.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc: protoc_dep_error $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc: protoc_dep_error else $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc: src/proto/grpc/testing/payloads.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[PROTOC] Generating protobuf CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $< $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc: src/proto/grpc/testing/payloads.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) $(GENDIR)/src/proto/grpc/testing/services.pb.cc: protoc_dep_error $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc: protoc_dep_error else $(GENDIR)/src/proto/grpc/testing/services.pb.cc: src/proto/grpc/testing/services.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(E) "[PROTOC] Generating protobuf CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $< $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc: src/proto/grpc/testing/services.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) $(GENDIR)/src/proto/grpc/testing/stats.pb.cc: protoc_dep_error $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc: protoc_dep_error else $(GENDIR)/src/proto/grpc/testing/stats.pb.cc: src/proto/grpc/testing/stats.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[PROTOC] Generating protobuf CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $< $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc: src/proto/grpc/testing/stats.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) $(GENDIR)/src/proto/grpc/testing/test.pb.cc: protoc_dep_error $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc: protoc_dep_error else $(GENDIR)/src/proto/grpc/testing/test.pb.cc: src/proto/grpc/testing/test.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(E) "[PROTOC] Generating protobuf CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $< $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc: src/proto/grpc/testing/test.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(CONFIG),stapprof) src/core/profiling/stap_timers.c: $(GENDIR)/src/core/profiling/stap_probes.h ifeq ($(HAS_SYSTEMTAP),true) $(GENDIR)/src/core/profiling/stap_probes.h: src/core/profiling/stap_probes.d $(E) "[DTRACE] Compiling $<" $(Q) mkdir -p `dirname $@` $(Q) $(DTRACE) -C -h -s $< -o $@ else $(GENDIR)/src/core/profiling/stap_probes.h: systemtap_dep_error stop endif endif $(OBJDIR)/$(CONFIG)/%.o : %.c $(E) "[C] Compiling $<" $(Q) mkdir -p `dirname $@` $(Q) $(CC) $(CPPFLAGS) $(CFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $< $(OBJDIR)/$(CONFIG)/%.o : $(GENDIR)/%.pb.cc $(E) "[CXX] Compiling $<" $(Q) mkdir -p `dirname $@` $(Q) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $< $(OBJDIR)/$(CONFIG)/src/compiler/%.o : src/compiler/%.cc $(E) "[HOSTCXX] Compiling $<" $(Q) mkdir -p `dirname $@` $(Q) $(HOST_CXX) $(HOST_CXXFLAGS) $(HOST_CPPFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $< $(OBJDIR)/$(CONFIG)/%.o : %.cc $(E) "[CXX] Compiling $<" $(Q) mkdir -p `dirname $@` $(Q) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $< install: install_c install_cxx install-plugins install-certs install_c: install-headers_c install-static_c install-shared_c install_cxx: install-headers_cxx install-static_cxx install-shared_cxx install_csharp: install-shared_csharp install_c install_grpc_csharp_ext: install_csharp install-headers: install-headers_c install-headers_cxx install-headers_c: $(E) "[INSTALL] Installing public C headers" $(Q) $(foreach h, $(PUBLIC_HEADERS_C), $(INSTALL) -d $(prefix)/$(dir $(h)) && ) exit 0 || exit 1 $(Q) $(foreach h, $(PUBLIC_HEADERS_C), $(INSTALL) $(h) $(prefix)/$(h) && ) exit 0 || exit 1 install-headers_cxx: $(E) "[INSTALL] Installing public C++ headers" $(Q) $(foreach h, $(PUBLIC_HEADERS_CXX), $(INSTALL) -d $(prefix)/$(dir $(h)) && ) exit 0 || exit 1 $(Q) $(foreach h, $(PUBLIC_HEADERS_CXX), $(INSTALL) $(h) $(prefix)/$(h) && ) exit 0 || exit 1 install-static: install-static_c install-static_cxx install-static_c: static_c strip-static_c install-pkg-config_c $(E) "[INSTALL] Installing libgpr.a" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgpr.a $(prefix)/lib/libgpr.a $(E) "[INSTALL] Installing libgrpc.a" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc.a $(prefix)/lib/libgrpc.a $(E) "[INSTALL] Installing libgrpc_cronet.a" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_cronet.a $(prefix)/lib/libgrpc_cronet.a $(E) "[INSTALL] Installing libgrpc_unsecure.a" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(prefix)/lib/libgrpc_unsecure.a install-static_cxx: static_cxx strip-static_cxx install-pkg-config_cxx $(E) "[INSTALL] Installing libgrpc++.a" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(prefix)/lib/libgrpc++.a $(E) "[INSTALL] Installing libgrpc++_cronet.a" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet.a $(prefix)/lib/libgrpc++_cronet.a $(E) "[INSTALL] Installing libgrpc++_error_details.a" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_error_details.a $(prefix)/lib/libgrpc++_error_details.a $(E) "[INSTALL] Installing libgrpc++_reflection.a" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(prefix)/lib/libgrpc++_reflection.a $(E) "[INSTALL] Installing libgrpc++_unsecure.a" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(prefix)/lib/libgrpc++_unsecure.a install-shared_c: shared_c strip-shared_c install-pkg-config_c $(E) "[INSTALL] Installing $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libgpr.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgpr.so.3 $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgpr.so endif $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libgrpc.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc.so.3 $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc.so endif $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libgrpc_cronet.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_cronet.so.3 $(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_cronet.so endif $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libgrpc_unsecure.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_unsecure.so.3 $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_unsecure.so endif ifneq ($(SYSTEM),MINGW32) ifneq ($(SYSTEM),Darwin) $(Q) ldconfig || true endif endif install-shared_cxx: shared_cxx strip-shared_cxx install-shared_c install-pkg-config_cxx $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++.so.3 $(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++.so endif $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++_cronet.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_cronet.so.3 $(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_cronet.so endif $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_error_details$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++_error_details.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_error_details.so.3 $(Q) ln -sf $(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_error_details.so endif $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++_reflection.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_reflection.so.3 $(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_reflection.so endif $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++_unsecure.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_unsecure.so.3 $(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_unsecure.so endif ifneq ($(SYSTEM),MINGW32) ifneq ($(SYSTEM),Darwin) $(Q) ldconfig || true endif endif install-shared_csharp: shared_csharp strip-shared_csharp $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP)" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP)-dll.a $(prefix)/lib/libgrpc_csharp_ext.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/libgrpc_csharp_ext.so.3 $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/libgrpc_csharp_ext.so endif ifneq ($(SYSTEM),MINGW32) ifneq ($(SYSTEM),Darwin) $(Q) ldconfig || true endif endif install-plugins: $(PROTOC_PLUGINS) $(E) "[INSTALL] Installing grpc protoc plugins" $(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(prefix)/bin/grpc_cpp_plugin $(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_csharp_plugin $(prefix)/bin/grpc_csharp_plugin $(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_node_plugin $(prefix)/bin/grpc_node_plugin $(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin $(prefix)/bin/grpc_objective_c_plugin $(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_php_plugin $(prefix)/bin/grpc_php_plugin $(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_python_plugin $(prefix)/bin/grpc_python_plugin $(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_ruby_plugin $(prefix)/bin/grpc_ruby_plugin install-pkg-config_c: pc_c pc_c_unsecure $(E) "[INSTALL] Installing C pkg-config files" $(Q) $(INSTALL) -d $(prefix)/lib/pkgconfig $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/pkgconfig/grpc.pc $(prefix)/lib/pkgconfig/grpc.pc $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/pkgconfig/grpc_unsecure.pc $(prefix)/lib/pkgconfig/grpc_unsecure.pc install-pkg-config_cxx: pc_cxx pc_cxx_unsecure $(E) "[INSTALL] Installing C++ pkg-config files" $(Q) $(INSTALL) -d $(prefix)/lib/pkgconfig $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++.pc $(prefix)/lib/pkgconfig/grpc++.pc $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc $(prefix)/lib/pkgconfig/grpc++_unsecure.pc install-certs: etc/roots.pem $(E) "[INSTALL] Installing root certificates" $(Q) $(INSTALL) -d $(prefix)/share/grpc $(Q) $(INSTALL) etc/roots.pem $(prefix)/share/grpc/roots.pem clean: $(E) "[CLEAN] Cleaning build directories." $(Q) $(RM) -rf $(OBJDIR) $(LIBDIR) $(BINDIR) $(GENDIR) cache.mk # The various libraries LIBGPR_SRC = \ src/core/lib/profiling/basic_timers.c \ src/core/lib/profiling/stap_timers.c \ src/core/lib/support/alloc.c \ src/core/lib/support/arena.c \ src/core/lib/support/atm.c \ src/core/lib/support/avl.c \ src/core/lib/support/backoff.c \ src/core/lib/support/cmdline.c \ src/core/lib/support/cpu_iphone.c \ src/core/lib/support/cpu_linux.c \ src/core/lib/support/cpu_posix.c \ src/core/lib/support/cpu_windows.c \ src/core/lib/support/env_linux.c \ src/core/lib/support/env_posix.c \ src/core/lib/support/env_windows.c \ src/core/lib/support/histogram.c \ src/core/lib/support/host_port.c \ src/core/lib/support/log.c \ src/core/lib/support/log_android.c \ src/core/lib/support/log_linux.c \ src/core/lib/support/log_posix.c \ src/core/lib/support/log_windows.c \ src/core/lib/support/mpscq.c \ src/core/lib/support/murmur_hash.c \ src/core/lib/support/stack_lockfree.c \ src/core/lib/support/string.c \ src/core/lib/support/string_posix.c \ src/core/lib/support/string_util_windows.c \ src/core/lib/support/string_windows.c \ src/core/lib/support/subprocess_posix.c \ src/core/lib/support/subprocess_windows.c \ src/core/lib/support/sync.c \ src/core/lib/support/sync_posix.c \ src/core/lib/support/sync_windows.c \ src/core/lib/support/thd.c \ src/core/lib/support/thd_posix.c \ src/core/lib/support/thd_windows.c \ src/core/lib/support/time.c \ src/core/lib/support/time_posix.c \ src/core/lib/support/time_precise.c \ src/core/lib/support/time_windows.c \ src/core/lib/support/tls_pthread.c \ src/core/lib/support/tmpfile_msys.c \ src/core/lib/support/tmpfile_posix.c \ src/core/lib/support/tmpfile_windows.c \ src/core/lib/support/wrap_memcpy.c \ PUBLIC_HEADERS_C += \ include/grpc/support/alloc.h \ include/grpc/support/atm.h \ include/grpc/support/atm_gcc_atomic.h \ include/grpc/support/atm_gcc_sync.h \ include/grpc/support/atm_windows.h \ include/grpc/support/avl.h \ include/grpc/support/cmdline.h \ include/grpc/support/cpu.h \ include/grpc/support/histogram.h \ include/grpc/support/host_port.h \ include/grpc/support/log.h \ include/grpc/support/log_windows.h \ include/grpc/support/port_platform.h \ include/grpc/support/string_util.h \ include/grpc/support/subprocess.h \ include/grpc/support/sync.h \ include/grpc/support/sync_generic.h \ include/grpc/support/sync_posix.h \ include/grpc/support/sync_windows.h \ include/grpc/support/thd.h \ include/grpc/support/time.h \ include/grpc/support/tls.h \ include/grpc/support/tls_gcc.h \ include/grpc/support/tls_msvc.h \ include/grpc/support/tls_pthread.h \ include/grpc/support/useful.h \ include/grpc/impl/codegen/atm.h \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/sync.h \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ LIBGPR_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGPR_SRC)))) $(LIBDIR)/$(CONFIG)/libgpr.a: $(ZLIB_DEP) $(CARES_DEP) $(LIBGPR_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgpr.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBGPR_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgpr.a endif ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGPR_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBS) else $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGPR_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBS) else $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgpr.so.3 -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBS) $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so.3 $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so endif endif ifneq ($(NO_DEPS),true) -include $(LIBGPR_OBJS:.o=.dep) endif LIBGPR_TEST_UTIL_SRC = \ test/core/util/test_config.c \ PUBLIC_HEADERS_C += \ LIBGPR_TEST_UTIL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGPR_TEST_UTIL_SRC)))) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a: $(ZLIB_DEP) $(CARES_DEP) $(LIBGPR_TEST_UTIL_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBGPR_TEST_UTIL_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgpr_test_util.a endif ifneq ($(NO_DEPS),true) -include $(LIBGPR_TEST_UTIL_OBJS:.o=.dep) endif LIBGRPC_SRC = \ src/core/lib/surface/init.c \ src/core/lib/channel/channel_args.c \ src/core/lib/channel/channel_stack.c \ src/core/lib/channel/channel_stack_builder.c \ src/core/lib/channel/compress_filter.c \ src/core/lib/channel/connected_channel.c \ src/core/lib/channel/deadline_filter.c \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/handshaker_factory.c \ src/core/lib/channel/handshaker_registry.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ src/core/lib/channel/message_size_filter.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ src/core/lib/debug/trace.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_uv.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ src/core/lib/iomgr/executor.c \ src/core/lib/iomgr/iocp_windows.c \ src/core/lib/iomgr/iomgr.c \ src/core/lib/iomgr/iomgr_posix.c \ src/core/lib/iomgr/iomgr_uv.c \ src/core/lib/iomgr/iomgr_windows.c \ src/core/lib/iomgr/load_file.c \ src/core/lib/iomgr/lockfree_event.c \ src/core/lib/iomgr/network_status_tracker.c \ src/core/lib/iomgr/polling_entity.c \ src/core/lib/iomgr/pollset_set_uv.c \ src/core/lib/iomgr/pollset_set_windows.c \ src/core/lib/iomgr/pollset_uv.c \ src/core/lib/iomgr/pollset_windows.c \ src/core/lib/iomgr/resolve_address_posix.c \ src/core/lib/iomgr/resolve_address_uv.c \ src/core/lib/iomgr/resolve_address_windows.c \ src/core/lib/iomgr/resource_quota.c \ src/core/lib/iomgr/sockaddr_utils.c \ src/core/lib/iomgr/socket_factory_posix.c \ src/core/lib/iomgr/socket_mutator.c \ src/core/lib/iomgr/socket_utils_common_posix.c \ src/core/lib/iomgr/socket_utils_linux.c \ src/core/lib/iomgr/socket_utils_posix.c \ src/core/lib/iomgr/socket_utils_uv.c \ src/core/lib/iomgr/socket_utils_windows.c \ src/core/lib/iomgr/socket_windows.c \ src/core/lib/iomgr/tcp_client_posix.c \ src/core/lib/iomgr/tcp_client_uv.c \ src/core/lib/iomgr/tcp_client_windows.c \ src/core/lib/iomgr/tcp_posix.c \ src/core/lib/iomgr/tcp_server_posix.c \ src/core/lib/iomgr/tcp_server_utils_posix_common.c \ src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ src/core/lib/iomgr/tcp_server_windows.c \ src/core/lib/iomgr/tcp_uv.c \ src/core/lib/iomgr/tcp_windows.c \ src/core/lib/iomgr/time_averaged_stats.c \ src/core/lib/iomgr/timer_generic.c \ src/core/lib/iomgr/timer_heap.c \ src/core/lib/iomgr/timer_uv.c \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ src/core/lib/iomgr/wakeup_fd_posix.c \ src/core/lib/iomgr/workqueue_uv.c \ src/core/lib/iomgr/workqueue_windows.c \ src/core/lib/json/json.c \ src/core/lib/json/json_reader.c \ src/core/lib/json/json_string.c \ src/core/lib/json/json_writer.c \ src/core/lib/slice/b64.c \ src/core/lib/slice/percent_encoding.c \ src/core/lib/slice/slice.c \ src/core/lib/slice/slice_buffer.c \ src/core/lib/slice/slice_hash_table.c \ src/core/lib/slice/slice_intern.c \ src/core/lib/slice/slice_string_helpers.c \ src/core/lib/surface/alarm.c \ src/core/lib/surface/api_trace.c \ src/core/lib/surface/byte_buffer.c \ src/core/lib/surface/byte_buffer_reader.c \ src/core/lib/surface/call.c \ src/core/lib/surface/call_details.c \ src/core/lib/surface/call_log_batch.c \ src/core/lib/surface/channel.c \ src/core/lib/surface/channel_init.c \ src/core/lib/surface/channel_ping.c \ src/core/lib/surface/channel_stack_type.c \ src/core/lib/surface/completion_queue.c \ src/core/lib/surface/completion_queue_factory.c \ src/core/lib/surface/event_string.c \ src/core/lib/surface/lame_client.c \ src/core/lib/surface/metadata_array.c \ src/core/lib/surface/server.c \ src/core/lib/surface/validate_metadata.c \ src/core/lib/surface/version.c \ src/core/lib/transport/bdp_estimator.c \ src/core/lib/transport/byte_stream.c \ src/core/lib/transport/connectivity_state.c \ src/core/lib/transport/error_utils.c \ src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/pid_controller.c \ src/core/lib/transport/service_config.c \ src/core/lib/transport/static_metadata.c \ src/core/lib/transport/status_conversion.c \ src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/transport.c \ src/core/lib/transport/transport_op_string.c \ src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c \ src/core/ext/transport/chttp2/transport/bin_decoder.c \ src/core/ext/transport/chttp2/transport/bin_encoder.c \ src/core/ext/transport/chttp2/transport/chttp2_plugin.c \ src/core/ext/transport/chttp2/transport/chttp2_transport.c \ src/core/ext/transport/chttp2/transport/frame_data.c \ src/core/ext/transport/chttp2/transport/frame_goaway.c \ src/core/ext/transport/chttp2/transport/frame_ping.c \ src/core/ext/transport/chttp2/transport/frame_rst_stream.c \ src/core/ext/transport/chttp2/transport/frame_settings.c \ src/core/ext/transport/chttp2/transport/frame_window_update.c \ src/core/ext/transport/chttp2/transport/hpack_encoder.c \ src/core/ext/transport/chttp2/transport/hpack_parser.c \ src/core/ext/transport/chttp2/transport/hpack_table.c \ src/core/ext/transport/chttp2/transport/http2_settings.c \ src/core/ext/transport/chttp2/transport/huffsyms.c \ src/core/ext/transport/chttp2/transport/incoming_metadata.c \ src/core/ext/transport/chttp2/transport/parsing.c \ src/core/ext/transport/chttp2/transport/stream_lists.c \ src/core/ext/transport/chttp2/transport/stream_map.c \ src/core/ext/transport/chttp2/transport/varint.c \ src/core/ext/transport/chttp2/transport/writing.c \ src/core/ext/transport/chttp2/alpn/alpn.c \ src/core/lib/http/httpcli_security_connector.c \ src/core/lib/security/context/security_context.c \ src/core/lib/security/credentials/composite/composite_credentials.c \ src/core/lib/security/credentials/credentials.c \ src/core/lib/security/credentials/credentials_metadata.c \ src/core/lib/security/credentials/fake/fake_credentials.c \ src/core/lib/security/credentials/google_default/credentials_generic.c \ src/core/lib/security/credentials/google_default/google_default_credentials.c \ src/core/lib/security/credentials/iam/iam_credentials.c \ src/core/lib/security/credentials/jwt/json_token.c \ src/core/lib/security/credentials/jwt/jwt_credentials.c \ src/core/lib/security/credentials/jwt/jwt_verifier.c \ src/core/lib/security/credentials/oauth2/oauth2_credentials.c \ src/core/lib/security/credentials/plugin/plugin_credentials.c \ src/core/lib/security/credentials/ssl/ssl_credentials.c \ src/core/lib/security/transport/client_auth_filter.c \ src/core/lib/security/transport/lb_targets_info.c \ src/core/lib/security/transport/secure_endpoint.c \ src/core/lib/security/transport/security_connector.c \ src/core/lib/security/transport/security_handshaker.c \ src/core/lib/security/transport/server_auth_filter.c \ src/core/lib/security/transport/tsi_error.c \ src/core/lib/security/util/json_util.c \ src/core/lib/surface/init_secure.c \ src/core/tsi/fake_transport_security.c \ src/core/tsi/ssl_transport_security.c \ src/core/tsi/transport_security.c \ src/core/ext/transport/chttp2/server/chttp2_server.c \ src/core/ext/transport/chttp2/client/secure/secure_channel_create.c \ src/core/ext/filters/client_channel/channel_connectivity.c \ src/core/ext/filters/client_channel/client_channel.c \ src/core/ext/filters/client_channel/client_channel_factory.c \ src/core/ext/filters/client_channel/client_channel_plugin.c \ src/core/ext/filters/client_channel/connector.c \ src/core/ext/filters/client_channel/http_connect_handshaker.c \ src/core/ext/filters/client_channel/http_proxy.c \ src/core/ext/filters/client_channel/lb_policy.c \ src/core/ext/filters/client_channel/lb_policy_factory.c \ src/core/ext/filters/client_channel/lb_policy_registry.c \ src/core/ext/filters/client_channel/parse_address.c \ src/core/ext/filters/client_channel/proxy_mapper.c \ src/core/ext/filters/client_channel/proxy_mapper_registry.c \ src/core/ext/filters/client_channel/resolver.c \ src/core/ext/filters/client_channel/resolver_factory.c \ src/core/ext/filters/client_channel/resolver_registry.c \ src/core/ext/filters/client_channel/retry_throttle.c \ src/core/ext/filters/client_channel/subchannel.c \ src/core/ext/filters/client_channel/subchannel_index.c \ src/core/ext/filters/client_channel/uri_parser.c \ src/core/ext/transport/chttp2/client/chttp2_connector.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ third_party/nanopb/pb_decode.c \ third_party/nanopb/pb_encode.c \ src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c \ src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c \ src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c \ src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.c \ src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c \ src/core/ext/filters/load_reporting/load_reporting.c \ src/core/ext/filters/load_reporting/load_reporting_filter.c \ src/core/ext/census/base_resources.c \ src/core/ext/census/context.c \ src/core/ext/census/gen/census.pb.c \ src/core/ext/census/gen/trace_context.pb.c \ src/core/ext/census/grpc_context.c \ src/core/ext/census/grpc_filter.c \ src/core/ext/census/grpc_plugin.c \ src/core/ext/census/initialize.c \ src/core/ext/census/mlog.c \ src/core/ext/census/operation.c \ src/core/ext/census/placeholders.c \ src/core/ext/census/resource.c \ src/core/ext/census/trace_context.c \ src/core/ext/census/tracing.c \ src/core/ext/filters/max_age/max_age_filter.c \ src/core/plugin_registry/grpc_plugin_registry.c \ PUBLIC_HEADERS_C += \ include/grpc/byte_buffer.h \ include/grpc/byte_buffer_reader.h \ include/grpc/compression.h \ include/grpc/grpc.h \ include/grpc/grpc_posix.h \ include/grpc/grpc_security_constants.h \ include/grpc/load_reporting.h \ include/grpc/slice.h \ include/grpc/slice_buffer.h \ include/grpc/status.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/slice.h \ include/grpc/impl/codegen/status.h \ include/grpc/impl/codegen/atm.h \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/sync.h \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ include/grpc/grpc_security.h \ include/grpc/census.h \ LIBGRPC_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libgrpc.a: openssl_dep_error $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): openssl_dep_error else $(LIBDIR)/$(CONFIG)/libgrpc.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(LIBGRPC_OBJS) $(LIBGPR_OBJS) $(ZLIB_MERGE_OBJS) $(CARES_MERGE_OBJS) $(OPENSSL_MERGE_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBGRPC_OBJS) $(LIBGPR_OBJS) $(ZLIB_MERGE_OBJS) $(CARES_MERGE_OBJS) $(OPENSSL_MERGE_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc.a endif ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBS) else $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBS) else $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBS) $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so.3 $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so endif endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBGRPC_OBJS:.o=.dep) endif endif LIBGRPC_CRONET_SRC = \ src/core/lib/surface/init.c \ src/core/lib/channel/channel_args.c \ src/core/lib/channel/channel_stack.c \ src/core/lib/channel/channel_stack_builder.c \ src/core/lib/channel/compress_filter.c \ src/core/lib/channel/connected_channel.c \ src/core/lib/channel/deadline_filter.c \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/handshaker_factory.c \ src/core/lib/channel/handshaker_registry.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ src/core/lib/channel/message_size_filter.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ src/core/lib/debug/trace.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_uv.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ src/core/lib/iomgr/executor.c \ src/core/lib/iomgr/iocp_windows.c \ src/core/lib/iomgr/iomgr.c \ src/core/lib/iomgr/iomgr_posix.c \ src/core/lib/iomgr/iomgr_uv.c \ src/core/lib/iomgr/iomgr_windows.c \ src/core/lib/iomgr/load_file.c \ src/core/lib/iomgr/lockfree_event.c \ src/core/lib/iomgr/network_status_tracker.c \ src/core/lib/iomgr/polling_entity.c \ src/core/lib/iomgr/pollset_set_uv.c \ src/core/lib/iomgr/pollset_set_windows.c \ src/core/lib/iomgr/pollset_uv.c \ src/core/lib/iomgr/pollset_windows.c \ src/core/lib/iomgr/resolve_address_posix.c \ src/core/lib/iomgr/resolve_address_uv.c \ src/core/lib/iomgr/resolve_address_windows.c \ src/core/lib/iomgr/resource_quota.c \ src/core/lib/iomgr/sockaddr_utils.c \ src/core/lib/iomgr/socket_factory_posix.c \ src/core/lib/iomgr/socket_mutator.c \ src/core/lib/iomgr/socket_utils_common_posix.c \ src/core/lib/iomgr/socket_utils_linux.c \ src/core/lib/iomgr/socket_utils_posix.c \ src/core/lib/iomgr/socket_utils_uv.c \ src/core/lib/iomgr/socket_utils_windows.c \ src/core/lib/iomgr/socket_windows.c \ src/core/lib/iomgr/tcp_client_posix.c \ src/core/lib/iomgr/tcp_client_uv.c \ src/core/lib/iomgr/tcp_client_windows.c \ src/core/lib/iomgr/tcp_posix.c \ src/core/lib/iomgr/tcp_server_posix.c \ src/core/lib/iomgr/tcp_server_utils_posix_common.c \ src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ src/core/lib/iomgr/tcp_server_windows.c \ src/core/lib/iomgr/tcp_uv.c \ src/core/lib/iomgr/tcp_windows.c \ src/core/lib/iomgr/time_averaged_stats.c \ src/core/lib/iomgr/timer_generic.c \ src/core/lib/iomgr/timer_heap.c \ src/core/lib/iomgr/timer_uv.c \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ src/core/lib/iomgr/wakeup_fd_posix.c \ src/core/lib/iomgr/workqueue_uv.c \ src/core/lib/iomgr/workqueue_windows.c \ src/core/lib/json/json.c \ src/core/lib/json/json_reader.c \ src/core/lib/json/json_string.c \ src/core/lib/json/json_writer.c \ src/core/lib/slice/b64.c \ src/core/lib/slice/percent_encoding.c \ src/core/lib/slice/slice.c \ src/core/lib/slice/slice_buffer.c \ src/core/lib/slice/slice_hash_table.c \ src/core/lib/slice/slice_intern.c \ src/core/lib/slice/slice_string_helpers.c \ src/core/lib/surface/alarm.c \ src/core/lib/surface/api_trace.c \ src/core/lib/surface/byte_buffer.c \ src/core/lib/surface/byte_buffer_reader.c \ src/core/lib/surface/call.c \ src/core/lib/surface/call_details.c \ src/core/lib/surface/call_log_batch.c \ src/core/lib/surface/channel.c \ src/core/lib/surface/channel_init.c \ src/core/lib/surface/channel_ping.c \ src/core/lib/surface/channel_stack_type.c \ src/core/lib/surface/completion_queue.c \ src/core/lib/surface/completion_queue_factory.c \ src/core/lib/surface/event_string.c \ src/core/lib/surface/lame_client.c \ src/core/lib/surface/metadata_array.c \ src/core/lib/surface/server.c \ src/core/lib/surface/validate_metadata.c \ src/core/lib/surface/version.c \ src/core/lib/transport/bdp_estimator.c \ src/core/lib/transport/byte_stream.c \ src/core/lib/transport/connectivity_state.c \ src/core/lib/transport/error_utils.c \ src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/pid_controller.c \ src/core/lib/transport/service_config.c \ src/core/lib/transport/static_metadata.c \ src/core/lib/transport/status_conversion.c \ src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/transport.c \ src/core/lib/transport/transport_op_string.c \ src/core/ext/transport/cronet/client/secure/cronet_channel_create.c \ src/core/ext/transport/cronet/transport/cronet_api_dummy.c \ src/core/ext/transport/cronet/transport/cronet_transport.c \ src/core/ext/transport/chttp2/client/secure/secure_channel_create.c \ src/core/ext/transport/chttp2/transport/bin_decoder.c \ src/core/ext/transport/chttp2/transport/bin_encoder.c \ src/core/ext/transport/chttp2/transport/chttp2_plugin.c \ src/core/ext/transport/chttp2/transport/chttp2_transport.c \ src/core/ext/transport/chttp2/transport/frame_data.c \ src/core/ext/transport/chttp2/transport/frame_goaway.c \ src/core/ext/transport/chttp2/transport/frame_ping.c \ src/core/ext/transport/chttp2/transport/frame_rst_stream.c \ src/core/ext/transport/chttp2/transport/frame_settings.c \ src/core/ext/transport/chttp2/transport/frame_window_update.c \ src/core/ext/transport/chttp2/transport/hpack_encoder.c \ src/core/ext/transport/chttp2/transport/hpack_parser.c \ src/core/ext/transport/chttp2/transport/hpack_table.c \ src/core/ext/transport/chttp2/transport/http2_settings.c \ src/core/ext/transport/chttp2/transport/huffsyms.c \ src/core/ext/transport/chttp2/transport/incoming_metadata.c \ src/core/ext/transport/chttp2/transport/parsing.c \ src/core/ext/transport/chttp2/transport/stream_lists.c \ src/core/ext/transport/chttp2/transport/stream_map.c \ src/core/ext/transport/chttp2/transport/varint.c \ src/core/ext/transport/chttp2/transport/writing.c \ src/core/ext/transport/chttp2/alpn/alpn.c \ src/core/ext/filters/client_channel/channel_connectivity.c \ src/core/ext/filters/client_channel/client_channel.c \ src/core/ext/filters/client_channel/client_channel_factory.c \ src/core/ext/filters/client_channel/client_channel_plugin.c \ src/core/ext/filters/client_channel/connector.c \ src/core/ext/filters/client_channel/http_connect_handshaker.c \ src/core/ext/filters/client_channel/http_proxy.c \ src/core/ext/filters/client_channel/lb_policy.c \ src/core/ext/filters/client_channel/lb_policy_factory.c \ src/core/ext/filters/client_channel/lb_policy_registry.c \ src/core/ext/filters/client_channel/parse_address.c \ src/core/ext/filters/client_channel/proxy_mapper.c \ src/core/ext/filters/client_channel/proxy_mapper_registry.c \ src/core/ext/filters/client_channel/resolver.c \ src/core/ext/filters/client_channel/resolver_factory.c \ src/core/ext/filters/client_channel/resolver_registry.c \ src/core/ext/filters/client_channel/retry_throttle.c \ src/core/ext/filters/client_channel/subchannel.c \ src/core/ext/filters/client_channel/subchannel_index.c \ src/core/ext/filters/client_channel/uri_parser.c \ src/core/lib/http/httpcli_security_connector.c \ src/core/lib/security/context/security_context.c \ src/core/lib/security/credentials/composite/composite_credentials.c \ src/core/lib/security/credentials/credentials.c \ src/core/lib/security/credentials/credentials_metadata.c \ src/core/lib/security/credentials/fake/fake_credentials.c \ src/core/lib/security/credentials/google_default/credentials_generic.c \ src/core/lib/security/credentials/google_default/google_default_credentials.c \ src/core/lib/security/credentials/iam/iam_credentials.c \ src/core/lib/security/credentials/jwt/json_token.c \ src/core/lib/security/credentials/jwt/jwt_credentials.c \ src/core/lib/security/credentials/jwt/jwt_verifier.c \ src/core/lib/security/credentials/oauth2/oauth2_credentials.c \ src/core/lib/security/credentials/plugin/plugin_credentials.c \ src/core/lib/security/credentials/ssl/ssl_credentials.c \ src/core/lib/security/transport/client_auth_filter.c \ src/core/lib/security/transport/lb_targets_info.c \ src/core/lib/security/transport/secure_endpoint.c \ src/core/lib/security/transport/security_connector.c \ src/core/lib/security/transport/security_handshaker.c \ src/core/lib/security/transport/server_auth_filter.c \ src/core/lib/security/transport/tsi_error.c \ src/core/lib/security/util/json_util.c \ src/core/lib/surface/init_secure.c \ src/core/tsi/fake_transport_security.c \ src/core/tsi/ssl_transport_security.c \ src/core/tsi/transport_security.c \ src/core/ext/transport/chttp2/client/chttp2_connector.c \ src/core/ext/filters/load_reporting/load_reporting.c \ src/core/ext/filters/load_reporting/load_reporting_filter.c \ src/core/plugin_registry/grpc_cronet_plugin_registry.c \ PUBLIC_HEADERS_C += \ include/grpc/byte_buffer.h \ include/grpc/byte_buffer_reader.h \ include/grpc/compression.h \ include/grpc/grpc.h \ include/grpc/grpc_posix.h \ include/grpc/grpc_security_constants.h \ include/grpc/load_reporting.h \ include/grpc/slice.h \ include/grpc/slice_buffer.h \ include/grpc/status.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/slice.h \ include/grpc/impl/codegen/status.h \ include/grpc/impl/codegen/atm.h \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/sync.h \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ include/grpc/grpc_cronet.h \ include/grpc/grpc_security.h \ LIBGRPC_CRONET_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_CRONET_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libgrpc_cronet.a: openssl_dep_error $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): openssl_dep_error else $(LIBDIR)/$(CONFIG)/libgrpc_cronet.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(LIBGRPC_CRONET_OBJS) $(LIBGPR_OBJS) $(ZLIB_MERGE_OBJS) $(CARES_MERGE_OBJS) $(OPENSSL_MERGE_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc_cronet.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc_cronet.a $(LIBGRPC_CRONET_OBJS) $(LIBGPR_OBJS) $(ZLIB_MERGE_OBJS) $(CARES_MERGE_OBJS) $(OPENSSL_MERGE_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc_cronet.a endif ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_CRONET_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBS) else $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_CRONET_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBS) else $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_cronet.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBS) $(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).so.3 $(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).so endif endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBGRPC_CRONET_OBJS:.o=.dep) endif endif LIBGRPC_TEST_UTIL_SRC = \ test/core/end2end/data/client_certs.c \ test/core/end2end/data/server1_cert.c \ test/core/end2end/data/server1_key.c \ test/core/end2end/data/test_root_cert.c \ test/core/security/oauth2_utils.c \ test/core/end2end/cq_verifier.c \ test/core/end2end/fake_resolver.c \ test/core/end2end/fixtures/http_proxy_fixture.c \ test/core/end2end/fixtures/proxy.c \ test/core/iomgr/endpoint_tests.c \ test/core/util/debugger_macros.c \ test/core/util/grpc_profiler.c \ test/core/util/memory_counters.c \ test/core/util/mock_endpoint.c \ test/core/util/parse_hexstring.c \ test/core/util/passthru_endpoint.c \ test/core/util/port.c \ test/core/util/port_server_client.c \ test/core/util/slice_splitter.c \ test/core/util/trickle_endpoint.c \ src/core/lib/channel/channel_args.c \ src/core/lib/channel/channel_stack.c \ src/core/lib/channel/channel_stack_builder.c \ src/core/lib/channel/compress_filter.c \ src/core/lib/channel/connected_channel.c \ src/core/lib/channel/deadline_filter.c \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/handshaker_factory.c \ src/core/lib/channel/handshaker_registry.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ src/core/lib/channel/message_size_filter.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ src/core/lib/debug/trace.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_uv.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ src/core/lib/iomgr/executor.c \ src/core/lib/iomgr/iocp_windows.c \ src/core/lib/iomgr/iomgr.c \ src/core/lib/iomgr/iomgr_posix.c \ src/core/lib/iomgr/iomgr_uv.c \ src/core/lib/iomgr/iomgr_windows.c \ src/core/lib/iomgr/load_file.c \ src/core/lib/iomgr/lockfree_event.c \ src/core/lib/iomgr/network_status_tracker.c \ src/core/lib/iomgr/polling_entity.c \ src/core/lib/iomgr/pollset_set_uv.c \ src/core/lib/iomgr/pollset_set_windows.c \ src/core/lib/iomgr/pollset_uv.c \ src/core/lib/iomgr/pollset_windows.c \ src/core/lib/iomgr/resolve_address_posix.c \ src/core/lib/iomgr/resolve_address_uv.c \ src/core/lib/iomgr/resolve_address_windows.c \ src/core/lib/iomgr/resource_quota.c \ src/core/lib/iomgr/sockaddr_utils.c \ src/core/lib/iomgr/socket_factory_posix.c \ src/core/lib/iomgr/socket_mutator.c \ src/core/lib/iomgr/socket_utils_common_posix.c \ src/core/lib/iomgr/socket_utils_linux.c \ src/core/lib/iomgr/socket_utils_posix.c \ src/core/lib/iomgr/socket_utils_uv.c \ src/core/lib/iomgr/socket_utils_windows.c \ src/core/lib/iomgr/socket_windows.c \ src/core/lib/iomgr/tcp_client_posix.c \ src/core/lib/iomgr/tcp_client_uv.c \ src/core/lib/iomgr/tcp_client_windows.c \ src/core/lib/iomgr/tcp_posix.c \ src/core/lib/iomgr/tcp_server_posix.c \ src/core/lib/iomgr/tcp_server_utils_posix_common.c \ src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ src/core/lib/iomgr/tcp_server_windows.c \ src/core/lib/iomgr/tcp_uv.c \ src/core/lib/iomgr/tcp_windows.c \ src/core/lib/iomgr/time_averaged_stats.c \ src/core/lib/iomgr/timer_generic.c \ src/core/lib/iomgr/timer_heap.c \ src/core/lib/iomgr/timer_uv.c \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ src/core/lib/iomgr/wakeup_fd_posix.c \ src/core/lib/iomgr/workqueue_uv.c \ src/core/lib/iomgr/workqueue_windows.c \ src/core/lib/json/json.c \ src/core/lib/json/json_reader.c \ src/core/lib/json/json_string.c \ src/core/lib/json/json_writer.c \ src/core/lib/slice/b64.c \ src/core/lib/slice/percent_encoding.c \ src/core/lib/slice/slice.c \ src/core/lib/slice/slice_buffer.c \ src/core/lib/slice/slice_hash_table.c \ src/core/lib/slice/slice_intern.c \ src/core/lib/slice/slice_string_helpers.c \ src/core/lib/surface/alarm.c \ src/core/lib/surface/api_trace.c \ src/core/lib/surface/byte_buffer.c \ src/core/lib/surface/byte_buffer_reader.c \ src/core/lib/surface/call.c \ src/core/lib/surface/call_details.c \ src/core/lib/surface/call_log_batch.c \ src/core/lib/surface/channel.c \ src/core/lib/surface/channel_init.c \ src/core/lib/surface/channel_ping.c \ src/core/lib/surface/channel_stack_type.c \ src/core/lib/surface/completion_queue.c \ src/core/lib/surface/completion_queue_factory.c \ src/core/lib/surface/event_string.c \ src/core/lib/surface/lame_client.c \ src/core/lib/surface/metadata_array.c \ src/core/lib/surface/server.c \ src/core/lib/surface/validate_metadata.c \ src/core/lib/surface/version.c \ src/core/lib/transport/bdp_estimator.c \ src/core/lib/transport/byte_stream.c \ src/core/lib/transport/connectivity_state.c \ src/core/lib/transport/error_utils.c \ src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/pid_controller.c \ src/core/lib/transport/service_config.c \ src/core/lib/transport/static_metadata.c \ src/core/lib/transport/status_conversion.c \ src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/transport.c \ src/core/lib/transport/transport_op_string.c \ PUBLIC_HEADERS_C += \ include/grpc/byte_buffer.h \ include/grpc/byte_buffer_reader.h \ include/grpc/compression.h \ include/grpc/grpc.h \ include/grpc/grpc_posix.h \ include/grpc/grpc_security_constants.h \ include/grpc/load_reporting.h \ include/grpc/slice.h \ include/grpc/slice_buffer.h \ include/grpc/status.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/slice.h \ include/grpc/impl/codegen/status.h \ include/grpc/impl/codegen/atm.h \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/sync.h \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ LIBGRPC_TEST_UTIL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_TEST_UTIL_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a: openssl_dep_error else $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(LIBGRPC_TEST_UTIL_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBGRPC_TEST_UTIL_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBGRPC_TEST_UTIL_OBJS:.o=.dep) endif endif LIBGRPC_TEST_UTIL_UNSECURE_SRC = \ test/core/end2end/cq_verifier.c \ test/core/end2end/fake_resolver.c \ test/core/end2end/fixtures/http_proxy_fixture.c \ test/core/end2end/fixtures/proxy.c \ test/core/iomgr/endpoint_tests.c \ test/core/util/debugger_macros.c \ test/core/util/grpc_profiler.c \ test/core/util/memory_counters.c \ test/core/util/mock_endpoint.c \ test/core/util/parse_hexstring.c \ test/core/util/passthru_endpoint.c \ test/core/util/port.c \ test/core/util/port_server_client.c \ test/core/util/slice_splitter.c \ test/core/util/trickle_endpoint.c \ PUBLIC_HEADERS_C += \ LIBGRPC_TEST_UTIL_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_TEST_UTIL_UNSECURE_SRC)))) $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a: $(ZLIB_DEP) $(CARES_DEP) $(LIBGRPC_TEST_UTIL_UNSECURE_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBGRPC_TEST_UTIL_UNSECURE_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a endif ifneq ($(NO_DEPS),true) -include $(LIBGRPC_TEST_UTIL_UNSECURE_OBJS:.o=.dep) endif LIBGRPC_UNSECURE_SRC = \ src/core/lib/surface/init.c \ src/core/lib/surface/init_unsecure.c \ src/core/lib/channel/channel_args.c \ src/core/lib/channel/channel_stack.c \ src/core/lib/channel/channel_stack_builder.c \ src/core/lib/channel/compress_filter.c \ src/core/lib/channel/connected_channel.c \ src/core/lib/channel/deadline_filter.c \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/handshaker_factory.c \ src/core/lib/channel/handshaker_registry.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ src/core/lib/channel/message_size_filter.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ src/core/lib/debug/trace.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_uv.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ src/core/lib/iomgr/executor.c \ src/core/lib/iomgr/iocp_windows.c \ src/core/lib/iomgr/iomgr.c \ src/core/lib/iomgr/iomgr_posix.c \ src/core/lib/iomgr/iomgr_uv.c \ src/core/lib/iomgr/iomgr_windows.c \ src/core/lib/iomgr/load_file.c \ src/core/lib/iomgr/lockfree_event.c \ src/core/lib/iomgr/network_status_tracker.c \ src/core/lib/iomgr/polling_entity.c \ src/core/lib/iomgr/pollset_set_uv.c \ src/core/lib/iomgr/pollset_set_windows.c \ src/core/lib/iomgr/pollset_uv.c \ src/core/lib/iomgr/pollset_windows.c \ src/core/lib/iomgr/resolve_address_posix.c \ src/core/lib/iomgr/resolve_address_uv.c \ src/core/lib/iomgr/resolve_address_windows.c \ src/core/lib/iomgr/resource_quota.c \ src/core/lib/iomgr/sockaddr_utils.c \ src/core/lib/iomgr/socket_factory_posix.c \ src/core/lib/iomgr/socket_mutator.c \ src/core/lib/iomgr/socket_utils_common_posix.c \ src/core/lib/iomgr/socket_utils_linux.c \ src/core/lib/iomgr/socket_utils_posix.c \ src/core/lib/iomgr/socket_utils_uv.c \ src/core/lib/iomgr/socket_utils_windows.c \ src/core/lib/iomgr/socket_windows.c \ src/core/lib/iomgr/tcp_client_posix.c \ src/core/lib/iomgr/tcp_client_uv.c \ src/core/lib/iomgr/tcp_client_windows.c \ src/core/lib/iomgr/tcp_posix.c \ src/core/lib/iomgr/tcp_server_posix.c \ src/core/lib/iomgr/tcp_server_utils_posix_common.c \ src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ src/core/lib/iomgr/tcp_server_windows.c \ src/core/lib/iomgr/tcp_uv.c \ src/core/lib/iomgr/tcp_windows.c \ src/core/lib/iomgr/time_averaged_stats.c \ src/core/lib/iomgr/timer_generic.c \ src/core/lib/iomgr/timer_heap.c \ src/core/lib/iomgr/timer_uv.c \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ src/core/lib/iomgr/wakeup_fd_posix.c \ src/core/lib/iomgr/workqueue_uv.c \ src/core/lib/iomgr/workqueue_windows.c \ src/core/lib/json/json.c \ src/core/lib/json/json_reader.c \ src/core/lib/json/json_string.c \ src/core/lib/json/json_writer.c \ src/core/lib/slice/b64.c \ src/core/lib/slice/percent_encoding.c \ src/core/lib/slice/slice.c \ src/core/lib/slice/slice_buffer.c \ src/core/lib/slice/slice_hash_table.c \ src/core/lib/slice/slice_intern.c \ src/core/lib/slice/slice_string_helpers.c \ src/core/lib/surface/alarm.c \ src/core/lib/surface/api_trace.c \ src/core/lib/surface/byte_buffer.c \ src/core/lib/surface/byte_buffer_reader.c \ src/core/lib/surface/call.c \ src/core/lib/surface/call_details.c \ src/core/lib/surface/call_log_batch.c \ src/core/lib/surface/channel.c \ src/core/lib/surface/channel_init.c \ src/core/lib/surface/channel_ping.c \ src/core/lib/surface/channel_stack_type.c \ src/core/lib/surface/completion_queue.c \ src/core/lib/surface/completion_queue_factory.c \ src/core/lib/surface/event_string.c \ src/core/lib/surface/lame_client.c \ src/core/lib/surface/metadata_array.c \ src/core/lib/surface/server.c \ src/core/lib/surface/validate_metadata.c \ src/core/lib/surface/version.c \ src/core/lib/transport/bdp_estimator.c \ src/core/lib/transport/byte_stream.c \ src/core/lib/transport/connectivity_state.c \ src/core/lib/transport/error_utils.c \ src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/pid_controller.c \ src/core/lib/transport/service_config.c \ src/core/lib/transport/static_metadata.c \ src/core/lib/transport/status_conversion.c \ src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/transport.c \ src/core/lib/transport/transport_op_string.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c \ src/core/ext/transport/chttp2/transport/bin_decoder.c \ src/core/ext/transport/chttp2/transport/bin_encoder.c \ src/core/ext/transport/chttp2/transport/chttp2_plugin.c \ src/core/ext/transport/chttp2/transport/chttp2_transport.c \ src/core/ext/transport/chttp2/transport/frame_data.c \ src/core/ext/transport/chttp2/transport/frame_goaway.c \ src/core/ext/transport/chttp2/transport/frame_ping.c \ src/core/ext/transport/chttp2/transport/frame_rst_stream.c \ src/core/ext/transport/chttp2/transport/frame_settings.c \ src/core/ext/transport/chttp2/transport/frame_window_update.c \ src/core/ext/transport/chttp2/transport/hpack_encoder.c \ src/core/ext/transport/chttp2/transport/hpack_parser.c \ src/core/ext/transport/chttp2/transport/hpack_table.c \ src/core/ext/transport/chttp2/transport/http2_settings.c \ src/core/ext/transport/chttp2/transport/huffsyms.c \ src/core/ext/transport/chttp2/transport/incoming_metadata.c \ src/core/ext/transport/chttp2/transport/parsing.c \ src/core/ext/transport/chttp2/transport/stream_lists.c \ src/core/ext/transport/chttp2/transport/stream_map.c \ src/core/ext/transport/chttp2/transport/varint.c \ src/core/ext/transport/chttp2/transport/writing.c \ src/core/ext/transport/chttp2/alpn/alpn.c \ src/core/ext/transport/chttp2/server/chttp2_server.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \ src/core/ext/transport/chttp2/client/chttp2_connector.c \ src/core/ext/filters/client_channel/channel_connectivity.c \ src/core/ext/filters/client_channel/client_channel.c \ src/core/ext/filters/client_channel/client_channel_factory.c \ src/core/ext/filters/client_channel/client_channel_plugin.c \ src/core/ext/filters/client_channel/connector.c \ src/core/ext/filters/client_channel/http_connect_handshaker.c \ src/core/ext/filters/client_channel/http_proxy.c \ src/core/ext/filters/client_channel/lb_policy.c \ src/core/ext/filters/client_channel/lb_policy_factory.c \ src/core/ext/filters/client_channel/lb_policy_registry.c \ src/core/ext/filters/client_channel/parse_address.c \ src/core/ext/filters/client_channel/proxy_mapper.c \ src/core/ext/filters/client_channel/proxy_mapper_registry.c \ src/core/ext/filters/client_channel/resolver.c \ src/core/ext/filters/client_channel/resolver_factory.c \ src/core/ext/filters/client_channel/resolver_registry.c \ src/core/ext/filters/client_channel/retry_throttle.c \ src/core/ext/filters/client_channel/subchannel.c \ src/core/ext/filters/client_channel/subchannel_index.c \ src/core/ext/filters/client_channel/uri_parser.c \ src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c \ src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.c \ src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c \ src/core/ext/filters/load_reporting/load_reporting.c \ src/core/ext/filters/load_reporting/load_reporting_filter.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ third_party/nanopb/pb_decode.c \ third_party/nanopb/pb_encode.c \ src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c \ src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c \ src/core/ext/census/base_resources.c \ src/core/ext/census/context.c \ src/core/ext/census/gen/census.pb.c \ src/core/ext/census/gen/trace_context.pb.c \ src/core/ext/census/grpc_context.c \ src/core/ext/census/grpc_filter.c \ src/core/ext/census/grpc_plugin.c \ src/core/ext/census/initialize.c \ src/core/ext/census/mlog.c \ src/core/ext/census/operation.c \ src/core/ext/census/placeholders.c \ src/core/ext/census/resource.c \ src/core/ext/census/trace_context.c \ src/core/ext/census/tracing.c \ src/core/ext/filters/max_age/max_age_filter.c \ src/core/plugin_registry/grpc_unsecure_plugin_registry.c \ PUBLIC_HEADERS_C += \ include/grpc/byte_buffer.h \ include/grpc/byte_buffer_reader.h \ include/grpc/compression.h \ include/grpc/grpc.h \ include/grpc/grpc_posix.h \ include/grpc/grpc_security_constants.h \ include/grpc/load_reporting.h \ include/grpc/slice.h \ include/grpc/slice_buffer.h \ include/grpc/status.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/slice.h \ include/grpc/impl/codegen/status.h \ include/grpc/impl/codegen/atm.h \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/sync.h \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ include/grpc/census.h \ LIBGRPC_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_UNSECURE_SRC)))) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a: $(ZLIB_DEP) $(CARES_DEP) $(LIBGRPC_UNSECURE_OBJS) $(LIBGPR_OBJS) $(ZLIB_MERGE_OBJS) $(CARES_MERGE_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBGRPC_UNSECURE_OBJS) $(LIBGPR_OBJS) $(ZLIB_MERGE_OBJS) $(CARES_MERGE_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a endif ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_UNSECURE_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBS) else $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_UNSECURE_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBS) else $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_unsecure.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBS) $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so.3 $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so endif endif ifneq ($(NO_DEPS),true) -include $(LIBGRPC_UNSECURE_OBJS:.o=.dep) endif LIBRECONNECT_SERVER_SRC = \ test/core/util/reconnect_server.c \ PUBLIC_HEADERS_C += \ LIBRECONNECT_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBRECONNECT_SERVER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libreconnect_server.a: openssl_dep_error else $(LIBDIR)/$(CONFIG)/libreconnect_server.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(LIBRECONNECT_SERVER_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libreconnect_server.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libreconnect_server.a $(LIBRECONNECT_SERVER_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libreconnect_server.a endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBRECONNECT_SERVER_OBJS:.o=.dep) endif endif LIBTEST_TCP_SERVER_SRC = \ test/core/util/test_tcp_server.c \ PUBLIC_HEADERS_C += \ LIBTEST_TCP_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBTEST_TCP_SERVER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a: openssl_dep_error else $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(LIBTEST_TCP_SERVER_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(LIBTEST_TCP_SERVER_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBTEST_TCP_SERVER_OBJS:.o=.dep) endif endif LIBGRPC++_SRC = \ src/cpp/client/insecure_credentials.cc \ src/cpp/client/secure_credentials.cc \ src/cpp/common/auth_property_iterator.cc \ src/cpp/common/secure_auth_context.cc \ src/cpp/common/secure_channel_arguments.cc \ src/cpp/common/secure_create_auth_context.cc \ src/cpp/server/insecure_server_credentials.cc \ src/cpp/server/secure_server_credentials.cc \ src/cpp/client/channel_cc.cc \ src/cpp/client/client_context.cc \ src/cpp/client/create_channel.cc \ src/cpp/client/create_channel_internal.cc \ src/cpp/client/create_channel_posix.cc \ src/cpp/client/credentials_cc.cc \ src/cpp/client/generic_stub.cc \ src/cpp/common/channel_arguments.cc \ src/cpp/common/channel_filter.cc \ src/cpp/common/completion_queue_cc.cc \ src/cpp/common/core_codegen.cc \ src/cpp/common/resource_quota_cc.cc \ src/cpp/common/rpc_method.cc \ src/cpp/common/version_cc.cc \ src/cpp/server/async_generic_service.cc \ src/cpp/server/channel_argument_option.cc \ src/cpp/server/create_default_thread_pool.cc \ src/cpp/server/dynamic_thread_pool.cc \ src/cpp/server/health/default_health_check_service.cc \ src/cpp/server/health/health.pb.c \ src/cpp/server/health/health_check_service.cc \ src/cpp/server/health/health_check_service_server_builder_option.cc \ src/cpp/server/server_builder.cc \ src/cpp/server/server_cc.cc \ src/cpp/server/server_context.cc \ src/cpp/server/server_credentials.cc \ src/cpp/server/server_posix.cc \ src/cpp/thread_manager/thread_manager.cc \ src/cpp/util/byte_buffer_cc.cc \ src/cpp/util/slice_cc.cc \ src/cpp/util/status.cc \ src/cpp/util/string_ref.cc \ src/cpp/util/time_cc.cc \ src/core/lib/channel/channel_args.c \ src/core/lib/channel/channel_stack.c \ src/core/lib/channel/channel_stack_builder.c \ src/core/lib/channel/compress_filter.c \ src/core/lib/channel/connected_channel.c \ src/core/lib/channel/deadline_filter.c \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/handshaker_factory.c \ src/core/lib/channel/handshaker_registry.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ src/core/lib/channel/message_size_filter.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ src/core/lib/debug/trace.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_uv.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ src/core/lib/iomgr/executor.c \ src/core/lib/iomgr/iocp_windows.c \ src/core/lib/iomgr/iomgr.c \ src/core/lib/iomgr/iomgr_posix.c \ src/core/lib/iomgr/iomgr_uv.c \ src/core/lib/iomgr/iomgr_windows.c \ src/core/lib/iomgr/load_file.c \ src/core/lib/iomgr/lockfree_event.c \ src/core/lib/iomgr/network_status_tracker.c \ src/core/lib/iomgr/polling_entity.c \ src/core/lib/iomgr/pollset_set_uv.c \ src/core/lib/iomgr/pollset_set_windows.c \ src/core/lib/iomgr/pollset_uv.c \ src/core/lib/iomgr/pollset_windows.c \ src/core/lib/iomgr/resolve_address_posix.c \ src/core/lib/iomgr/resolve_address_uv.c \ src/core/lib/iomgr/resolve_address_windows.c \ src/core/lib/iomgr/resource_quota.c \ src/core/lib/iomgr/sockaddr_utils.c \ src/core/lib/iomgr/socket_factory_posix.c \ src/core/lib/iomgr/socket_mutator.c \ src/core/lib/iomgr/socket_utils_common_posix.c \ src/core/lib/iomgr/socket_utils_linux.c \ src/core/lib/iomgr/socket_utils_posix.c \ src/core/lib/iomgr/socket_utils_uv.c \ src/core/lib/iomgr/socket_utils_windows.c \ src/core/lib/iomgr/socket_windows.c \ src/core/lib/iomgr/tcp_client_posix.c \ src/core/lib/iomgr/tcp_client_uv.c \ src/core/lib/iomgr/tcp_client_windows.c \ src/core/lib/iomgr/tcp_posix.c \ src/core/lib/iomgr/tcp_server_posix.c \ src/core/lib/iomgr/tcp_server_utils_posix_common.c \ src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ src/core/lib/iomgr/tcp_server_windows.c \ src/core/lib/iomgr/tcp_uv.c \ src/core/lib/iomgr/tcp_windows.c \ src/core/lib/iomgr/time_averaged_stats.c \ src/core/lib/iomgr/timer_generic.c \ src/core/lib/iomgr/timer_heap.c \ src/core/lib/iomgr/timer_uv.c \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ src/core/lib/iomgr/wakeup_fd_posix.c \ src/core/lib/iomgr/workqueue_uv.c \ src/core/lib/iomgr/workqueue_windows.c \ src/core/lib/json/json.c \ src/core/lib/json/json_reader.c \ src/core/lib/json/json_string.c \ src/core/lib/json/json_writer.c \ src/core/lib/slice/b64.c \ src/core/lib/slice/percent_encoding.c \ src/core/lib/slice/slice.c \ src/core/lib/slice/slice_buffer.c \ src/core/lib/slice/slice_hash_table.c \ src/core/lib/slice/slice_intern.c \ src/core/lib/slice/slice_string_helpers.c \ src/core/lib/surface/alarm.c \ src/core/lib/surface/api_trace.c \ src/core/lib/surface/byte_buffer.c \ src/core/lib/surface/byte_buffer_reader.c \ src/core/lib/surface/call.c \ src/core/lib/surface/call_details.c \ src/core/lib/surface/call_log_batch.c \ src/core/lib/surface/channel.c \ src/core/lib/surface/channel_init.c \ src/core/lib/surface/channel_ping.c \ src/core/lib/surface/channel_stack_type.c \ src/core/lib/surface/completion_queue.c \ src/core/lib/surface/completion_queue_factory.c \ src/core/lib/surface/event_string.c \ src/core/lib/surface/lame_client.c \ src/core/lib/surface/metadata_array.c \ src/core/lib/surface/server.c \ src/core/lib/surface/validate_metadata.c \ src/core/lib/surface/version.c \ src/core/lib/transport/bdp_estimator.c \ src/core/lib/transport/byte_stream.c \ src/core/lib/transport/connectivity_state.c \ src/core/lib/transport/error_utils.c \ src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/pid_controller.c \ src/core/lib/transport/service_config.c \ src/core/lib/transport/static_metadata.c \ src/core/lib/transport/status_conversion.c \ src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/transport.c \ src/core/lib/transport/transport_op_string.c \ third_party/nanopb/pb_common.c \ third_party/nanopb/pb_decode.c \ third_party/nanopb/pb_encode.c \ src/cpp/codegen/codegen_init.cc \ PUBLIC_HEADERS_CXX += \ include/grpc++/alarm.h \ include/grpc++/channel.h \ include/grpc++/client_context.h \ include/grpc++/completion_queue.h \ include/grpc++/create_channel.h \ include/grpc++/create_channel_posix.h \ include/grpc++/ext/health_check_service_server_builder_option.h \ include/grpc++/generic/async_generic_service.h \ include/grpc++/generic/generic_stub.h \ include/grpc++/grpc++.h \ include/grpc++/health_check_service_interface.h \ include/grpc++/impl/call.h \ include/grpc++/impl/channel_argument_option.h \ include/grpc++/impl/client_unary_call.h \ include/grpc++/impl/codegen/core_codegen.h \ include/grpc++/impl/grpc_library.h \ include/grpc++/impl/method_handler_impl.h \ include/grpc++/impl/rpc_method.h \ include/grpc++/impl/rpc_service_method.h \ include/grpc++/impl/serialization_traits.h \ include/grpc++/impl/server_builder_option.h \ include/grpc++/impl/server_builder_plugin.h \ include/grpc++/impl/server_initializer.h \ include/grpc++/impl/service_type.h \ include/grpc++/resource_quota.h \ include/grpc++/security/auth_context.h \ include/grpc++/security/auth_metadata_processor.h \ include/grpc++/security/credentials.h \ include/grpc++/security/server_credentials.h \ include/grpc++/server.h \ include/grpc++/server_builder.h \ include/grpc++/server_context.h \ include/grpc++/server_posix.h \ include/grpc++/support/async_stream.h \ include/grpc++/support/async_unary_call.h \ include/grpc++/support/byte_buffer.h \ include/grpc++/support/channel_arguments.h \ include/grpc++/support/config.h \ include/grpc++/support/slice.h \ include/grpc++/support/status.h \ include/grpc++/support/status_code_enum.h \ include/grpc++/support/string_ref.h \ include/grpc++/support/stub_options.h \ include/grpc++/support/sync_stream.h \ include/grpc++/support/time.h \ include/grpc++/impl/codegen/async_stream.h \ include/grpc++/impl/codegen/async_unary_call.h \ include/grpc++/impl/codegen/call.h \ include/grpc++/impl/codegen/call_hook.h \ include/grpc++/impl/codegen/channel_interface.h \ include/grpc++/impl/codegen/client_context.h \ include/grpc++/impl/codegen/client_unary_call.h \ include/grpc++/impl/codegen/completion_queue.h \ include/grpc++/impl/codegen/completion_queue_tag.h \ include/grpc++/impl/codegen/config.h \ include/grpc++/impl/codegen/core_codegen_interface.h \ include/grpc++/impl/codegen/create_auth_context.h \ include/grpc++/impl/codegen/grpc_library.h \ include/grpc++/impl/codegen/metadata_map.h \ include/grpc++/impl/codegen/method_handler_impl.h \ include/grpc++/impl/codegen/rpc_method.h \ include/grpc++/impl/codegen/rpc_service_method.h \ include/grpc++/impl/codegen/security/auth_context.h \ include/grpc++/impl/codegen/serialization_traits.h \ include/grpc++/impl/codegen/server_context.h \ include/grpc++/impl/codegen/server_interface.h \ include/grpc++/impl/codegen/service_type.h \ include/grpc++/impl/codegen/slice.h \ include/grpc++/impl/codegen/status.h \ include/grpc++/impl/codegen/status_code_enum.h \ include/grpc++/impl/codegen/status_helper.h \ include/grpc++/impl/codegen/string_ref.h \ include/grpc++/impl/codegen/stub_options.h \ include/grpc++/impl/codegen/sync_stream.h \ include/grpc++/impl/codegen/time.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/slice.h \ include/grpc/impl/codegen/status.h \ include/grpc/impl/codegen/atm.h \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/sync.h \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ include/grpc/byte_buffer.h \ include/grpc/byte_buffer_reader.h \ include/grpc/compression.h \ include/grpc/grpc.h \ include/grpc/grpc_posix.h \ include/grpc/grpc_security_constants.h \ include/grpc/load_reporting.h \ include/grpc/slice.h \ include/grpc/slice_buffer.h \ include/grpc/status.h \ include/grpc++/impl/codegen/proto_utils.h \ include/grpc++/impl/codegen/config_protobuf.h \ LIBGRPC++_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libgrpc++.a: openssl_dep_error $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libgrpc++.a: protobuf_dep_error $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libgrpc++.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBGRPC++_OBJS) $(LIBGPR_OBJS) $(ZLIB_MERGE_OBJS) $(CARES_MERGE_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc++.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBGRPC++_OBJS) $(LIBGPR_OBJS) $(ZLIB_MERGE_OBJS) $(CARES_MERGE_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc++.a endif ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc$(SHARED_VERSION_CORE)-dll -lgpr$(SHARED_VERSION_CORE)-dll else $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc -lgpr else $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc -lgpr $(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so.1 $(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so endif endif endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBGRPC++_OBJS:.o=.dep) endif endif LIBGRPC++_CRONET_SRC = \ src/cpp/client/cronet_credentials.cc \ src/cpp/client/insecure_credentials.cc \ src/cpp/common/insecure_create_auth_context.cc \ src/cpp/server/insecure_server_credentials.cc \ src/cpp/client/channel_cc.cc \ src/cpp/client/client_context.cc \ src/cpp/client/create_channel.cc \ src/cpp/client/create_channel_internal.cc \ src/cpp/client/create_channel_posix.cc \ src/cpp/client/credentials_cc.cc \ src/cpp/client/generic_stub.cc \ src/cpp/common/channel_arguments.cc \ src/cpp/common/channel_filter.cc \ src/cpp/common/completion_queue_cc.cc \ src/cpp/common/core_codegen.cc \ src/cpp/common/resource_quota_cc.cc \ src/cpp/common/rpc_method.cc \ src/cpp/common/version_cc.cc \ src/cpp/server/async_generic_service.cc \ src/cpp/server/channel_argument_option.cc \ src/cpp/server/create_default_thread_pool.cc \ src/cpp/server/dynamic_thread_pool.cc \ src/cpp/server/health/default_health_check_service.cc \ src/cpp/server/health/health.pb.c \ src/cpp/server/health/health_check_service.cc \ src/cpp/server/health/health_check_service_server_builder_option.cc \ src/cpp/server/server_builder.cc \ src/cpp/server/server_cc.cc \ src/cpp/server/server_context.cc \ src/cpp/server/server_credentials.cc \ src/cpp/server/server_posix.cc \ src/cpp/thread_manager/thread_manager.cc \ src/cpp/util/byte_buffer_cc.cc \ src/cpp/util/slice_cc.cc \ src/cpp/util/status.cc \ src/cpp/util/string_ref.cc \ src/cpp/util/time_cc.cc \ src/core/lib/channel/channel_args.c \ src/core/lib/channel/channel_stack.c \ src/core/lib/channel/channel_stack_builder.c \ src/core/lib/channel/compress_filter.c \ src/core/lib/channel/connected_channel.c \ src/core/lib/channel/deadline_filter.c \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/handshaker_factory.c \ src/core/lib/channel/handshaker_registry.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ src/core/lib/channel/message_size_filter.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ src/core/lib/debug/trace.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_uv.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ src/core/lib/iomgr/executor.c \ src/core/lib/iomgr/iocp_windows.c \ src/core/lib/iomgr/iomgr.c \ src/core/lib/iomgr/iomgr_posix.c \ src/core/lib/iomgr/iomgr_uv.c \ src/core/lib/iomgr/iomgr_windows.c \ src/core/lib/iomgr/load_file.c \ src/core/lib/iomgr/lockfree_event.c \ src/core/lib/iomgr/network_status_tracker.c \ src/core/lib/iomgr/polling_entity.c \ src/core/lib/iomgr/pollset_set_uv.c \ src/core/lib/iomgr/pollset_set_windows.c \ src/core/lib/iomgr/pollset_uv.c \ src/core/lib/iomgr/pollset_windows.c \ src/core/lib/iomgr/resolve_address_posix.c \ src/core/lib/iomgr/resolve_address_uv.c \ src/core/lib/iomgr/resolve_address_windows.c \ src/core/lib/iomgr/resource_quota.c \ src/core/lib/iomgr/sockaddr_utils.c \ src/core/lib/iomgr/socket_factory_posix.c \ src/core/lib/iomgr/socket_mutator.c \ src/core/lib/iomgr/socket_utils_common_posix.c \ src/core/lib/iomgr/socket_utils_linux.c \ src/core/lib/iomgr/socket_utils_posix.c \ src/core/lib/iomgr/socket_utils_uv.c \ src/core/lib/iomgr/socket_utils_windows.c \ src/core/lib/iomgr/socket_windows.c \ src/core/lib/iomgr/tcp_client_posix.c \ src/core/lib/iomgr/tcp_client_uv.c \ src/core/lib/iomgr/tcp_client_windows.c \ src/core/lib/iomgr/tcp_posix.c \ src/core/lib/iomgr/tcp_server_posix.c \ src/core/lib/iomgr/tcp_server_utils_posix_common.c \ src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ src/core/lib/iomgr/tcp_server_windows.c \ src/core/lib/iomgr/tcp_uv.c \ src/core/lib/iomgr/tcp_windows.c \ src/core/lib/iomgr/time_averaged_stats.c \ src/core/lib/iomgr/timer_generic.c \ src/core/lib/iomgr/timer_heap.c \ src/core/lib/iomgr/timer_uv.c \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ src/core/lib/iomgr/wakeup_fd_posix.c \ src/core/lib/iomgr/workqueue_uv.c \ src/core/lib/iomgr/workqueue_windows.c \ src/core/lib/json/json.c \ src/core/lib/json/json_reader.c \ src/core/lib/json/json_string.c \ src/core/lib/json/json_writer.c \ src/core/lib/slice/b64.c \ src/core/lib/slice/percent_encoding.c \ src/core/lib/slice/slice.c \ src/core/lib/slice/slice_buffer.c \ src/core/lib/slice/slice_hash_table.c \ src/core/lib/slice/slice_intern.c \ src/core/lib/slice/slice_string_helpers.c \ src/core/lib/surface/alarm.c \ src/core/lib/surface/api_trace.c \ src/core/lib/surface/byte_buffer.c \ src/core/lib/surface/byte_buffer_reader.c \ src/core/lib/surface/call.c \ src/core/lib/surface/call_details.c \ src/core/lib/surface/call_log_batch.c \ src/core/lib/surface/channel.c \ src/core/lib/surface/channel_init.c \ src/core/lib/surface/channel_ping.c \ src/core/lib/surface/channel_stack_type.c \ src/core/lib/surface/completion_queue.c \ src/core/lib/surface/completion_queue_factory.c \ src/core/lib/surface/event_string.c \ src/core/lib/surface/lame_client.c \ src/core/lib/surface/metadata_array.c \ src/core/lib/surface/server.c \ src/core/lib/surface/validate_metadata.c \ src/core/lib/surface/version.c \ src/core/lib/transport/bdp_estimator.c \ src/core/lib/transport/byte_stream.c \ src/core/lib/transport/connectivity_state.c \ src/core/lib/transport/error_utils.c \ src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/pid_controller.c \ src/core/lib/transport/service_config.c \ src/core/lib/transport/static_metadata.c \ src/core/lib/transport/status_conversion.c \ src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/transport.c \ src/core/lib/transport/transport_op_string.c \ third_party/nanopb/pb_common.c \ third_party/nanopb/pb_decode.c \ third_party/nanopb/pb_encode.c \ src/cpp/codegen/codegen_init.cc \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \ src/core/ext/transport/chttp2/client/chttp2_connector.c \ src/core/ext/transport/chttp2/transport/bin_decoder.c \ src/core/ext/transport/chttp2/transport/bin_encoder.c \ src/core/ext/transport/chttp2/transport/chttp2_plugin.c \ src/core/ext/transport/chttp2/transport/chttp2_transport.c \ src/core/ext/transport/chttp2/transport/frame_data.c \ src/core/ext/transport/chttp2/transport/frame_goaway.c \ src/core/ext/transport/chttp2/transport/frame_ping.c \ src/core/ext/transport/chttp2/transport/frame_rst_stream.c \ src/core/ext/transport/chttp2/transport/frame_settings.c \ src/core/ext/transport/chttp2/transport/frame_window_update.c \ src/core/ext/transport/chttp2/transport/hpack_encoder.c \ src/core/ext/transport/chttp2/transport/hpack_parser.c \ src/core/ext/transport/chttp2/transport/hpack_table.c \ src/core/ext/transport/chttp2/transport/http2_settings.c \ src/core/ext/transport/chttp2/transport/huffsyms.c \ src/core/ext/transport/chttp2/transport/incoming_metadata.c \ src/core/ext/transport/chttp2/transport/parsing.c \ src/core/ext/transport/chttp2/transport/stream_lists.c \ src/core/ext/transport/chttp2/transport/stream_map.c \ src/core/ext/transport/chttp2/transport/varint.c \ src/core/ext/transport/chttp2/transport/writing.c \ src/core/ext/transport/chttp2/alpn/alpn.c \ src/core/ext/filters/client_channel/channel_connectivity.c \ src/core/ext/filters/client_channel/client_channel.c \ src/core/ext/filters/client_channel/client_channel_factory.c \ src/core/ext/filters/client_channel/client_channel_plugin.c \ src/core/ext/filters/client_channel/connector.c \ src/core/ext/filters/client_channel/http_connect_handshaker.c \ src/core/ext/filters/client_channel/http_proxy.c \ src/core/ext/filters/client_channel/lb_policy.c \ src/core/ext/filters/client_channel/lb_policy_factory.c \ src/core/ext/filters/client_channel/lb_policy_registry.c \ src/core/ext/filters/client_channel/parse_address.c \ src/core/ext/filters/client_channel/proxy_mapper.c \ src/core/ext/filters/client_channel/proxy_mapper_registry.c \ src/core/ext/filters/client_channel/resolver.c \ src/core/ext/filters/client_channel/resolver_factory.c \ src/core/ext/filters/client_channel/resolver_registry.c \ src/core/ext/filters/client_channel/retry_throttle.c \ src/core/ext/filters/client_channel/subchannel.c \ src/core/ext/filters/client_channel/subchannel_index.c \ src/core/ext/filters/client_channel/uri_parser.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c \ src/core/ext/transport/chttp2/server/chttp2_server.c \ src/core/ext/census/base_resources.c \ src/core/ext/census/context.c \ src/core/ext/census/gen/census.pb.c \ src/core/ext/census/gen/trace_context.pb.c \ src/core/ext/census/grpc_context.c \ src/core/ext/census/grpc_filter.c \ src/core/ext/census/grpc_plugin.c \ src/core/ext/census/initialize.c \ src/core/ext/census/mlog.c \ src/core/ext/census/operation.c \ src/core/ext/census/placeholders.c \ src/core/ext/census/resource.c \ src/core/ext/census/trace_context.c \ src/core/ext/census/tracing.c \ PUBLIC_HEADERS_CXX += \ include/grpc++/alarm.h \ include/grpc++/channel.h \ include/grpc++/client_context.h \ include/grpc++/completion_queue.h \ include/grpc++/create_channel.h \ include/grpc++/create_channel_posix.h \ include/grpc++/ext/health_check_service_server_builder_option.h \ include/grpc++/generic/async_generic_service.h \ include/grpc++/generic/generic_stub.h \ include/grpc++/grpc++.h \ include/grpc++/health_check_service_interface.h \ include/grpc++/impl/call.h \ include/grpc++/impl/channel_argument_option.h \ include/grpc++/impl/client_unary_call.h \ include/grpc++/impl/codegen/core_codegen.h \ include/grpc++/impl/grpc_library.h \ include/grpc++/impl/method_handler_impl.h \ include/grpc++/impl/rpc_method.h \ include/grpc++/impl/rpc_service_method.h \ include/grpc++/impl/serialization_traits.h \ include/grpc++/impl/server_builder_option.h \ include/grpc++/impl/server_builder_plugin.h \ include/grpc++/impl/server_initializer.h \ include/grpc++/impl/service_type.h \ include/grpc++/resource_quota.h \ include/grpc++/security/auth_context.h \ include/grpc++/security/auth_metadata_processor.h \ include/grpc++/security/credentials.h \ include/grpc++/security/server_credentials.h \ include/grpc++/server.h \ include/grpc++/server_builder.h \ include/grpc++/server_context.h \ include/grpc++/server_posix.h \ include/grpc++/support/async_stream.h \ include/grpc++/support/async_unary_call.h \ include/grpc++/support/byte_buffer.h \ include/grpc++/support/channel_arguments.h \ include/grpc++/support/config.h \ include/grpc++/support/slice.h \ include/grpc++/support/status.h \ include/grpc++/support/status_code_enum.h \ include/grpc++/support/string_ref.h \ include/grpc++/support/stub_options.h \ include/grpc++/support/sync_stream.h \ include/grpc++/support/time.h \ include/grpc++/impl/codegen/async_stream.h \ include/grpc++/impl/codegen/async_unary_call.h \ include/grpc++/impl/codegen/call.h \ include/grpc++/impl/codegen/call_hook.h \ include/grpc++/impl/codegen/channel_interface.h \ include/grpc++/impl/codegen/client_context.h \ include/grpc++/impl/codegen/client_unary_call.h \ include/grpc++/impl/codegen/completion_queue.h \ include/grpc++/impl/codegen/completion_queue_tag.h \ include/grpc++/impl/codegen/config.h \ include/grpc++/impl/codegen/core_codegen_interface.h \ include/grpc++/impl/codegen/create_auth_context.h \ include/grpc++/impl/codegen/grpc_library.h \ include/grpc++/impl/codegen/metadata_map.h \ include/grpc++/impl/codegen/method_handler_impl.h \ include/grpc++/impl/codegen/rpc_method.h \ include/grpc++/impl/codegen/rpc_service_method.h \ include/grpc++/impl/codegen/security/auth_context.h \ include/grpc++/impl/codegen/serialization_traits.h \ include/grpc++/impl/codegen/server_context.h \ include/grpc++/impl/codegen/server_interface.h \ include/grpc++/impl/codegen/service_type.h \ include/grpc++/impl/codegen/slice.h \ include/grpc++/impl/codegen/status.h \ include/grpc++/impl/codegen/status_code_enum.h \ include/grpc++/impl/codegen/status_helper.h \ include/grpc++/impl/codegen/string_ref.h \ include/grpc++/impl/codegen/stub_options.h \ include/grpc++/impl/codegen/sync_stream.h \ include/grpc++/impl/codegen/time.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/slice.h \ include/grpc/impl/codegen/status.h \ include/grpc/impl/codegen/atm.h \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/sync.h \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ include/grpc/byte_buffer.h \ include/grpc/byte_buffer_reader.h \ include/grpc/compression.h \ include/grpc/grpc.h \ include/grpc/grpc_posix.h \ include/grpc/grpc_security_constants.h \ include/grpc/load_reporting.h \ include/grpc/slice.h \ include/grpc/slice_buffer.h \ include/grpc/status.h \ include/grpc/census.h \ LIBGRPC++_CRONET_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_CRONET_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libgrpc++_cronet.a: openssl_dep_error $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libgrpc++_cronet.a: protobuf_dep_error $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libgrpc++_cronet.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBGRPC++_CRONET_OBJS) $(LIBGPR_OBJS) $(ZLIB_MERGE_OBJS) $(CARES_MERGE_OBJS) $(OPENSSL_MERGE_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc++_cronet.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet.a $(LIBGRPC++_CRONET_OBJS) $(LIBGPR_OBJS) $(ZLIB_MERGE_OBJS) $(CARES_MERGE_OBJS) $(OPENSSL_MERGE_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc++_cronet.a endif ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr$(SHARED_VERSION_CORE)-dll -lgrpc_cronet$(SHARED_VERSION_CORE)-dll else $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet.$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_cronet else $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_cronet.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_cronet $(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so.1 $(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so endif endif endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBGRPC++_CRONET_OBJS:.o=.dep) endif endif LIBGRPC++_ERROR_DETAILS_SRC = \ $(GENDIR)/src/proto/grpc/status/status.pb.cc $(GENDIR)/src/proto/grpc/status/status.grpc.pb.cc \ src/cpp/util/error_details.cc \ PUBLIC_HEADERS_CXX += \ include/grpc++/support/error_details.h \ LIBGRPC++_ERROR_DETAILS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_ERROR_DETAILS_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libgrpc++_error_details.a: openssl_dep_error $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libgrpc++_error_details.a: protobuf_dep_error $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libgrpc++_error_details.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBGRPC++_ERROR_DETAILS_OBJS) $(LIBGPR_OBJS) $(ZLIB_MERGE_OBJS) $(CARES_MERGE_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc++_error_details.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc++_error_details.a $(LIBGRPC++_ERROR_DETAILS_OBJS) $(LIBGPR_OBJS) $(ZLIB_MERGE_OBJS) $(CARES_MERGE_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc++_error_details.a endif ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_ERROR_DETAILS_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_error_details$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_error_details$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_ERROR_DETAILS_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc++$(SHARED_VERSION_CPP)-dll else $(LIBDIR)/$(CONFIG)/libgrpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_ERROR_DETAILS_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc++.$(SHARED_EXT_CPP) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_ERROR_DETAILS_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc++ else $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_error_details.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_ERROR_DETAILS_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc++ $(Q) ln -sf $(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_error_details$(SHARED_VERSION_CPP).so.1 $(Q) ln -sf $(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_error_details$(SHARED_VERSION_CPP).so endif endif endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBGRPC++_ERROR_DETAILS_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/src/cpp/util/error_details.o: $(GENDIR)/src/proto/grpc/status/status.pb.cc $(GENDIR)/src/proto/grpc/status/status.grpc.pb.cc LIBGRPC++_PROTO_REFLECTION_DESC_DB_SRC = \ test/cpp/util/proto_reflection_descriptor_database.cc \ $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.pb.cc $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc \ PUBLIC_HEADERS_CXX += \ include/grpc++/impl/codegen/config_protobuf.h \ LIBGRPC++_PROTO_REFLECTION_DESC_DB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_PROTO_REFLECTION_DESC_DB_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBGRPC++_PROTO_REFLECTION_DESC_DB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBGRPC++_PROTO_REFLECTION_DESC_DB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a endif endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBGRPC++_PROTO_REFLECTION_DESC_DB_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/test/cpp/util/proto_reflection_descriptor_database.o: $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.pb.cc $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc LIBGRPC++_REFLECTION_SRC = \ src/cpp/ext/proto_server_reflection.cc \ src/cpp/ext/proto_server_reflection_plugin.cc \ $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.pb.cc $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc \ PUBLIC_HEADERS_CXX += \ include/grpc++/ext/proto_server_reflection_plugin.h \ LIBGRPC++_REFLECTION_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_REFLECTION_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a: openssl_dep_error $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a: protobuf_dep_error $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBGRPC++_REFLECTION_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBGRPC++_REFLECTION_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a endif ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc++$(SHARED_VERSION_CPP)-dll else $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc++.$(SHARED_EXT_CPP) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc++ else $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_reflection.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc++ $(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).so.1 $(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).so endif endif endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBGRPC++_REFLECTION_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/src/cpp/ext/proto_server_reflection.o: $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.pb.cc $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc $(OBJDIR)/$(CONFIG)/src/cpp/ext/proto_server_reflection_plugin.o: $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.pb.cc $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc LIBGRPC++_TEST_CONFIG_SRC = \ test/cpp/util/test_config_cc.cc \ PUBLIC_HEADERS_CXX += \ LIBGRPC++_TEST_CONFIG_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_TEST_CONFIG_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBGRPC++_TEST_CONFIG_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBGRPC++_TEST_CONFIG_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a endif endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBGRPC++_TEST_CONFIG_OBJS:.o=.dep) endif endif LIBGRPC++_TEST_UTIL_SRC = \ $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc \ test/cpp/end2end/test_service_impl.cc \ test/cpp/util/byte_buffer_proto_helper.cc \ test/cpp/util/create_test_channel.cc \ test/cpp/util/string_ref_helper.cc \ test/cpp/util/subprocess.cc \ test/cpp/util/test_credentials_provider.cc \ src/cpp/codegen/codegen_init.cc \ PUBLIC_HEADERS_CXX += \ include/grpc++/impl/codegen/async_stream.h \ include/grpc++/impl/codegen/async_unary_call.h \ include/grpc++/impl/codegen/call.h \ include/grpc++/impl/codegen/call_hook.h \ include/grpc++/impl/codegen/channel_interface.h \ include/grpc++/impl/codegen/client_context.h \ include/grpc++/impl/codegen/client_unary_call.h \ include/grpc++/impl/codegen/completion_queue.h \ include/grpc++/impl/codegen/completion_queue_tag.h \ include/grpc++/impl/codegen/config.h \ include/grpc++/impl/codegen/core_codegen_interface.h \ include/grpc++/impl/codegen/create_auth_context.h \ include/grpc++/impl/codegen/grpc_library.h \ include/grpc++/impl/codegen/metadata_map.h \ include/grpc++/impl/codegen/method_handler_impl.h \ include/grpc++/impl/codegen/rpc_method.h \ include/grpc++/impl/codegen/rpc_service_method.h \ include/grpc++/impl/codegen/security/auth_context.h \ include/grpc++/impl/codegen/serialization_traits.h \ include/grpc++/impl/codegen/server_context.h \ include/grpc++/impl/codegen/server_interface.h \ include/grpc++/impl/codegen/service_type.h \ include/grpc++/impl/codegen/slice.h \ include/grpc++/impl/codegen/status.h \ include/grpc++/impl/codegen/status_code_enum.h \ include/grpc++/impl/codegen/status_helper.h \ include/grpc++/impl/codegen/string_ref.h \ include/grpc++/impl/codegen/stub_options.h \ include/grpc++/impl/codegen/sync_stream.h \ include/grpc++/impl/codegen/time.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/slice.h \ include/grpc/impl/codegen/status.h \ include/grpc/impl/codegen/atm.h \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/sync.h \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ include/grpc++/impl/codegen/proto_utils.h \ include/grpc++/impl/codegen/config_protobuf.h \ include/grpc++/impl/codegen/thrift_serializer.h \ include/grpc++/impl/codegen/thrift_utils.h \ LIBGRPC++_TEST_UTIL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_TEST_UTIL_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBGRPC++_TEST_UTIL_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBGRPC++_TEST_UTIL_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a endif endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBGRPC++_TEST_UTIL_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/test/cpp/end2end/test_service_impl.o: $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/util/byte_buffer_proto_helper.o: $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/util/create_test_channel.o: $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/util/string_ref_helper.o: $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/util/subprocess.o: $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/util/test_credentials_provider.o: $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc $(OBJDIR)/$(CONFIG)/src/cpp/codegen/codegen_init.o: $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc LIBGRPC++_UNSECURE_SRC = \ src/cpp/client/insecure_credentials.cc \ src/cpp/common/insecure_create_auth_context.cc \ src/cpp/server/insecure_server_credentials.cc \ src/cpp/client/channel_cc.cc \ src/cpp/client/client_context.cc \ src/cpp/client/create_channel.cc \ src/cpp/client/create_channel_internal.cc \ src/cpp/client/create_channel_posix.cc \ src/cpp/client/credentials_cc.cc \ src/cpp/client/generic_stub.cc \ src/cpp/common/channel_arguments.cc \ src/cpp/common/channel_filter.cc \ src/cpp/common/completion_queue_cc.cc \ src/cpp/common/core_codegen.cc \ src/cpp/common/resource_quota_cc.cc \ src/cpp/common/rpc_method.cc \ src/cpp/common/version_cc.cc \ src/cpp/server/async_generic_service.cc \ src/cpp/server/channel_argument_option.cc \ src/cpp/server/create_default_thread_pool.cc \ src/cpp/server/dynamic_thread_pool.cc \ src/cpp/server/health/default_health_check_service.cc \ src/cpp/server/health/health.pb.c \ src/cpp/server/health/health_check_service.cc \ src/cpp/server/health/health_check_service_server_builder_option.cc \ src/cpp/server/server_builder.cc \ src/cpp/server/server_cc.cc \ src/cpp/server/server_context.cc \ src/cpp/server/server_credentials.cc \ src/cpp/server/server_posix.cc \ src/cpp/thread_manager/thread_manager.cc \ src/cpp/util/byte_buffer_cc.cc \ src/cpp/util/slice_cc.cc \ src/cpp/util/status.cc \ src/cpp/util/string_ref.cc \ src/cpp/util/time_cc.cc \ src/core/lib/channel/channel_args.c \ src/core/lib/channel/channel_stack.c \ src/core/lib/channel/channel_stack_builder.c \ src/core/lib/channel/compress_filter.c \ src/core/lib/channel/connected_channel.c \ src/core/lib/channel/deadline_filter.c \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/handshaker_factory.c \ src/core/lib/channel/handshaker_registry.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ src/core/lib/channel/message_size_filter.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ src/core/lib/debug/trace.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_uv.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ src/core/lib/iomgr/executor.c \ src/core/lib/iomgr/iocp_windows.c \ src/core/lib/iomgr/iomgr.c \ src/core/lib/iomgr/iomgr_posix.c \ src/core/lib/iomgr/iomgr_uv.c \ src/core/lib/iomgr/iomgr_windows.c \ src/core/lib/iomgr/load_file.c \ src/core/lib/iomgr/lockfree_event.c \ src/core/lib/iomgr/network_status_tracker.c \ src/core/lib/iomgr/polling_entity.c \ src/core/lib/iomgr/pollset_set_uv.c \ src/core/lib/iomgr/pollset_set_windows.c \ src/core/lib/iomgr/pollset_uv.c \ src/core/lib/iomgr/pollset_windows.c \ src/core/lib/iomgr/resolve_address_posix.c \ src/core/lib/iomgr/resolve_address_uv.c \ src/core/lib/iomgr/resolve_address_windows.c \ src/core/lib/iomgr/resource_quota.c \ src/core/lib/iomgr/sockaddr_utils.c \ src/core/lib/iomgr/socket_factory_posix.c \ src/core/lib/iomgr/socket_mutator.c \ src/core/lib/iomgr/socket_utils_common_posix.c \ src/core/lib/iomgr/socket_utils_linux.c \ src/core/lib/iomgr/socket_utils_posix.c \ src/core/lib/iomgr/socket_utils_uv.c \ src/core/lib/iomgr/socket_utils_windows.c \ src/core/lib/iomgr/socket_windows.c \ src/core/lib/iomgr/tcp_client_posix.c \ src/core/lib/iomgr/tcp_client_uv.c \ src/core/lib/iomgr/tcp_client_windows.c \ src/core/lib/iomgr/tcp_posix.c \ src/core/lib/iomgr/tcp_server_posix.c \ src/core/lib/iomgr/tcp_server_utils_posix_common.c \ src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ src/core/lib/iomgr/tcp_server_windows.c \ src/core/lib/iomgr/tcp_uv.c \ src/core/lib/iomgr/tcp_windows.c \ src/core/lib/iomgr/time_averaged_stats.c \ src/core/lib/iomgr/timer_generic.c \ src/core/lib/iomgr/timer_heap.c \ src/core/lib/iomgr/timer_uv.c \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ src/core/lib/iomgr/wakeup_fd_posix.c \ src/core/lib/iomgr/workqueue_uv.c \ src/core/lib/iomgr/workqueue_windows.c \ src/core/lib/json/json.c \ src/core/lib/json/json_reader.c \ src/core/lib/json/json_string.c \ src/core/lib/json/json_writer.c \ src/core/lib/slice/b64.c \ src/core/lib/slice/percent_encoding.c \ src/core/lib/slice/slice.c \ src/core/lib/slice/slice_buffer.c \ src/core/lib/slice/slice_hash_table.c \ src/core/lib/slice/slice_intern.c \ src/core/lib/slice/slice_string_helpers.c \ src/core/lib/surface/alarm.c \ src/core/lib/surface/api_trace.c \ src/core/lib/surface/byte_buffer.c \ src/core/lib/surface/byte_buffer_reader.c \ src/core/lib/surface/call.c \ src/core/lib/surface/call_details.c \ src/core/lib/surface/call_log_batch.c \ src/core/lib/surface/channel.c \ src/core/lib/surface/channel_init.c \ src/core/lib/surface/channel_ping.c \ src/core/lib/surface/channel_stack_type.c \ src/core/lib/surface/completion_queue.c \ src/core/lib/surface/completion_queue_factory.c \ src/core/lib/surface/event_string.c \ src/core/lib/surface/lame_client.c \ src/core/lib/surface/metadata_array.c \ src/core/lib/surface/server.c \ src/core/lib/surface/validate_metadata.c \ src/core/lib/surface/version.c \ src/core/lib/transport/bdp_estimator.c \ src/core/lib/transport/byte_stream.c \ src/core/lib/transport/connectivity_state.c \ src/core/lib/transport/error_utils.c \ src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/pid_controller.c \ src/core/lib/transport/service_config.c \ src/core/lib/transport/static_metadata.c \ src/core/lib/transport/status_conversion.c \ src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/transport.c \ src/core/lib/transport/transport_op_string.c \ third_party/nanopb/pb_common.c \ third_party/nanopb/pb_decode.c \ third_party/nanopb/pb_encode.c \ src/cpp/codegen/codegen_init.cc \ PUBLIC_HEADERS_CXX += \ include/grpc++/alarm.h \ include/grpc++/channel.h \ include/grpc++/client_context.h \ include/grpc++/completion_queue.h \ include/grpc++/create_channel.h \ include/grpc++/create_channel_posix.h \ include/grpc++/ext/health_check_service_server_builder_option.h \ include/grpc++/generic/async_generic_service.h \ include/grpc++/generic/generic_stub.h \ include/grpc++/grpc++.h \ include/grpc++/health_check_service_interface.h \ include/grpc++/impl/call.h \ include/grpc++/impl/channel_argument_option.h \ include/grpc++/impl/client_unary_call.h \ include/grpc++/impl/codegen/core_codegen.h \ include/grpc++/impl/grpc_library.h \ include/grpc++/impl/method_handler_impl.h \ include/grpc++/impl/rpc_method.h \ include/grpc++/impl/rpc_service_method.h \ include/grpc++/impl/serialization_traits.h \ include/grpc++/impl/server_builder_option.h \ include/grpc++/impl/server_builder_plugin.h \ include/grpc++/impl/server_initializer.h \ include/grpc++/impl/service_type.h \ include/grpc++/resource_quota.h \ include/grpc++/security/auth_context.h \ include/grpc++/security/auth_metadata_processor.h \ include/grpc++/security/credentials.h \ include/grpc++/security/server_credentials.h \ include/grpc++/server.h \ include/grpc++/server_builder.h \ include/grpc++/server_context.h \ include/grpc++/server_posix.h \ include/grpc++/support/async_stream.h \ include/grpc++/support/async_unary_call.h \ include/grpc++/support/byte_buffer.h \ include/grpc++/support/channel_arguments.h \ include/grpc++/support/config.h \ include/grpc++/support/slice.h \ include/grpc++/support/status.h \ include/grpc++/support/status_code_enum.h \ include/grpc++/support/string_ref.h \ include/grpc++/support/stub_options.h \ include/grpc++/support/sync_stream.h \ include/grpc++/support/time.h \ include/grpc++/impl/codegen/async_stream.h \ include/grpc++/impl/codegen/async_unary_call.h \ include/grpc++/impl/codegen/call.h \ include/grpc++/impl/codegen/call_hook.h \ include/grpc++/impl/codegen/channel_interface.h \ include/grpc++/impl/codegen/client_context.h \ include/grpc++/impl/codegen/client_unary_call.h \ include/grpc++/impl/codegen/completion_queue.h \ include/grpc++/impl/codegen/completion_queue_tag.h \ include/grpc++/impl/codegen/config.h \ include/grpc++/impl/codegen/core_codegen_interface.h \ include/grpc++/impl/codegen/create_auth_context.h \ include/grpc++/impl/codegen/grpc_library.h \ include/grpc++/impl/codegen/metadata_map.h \ include/grpc++/impl/codegen/method_handler_impl.h \ include/grpc++/impl/codegen/rpc_method.h \ include/grpc++/impl/codegen/rpc_service_method.h \ include/grpc++/impl/codegen/security/auth_context.h \ include/grpc++/impl/codegen/serialization_traits.h \ include/grpc++/impl/codegen/server_context.h \ include/grpc++/impl/codegen/server_interface.h \ include/grpc++/impl/codegen/service_type.h \ include/grpc++/impl/codegen/slice.h \ include/grpc++/impl/codegen/status.h \ include/grpc++/impl/codegen/status_code_enum.h \ include/grpc++/impl/codegen/status_helper.h \ include/grpc++/impl/codegen/string_ref.h \ include/grpc++/impl/codegen/stub_options.h \ include/grpc++/impl/codegen/sync_stream.h \ include/grpc++/impl/codegen/time.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/exec_ctx_fwd.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/slice.h \ include/grpc/impl/codegen/status.h \ include/grpc/impl/codegen/atm.h \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/sync.h \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ include/grpc/byte_buffer.h \ include/grpc/byte_buffer_reader.h \ include/grpc/compression.h \ include/grpc/grpc.h \ include/grpc/grpc_posix.h \ include/grpc/grpc_security_constants.h \ include/grpc/load_reporting.h \ include/grpc/slice.h \ include/grpc/slice_buffer.h \ include/grpc/status.h \ LIBGRPC++_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_UNSECURE_SRC)))) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a: protobuf_dep_error $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBGRPC++_UNSECURE_OBJS) $(LIBGPR_OBJS) $(ZLIB_MERGE_OBJS) $(CARES_MERGE_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBGRPC++_UNSECURE_OBJS) $(LIBGPR_OBJS) $(ZLIB_MERGE_OBJS) $(CARES_MERGE_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a endif ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr$(SHARED_VERSION_CORE)-dll -lgrpc_unsecure$(SHARED_VERSION_CORE)-dll else $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT_CORE) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_unsecure else $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_unsecure.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_unsecure $(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so.1 $(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so endif endif endif ifneq ($(NO_DEPS),true) -include $(LIBGRPC++_UNSECURE_OBJS:.o=.dep) endif LIBGRPC_BENCHMARK_SRC = \ test/cpp/microbenchmarks/helpers.cc \ PUBLIC_HEADERS_CXX += \ LIBGRPC_BENCHMARK_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_BENCHMARK_SRC)))) $(LIBGRPC_BENCHMARK_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBGRPC_BENCHMARK_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBGRPC_BENCHMARK_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a endif endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBGRPC_BENCHMARK_OBJS:.o=.dep) endif endif LIBGRPC_CLI_LIBS_SRC = \ test/cpp/util/cli_call.cc \ test/cpp/util/cli_credentials.cc \ test/cpp/util/grpc_tool.cc \ test/cpp/util/proto_file_parser.cc \ test/cpp/util/service_describer.cc \ $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.pb.cc $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc \ PUBLIC_HEADERS_CXX += \ include/grpc++/impl/codegen/config_protobuf.h \ LIBGRPC_CLI_LIBS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_CLI_LIBS_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBGRPC_CLI_LIBS_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBGRPC_CLI_LIBS_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a endif endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBGRPC_CLI_LIBS_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/test/cpp/util/cli_call.o: $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.pb.cc $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/util/cli_credentials.o: $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.pb.cc $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/util/grpc_tool.o: $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.pb.cc $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/util/proto_file_parser.o: $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.pb.cc $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/util/service_describer.o: $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.pb.cc $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc LIBGRPC_PLUGIN_SUPPORT_SRC = \ src/compiler/cpp_generator.cc \ src/compiler/csharp_generator.cc \ src/compiler/node_generator.cc \ src/compiler/objective_c_generator.cc \ src/compiler/php_generator.cc \ src/compiler/python_generator.cc \ src/compiler/ruby_generator.cc \ PUBLIC_HEADERS_CXX += \ include/grpc++/impl/codegen/config_protobuf.h \ LIBGRPC_PLUGIN_SUPPORT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_PLUGIN_SUPPORT_SRC)))) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBGRPC_PLUGIN_SUPPORT_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(LIBGRPC_PLUGIN_SUPPORT_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBGRPC_PLUGIN_SUPPORT_OBJS:.o=.dep) endif LIBHTTP2_CLIENT_MAIN_SRC = \ $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc \ test/cpp/interop/http2_client.cc \ PUBLIC_HEADERS_CXX += \ LIBHTTP2_CLIENT_MAIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBHTTP2_CLIENT_MAIN_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBHTTP2_CLIENT_MAIN_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBHTTP2_CLIENT_MAIN_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a endif endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBHTTP2_CLIENT_MAIN_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/test/cpp/interop/http2_client.o: $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc LIBINTEROP_CLIENT_HELPER_SRC = \ $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \ test/cpp/interop/client_helper.cc \ PUBLIC_HEADERS_CXX += \ LIBINTEROP_CLIENT_HELPER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBINTEROP_CLIENT_HELPER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBINTEROP_CLIENT_HELPER_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBINTEROP_CLIENT_HELPER_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a endif endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBINTEROP_CLIENT_HELPER_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/test/cpp/interop/client_helper.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc LIBINTEROP_CLIENT_MAIN_SRC = \ $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc \ test/cpp/interop/client.cc \ test/cpp/interop/interop_client.cc \ PUBLIC_HEADERS_CXX += \ LIBINTEROP_CLIENT_MAIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBINTEROP_CLIENT_MAIN_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libinterop_client_main.a: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libinterop_client_main.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libinterop_client_main.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBINTEROP_CLIENT_MAIN_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBINTEROP_CLIENT_MAIN_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libinterop_client_main.a endif endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBINTEROP_CLIENT_MAIN_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/test/cpp/interop/client.o: $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/interop/interop_client.o: $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc LIBINTEROP_SERVER_HELPER_SRC = \ test/cpp/interop/server_helper.cc \ PUBLIC_HEADERS_CXX += \ LIBINTEROP_SERVER_HELPER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBINTEROP_SERVER_HELPER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBINTEROP_SERVER_HELPER_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBINTEROP_SERVER_HELPER_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a endif endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBINTEROP_SERVER_HELPER_OBJS:.o=.dep) endif endif LIBINTEROP_SERVER_LIB_SRC = \ $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc \ test/cpp/interop/interop_server.cc \ PUBLIC_HEADERS_CXX += \ LIBINTEROP_SERVER_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBINTEROP_SERVER_LIB_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBINTEROP_SERVER_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBINTEROP_SERVER_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a endif endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBINTEROP_SERVER_LIB_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/test/cpp/interop/interop_server.o: $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc LIBINTEROP_SERVER_MAIN_SRC = \ test/cpp/interop/interop_server_bootstrap.cc \ PUBLIC_HEADERS_CXX += \ LIBINTEROP_SERVER_MAIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBINTEROP_SERVER_MAIN_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libinterop_server_main.a: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libinterop_server_main.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libinterop_server_main.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBINTEROP_SERVER_MAIN_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBINTEROP_SERVER_MAIN_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libinterop_server_main.a endif endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBINTEROP_SERVER_MAIN_OBJS:.o=.dep) endif endif LIBQPS_SRC = \ $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc \ test/cpp/qps/benchmark_config.cc \ test/cpp/qps/client_async.cc \ test/cpp/qps/client_sync.cc \ test/cpp/qps/driver.cc \ test/cpp/qps/parse_json.cc \ test/cpp/qps/qps_worker.cc \ test/cpp/qps/report.cc \ test/cpp/qps/server_async.cc \ test/cpp/qps/server_sync.cc \ test/cpp/qps/usage_timer.cc \ PUBLIC_HEADERS_CXX += \ LIBQPS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBQPS_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libqps.a: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libqps.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libqps.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBQPS_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libqps.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBQPS_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libqps.a endif endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBQPS_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/test/cpp/qps/benchmark_config.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/qps/client_async.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/qps/client_sync.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/qps/driver.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/qps/parse_json.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_worker.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/qps/report.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/qps/server_async.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/qps/server_sync.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/qps/usage_timer.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc LIBGRPC_CSHARP_EXT_SRC = \ src/csharp/ext/grpc_csharp_ext.c \ PUBLIC_HEADERS_C += \ LIBGRPC_CSHARP_EXT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_CSHARP_EXT_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.a: openssl_dep_error $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP): openssl_dep_error else $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(LIBGRPC_CSHARP_EXT_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.a $(LIBGRPC_CSHARP_EXT_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.a endif ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP): $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CSHARP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBS) else $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP): $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) $(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBS) else $(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_csharp_ext.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBS) $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).so.1 $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).so endif endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBGRPC_CSHARP_EXT_OBJS:.o=.dep) endif endif LIBBORINGSSL_SRC = \ src/boringssl/err_data.c \ third_party/boringssl/crypto/aes/aes.c \ third_party/boringssl/crypto/aes/mode_wrappers.c \ third_party/boringssl/crypto/asn1/a_bitstr.c \ third_party/boringssl/crypto/asn1/a_bool.c \ third_party/boringssl/crypto/asn1/a_d2i_fp.c \ third_party/boringssl/crypto/asn1/a_dup.c \ third_party/boringssl/crypto/asn1/a_enum.c \ third_party/boringssl/crypto/asn1/a_gentm.c \ third_party/boringssl/crypto/asn1/a_i2d_fp.c \ third_party/boringssl/crypto/asn1/a_int.c \ third_party/boringssl/crypto/asn1/a_mbstr.c \ third_party/boringssl/crypto/asn1/a_object.c \ third_party/boringssl/crypto/asn1/a_octet.c \ third_party/boringssl/crypto/asn1/a_print.c \ third_party/boringssl/crypto/asn1/a_strnid.c \ third_party/boringssl/crypto/asn1/a_time.c \ third_party/boringssl/crypto/asn1/a_type.c \ third_party/boringssl/crypto/asn1/a_utctm.c \ third_party/boringssl/crypto/asn1/a_utf8.c \ third_party/boringssl/crypto/asn1/asn1_lib.c \ third_party/boringssl/crypto/asn1/asn1_par.c \ third_party/boringssl/crypto/asn1/asn_pack.c \ third_party/boringssl/crypto/asn1/f_enum.c \ third_party/boringssl/crypto/asn1/f_int.c \ third_party/boringssl/crypto/asn1/f_string.c \ third_party/boringssl/crypto/asn1/t_bitst.c \ third_party/boringssl/crypto/asn1/tasn_dec.c \ third_party/boringssl/crypto/asn1/tasn_enc.c \ third_party/boringssl/crypto/asn1/tasn_fre.c \ third_party/boringssl/crypto/asn1/tasn_new.c \ third_party/boringssl/crypto/asn1/tasn_typ.c \ third_party/boringssl/crypto/asn1/tasn_utl.c \ third_party/boringssl/crypto/asn1/x_bignum.c \ third_party/boringssl/crypto/asn1/x_long.c \ third_party/boringssl/crypto/base64/base64.c \ third_party/boringssl/crypto/bio/bio.c \ third_party/boringssl/crypto/bio/bio_mem.c \ third_party/boringssl/crypto/bio/buffer.c \ third_party/boringssl/crypto/bio/connect.c \ third_party/boringssl/crypto/bio/fd.c \ third_party/boringssl/crypto/bio/file.c \ third_party/boringssl/crypto/bio/hexdump.c \ third_party/boringssl/crypto/bio/pair.c \ third_party/boringssl/crypto/bio/printf.c \ third_party/boringssl/crypto/bio/socket.c \ third_party/boringssl/crypto/bio/socket_helper.c \ third_party/boringssl/crypto/bn/add.c \ third_party/boringssl/crypto/bn/asm/x86_64-gcc.c \ third_party/boringssl/crypto/bn/bn.c \ third_party/boringssl/crypto/bn/bn_asn1.c \ third_party/boringssl/crypto/bn/cmp.c \ third_party/boringssl/crypto/bn/convert.c \ third_party/boringssl/crypto/bn/ctx.c \ third_party/boringssl/crypto/bn/div.c \ third_party/boringssl/crypto/bn/exponentiation.c \ third_party/boringssl/crypto/bn/gcd.c \ third_party/boringssl/crypto/bn/generic.c \ third_party/boringssl/crypto/bn/kronecker.c \ third_party/boringssl/crypto/bn/montgomery.c \ third_party/boringssl/crypto/bn/montgomery_inv.c \ third_party/boringssl/crypto/bn/mul.c \ third_party/boringssl/crypto/bn/prime.c \ third_party/boringssl/crypto/bn/random.c \ third_party/boringssl/crypto/bn/rsaz_exp.c \ third_party/boringssl/crypto/bn/shift.c \ third_party/boringssl/crypto/bn/sqrt.c \ third_party/boringssl/crypto/buf/buf.c \ third_party/boringssl/crypto/bytestring/asn1_compat.c \ third_party/boringssl/crypto/bytestring/ber.c \ third_party/boringssl/crypto/bytestring/cbb.c \ third_party/boringssl/crypto/bytestring/cbs.c \ third_party/boringssl/crypto/chacha/chacha.c \ third_party/boringssl/crypto/cipher/aead.c \ third_party/boringssl/crypto/cipher/cipher.c \ third_party/boringssl/crypto/cipher/derive_key.c \ third_party/boringssl/crypto/cipher/e_aes.c \ third_party/boringssl/crypto/cipher/e_chacha20poly1305.c \ third_party/boringssl/crypto/cipher/e_des.c \ third_party/boringssl/crypto/cipher/e_null.c \ third_party/boringssl/crypto/cipher/e_rc2.c \ third_party/boringssl/crypto/cipher/e_rc4.c \ third_party/boringssl/crypto/cipher/e_ssl3.c \ third_party/boringssl/crypto/cipher/e_tls.c \ third_party/boringssl/crypto/cipher/tls_cbc.c \ third_party/boringssl/crypto/cmac/cmac.c \ third_party/boringssl/crypto/conf/conf.c \ third_party/boringssl/crypto/cpu-aarch64-linux.c \ third_party/boringssl/crypto/cpu-arm-linux.c \ third_party/boringssl/crypto/cpu-arm.c \ third_party/boringssl/crypto/cpu-intel.c \ third_party/boringssl/crypto/cpu-ppc64le.c \ third_party/boringssl/crypto/crypto.c \ third_party/boringssl/crypto/curve25519/curve25519.c \ third_party/boringssl/crypto/curve25519/spake25519.c \ third_party/boringssl/crypto/curve25519/x25519-x86_64.c \ third_party/boringssl/crypto/des/des.c \ third_party/boringssl/crypto/dh/check.c \ third_party/boringssl/crypto/dh/dh.c \ third_party/boringssl/crypto/dh/dh_asn1.c \ third_party/boringssl/crypto/dh/params.c \ third_party/boringssl/crypto/digest/digest.c \ third_party/boringssl/crypto/digest/digests.c \ third_party/boringssl/crypto/dsa/dsa.c \ third_party/boringssl/crypto/dsa/dsa_asn1.c \ third_party/boringssl/crypto/ec/ec.c \ third_party/boringssl/crypto/ec/ec_asn1.c \ third_party/boringssl/crypto/ec/ec_key.c \ third_party/boringssl/crypto/ec/ec_montgomery.c \ third_party/boringssl/crypto/ec/oct.c \ third_party/boringssl/crypto/ec/p224-64.c \ third_party/boringssl/crypto/ec/p256-64.c \ third_party/boringssl/crypto/ec/p256-x86_64.c \ third_party/boringssl/crypto/ec/simple.c \ third_party/boringssl/crypto/ec/util-64.c \ third_party/boringssl/crypto/ec/wnaf.c \ third_party/boringssl/crypto/ecdh/ecdh.c \ third_party/boringssl/crypto/ecdsa/ecdsa.c \ third_party/boringssl/crypto/ecdsa/ecdsa_asn1.c \ third_party/boringssl/crypto/engine/engine.c \ third_party/boringssl/crypto/err/err.c \ third_party/boringssl/crypto/evp/digestsign.c \ third_party/boringssl/crypto/evp/evp.c \ third_party/boringssl/crypto/evp/evp_asn1.c \ third_party/boringssl/crypto/evp/evp_ctx.c \ third_party/boringssl/crypto/evp/p_dsa_asn1.c \ third_party/boringssl/crypto/evp/p_ec.c \ third_party/boringssl/crypto/evp/p_ec_asn1.c \ third_party/boringssl/crypto/evp/p_rsa.c \ third_party/boringssl/crypto/evp/p_rsa_asn1.c \ third_party/boringssl/crypto/evp/pbkdf.c \ third_party/boringssl/crypto/evp/print.c \ third_party/boringssl/crypto/evp/sign.c \ third_party/boringssl/crypto/ex_data.c \ third_party/boringssl/crypto/hkdf/hkdf.c \ third_party/boringssl/crypto/hmac/hmac.c \ third_party/boringssl/crypto/lhash/lhash.c \ third_party/boringssl/crypto/md4/md4.c \ third_party/boringssl/crypto/md5/md5.c \ third_party/boringssl/crypto/mem.c \ third_party/boringssl/crypto/modes/cbc.c \ third_party/boringssl/crypto/modes/cfb.c \ third_party/boringssl/crypto/modes/ctr.c \ third_party/boringssl/crypto/modes/gcm.c \ third_party/boringssl/crypto/modes/ofb.c \ third_party/boringssl/crypto/newhope/error_correction.c \ third_party/boringssl/crypto/newhope/newhope.c \ third_party/boringssl/crypto/newhope/ntt.c \ third_party/boringssl/crypto/newhope/poly.c \ third_party/boringssl/crypto/newhope/precomp.c \ third_party/boringssl/crypto/newhope/reduce.c \ third_party/boringssl/crypto/obj/obj.c \ third_party/boringssl/crypto/obj/obj_xref.c \ third_party/boringssl/crypto/pem/pem_all.c \ third_party/boringssl/crypto/pem/pem_info.c \ third_party/boringssl/crypto/pem/pem_lib.c \ third_party/boringssl/crypto/pem/pem_oth.c \ third_party/boringssl/crypto/pem/pem_pk8.c \ third_party/boringssl/crypto/pem/pem_pkey.c \ third_party/boringssl/crypto/pem/pem_x509.c \ third_party/boringssl/crypto/pem/pem_xaux.c \ third_party/boringssl/crypto/pkcs8/p5_pbe.c \ third_party/boringssl/crypto/pkcs8/p5_pbev2.c \ third_party/boringssl/crypto/pkcs8/p8_pkey.c \ third_party/boringssl/crypto/pkcs8/pkcs8.c \ third_party/boringssl/crypto/poly1305/poly1305.c \ third_party/boringssl/crypto/poly1305/poly1305_arm.c \ third_party/boringssl/crypto/poly1305/poly1305_vec.c \ third_party/boringssl/crypto/rand/deterministic.c \ third_party/boringssl/crypto/rand/rand.c \ third_party/boringssl/crypto/rand/urandom.c \ third_party/boringssl/crypto/rand/windows.c \ third_party/boringssl/crypto/rc4/rc4.c \ third_party/boringssl/crypto/refcount_c11.c \ third_party/boringssl/crypto/refcount_lock.c \ third_party/boringssl/crypto/rsa/blinding.c \ third_party/boringssl/crypto/rsa/padding.c \ third_party/boringssl/crypto/rsa/rsa.c \ third_party/boringssl/crypto/rsa/rsa_asn1.c \ third_party/boringssl/crypto/rsa/rsa_impl.c \ third_party/boringssl/crypto/sha/sha1.c \ third_party/boringssl/crypto/sha/sha256.c \ third_party/boringssl/crypto/sha/sha512.c \ third_party/boringssl/crypto/stack/stack.c \ third_party/boringssl/crypto/thread.c \ third_party/boringssl/crypto/thread_none.c \ third_party/boringssl/crypto/thread_pthread.c \ third_party/boringssl/crypto/thread_win.c \ third_party/boringssl/crypto/time_support.c \ third_party/boringssl/crypto/x509/a_digest.c \ third_party/boringssl/crypto/x509/a_sign.c \ third_party/boringssl/crypto/x509/a_strex.c \ third_party/boringssl/crypto/x509/a_verify.c \ third_party/boringssl/crypto/x509/algorithm.c \ third_party/boringssl/crypto/x509/asn1_gen.c \ third_party/boringssl/crypto/x509/by_dir.c \ third_party/boringssl/crypto/x509/by_file.c \ third_party/boringssl/crypto/x509/i2d_pr.c \ third_party/boringssl/crypto/x509/pkcs7.c \ third_party/boringssl/crypto/x509/rsa_pss.c \ third_party/boringssl/crypto/x509/t_crl.c \ third_party/boringssl/crypto/x509/t_req.c \ third_party/boringssl/crypto/x509/t_x509.c \ third_party/boringssl/crypto/x509/t_x509a.c \ third_party/boringssl/crypto/x509/x509.c \ third_party/boringssl/crypto/x509/x509_att.c \ third_party/boringssl/crypto/x509/x509_cmp.c \ third_party/boringssl/crypto/x509/x509_d2.c \ third_party/boringssl/crypto/x509/x509_def.c \ third_party/boringssl/crypto/x509/x509_ext.c \ third_party/boringssl/crypto/x509/x509_lu.c \ third_party/boringssl/crypto/x509/x509_obj.c \ third_party/boringssl/crypto/x509/x509_r2x.c \ third_party/boringssl/crypto/x509/x509_req.c \ third_party/boringssl/crypto/x509/x509_set.c \ third_party/boringssl/crypto/x509/x509_trs.c \ third_party/boringssl/crypto/x509/x509_txt.c \ third_party/boringssl/crypto/x509/x509_v3.c \ third_party/boringssl/crypto/x509/x509_vfy.c \ third_party/boringssl/crypto/x509/x509_vpm.c \ third_party/boringssl/crypto/x509/x509cset.c \ third_party/boringssl/crypto/x509/x509name.c \ third_party/boringssl/crypto/x509/x509rset.c \ third_party/boringssl/crypto/x509/x509spki.c \ third_party/boringssl/crypto/x509/x509type.c \ third_party/boringssl/crypto/x509/x_algor.c \ third_party/boringssl/crypto/x509/x_all.c \ third_party/boringssl/crypto/x509/x_attrib.c \ third_party/boringssl/crypto/x509/x_crl.c \ third_party/boringssl/crypto/x509/x_exten.c \ third_party/boringssl/crypto/x509/x_info.c \ third_party/boringssl/crypto/x509/x_name.c \ third_party/boringssl/crypto/x509/x_pkey.c \ third_party/boringssl/crypto/x509/x_pubkey.c \ third_party/boringssl/crypto/x509/x_req.c \ third_party/boringssl/crypto/x509/x_sig.c \ third_party/boringssl/crypto/x509/x_spki.c \ third_party/boringssl/crypto/x509/x_val.c \ third_party/boringssl/crypto/x509/x_x509.c \ third_party/boringssl/crypto/x509/x_x509a.c \ third_party/boringssl/crypto/x509v3/pcy_cache.c \ third_party/boringssl/crypto/x509v3/pcy_data.c \ third_party/boringssl/crypto/x509v3/pcy_lib.c \ third_party/boringssl/crypto/x509v3/pcy_map.c \ third_party/boringssl/crypto/x509v3/pcy_node.c \ third_party/boringssl/crypto/x509v3/pcy_tree.c \ third_party/boringssl/crypto/x509v3/v3_akey.c \ third_party/boringssl/crypto/x509v3/v3_akeya.c \ third_party/boringssl/crypto/x509v3/v3_alt.c \ third_party/boringssl/crypto/x509v3/v3_bcons.c \ third_party/boringssl/crypto/x509v3/v3_bitst.c \ third_party/boringssl/crypto/x509v3/v3_conf.c \ third_party/boringssl/crypto/x509v3/v3_cpols.c \ third_party/boringssl/crypto/x509v3/v3_crld.c \ third_party/boringssl/crypto/x509v3/v3_enum.c \ third_party/boringssl/crypto/x509v3/v3_extku.c \ third_party/boringssl/crypto/x509v3/v3_genn.c \ third_party/boringssl/crypto/x509v3/v3_ia5.c \ third_party/boringssl/crypto/x509v3/v3_info.c \ third_party/boringssl/crypto/x509v3/v3_int.c \ third_party/boringssl/crypto/x509v3/v3_lib.c \ third_party/boringssl/crypto/x509v3/v3_ncons.c \ third_party/boringssl/crypto/x509v3/v3_pci.c \ third_party/boringssl/crypto/x509v3/v3_pcia.c \ third_party/boringssl/crypto/x509v3/v3_pcons.c \ third_party/boringssl/crypto/x509v3/v3_pku.c \ third_party/boringssl/crypto/x509v3/v3_pmaps.c \ third_party/boringssl/crypto/x509v3/v3_prn.c \ third_party/boringssl/crypto/x509v3/v3_purp.c \ third_party/boringssl/crypto/x509v3/v3_skey.c \ third_party/boringssl/crypto/x509v3/v3_sxnet.c \ third_party/boringssl/crypto/x509v3/v3_utl.c \ third_party/boringssl/ssl/custom_extensions.c \ third_party/boringssl/ssl/d1_both.c \ third_party/boringssl/ssl/d1_lib.c \ third_party/boringssl/ssl/d1_pkt.c \ third_party/boringssl/ssl/d1_srtp.c \ third_party/boringssl/ssl/dtls_method.c \ third_party/boringssl/ssl/dtls_record.c \ third_party/boringssl/ssl/handshake_client.c \ third_party/boringssl/ssl/handshake_server.c \ third_party/boringssl/ssl/s3_both.c \ third_party/boringssl/ssl/s3_enc.c \ third_party/boringssl/ssl/s3_lib.c \ third_party/boringssl/ssl/s3_pkt.c \ third_party/boringssl/ssl/ssl_aead_ctx.c \ third_party/boringssl/ssl/ssl_asn1.c \ third_party/boringssl/ssl/ssl_buffer.c \ third_party/boringssl/ssl/ssl_cert.c \ third_party/boringssl/ssl/ssl_cipher.c \ third_party/boringssl/ssl/ssl_ecdh.c \ third_party/boringssl/ssl/ssl_file.c \ third_party/boringssl/ssl/ssl_lib.c \ third_party/boringssl/ssl/ssl_rsa.c \ third_party/boringssl/ssl/ssl_session.c \ third_party/boringssl/ssl/ssl_stat.c \ third_party/boringssl/ssl/t1_enc.c \ third_party/boringssl/ssl/t1_lib.c \ third_party/boringssl/ssl/tls13_both.c \ third_party/boringssl/ssl/tls13_client.c \ third_party/boringssl/ssl/tls13_enc.c \ third_party/boringssl/ssl/tls13_server.c \ third_party/boringssl/ssl/tls_method.c \ third_party/boringssl/ssl/tls_record.c \ PUBLIC_HEADERS_C += \ LIBBORINGSSL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_SRC)))) $(LIBBORINGSSL_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) $(LIBDIR)/$(CONFIG)/libboringssl.a: $(ZLIB_DEP) $(CARES_DEP) $(LIBBORINGSSL_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl.a $(LIBBORINGSSL_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl.a endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_OBJS:.o=.dep) endif LIBBORINGSSL_TEST_UTIL_SRC = \ third_party/boringssl/crypto/test/file_test.cc \ third_party/boringssl/crypto/test/malloc.cc \ third_party/boringssl/crypto/test/test_util.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_TEST_UTIL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_TEST_UTIL_SRC)))) $(LIBBORINGSSL_TEST_UTIL_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_TEST_UTIL_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_TEST_UTIL_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBBORINGSSL_TEST_UTIL_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_TEST_UTIL_OBJS:.o=.dep) endif LIBBORINGSSL_AES_TEST_LIB_SRC = \ third_party/boringssl/crypto/aes/aes_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_AES_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_AES_TEST_LIB_SRC)))) $(LIBBORINGSSL_AES_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_AES_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_AES_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBBORINGSSL_AES_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_AES_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_ASN1_TEST_LIB_SRC = \ third_party/boringssl/crypto/asn1/asn1_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_ASN1_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_ASN1_TEST_LIB_SRC)))) $(LIBBORINGSSL_ASN1_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_ASN1_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_ASN1_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBBORINGSSL_ASN1_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_ASN1_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_BASE64_TEST_LIB_SRC = \ third_party/boringssl/crypto/base64/base64_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_BASE64_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_BASE64_TEST_LIB_SRC)))) $(LIBBORINGSSL_BASE64_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_BASE64_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_BASE64_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBBORINGSSL_BASE64_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_BASE64_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_BIO_TEST_LIB_SRC = \ third_party/boringssl/crypto/bio/bio_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_BIO_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_BIO_TEST_LIB_SRC)))) $(LIBBORINGSSL_BIO_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_BIO_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_BIO_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBBORINGSSL_BIO_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_BIO_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_BN_TEST_LIB_SRC = \ third_party/boringssl/crypto/bn/bn_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_BN_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_BN_TEST_LIB_SRC)))) $(LIBBORINGSSL_BN_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_BN_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_BN_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBBORINGSSL_BN_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_BN_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_BYTESTRING_TEST_LIB_SRC = \ third_party/boringssl/crypto/bytestring/bytestring_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_BYTESTRING_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_BYTESTRING_TEST_LIB_SRC)))) $(LIBBORINGSSL_BYTESTRING_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_BYTESTRING_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_BYTESTRING_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBBORINGSSL_BYTESTRING_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_BYTESTRING_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_CHACHA_TEST_LIB_SRC = \ third_party/boringssl/crypto/chacha/chacha_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_CHACHA_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_CHACHA_TEST_LIB_SRC)))) $(LIBBORINGSSL_CHACHA_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_CHACHA_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_chacha_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_chacha_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_CHACHA_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_chacha_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_chacha_test_lib.a $(LIBBORINGSSL_CHACHA_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_chacha_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_CHACHA_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_AEAD_TEST_LIB_SRC = \ third_party/boringssl/crypto/cipher/aead_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_AEAD_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_AEAD_TEST_LIB_SRC)))) $(LIBBORINGSSL_AEAD_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_AEAD_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_AEAD_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBBORINGSSL_AEAD_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_AEAD_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_CIPHER_TEST_LIB_SRC = \ third_party/boringssl/crypto/cipher/cipher_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_CIPHER_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_CIPHER_TEST_LIB_SRC)))) $(LIBBORINGSSL_CIPHER_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_CIPHER_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_CIPHER_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBBORINGSSL_CIPHER_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_CIPHER_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_CMAC_TEST_LIB_SRC = \ third_party/boringssl/crypto/cmac/cmac_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_CMAC_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_CMAC_TEST_LIB_SRC)))) $(LIBBORINGSSL_CMAC_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_CMAC_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_CMAC_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBBORINGSSL_CMAC_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_CMAC_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_CONSTANT_TIME_TEST_LIB_SRC = \ third_party/boringssl/crypto/constant_time_test.c \ PUBLIC_HEADERS_C += \ LIBBORINGSSL_CONSTANT_TIME_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_CONSTANT_TIME_TEST_LIB_SRC)))) $(LIBBORINGSSL_CONSTANT_TIME_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_CONSTANT_TIME_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) $(LIBDIR)/$(CONFIG)/libboringssl_constant_time_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(LIBBORINGSSL_CONSTANT_TIME_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_constant_time_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_constant_time_test_lib.a $(LIBBORINGSSL_CONSTANT_TIME_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_constant_time_test_lib.a endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_CONSTANT_TIME_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_ED25519_TEST_LIB_SRC = \ third_party/boringssl/crypto/curve25519/ed25519_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_ED25519_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_ED25519_TEST_LIB_SRC)))) $(LIBBORINGSSL_ED25519_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_ED25519_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_ED25519_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBBORINGSSL_ED25519_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_ED25519_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_SPAKE25519_TEST_LIB_SRC = \ third_party/boringssl/crypto/curve25519/spake25519_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_SPAKE25519_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_SPAKE25519_TEST_LIB_SRC)))) $(LIBBORINGSSL_SPAKE25519_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_SPAKE25519_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_spake25519_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_spake25519_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_SPAKE25519_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_spake25519_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_spake25519_test_lib.a $(LIBBORINGSSL_SPAKE25519_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_spake25519_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_SPAKE25519_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_X25519_TEST_LIB_SRC = \ third_party/boringssl/crypto/curve25519/x25519_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_X25519_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_X25519_TEST_LIB_SRC)))) $(LIBBORINGSSL_X25519_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_X25519_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_X25519_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBBORINGSSL_X25519_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_X25519_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_DH_TEST_LIB_SRC = \ third_party/boringssl/crypto/dh/dh_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_DH_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_DH_TEST_LIB_SRC)))) $(LIBBORINGSSL_DH_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_DH_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_DH_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBBORINGSSL_DH_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_DH_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_DIGEST_TEST_LIB_SRC = \ third_party/boringssl/crypto/digest/digest_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_DIGEST_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_DIGEST_TEST_LIB_SRC)))) $(LIBBORINGSSL_DIGEST_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_DIGEST_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_DIGEST_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBBORINGSSL_DIGEST_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_DIGEST_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_DSA_TEST_LIB_SRC = \ third_party/boringssl/crypto/dsa/dsa_test.c \ PUBLIC_HEADERS_C += \ LIBBORINGSSL_DSA_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_DSA_TEST_LIB_SRC)))) $(LIBBORINGSSL_DSA_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_DSA_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) $(LIBDIR)/$(CONFIG)/libboringssl_dsa_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(LIBBORINGSSL_DSA_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_dsa_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_dsa_test_lib.a $(LIBBORINGSSL_DSA_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_dsa_test_lib.a endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_DSA_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_EC_TEST_LIB_SRC = \ third_party/boringssl/crypto/ec/ec_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_EC_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_EC_TEST_LIB_SRC)))) $(LIBBORINGSSL_EC_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_EC_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_EC_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBBORINGSSL_EC_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_EC_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_EXAMPLE_MUL_LIB_SRC = \ third_party/boringssl/crypto/ec/example_mul.c \ PUBLIC_HEADERS_C += \ LIBBORINGSSL_EXAMPLE_MUL_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_EXAMPLE_MUL_LIB_SRC)))) $(LIBBORINGSSL_EXAMPLE_MUL_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_EXAMPLE_MUL_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) $(LIBDIR)/$(CONFIG)/libboringssl_example_mul_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(LIBBORINGSSL_EXAMPLE_MUL_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_example_mul_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_example_mul_lib.a $(LIBBORINGSSL_EXAMPLE_MUL_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_example_mul_lib.a endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_EXAMPLE_MUL_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_ECDH_TEST_LIB_SRC = \ third_party/boringssl/crypto/ecdh/ecdh_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_ECDH_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_ECDH_TEST_LIB_SRC)))) $(LIBBORINGSSL_ECDH_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_ECDH_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_ecdh_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_ecdh_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_ECDH_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_ecdh_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_ecdh_test_lib.a $(LIBBORINGSSL_ECDH_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_ecdh_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_ECDH_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_ECDSA_SIGN_TEST_LIB_SRC = \ third_party/boringssl/crypto/ecdsa/ecdsa_sign_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_ECDSA_SIGN_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_ECDSA_SIGN_TEST_LIB_SRC)))) $(LIBBORINGSSL_ECDSA_SIGN_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_ECDSA_SIGN_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_sign_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_sign_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_ECDSA_SIGN_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_sign_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_sign_test_lib.a $(LIBBORINGSSL_ECDSA_SIGN_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_sign_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_ECDSA_SIGN_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_ECDSA_TEST_LIB_SRC = \ third_party/boringssl/crypto/ecdsa/ecdsa_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_ECDSA_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_ECDSA_TEST_LIB_SRC)))) $(LIBBORINGSSL_ECDSA_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_ECDSA_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_ECDSA_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBBORINGSSL_ECDSA_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_ECDSA_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_ECDSA_VERIFY_TEST_LIB_SRC = \ third_party/boringssl/crypto/ecdsa/ecdsa_verify_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_ECDSA_VERIFY_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_ECDSA_VERIFY_TEST_LIB_SRC)))) $(LIBBORINGSSL_ECDSA_VERIFY_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_ECDSA_VERIFY_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_verify_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_verify_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_ECDSA_VERIFY_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_verify_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_verify_test_lib.a $(LIBBORINGSSL_ECDSA_VERIFY_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_verify_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_ECDSA_VERIFY_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_ERR_TEST_LIB_SRC = \ third_party/boringssl/crypto/err/err_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_ERR_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_ERR_TEST_LIB_SRC)))) $(LIBBORINGSSL_ERR_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_ERR_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_ERR_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBBORINGSSL_ERR_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_ERR_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_EVP_EXTRA_TEST_LIB_SRC = \ third_party/boringssl/crypto/evp/evp_extra_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_EVP_EXTRA_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_EVP_EXTRA_TEST_LIB_SRC)))) $(LIBBORINGSSL_EVP_EXTRA_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_EVP_EXTRA_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_EVP_EXTRA_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBBORINGSSL_EVP_EXTRA_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_EVP_EXTRA_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_EVP_TEST_LIB_SRC = \ third_party/boringssl/crypto/evp/evp_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_EVP_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_EVP_TEST_LIB_SRC)))) $(LIBBORINGSSL_EVP_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_EVP_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_EVP_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBBORINGSSL_EVP_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_EVP_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_PBKDF_TEST_LIB_SRC = \ third_party/boringssl/crypto/evp/pbkdf_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_PBKDF_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_PBKDF_TEST_LIB_SRC)))) $(LIBBORINGSSL_PBKDF_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_PBKDF_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_PBKDF_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBBORINGSSL_PBKDF_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_PBKDF_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_HKDF_TEST_LIB_SRC = \ third_party/boringssl/crypto/hkdf/hkdf_test.c \ PUBLIC_HEADERS_C += \ LIBBORINGSSL_HKDF_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_HKDF_TEST_LIB_SRC)))) $(LIBBORINGSSL_HKDF_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_HKDF_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) $(LIBDIR)/$(CONFIG)/libboringssl_hkdf_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(LIBBORINGSSL_HKDF_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_hkdf_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_hkdf_test_lib.a $(LIBBORINGSSL_HKDF_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_hkdf_test_lib.a endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_HKDF_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_HMAC_TEST_LIB_SRC = \ third_party/boringssl/crypto/hmac/hmac_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_HMAC_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_HMAC_TEST_LIB_SRC)))) $(LIBBORINGSSL_HMAC_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_HMAC_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_HMAC_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBBORINGSSL_HMAC_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_HMAC_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_LHASH_TEST_LIB_SRC = \ third_party/boringssl/crypto/lhash/lhash_test.c \ PUBLIC_HEADERS_C += \ LIBBORINGSSL_LHASH_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_LHASH_TEST_LIB_SRC)))) $(LIBBORINGSSL_LHASH_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_LHASH_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) $(LIBDIR)/$(CONFIG)/libboringssl_lhash_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(LIBBORINGSSL_LHASH_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_lhash_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_lhash_test_lib.a $(LIBBORINGSSL_LHASH_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_lhash_test_lib.a endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_LHASH_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_GCM_TEST_LIB_SRC = \ third_party/boringssl/crypto/modes/gcm_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_GCM_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_GCM_TEST_LIB_SRC)))) $(LIBBORINGSSL_GCM_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_GCM_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_gcm_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_gcm_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_GCM_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_gcm_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_gcm_test_lib.a $(LIBBORINGSSL_GCM_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_gcm_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_GCM_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_NEWHOPE_STATISTICAL_TEST_LIB_SRC = \ third_party/boringssl/crypto/newhope/newhope_statistical_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_NEWHOPE_STATISTICAL_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_NEWHOPE_STATISTICAL_TEST_LIB_SRC)))) $(LIBBORINGSSL_NEWHOPE_STATISTICAL_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_NEWHOPE_STATISTICAL_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_newhope_statistical_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_newhope_statistical_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_NEWHOPE_STATISTICAL_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_newhope_statistical_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_newhope_statistical_test_lib.a $(LIBBORINGSSL_NEWHOPE_STATISTICAL_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_newhope_statistical_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_NEWHOPE_STATISTICAL_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_NEWHOPE_TEST_LIB_SRC = \ third_party/boringssl/crypto/newhope/newhope_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_NEWHOPE_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_NEWHOPE_TEST_LIB_SRC)))) $(LIBBORINGSSL_NEWHOPE_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_NEWHOPE_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_newhope_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_newhope_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_NEWHOPE_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_newhope_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_newhope_test_lib.a $(LIBBORINGSSL_NEWHOPE_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_newhope_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_NEWHOPE_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_NEWHOPE_VECTORS_TEST_LIB_SRC = \ third_party/boringssl/crypto/newhope/newhope_vectors_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_NEWHOPE_VECTORS_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_NEWHOPE_VECTORS_TEST_LIB_SRC)))) $(LIBBORINGSSL_NEWHOPE_VECTORS_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_NEWHOPE_VECTORS_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_newhope_vectors_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_newhope_vectors_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_NEWHOPE_VECTORS_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_newhope_vectors_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_newhope_vectors_test_lib.a $(LIBBORINGSSL_NEWHOPE_VECTORS_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_newhope_vectors_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_NEWHOPE_VECTORS_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_OBJ_TEST_LIB_SRC = \ third_party/boringssl/crypto/obj/obj_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_OBJ_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_OBJ_TEST_LIB_SRC)))) $(LIBBORINGSSL_OBJ_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_OBJ_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_obj_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_obj_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_OBJ_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_obj_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_obj_test_lib.a $(LIBBORINGSSL_OBJ_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_obj_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_OBJ_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_PKCS12_TEST_LIB_SRC = \ third_party/boringssl/crypto/pkcs8/pkcs12_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_PKCS12_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_PKCS12_TEST_LIB_SRC)))) $(LIBBORINGSSL_PKCS12_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_PKCS12_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_PKCS12_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBBORINGSSL_PKCS12_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_PKCS12_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_PKCS8_TEST_LIB_SRC = \ third_party/boringssl/crypto/pkcs8/pkcs8_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_PKCS8_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_PKCS8_TEST_LIB_SRC)))) $(LIBBORINGSSL_PKCS8_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_PKCS8_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_PKCS8_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBBORINGSSL_PKCS8_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_PKCS8_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_POLY1305_TEST_LIB_SRC = \ third_party/boringssl/crypto/poly1305/poly1305_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_POLY1305_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_POLY1305_TEST_LIB_SRC)))) $(LIBBORINGSSL_POLY1305_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_POLY1305_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_POLY1305_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBBORINGSSL_POLY1305_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_POLY1305_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_REFCOUNT_TEST_LIB_SRC = \ third_party/boringssl/crypto/refcount_test.c \ PUBLIC_HEADERS_C += \ LIBBORINGSSL_REFCOUNT_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_REFCOUNT_TEST_LIB_SRC)))) $(LIBBORINGSSL_REFCOUNT_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_REFCOUNT_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) $(LIBDIR)/$(CONFIG)/libboringssl_refcount_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(LIBBORINGSSL_REFCOUNT_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_refcount_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_refcount_test_lib.a $(LIBBORINGSSL_REFCOUNT_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_refcount_test_lib.a endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_REFCOUNT_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_RSA_TEST_LIB_SRC = \ third_party/boringssl/crypto/rsa/rsa_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_RSA_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_RSA_TEST_LIB_SRC)))) $(LIBBORINGSSL_RSA_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_RSA_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_RSA_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBBORINGSSL_RSA_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_RSA_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_THREAD_TEST_LIB_SRC = \ third_party/boringssl/crypto/thread_test.c \ PUBLIC_HEADERS_C += \ LIBBORINGSSL_THREAD_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_THREAD_TEST_LIB_SRC)))) $(LIBBORINGSSL_THREAD_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_THREAD_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) $(LIBDIR)/$(CONFIG)/libboringssl_thread_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(LIBBORINGSSL_THREAD_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_thread_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_thread_test_lib.a $(LIBBORINGSSL_THREAD_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_thread_test_lib.a endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_THREAD_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_PKCS7_TEST_LIB_SRC = \ third_party/boringssl/crypto/x509/pkcs7_test.c \ PUBLIC_HEADERS_C += \ LIBBORINGSSL_PKCS7_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_PKCS7_TEST_LIB_SRC)))) $(LIBBORINGSSL_PKCS7_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_PKCS7_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) $(LIBDIR)/$(CONFIG)/libboringssl_pkcs7_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(LIBBORINGSSL_PKCS7_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_pkcs7_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_pkcs7_test_lib.a $(LIBBORINGSSL_PKCS7_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_pkcs7_test_lib.a endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_PKCS7_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_X509_TEST_LIB_SRC = \ third_party/boringssl/crypto/x509/x509_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_X509_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_X509_TEST_LIB_SRC)))) $(LIBBORINGSSL_X509_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_X509_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_X509_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBBORINGSSL_X509_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_X509_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_TAB_TEST_LIB_SRC = \ third_party/boringssl/crypto/x509v3/tab_test.c \ PUBLIC_HEADERS_C += \ LIBBORINGSSL_TAB_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_TAB_TEST_LIB_SRC)))) $(LIBBORINGSSL_TAB_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_TAB_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) $(LIBDIR)/$(CONFIG)/libboringssl_tab_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(LIBBORINGSSL_TAB_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_tab_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_tab_test_lib.a $(LIBBORINGSSL_TAB_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_tab_test_lib.a endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_TAB_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_V3NAME_TEST_LIB_SRC = \ third_party/boringssl/crypto/x509v3/v3name_test.c \ PUBLIC_HEADERS_C += \ LIBBORINGSSL_V3NAME_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_V3NAME_TEST_LIB_SRC)))) $(LIBBORINGSSL_V3NAME_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_V3NAME_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) $(LIBDIR)/$(CONFIG)/libboringssl_v3name_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(LIBBORINGSSL_V3NAME_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_v3name_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_v3name_test_lib.a $(LIBBORINGSSL_V3NAME_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_v3name_test_lib.a endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_V3NAME_TEST_LIB_OBJS:.o=.dep) endif LIBBORINGSSL_SSL_TEST_LIB_SRC = \ third_party/boringssl/ssl/ssl_test.cc \ PUBLIC_HEADERS_CXX += \ LIBBORINGSSL_SSL_TEST_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_SSL_TEST_LIB_SRC)))) $(LIBBORINGSSL_SSL_TEST_LIB_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(LIBBORINGSSL_SSL_TEST_LIB_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBORINGSSL_SSL_TEST_LIB_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a $(LIBBORINGSSL_SSL_TEST_LIB_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBORINGSSL_SSL_TEST_LIB_OBJS:.o=.dep) endif LIBBENCHMARK_SRC = \ third_party/benchmark/src/benchmark.cc \ third_party/benchmark/src/benchmark_register.cc \ third_party/benchmark/src/colorprint.cc \ third_party/benchmark/src/commandlineflags.cc \ third_party/benchmark/src/complexity.cc \ third_party/benchmark/src/console_reporter.cc \ third_party/benchmark/src/csv_reporter.cc \ third_party/benchmark/src/json_reporter.cc \ third_party/benchmark/src/reporter.cc \ third_party/benchmark/src/sleep.cc \ third_party/benchmark/src/string_util.cc \ third_party/benchmark/src/sysinfo.cc \ third_party/benchmark/src/timers.cc \ PUBLIC_HEADERS_CXX += \ LIBBENCHMARK_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBENCHMARK_SRC)))) $(LIBBENCHMARK_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX ifeq ($(NO_PROTOBUF),true) # You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. $(LIBDIR)/$(CONFIG)/libbenchmark.a: protobuf_dep_error else $(LIBDIR)/$(CONFIG)/libbenchmark.a: $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBBENCHMARK_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libbenchmark.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBBENCHMARK_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libbenchmark.a endif endif ifneq ($(NO_DEPS),true) -include $(LIBBENCHMARK_OBJS:.o=.dep) endif LIBZ_SRC = \ third_party/zlib/adler32.c \ third_party/zlib/compress.c \ third_party/zlib/crc32.c \ third_party/zlib/deflate.c \ third_party/zlib/gzclose.c \ third_party/zlib/gzlib.c \ third_party/zlib/gzread.c \ third_party/zlib/gzwrite.c \ third_party/zlib/infback.c \ third_party/zlib/inffast.c \ third_party/zlib/inflate.c \ third_party/zlib/inftrees.c \ third_party/zlib/trees.c \ third_party/zlib/uncompr.c \ third_party/zlib/zutil.c \ PUBLIC_HEADERS_C += \ LIBZ_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBZ_SRC)))) $(LIBZ_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-implicit-function-declaration $(W_NO_SHIFT_NEGATIVE_VALUE) -fvisibility=hidden $(LIBDIR)/$(CONFIG)/libz.a: $(CARES_DEP) $(LIBZ_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libz.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libz.a $(LIBZ_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libz.a endif ifneq ($(NO_DEPS),true) -include $(LIBZ_OBJS:.o=.dep) endif LIBARES_SRC = \ third_party/cares/cares/ares__close_sockets.c \ third_party/cares/cares/ares__get_hostent.c \ third_party/cares/cares/ares__read_line.c \ third_party/cares/cares/ares__timeval.c \ third_party/cares/cares/ares_cancel.c \ third_party/cares/cares/ares_create_query.c \ third_party/cares/cares/ares_data.c \ third_party/cares/cares/ares_destroy.c \ third_party/cares/cares/ares_expand_name.c \ third_party/cares/cares/ares_expand_string.c \ third_party/cares/cares/ares_fds.c \ third_party/cares/cares/ares_free_hostent.c \ third_party/cares/cares/ares_free_string.c \ third_party/cares/cares/ares_getenv.c \ third_party/cares/cares/ares_gethostbyaddr.c \ third_party/cares/cares/ares_gethostbyname.c \ third_party/cares/cares/ares_getnameinfo.c \ third_party/cares/cares/ares_getopt.c \ third_party/cares/cares/ares_getsock.c \ third_party/cares/cares/ares_init.c \ third_party/cares/cares/ares_library_init.c \ third_party/cares/cares/ares_llist.c \ third_party/cares/cares/ares_mkquery.c \ third_party/cares/cares/ares_nowarn.c \ third_party/cares/cares/ares_options.c \ third_party/cares/cares/ares_parse_a_reply.c \ third_party/cares/cares/ares_parse_aaaa_reply.c \ third_party/cares/cares/ares_parse_mx_reply.c \ third_party/cares/cares/ares_parse_naptr_reply.c \ third_party/cares/cares/ares_parse_ns_reply.c \ third_party/cares/cares/ares_parse_ptr_reply.c \ third_party/cares/cares/ares_parse_soa_reply.c \ third_party/cares/cares/ares_parse_srv_reply.c \ third_party/cares/cares/ares_parse_txt_reply.c \ third_party/cares/cares/ares_platform.c \ third_party/cares/cares/ares_process.c \ third_party/cares/cares/ares_query.c \ third_party/cares/cares/ares_search.c \ third_party/cares/cares/ares_send.c \ third_party/cares/cares/ares_strcasecmp.c \ third_party/cares/cares/ares_strdup.c \ third_party/cares/cares/ares_strerror.c \ third_party/cares/cares/ares_timeout.c \ third_party/cares/cares/ares_version.c \ third_party/cares/cares/ares_writev.c \ third_party/cares/cares/bitncmp.c \ third_party/cares/cares/inet_net_pton.c \ third_party/cares/cares/inet_ntop.c \ third_party/cares/cares/windows_port.c \ PUBLIC_HEADERS_C += \ LIBARES_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBARES_SRC)))) $(LIBARES_OBJS): CPPFLAGS += -Ithird_party/cares -Ithird_party/cares/cares $(if $(subst Linux,,$(SYSTEM)),,-Ithird_party/cares/config_linux) $(if $(subst Darwin,,$(SYSTEM)),,-Ithird_party/cares/config_darwin) -fvisibility=hidden -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(if $(subst MINGW32,,$(SYSTEM)),-DHAVE_CONFIG_H,) $(LIBARES_OBJS): CFLAGS += -Wno-sign-conversion $(if $(subst MINGW32,,$(SYSTEM)),-Wno-invalid-source-encoding,) $(LIBDIR)/$(CONFIG)/libares.a: $(ZLIB_DEP) $(LIBARES_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libares.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libares.a $(LIBARES_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libares.a endif ifneq ($(NO_DEPS),true) -include $(LIBARES_OBJS:.o=.dep) endif LIBBAD_CLIENT_TEST_SRC = \ test/core/bad_client/bad_client.c \ PUBLIC_HEADERS_C += \ LIBBAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBAD_CLIENT_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libbad_client_test.a: openssl_dep_error else $(LIBDIR)/$(CONFIG)/libbad_client_test.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(LIBBAD_CLIENT_TEST_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBBAD_CLIENT_TEST_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libbad_client_test.a endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBBAD_CLIENT_TEST_OBJS:.o=.dep) endif endif LIBBAD_SSL_TEST_SERVER_SRC = \ test/core/bad_ssl/server_common.c \ PUBLIC_HEADERS_C += \ LIBBAD_SSL_TEST_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBAD_SSL_TEST_SERVER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libbad_ssl_test_server.a: openssl_dep_error else $(LIBDIR)/$(CONFIG)/libbad_ssl_test_server.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(LIBBAD_SSL_TEST_SERVER_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libbad_ssl_test_server.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libbad_ssl_test_server.a $(LIBBAD_SSL_TEST_SERVER_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libbad_ssl_test_server.a endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBBAD_SSL_TEST_SERVER_OBJS:.o=.dep) endif endif LIBEND2END_TESTS_SRC = \ test/core/end2end/end2end_tests.c \ test/core/end2end/end2end_test_utils.c \ test/core/end2end/tests/authority_not_supported.c \ test/core/end2end/tests/bad_hostname.c \ test/core/end2end/tests/bad_ping.c \ test/core/end2end/tests/binary_metadata.c \ test/core/end2end/tests/call_creds.c \ test/core/end2end/tests/cancel_after_accept.c \ test/core/end2end/tests/cancel_after_client_done.c \ test/core/end2end/tests/cancel_after_invoke.c \ test/core/end2end/tests/cancel_before_invoke.c \ test/core/end2end/tests/cancel_in_a_vacuum.c \ test/core/end2end/tests/cancel_with_status.c \ test/core/end2end/tests/compressed_payload.c \ test/core/end2end/tests/connectivity.c \ test/core/end2end/tests/default_host.c \ test/core/end2end/tests/disappearing_server.c \ test/core/end2end/tests/empty_batch.c \ test/core/end2end/tests/filter_call_init_fails.c \ test/core/end2end/tests/filter_causes_close.c \ test/core/end2end/tests/filter_latency.c \ test/core/end2end/tests/graceful_server_shutdown.c \ test/core/end2end/tests/high_initial_seqno.c \ test/core/end2end/tests/hpack_size.c \ test/core/end2end/tests/idempotent_request.c \ test/core/end2end/tests/invoke_large_request.c \ test/core/end2end/tests/keepalive_timeout.c \ test/core/end2end/tests/large_metadata.c \ test/core/end2end/tests/load_reporting_hook.c \ test/core/end2end/tests/max_concurrent_streams.c \ test/core/end2end/tests/max_connection_age.c \ test/core/end2end/tests/max_connection_idle.c \ test/core/end2end/tests/max_message_length.c \ test/core/end2end/tests/negative_deadline.c \ test/core/end2end/tests/network_status_change.c \ test/core/end2end/tests/no_logging.c \ test/core/end2end/tests/no_op.c \ test/core/end2end/tests/payload.c \ test/core/end2end/tests/ping.c \ test/core/end2end/tests/ping_pong_streaming.c \ test/core/end2end/tests/registered_call.c \ test/core/end2end/tests/request_with_flags.c \ test/core/end2end/tests/request_with_payload.c \ test/core/end2end/tests/resource_quota_server.c \ test/core/end2end/tests/server_finishes_request.c \ test/core/end2end/tests/shutdown_finishes_calls.c \ test/core/end2end/tests/shutdown_finishes_tags.c \ test/core/end2end/tests/simple_cacheable_request.c \ test/core/end2end/tests/simple_delayed_request.c \ test/core/end2end/tests/simple_metadata.c \ test/core/end2end/tests/simple_request.c \ test/core/end2end/tests/streaming_error_response.c \ test/core/end2end/tests/trailing_metadata.c \ test/core/end2end/tests/write_buffering.c \ test/core/end2end/tests/write_buffering_at_end.c \ PUBLIC_HEADERS_C += \ LIBEND2END_TESTS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBEND2END_TESTS_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. $(LIBDIR)/$(CONFIG)/libend2end_tests.a: openssl_dep_error else $(LIBDIR)/$(CONFIG)/libend2end_tests.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(LIBEND2END_TESTS_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBEND2END_TESTS_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libend2end_tests.a endif endif ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBEND2END_TESTS_OBJS:.o=.dep) endif endif LIBEND2END_NOSEC_TESTS_SRC = \ test/core/end2end/end2end_nosec_tests.c \ test/core/end2end/end2end_test_utils.c \ test/core/end2end/tests/authority_not_supported.c \ test/core/end2end/tests/bad_hostname.c \ test/core/end2end/tests/bad_ping.c \ test/core/end2end/tests/binary_metadata.c \ test/core/end2end/tests/cancel_after_accept.c \ test/core/end2end/tests/cancel_after_client_done.c \ test/core/end2end/tests/cancel_after_invoke.c \ test/core/end2end/tests/cancel_before_invoke.c \ test/core/end2end/tests/cancel_in_a_vacuum.c \ test/core/end2end/tests/cancel_with_status.c \ test/core/end2end/tests/compressed_payload.c \ test/core/end2end/tests/connectivity.c \ test/core/end2end/tests/default_host.c \ test/core/end2end/tests/disappearing_server.c \ test/core/end2end/tests/empty_batch.c \ test/core/end2end/tests/filter_call_init_fails.c \ test/core/end2end/tests/filter_causes_close.c \ test/core/end2end/tests/filter_latency.c \ test/core/end2end/tests/graceful_server_shutdown.c \ test/core/end2end/tests/high_initial_seqno.c \ test/core/end2end/tests/hpack_size.c \ test/core/end2end/tests/idempotent_request.c \ test/core/end2end/tests/invoke_large_request.c \ test/core/end2end/tests/keepalive_timeout.c \ test/core/end2end/tests/large_metadata.c \ test/core/end2end/tests/load_reporting_hook.c \ test/core/end2end/tests/max_concurrent_streams.c \ test/core/end2end/tests/max_connection_age.c \ test/core/end2end/tests/max_connection_idle.c \ test/core/end2end/tests/max_message_length.c \ test/core/end2end/tests/negative_deadline.c \ test/core/end2end/tests/network_status_change.c \ test/core/end2end/tests/no_logging.c \ test/core/end2end/tests/no_op.c \ test/core/end2end/tests/payload.c \ test/core/end2end/tests/ping.c \ test/core/end2end/tests/ping_pong_streaming.c \ test/core/end2end/tests/registered_call.c \ test/core/end2end/tests/request_with_flags.c \ test/core/end2end/tests/request_with_payload.c \ test/core/end2end/tests/resource_quota_server.c \ test/core/end2end/tests/server_finishes_request.c \ test/core/end2end/tests/shutdown_finishes_calls.c \ test/core/end2end/tests/shutdown_finishes_tags.c \ test/core/end2end/tests/simple_cacheable_request.c \ test/core/end2end/tests/simple_delayed_request.c \ test/core/end2end/tests/simple_metadata.c \ test/core/end2end/tests/simple_request.c \ test/core/end2end/tests/streaming_error_response.c \ test/core/end2end/tests/trailing_metadata.c \ test/core/end2end/tests/write_buffering.c \ test/core/end2end/tests/write_buffering_at_end.c \ PUBLIC_HEADERS_C += \ LIBEND2END_NOSEC_TESTS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBEND2END_NOSEC_TESTS_SRC)))) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a: $(ZLIB_DEP) $(CARES_DEP) $(LIBEND2END_NOSEC_TESTS_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBEND2END_NOSEC_TESTS_OBJS) ifeq ($(SYSTEM),Darwin) $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a endif ifneq ($(NO_DEPS),true) -include $(LIBEND2END_NOSEC_TESTS_OBJS:.o=.dep) endif # All of the test targets, and protoc plugins ALARM_TEST_SRC = \ test/core/surface/alarm_test.c \ ALARM_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ALARM_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/alarm_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/alarm_test: $(ALARM_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) $(ALARM_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)/alarm_test endif $(OBJDIR)/$(CONFIG)/test/core/surface/alarm_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_alarm_test: $(ALARM_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(ALARM_TEST_OBJS:.o=.dep) endif endif ALGORITHM_TEST_SRC = \ test/core/compression/algorithm_test.c \ ALGORITHM_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ALGORITHM_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/algorithm_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/algorithm_test: $(ALGORITHM_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) $(ALGORITHM_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)/algorithm_test endif $(OBJDIR)/$(CONFIG)/test/core/compression/algorithm_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_algorithm_test: $(ALGORITHM_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(ALGORITHM_TEST_OBJS:.o=.dep) endif endif ALLOC_TEST_SRC = \ test/core/support/alloc_test.c \ ALLOC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ALLOC_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/alloc_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/alloc_test: $(ALLOC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(ALLOC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/alloc_test endif $(OBJDIR)/$(CONFIG)/test/core/support/alloc_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_alloc_test: $(ALLOC_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(ALLOC_TEST_OBJS:.o=.dep) endif endif ALPN_TEST_SRC = \ test/core/transport/chttp2/alpn_test.c \ ALPN_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ALPN_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/alpn_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/alpn_test: $(ALPN_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) $(ALPN_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)/alpn_test endif $(OBJDIR)/$(CONFIG)/test/core/transport/chttp2/alpn_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_alpn_test: $(ALPN_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(ALPN_TEST_OBJS:.o=.dep) endif endif API_FUZZER_SRC = \ test/core/end2end/fuzzers/api_fuzzer.c \ API_FUZZER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(API_FUZZER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/api_fuzzer: openssl_dep_error else $(BINDIR)/$(CONFIG)/api_fuzzer: $(API_FUZZER_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) $(LDXX) $(LDFLAGS) $(API_FUZZER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -lFuzzer -o $(BINDIR)/$(CONFIG)/api_fuzzer endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fuzzers/api_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_api_fuzzer: $(API_FUZZER_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(API_FUZZER_OBJS:.o=.dep) endif endif ARENA_TEST_SRC = \ test/core/support/arena_test.c \ ARENA_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ARENA_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/arena_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/arena_test: $(ARENA_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(ARENA_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/arena_test endif $(OBJDIR)/$(CONFIG)/test/core/support/arena_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_arena_test: $(ARENA_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(ARENA_TEST_OBJS:.o=.dep) endif endif BAD_SERVER_RESPONSE_TEST_SRC = \ test/core/end2end/bad_server_response_test.c \ BAD_SERVER_RESPONSE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BAD_SERVER_RESPONSE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/bad_server_response_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/bad_server_response_test: $(BAD_SERVER_RESPONSE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(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) $(BAD_SERVER_RESPONSE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(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)/bad_server_response_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/bad_server_response_test.o: $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_bad_server_response_test: $(BAD_SERVER_RESPONSE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(BAD_SERVER_RESPONSE_TEST_OBJS:.o=.dep) endif endif BDP_ESTIMATOR_TEST_SRC = \ test/core/transport/bdp_estimator_test.c \ BDP_ESTIMATOR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BDP_ESTIMATOR_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/bdp_estimator_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/bdp_estimator_test: $(BDP_ESTIMATOR_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) $(BDP_ESTIMATOR_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)/bdp_estimator_test endif $(OBJDIR)/$(CONFIG)/test/core/transport/bdp_estimator_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_bdp_estimator_test: $(BDP_ESTIMATOR_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(BDP_ESTIMATOR_TEST_OBJS:.o=.dep) endif endif BIN_DECODER_TEST_SRC = \ test/core/transport/chttp2/bin_decoder_test.c \ BIN_DECODER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BIN_DECODER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/bin_decoder_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/bin_decoder_test: $(BIN_DECODER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(BIN_DECODER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/bin_decoder_test endif $(OBJDIR)/$(CONFIG)/test/core/transport/chttp2/bin_decoder_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a deps_bin_decoder_test: $(BIN_DECODER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(BIN_DECODER_TEST_OBJS:.o=.dep) endif endif BIN_ENCODER_TEST_SRC = \ test/core/transport/chttp2/bin_encoder_test.c \ BIN_ENCODER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BIN_ENCODER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/bin_encoder_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/bin_encoder_test: $(BIN_ENCODER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(BIN_ENCODER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/bin_encoder_test endif $(OBJDIR)/$(CONFIG)/test/core/transport/chttp2/bin_encoder_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a deps_bin_encoder_test: $(BIN_ENCODER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(BIN_ENCODER_TEST_OBJS:.o=.dep) endif endif CENSUS_CONTEXT_TEST_SRC = \ test/core/census/context_test.c \ CENSUS_CONTEXT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_CONTEXT_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/census_context_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/census_context_test: $(CENSUS_CONTEXT_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_CONTEXT_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_context_test endif $(OBJDIR)/$(CONFIG)/test/core/census/context_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_census_context_test: $(CENSUS_CONTEXT_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CENSUS_CONTEXT_TEST_OBJS:.o=.dep) endif endif CENSUS_RESOURCE_TEST_SRC = \ test/core/census/resource_test.c \ CENSUS_RESOURCE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_RESOURCE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/census_resource_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/census_resource_test: $(CENSUS_RESOURCE_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_RESOURCE_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_resource_test endif $(OBJDIR)/$(CONFIG)/test/core/census/resource_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_census_resource_test: $(CENSUS_RESOURCE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CENSUS_RESOURCE_TEST_OBJS:.o=.dep) endif endif CENSUS_TRACE_CONTEXT_TEST_SRC = \ test/core/census/trace_context_test.c \ CENSUS_TRACE_CONTEXT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_TRACE_CONTEXT_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/census_trace_context_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/census_trace_context_test: $(CENSUS_TRACE_CONTEXT_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_TRACE_CONTEXT_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_trace_context_test endif $(OBJDIR)/$(CONFIG)/test/core/census/trace_context_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_census_trace_context_test: $(CENSUS_TRACE_CONTEXT_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CENSUS_TRACE_CONTEXT_TEST_OBJS:.o=.dep) endif endif CHANNEL_CREATE_TEST_SRC = \ test/core/surface/channel_create_test.c \ CHANNEL_CREATE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHANNEL_CREATE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/channel_create_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/channel_create_test: $(CHANNEL_CREATE_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) $(CHANNEL_CREATE_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)/channel_create_test endif $(OBJDIR)/$(CONFIG)/test/core/surface/channel_create_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_channel_create_test: $(CHANNEL_CREATE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CHANNEL_CREATE_TEST_OBJS:.o=.dep) endif endif CHTTP2_HPACK_ENCODER_TEST_SRC = \ test/core/transport/chttp2/hpack_encoder_test.c \ CHTTP2_HPACK_ENCODER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_HPACK_ENCODER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test: $(CHTTP2_HPACK_ENCODER_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) $(CHTTP2_HPACK_ENCODER_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)/chttp2_hpack_encoder_test endif $(OBJDIR)/$(CONFIG)/test/core/transport/chttp2/hpack_encoder_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_chttp2_hpack_encoder_test: $(CHTTP2_HPACK_ENCODER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CHTTP2_HPACK_ENCODER_TEST_OBJS:.o=.dep) endif endif CHTTP2_STREAM_MAP_TEST_SRC = \ test/core/transport/chttp2/stream_map_test.c \ CHTTP2_STREAM_MAP_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_STREAM_MAP_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/chttp2_stream_map_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/chttp2_stream_map_test: $(CHTTP2_STREAM_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) $(CHTTP2_STREAM_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)/chttp2_stream_map_test endif $(OBJDIR)/$(CONFIG)/test/core/transport/chttp2/stream_map_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_chttp2_stream_map_test: $(CHTTP2_STREAM_MAP_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CHTTP2_STREAM_MAP_TEST_OBJS:.o=.dep) endif endif CHTTP2_VARINT_TEST_SRC = \ test/core/transport/chttp2/varint_test.c \ CHTTP2_VARINT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_VARINT_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/chttp2_varint_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/chttp2_varint_test: $(CHTTP2_VARINT_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) $(CHTTP2_VARINT_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)/chttp2_varint_test endif $(OBJDIR)/$(CONFIG)/test/core/transport/chttp2/varint_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_chttp2_varint_test: $(CHTTP2_VARINT_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CHTTP2_VARINT_TEST_OBJS:.o=.dep) endif endif CLIENT_FUZZER_SRC = \ test/core/end2end/fuzzers/client_fuzzer.c \ CLIENT_FUZZER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CLIENT_FUZZER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/client_fuzzer: openssl_dep_error else $(BINDIR)/$(CONFIG)/client_fuzzer: $(CLIENT_FUZZER_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) $(LDXX) $(LDFLAGS) $(CLIENT_FUZZER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -lFuzzer -o $(BINDIR)/$(CONFIG)/client_fuzzer endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fuzzers/client_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_client_fuzzer: $(CLIENT_FUZZER_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CLIENT_FUZZER_OBJS:.o=.dep) endif endif COMBINER_TEST_SRC = \ test/core/iomgr/combiner_test.c \ COMBINER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(COMBINER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/combiner_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/combiner_test: $(COMBINER_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) $(COMBINER_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)/combiner_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/combiner_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_combiner_test: $(COMBINER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(COMBINER_TEST_OBJS:.o=.dep) endif endif COMPRESSION_TEST_SRC = \ test/core/compression/compression_test.c \ COMPRESSION_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(COMPRESSION_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/compression_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/compression_test: $(COMPRESSION_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) $(COMPRESSION_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)/compression_test endif $(OBJDIR)/$(CONFIG)/test/core/compression/compression_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_compression_test: $(COMPRESSION_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(COMPRESSION_TEST_OBJS:.o=.dep) endif endif CONCURRENT_CONNECTIVITY_TEST_SRC = \ test/core/surface/concurrent_connectivity_test.c \ CONCURRENT_CONNECTIVITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CONCURRENT_CONNECTIVITY_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/concurrent_connectivity_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/concurrent_connectivity_test: $(CONCURRENT_CONNECTIVITY_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) $(CONCURRENT_CONNECTIVITY_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)/concurrent_connectivity_test endif $(OBJDIR)/$(CONFIG)/test/core/surface/concurrent_connectivity_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_concurrent_connectivity_test: $(CONCURRENT_CONNECTIVITY_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CONCURRENT_CONNECTIVITY_TEST_OBJS:.o=.dep) endif endif CONNECTION_REFUSED_TEST_SRC = \ test/core/end2end/connection_refused_test.c \ CONNECTION_REFUSED_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CONNECTION_REFUSED_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/connection_refused_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/connection_refused_test: $(CONNECTION_REFUSED_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) $(CONNECTION_REFUSED_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)/connection_refused_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/connection_refused_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_connection_refused_test: $(CONNECTION_REFUSED_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CONNECTION_REFUSED_TEST_OBJS:.o=.dep) endif endif DNS_RESOLVER_CONNECTIVITY_TEST_SRC = \ test/core/client_channel/resolvers/dns_resolver_connectivity_test.c \ DNS_RESOLVER_CONNECTIVITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(DNS_RESOLVER_CONNECTIVITY_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test: $(DNS_RESOLVER_CONNECTIVITY_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) $(DNS_RESOLVER_CONNECTIVITY_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)/dns_resolver_connectivity_test endif $(OBJDIR)/$(CONFIG)/test/core/client_channel/resolvers/dns_resolver_connectivity_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_dns_resolver_connectivity_test: $(DNS_RESOLVER_CONNECTIVITY_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(DNS_RESOLVER_CONNECTIVITY_TEST_OBJS:.o=.dep) endif endif DNS_RESOLVER_TEST_SRC = \ test/core/client_channel/resolvers/dns_resolver_test.c \ DNS_RESOLVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(DNS_RESOLVER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/dns_resolver_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/dns_resolver_test: $(DNS_RESOLVER_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) $(DNS_RESOLVER_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)/dns_resolver_test endif $(OBJDIR)/$(CONFIG)/test/core/client_channel/resolvers/dns_resolver_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_dns_resolver_test: $(DNS_RESOLVER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(DNS_RESOLVER_TEST_OBJS:.o=.dep) endif endif DUALSTACK_SOCKET_TEST_SRC = \ test/core/end2end/dualstack_socket_test.c \ DUALSTACK_SOCKET_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(DUALSTACK_SOCKET_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/dualstack_socket_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/dualstack_socket_test: $(DUALSTACK_SOCKET_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) $(DUALSTACK_SOCKET_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)/dualstack_socket_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/dualstack_socket_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_dualstack_socket_test: $(DUALSTACK_SOCKET_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(DUALSTACK_SOCKET_TEST_OBJS:.o=.dep) endif endif ENDPOINT_PAIR_TEST_SRC = \ test/core/iomgr/endpoint_pair_test.c \ ENDPOINT_PAIR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ENDPOINT_PAIR_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/endpoint_pair_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/endpoint_pair_test: $(ENDPOINT_PAIR_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) $(ENDPOINT_PAIR_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)/endpoint_pair_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/endpoint_pair_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_endpoint_pair_test: $(ENDPOINT_PAIR_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(ENDPOINT_PAIR_TEST_OBJS:.o=.dep) endif endif ERROR_TEST_SRC = \ test/core/iomgr/error_test.c \ ERROR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ERROR_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/error_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/error_test: $(ERROR_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) $(ERROR_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)/error_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/error_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_error_test: $(ERROR_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(ERROR_TEST_OBJS:.o=.dep) endif endif EV_EPOLL_LINUX_TEST_SRC = \ test/core/iomgr/ev_epoll_linux_test.c \ EV_EPOLL_LINUX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(EV_EPOLL_LINUX_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/ev_epoll_linux_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/ev_epoll_linux_test: $(EV_EPOLL_LINUX_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) $(EV_EPOLL_LINUX_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)/ev_epoll_linux_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/ev_epoll_linux_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_ev_epoll_linux_test: $(EV_EPOLL_LINUX_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(EV_EPOLL_LINUX_TEST_OBJS:.o=.dep) endif endif FD_CONSERVATION_POSIX_TEST_SRC = \ test/core/iomgr/fd_conservation_posix_test.c \ FD_CONSERVATION_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FD_CONSERVATION_POSIX_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/fd_conservation_posix_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/fd_conservation_posix_test: $(FD_CONSERVATION_POSIX_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) $(FD_CONSERVATION_POSIX_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)/fd_conservation_posix_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/fd_conservation_posix_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_fd_conservation_posix_test: $(FD_CONSERVATION_POSIX_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(FD_CONSERVATION_POSIX_TEST_OBJS:.o=.dep) endif endif FD_POSIX_TEST_SRC = \ test/core/iomgr/fd_posix_test.c \ FD_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FD_POSIX_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/fd_posix_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/fd_posix_test: $(FD_POSIX_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) $(FD_POSIX_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)/fd_posix_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/fd_posix_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_fd_posix_test: $(FD_POSIX_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(FD_POSIX_TEST_OBJS:.o=.dep) endif endif FLING_CLIENT_SRC = \ test/core/fling/client.c \ FLING_CLIENT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FLING_CLIENT_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/fling_client: openssl_dep_error else $(BINDIR)/$(CONFIG)/fling_client: $(FLING_CLIENT_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) $(FLING_CLIENT_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)/fling_client endif $(OBJDIR)/$(CONFIG)/test/core/fling/client.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_fling_client: $(FLING_CLIENT_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(FLING_CLIENT_OBJS:.o=.dep) endif endif FLING_SERVER_SRC = \ test/core/fling/server.c \ FLING_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FLING_SERVER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/fling_server: openssl_dep_error else $(BINDIR)/$(CONFIG)/fling_server: $(FLING_SERVER_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) $(FLING_SERVER_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)/fling_server endif $(OBJDIR)/$(CONFIG)/test/core/fling/server.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_fling_server: $(FLING_SERVER_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(FLING_SERVER_OBJS:.o=.dep) endif endif FLING_STREAM_TEST_SRC = \ test/core/fling/fling_stream_test.c \ FLING_STREAM_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FLING_STREAM_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/fling_stream_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/fling_stream_test: $(FLING_STREAM_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) $(FLING_STREAM_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)/fling_stream_test endif $(OBJDIR)/$(CONFIG)/test/core/fling/fling_stream_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_fling_stream_test: $(FLING_STREAM_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(FLING_STREAM_TEST_OBJS:.o=.dep) endif endif FLING_TEST_SRC = \ test/core/fling/fling_test.c \ FLING_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FLING_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/fling_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/fling_test: $(FLING_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) $(FLING_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)/fling_test endif $(OBJDIR)/$(CONFIG)/test/core/fling/fling_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_fling_test: $(FLING_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(FLING_TEST_OBJS:.o=.dep) endif endif GEN_HPACK_TABLES_SRC = \ tools/codegen/core/gen_hpack_tables.c \ GEN_HPACK_TABLES_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GEN_HPACK_TABLES_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/gen_hpack_tables: openssl_dep_error else $(BINDIR)/$(CONFIG)/gen_hpack_tables: $(GEN_HPACK_TABLES_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GEN_HPACK_TABLES_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gen_hpack_tables endif $(OBJDIR)/$(CONFIG)/tools/codegen/core/gen_hpack_tables.o: $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a deps_gen_hpack_tables: $(GEN_HPACK_TABLES_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GEN_HPACK_TABLES_OBJS:.o=.dep) endif endif GEN_LEGAL_METADATA_CHARACTERS_SRC = \ tools/codegen/core/gen_legal_metadata_characters.c \ GEN_LEGAL_METADATA_CHARACTERS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GEN_LEGAL_METADATA_CHARACTERS_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/gen_legal_metadata_characters: openssl_dep_error else $(BINDIR)/$(CONFIG)/gen_legal_metadata_characters: $(GEN_LEGAL_METADATA_CHARACTERS_OBJS) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GEN_LEGAL_METADATA_CHARACTERS_OBJS) $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gen_legal_metadata_characters endif $(OBJDIR)/$(CONFIG)/tools/codegen/core/gen_legal_metadata_characters.o: deps_gen_legal_metadata_characters: $(GEN_LEGAL_METADATA_CHARACTERS_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GEN_LEGAL_METADATA_CHARACTERS_OBJS:.o=.dep) endif endif GEN_PERCENT_ENCODING_TABLES_SRC = \ tools/codegen/core/gen_percent_encoding_tables.c \ GEN_PERCENT_ENCODING_TABLES_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GEN_PERCENT_ENCODING_TABLES_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/gen_percent_encoding_tables: openssl_dep_error else $(BINDIR)/$(CONFIG)/gen_percent_encoding_tables: $(GEN_PERCENT_ENCODING_TABLES_OBJS) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GEN_PERCENT_ENCODING_TABLES_OBJS) $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gen_percent_encoding_tables endif $(OBJDIR)/$(CONFIG)/tools/codegen/core/gen_percent_encoding_tables.o: deps_gen_percent_encoding_tables: $(GEN_PERCENT_ENCODING_TABLES_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GEN_PERCENT_ENCODING_TABLES_OBJS:.o=.dep) endif endif GOAWAY_SERVER_TEST_SRC = \ test/core/end2end/goaway_server_test.c \ GOAWAY_SERVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GOAWAY_SERVER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/goaway_server_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/goaway_server_test: $(GOAWAY_SERVER_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) $(GOAWAY_SERVER_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)/goaway_server_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/goaway_server_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_goaway_server_test: $(GOAWAY_SERVER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GOAWAY_SERVER_TEST_OBJS:.o=.dep) endif endif GPR_AVL_TEST_SRC = \ test/core/support/avl_test.c \ GPR_AVL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_AVL_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/gpr_avl_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/gpr_avl_test: $(GPR_AVL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GPR_AVL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_avl_test endif $(OBJDIR)/$(CONFIG)/test/core/support/avl_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_gpr_avl_test: $(GPR_AVL_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GPR_AVL_TEST_OBJS:.o=.dep) endif endif GPR_BACKOFF_TEST_SRC = \ test/core/support/backoff_test.c \ GPR_BACKOFF_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_BACKOFF_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/gpr_backoff_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/gpr_backoff_test: $(GPR_BACKOFF_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GPR_BACKOFF_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_backoff_test endif $(OBJDIR)/$(CONFIG)/test/core/support/backoff_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_gpr_backoff_test: $(GPR_BACKOFF_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GPR_BACKOFF_TEST_OBJS:.o=.dep) endif endif GPR_CMDLINE_TEST_SRC = \ test/core/support/cmdline_test.c \ GPR_CMDLINE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_CMDLINE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/gpr_cmdline_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/gpr_cmdline_test: $(GPR_CMDLINE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GPR_CMDLINE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_cmdline_test endif $(OBJDIR)/$(CONFIG)/test/core/support/cmdline_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_gpr_cmdline_test: $(GPR_CMDLINE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GPR_CMDLINE_TEST_OBJS:.o=.dep) endif endif GPR_CPU_TEST_SRC = \ test/core/support/cpu_test.c \ GPR_CPU_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_CPU_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/gpr_cpu_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/gpr_cpu_test: $(GPR_CPU_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GPR_CPU_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_cpu_test endif $(OBJDIR)/$(CONFIG)/test/core/support/cpu_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_gpr_cpu_test: $(GPR_CPU_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GPR_CPU_TEST_OBJS:.o=.dep) endif endif GPR_ENV_TEST_SRC = \ test/core/support/env_test.c \ GPR_ENV_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_ENV_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/gpr_env_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/gpr_env_test: $(GPR_ENV_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GPR_ENV_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_env_test endif $(OBJDIR)/$(CONFIG)/test/core/support/env_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_gpr_env_test: $(GPR_ENV_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GPR_ENV_TEST_OBJS:.o=.dep) endif endif GPR_HISTOGRAM_TEST_SRC = \ test/core/support/histogram_test.c \ GPR_HISTOGRAM_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_HISTOGRAM_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/gpr_histogram_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/gpr_histogram_test: $(GPR_HISTOGRAM_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GPR_HISTOGRAM_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_histogram_test endif $(OBJDIR)/$(CONFIG)/test/core/support/histogram_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_gpr_histogram_test: $(GPR_HISTOGRAM_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GPR_HISTOGRAM_TEST_OBJS:.o=.dep) endif endif GPR_HOST_PORT_TEST_SRC = \ test/core/support/host_port_test.c \ GPR_HOST_PORT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_HOST_PORT_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/gpr_host_port_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/gpr_host_port_test: $(GPR_HOST_PORT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GPR_HOST_PORT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_host_port_test endif $(OBJDIR)/$(CONFIG)/test/core/support/host_port_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_gpr_host_port_test: $(GPR_HOST_PORT_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GPR_HOST_PORT_TEST_OBJS:.o=.dep) endif endif GPR_LOG_TEST_SRC = \ test/core/support/log_test.c \ GPR_LOG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_LOG_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/gpr_log_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/gpr_log_test: $(GPR_LOG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GPR_LOG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_log_test endif $(OBJDIR)/$(CONFIG)/test/core/support/log_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_gpr_log_test: $(GPR_LOG_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GPR_LOG_TEST_OBJS:.o=.dep) endif endif GPR_MPSCQ_TEST_SRC = \ test/core/support/mpscq_test.c \ GPR_MPSCQ_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_MPSCQ_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/gpr_mpscq_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/gpr_mpscq_test: $(GPR_MPSCQ_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GPR_MPSCQ_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_mpscq_test endif $(OBJDIR)/$(CONFIG)/test/core/support/mpscq_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_gpr_mpscq_test: $(GPR_MPSCQ_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GPR_MPSCQ_TEST_OBJS:.o=.dep) endif endif GPR_SPINLOCK_TEST_SRC = \ test/core/support/spinlock_test.c \ GPR_SPINLOCK_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_SPINLOCK_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/gpr_spinlock_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/gpr_spinlock_test: $(GPR_SPINLOCK_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GPR_SPINLOCK_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_spinlock_test endif $(OBJDIR)/$(CONFIG)/test/core/support/spinlock_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_gpr_spinlock_test: $(GPR_SPINLOCK_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GPR_SPINLOCK_TEST_OBJS:.o=.dep) endif endif GPR_STACK_LOCKFREE_TEST_SRC = \ test/core/support/stack_lockfree_test.c \ GPR_STACK_LOCKFREE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_STACK_LOCKFREE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/gpr_stack_lockfree_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/gpr_stack_lockfree_test: $(GPR_STACK_LOCKFREE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GPR_STACK_LOCKFREE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_stack_lockfree_test endif $(OBJDIR)/$(CONFIG)/test/core/support/stack_lockfree_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_gpr_stack_lockfree_test: $(GPR_STACK_LOCKFREE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GPR_STACK_LOCKFREE_TEST_OBJS:.o=.dep) endif endif GPR_STRING_TEST_SRC = \ test/core/support/string_test.c \ GPR_STRING_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_STRING_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/gpr_string_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/gpr_string_test: $(GPR_STRING_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GPR_STRING_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_string_test endif $(OBJDIR)/$(CONFIG)/test/core/support/string_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_gpr_string_test: $(GPR_STRING_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GPR_STRING_TEST_OBJS:.o=.dep) endif endif GPR_SYNC_TEST_SRC = \ test/core/support/sync_test.c \ GPR_SYNC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_SYNC_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/gpr_sync_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/gpr_sync_test: $(GPR_SYNC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GPR_SYNC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_sync_test endif $(OBJDIR)/$(CONFIG)/test/core/support/sync_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_gpr_sync_test: $(GPR_SYNC_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GPR_SYNC_TEST_OBJS:.o=.dep) endif endif GPR_THD_TEST_SRC = \ test/core/support/thd_test.c \ GPR_THD_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_THD_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/gpr_thd_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/gpr_thd_test: $(GPR_THD_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GPR_THD_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_thd_test endif $(OBJDIR)/$(CONFIG)/test/core/support/thd_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_gpr_thd_test: $(GPR_THD_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GPR_THD_TEST_OBJS:.o=.dep) endif endif GPR_TIME_TEST_SRC = \ test/core/support/time_test.c \ GPR_TIME_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_TIME_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/gpr_time_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/gpr_time_test: $(GPR_TIME_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GPR_TIME_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_time_test endif $(OBJDIR)/$(CONFIG)/test/core/support/time_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_gpr_time_test: $(GPR_TIME_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GPR_TIME_TEST_OBJS:.o=.dep) endif endif GPR_TLS_TEST_SRC = \ test/core/support/tls_test.c \ GPR_TLS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_TLS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/gpr_tls_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/gpr_tls_test: $(GPR_TLS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GPR_TLS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_tls_test endif $(OBJDIR)/$(CONFIG)/test/core/support/tls_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_gpr_tls_test: $(GPR_TLS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GPR_TLS_TEST_OBJS:.o=.dep) endif endif GPR_USEFUL_TEST_SRC = \ test/core/support/useful_test.c \ GPR_USEFUL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_USEFUL_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/gpr_useful_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/gpr_useful_test: $(GPR_USEFUL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GPR_USEFUL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_useful_test endif $(OBJDIR)/$(CONFIG)/test/core/support/useful_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_gpr_useful_test: $(GPR_USEFUL_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GPR_USEFUL_TEST_OBJS:.o=.dep) endif endif GRPC_AUTH_CONTEXT_TEST_SRC = \ test/core/security/auth_context_test.c \ GRPC_AUTH_CONTEXT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_AUTH_CONTEXT_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/grpc_auth_context_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/grpc_auth_context_test: $(GRPC_AUTH_CONTEXT_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) $(GRPC_AUTH_CONTEXT_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)/grpc_auth_context_test endif $(OBJDIR)/$(CONFIG)/test/core/security/auth_context_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_grpc_auth_context_test: $(GRPC_AUTH_CONTEXT_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GRPC_AUTH_CONTEXT_TEST_OBJS:.o=.dep) endif endif GRPC_B64_TEST_SRC = \ test/core/slice/b64_test.c \ GRPC_B64_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_B64_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/grpc_b64_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/grpc_b64_test: $(GRPC_B64_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) $(GRPC_B64_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)/grpc_b64_test endif $(OBJDIR)/$(CONFIG)/test/core/slice/b64_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_grpc_b64_test: $(GRPC_B64_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GRPC_B64_TEST_OBJS:.o=.dep) endif endif GRPC_BYTE_BUFFER_READER_TEST_SRC = \ test/core/surface/byte_buffer_reader_test.c \ GRPC_BYTE_BUFFER_READER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_BYTE_BUFFER_READER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test: $(GRPC_BYTE_BUFFER_READER_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) $(GRPC_BYTE_BUFFER_READER_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)/grpc_byte_buffer_reader_test endif $(OBJDIR)/$(CONFIG)/test/core/surface/byte_buffer_reader_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_grpc_byte_buffer_reader_test: $(GRPC_BYTE_BUFFER_READER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GRPC_BYTE_BUFFER_READER_TEST_OBJS:.o=.dep) endif endif GRPC_CHANNEL_ARGS_TEST_SRC = \ test/core/channel/channel_args_test.c \ GRPC_CHANNEL_ARGS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_CHANNEL_ARGS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/grpc_channel_args_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/grpc_channel_args_test: $(GRPC_CHANNEL_ARGS_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) $(GRPC_CHANNEL_ARGS_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)/grpc_channel_args_test endif $(OBJDIR)/$(CONFIG)/test/core/channel/channel_args_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_grpc_channel_args_test: $(GRPC_CHANNEL_ARGS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GRPC_CHANNEL_ARGS_TEST_OBJS:.o=.dep) endif endif GRPC_CHANNEL_STACK_TEST_SRC = \ test/core/channel/channel_stack_test.c \ GRPC_CHANNEL_STACK_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_CHANNEL_STACK_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/grpc_channel_stack_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/grpc_channel_stack_test: $(GRPC_CHANNEL_STACK_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) $(GRPC_CHANNEL_STACK_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)/grpc_channel_stack_test endif $(OBJDIR)/$(CONFIG)/test/core/channel/channel_stack_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_grpc_channel_stack_test: $(GRPC_CHANNEL_STACK_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GRPC_CHANNEL_STACK_TEST_OBJS:.o=.dep) endif endif GRPC_COMPLETION_QUEUE_TEST_SRC = \ test/core/surface/completion_queue_test.c \ GRPC_COMPLETION_QUEUE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_COMPLETION_QUEUE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/grpc_completion_queue_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/grpc_completion_queue_test: $(GRPC_COMPLETION_QUEUE_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) $(GRPC_COMPLETION_QUEUE_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)/grpc_completion_queue_test endif $(OBJDIR)/$(CONFIG)/test/core/surface/completion_queue_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_grpc_completion_queue_test: $(GRPC_COMPLETION_QUEUE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GRPC_COMPLETION_QUEUE_TEST_OBJS:.o=.dep) endif endif GRPC_COMPLETION_QUEUE_THREADING_TEST_SRC = \ test/core/surface/completion_queue_threading_test.c \ GRPC_COMPLETION_QUEUE_THREADING_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_COMPLETION_QUEUE_THREADING_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test: $(GRPC_COMPLETION_QUEUE_THREADING_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) $(GRPC_COMPLETION_QUEUE_THREADING_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)/grpc_completion_queue_threading_test endif $(OBJDIR)/$(CONFIG)/test/core/surface/completion_queue_threading_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_grpc_completion_queue_threading_test: $(GRPC_COMPLETION_QUEUE_THREADING_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GRPC_COMPLETION_QUEUE_THREADING_TEST_OBJS:.o=.dep) endif endif GRPC_CREATE_JWT_SRC = \ test/core/security/create_jwt.c \ GRPC_CREATE_JWT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_CREATE_JWT_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/grpc_create_jwt: openssl_dep_error else $(BINDIR)/$(CONFIG)/grpc_create_jwt: $(GRPC_CREATE_JWT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GRPC_CREATE_JWT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/grpc_create_jwt endif $(OBJDIR)/$(CONFIG)/test/core/security/create_jwt.o: $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_grpc_create_jwt: $(GRPC_CREATE_JWT_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GRPC_CREATE_JWT_OBJS:.o=.dep) endif endif GRPC_CREDENTIALS_TEST_SRC = \ test/core/security/credentials_test.c \ GRPC_CREDENTIALS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_CREDENTIALS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/grpc_credentials_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/grpc_credentials_test: $(GRPC_CREDENTIALS_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) $(GRPC_CREDENTIALS_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)/grpc_credentials_test endif $(OBJDIR)/$(CONFIG)/test/core/security/credentials_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_grpc_credentials_test: $(GRPC_CREDENTIALS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GRPC_CREDENTIALS_TEST_OBJS:.o=.dep) endif endif GRPC_FETCH_OAUTH2_SRC = \ test/core/security/fetch_oauth2.c \ GRPC_FETCH_OAUTH2_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_FETCH_OAUTH2_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2: openssl_dep_error else $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2: $(GRPC_FETCH_OAUTH2_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) $(GRPC_FETCH_OAUTH2_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)/grpc_fetch_oauth2 endif $(OBJDIR)/$(CONFIG)/test/core/security/fetch_oauth2.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_grpc_fetch_oauth2: $(GRPC_FETCH_OAUTH2_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GRPC_FETCH_OAUTH2_OBJS:.o=.dep) endif endif GRPC_INVALID_CHANNEL_ARGS_TEST_SRC = \ test/core/surface/invalid_channel_args_test.c \ GRPC_INVALID_CHANNEL_ARGS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_INVALID_CHANNEL_ARGS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/grpc_invalid_channel_args_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/grpc_invalid_channel_args_test: $(GRPC_INVALID_CHANNEL_ARGS_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) $(GRPC_INVALID_CHANNEL_ARGS_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)/grpc_invalid_channel_args_test endif $(OBJDIR)/$(CONFIG)/test/core/surface/invalid_channel_args_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_grpc_invalid_channel_args_test: $(GRPC_INVALID_CHANNEL_ARGS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GRPC_INVALID_CHANNEL_ARGS_TEST_OBJS:.o=.dep) endif endif GRPC_JSON_TOKEN_TEST_SRC = \ test/core/security/json_token_test.c \ GRPC_JSON_TOKEN_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_JSON_TOKEN_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/grpc_json_token_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/grpc_json_token_test: $(GRPC_JSON_TOKEN_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) $(GRPC_JSON_TOKEN_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)/grpc_json_token_test endif $(OBJDIR)/$(CONFIG)/test/core/security/json_token_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_grpc_json_token_test: $(GRPC_JSON_TOKEN_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GRPC_JSON_TOKEN_TEST_OBJS:.o=.dep) endif endif GRPC_JWT_VERIFIER_TEST_SRC = \ test/core/security/jwt_verifier_test.c \ GRPC_JWT_VERIFIER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_JWT_VERIFIER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test: $(GRPC_JWT_VERIFIER_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) $(GRPC_JWT_VERIFIER_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)/grpc_jwt_verifier_test endif $(OBJDIR)/$(CONFIG)/test/core/security/jwt_verifier_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_grpc_jwt_verifier_test: $(GRPC_JWT_VERIFIER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GRPC_JWT_VERIFIER_TEST_OBJS:.o=.dep) endif endif GRPC_PRINT_GOOGLE_DEFAULT_CREDS_TOKEN_SRC = \ test/core/security/print_google_default_creds_token.c \ GRPC_PRINT_GOOGLE_DEFAULT_CREDS_TOKEN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_PRINT_GOOGLE_DEFAULT_CREDS_TOKEN_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token: openssl_dep_error else $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token: $(GRPC_PRINT_GOOGLE_DEFAULT_CREDS_TOKEN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GRPC_PRINT_GOOGLE_DEFAULT_CREDS_TOKEN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token endif $(OBJDIR)/$(CONFIG)/test/core/security/print_google_default_creds_token.o: $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_grpc_print_google_default_creds_token: $(GRPC_PRINT_GOOGLE_DEFAULT_CREDS_TOKEN_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GRPC_PRINT_GOOGLE_DEFAULT_CREDS_TOKEN_OBJS:.o=.dep) endif endif GRPC_SECURITY_CONNECTOR_TEST_SRC = \ test/core/security/security_connector_test.c \ GRPC_SECURITY_CONNECTOR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_SECURITY_CONNECTOR_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/grpc_security_connector_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/grpc_security_connector_test: $(GRPC_SECURITY_CONNECTOR_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) $(GRPC_SECURITY_CONNECTOR_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)/grpc_security_connector_test endif $(OBJDIR)/$(CONFIG)/test/core/security/security_connector_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_grpc_security_connector_test: $(GRPC_SECURITY_CONNECTOR_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GRPC_SECURITY_CONNECTOR_TEST_OBJS:.o=.dep) endif endif GRPC_VERIFY_JWT_SRC = \ test/core/security/verify_jwt.c \ GRPC_VERIFY_JWT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_VERIFY_JWT_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/grpc_verify_jwt: openssl_dep_error else $(BINDIR)/$(CONFIG)/grpc_verify_jwt: $(GRPC_VERIFY_JWT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(GRPC_VERIFY_JWT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/grpc_verify_jwt endif $(OBJDIR)/$(CONFIG)/test/core/security/verify_jwt.o: $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_grpc_verify_jwt: $(GRPC_VERIFY_JWT_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GRPC_VERIFY_JWT_OBJS:.o=.dep) endif endif HANDSHAKE_CLIENT_SRC = \ test/core/handshake/client_ssl.c \ HANDSHAKE_CLIENT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HANDSHAKE_CLIENT_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/handshake_client: openssl_dep_error else $(BINDIR)/$(CONFIG)/handshake_client: $(HANDSHAKE_CLIENT_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) $(HANDSHAKE_CLIENT_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)/handshake_client endif $(OBJDIR)/$(CONFIG)/test/core/handshake/client_ssl.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_handshake_client: $(HANDSHAKE_CLIENT_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(HANDSHAKE_CLIENT_OBJS:.o=.dep) endif endif HANDSHAKE_SERVER_SRC = \ test/core/handshake/server_ssl.c \ HANDSHAKE_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HANDSHAKE_SERVER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/handshake_server: openssl_dep_error else $(BINDIR)/$(CONFIG)/handshake_server: $(HANDSHAKE_SERVER_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) $(HANDSHAKE_SERVER_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)/handshake_server endif $(OBJDIR)/$(CONFIG)/test/core/handshake/server_ssl.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_handshake_server: $(HANDSHAKE_SERVER_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(HANDSHAKE_SERVER_OBJS:.o=.dep) endif endif HPACK_PARSER_FUZZER_TEST_SRC = \ test/core/transport/chttp2/hpack_parser_fuzzer_test.c \ HPACK_PARSER_FUZZER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HPACK_PARSER_FUZZER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test: $(HPACK_PARSER_FUZZER_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) $(LDXX) $(LDFLAGS) $(HPACK_PARSER_FUZZER_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) -lFuzzer -o $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test endif $(OBJDIR)/$(CONFIG)/test/core/transport/chttp2/hpack_parser_fuzzer_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_hpack_parser_fuzzer_test: $(HPACK_PARSER_FUZZER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(HPACK_PARSER_FUZZER_TEST_OBJS:.o=.dep) endif endif HPACK_PARSER_TEST_SRC = \ test/core/transport/chttp2/hpack_parser_test.c \ HPACK_PARSER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HPACK_PARSER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/hpack_parser_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/hpack_parser_test: $(HPACK_PARSER_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) $(HPACK_PARSER_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)/hpack_parser_test endif $(OBJDIR)/$(CONFIG)/test/core/transport/chttp2/hpack_parser_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_hpack_parser_test: $(HPACK_PARSER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(HPACK_PARSER_TEST_OBJS:.o=.dep) endif endif HPACK_TABLE_TEST_SRC = \ test/core/transport/chttp2/hpack_table_test.c \ HPACK_TABLE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HPACK_TABLE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/hpack_table_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/hpack_table_test: $(HPACK_TABLE_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) $(HPACK_TABLE_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)/hpack_table_test endif $(OBJDIR)/$(CONFIG)/test/core/transport/chttp2/hpack_table_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_hpack_table_test: $(HPACK_TABLE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(HPACK_TABLE_TEST_OBJS:.o=.dep) endif endif HTTP_PARSER_TEST_SRC = \ test/core/http/parser_test.c \ HTTP_PARSER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_PARSER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/http_parser_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/http_parser_test: $(HTTP_PARSER_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) $(HTTP_PARSER_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)/http_parser_test endif $(OBJDIR)/$(CONFIG)/test/core/http/parser_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_http_parser_test: $(HTTP_PARSER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(HTTP_PARSER_TEST_OBJS:.o=.dep) endif endif HTTP_REQUEST_FUZZER_TEST_SRC = \ test/core/http/request_fuzzer.c \ HTTP_REQUEST_FUZZER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_REQUEST_FUZZER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/http_request_fuzzer_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/http_request_fuzzer_test: $(HTTP_REQUEST_FUZZER_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) $(LDXX) $(LDFLAGS) $(HTTP_REQUEST_FUZZER_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) -lFuzzer -o $(BINDIR)/$(CONFIG)/http_request_fuzzer_test endif $(OBJDIR)/$(CONFIG)/test/core/http/request_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_http_request_fuzzer_test: $(HTTP_REQUEST_FUZZER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(HTTP_REQUEST_FUZZER_TEST_OBJS:.o=.dep) endif endif HTTP_RESPONSE_FUZZER_TEST_SRC = \ test/core/http/response_fuzzer.c \ HTTP_RESPONSE_FUZZER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_RESPONSE_FUZZER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/http_response_fuzzer_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/http_response_fuzzer_test: $(HTTP_RESPONSE_FUZZER_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) $(LDXX) $(LDFLAGS) $(HTTP_RESPONSE_FUZZER_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) -lFuzzer -o $(BINDIR)/$(CONFIG)/http_response_fuzzer_test endif $(OBJDIR)/$(CONFIG)/test/core/http/response_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_http_response_fuzzer_test: $(HTTP_RESPONSE_FUZZER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(HTTP_RESPONSE_FUZZER_TEST_OBJS:.o=.dep) endif endif HTTPCLI_FORMAT_REQUEST_TEST_SRC = \ test/core/http/format_request_test.c \ HTTPCLI_FORMAT_REQUEST_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTPCLI_FORMAT_REQUEST_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/httpcli_format_request_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/httpcli_format_request_test: $(HTTPCLI_FORMAT_REQUEST_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) $(HTTPCLI_FORMAT_REQUEST_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)/httpcli_format_request_test endif $(OBJDIR)/$(CONFIG)/test/core/http/format_request_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_httpcli_format_request_test: $(HTTPCLI_FORMAT_REQUEST_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(HTTPCLI_FORMAT_REQUEST_TEST_OBJS:.o=.dep) endif endif HTTPCLI_TEST_SRC = \ test/core/http/httpcli_test.c \ HTTPCLI_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTPCLI_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/httpcli_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/httpcli_test: $(HTTPCLI_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) $(HTTPCLI_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)/httpcli_test endif $(OBJDIR)/$(CONFIG)/test/core/http/httpcli_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_httpcli_test: $(HTTPCLI_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(HTTPCLI_TEST_OBJS:.o=.dep) endif endif HTTPSCLI_TEST_SRC = \ test/core/http/httpscli_test.c \ HTTPSCLI_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTPSCLI_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/httpscli_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/httpscli_test: $(HTTPSCLI_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) $(HTTPSCLI_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)/httpscli_test endif $(OBJDIR)/$(CONFIG)/test/core/http/httpscli_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_httpscli_test: $(HTTPSCLI_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(HTTPSCLI_TEST_OBJS:.o=.dep) endif endif INIT_TEST_SRC = \ test/core/surface/init_test.c \ INIT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(INIT_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/init_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/init_test: $(INIT_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) $(INIT_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)/init_test endif $(OBJDIR)/$(CONFIG)/test/core/surface/init_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_init_test: $(INIT_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(INIT_TEST_OBJS:.o=.dep) endif endif INVALID_CALL_ARGUMENT_TEST_SRC = \ test/core/end2end/invalid_call_argument_test.c \ INVALID_CALL_ARGUMENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(INVALID_CALL_ARGUMENT_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/invalid_call_argument_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/invalid_call_argument_test: $(INVALID_CALL_ARGUMENT_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) $(INVALID_CALL_ARGUMENT_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)/invalid_call_argument_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/invalid_call_argument_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_invalid_call_argument_test: $(INVALID_CALL_ARGUMENT_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(INVALID_CALL_ARGUMENT_TEST_OBJS:.o=.dep) endif endif JSON_FUZZER_TEST_SRC = \ test/core/json/fuzzer.c \ JSON_FUZZER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_FUZZER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/json_fuzzer_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/json_fuzzer_test: $(JSON_FUZZER_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) $(LDXX) $(LDFLAGS) $(JSON_FUZZER_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) -lFuzzer -o $(BINDIR)/$(CONFIG)/json_fuzzer_test endif $(OBJDIR)/$(CONFIG)/test/core/json/fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_json_fuzzer_test: $(JSON_FUZZER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(JSON_FUZZER_TEST_OBJS:.o=.dep) endif endif JSON_REWRITE_SRC = \ test/core/json/json_rewrite.c \ JSON_REWRITE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_REWRITE_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/json_rewrite: openssl_dep_error else $(BINDIR)/$(CONFIG)/json_rewrite: $(JSON_REWRITE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(JSON_REWRITE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/json_rewrite endif $(OBJDIR)/$(CONFIG)/test/core/json/json_rewrite.o: $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_json_rewrite: $(JSON_REWRITE_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(JSON_REWRITE_OBJS:.o=.dep) endif endif JSON_REWRITE_TEST_SRC = \ test/core/json/json_rewrite_test.c \ JSON_REWRITE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_REWRITE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/json_rewrite_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/json_rewrite_test: $(JSON_REWRITE_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) $(JSON_REWRITE_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)/json_rewrite_test endif $(OBJDIR)/$(CONFIG)/test/core/json/json_rewrite_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_json_rewrite_test: $(JSON_REWRITE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(JSON_REWRITE_TEST_OBJS:.o=.dep) endif endif JSON_STREAM_ERROR_TEST_SRC = \ test/core/json/json_stream_error_test.c \ JSON_STREAM_ERROR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_STREAM_ERROR_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/json_stream_error_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/json_stream_error_test: $(JSON_STREAM_ERROR_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) $(JSON_STREAM_ERROR_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)/json_stream_error_test endif $(OBJDIR)/$(CONFIG)/test/core/json/json_stream_error_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_json_stream_error_test: $(JSON_STREAM_ERROR_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(JSON_STREAM_ERROR_TEST_OBJS:.o=.dep) endif endif JSON_TEST_SRC = \ test/core/json/json_test.c \ JSON_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/json_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/json_test: $(JSON_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) $(JSON_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)/json_test endif $(OBJDIR)/$(CONFIG)/test/core/json/json_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_json_test: $(JSON_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(JSON_TEST_OBJS:.o=.dep) endif endif LAME_CLIENT_TEST_SRC = \ test/core/surface/lame_client_test.c \ LAME_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LAME_CLIENT_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/lame_client_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/lame_client_test: $(LAME_CLIENT_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) $(LAME_CLIENT_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)/lame_client_test endif $(OBJDIR)/$(CONFIG)/test/core/surface/lame_client_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_lame_client_test: $(LAME_CLIENT_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LAME_CLIENT_TEST_OBJS:.o=.dep) endif endif LB_POLICIES_TEST_SRC = \ test/core/client_channel/lb_policies_test.c \ LB_POLICIES_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LB_POLICIES_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/lb_policies_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/lb_policies_test: $(LB_POLICIES_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) $(LB_POLICIES_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)/lb_policies_test endif $(OBJDIR)/$(CONFIG)/test/core/client_channel/lb_policies_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_lb_policies_test: $(LB_POLICIES_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LB_POLICIES_TEST_OBJS:.o=.dep) endif endif LOAD_FILE_TEST_SRC = \ test/core/iomgr/load_file_test.c \ LOAD_FILE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LOAD_FILE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/load_file_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/load_file_test: $(LOAD_FILE_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) $(LOAD_FILE_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)/load_file_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/load_file_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_load_file_test: $(LOAD_FILE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LOAD_FILE_TEST_OBJS:.o=.dep) endif endif LOW_LEVEL_PING_PONG_BENCHMARK_SRC = \ test/core/network_benchmarks/low_level_ping_pong.c \ LOW_LEVEL_PING_PONG_BENCHMARK_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LOW_LEVEL_PING_PONG_BENCHMARK_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/low_level_ping_pong_benchmark: openssl_dep_error else $(BINDIR)/$(CONFIG)/low_level_ping_pong_benchmark: $(LOW_LEVEL_PING_PONG_BENCHMARK_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) $(LOW_LEVEL_PING_PONG_BENCHMARK_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)/low_level_ping_pong_benchmark endif $(OBJDIR)/$(CONFIG)/test/core/network_benchmarks/low_level_ping_pong.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_low_level_ping_pong_benchmark: $(LOW_LEVEL_PING_PONG_BENCHMARK_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LOW_LEVEL_PING_PONG_BENCHMARK_OBJS:.o=.dep) endif endif MEMORY_PROFILE_CLIENT_SRC = \ test/core/memory_usage/client.c \ MEMORY_PROFILE_CLIENT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MEMORY_PROFILE_CLIENT_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/memory_profile_client: openssl_dep_error else $(BINDIR)/$(CONFIG)/memory_profile_client: $(MEMORY_PROFILE_CLIENT_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) $(MEMORY_PROFILE_CLIENT_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)/memory_profile_client endif $(OBJDIR)/$(CONFIG)/test/core/memory_usage/client.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_memory_profile_client: $(MEMORY_PROFILE_CLIENT_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(MEMORY_PROFILE_CLIENT_OBJS:.o=.dep) endif endif MEMORY_PROFILE_SERVER_SRC = \ test/core/memory_usage/server.c \ MEMORY_PROFILE_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MEMORY_PROFILE_SERVER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/memory_profile_server: openssl_dep_error else $(BINDIR)/$(CONFIG)/memory_profile_server: $(MEMORY_PROFILE_SERVER_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) $(MEMORY_PROFILE_SERVER_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)/memory_profile_server endif $(OBJDIR)/$(CONFIG)/test/core/memory_usage/server.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_memory_profile_server: $(MEMORY_PROFILE_SERVER_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(MEMORY_PROFILE_SERVER_OBJS:.o=.dep) endif endif MEMORY_PROFILE_TEST_SRC = \ test/core/memory_usage/memory_usage_test.c \ MEMORY_PROFILE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MEMORY_PROFILE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/memory_profile_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/memory_profile_test: $(MEMORY_PROFILE_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) $(MEMORY_PROFILE_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)/memory_profile_test endif $(OBJDIR)/$(CONFIG)/test/core/memory_usage/memory_usage_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_memory_profile_test: $(MEMORY_PROFILE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(MEMORY_PROFILE_TEST_OBJS:.o=.dep) endif endif MESSAGE_COMPRESS_TEST_SRC = \ test/core/compression/message_compress_test.c \ MESSAGE_COMPRESS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MESSAGE_COMPRESS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/message_compress_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/message_compress_test: $(MESSAGE_COMPRESS_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) $(MESSAGE_COMPRESS_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)/message_compress_test endif $(OBJDIR)/$(CONFIG)/test/core/compression/message_compress_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_message_compress_test: $(MESSAGE_COMPRESS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(MESSAGE_COMPRESS_TEST_OBJS:.o=.dep) endif endif MLOG_TEST_SRC = \ test/core/census/mlog_test.c \ MLOG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MLOG_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/mlog_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/mlog_test: $(MLOG_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) $(MLOG_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)/mlog_test endif $(OBJDIR)/$(CONFIG)/test/core/census/mlog_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_mlog_test: $(MLOG_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(MLOG_TEST_OBJS:.o=.dep) endif endif MULTIPLE_SERVER_QUEUES_TEST_SRC = \ test/core/end2end/multiple_server_queues_test.c \ MULTIPLE_SERVER_QUEUES_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MULTIPLE_SERVER_QUEUES_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/multiple_server_queues_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/multiple_server_queues_test: $(MULTIPLE_SERVER_QUEUES_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) $(MULTIPLE_SERVER_QUEUES_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)/multiple_server_queues_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/multiple_server_queues_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_multiple_server_queues_test: $(MULTIPLE_SERVER_QUEUES_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(MULTIPLE_SERVER_QUEUES_TEST_OBJS:.o=.dep) endif endif MURMUR_HASH_TEST_SRC = \ test/core/support/murmur_hash_test.c \ MURMUR_HASH_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MURMUR_HASH_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/murmur_hash_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/murmur_hash_test: $(MURMUR_HASH_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(MURMUR_HASH_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/murmur_hash_test endif $(OBJDIR)/$(CONFIG)/test/core/support/murmur_hash_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_murmur_hash_test: $(MURMUR_HASH_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(MURMUR_HASH_TEST_OBJS:.o=.dep) endif endif NANOPB_FUZZER_RESPONSE_TEST_SRC = \ test/core/nanopb/fuzzer_response.c \ NANOPB_FUZZER_RESPONSE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(NANOPB_FUZZER_RESPONSE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test: $(NANOPB_FUZZER_RESPONSE_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) $(LDXX) $(LDFLAGS) $(NANOPB_FUZZER_RESPONSE_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) -lFuzzer -o $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test endif $(OBJDIR)/$(CONFIG)/test/core/nanopb/fuzzer_response.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_nanopb_fuzzer_response_test: $(NANOPB_FUZZER_RESPONSE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(NANOPB_FUZZER_RESPONSE_TEST_OBJS:.o=.dep) endif endif NANOPB_FUZZER_SERVERLIST_TEST_SRC = \ test/core/nanopb/fuzzer_serverlist.c \ NANOPB_FUZZER_SERVERLIST_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(NANOPB_FUZZER_SERVERLIST_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test: $(NANOPB_FUZZER_SERVERLIST_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) $(LDXX) $(LDFLAGS) $(NANOPB_FUZZER_SERVERLIST_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) -lFuzzer -o $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test endif $(OBJDIR)/$(CONFIG)/test/core/nanopb/fuzzer_serverlist.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_nanopb_fuzzer_serverlist_test: $(NANOPB_FUZZER_SERVERLIST_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(NANOPB_FUZZER_SERVERLIST_TEST_OBJS:.o=.dep) endif endif NO_SERVER_TEST_SRC = \ test/core/end2end/no_server_test.c \ NO_SERVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(NO_SERVER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/no_server_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/no_server_test: $(NO_SERVER_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) $(NO_SERVER_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)/no_server_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/no_server_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_no_server_test: $(NO_SERVER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(NO_SERVER_TEST_OBJS:.o=.dep) endif endif PARSE_ADDRESS_TEST_SRC = \ test/core/client_channel/parse_address_test.c \ PARSE_ADDRESS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PARSE_ADDRESS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/parse_address_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/parse_address_test: $(PARSE_ADDRESS_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) $(PARSE_ADDRESS_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)/parse_address_test endif $(OBJDIR)/$(CONFIG)/test/core/client_channel/parse_address_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_parse_address_test: $(PARSE_ADDRESS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(PARSE_ADDRESS_TEST_OBJS:.o=.dep) endif endif PERCENT_DECODE_FUZZER_SRC = \ test/core/slice/percent_decode_fuzzer.c \ PERCENT_DECODE_FUZZER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PERCENT_DECODE_FUZZER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/percent_decode_fuzzer: openssl_dep_error else $(BINDIR)/$(CONFIG)/percent_decode_fuzzer: $(PERCENT_DECODE_FUZZER_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) $(LDXX) $(LDFLAGS) $(PERCENT_DECODE_FUZZER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -lFuzzer -o $(BINDIR)/$(CONFIG)/percent_decode_fuzzer endif $(OBJDIR)/$(CONFIG)/test/core/slice/percent_decode_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_percent_decode_fuzzer: $(PERCENT_DECODE_FUZZER_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(PERCENT_DECODE_FUZZER_OBJS:.o=.dep) endif endif PERCENT_ENCODE_FUZZER_SRC = \ test/core/slice/percent_encode_fuzzer.c \ PERCENT_ENCODE_FUZZER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PERCENT_ENCODE_FUZZER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/percent_encode_fuzzer: openssl_dep_error else $(BINDIR)/$(CONFIG)/percent_encode_fuzzer: $(PERCENT_ENCODE_FUZZER_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) $(LDXX) $(LDFLAGS) $(PERCENT_ENCODE_FUZZER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -lFuzzer -o $(BINDIR)/$(CONFIG)/percent_encode_fuzzer endif $(OBJDIR)/$(CONFIG)/test/core/slice/percent_encode_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_percent_encode_fuzzer: $(PERCENT_ENCODE_FUZZER_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(PERCENT_ENCODE_FUZZER_OBJS:.o=.dep) endif endif PERCENT_ENCODING_TEST_SRC = \ test/core/slice/percent_encoding_test.c \ PERCENT_ENCODING_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PERCENT_ENCODING_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/percent_encoding_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/percent_encoding_test: $(PERCENT_ENCODING_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) $(PERCENT_ENCODING_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)/percent_encoding_test endif $(OBJDIR)/$(CONFIG)/test/core/slice/percent_encoding_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_percent_encoding_test: $(PERCENT_ENCODING_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(PERCENT_ENCODING_TEST_OBJS:.o=.dep) endif endif POLLSET_SET_TEST_SRC = \ test/core/iomgr/pollset_set_test.c \ POLLSET_SET_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(POLLSET_SET_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/pollset_set_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/pollset_set_test: $(POLLSET_SET_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) $(POLLSET_SET_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)/pollset_set_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/pollset_set_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_pollset_set_test: $(POLLSET_SET_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(POLLSET_SET_TEST_OBJS:.o=.dep) endif endif RESOLVE_ADDRESS_POSIX_TEST_SRC = \ test/core/iomgr/resolve_address_posix_test.c \ RESOLVE_ADDRESS_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOLVE_ADDRESS_POSIX_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/resolve_address_posix_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/resolve_address_posix_test: $(RESOLVE_ADDRESS_POSIX_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) $(RESOLVE_ADDRESS_POSIX_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)/resolve_address_posix_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/resolve_address_posix_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_resolve_address_posix_test: $(RESOLVE_ADDRESS_POSIX_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(RESOLVE_ADDRESS_POSIX_TEST_OBJS:.o=.dep) endif endif RESOLVE_ADDRESS_TEST_SRC = \ test/core/iomgr/resolve_address_test.c \ RESOLVE_ADDRESS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOLVE_ADDRESS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/resolve_address_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/resolve_address_test: $(RESOLVE_ADDRESS_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) $(RESOLVE_ADDRESS_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)/resolve_address_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/resolve_address_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_resolve_address_test: $(RESOLVE_ADDRESS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(RESOLVE_ADDRESS_TEST_OBJS:.o=.dep) endif endif RESOURCE_QUOTA_TEST_SRC = \ test/core/iomgr/resource_quota_test.c \ RESOURCE_QUOTA_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOURCE_QUOTA_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/resource_quota_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/resource_quota_test: $(RESOURCE_QUOTA_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) $(RESOURCE_QUOTA_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)/resource_quota_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/resource_quota_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_resource_quota_test: $(RESOURCE_QUOTA_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(RESOURCE_QUOTA_TEST_OBJS:.o=.dep) endif endif SECURE_CHANNEL_CREATE_TEST_SRC = \ test/core/surface/secure_channel_create_test.c \ SECURE_CHANNEL_CREATE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SECURE_CHANNEL_CREATE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/secure_channel_create_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/secure_channel_create_test: $(SECURE_CHANNEL_CREATE_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) $(SECURE_CHANNEL_CREATE_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)/secure_channel_create_test endif $(OBJDIR)/$(CONFIG)/test/core/surface/secure_channel_create_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_secure_channel_create_test: $(SECURE_CHANNEL_CREATE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SECURE_CHANNEL_CREATE_TEST_OBJS:.o=.dep) endif endif SECURE_ENDPOINT_TEST_SRC = \ test/core/security/secure_endpoint_test.c \ SECURE_ENDPOINT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SECURE_ENDPOINT_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/secure_endpoint_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/secure_endpoint_test: $(SECURE_ENDPOINT_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) $(SECURE_ENDPOINT_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)/secure_endpoint_test endif $(OBJDIR)/$(CONFIG)/test/core/security/secure_endpoint_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_secure_endpoint_test: $(SECURE_ENDPOINT_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SECURE_ENDPOINT_TEST_OBJS:.o=.dep) endif endif SEQUENTIAL_CONNECTIVITY_TEST_SRC = \ test/core/surface/sequential_connectivity_test.c \ SEQUENTIAL_CONNECTIVITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SEQUENTIAL_CONNECTIVITY_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/sequential_connectivity_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/sequential_connectivity_test: $(SEQUENTIAL_CONNECTIVITY_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) $(SEQUENTIAL_CONNECTIVITY_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)/sequential_connectivity_test endif $(OBJDIR)/$(CONFIG)/test/core/surface/sequential_connectivity_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_sequential_connectivity_test: $(SEQUENTIAL_CONNECTIVITY_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SEQUENTIAL_CONNECTIVITY_TEST_OBJS:.o=.dep) endif endif SERVER_CHTTP2_TEST_SRC = \ test/core/surface/server_chttp2_test.c \ SERVER_CHTTP2_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_CHTTP2_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/server_chttp2_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/server_chttp2_test: $(SERVER_CHTTP2_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) $(SERVER_CHTTP2_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)/server_chttp2_test endif $(OBJDIR)/$(CONFIG)/test/core/surface/server_chttp2_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_server_chttp2_test: $(SERVER_CHTTP2_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SERVER_CHTTP2_TEST_OBJS:.o=.dep) endif endif SERVER_FUZZER_SRC = \ test/core/end2end/fuzzers/server_fuzzer.c \ SERVER_FUZZER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_FUZZER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/server_fuzzer: openssl_dep_error else $(BINDIR)/$(CONFIG)/server_fuzzer: $(SERVER_FUZZER_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) $(LDXX) $(LDFLAGS) $(SERVER_FUZZER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -lFuzzer -o $(BINDIR)/$(CONFIG)/server_fuzzer endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fuzzers/server_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_server_fuzzer: $(SERVER_FUZZER_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SERVER_FUZZER_OBJS:.o=.dep) endif endif SERVER_TEST_SRC = \ test/core/surface/server_test.c \ SERVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/server_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/server_test: $(SERVER_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) $(SERVER_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)/server_test endif $(OBJDIR)/$(CONFIG)/test/core/surface/server_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_server_test: $(SERVER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SERVER_TEST_OBJS:.o=.dep) endif endif SLICE_BUFFER_TEST_SRC = \ test/core/slice/slice_buffer_test.c \ SLICE_BUFFER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SLICE_BUFFER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/slice_buffer_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/slice_buffer_test: $(SLICE_BUFFER_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) $(SLICE_BUFFER_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)/slice_buffer_test endif $(OBJDIR)/$(CONFIG)/test/core/slice/slice_buffer_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_slice_buffer_test: $(SLICE_BUFFER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SLICE_BUFFER_TEST_OBJS:.o=.dep) endif endif SLICE_STRING_HELPERS_TEST_SRC = \ test/core/slice/slice_string_helpers_test.c \ SLICE_STRING_HELPERS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SLICE_STRING_HELPERS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/slice_string_helpers_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/slice_string_helpers_test: $(SLICE_STRING_HELPERS_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) $(SLICE_STRING_HELPERS_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)/slice_string_helpers_test endif $(OBJDIR)/$(CONFIG)/test/core/slice/slice_string_helpers_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_slice_string_helpers_test: $(SLICE_STRING_HELPERS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SLICE_STRING_HELPERS_TEST_OBJS:.o=.dep) endif endif SLICE_TEST_SRC = \ test/core/slice/slice_test.c \ SLICE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SLICE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/slice_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/slice_test: $(SLICE_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) $(SLICE_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)/slice_test endif $(OBJDIR)/$(CONFIG)/test/core/slice/slice_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_slice_test: $(SLICE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SLICE_TEST_OBJS:.o=.dep) endif endif SOCKADDR_RESOLVER_TEST_SRC = \ test/core/client_channel/resolvers/sockaddr_resolver_test.c \ SOCKADDR_RESOLVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SOCKADDR_RESOLVER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/sockaddr_resolver_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/sockaddr_resolver_test: $(SOCKADDR_RESOLVER_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) $(SOCKADDR_RESOLVER_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)/sockaddr_resolver_test endif $(OBJDIR)/$(CONFIG)/test/core/client_channel/resolvers/sockaddr_resolver_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_sockaddr_resolver_test: $(SOCKADDR_RESOLVER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SOCKADDR_RESOLVER_TEST_OBJS:.o=.dep) endif endif SOCKADDR_UTILS_TEST_SRC = \ test/core/iomgr/sockaddr_utils_test.c \ SOCKADDR_UTILS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SOCKADDR_UTILS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/sockaddr_utils_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/sockaddr_utils_test: $(SOCKADDR_UTILS_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) $(SOCKADDR_UTILS_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)/sockaddr_utils_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/sockaddr_utils_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_sockaddr_utils_test: $(SOCKADDR_UTILS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SOCKADDR_UTILS_TEST_OBJS:.o=.dep) endif endif SOCKET_UTILS_TEST_SRC = \ test/core/iomgr/socket_utils_test.c \ SOCKET_UTILS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SOCKET_UTILS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/socket_utils_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/socket_utils_test: $(SOCKET_UTILS_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) $(SOCKET_UTILS_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)/socket_utils_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/socket_utils_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_socket_utils_test: $(SOCKET_UTILS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SOCKET_UTILS_TEST_OBJS:.o=.dep) endif endif SSL_SERVER_FUZZER_SRC = \ test/core/security/ssl_server_fuzzer.c \ SSL_SERVER_FUZZER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SSL_SERVER_FUZZER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/ssl_server_fuzzer: openssl_dep_error else $(BINDIR)/$(CONFIG)/ssl_server_fuzzer: $(SSL_SERVER_FUZZER_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) $(LDXX) $(LDFLAGS) $(SSL_SERVER_FUZZER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -lFuzzer -o $(BINDIR)/$(CONFIG)/ssl_server_fuzzer endif $(OBJDIR)/$(CONFIG)/test/core/security/ssl_server_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_ssl_server_fuzzer: $(SSL_SERVER_FUZZER_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SSL_SERVER_FUZZER_OBJS:.o=.dep) endif endif STATUS_CONVERSION_TEST_SRC = \ test/core/transport/status_conversion_test.c \ STATUS_CONVERSION_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(STATUS_CONVERSION_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/status_conversion_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/status_conversion_test: $(STATUS_CONVERSION_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) $(STATUS_CONVERSION_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)/status_conversion_test endif $(OBJDIR)/$(CONFIG)/test/core/transport/status_conversion_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_status_conversion_test: $(STATUS_CONVERSION_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(STATUS_CONVERSION_TEST_OBJS:.o=.dep) endif endif STREAM_OWNED_SLICE_TEST_SRC = \ test/core/transport/stream_owned_slice_test.c \ STREAM_OWNED_SLICE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(STREAM_OWNED_SLICE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/stream_owned_slice_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/stream_owned_slice_test: $(STREAM_OWNED_SLICE_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) $(STREAM_OWNED_SLICE_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)/stream_owned_slice_test endif $(OBJDIR)/$(CONFIG)/test/core/transport/stream_owned_slice_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_stream_owned_slice_test: $(STREAM_OWNED_SLICE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(STREAM_OWNED_SLICE_TEST_OBJS:.o=.dep) endif endif TCP_CLIENT_POSIX_TEST_SRC = \ test/core/iomgr/tcp_client_posix_test.c \ TCP_CLIENT_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TCP_CLIENT_POSIX_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/tcp_client_posix_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/tcp_client_posix_test: $(TCP_CLIENT_POSIX_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) $(TCP_CLIENT_POSIX_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)/tcp_client_posix_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/tcp_client_posix_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_tcp_client_posix_test: $(TCP_CLIENT_POSIX_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(TCP_CLIENT_POSIX_TEST_OBJS:.o=.dep) endif endif TCP_CLIENT_UV_TEST_SRC = \ test/core/iomgr/tcp_client_uv_test.c \ TCP_CLIENT_UV_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TCP_CLIENT_UV_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/tcp_client_uv_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/tcp_client_uv_test: $(TCP_CLIENT_UV_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) $(TCP_CLIENT_UV_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)/tcp_client_uv_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/tcp_client_uv_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_tcp_client_uv_test: $(TCP_CLIENT_UV_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(TCP_CLIENT_UV_TEST_OBJS:.o=.dep) endif endif TCP_POSIX_TEST_SRC = \ test/core/iomgr/tcp_posix_test.c \ TCP_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TCP_POSIX_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/tcp_posix_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/tcp_posix_test: $(TCP_POSIX_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) $(TCP_POSIX_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)/tcp_posix_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/tcp_posix_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_tcp_posix_test: $(TCP_POSIX_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(TCP_POSIX_TEST_OBJS:.o=.dep) endif endif TCP_SERVER_POSIX_TEST_SRC = \ test/core/iomgr/tcp_server_posix_test.c \ TCP_SERVER_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TCP_SERVER_POSIX_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/tcp_server_posix_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/tcp_server_posix_test: $(TCP_SERVER_POSIX_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) $(TCP_SERVER_POSIX_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)/tcp_server_posix_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/tcp_server_posix_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_tcp_server_posix_test: $(TCP_SERVER_POSIX_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(TCP_SERVER_POSIX_TEST_OBJS:.o=.dep) endif endif TCP_SERVER_UV_TEST_SRC = \ test/core/iomgr/tcp_server_uv_test.c \ TCP_SERVER_UV_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TCP_SERVER_UV_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/tcp_server_uv_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/tcp_server_uv_test: $(TCP_SERVER_UV_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) $(TCP_SERVER_UV_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)/tcp_server_uv_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/tcp_server_uv_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_tcp_server_uv_test: $(TCP_SERVER_UV_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(TCP_SERVER_UV_TEST_OBJS:.o=.dep) endif endif TIME_AVERAGED_STATS_TEST_SRC = \ test/core/iomgr/time_averaged_stats_test.c \ TIME_AVERAGED_STATS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TIME_AVERAGED_STATS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/time_averaged_stats_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/time_averaged_stats_test: $(TIME_AVERAGED_STATS_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) $(TIME_AVERAGED_STATS_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)/time_averaged_stats_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/time_averaged_stats_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_time_averaged_stats_test: $(TIME_AVERAGED_STATS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(TIME_AVERAGED_STATS_TEST_OBJS:.o=.dep) endif endif TIMEOUT_ENCODING_TEST_SRC = \ test/core/transport/timeout_encoding_test.c \ TIMEOUT_ENCODING_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TIMEOUT_ENCODING_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/timeout_encoding_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/timeout_encoding_test: $(TIMEOUT_ENCODING_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) $(TIMEOUT_ENCODING_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)/timeout_encoding_test endif $(OBJDIR)/$(CONFIG)/test/core/transport/timeout_encoding_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_timeout_encoding_test: $(TIMEOUT_ENCODING_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(TIMEOUT_ENCODING_TEST_OBJS:.o=.dep) endif endif TIMER_HEAP_TEST_SRC = \ test/core/iomgr/timer_heap_test.c \ TIMER_HEAP_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TIMER_HEAP_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/timer_heap_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/timer_heap_test: $(TIMER_HEAP_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) $(TIMER_HEAP_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)/timer_heap_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/timer_heap_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_timer_heap_test: $(TIMER_HEAP_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(TIMER_HEAP_TEST_OBJS:.o=.dep) endif endif TIMER_LIST_TEST_SRC = \ test/core/iomgr/timer_list_test.c \ TIMER_LIST_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TIMER_LIST_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/timer_list_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/timer_list_test: $(TIMER_LIST_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) $(TIMER_LIST_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)/timer_list_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/timer_list_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_timer_list_test: $(TIMER_LIST_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(TIMER_LIST_TEST_OBJS:.o=.dep) endif endif TRANSPORT_CONNECTIVITY_STATE_TEST_SRC = \ test/core/transport/connectivity_state_test.c \ TRANSPORT_CONNECTIVITY_STATE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TRANSPORT_CONNECTIVITY_STATE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/transport_connectivity_state_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/transport_connectivity_state_test: $(TRANSPORT_CONNECTIVITY_STATE_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) $(TRANSPORT_CONNECTIVITY_STATE_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)/transport_connectivity_state_test endif $(OBJDIR)/$(CONFIG)/test/core/transport/connectivity_state_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_transport_connectivity_state_test: $(TRANSPORT_CONNECTIVITY_STATE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(TRANSPORT_CONNECTIVITY_STATE_TEST_OBJS:.o=.dep) endif endif TRANSPORT_METADATA_TEST_SRC = \ test/core/transport/metadata_test.c \ TRANSPORT_METADATA_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TRANSPORT_METADATA_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/transport_metadata_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/transport_metadata_test: $(TRANSPORT_METADATA_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) $(TRANSPORT_METADATA_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)/transport_metadata_test endif $(OBJDIR)/$(CONFIG)/test/core/transport/metadata_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_transport_metadata_test: $(TRANSPORT_METADATA_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(TRANSPORT_METADATA_TEST_OBJS:.o=.dep) endif endif TRANSPORT_PID_CONTROLLER_TEST_SRC = \ test/core/transport/pid_controller_test.c \ TRANSPORT_PID_CONTROLLER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TRANSPORT_PID_CONTROLLER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/transport_pid_controller_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/transport_pid_controller_test: $(TRANSPORT_PID_CONTROLLER_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) $(TRANSPORT_PID_CONTROLLER_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)/transport_pid_controller_test endif $(OBJDIR)/$(CONFIG)/test/core/transport/pid_controller_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_transport_pid_controller_test: $(TRANSPORT_PID_CONTROLLER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(TRANSPORT_PID_CONTROLLER_TEST_OBJS:.o=.dep) endif endif TRANSPORT_SECURITY_TEST_SRC = \ test/core/tsi/transport_security_test.c \ TRANSPORT_SECURITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TRANSPORT_SECURITY_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/transport_security_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/transport_security_test: $(TRANSPORT_SECURITY_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) $(TRANSPORT_SECURITY_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)/transport_security_test endif $(OBJDIR)/$(CONFIG)/test/core/tsi/transport_security_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_transport_security_test: $(TRANSPORT_SECURITY_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(TRANSPORT_SECURITY_TEST_OBJS:.o=.dep) endif endif UDP_SERVER_TEST_SRC = \ test/core/iomgr/udp_server_test.c \ UDP_SERVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(UDP_SERVER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/udp_server_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/udp_server_test: $(UDP_SERVER_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) $(UDP_SERVER_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)/udp_server_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/udp_server_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_udp_server_test: $(UDP_SERVER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(UDP_SERVER_TEST_OBJS:.o=.dep) endif endif URI_FUZZER_TEST_SRC = \ test/core/client_channel/uri_fuzzer_test.c \ URI_FUZZER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(URI_FUZZER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/uri_fuzzer_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/uri_fuzzer_test: $(URI_FUZZER_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) $(LDXX) $(LDFLAGS) $(URI_FUZZER_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) -lFuzzer -o $(BINDIR)/$(CONFIG)/uri_fuzzer_test endif $(OBJDIR)/$(CONFIG)/test/core/client_channel/uri_fuzzer_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_uri_fuzzer_test: $(URI_FUZZER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(URI_FUZZER_TEST_OBJS:.o=.dep) endif endif URI_PARSER_TEST_SRC = \ test/core/client_channel/uri_parser_test.c \ URI_PARSER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(URI_PARSER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/uri_parser_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/uri_parser_test: $(URI_PARSER_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) $(URI_PARSER_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)/uri_parser_test endif $(OBJDIR)/$(CONFIG)/test/core/client_channel/uri_parser_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_uri_parser_test: $(URI_PARSER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(URI_PARSER_TEST_OBJS:.o=.dep) endif endif WAKEUP_FD_CV_TEST_SRC = \ test/core/iomgr/wakeup_fd_cv_test.c \ WAKEUP_FD_CV_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(WAKEUP_FD_CV_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/wakeup_fd_cv_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/wakeup_fd_cv_test: $(WAKEUP_FD_CV_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) $(WAKEUP_FD_CV_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)/wakeup_fd_cv_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/wakeup_fd_cv_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_wakeup_fd_cv_test: $(WAKEUP_FD_CV_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(WAKEUP_FD_CV_TEST_OBJS:.o=.dep) endif endif ALARM_CPP_TEST_SRC = \ test/cpp/common/alarm_cpp_test.cc \ ALARM_CPP_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ALARM_CPP_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/alarm_cpp_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/alarm_cpp_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/alarm_cpp_test: $(PROTOBUF_DEP) $(ALARM_CPP_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(ALARM_CPP_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/alarm_cpp_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/common/alarm_cpp_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_alarm_cpp_test: $(ALARM_CPP_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(ALARM_CPP_TEST_OBJS:.o=.dep) endif endif ASYNC_END2END_TEST_SRC = \ test/cpp/end2end/async_end2end_test.cc \ ASYNC_END2END_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ASYNC_END2END_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/async_end2end_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/async_end2end_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/async_end2end_test: $(PROTOBUF_DEP) $(ASYNC_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(ASYNC_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/async_end2end_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/end2end/async_end2end_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_async_end2end_test: $(ASYNC_END2END_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(ASYNC_END2END_TEST_OBJS:.o=.dep) endif endif AUTH_PROPERTY_ITERATOR_TEST_SRC = \ test/cpp/common/auth_property_iterator_test.cc \ AUTH_PROPERTY_ITERATOR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(AUTH_PROPERTY_ITERATOR_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/auth_property_iterator_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/auth_property_iterator_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/auth_property_iterator_test: $(PROTOBUF_DEP) $(AUTH_PROPERTY_ITERATOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(AUTH_PROPERTY_ITERATOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/auth_property_iterator_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/common/auth_property_iterator_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_auth_property_iterator_test: $(AUTH_PROPERTY_ITERATOR_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(AUTH_PROPERTY_ITERATOR_TEST_OBJS:.o=.dep) endif endif BM_ARENA_SRC = \ test/cpp/microbenchmarks/bm_arena.cc \ BM_ARENA_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_ARENA_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/bm_arena: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/bm_arena: protobuf_dep_error else $(BINDIR)/$(CONFIG)/bm_arena: $(PROTOBUF_DEP) $(BM_ARENA_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(BM_ARENA_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_arena endif endif $(BM_ARENA_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX $(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_arena.o: $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_bm_arena: $(BM_ARENA_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(BM_ARENA_OBJS:.o=.dep) endif endif BM_CALL_CREATE_SRC = \ test/cpp/microbenchmarks/bm_call_create.cc \ BM_CALL_CREATE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_CALL_CREATE_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/bm_call_create: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/bm_call_create: protobuf_dep_error else $(BINDIR)/$(CONFIG)/bm_call_create: $(PROTOBUF_DEP) $(BM_CALL_CREATE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(BM_CALL_CREATE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_call_create endif endif $(BM_CALL_CREATE_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX $(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_call_create.o: $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_bm_call_create: $(BM_CALL_CREATE_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(BM_CALL_CREATE_OBJS:.o=.dep) endif endif BM_CHTTP2_HPACK_SRC = \ test/cpp/microbenchmarks/bm_chttp2_hpack.cc \ BM_CHTTP2_HPACK_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_CHTTP2_HPACK_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/bm_chttp2_hpack: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/bm_chttp2_hpack: protobuf_dep_error else $(BINDIR)/$(CONFIG)/bm_chttp2_hpack: $(PROTOBUF_DEP) $(BM_CHTTP2_HPACK_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(BM_CHTTP2_HPACK_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_chttp2_hpack endif endif $(BM_CHTTP2_HPACK_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX $(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_chttp2_hpack.o: $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_bm_chttp2_hpack: $(BM_CHTTP2_HPACK_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(BM_CHTTP2_HPACK_OBJS:.o=.dep) endif endif BM_CHTTP2_TRANSPORT_SRC = \ test/cpp/microbenchmarks/bm_chttp2_transport.cc \ BM_CHTTP2_TRANSPORT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_CHTTP2_TRANSPORT_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/bm_chttp2_transport: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/bm_chttp2_transport: protobuf_dep_error else $(BINDIR)/$(CONFIG)/bm_chttp2_transport: $(PROTOBUF_DEP) $(BM_CHTTP2_TRANSPORT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(BM_CHTTP2_TRANSPORT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_chttp2_transport endif endif $(BM_CHTTP2_TRANSPORT_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX $(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_chttp2_transport.o: $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_bm_chttp2_transport: $(BM_CHTTP2_TRANSPORT_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(BM_CHTTP2_TRANSPORT_OBJS:.o=.dep) endif endif BM_CLOSURE_SRC = \ test/cpp/microbenchmarks/bm_closure.cc \ BM_CLOSURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_CLOSURE_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/bm_closure: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/bm_closure: protobuf_dep_error else $(BINDIR)/$(CONFIG)/bm_closure: $(PROTOBUF_DEP) $(BM_CLOSURE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(BM_CLOSURE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_closure endif endif $(BM_CLOSURE_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX $(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_closure.o: $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_bm_closure: $(BM_CLOSURE_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(BM_CLOSURE_OBJS:.o=.dep) endif endif BM_CQ_SRC = \ test/cpp/microbenchmarks/bm_cq.cc \ BM_CQ_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_CQ_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/bm_cq: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/bm_cq: protobuf_dep_error else $(BINDIR)/$(CONFIG)/bm_cq: $(PROTOBUF_DEP) $(BM_CQ_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(BM_CQ_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_cq endif endif $(BM_CQ_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX $(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_cq.o: $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_bm_cq: $(BM_CQ_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(BM_CQ_OBJS:.o=.dep) endif endif BM_CQ_MULTIPLE_THREADS_SRC = \ test/cpp/microbenchmarks/bm_cq_multiple_threads.cc \ BM_CQ_MULTIPLE_THREADS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_CQ_MULTIPLE_THREADS_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/bm_cq_multiple_threads: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/bm_cq_multiple_threads: protobuf_dep_error else $(BINDIR)/$(CONFIG)/bm_cq_multiple_threads: $(PROTOBUF_DEP) $(BM_CQ_MULTIPLE_THREADS_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(BM_CQ_MULTIPLE_THREADS_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_cq_multiple_threads endif endif $(BM_CQ_MULTIPLE_THREADS_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX $(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_cq_multiple_threads.o: $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_bm_cq_multiple_threads: $(BM_CQ_MULTIPLE_THREADS_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(BM_CQ_MULTIPLE_THREADS_OBJS:.o=.dep) endif endif BM_ERROR_SRC = \ test/cpp/microbenchmarks/bm_error.cc \ BM_ERROR_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_ERROR_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/bm_error: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/bm_error: protobuf_dep_error else $(BINDIR)/$(CONFIG)/bm_error: $(PROTOBUF_DEP) $(BM_ERROR_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(BM_ERROR_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_error endif endif $(BM_ERROR_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX $(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_error.o: $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_bm_error: $(BM_ERROR_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(BM_ERROR_OBJS:.o=.dep) endif endif BM_FULLSTACK_STREAMING_PING_PONG_SRC = \ test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc \ BM_FULLSTACK_STREAMING_PING_PONG_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_FULLSTACK_STREAMING_PING_PONG_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_ping_pong: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_ping_pong: protobuf_dep_error else $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_ping_pong: $(PROTOBUF_DEP) $(BM_FULLSTACK_STREAMING_PING_PONG_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(BM_FULLSTACK_STREAMING_PING_PONG_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_ping_pong endif endif $(BM_FULLSTACK_STREAMING_PING_PONG_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX $(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.o: $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_bm_fullstack_streaming_ping_pong: $(BM_FULLSTACK_STREAMING_PING_PONG_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(BM_FULLSTACK_STREAMING_PING_PONG_OBJS:.o=.dep) endif endif BM_FULLSTACK_STREAMING_PUMP_SRC = \ test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc \ BM_FULLSTACK_STREAMING_PUMP_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_FULLSTACK_STREAMING_PUMP_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_pump: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_pump: protobuf_dep_error else $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_pump: $(PROTOBUF_DEP) $(BM_FULLSTACK_STREAMING_PUMP_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(BM_FULLSTACK_STREAMING_PUMP_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_pump endif endif $(BM_FULLSTACK_STREAMING_PUMP_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX $(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.o: $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_bm_fullstack_streaming_pump: $(BM_FULLSTACK_STREAMING_PUMP_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(BM_FULLSTACK_STREAMING_PUMP_OBJS:.o=.dep) endif endif BM_FULLSTACK_TRICKLE_SRC = \ test/cpp/microbenchmarks/bm_fullstack_trickle.cc \ BM_FULLSTACK_TRICKLE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_FULLSTACK_TRICKLE_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/bm_fullstack_trickle: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/bm_fullstack_trickle: protobuf_dep_error else $(BINDIR)/$(CONFIG)/bm_fullstack_trickle: $(PROTOBUF_DEP) $(BM_FULLSTACK_TRICKLE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(BM_FULLSTACK_TRICKLE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_fullstack_trickle endif endif $(BM_FULLSTACK_TRICKLE_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX $(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_fullstack_trickle.o: $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_bm_fullstack_trickle: $(BM_FULLSTACK_TRICKLE_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(BM_FULLSTACK_TRICKLE_OBJS:.o=.dep) endif endif BM_FULLSTACK_UNARY_PING_PONG_SRC = \ test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc \ BM_FULLSTACK_UNARY_PING_PONG_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_FULLSTACK_UNARY_PING_PONG_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/bm_fullstack_unary_ping_pong: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/bm_fullstack_unary_ping_pong: protobuf_dep_error else $(BINDIR)/$(CONFIG)/bm_fullstack_unary_ping_pong: $(PROTOBUF_DEP) $(BM_FULLSTACK_UNARY_PING_PONG_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(BM_FULLSTACK_UNARY_PING_PONG_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_fullstack_unary_ping_pong endif endif $(BM_FULLSTACK_UNARY_PING_PONG_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX $(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.o: $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_bm_fullstack_unary_ping_pong: $(BM_FULLSTACK_UNARY_PING_PONG_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(BM_FULLSTACK_UNARY_PING_PONG_OBJS:.o=.dep) endif endif BM_METADATA_SRC = \ test/cpp/microbenchmarks/bm_metadata.cc \ BM_METADATA_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_METADATA_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/bm_metadata: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/bm_metadata: protobuf_dep_error else $(BINDIR)/$(CONFIG)/bm_metadata: $(PROTOBUF_DEP) $(BM_METADATA_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(BM_METADATA_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_metadata endif endif $(BM_METADATA_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX $(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_metadata.o: $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_bm_metadata: $(BM_METADATA_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(BM_METADATA_OBJS:.o=.dep) endif endif BM_POLLSET_SRC = \ test/cpp/microbenchmarks/bm_pollset.cc \ BM_POLLSET_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_POLLSET_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/bm_pollset: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/bm_pollset: protobuf_dep_error else $(BINDIR)/$(CONFIG)/bm_pollset: $(PROTOBUF_DEP) $(BM_POLLSET_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(BM_POLLSET_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_pollset endif endif $(BM_POLLSET_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX $(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_pollset.o: $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_bm_pollset: $(BM_POLLSET_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(BM_POLLSET_OBJS:.o=.dep) endif endif CHANNEL_ARGUMENTS_TEST_SRC = \ test/cpp/common/channel_arguments_test.cc \ CHANNEL_ARGUMENTS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHANNEL_ARGUMENTS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/channel_arguments_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/channel_arguments_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/channel_arguments_test: $(PROTOBUF_DEP) $(CHANNEL_ARGUMENTS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(CHANNEL_ARGUMENTS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/channel_arguments_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/common/channel_arguments_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_channel_arguments_test: $(CHANNEL_ARGUMENTS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CHANNEL_ARGUMENTS_TEST_OBJS:.o=.dep) endif endif CHANNEL_FILTER_TEST_SRC = \ test/cpp/common/channel_filter_test.cc \ CHANNEL_FILTER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHANNEL_FILTER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/channel_filter_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/channel_filter_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/channel_filter_test: $(PROTOBUF_DEP) $(CHANNEL_FILTER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(CHANNEL_FILTER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/channel_filter_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/common/channel_filter_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_channel_filter_test: $(CHANNEL_FILTER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CHANNEL_FILTER_TEST_OBJS:.o=.dep) endif endif CLI_CALL_TEST_SRC = \ test/cpp/util/cli_call_test.cc \ CLI_CALL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CLI_CALL_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/cli_call_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/cli_call_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/cli_call_test: $(PROTOBUF_DEP) $(CLI_CALL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(CLI_CALL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/cli_call_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/util/cli_call_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_cli_call_test: $(CLI_CALL_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CLI_CALL_TEST_OBJS:.o=.dep) endif endif CLIENT_CRASH_TEST_SRC = \ test/cpp/end2end/client_crash_test.cc \ CLIENT_CRASH_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CLIENT_CRASH_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/client_crash_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/client_crash_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/client_crash_test: $(PROTOBUF_DEP) $(CLIENT_CRASH_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(CLIENT_CRASH_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/client_crash_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/end2end/client_crash_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_client_crash_test: $(CLIENT_CRASH_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CLIENT_CRASH_TEST_OBJS:.o=.dep) endif endif CLIENT_CRASH_TEST_SERVER_SRC = \ test/cpp/end2end/client_crash_test_server.cc \ CLIENT_CRASH_TEST_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CLIENT_CRASH_TEST_SERVER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/client_crash_test_server: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/client_crash_test_server: protobuf_dep_error else $(BINDIR)/$(CONFIG)/client_crash_test_server: $(PROTOBUF_DEP) $(CLIENT_CRASH_TEST_SERVER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(CLIENT_CRASH_TEST_SERVER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/client_crash_test_server endif endif $(OBJDIR)/$(CONFIG)/test/cpp/end2end/client_crash_test_server.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_client_crash_test_server: $(CLIENT_CRASH_TEST_SERVER_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CLIENT_CRASH_TEST_SERVER_OBJS:.o=.dep) endif endif CODEGEN_TEST_FULL_SRC = \ $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc \ test/cpp/codegen/codegen_test_full.cc \ CODEGEN_TEST_FULL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CODEGEN_TEST_FULL_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/codegen_test_full: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/codegen_test_full: protobuf_dep_error else $(BINDIR)/$(CONFIG)/codegen_test_full: $(PROTOBUF_DEP) $(CODEGEN_TEST_FULL_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(CODEGEN_TEST_FULL_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/codegen_test_full endif endif $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/control.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/messages.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/payloads.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/services.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/stats.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/cpp/codegen/codegen_test_full.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_codegen_test_full: $(CODEGEN_TEST_FULL_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CODEGEN_TEST_FULL_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/test/cpp/codegen/codegen_test_full.o: $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc CODEGEN_TEST_MINIMAL_SRC = \ $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc \ test/cpp/codegen/codegen_test_minimal.cc \ src/cpp/codegen/codegen_init.cc \ CODEGEN_TEST_MINIMAL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CODEGEN_TEST_MINIMAL_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/codegen_test_minimal: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/codegen_test_minimal: protobuf_dep_error else $(BINDIR)/$(CONFIG)/codegen_test_minimal: $(PROTOBUF_DEP) $(CODEGEN_TEST_MINIMAL_OBJS) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(CODEGEN_TEST_MINIMAL_OBJS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/codegen_test_minimal endif endif $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/control.o: $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/messages.o: $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/payloads.o: $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/services.o: $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/stats.o: $(OBJDIR)/$(CONFIG)/test/cpp/codegen/codegen_test_minimal.o: $(OBJDIR)/$(CONFIG)/src/cpp/codegen/codegen_init.o: deps_codegen_test_minimal: $(CODEGEN_TEST_MINIMAL_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CODEGEN_TEST_MINIMAL_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/test/cpp/codegen/codegen_test_minimal.o: $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(OBJDIR)/$(CONFIG)/src/cpp/codegen/codegen_init.o: $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc CREDENTIALS_TEST_SRC = \ test/cpp/client/credentials_test.cc \ CREDENTIALS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CREDENTIALS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/credentials_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/credentials_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/credentials_test: $(PROTOBUF_DEP) $(CREDENTIALS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(CREDENTIALS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/credentials_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/client/credentials_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_credentials_test: $(CREDENTIALS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CREDENTIALS_TEST_OBJS:.o=.dep) endif endif CXX_BYTE_BUFFER_TEST_SRC = \ test/cpp/util/byte_buffer_test.cc \ CXX_BYTE_BUFFER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CXX_BYTE_BUFFER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/cxx_byte_buffer_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/cxx_byte_buffer_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/cxx_byte_buffer_test: $(PROTOBUF_DEP) $(CXX_BYTE_BUFFER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(CXX_BYTE_BUFFER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/cxx_byte_buffer_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/util/byte_buffer_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_cxx_byte_buffer_test: $(CXX_BYTE_BUFFER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CXX_BYTE_BUFFER_TEST_OBJS:.o=.dep) endif endif CXX_SLICE_TEST_SRC = \ test/cpp/util/slice_test.cc \ CXX_SLICE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CXX_SLICE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/cxx_slice_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/cxx_slice_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/cxx_slice_test: $(PROTOBUF_DEP) $(CXX_SLICE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(CXX_SLICE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/cxx_slice_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/util/slice_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_cxx_slice_test: $(CXX_SLICE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CXX_SLICE_TEST_OBJS:.o=.dep) endif endif CXX_STRING_REF_TEST_SRC = \ test/cpp/util/string_ref_test.cc \ CXX_STRING_REF_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CXX_STRING_REF_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/cxx_string_ref_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/cxx_string_ref_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/cxx_string_ref_test: $(PROTOBUF_DEP) $(CXX_STRING_REF_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(CXX_STRING_REF_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/cxx_string_ref_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/util/string_ref_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a deps_cxx_string_ref_test: $(CXX_STRING_REF_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CXX_STRING_REF_TEST_OBJS:.o=.dep) endif endif CXX_TIME_TEST_SRC = \ test/cpp/util/time_test.cc \ CXX_TIME_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CXX_TIME_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/cxx_time_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/cxx_time_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/cxx_time_test: $(PROTOBUF_DEP) $(CXX_TIME_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(CXX_TIME_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/cxx_time_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/util/time_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_cxx_time_test: $(CXX_TIME_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CXX_TIME_TEST_OBJS:.o=.dep) endif endif END2END_TEST_SRC = \ test/cpp/end2end/end2end_test.cc \ END2END_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(END2END_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/end2end_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/end2end_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/end2end_test: $(PROTOBUF_DEP) $(END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/end2end_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/end2end/end2end_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_end2end_test: $(END2END_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(END2END_TEST_OBJS:.o=.dep) endif endif ERROR_DETAILS_TEST_SRC = \ $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc \ test/cpp/util/error_details_test.cc \ ERROR_DETAILS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ERROR_DETAILS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/error_details_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/error_details_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/error_details_test: $(PROTOBUF_DEP) $(ERROR_DETAILS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_error_details.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(ERROR_DETAILS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_error_details.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/error_details_test endif endif $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/echo_messages.o: $(LIBDIR)/$(CONFIG)/libgrpc++_error_details.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(OBJDIR)/$(CONFIG)/test/cpp/util/error_details_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_error_details.a $(LIBDIR)/$(CONFIG)/libgrpc++.a deps_error_details_test: $(ERROR_DETAILS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(ERROR_DETAILS_TEST_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/test/cpp/util/error_details_test.o: $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc FILTER_END2END_TEST_SRC = \ test/cpp/end2end/filter_end2end_test.cc \ FILTER_END2END_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FILTER_END2END_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/filter_end2end_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/filter_end2end_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/filter_end2end_test: $(PROTOBUF_DEP) $(FILTER_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(FILTER_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/filter_end2end_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/end2end/filter_end2end_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_filter_end2end_test: $(FILTER_END2END_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(FILTER_END2END_TEST_OBJS:.o=.dep) endif endif GENERIC_END2END_TEST_SRC = \ test/cpp/end2end/generic_end2end_test.cc \ GENERIC_END2END_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GENERIC_END2END_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/generic_end2end_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/generic_end2end_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/generic_end2end_test: $(PROTOBUF_DEP) $(GENERIC_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(GENERIC_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/generic_end2end_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/end2end/generic_end2end_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_generic_end2end_test: $(GENERIC_END2END_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GENERIC_END2END_TEST_OBJS:.o=.dep) endif endif GOLDEN_FILE_TEST_SRC = \ $(GENDIR)/src/proto/grpc/testing/compiler_test.pb.cc $(GENDIR)/src/proto/grpc/testing/compiler_test.grpc.pb.cc \ test/cpp/codegen/golden_file_test.cc \ GOLDEN_FILE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GOLDEN_FILE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/golden_file_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/golden_file_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/golden_file_test: $(PROTOBUF_DEP) $(GOLDEN_FILE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(GOLDEN_FILE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/golden_file_test endif endif $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/compiler_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/cpp/codegen/golden_file_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_golden_file_test: $(GOLDEN_FILE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GOLDEN_FILE_TEST_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/test/cpp/codegen/golden_file_test.o: $(GENDIR)/src/proto/grpc/testing/compiler_test.pb.cc $(GENDIR)/src/proto/grpc/testing/compiler_test.grpc.pb.cc GRPC_CLI_SRC = \ test/cpp/util/grpc_cli.cc \ GRPC_CLI_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_CLI_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/grpc_cli: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/grpc_cli: protobuf_dep_error else $(BINDIR)/$(CONFIG)/grpc_cli: $(PROTOBUF_DEP) $(GRPC_CLI_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(GRPC_CLI_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/grpc_cli endif endif $(OBJDIR)/$(CONFIG)/test/cpp/util/grpc_cli.o: $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a deps_grpc_cli: $(GRPC_CLI_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GRPC_CLI_OBJS:.o=.dep) endif endif GRPC_CPP_PLUGIN_SRC = \ src/compiler/cpp_plugin.cc \ GRPC_CPP_PLUGIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_CPP_PLUGIN_SRC)))) ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/grpc_cpp_plugin: protobuf_dep_error else $(BINDIR)/$(CONFIG)/grpc_cpp_plugin: $(PROTOBUF_DEP) $(GRPC_CPP_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(E) "[HOSTLD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(GRPC_CPP_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o $(BINDIR)/$(CONFIG)/grpc_cpp_plugin endif $(OBJDIR)/$(CONFIG)/src/compiler/cpp_plugin.o: $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a deps_grpc_cpp_plugin: $(GRPC_CPP_PLUGIN_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(GRPC_CPP_PLUGIN_OBJS:.o=.dep) endif GRPC_CSHARP_PLUGIN_SRC = \ src/compiler/csharp_plugin.cc \ GRPC_CSHARP_PLUGIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_CSHARP_PLUGIN_SRC)))) ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/grpc_csharp_plugin: protobuf_dep_error else $(BINDIR)/$(CONFIG)/grpc_csharp_plugin: $(PROTOBUF_DEP) $(GRPC_CSHARP_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(E) "[HOSTLD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(GRPC_CSHARP_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o $(BINDIR)/$(CONFIG)/grpc_csharp_plugin endif $(OBJDIR)/$(CONFIG)/src/compiler/csharp_plugin.o: $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a deps_grpc_csharp_plugin: $(GRPC_CSHARP_PLUGIN_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(GRPC_CSHARP_PLUGIN_OBJS:.o=.dep) endif GRPC_NODE_PLUGIN_SRC = \ src/compiler/node_plugin.cc \ GRPC_NODE_PLUGIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_NODE_PLUGIN_SRC)))) ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/grpc_node_plugin: protobuf_dep_error else $(BINDIR)/$(CONFIG)/grpc_node_plugin: $(PROTOBUF_DEP) $(GRPC_NODE_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(E) "[HOSTLD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(GRPC_NODE_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o $(BINDIR)/$(CONFIG)/grpc_node_plugin endif $(OBJDIR)/$(CONFIG)/src/compiler/node_plugin.o: $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a deps_grpc_node_plugin: $(GRPC_NODE_PLUGIN_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(GRPC_NODE_PLUGIN_OBJS:.o=.dep) endif GRPC_OBJECTIVE_C_PLUGIN_SRC = \ src/compiler/objective_c_plugin.cc \ GRPC_OBJECTIVE_C_PLUGIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_OBJECTIVE_C_PLUGIN_SRC)))) ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin: protobuf_dep_error else $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin: $(PROTOBUF_DEP) $(GRPC_OBJECTIVE_C_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(E) "[HOSTLD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(GRPC_OBJECTIVE_C_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin endif $(OBJDIR)/$(CONFIG)/src/compiler/objective_c_plugin.o: $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a deps_grpc_objective_c_plugin: $(GRPC_OBJECTIVE_C_PLUGIN_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(GRPC_OBJECTIVE_C_PLUGIN_OBJS:.o=.dep) endif GRPC_PHP_PLUGIN_SRC = \ src/compiler/php_plugin.cc \ GRPC_PHP_PLUGIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_PHP_PLUGIN_SRC)))) ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/grpc_php_plugin: protobuf_dep_error else $(BINDIR)/$(CONFIG)/grpc_php_plugin: $(PROTOBUF_DEP) $(GRPC_PHP_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(E) "[HOSTLD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(GRPC_PHP_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o $(BINDIR)/$(CONFIG)/grpc_php_plugin endif $(OBJDIR)/$(CONFIG)/src/compiler/php_plugin.o: $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a deps_grpc_php_plugin: $(GRPC_PHP_PLUGIN_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(GRPC_PHP_PLUGIN_OBJS:.o=.dep) endif GRPC_PYTHON_PLUGIN_SRC = \ src/compiler/python_plugin.cc \ GRPC_PYTHON_PLUGIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_PYTHON_PLUGIN_SRC)))) ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/grpc_python_plugin: protobuf_dep_error else $(BINDIR)/$(CONFIG)/grpc_python_plugin: $(PROTOBUF_DEP) $(GRPC_PYTHON_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(E) "[HOSTLD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(GRPC_PYTHON_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o $(BINDIR)/$(CONFIG)/grpc_python_plugin endif $(OBJDIR)/$(CONFIG)/src/compiler/python_plugin.o: $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a deps_grpc_python_plugin: $(GRPC_PYTHON_PLUGIN_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(GRPC_PYTHON_PLUGIN_OBJS:.o=.dep) endif GRPC_RUBY_PLUGIN_SRC = \ src/compiler/ruby_plugin.cc \ GRPC_RUBY_PLUGIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_RUBY_PLUGIN_SRC)))) ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/grpc_ruby_plugin: protobuf_dep_error else $(BINDIR)/$(CONFIG)/grpc_ruby_plugin: $(PROTOBUF_DEP) $(GRPC_RUBY_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(E) "[HOSTLD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(GRPC_RUBY_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o $(BINDIR)/$(CONFIG)/grpc_ruby_plugin endif $(OBJDIR)/$(CONFIG)/src/compiler/ruby_plugin.o: $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a deps_grpc_ruby_plugin: $(GRPC_RUBY_PLUGIN_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(GRPC_RUBY_PLUGIN_OBJS:.o=.dep) endif GRPC_TOOL_TEST_SRC = \ $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc \ test/cpp/util/grpc_tool_test.cc \ GRPC_TOOL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_TOOL_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/grpc_tool_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/grpc_tool_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/grpc_tool_test: $(PROTOBUF_DEP) $(GRPC_TOOL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(GRPC_TOOL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/grpc_tool_test endif endif $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/echo.o: $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/echo_messages.o: $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/cpp/util/grpc_tool_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_grpc_tool_test: $(GRPC_TOOL_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GRPC_TOOL_TEST_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/test/cpp/util/grpc_tool_test.o: $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc GRPCLB_API_TEST_SRC = \ $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc \ test/cpp/grpclb/grpclb_api_test.cc \ GRPCLB_API_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPCLB_API_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/grpclb_api_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/grpclb_api_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/grpclb_api_test: $(PROTOBUF_DEP) $(GRPCLB_API_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(GRPCLB_API_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/grpclb_api_test endif endif $(OBJDIR)/$(CONFIG)/src/proto/grpc/lb/v1/load_balancer.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_api_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a deps_grpclb_api_test: $(GRPCLB_API_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GRPCLB_API_TEST_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_api_test.o: $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc GRPCLB_TEST_SRC = \ $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc \ test/cpp/grpclb/grpclb_test.cc \ GRPCLB_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPCLB_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/grpclb_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/grpclb_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/grpclb_test: $(PROTOBUF_DEP) $(GRPCLB_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(GRPCLB_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/grpclb_test endif endif $(OBJDIR)/$(CONFIG)/src/proto/grpc/lb/v1/load_balancer.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_grpclb_test: $(GRPCLB_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(GRPCLB_TEST_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_test.o: $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc HEALTH_SERVICE_END2END_TEST_SRC = \ test/cpp/end2end/health_service_end2end_test.cc \ HEALTH_SERVICE_END2END_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HEALTH_SERVICE_END2END_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/health_service_end2end_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/health_service_end2end_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/health_service_end2end_test: $(PROTOBUF_DEP) $(HEALTH_SERVICE_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(HEALTH_SERVICE_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/health_service_end2end_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/end2end/health_service_end2end_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_health_service_end2end_test: $(HEALTH_SERVICE_END2END_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(HEALTH_SERVICE_END2END_TEST_OBJS:.o=.dep) endif endif ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/http2_client: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/http2_client: protobuf_dep_error else $(BINDIR)/$(CONFIG)/http2_client: $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/http2_client endif endif HYBRID_END2END_TEST_SRC = \ test/cpp/end2end/hybrid_end2end_test.cc \ HYBRID_END2END_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HYBRID_END2END_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/hybrid_end2end_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/hybrid_end2end_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/hybrid_end2end_test: $(PROTOBUF_DEP) $(HYBRID_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(HYBRID_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/hybrid_end2end_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/end2end/hybrid_end2end_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_hybrid_end2end_test: $(HYBRID_END2END_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(HYBRID_END2END_TEST_OBJS:.o=.dep) endif endif ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/interop_client: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/interop_client: protobuf_dep_error else $(BINDIR)/$(CONFIG)/interop_client: $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/interop_client endif endif ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/interop_server: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/interop_server: protobuf_dep_error else $(BINDIR)/$(CONFIG)/interop_server: $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/interop_server endif endif INTEROP_TEST_SRC = \ test/cpp/interop/interop_test.cc \ INTEROP_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(INTEROP_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/interop_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/interop_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/interop_test: $(PROTOBUF_DEP) $(INTEROP_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(INTEROP_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/interop_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/interop/interop_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a deps_interop_test: $(INTEROP_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(INTEROP_TEST_OBJS:.o=.dep) endif endif JSON_RUN_LOCALHOST_SRC = \ test/cpp/qps/json_run_localhost.cc \ JSON_RUN_LOCALHOST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_RUN_LOCALHOST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/json_run_localhost: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/json_run_localhost: protobuf_dep_error else $(BINDIR)/$(CONFIG)/json_run_localhost: $(PROTOBUF_DEP) $(JSON_RUN_LOCALHOST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(JSON_RUN_LOCALHOST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/json_run_localhost endif endif $(OBJDIR)/$(CONFIG)/test/cpp/qps/json_run_localhost.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a deps_json_run_localhost: $(JSON_RUN_LOCALHOST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(JSON_RUN_LOCALHOST_OBJS:.o=.dep) endif endif METRICS_CLIENT_SRC = \ $(GENDIR)/src/proto/grpc/testing/metrics.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.grpc.pb.cc \ test/cpp/interop/metrics_client.cc \ METRICS_CLIENT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(METRICS_CLIENT_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/metrics_client: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/metrics_client: protobuf_dep_error else $(BINDIR)/$(CONFIG)/metrics_client: $(PROTOBUF_DEP) $(METRICS_CLIENT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(METRICS_CLIENT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/metrics_client endif endif $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/metrics.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(OBJDIR)/$(CONFIG)/test/cpp/interop/metrics_client.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a deps_metrics_client: $(METRICS_CLIENT_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(METRICS_CLIENT_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/test/cpp/interop/metrics_client.o: $(GENDIR)/src/proto/grpc/testing/metrics.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.grpc.pb.cc MOCK_TEST_SRC = \ test/cpp/end2end/mock_test.cc \ MOCK_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MOCK_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/mock_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/mock_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/mock_test: $(PROTOBUF_DEP) $(MOCK_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(MOCK_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/mock_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/end2end/mock_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_mock_test: $(MOCK_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(MOCK_TEST_OBJS:.o=.dep) endif endif NOOP-BENCHMARK_SRC = \ test/cpp/microbenchmarks/noop-benchmark.cc \ NOOP-BENCHMARK_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(NOOP-BENCHMARK_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/noop-benchmark: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/noop-benchmark: protobuf_dep_error else $(BINDIR)/$(CONFIG)/noop-benchmark: $(PROTOBUF_DEP) $(NOOP-BENCHMARK_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(NOOP-BENCHMARK_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/noop-benchmark endif endif $(NOOP-BENCHMARK_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX $(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/noop-benchmark.o: $(LIBDIR)/$(CONFIG)/libbenchmark.a deps_noop-benchmark: $(NOOP-BENCHMARK_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(NOOP-BENCHMARK_OBJS:.o=.dep) endif endif PROTO_SERVER_REFLECTION_TEST_SRC = \ test/cpp/end2end/proto_server_reflection_test.cc \ PROTO_SERVER_REFLECTION_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PROTO_SERVER_REFLECTION_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/proto_server_reflection_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/proto_server_reflection_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/proto_server_reflection_test: $(PROTOBUF_DEP) $(PROTO_SERVER_REFLECTION_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(PROTO_SERVER_REFLECTION_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/proto_server_reflection_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/end2end/proto_server_reflection_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_proto_server_reflection_test: $(PROTO_SERVER_REFLECTION_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(PROTO_SERVER_REFLECTION_TEST_OBJS:.o=.dep) endif endif PROTO_UTILS_TEST_SRC = \ test/cpp/codegen/proto_utils_test.cc \ PROTO_UTILS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PROTO_UTILS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/proto_utils_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/proto_utils_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/proto_utils_test: $(PROTOBUF_DEP) $(PROTO_UTILS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(PROTO_UTILS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/proto_utils_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/codegen/proto_utils_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a deps_proto_utils_test: $(PROTO_UTILS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(PROTO_UTILS_TEST_OBJS:.o=.dep) endif endif QPS_INTERARRIVAL_TEST_SRC = \ test/cpp/qps/qps_interarrival_test.cc \ QPS_INTERARRIVAL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_INTERARRIVAL_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/qps_interarrival_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/qps_interarrival_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/qps_interarrival_test: $(PROTOBUF_DEP) $(QPS_INTERARRIVAL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(QPS_INTERARRIVAL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/qps_interarrival_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_interarrival_test.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_qps_interarrival_test: $(QPS_INTERARRIVAL_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(QPS_INTERARRIVAL_TEST_OBJS:.o=.dep) endif endif QPS_JSON_DRIVER_SRC = \ test/cpp/qps/qps_json_driver.cc \ QPS_JSON_DRIVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_JSON_DRIVER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/qps_json_driver: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/qps_json_driver: protobuf_dep_error else $(BINDIR)/$(CONFIG)/qps_json_driver: $(PROTOBUF_DEP) $(QPS_JSON_DRIVER_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(QPS_JSON_DRIVER_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/qps_json_driver endif endif $(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_json_driver.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a deps_qps_json_driver: $(QPS_JSON_DRIVER_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(QPS_JSON_DRIVER_OBJS:.o=.dep) endif endif QPS_OPENLOOP_TEST_SRC = \ test/cpp/qps/qps_openloop_test.cc \ QPS_OPENLOOP_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_OPENLOOP_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/qps_openloop_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/qps_openloop_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/qps_openloop_test: $(PROTOBUF_DEP) $(QPS_OPENLOOP_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(QPS_OPENLOOP_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/qps_openloop_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_openloop_test.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a deps_qps_openloop_test: $(QPS_OPENLOOP_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(QPS_OPENLOOP_TEST_OBJS:.o=.dep) endif endif QPS_WORKER_SRC = \ test/cpp/qps/worker.cc \ QPS_WORKER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_WORKER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/qps_worker: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/qps_worker: protobuf_dep_error else $(BINDIR)/$(CONFIG)/qps_worker: $(PROTOBUF_DEP) $(QPS_WORKER_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(QPS_WORKER_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/qps_worker endif endif $(OBJDIR)/$(CONFIG)/test/cpp/qps/worker.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a deps_qps_worker: $(QPS_WORKER_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(QPS_WORKER_OBJS:.o=.dep) endif endif RECONNECT_INTEROP_CLIENT_SRC = \ $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc \ test/cpp/interop/reconnect_interop_client.cc \ RECONNECT_INTEROP_CLIENT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RECONNECT_INTEROP_CLIENT_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/reconnect_interop_client: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/reconnect_interop_client: protobuf_dep_error else $(BINDIR)/$(CONFIG)/reconnect_interop_client: $(PROTOBUF_DEP) $(RECONNECT_INTEROP_CLIENT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(RECONNECT_INTEROP_CLIENT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/reconnect_interop_client endif endif $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/empty.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/messages.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(OBJDIR)/$(CONFIG)/test/cpp/interop/reconnect_interop_client.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a deps_reconnect_interop_client: $(RECONNECT_INTEROP_CLIENT_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(RECONNECT_INTEROP_CLIENT_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/test/cpp/interop/reconnect_interop_client.o: $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc RECONNECT_INTEROP_SERVER_SRC = \ $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc \ test/cpp/interop/reconnect_interop_server.cc \ RECONNECT_INTEROP_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RECONNECT_INTEROP_SERVER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/reconnect_interop_server: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/reconnect_interop_server: protobuf_dep_error else $(BINDIR)/$(CONFIG)/reconnect_interop_server: $(PROTOBUF_DEP) $(RECONNECT_INTEROP_SERVER_OBJS) $(LIBDIR)/$(CONFIG)/libreconnect_server.a $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(RECONNECT_INTEROP_SERVER_OBJS) $(LIBDIR)/$(CONFIG)/libreconnect_server.a $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/reconnect_interop_server endif endif $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/empty.o: $(LIBDIR)/$(CONFIG)/libreconnect_server.a $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/messages.o: $(LIBDIR)/$(CONFIG)/libreconnect_server.a $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/test.o: $(LIBDIR)/$(CONFIG)/libreconnect_server.a $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(OBJDIR)/$(CONFIG)/test/cpp/interop/reconnect_interop_server.o: $(LIBDIR)/$(CONFIG)/libreconnect_server.a $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a deps_reconnect_interop_server: $(RECONNECT_INTEROP_SERVER_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(RECONNECT_INTEROP_SERVER_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/test/cpp/interop/reconnect_interop_server.o: $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc ROUND_ROBIN_END2END_TEST_SRC = \ test/cpp/end2end/round_robin_end2end_test.cc \ ROUND_ROBIN_END2END_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ROUND_ROBIN_END2END_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/round_robin_end2end_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/round_robin_end2end_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/round_robin_end2end_test: $(PROTOBUF_DEP) $(ROUND_ROBIN_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(ROUND_ROBIN_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/round_robin_end2end_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/end2end/round_robin_end2end_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_round_robin_end2end_test: $(ROUND_ROBIN_END2END_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(ROUND_ROBIN_END2END_TEST_OBJS:.o=.dep) endif endif SECURE_AUTH_CONTEXT_TEST_SRC = \ test/cpp/common/secure_auth_context_test.cc \ SECURE_AUTH_CONTEXT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SECURE_AUTH_CONTEXT_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/secure_auth_context_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/secure_auth_context_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/secure_auth_context_test: $(PROTOBUF_DEP) $(SECURE_AUTH_CONTEXT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(SECURE_AUTH_CONTEXT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/secure_auth_context_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/common/secure_auth_context_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_secure_auth_context_test: $(SECURE_AUTH_CONTEXT_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SECURE_AUTH_CONTEXT_TEST_OBJS:.o=.dep) endif endif SECURE_SYNC_UNARY_PING_PONG_TEST_SRC = \ test/cpp/qps/secure_sync_unary_ping_pong_test.cc \ SECURE_SYNC_UNARY_PING_PONG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SECURE_SYNC_UNARY_PING_PONG_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test: $(PROTOBUF_DEP) $(SECURE_SYNC_UNARY_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(SECURE_SYNC_UNARY_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/qps/secure_sync_unary_ping_pong_test.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_secure_sync_unary_ping_pong_test: $(SECURE_SYNC_UNARY_PING_PONG_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SECURE_SYNC_UNARY_PING_PONG_TEST_OBJS:.o=.dep) endif endif SERVER_BUILDER_PLUGIN_TEST_SRC = \ test/cpp/end2end/server_builder_plugin_test.cc \ SERVER_BUILDER_PLUGIN_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_BUILDER_PLUGIN_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/server_builder_plugin_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/server_builder_plugin_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/server_builder_plugin_test: $(PROTOBUF_DEP) $(SERVER_BUILDER_PLUGIN_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(SERVER_BUILDER_PLUGIN_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/server_builder_plugin_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/end2end/server_builder_plugin_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_server_builder_plugin_test: $(SERVER_BUILDER_PLUGIN_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SERVER_BUILDER_PLUGIN_TEST_OBJS:.o=.dep) endif endif SERVER_BUILDER_TEST_SRC = \ $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc \ test/cpp/server/server_builder_test.cc \ SERVER_BUILDER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_BUILDER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/server_builder_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/server_builder_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/server_builder_test: $(PROTOBUF_DEP) $(SERVER_BUILDER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(SERVER_BUILDER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/server_builder_test endif endif $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/echo_messages.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/echo.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/cpp/server/server_builder_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_server_builder_test: $(SERVER_BUILDER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SERVER_BUILDER_TEST_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/test/cpp/server/server_builder_test.o: $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc SERVER_CONTEXT_TEST_SPOUSE_TEST_SRC = \ test/cpp/test/server_context_test_spouse_test.cc \ SERVER_CONTEXT_TEST_SPOUSE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_CONTEXT_TEST_SPOUSE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/server_context_test_spouse_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/server_context_test_spouse_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/server_context_test_spouse_test: $(PROTOBUF_DEP) $(SERVER_CONTEXT_TEST_SPOUSE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(SERVER_CONTEXT_TEST_SPOUSE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/server_context_test_spouse_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/test/server_context_test_spouse_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_server_context_test_spouse_test: $(SERVER_CONTEXT_TEST_SPOUSE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SERVER_CONTEXT_TEST_SPOUSE_TEST_OBJS:.o=.dep) endif endif SERVER_CRASH_TEST_SRC = \ test/cpp/end2end/server_crash_test.cc \ SERVER_CRASH_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_CRASH_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/server_crash_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/server_crash_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/server_crash_test: $(PROTOBUF_DEP) $(SERVER_CRASH_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(SERVER_CRASH_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/server_crash_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/end2end/server_crash_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_server_crash_test: $(SERVER_CRASH_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SERVER_CRASH_TEST_OBJS:.o=.dep) endif endif SERVER_CRASH_TEST_CLIENT_SRC = \ test/cpp/end2end/server_crash_test_client.cc \ SERVER_CRASH_TEST_CLIENT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_CRASH_TEST_CLIENT_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/server_crash_test_client: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/server_crash_test_client: protobuf_dep_error else $(BINDIR)/$(CONFIG)/server_crash_test_client: $(PROTOBUF_DEP) $(SERVER_CRASH_TEST_CLIENT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(SERVER_CRASH_TEST_CLIENT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/server_crash_test_client endif endif $(OBJDIR)/$(CONFIG)/test/cpp/end2end/server_crash_test_client.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_server_crash_test_client: $(SERVER_CRASH_TEST_CLIENT_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SERVER_CRASH_TEST_CLIENT_OBJS:.o=.dep) endif endif SHUTDOWN_TEST_SRC = \ test/cpp/end2end/shutdown_test.cc \ SHUTDOWN_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SHUTDOWN_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/shutdown_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/shutdown_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/shutdown_test: $(PROTOBUF_DEP) $(SHUTDOWN_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(SHUTDOWN_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/shutdown_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/end2end/shutdown_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_shutdown_test: $(SHUTDOWN_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SHUTDOWN_TEST_OBJS:.o=.dep) endif endif STATUS_TEST_SRC = \ test/cpp/util/status_test.cc \ STATUS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(STATUS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/status_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/status_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/status_test: $(PROTOBUF_DEP) $(STATUS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(STATUS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/status_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/util/status_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_status_test: $(STATUS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(STATUS_TEST_OBJS:.o=.dep) endif endif STREAMING_THROUGHPUT_TEST_SRC = \ test/cpp/end2end/streaming_throughput_test.cc \ STREAMING_THROUGHPUT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(STREAMING_THROUGHPUT_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/streaming_throughput_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/streaming_throughput_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/streaming_throughput_test: $(PROTOBUF_DEP) $(STREAMING_THROUGHPUT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(STREAMING_THROUGHPUT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/streaming_throughput_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/end2end/streaming_throughput_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_streaming_throughput_test: $(STREAMING_THROUGHPUT_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(STREAMING_THROUGHPUT_TEST_OBJS:.o=.dep) endif endif STRESS_TEST_SRC = \ $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/metrics.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.grpc.pb.cc \ $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc \ test/cpp/interop/interop_client.cc \ test/cpp/interop/stress_interop_client.cc \ test/cpp/interop/stress_test.cc \ test/cpp/util/metrics_server.cc \ STRESS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(STRESS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/stress_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/stress_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/stress_test: $(PROTOBUF_DEP) $(STRESS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(STRESS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/stress_test endif endif $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/empty.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/messages.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/metrics.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(OBJDIR)/$(CONFIG)/test/cpp/interop/interop_client.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(OBJDIR)/$(CONFIG)/test/cpp/interop/stress_interop_client.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(OBJDIR)/$(CONFIG)/test/cpp/interop/stress_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(OBJDIR)/$(CONFIG)/test/cpp/util/metrics_server.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a deps_stress_test: $(STRESS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(STRESS_TEST_OBJS:.o=.dep) endif endif $(OBJDIR)/$(CONFIG)/test/cpp/interop/interop_client.o: $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/interop/stress_interop_client.o: $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/interop/stress_test.o: $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/util/metrics_server.o: $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc THREAD_MANAGER_TEST_SRC = \ test/cpp/thread_manager/thread_manager_test.cc \ THREAD_MANAGER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(THREAD_MANAGER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/thread_manager_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/thread_manager_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/thread_manager_test: $(PROTOBUF_DEP) $(THREAD_MANAGER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(THREAD_MANAGER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/thread_manager_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/thread_manager/thread_manager_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a deps_thread_manager_test: $(THREAD_MANAGER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(THREAD_MANAGER_TEST_OBJS:.o=.dep) endif endif THREAD_STRESS_TEST_SRC = \ test/cpp/end2end/thread_stress_test.cc \ THREAD_STRESS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(THREAD_STRESS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/thread_stress_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/thread_stress_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/thread_stress_test: $(PROTOBUF_DEP) $(THREAD_STRESS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(THREAD_STRESS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/thread_stress_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/end2end/thread_stress_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_thread_stress_test: $(THREAD_STRESS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(THREAD_STRESS_TEST_OBJS:.o=.dep) endif endif WRITES_PER_RPC_TEST_SRC = \ test/cpp/performance/writes_per_rpc_test.cc \ WRITES_PER_RPC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(WRITES_PER_RPC_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/writes_per_rpc_test: openssl_dep_error else ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/writes_per_rpc_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/writes_per_rpc_test: $(PROTOBUF_DEP) $(WRITES_PER_RPC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(WRITES_PER_RPC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/writes_per_rpc_test endif endif $(OBJDIR)/$(CONFIG)/test/cpp/performance/writes_per_rpc_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_writes_per_rpc_test: $(WRITES_PER_RPC_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(WRITES_PER_RPC_TEST_OBJS:.o=.dep) endif endif PUBLIC_HEADERS_MUST_BE_C89_SRC = \ test/core/surface/public_headers_must_be_c89.c \ PUBLIC_HEADERS_MUST_BE_C89_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PUBLIC_HEADERS_MUST_BE_C89_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/public_headers_must_be_c89: openssl_dep_error else $(BINDIR)/$(CONFIG)/public_headers_must_be_c89: $(PUBLIC_HEADERS_MUST_BE_C89_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(PUBLIC_HEADERS_MUST_BE_C89_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/public_headers_must_be_c89 endif $(OBJDIR)/$(CONFIG)/test/core/surface/public_headers_must_be_c89.o: $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/surface/public_headers_must_be_c89.o : test/core/surface/public_headers_must_be_c89.c $(E) "[C] Compiling $<" $(Q) mkdir -p `dirname $@` $(Q) $(CC) $(CPPFLAGS) $(CFLAGS) -std=c89 -pedantic -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $< deps_public_headers_must_be_c89: $(PUBLIC_HEADERS_MUST_BE_C89_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(PUBLIC_HEADERS_MUST_BE_C89_OBJS:.o=.dep) endif endif # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_AES_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_AES_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_AES_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_aes_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_aes_test: $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_aes_test endif $(BORINGSSL_AES_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_AES_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_ASN1_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_ASN1_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_ASN1_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_asn1_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_asn1_test: $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_asn1_test endif $(BORINGSSL_ASN1_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_ASN1_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_BASE64_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_BASE64_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_BASE64_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_base64_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_base64_test: $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_base64_test endif $(BORINGSSL_BASE64_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_BASE64_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_BIO_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_BIO_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_BIO_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_bio_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_bio_test: $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_bio_test endif $(BORINGSSL_BIO_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_BIO_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_BN_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_BN_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_BN_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_bn_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_bn_test: $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_bn_test endif $(BORINGSSL_BN_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_BN_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_BYTESTRING_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_BYTESTRING_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_BYTESTRING_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_bytestring_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_bytestring_test: $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_bytestring_test endif $(BORINGSSL_BYTESTRING_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_BYTESTRING_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_CHACHA_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_CHACHA_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_CHACHA_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_chacha_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_chacha_test: $(LIBDIR)/$(CONFIG)/libboringssl_chacha_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_chacha_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_chacha_test endif $(BORINGSSL_CHACHA_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_CHACHA_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_AEAD_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_AEAD_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_AEAD_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_aead_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_aead_test: $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_aead_test endif $(BORINGSSL_AEAD_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_AEAD_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_CIPHER_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_CIPHER_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_CIPHER_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_cipher_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_cipher_test: $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_cipher_test endif $(BORINGSSL_CIPHER_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_CIPHER_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_CMAC_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_CMAC_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_CMAC_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_cmac_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_cmac_test: $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_cmac_test endif $(BORINGSSL_CMAC_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_CMAC_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_CONSTANT_TIME_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_CONSTANT_TIME_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_CONSTANT_TIME_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_constant_time_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_constant_time_test: $(LIBDIR)/$(CONFIG)/libboringssl_constant_time_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_constant_time_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_constant_time_test endif $(BORINGSSL_CONSTANT_TIME_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_CONSTANT_TIME_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_ED25519_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_ED25519_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_ED25519_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_ed25519_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_ed25519_test: $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_ed25519_test endif $(BORINGSSL_ED25519_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_ED25519_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_SPAKE25519_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_SPAKE25519_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_SPAKE25519_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_spake25519_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_spake25519_test: $(LIBDIR)/$(CONFIG)/libboringssl_spake25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_spake25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_spake25519_test endif $(BORINGSSL_SPAKE25519_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_SPAKE25519_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_X25519_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_X25519_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_X25519_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_x25519_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_x25519_test: $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_x25519_test endif $(BORINGSSL_X25519_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_X25519_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_DH_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_DH_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_DH_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_dh_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_dh_test: $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_dh_test endif $(BORINGSSL_DH_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_DH_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_DIGEST_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_DIGEST_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_DIGEST_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_digest_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_digest_test: $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_digest_test endif $(BORINGSSL_DIGEST_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_DIGEST_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_DSA_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_DSA_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_DSA_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_dsa_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_dsa_test: $(LIBDIR)/$(CONFIG)/libboringssl_dsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_dsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_dsa_test endif $(BORINGSSL_DSA_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_DSA_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_EC_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_EC_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_EC_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_ec_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_ec_test: $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_ec_test endif $(BORINGSSL_EC_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_EC_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_EXAMPLE_MUL_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_EXAMPLE_MUL_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_EXAMPLE_MUL_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_example_mul: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_example_mul: $(LIBDIR)/$(CONFIG)/libboringssl_example_mul_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_example_mul_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_example_mul endif $(BORINGSSL_EXAMPLE_MUL_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_EXAMPLE_MUL_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_ECDH_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_ECDH_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_ECDH_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_ecdh_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_ecdh_test: $(LIBDIR)/$(CONFIG)/libboringssl_ecdh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_ecdh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_ecdh_test endif $(BORINGSSL_ECDH_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_ECDH_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_ECDSA_SIGN_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_ECDSA_SIGN_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_ECDSA_SIGN_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_ecdsa_sign_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_ecdsa_sign_test: $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_sign_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_sign_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_ecdsa_sign_test endif $(BORINGSSL_ECDSA_SIGN_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_ECDSA_SIGN_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_ECDSA_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_ECDSA_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_ECDSA_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_ecdsa_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_ecdsa_test: $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_ecdsa_test endif $(BORINGSSL_ECDSA_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_ECDSA_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_ECDSA_VERIFY_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_ECDSA_VERIFY_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_ECDSA_VERIFY_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_ecdsa_verify_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_ecdsa_verify_test: $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_verify_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_verify_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_ecdsa_verify_test endif $(BORINGSSL_ECDSA_VERIFY_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_ECDSA_VERIFY_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_ERR_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_ERR_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_ERR_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_err_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_err_test: $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_err_test endif $(BORINGSSL_ERR_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_ERR_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_EVP_EXTRA_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_EVP_EXTRA_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_EVP_EXTRA_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_evp_extra_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_evp_extra_test: $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_evp_extra_test endif $(BORINGSSL_EVP_EXTRA_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_EVP_EXTRA_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_EVP_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_EVP_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_EVP_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_evp_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_evp_test: $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_evp_test endif $(BORINGSSL_EVP_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_EVP_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_PBKDF_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_PBKDF_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_PBKDF_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_pbkdf_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_pbkdf_test: $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_pbkdf_test endif $(BORINGSSL_PBKDF_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_PBKDF_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_HKDF_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_HKDF_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_HKDF_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_hkdf_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_hkdf_test: $(LIBDIR)/$(CONFIG)/libboringssl_hkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_hkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_hkdf_test endif $(BORINGSSL_HKDF_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_HKDF_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_HMAC_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_HMAC_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_HMAC_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_hmac_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_hmac_test: $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_hmac_test endif $(BORINGSSL_HMAC_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_HMAC_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_LHASH_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_LHASH_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_LHASH_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_lhash_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_lhash_test: $(LIBDIR)/$(CONFIG)/libboringssl_lhash_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_lhash_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_lhash_test endif $(BORINGSSL_LHASH_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_LHASH_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_GCM_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_GCM_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_GCM_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_gcm_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_gcm_test: $(LIBDIR)/$(CONFIG)/libboringssl_gcm_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_gcm_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_gcm_test endif $(BORINGSSL_GCM_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_GCM_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_NEWHOPE_STATISTICAL_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_NEWHOPE_STATISTICAL_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_NEWHOPE_STATISTICAL_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_newhope_statistical_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_newhope_statistical_test: $(LIBDIR)/$(CONFIG)/libboringssl_newhope_statistical_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_newhope_statistical_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_newhope_statistical_test endif $(BORINGSSL_NEWHOPE_STATISTICAL_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_NEWHOPE_STATISTICAL_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_NEWHOPE_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_NEWHOPE_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_NEWHOPE_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_newhope_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_newhope_test: $(LIBDIR)/$(CONFIG)/libboringssl_newhope_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_newhope_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_newhope_test endif $(BORINGSSL_NEWHOPE_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_NEWHOPE_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_NEWHOPE_VECTORS_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_NEWHOPE_VECTORS_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_NEWHOPE_VECTORS_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_newhope_vectors_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_newhope_vectors_test: $(LIBDIR)/$(CONFIG)/libboringssl_newhope_vectors_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_newhope_vectors_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_newhope_vectors_test endif $(BORINGSSL_NEWHOPE_VECTORS_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_NEWHOPE_VECTORS_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_OBJ_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_OBJ_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_OBJ_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_obj_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_obj_test: $(LIBDIR)/$(CONFIG)/libboringssl_obj_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_obj_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_obj_test endif $(BORINGSSL_OBJ_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_OBJ_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_PKCS12_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_PKCS12_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_PKCS12_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_pkcs12_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_pkcs12_test: $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_pkcs12_test endif $(BORINGSSL_PKCS12_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_PKCS12_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_PKCS8_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_PKCS8_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_PKCS8_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_pkcs8_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_pkcs8_test: $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_pkcs8_test endif $(BORINGSSL_PKCS8_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_PKCS8_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_POLY1305_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_POLY1305_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_POLY1305_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_poly1305_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_poly1305_test: $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_poly1305_test endif $(BORINGSSL_POLY1305_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_POLY1305_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_REFCOUNT_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_REFCOUNT_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_REFCOUNT_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_refcount_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_refcount_test: $(LIBDIR)/$(CONFIG)/libboringssl_refcount_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_refcount_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_refcount_test endif $(BORINGSSL_REFCOUNT_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_REFCOUNT_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_RSA_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_RSA_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_RSA_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_rsa_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_rsa_test: $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_rsa_test endif $(BORINGSSL_RSA_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_RSA_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_THREAD_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_THREAD_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_THREAD_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_thread_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_thread_test: $(LIBDIR)/$(CONFIG)/libboringssl_thread_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_thread_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_thread_test endif $(BORINGSSL_THREAD_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_THREAD_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_PKCS7_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_PKCS7_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_PKCS7_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_pkcs7_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_pkcs7_test: $(LIBDIR)/$(CONFIG)/libboringssl_pkcs7_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_pkcs7_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_pkcs7_test endif $(BORINGSSL_PKCS7_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_PKCS7_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_X509_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_X509_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_X509_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_x509_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_x509_test: $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_x509_test endif $(BORINGSSL_X509_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_X509_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_TAB_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_TAB_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_TAB_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_tab_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_tab_test: $(LIBDIR)/$(CONFIG)/libboringssl_tab_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_tab_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_tab_test endif $(BORINGSSL_TAB_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_TAB_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_V3NAME_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_V3NAME_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_V3NAME_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_v3name_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_v3name_test: $(LIBDIR)/$(CONFIG)/libboringssl_v3name_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_v3name_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_v3name_test endif $(BORINGSSL_V3NAME_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_V3NAME_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) # boringssl needs an override to ensure that it does not include # system openssl headers regardless of other configuration # we do so here with a target specific variable assignment $(BORINGSSL_SSL_TEST_OBJS): CFLAGS := -Ithird_party/boringssl/include $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value $(NO_W_EXTRA_SEMI) $(BORINGSSL_SSL_TEST_OBJS): CXXFLAGS := -Ithird_party/boringssl/include $(CXXFLAGS) $(BORINGSSL_SSL_TEST_OBJS): CPPFLAGS += -DOPENSSL_NO_ASM -D_GNU_SOURCE ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. $(BINDIR)/$(CONFIG)/boringssl_ssl_test: protobuf_dep_error else $(BINDIR)/$(CONFIG)/boringssl_ssl_test: $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/boringssl_ssl_test endif $(BORINGSSL_SSL_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(BORINGSSL_SSL_TEST_OBJS): CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) BADREQ_BAD_CLIENT_TEST_SRC = \ test/core/bad_client/tests/badreq.c \ BADREQ_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BADREQ_BAD_CLIENT_TEST_SRC)))) $(BINDIR)/$(CONFIG)/badreq_bad_client_test: $(BADREQ_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(BADREQ_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/badreq_bad_client_test $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/badreq.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_badreq_bad_client_test: $(BADREQ_BAD_CLIENT_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(BADREQ_BAD_CLIENT_TEST_OBJS:.o=.dep) endif CONNECTION_PREFIX_BAD_CLIENT_TEST_SRC = \ test/core/bad_client/tests/connection_prefix.c \ CONNECTION_PREFIX_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CONNECTION_PREFIX_BAD_CLIENT_TEST_SRC)))) $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test: $(CONNECTION_PREFIX_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(CONNECTION_PREFIX_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/connection_prefix.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_connection_prefix_bad_client_test: $(CONNECTION_PREFIX_BAD_CLIENT_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(CONNECTION_PREFIX_BAD_CLIENT_TEST_OBJS:.o=.dep) endif HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_SRC = \ test/core/bad_client/tests/head_of_line_blocking.c \ HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_SRC)))) $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test: $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/head_of_line_blocking.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_head_of_line_blocking_bad_client_test: $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS:.o=.dep) endif HEADERS_BAD_CLIENT_TEST_SRC = \ test/core/bad_client/tests/headers.c \ HEADERS_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HEADERS_BAD_CLIENT_TEST_SRC)))) $(BINDIR)/$(CONFIG)/headers_bad_client_test: $(HEADERS_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(HEADERS_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/headers_bad_client_test $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/headers.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_headers_bad_client_test: $(HEADERS_BAD_CLIENT_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(HEADERS_BAD_CLIENT_TEST_OBJS:.o=.dep) endif INITIAL_SETTINGS_FRAME_BAD_CLIENT_TEST_SRC = \ test/core/bad_client/tests/initial_settings_frame.c \ INITIAL_SETTINGS_FRAME_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(INITIAL_SETTINGS_FRAME_BAD_CLIENT_TEST_SRC)))) $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test: $(INITIAL_SETTINGS_FRAME_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(INITIAL_SETTINGS_FRAME_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/initial_settings_frame.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_initial_settings_frame_bad_client_test: $(INITIAL_SETTINGS_FRAME_BAD_CLIENT_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(INITIAL_SETTINGS_FRAME_BAD_CLIENT_TEST_OBJS:.o=.dep) endif LARGE_METADATA_BAD_CLIENT_TEST_SRC = \ test/core/bad_client/tests/large_metadata.c \ LARGE_METADATA_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LARGE_METADATA_BAD_CLIENT_TEST_SRC)))) $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test: $(LARGE_METADATA_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(LARGE_METADATA_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/large_metadata.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_large_metadata_bad_client_test: $(LARGE_METADATA_BAD_CLIENT_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(LARGE_METADATA_BAD_CLIENT_TEST_OBJS:.o=.dep) endif SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_SRC = \ test/core/bad_client/tests/server_registered_method.c \ SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_SRC)))) $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test: $(SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/server_registered_method.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_server_registered_method_bad_client_test: $(SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_OBJS:.o=.dep) endif SIMPLE_REQUEST_BAD_CLIENT_TEST_SRC = \ test/core/bad_client/tests/simple_request.c \ SIMPLE_REQUEST_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SIMPLE_REQUEST_BAD_CLIENT_TEST_SRC)))) $(BINDIR)/$(CONFIG)/simple_request_bad_client_test: $(SIMPLE_REQUEST_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(SIMPLE_REQUEST_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/simple_request_bad_client_test $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/simple_request.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_simple_request_bad_client_test: $(SIMPLE_REQUEST_BAD_CLIENT_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(SIMPLE_REQUEST_BAD_CLIENT_TEST_OBJS:.o=.dep) endif UNKNOWN_FRAME_BAD_CLIENT_TEST_SRC = \ test/core/bad_client/tests/unknown_frame.c \ UNKNOWN_FRAME_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(UNKNOWN_FRAME_BAD_CLIENT_TEST_SRC)))) $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test: $(UNKNOWN_FRAME_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(UNKNOWN_FRAME_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/unknown_frame.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_unknown_frame_bad_client_test: $(UNKNOWN_FRAME_BAD_CLIENT_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(UNKNOWN_FRAME_BAD_CLIENT_TEST_OBJS:.o=.dep) endif WINDOW_OVERFLOW_BAD_CLIENT_TEST_SRC = \ test/core/bad_client/tests/window_overflow.c \ WINDOW_OVERFLOW_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(WINDOW_OVERFLOW_BAD_CLIENT_TEST_SRC)))) $(BINDIR)/$(CONFIG)/window_overflow_bad_client_test: $(WINDOW_OVERFLOW_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(WINDOW_OVERFLOW_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/window_overflow_bad_client_test $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/window_overflow.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_window_overflow_bad_client_test: $(WINDOW_OVERFLOW_BAD_CLIENT_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(WINDOW_OVERFLOW_BAD_CLIENT_TEST_OBJS:.o=.dep) endif BAD_SSL_CERT_SERVER_SRC = \ test/core/bad_ssl/servers/cert.c \ BAD_SSL_CERT_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BAD_SSL_CERT_SERVER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/bad_ssl_cert_server: openssl_dep_error else $(BINDIR)/$(CONFIG)/bad_ssl_cert_server: $(BAD_SSL_CERT_SERVER_OBJS) $(LIBDIR)/$(CONFIG)/libbad_ssl_test_server.a $(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) $(BAD_SSL_CERT_SERVER_OBJS) $(LIBDIR)/$(CONFIG)/libbad_ssl_test_server.a $(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)/bad_ssl_cert_server endif $(OBJDIR)/$(CONFIG)/test/core/bad_ssl/servers/cert.o: $(LIBDIR)/$(CONFIG)/libbad_ssl_test_server.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_bad_ssl_cert_server: $(BAD_SSL_CERT_SERVER_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(BAD_SSL_CERT_SERVER_OBJS:.o=.dep) endif endif BAD_SSL_CERT_TEST_SRC = \ test/core/bad_ssl/bad_ssl_test.c \ BAD_SSL_CERT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BAD_SSL_CERT_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/bad_ssl_cert_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/bad_ssl_cert_test: $(BAD_SSL_CERT_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) $(BAD_SSL_CERT_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)/bad_ssl_cert_test endif $(OBJDIR)/$(CONFIG)/test/core/bad_ssl/bad_ssl_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_bad_ssl_cert_test: $(BAD_SSL_CERT_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(BAD_SSL_CERT_TEST_OBJS:.o=.dep) endif endif H2_CENSUS_TEST_SRC = \ test/core/end2end/fixtures/h2_census.c \ H2_CENSUS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_CENSUS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/h2_census_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/h2_census_test: $(H2_CENSUS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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) $(H2_CENSUS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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)/h2_census_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_census.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_census_test: $(H2_CENSUS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(H2_CENSUS_TEST_OBJS:.o=.dep) endif endif H2_COMPRESS_TEST_SRC = \ test/core/end2end/fixtures/h2_compress.c \ H2_COMPRESS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_COMPRESS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/h2_compress_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/h2_compress_test: $(H2_COMPRESS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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) $(H2_COMPRESS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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)/h2_compress_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_compress.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_compress_test: $(H2_COMPRESS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(H2_COMPRESS_TEST_OBJS:.o=.dep) endif endif H2_FAKESEC_TEST_SRC = \ test/core/end2end/fixtures/h2_fakesec.c \ H2_FAKESEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FAKESEC_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/h2_fakesec_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/h2_fakesec_test: $(H2_FAKESEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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) $(H2_FAKESEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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)/h2_fakesec_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_fakesec.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_fakesec_test: $(H2_FAKESEC_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(H2_FAKESEC_TEST_OBJS:.o=.dep) endif endif H2_FD_TEST_SRC = \ test/core/end2end/fixtures/h2_fd.c \ H2_FD_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FD_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/h2_fd_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/h2_fd_test: $(H2_FD_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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) $(H2_FD_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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)/h2_fd_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_fd.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_fd_test: $(H2_FD_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(H2_FD_TEST_OBJS:.o=.dep) endif endif H2_FULL_TEST_SRC = \ test/core/end2end/fixtures/h2_full.c \ H2_FULL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FULL_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/h2_full_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/h2_full_test: $(H2_FULL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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) $(H2_FULL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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)/h2_full_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_full.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_full_test: $(H2_FULL_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(H2_FULL_TEST_OBJS:.o=.dep) endif endif H2_FULL+PIPE_TEST_SRC = \ test/core/end2end/fixtures/h2_full+pipe.c \ H2_FULL+PIPE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FULL+PIPE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/h2_full+pipe_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/h2_full+pipe_test: $(H2_FULL+PIPE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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) $(H2_FULL+PIPE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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)/h2_full+pipe_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_full+pipe.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_full+pipe_test: $(H2_FULL+PIPE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(H2_FULL+PIPE_TEST_OBJS:.o=.dep) endif endif H2_FULL+TRACE_TEST_SRC = \ test/core/end2end/fixtures/h2_full+trace.c \ H2_FULL+TRACE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FULL+TRACE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/h2_full+trace_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/h2_full+trace_test: $(H2_FULL+TRACE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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) $(H2_FULL+TRACE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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)/h2_full+trace_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_full+trace.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_full+trace_test: $(H2_FULL+TRACE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(H2_FULL+TRACE_TEST_OBJS:.o=.dep) endif endif H2_HTTP_PROXY_TEST_SRC = \ test/core/end2end/fixtures/h2_http_proxy.c \ H2_HTTP_PROXY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_HTTP_PROXY_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/h2_http_proxy_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/h2_http_proxy_test: $(H2_HTTP_PROXY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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) $(H2_HTTP_PROXY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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)/h2_http_proxy_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_http_proxy.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_http_proxy_test: $(H2_HTTP_PROXY_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(H2_HTTP_PROXY_TEST_OBJS:.o=.dep) endif endif H2_LOAD_REPORTING_TEST_SRC = \ test/core/end2end/fixtures/h2_load_reporting.c \ H2_LOAD_REPORTING_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_LOAD_REPORTING_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/h2_load_reporting_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/h2_load_reporting_test: $(H2_LOAD_REPORTING_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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) $(H2_LOAD_REPORTING_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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)/h2_load_reporting_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_load_reporting.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_load_reporting_test: $(H2_LOAD_REPORTING_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(H2_LOAD_REPORTING_TEST_OBJS:.o=.dep) endif endif H2_OAUTH2_TEST_SRC = \ test/core/end2end/fixtures/h2_oauth2.c \ H2_OAUTH2_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_OAUTH2_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/h2_oauth2_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/h2_oauth2_test: $(H2_OAUTH2_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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) $(H2_OAUTH2_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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)/h2_oauth2_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_oauth2.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_oauth2_test: $(H2_OAUTH2_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(H2_OAUTH2_TEST_OBJS:.o=.dep) endif endif H2_PROXY_TEST_SRC = \ test/core/end2end/fixtures/h2_proxy.c \ H2_PROXY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_PROXY_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/h2_proxy_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/h2_proxy_test: $(H2_PROXY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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) $(H2_PROXY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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)/h2_proxy_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_proxy.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_proxy_test: $(H2_PROXY_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(H2_PROXY_TEST_OBJS:.o=.dep) endif endif H2_SOCKPAIR_TEST_SRC = \ test/core/end2end/fixtures/h2_sockpair.c \ H2_SOCKPAIR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SOCKPAIR_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/h2_sockpair_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/h2_sockpair_test: $(H2_SOCKPAIR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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) $(H2_SOCKPAIR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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)/h2_sockpair_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_sockpair.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_sockpair_test: $(H2_SOCKPAIR_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(H2_SOCKPAIR_TEST_OBJS:.o=.dep) endif endif H2_SOCKPAIR+TRACE_TEST_SRC = \ test/core/end2end/fixtures/h2_sockpair+trace.c \ H2_SOCKPAIR+TRACE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SOCKPAIR+TRACE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/h2_sockpair+trace_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/h2_sockpair+trace_test: $(H2_SOCKPAIR+TRACE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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) $(H2_SOCKPAIR+TRACE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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)/h2_sockpair+trace_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_sockpair+trace.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_sockpair+trace_test: $(H2_SOCKPAIR+TRACE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(H2_SOCKPAIR+TRACE_TEST_OBJS:.o=.dep) endif endif H2_SOCKPAIR_1BYTE_TEST_SRC = \ test/core/end2end/fixtures/h2_sockpair_1byte.c \ H2_SOCKPAIR_1BYTE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SOCKPAIR_1BYTE_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_test: $(H2_SOCKPAIR_1BYTE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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) $(H2_SOCKPAIR_1BYTE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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)/h2_sockpair_1byte_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_sockpair_1byte.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_sockpair_1byte_test: $(H2_SOCKPAIR_1BYTE_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(H2_SOCKPAIR_1BYTE_TEST_OBJS:.o=.dep) endif endif H2_SSL_TEST_SRC = \ test/core/end2end/fixtures/h2_ssl.c \ H2_SSL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SSL_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/h2_ssl_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/h2_ssl_test: $(H2_SSL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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) $(H2_SSL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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)/h2_ssl_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_ssl.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_ssl_test: $(H2_SSL_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(H2_SSL_TEST_OBJS:.o=.dep) endif endif H2_SSL_CERT_TEST_SRC = \ test/core/end2end/fixtures/h2_ssl_cert.c \ H2_SSL_CERT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SSL_CERT_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/h2_ssl_cert_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/h2_ssl_cert_test: $(H2_SSL_CERT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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) $(H2_SSL_CERT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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)/h2_ssl_cert_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_ssl_cert.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_ssl_cert_test: $(H2_SSL_CERT_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(H2_SSL_CERT_TEST_OBJS:.o=.dep) endif endif H2_SSL_PROXY_TEST_SRC = \ test/core/end2end/fixtures/h2_ssl_proxy.c \ H2_SSL_PROXY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SSL_PROXY_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/h2_ssl_proxy_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/h2_ssl_proxy_test: $(H2_SSL_PROXY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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) $(H2_SSL_PROXY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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)/h2_ssl_proxy_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_ssl_proxy.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_ssl_proxy_test: $(H2_SSL_PROXY_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(H2_SSL_PROXY_TEST_OBJS:.o=.dep) endif endif H2_UDS_TEST_SRC = \ test/core/end2end/fixtures/h2_uds.c \ H2_UDS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_UDS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/h2_uds_test: openssl_dep_error else $(BINDIR)/$(CONFIG)/h2_uds_test: $(H2_UDS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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) $(H2_UDS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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)/h2_uds_test endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_uds.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_uds_test: $(H2_UDS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(H2_UDS_TEST_OBJS:.o=.dep) endif endif H2_CENSUS_NOSEC_TEST_SRC = \ test/core/end2end/fixtures/h2_census.c \ H2_CENSUS_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_CENSUS_NOSEC_TEST_SRC)))) $(BINDIR)/$(CONFIG)/h2_census_nosec_test: $(H2_CENSUS_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(H2_CENSUS_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_census_nosec_test $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_census.o: $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_census_nosec_test: $(H2_CENSUS_NOSEC_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(H2_CENSUS_NOSEC_TEST_OBJS:.o=.dep) endif H2_COMPRESS_NOSEC_TEST_SRC = \ test/core/end2end/fixtures/h2_compress.c \ H2_COMPRESS_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_COMPRESS_NOSEC_TEST_SRC)))) $(BINDIR)/$(CONFIG)/h2_compress_nosec_test: $(H2_COMPRESS_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(H2_COMPRESS_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_compress_nosec_test $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_compress.o: $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_compress_nosec_test: $(H2_COMPRESS_NOSEC_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(H2_COMPRESS_NOSEC_TEST_OBJS:.o=.dep) endif H2_FD_NOSEC_TEST_SRC = \ test/core/end2end/fixtures/h2_fd.c \ H2_FD_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FD_NOSEC_TEST_SRC)))) $(BINDIR)/$(CONFIG)/h2_fd_nosec_test: $(H2_FD_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(H2_FD_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_fd_nosec_test $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_fd.o: $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_fd_nosec_test: $(H2_FD_NOSEC_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(H2_FD_NOSEC_TEST_OBJS:.o=.dep) endif H2_FULL_NOSEC_TEST_SRC = \ test/core/end2end/fixtures/h2_full.c \ H2_FULL_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FULL_NOSEC_TEST_SRC)))) $(BINDIR)/$(CONFIG)/h2_full_nosec_test: $(H2_FULL_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(H2_FULL_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_full_nosec_test $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_full.o: $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_full_nosec_test: $(H2_FULL_NOSEC_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(H2_FULL_NOSEC_TEST_OBJS:.o=.dep) endif H2_FULL+PIPE_NOSEC_TEST_SRC = \ test/core/end2end/fixtures/h2_full+pipe.c \ H2_FULL+PIPE_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FULL+PIPE_NOSEC_TEST_SRC)))) $(BINDIR)/$(CONFIG)/h2_full+pipe_nosec_test: $(H2_FULL+PIPE_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(H2_FULL+PIPE_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_full+pipe_nosec_test $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_full+pipe.o: $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_full+pipe_nosec_test: $(H2_FULL+PIPE_NOSEC_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(H2_FULL+PIPE_NOSEC_TEST_OBJS:.o=.dep) endif H2_FULL+TRACE_NOSEC_TEST_SRC = \ test/core/end2end/fixtures/h2_full+trace.c \ H2_FULL+TRACE_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_FULL+TRACE_NOSEC_TEST_SRC)))) $(BINDIR)/$(CONFIG)/h2_full+trace_nosec_test: $(H2_FULL+TRACE_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(H2_FULL+TRACE_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_full+trace_nosec_test $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_full+trace.o: $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_full+trace_nosec_test: $(H2_FULL+TRACE_NOSEC_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(H2_FULL+TRACE_NOSEC_TEST_OBJS:.o=.dep) endif H2_HTTP_PROXY_NOSEC_TEST_SRC = \ test/core/end2end/fixtures/h2_http_proxy.c \ H2_HTTP_PROXY_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_HTTP_PROXY_NOSEC_TEST_SRC)))) $(BINDIR)/$(CONFIG)/h2_http_proxy_nosec_test: $(H2_HTTP_PROXY_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(H2_HTTP_PROXY_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_http_proxy_nosec_test $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_http_proxy.o: $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_http_proxy_nosec_test: $(H2_HTTP_PROXY_NOSEC_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(H2_HTTP_PROXY_NOSEC_TEST_OBJS:.o=.dep) endif H2_LOAD_REPORTING_NOSEC_TEST_SRC = \ test/core/end2end/fixtures/h2_load_reporting.c \ H2_LOAD_REPORTING_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_LOAD_REPORTING_NOSEC_TEST_SRC)))) $(BINDIR)/$(CONFIG)/h2_load_reporting_nosec_test: $(H2_LOAD_REPORTING_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(H2_LOAD_REPORTING_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_load_reporting_nosec_test $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_load_reporting.o: $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_load_reporting_nosec_test: $(H2_LOAD_REPORTING_NOSEC_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(H2_LOAD_REPORTING_NOSEC_TEST_OBJS:.o=.dep) endif H2_PROXY_NOSEC_TEST_SRC = \ test/core/end2end/fixtures/h2_proxy.c \ H2_PROXY_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_PROXY_NOSEC_TEST_SRC)))) $(BINDIR)/$(CONFIG)/h2_proxy_nosec_test: $(H2_PROXY_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(H2_PROXY_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_proxy_nosec_test $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_proxy.o: $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_proxy_nosec_test: $(H2_PROXY_NOSEC_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(H2_PROXY_NOSEC_TEST_OBJS:.o=.dep) endif H2_SOCKPAIR_NOSEC_TEST_SRC = \ test/core/end2end/fixtures/h2_sockpair.c \ H2_SOCKPAIR_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SOCKPAIR_NOSEC_TEST_SRC)))) $(BINDIR)/$(CONFIG)/h2_sockpair_nosec_test: $(H2_SOCKPAIR_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(H2_SOCKPAIR_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_sockpair_nosec_test $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_sockpair.o: $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_sockpair_nosec_test: $(H2_SOCKPAIR_NOSEC_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(H2_SOCKPAIR_NOSEC_TEST_OBJS:.o=.dep) endif H2_SOCKPAIR+TRACE_NOSEC_TEST_SRC = \ test/core/end2end/fixtures/h2_sockpair+trace.c \ H2_SOCKPAIR+TRACE_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SOCKPAIR+TRACE_NOSEC_TEST_SRC)))) $(BINDIR)/$(CONFIG)/h2_sockpair+trace_nosec_test: $(H2_SOCKPAIR+TRACE_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(H2_SOCKPAIR+TRACE_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_sockpair+trace_nosec_test $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_sockpair+trace.o: $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_sockpair+trace_nosec_test: $(H2_SOCKPAIR+TRACE_NOSEC_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(H2_SOCKPAIR+TRACE_NOSEC_TEST_OBJS:.o=.dep) endif H2_SOCKPAIR_1BYTE_NOSEC_TEST_SRC = \ test/core/end2end/fixtures/h2_sockpair_1byte.c \ H2_SOCKPAIR_1BYTE_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SOCKPAIR_1BYTE_NOSEC_TEST_SRC)))) $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_nosec_test: $(H2_SOCKPAIR_1BYTE_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(H2_SOCKPAIR_1BYTE_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_nosec_test $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_sockpair_1byte.o: $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_sockpair_1byte_nosec_test: $(H2_SOCKPAIR_1BYTE_NOSEC_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(H2_SOCKPAIR_1BYTE_NOSEC_TEST_OBJS:.o=.dep) endif H2_UDS_NOSEC_TEST_SRC = \ test/core/end2end/fixtures/h2_uds.c \ H2_UDS_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_UDS_NOSEC_TEST_SRC)))) $(BINDIR)/$(CONFIG)/h2_uds_nosec_test: $(H2_UDS_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LD) $(LDFLAGS) $(H2_UDS_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_uds_nosec_test $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_uds.o: $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_h2_uds_nosec_test: $(H2_UDS_NOSEC_TEST_OBJS:.o=.dep) ifneq ($(NO_DEPS),true) -include $(H2_UDS_NOSEC_TEST_OBJS:.o=.dep) endif API_FUZZER_ONE_ENTRY_SRC = \ test/core/end2end/fuzzers/api_fuzzer.c \ test/core/util/one_corpus_entry_fuzzer.c \ API_FUZZER_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(API_FUZZER_ONE_ENTRY_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/api_fuzzer_one_entry: openssl_dep_error else $(BINDIR)/$(CONFIG)/api_fuzzer_one_entry: $(API_FUZZER_ONE_ENTRY_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) $(API_FUZZER_ONE_ENTRY_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)/api_fuzzer_one_entry endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fuzzers/api_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_api_fuzzer_one_entry: $(API_FUZZER_ONE_ENTRY_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(API_FUZZER_ONE_ENTRY_OBJS:.o=.dep) endif endif CLIENT_FUZZER_ONE_ENTRY_SRC = \ test/core/end2end/fuzzers/client_fuzzer.c \ test/core/util/one_corpus_entry_fuzzer.c \ CLIENT_FUZZER_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CLIENT_FUZZER_ONE_ENTRY_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/client_fuzzer_one_entry: openssl_dep_error else $(BINDIR)/$(CONFIG)/client_fuzzer_one_entry: $(CLIENT_FUZZER_ONE_ENTRY_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) $(CLIENT_FUZZER_ONE_ENTRY_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)/client_fuzzer_one_entry endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fuzzers/client_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_client_fuzzer_one_entry: $(CLIENT_FUZZER_ONE_ENTRY_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(CLIENT_FUZZER_ONE_ENTRY_OBJS:.o=.dep) endif endif HPACK_PARSER_FUZZER_TEST_ONE_ENTRY_SRC = \ test/core/transport/chttp2/hpack_parser_fuzzer_test.c \ test/core/util/one_corpus_entry_fuzzer.c \ HPACK_PARSER_FUZZER_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HPACK_PARSER_FUZZER_TEST_ONE_ENTRY_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry: openssl_dep_error else $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry: $(HPACK_PARSER_FUZZER_TEST_ONE_ENTRY_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) $(HPACK_PARSER_FUZZER_TEST_ONE_ENTRY_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)/hpack_parser_fuzzer_test_one_entry endif $(OBJDIR)/$(CONFIG)/test/core/transport/chttp2/hpack_parser_fuzzer_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_hpack_parser_fuzzer_test_one_entry: $(HPACK_PARSER_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(HPACK_PARSER_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep) endif endif HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_SRC = \ test/core/http/request_fuzzer.c \ test/core/util/one_corpus_entry_fuzzer.c \ HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/http_request_fuzzer_test_one_entry: openssl_dep_error else $(BINDIR)/$(CONFIG)/http_request_fuzzer_test_one_entry: $(HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_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) $(HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_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)/http_request_fuzzer_test_one_entry endif $(OBJDIR)/$(CONFIG)/test/core/http/request_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_http_request_fuzzer_test_one_entry: $(HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep) endif endif HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_SRC = \ test/core/http/response_fuzzer.c \ test/core/util/one_corpus_entry_fuzzer.c \ HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/http_response_fuzzer_test_one_entry: openssl_dep_error else $(BINDIR)/$(CONFIG)/http_response_fuzzer_test_one_entry: $(HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_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) $(HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_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)/http_response_fuzzer_test_one_entry endif $(OBJDIR)/$(CONFIG)/test/core/http/response_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_http_response_fuzzer_test_one_entry: $(HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep) endif endif JSON_FUZZER_TEST_ONE_ENTRY_SRC = \ test/core/json/fuzzer.c \ test/core/util/one_corpus_entry_fuzzer.c \ JSON_FUZZER_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_FUZZER_TEST_ONE_ENTRY_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/json_fuzzer_test_one_entry: openssl_dep_error else $(BINDIR)/$(CONFIG)/json_fuzzer_test_one_entry: $(JSON_FUZZER_TEST_ONE_ENTRY_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) $(JSON_FUZZER_TEST_ONE_ENTRY_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)/json_fuzzer_test_one_entry endif $(OBJDIR)/$(CONFIG)/test/core/json/fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_json_fuzzer_test_one_entry: $(JSON_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(JSON_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep) endif endif NANOPB_FUZZER_RESPONSE_TEST_ONE_ENTRY_SRC = \ test/core/nanopb/fuzzer_response.c \ test/core/util/one_corpus_entry_fuzzer.c \ NANOPB_FUZZER_RESPONSE_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(NANOPB_FUZZER_RESPONSE_TEST_ONE_ENTRY_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test_one_entry: openssl_dep_error else $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test_one_entry: $(NANOPB_FUZZER_RESPONSE_TEST_ONE_ENTRY_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) $(NANOPB_FUZZER_RESPONSE_TEST_ONE_ENTRY_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)/nanopb_fuzzer_response_test_one_entry endif $(OBJDIR)/$(CONFIG)/test/core/nanopb/fuzzer_response.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_nanopb_fuzzer_response_test_one_entry: $(NANOPB_FUZZER_RESPONSE_TEST_ONE_ENTRY_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(NANOPB_FUZZER_RESPONSE_TEST_ONE_ENTRY_OBJS:.o=.dep) endif endif NANOPB_FUZZER_SERVERLIST_TEST_ONE_ENTRY_SRC = \ test/core/nanopb/fuzzer_serverlist.c \ test/core/util/one_corpus_entry_fuzzer.c \ NANOPB_FUZZER_SERVERLIST_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(NANOPB_FUZZER_SERVERLIST_TEST_ONE_ENTRY_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test_one_entry: openssl_dep_error else $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test_one_entry: $(NANOPB_FUZZER_SERVERLIST_TEST_ONE_ENTRY_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) $(NANOPB_FUZZER_SERVERLIST_TEST_ONE_ENTRY_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)/nanopb_fuzzer_serverlist_test_one_entry endif $(OBJDIR)/$(CONFIG)/test/core/nanopb/fuzzer_serverlist.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_nanopb_fuzzer_serverlist_test_one_entry: $(NANOPB_FUZZER_SERVERLIST_TEST_ONE_ENTRY_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(NANOPB_FUZZER_SERVERLIST_TEST_ONE_ENTRY_OBJS:.o=.dep) endif endif PERCENT_DECODE_FUZZER_ONE_ENTRY_SRC = \ test/core/slice/percent_decode_fuzzer.c \ test/core/util/one_corpus_entry_fuzzer.c \ PERCENT_DECODE_FUZZER_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PERCENT_DECODE_FUZZER_ONE_ENTRY_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/percent_decode_fuzzer_one_entry: openssl_dep_error else $(BINDIR)/$(CONFIG)/percent_decode_fuzzer_one_entry: $(PERCENT_DECODE_FUZZER_ONE_ENTRY_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) $(PERCENT_DECODE_FUZZER_ONE_ENTRY_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)/percent_decode_fuzzer_one_entry endif $(OBJDIR)/$(CONFIG)/test/core/slice/percent_decode_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_percent_decode_fuzzer_one_entry: $(PERCENT_DECODE_FUZZER_ONE_ENTRY_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(PERCENT_DECODE_FUZZER_ONE_ENTRY_OBJS:.o=.dep) endif endif PERCENT_ENCODE_FUZZER_ONE_ENTRY_SRC = \ test/core/slice/percent_encode_fuzzer.c \ test/core/util/one_corpus_entry_fuzzer.c \ PERCENT_ENCODE_FUZZER_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PERCENT_ENCODE_FUZZER_ONE_ENTRY_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/percent_encode_fuzzer_one_entry: openssl_dep_error else $(BINDIR)/$(CONFIG)/percent_encode_fuzzer_one_entry: $(PERCENT_ENCODE_FUZZER_ONE_ENTRY_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) $(PERCENT_ENCODE_FUZZER_ONE_ENTRY_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)/percent_encode_fuzzer_one_entry endif $(OBJDIR)/$(CONFIG)/test/core/slice/percent_encode_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_percent_encode_fuzzer_one_entry: $(PERCENT_ENCODE_FUZZER_ONE_ENTRY_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(PERCENT_ENCODE_FUZZER_ONE_ENTRY_OBJS:.o=.dep) endif endif SERVER_FUZZER_ONE_ENTRY_SRC = \ test/core/end2end/fuzzers/server_fuzzer.c \ test/core/util/one_corpus_entry_fuzzer.c \ SERVER_FUZZER_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_FUZZER_ONE_ENTRY_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/server_fuzzer_one_entry: openssl_dep_error else $(BINDIR)/$(CONFIG)/server_fuzzer_one_entry: $(SERVER_FUZZER_ONE_ENTRY_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) $(SERVER_FUZZER_ONE_ENTRY_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)/server_fuzzer_one_entry endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fuzzers/server_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_server_fuzzer_one_entry: $(SERVER_FUZZER_ONE_ENTRY_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SERVER_FUZZER_ONE_ENTRY_OBJS:.o=.dep) endif endif SSL_SERVER_FUZZER_ONE_ENTRY_SRC = \ test/core/security/ssl_server_fuzzer.c \ test/core/util/one_corpus_entry_fuzzer.c \ SSL_SERVER_FUZZER_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SSL_SERVER_FUZZER_ONE_ENTRY_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/ssl_server_fuzzer_one_entry: openssl_dep_error else $(BINDIR)/$(CONFIG)/ssl_server_fuzzer_one_entry: $(SSL_SERVER_FUZZER_ONE_ENTRY_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) $(SSL_SERVER_FUZZER_ONE_ENTRY_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)/ssl_server_fuzzer_one_entry endif $(OBJDIR)/$(CONFIG)/test/core/security/ssl_server_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_ssl_server_fuzzer_one_entry: $(SSL_SERVER_FUZZER_ONE_ENTRY_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(SSL_SERVER_FUZZER_ONE_ENTRY_OBJS:.o=.dep) endif endif URI_FUZZER_TEST_ONE_ENTRY_SRC = \ test/core/client_channel/uri_fuzzer_test.c \ test/core/util/one_corpus_entry_fuzzer.c \ URI_FUZZER_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(URI_FUZZER_TEST_ONE_ENTRY_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. $(BINDIR)/$(CONFIG)/uri_fuzzer_test_one_entry: openssl_dep_error else $(BINDIR)/$(CONFIG)/uri_fuzzer_test_one_entry: $(URI_FUZZER_TEST_ONE_ENTRY_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) $(URI_FUZZER_TEST_ONE_ENTRY_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)/uri_fuzzer_test_one_entry endif $(OBJDIR)/$(CONFIG)/test/core/client_channel/uri_fuzzer_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_uri_fuzzer_test_one_entry: $(URI_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(URI_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep) endif endif ifneq ($(OPENSSL_DEP),) # This is to ensure the embedded OpenSSL is built beforehand, properly # installing headers to their final destination on the drive. We need this # otherwise parallel compilation will fail if a source is compiled first. src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c: $(OPENSSL_DEP) src/core/ext/transport/chttp2/client/secure/secure_channel_create.c: $(OPENSSL_DEP) src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c: $(OPENSSL_DEP) src/core/ext/transport/cronet/client/secure/cronet_channel_create.c: $(OPENSSL_DEP) src/core/ext/transport/cronet/transport/cronet_api_dummy.c: $(OPENSSL_DEP) src/core/ext/transport/cronet/transport/cronet_transport.c: $(OPENSSL_DEP) src/core/lib/http/httpcli_security_connector.c: $(OPENSSL_DEP) src/core/lib/security/context/security_context.c: $(OPENSSL_DEP) src/core/lib/security/credentials/composite/composite_credentials.c: $(OPENSSL_DEP) src/core/lib/security/credentials/credentials.c: $(OPENSSL_DEP) src/core/lib/security/credentials/credentials_metadata.c: $(OPENSSL_DEP) src/core/lib/security/credentials/fake/fake_credentials.c: $(OPENSSL_DEP) src/core/lib/security/credentials/google_default/credentials_generic.c: $(OPENSSL_DEP) src/core/lib/security/credentials/google_default/google_default_credentials.c: $(OPENSSL_DEP) src/core/lib/security/credentials/iam/iam_credentials.c: $(OPENSSL_DEP) src/core/lib/security/credentials/jwt/json_token.c: $(OPENSSL_DEP) src/core/lib/security/credentials/jwt/jwt_credentials.c: $(OPENSSL_DEP) src/core/lib/security/credentials/jwt/jwt_verifier.c: $(OPENSSL_DEP) src/core/lib/security/credentials/oauth2/oauth2_credentials.c: $(OPENSSL_DEP) src/core/lib/security/credentials/plugin/plugin_credentials.c: $(OPENSSL_DEP) src/core/lib/security/credentials/ssl/ssl_credentials.c: $(OPENSSL_DEP) src/core/lib/security/transport/client_auth_filter.c: $(OPENSSL_DEP) src/core/lib/security/transport/lb_targets_info.c: $(OPENSSL_DEP) src/core/lib/security/transport/secure_endpoint.c: $(OPENSSL_DEP) src/core/lib/security/transport/security_connector.c: $(OPENSSL_DEP) src/core/lib/security/transport/security_handshaker.c: $(OPENSSL_DEP) src/core/lib/security/transport/server_auth_filter.c: $(OPENSSL_DEP) src/core/lib/security/transport/tsi_error.c: $(OPENSSL_DEP) src/core/lib/security/util/json_util.c: $(OPENSSL_DEP) src/core/lib/surface/init_secure.c: $(OPENSSL_DEP) src/core/plugin_registry/grpc_cronet_plugin_registry.c: $(OPENSSL_DEP) src/core/plugin_registry/grpc_plugin_registry.c: $(OPENSSL_DEP) src/core/tsi/fake_transport_security.c: $(OPENSSL_DEP) src/core/tsi/ssl_transport_security.c: $(OPENSSL_DEP) src/core/tsi/transport_security.c: $(OPENSSL_DEP) src/cpp/client/cronet_credentials.cc: $(OPENSSL_DEP) src/cpp/client/secure_credentials.cc: $(OPENSSL_DEP) src/cpp/common/auth_property_iterator.cc: $(OPENSSL_DEP) src/cpp/common/secure_auth_context.cc: $(OPENSSL_DEP) src/cpp/common/secure_channel_arguments.cc: $(OPENSSL_DEP) src/cpp/common/secure_create_auth_context.cc: $(OPENSSL_DEP) src/cpp/ext/proto_server_reflection.cc: $(OPENSSL_DEP) src/cpp/ext/proto_server_reflection_plugin.cc: $(OPENSSL_DEP) src/cpp/server/secure_server_credentials.cc: $(OPENSSL_DEP) src/cpp/util/error_details.cc: $(OPENSSL_DEP) src/csharp/ext/grpc_csharp_ext.c: $(OPENSSL_DEP) test/core/bad_client/bad_client.c: $(OPENSSL_DEP) test/core/bad_ssl/server_common.c: $(OPENSSL_DEP) test/core/end2end/data/client_certs.c: $(OPENSSL_DEP) test/core/end2end/data/server1_cert.c: $(OPENSSL_DEP) test/core/end2end/data/server1_key.c: $(OPENSSL_DEP) test/core/end2end/data/test_root_cert.c: $(OPENSSL_DEP) test/core/end2end/end2end_tests.c: $(OPENSSL_DEP) test/core/end2end/tests/call_creds.c: $(OPENSSL_DEP) test/core/security/oauth2_utils.c: $(OPENSSL_DEP) test/core/util/reconnect_server.c: $(OPENSSL_DEP) test/core/util/test_tcp_server.c: $(OPENSSL_DEP) test/cpp/end2end/test_service_impl.cc: $(OPENSSL_DEP) test/cpp/interop/client.cc: $(OPENSSL_DEP) test/cpp/interop/client_helper.cc: $(OPENSSL_DEP) test/cpp/interop/http2_client.cc: $(OPENSSL_DEP) test/cpp/interop/interop_client.cc: $(OPENSSL_DEP) test/cpp/interop/interop_server.cc: $(OPENSSL_DEP) test/cpp/interop/interop_server_bootstrap.cc: $(OPENSSL_DEP) test/cpp/interop/server_helper.cc: $(OPENSSL_DEP) test/cpp/microbenchmarks/helpers.cc: $(OPENSSL_DEP) test/cpp/qps/benchmark_config.cc: $(OPENSSL_DEP) test/cpp/qps/client_async.cc: $(OPENSSL_DEP) test/cpp/qps/client_sync.cc: $(OPENSSL_DEP) test/cpp/qps/driver.cc: $(OPENSSL_DEP) test/cpp/qps/parse_json.cc: $(OPENSSL_DEP) test/cpp/qps/qps_worker.cc: $(OPENSSL_DEP) test/cpp/qps/report.cc: $(OPENSSL_DEP) test/cpp/qps/server_async.cc: $(OPENSSL_DEP) test/cpp/qps/server_sync.cc: $(OPENSSL_DEP) test/cpp/qps/usage_timer.cc: $(OPENSSL_DEP) test/cpp/util/byte_buffer_proto_helper.cc: $(OPENSSL_DEP) test/cpp/util/cli_call.cc: $(OPENSSL_DEP) test/cpp/util/cli_credentials.cc: $(OPENSSL_DEP) test/cpp/util/create_test_channel.cc: $(OPENSSL_DEP) test/cpp/util/grpc_tool.cc: $(OPENSSL_DEP) test/cpp/util/proto_file_parser.cc: $(OPENSSL_DEP) test/cpp/util/proto_reflection_descriptor_database.cc: $(OPENSSL_DEP) test/cpp/util/service_describer.cc: $(OPENSSL_DEP) test/cpp/util/string_ref_helper.cc: $(OPENSSL_DEP) test/cpp/util/subprocess.cc: $(OPENSSL_DEP) test/cpp/util/test_config_cc.cc: $(OPENSSL_DEP) test/cpp/util/test_credentials_provider.cc: $(OPENSSL_DEP) endif .PHONY: all strip tools dep_error openssl_dep_error openssl_dep_message git_update stop buildtests buildtests_c buildtests_cxx test test_c test_cxx install install_c install_cxx install-headers install-headers_c install-headers_cxx install-shared install-shared_c install-shared_cxx install-static install-static_c install-static_cxx strip strip-shared strip-static strip_c strip-shared_c strip-static_c strip_cxx strip-shared_cxx strip-static_cxx dep_c dep_cxx bins_dep_c bins_dep_cxx clean .PHONY: printvars printvars: @$(foreach V,$(sort $(.VARIABLES)), $(if $(filter-out environment% default automatic, $(origin $V)),$(warning $V=$($V) ($(value $V))))) grpc-1.3.2/PATENTS000066400000000000000000000024431310511640000135030ustar00rootroot00000000000000Additional IP Rights Grant (Patents) "This implementation" means the copyrightable works distributed by Google as part of the GRPC project. Google hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, transfer and otherwise run, modify and propagate the contents of this implementation of GRPC, where such license applies only to those patent claims, both currently owned or controlled by Google and acquired in the future, licensable by Google that are necessarily infringed by this implementation of GRPC. This grant does not include claims that would be infringed only as a consequence of further modification of this implementation. If you or your agent or exclusive licensee institute or order or agree to the institution of patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that this implementation of GRPC or any code incorporated within this implementation of GRPC constitutes direct or contributory patent infringement, or inducement of patent infringement, then any patent rights granted to you under this License for this implementation of GRPC shall terminate as of the date such litigation is filed. grpc-1.3.2/PYTHON-MANIFEST.in000066400000000000000000000012451310511640000152160ustar00rootroot00000000000000recursive-include src/python/grpcio/grpc *.c *.h *.py *.pyx *.pxd *.pxi *.python *.pem recursive-exclude src/python/grpcio/grpc/_cython *.so *.pyd graft src/python/grpcio/grpcio.egg-info graft src/core graft src/boringssl graft include/grpc graft third_party/boringssl graft third_party/nanopb graft third_party/zlib graft third_party/cares include src/python/grpcio/_spawn_patch.py include src/python/grpcio/commands.py include src/python/grpcio/grpc_version.py include src/python/grpcio/grpc_core_dependencies.py include src/python/grpcio/precompiled.py include src/python/grpcio/support.py include src/python/grpcio/README.rst include requirements.txt include etc/roots.pem grpc-1.3.2/README.md000066400000000000000000000132461310511640000137240ustar00rootroot00000000000000[![Build Status](https://grpc-testing.appspot.com/job/gRPC_master/badge/icon)](https://grpc-testing.appspot.com/job/gRPC_master) [gRPC - An RPC library and framework](http://github.com/grpc/grpc) =================================== [![Join the chat at https://gitter.im/grpc/grpc](https://badges.gitter.im/grpc/grpc.svg)](https://gitter.im/grpc/grpc?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) Copyright 2015 Google Inc. # Documentation You can find more detailed documentation and examples in the [doc](doc) and [examples](examples) directories respectively. # Installation & Testing See [INSTALL](INSTALL.md) for installation instructions for various platforms. See [tools/run_tests](tools/run_tests) for more guidance on how to run various test suites (e.g. unit tests, interop tests, benchmarks) See [Performance dashboard](http://performance-dot-grpc-testing.appspot.com/explore?dashboard=5712453606309888) for the performance numbers for v1.0.x. # Repository Structure & Status This repository contains source code for gRPC libraries for multiple languages written on top of shared C core library [src/core] (src/core). Libraries in different languages may be in different states of development. We are seeking contributions for all of these libraries. | Language | Source | Status | |-------------------------|-------------------------------------|---------| | Shared C [core library] | [src/core](src/core) | 1.0 | | C++ | [src/cpp](src/cpp) | 1.0 | | Ruby | [src/ruby](src/ruby) | 1.0 | | NodeJS | [src/node](src/node) | 1.0 | | Python | [src/python](src/python) | 1.0 | | PHP | [src/php](src/php) | 1.0 | | C# | [src/csharp](src/csharp) | 1.0 | | Objective-C | [src/objective-c](src/objective-c) | 1.0 | Java source code is in the [grpc-java](http://github.com/grpc/grpc-java) repository. Go source code is in the [grpc-go](http://github.com/grpc/grpc-go) repository. See [MANIFEST.md](MANIFEST.md) for a listing of top-level items in the repository. # Overview Remote Procedure Calls (RPCs) provide a useful abstraction for building distributed applications and services. The libraries in this repository provide a concrete implementation of the gRPC protocol, layered over HTTP/2. These libraries enable communication between clients and servers using any combination of the supported languages. ## Interface Developers using gRPC typically start with the description of an RPC service (a collection of methods), and generate client and server side interfaces which they use on the client-side and implement on the server side. By default, gRPC uses [Protocol Buffers](https://github.com/google/protobuf) as the Interface Definition Language (IDL) for describing both the service interface and the structure of the payload messages. It is possible to use other alternatives if desired. ### Surface API Starting from an interface definition in a .proto file, gRPC provides Protocol Compiler plugins that generate Client- and Server-side APIs. gRPC users typically call into these APIs on the Client side and implement the corresponding API on the server side. #### Synchronous vs. asynchronous Synchronous RPC calls, that block until a response arrives from the server, are the closest approximation to the abstraction of a procedure call that RPC aspires to. On the other hand, networks are inherently asynchronous and in many scenarios, it is desirable to have the ability to start RPCs without blocking the current thread. The gRPC programming surface in most languages comes in both synchronous and asynchronous flavors. ## Streaming gRPC supports streaming semantics, where either the client or the server (or both) send a stream of messages on a single RPC call. The most general case is Bidirectional Streaming where a single gRPC call establishes a stream where both the client and the server can send a stream of messages to each other. The streamed messages are delivered in the order they were sent. # Protocol The [gRPC protocol](doc/PROTOCOL-HTTP2.md) specifies the abstract requirements for communication between clients and servers. A concrete embedding over HTTP/2 completes the picture by fleshing out the details of each of the required operations. ## Abstract gRPC protocol A gRPC RPC comprises of a bidirectional stream of messages, initiated by the client. In the client-to-server direction, this stream begins with a mandatory `Call Header`, followed by optional `Initial-Metadata`, followed by zero or more `Payload Messages`. The server-to-client direction contains an optional `Initial-Metadata`, followed by zero or more `Payload Messages` terminated with a mandatory `Status` and optional `Status-Metadata` (a.k.a.,`Trailing-Metadata`). ## Implementation over HTTP/2 The abstract protocol defined above is implemented over [HTTP/2](https://http2.github.io/). gRPC bidirectional streams are mapped to HTTP/2 streams. The contents of `Call Header` and `Initial Metadata` are sent as HTTP/2 headers and subject to HPACK compression. `Payload Messages` are serialized into a byte stream of length prefixed gRPC frames which are then fragmented into HTTP/2 frames at the sender and reassembled at the receiver. `Status` and `Trailing-Metadata` are sent as HTTP/2 trailing headers (a.k.a., trailers). ## Flow Control gRPC inherits the flow control mechanisms in HTTP/2 and uses them to enable fine-grained control of the amount of memory used for buffering in-flight messages. grpc-1.3.2/Rakefile000077500000000000000000000103151310511640000141070ustar00rootroot00000000000000# -*- ruby -*- require 'rake/extensiontask' require 'rspec/core/rake_task' require 'rubocop/rake_task' require 'bundler/gem_tasks' require 'fileutils' require_relative 'build_config.rb' load 'tools/distrib/docker_for_windows.rb' # Add rubocop style checking tasks RuboCop::RakeTask.new(:rubocop) do |task| task.options = ['-c', 'src/ruby/.rubocop.yml'] # add end2end tests to formatter but don't add generated proto _pb.rb's task.patterns = ['src/ruby/{lib,spec}/**/*.rb', 'src/ruby/end2end/*.rb'] end spec = Gem::Specification.load('grpc.gemspec') Gem::PackageTask.new(spec) do |pkg| end # Add the extension compiler task Rake::ExtensionTask.new('grpc_c', spec) do |ext| ext.source_pattern = '**/*.{c,h}' ext.ext_dir = File.join('src', 'ruby', 'ext', 'grpc') ext.lib_dir = File.join('src', 'ruby', 'lib', 'grpc') ext.cross_compile = true ext.cross_platform = [ 'x86-mingw32', 'x64-mingw32', 'x86_64-linux', 'x86-linux', 'universal-darwin' ] ext.cross_compiling do |spec| spec.files = %w( etc/roots.pem grpc_c.32.ruby grpc_c.64.ruby ) spec.files += Dir.glob('src/ruby/bin/**/*') spec.files += Dir.glob('src/ruby/ext/**/*') spec.files += Dir.glob('src/ruby/lib/**/*') spec.files += Dir.glob('src/ruby/pb/**/*') end end # Define the test suites SPEC_SUITES = [ { id: :wrapper, title: 'wrapper layer', files: %w(src/ruby/spec/*.rb) }, { id: :idiomatic, title: 'idiomatic layer', dir: %w(src/ruby/spec/generic), tags: ['~bidi', '~server'] }, { id: :bidi, title: 'bidi tests', dir: %w(src/ruby/spec/generic), tag: 'bidi' }, { id: :server, title: 'rpc server thread tests', dir: %w(src/ruby/spec/generic), tag: 'server' }, { id: :pb, title: 'protobuf service tests', dir: %w(src/ruby/spec/pb) } ] namespace :suite do SPEC_SUITES.each do |suite| desc "Run all specs in the #{suite[:title]} spec suite" RSpec::Core::RakeTask.new(suite[:id]) do |t| ENV['COVERAGE_NAME'] = suite[:id].to_s spec_files = [] suite[:files].each { |f| spec_files += Dir[f] } if suite[:files] if suite[:dir] suite[:dir].each { |f| spec_files += Dir["#{f}/**/*_spec.rb"] } end helper = 'src/ruby/spec/spec_helper.rb' spec_files << helper unless spec_files.include?(helper) t.pattern = spec_files t.rspec_opts = "--tag #{suite[:tag]}" if suite[:tag] if suite[:tags] t.rspec_opts = suite[:tags].map { |x| "--tag #{x}" }.join(' ') end end end end desc 'Build the Windows gRPC DLLs for Ruby' task 'dlls' do grpc_config = ENV['GRPC_CONFIG'] || 'opt' verbose = ENV['V'] || '0' env = 'CPPFLAGS="-D_WIN32_WINNT=0x600 -DUNICODE -D_UNICODE -Wno-unused-variable -Wno-unused-result -DCARES_STATICLIB" ' env += 'LDFLAGS=-static ' env += 'SYSTEM=MINGW32 ' env += 'EMBED_ZLIB=true ' env += 'BUILDDIR=/tmp ' env += "V=#{verbose} " out = GrpcBuildConfig::CORE_WINDOWS_DLL w64 = { cross: 'x86_64-w64-mingw32', out: 'grpc_c.64.ruby' } w32 = { cross: 'i686-w64-mingw32', out: 'grpc_c.32.ruby' } [ w64, w32 ].each do |opt| env_comp = "CC=#{opt[:cross]}-gcc " env_comp += "LD=#{opt[:cross]}-gcc " docker_for_windows "gem update --system && #{env} #{env_comp} make -j #{out} && #{opt[:cross]}-strip -x -S #{out} && cp #{out} #{opt[:out]}" end end desc 'Build the native gem file under rake_compiler_dock' task 'gem:native' do verbose = ENV['V'] || '0' grpc_config = ENV['GRPC_CONFIG'] || 'opt' if RUBY_PLATFORM =~ /darwin/ FileUtils.touch 'grpc_c.32.ruby' FileUtils.touch 'grpc_c.64.ruby' system "rake cross native gem RUBY_CC_VERSION=2.4.0:2.3.0:2.2.2:2.1.5:2.0.0 V=#{verbose} GRPC_CONFIG=#{grpc_config}" else Rake::Task['dlls'].execute docker_for_windows "gem update --system && bundle && rake cross native gem RUBY_CC_VERSION=2.4.0:2.3.0:2.2.2:2.1.5:2.0.0 V=#{verbose} GRPC_CONFIG=#{grpc_config}" end end # Define dependencies between the suites. task 'suite:wrapper' => [:compile, :rubocop] task 'suite:idiomatic' => 'suite:wrapper' task 'suite:bidi' => 'suite:wrapper' task 'suite:server' => 'suite:wrapper' task 'suite:pb' => 'suite:server' desc 'Compiles the gRPC extension then runs all the tests' task all: ['suite:idiomatic', 'suite:bidi', 'suite:pb', 'suite:server'] task default: :all grpc-1.3.2/WORKSPACE000066400000000000000000000032421310511640000137210ustar00rootroot00000000000000bind( name = "nanopb", actual = "//third_party/nanopb", ) bind( name = "libssl", actual = "@submodule_boringssl//:ssl", ) bind( name = "zlib", actual = "@submodule_zlib//:z", ) bind( name = "protobuf", actual = "@submodule_protobuf//:protobuf", ) bind( name = "protobuf_clib", actual = "@submodule_protobuf//:protoc_lib", ) bind( name = "protocol_compiler", actual = "@submodule_protobuf//:protoc", ) bind( name = "cares", actual = "@submodule_cares//:ares", ) bind( name = "gtest", actual = "@submodule_gtest//:gtest", ) bind( name = "benchmark", actual = "@submodule_benchmark//:benchmark", ) bind( name = "gflags", actual = "@com_github_gflags_gflags//:gflags", ) new_local_repository( name = "submodule_boringssl", build_file = "third_party/boringssl-with-bazel/BUILD", path = "third_party/boringssl-with-bazel", ) new_local_repository( name = "submodule_zlib", build_file = "third_party/zlib.BUILD", path = "third_party/zlib", ) new_local_repository( name = "submodule_protobuf", build_file = "third_party/protobuf/BUILD", path = "third_party/protobuf", ) new_local_repository( name = "submodule_gtest", build_file = "third_party/gtest.BUILD", path = "third_party/googletest", ) local_repository( name = "com_github_gflags_gflags", path = "third_party/gflags", ) new_local_repository( name = "submodule_benchmark", path = "third_party/benchmark", build_file = "third_party/benchmark.BUILD", ) new_local_repository( name = "submodule_cares", path = "third_party/cares", build_file = "third_party/cares/cares.BUILD", ) grpc-1.3.2/bazel/000077500000000000000000000000001310511640000135345ustar00rootroot00000000000000grpc-1.3.2/bazel/BUILD000066400000000000000000000035631310511640000143250ustar00rootroot00000000000000# Copyright 2017, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. licenses(["notice"]) # 3-clause BSD package(default_visibility = ["//:__subpackages__"]) load(":cc_grpc_library.bzl", "cc_grpc_library") proto_library( name = "well_known_protos_list", srcs = ["@submodule_protobuf//:well_known_protos"], ) cc_grpc_library( name = "well_known_protos", srcs = "well_known_protos_list", deps = [], proto_only = True, ) grpc-1.3.2/bazel/cc_grpc_library.bzl000066400000000000000000000053141310511640000173740ustar00rootroot00000000000000"""Generates and compiles C++ grpc stubs from proto_library rules.""" load("//:bazel/generate_cc.bzl", "generate_cc") def cc_grpc_library(name, srcs, deps, proto_only, well_known_protos, use_external = False, **kwargs): """Generates C++ grpc classes from a .proto file. Assumes the generated classes will be used in cc_api_version = 2. Arguments: name: name of rule. srcs: a single proto_library, which wraps the .proto files with services. deps: a list of C++ proto_library (or cc_proto_library) which provides the compiled code of any message that the services depend on. well_known_protos: The target from protobuf library that exports well known protos. Currently it will only work if the value is "@submodule_protobuf//:well_known_protos" use_external: When True the grpc deps are prefixed with //external. This allows grpc to be used as a dependency in other bazel projects. **kwargs: rest of arguments, e.g., compatible_with and visibility. """ if len(srcs) > 1: fail("Only one srcs value supported", "srcs") proto_target = "_" + name + "_only" codegen_target = "_" + name + "_codegen" codegen_grpc_target = "_" + name + "_grpc_codegen" proto_deps = ["_" + dep + "_only" for dep in deps if dep.find(':') == -1] proto_deps += [dep.split(':')[0] + ':' + "_" + dep.split(':')[1] + "_only" for dep in deps if dep.find(':') != -1] native.proto_library( name = proto_target, srcs = srcs, deps = proto_deps, **kwargs ) generate_cc( name = codegen_target, srcs = [proto_target], well_known_protos = well_known_protos, **kwargs ) if not proto_only: if use_external: # when this file is used by non-grpc projects plugin = "//external:grpc_cpp_plugin" else: plugin = "//:grpc_cpp_plugin" generate_cc( name = codegen_grpc_target, srcs = [proto_target], plugin = plugin, well_known_protos = well_known_protos, **kwargs ) if use_external: # when this file is used by non-grpc projects grpc_deps = ["//external:grpc++", "//external:grpc++_codegen_proto", "//external:protobuf"] else: grpc_deps = ["//:grpc++", "//:grpc++_codegen_proto", "//external:protobuf"] native.cc_library( name = name, srcs = [":" + codegen_grpc_target, ":" + codegen_target], hdrs = [":" + codegen_grpc_target, ":" + codegen_target], deps = deps + grpc_deps, **kwargs ) else: native.cc_library( name = name, srcs = [":" + codegen_target], hdrs = [":" + codegen_target], deps = deps + ["//external:protobuf"], **kwargs ) grpc-1.3.2/bazel/generate_cc.bzl000066400000000000000000000060401310511640000165040ustar00rootroot00000000000000"""Generates C++ grpc stubs from proto_library rules. This is an internal rule used by cc_grpc_library, and shouldn't be used directly. """ def generate_cc_impl(ctx): """Implementation of the generate_cc rule.""" protos = [f for src in ctx.attr.srcs for f in src.proto.direct_sources] includes = [f for src in ctx.attr.srcs for f in src.proto.transitive_imports] outs = [] if ctx.executable.plugin: outs += [proto.basename[:-len(".proto")] + ".grpc.pb.h" for proto in protos] outs += [proto.basename[:-len(".proto")] + ".grpc.pb.cc" for proto in protos] else: outs += [proto.basename[:-len(".proto")] + ".pb.h" for proto in protos] outs += [proto.basename[:-len(".proto")] + ".pb.cc" for proto in protos] out_files = [ctx.new_file(out) for out in outs] # The following should be replaced with ctx.configuration.buildout # whenever this is added to Skylark. dir_out = out_files[0].dirname[:-len(protos[0].dirname)] arguments = [] if ctx.executable.plugin: arguments += ["--plugin=protoc-gen-PLUGIN=" + ctx.executable.plugin.path] arguments += ["--PLUGIN_out=" + ",".join(ctx.attr.flags) + ":" + dir_out] additional_input = [ctx.executable.plugin] else: arguments += ["--cpp_out=" + ",".join(ctx.attr.flags) + ":" + dir_out] additional_input = [] arguments += ["-I{0}={0}".format(include.path) for include in includes] arguments += [proto.path for proto in protos] # create a list of well known proto files if the argument is non-None well_known_proto_files = [] if ctx.attr.well_known_protos: f = ctx.attr.well_known_protos.files.to_list()[0].dirname if f != "external/submodule_protobuf/src/google/protobuf": print("Error: Only @submodule_protobuf//:well_known_protos is supported") else: # f points to "external/submodule_protobuf/src/google/protobuf" # add -I argument to protoc so it knows where to look for the proto files. arguments += ["-I{0}".format(f + "/../..")] well_known_proto_files = [f for f in ctx.attr.well_known_protos.files] ctx.action( inputs = protos + includes + additional_input + well_known_proto_files, outputs = out_files, executable = ctx.executable._protoc, arguments = arguments, ) return struct(files=set(out_files)) generate_cc = rule( attrs = { "srcs": attr.label_list( mandatory = True, non_empty = True, providers = ["proto"], ), "plugin": attr.label( executable = True, providers = ["files_to_run"], cfg = "host", ), "flags": attr.string_list( mandatory = False, allow_empty = True, ), "well_known_protos" : attr.label( mandatory = False, ), "_protoc": attr.label( default = Label("//external:protocol_compiler"), executable = True, cfg = "host", ), }, # We generate .h files, so we need to output to genfiles. output_to_genfiles = True, implementation = generate_cc_impl, ) grpc-1.3.2/bazel/grpc_build_system.bzl000066400000000000000000000052261310511640000177700ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # This is for the gRPC build system. This isn't intended to be used outsite of # the BUILD file for gRPC. It contains the mapping for the template system we # use to generate other platform's build system files. # def grpc_cc_library(name, srcs = [], public_hdrs = [], hdrs = [], external_deps = [], deps = [], standalone = False, language = "C++"): copts = [] if language.upper() == "C": copts = ["-std=c99"] native.cc_library( name = name, srcs = srcs, hdrs = hdrs + public_hdrs, deps = deps + ["//external:" + dep for dep in external_deps], copts = copts, linkopts = ["-pthread"], includes = [ "include" ] ) def grpc_proto_plugin(name, srcs = [], deps = []): native.cc_binary( name = name, srcs = srcs, deps = deps, ) load("//:bazel/cc_grpc_library.bzl", "cc_grpc_library") def grpc_proto_library(name, srcs = [], deps = [], well_known_protos = None, has_services = True, use_external = False): cc_grpc_library( name = name, srcs = srcs, deps = deps, well_known_protos = well_known_protos, proto_only = not has_services, use_external = use_external, ) grpc-1.3.2/binding.gyp000066400000000000000000001250101310511640000145710ustar00rootroot00000000000000# GRPC Node gyp file # This currently builds the Node extension and dependencies # This file has been automatically generated from a template file. # Please look at the templates directory instead. # This file can be regenerated from the template by running # tools/buildgen/generate_projects.sh # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Some of this file is built with the help of # https://n8.io/converting-a-c-library-to-gyp/ { 'variables': { 'runtime%': 'node', # Some Node installations use the system installation of OpenSSL, and on # some systems, the system OpenSSL still does not have ALPN support. This # will let users recompile gRPC to work without ALPN. 'grpc_alpn%': 'true', # Indicates that the library should be built with gcov. 'grpc_gcov%': 'false', # Indicates that the library should be built with compatibility for musl # libc, so that it can run on Alpine Linux. This is only necessary if not # building on Alpine Linux 'grpc_alpine%': 'false' }, 'target_defaults': { 'configurations': { 'Release': { 'cflags': [ '-O2', ], 'defines': [ 'NDEBUG', ], }, 'Debug': { 'cflags': [ '-O0', ], 'defines': [ '_DEBUG', 'DEBUG', ], }, }, 'cflags': [ '-g', '-Wall', '-Wextra', '-Werror', '-Wno-long-long', '-Wno-unused-parameter', '-DOSATOMIC_USE_INLINED=1', ], 'ldflags': [ '-g', ], 'include_dirs': [ '.', 'include' ], 'defines': [ 'GPR_BACKWARDS_COMPATIBILITY_MODE', 'GRPC_ARES=0', 'GRPC_UV' ], 'conditions': [ ['grpc_gcov=="true"', { 'cflags': [ '-O0', '-fprofile-arcs', '-ftest-coverage', '-Wno-return-type', ], 'defines': [ '_DEBUG', 'DEBUG', 'GPR_GCOV', ], 'ldflags': [ '-fprofile-arcs', '-ftest-coverage', '-rdynamic', ], }], ['grpc_alpine=="true"', { 'defines': [ 'GPR_MUSL_LIBC_COMPAT' ] }], ['OS!="win" and runtime=="electron"', { "defines": [ 'OPENSSL_NO_THREADS' ] }], # This is the condition for using boringssl ['OS=="win" or runtime=="electron"', { "include_dirs": [ "third_party/boringssl/include" ], "defines": [ 'OPENSSL_NO_ASM' ] }, { 'conditions': [ ['grpc_alpn=="true"', { 'defines': [ 'TSI_OPENSSL_ALPN_SUPPORT=1' ], }, { 'defines': [ 'TSI_OPENSSL_ALPN_SUPPORT=0' ], }] ], 'include_dirs': [ '<(node_root_dir)/deps/openssl/openssl/include', ], 'conditions': [ ["target_arch=='ia32'", { "include_dirs": [ "<(node_root_dir)/deps/openssl/config/piii" ] }], ["target_arch=='x64'", { "include_dirs": [ "<(node_root_dir)/deps/openssl/config/k8" ] }], ["target_arch=='arm'", { "include_dirs": [ "<(node_root_dir)/deps/openssl/config/arm" ] }] ] }], ['OS == "win"', { "include_dirs": [ "third_party/zlib", "third_party/cares/cares" ], "defines": [ '_WIN32_WINNT=0x0600', 'WIN32_LEAN_AND_MEAN', '_HAS_EXCEPTIONS=0', 'UNICODE', '_UNICODE', 'NOMINMAX', ], "msvs_settings": { 'VCCLCompilerTool': { 'RuntimeLibrary': 1, # static debug } }, "libraries": [ "ws2_32" ] }, { # OS != "win" 'include_dirs': [ '<(node_root_dir)/deps/zlib', '<(node_root_dir)/deps/cares/include' ] }] ] }, 'conditions': [ ['OS=="win" or runtime=="electron"', { 'targets': [ { 'cflags': [ '-std=c99', '-Wall', '-Werror' ], 'target_name': 'boringssl', 'product_prefix': 'lib', 'type': 'static_library', 'dependencies': [ ], 'sources': [ 'src/boringssl/err_data.c', 'third_party/boringssl/crypto/aes/aes.c', 'third_party/boringssl/crypto/aes/mode_wrappers.c', 'third_party/boringssl/crypto/asn1/a_bitstr.c', 'third_party/boringssl/crypto/asn1/a_bool.c', 'third_party/boringssl/crypto/asn1/a_d2i_fp.c', 'third_party/boringssl/crypto/asn1/a_dup.c', 'third_party/boringssl/crypto/asn1/a_enum.c', 'third_party/boringssl/crypto/asn1/a_gentm.c', 'third_party/boringssl/crypto/asn1/a_i2d_fp.c', 'third_party/boringssl/crypto/asn1/a_int.c', 'third_party/boringssl/crypto/asn1/a_mbstr.c', 'third_party/boringssl/crypto/asn1/a_object.c', 'third_party/boringssl/crypto/asn1/a_octet.c', 'third_party/boringssl/crypto/asn1/a_print.c', 'third_party/boringssl/crypto/asn1/a_strnid.c', 'third_party/boringssl/crypto/asn1/a_time.c', 'third_party/boringssl/crypto/asn1/a_type.c', 'third_party/boringssl/crypto/asn1/a_utctm.c', 'third_party/boringssl/crypto/asn1/a_utf8.c', 'third_party/boringssl/crypto/asn1/asn1_lib.c', 'third_party/boringssl/crypto/asn1/asn1_par.c', 'third_party/boringssl/crypto/asn1/asn_pack.c', 'third_party/boringssl/crypto/asn1/f_enum.c', 'third_party/boringssl/crypto/asn1/f_int.c', 'third_party/boringssl/crypto/asn1/f_string.c', 'third_party/boringssl/crypto/asn1/t_bitst.c', 'third_party/boringssl/crypto/asn1/tasn_dec.c', 'third_party/boringssl/crypto/asn1/tasn_enc.c', 'third_party/boringssl/crypto/asn1/tasn_fre.c', 'third_party/boringssl/crypto/asn1/tasn_new.c', 'third_party/boringssl/crypto/asn1/tasn_typ.c', 'third_party/boringssl/crypto/asn1/tasn_utl.c', 'third_party/boringssl/crypto/asn1/x_bignum.c', 'third_party/boringssl/crypto/asn1/x_long.c', 'third_party/boringssl/crypto/base64/base64.c', 'third_party/boringssl/crypto/bio/bio.c', 'third_party/boringssl/crypto/bio/bio_mem.c', 'third_party/boringssl/crypto/bio/buffer.c', 'third_party/boringssl/crypto/bio/connect.c', 'third_party/boringssl/crypto/bio/fd.c', 'third_party/boringssl/crypto/bio/file.c', 'third_party/boringssl/crypto/bio/hexdump.c', 'third_party/boringssl/crypto/bio/pair.c', 'third_party/boringssl/crypto/bio/printf.c', 'third_party/boringssl/crypto/bio/socket.c', 'third_party/boringssl/crypto/bio/socket_helper.c', 'third_party/boringssl/crypto/bn/add.c', 'third_party/boringssl/crypto/bn/asm/x86_64-gcc.c', 'third_party/boringssl/crypto/bn/bn.c', 'third_party/boringssl/crypto/bn/bn_asn1.c', 'third_party/boringssl/crypto/bn/cmp.c', 'third_party/boringssl/crypto/bn/convert.c', 'third_party/boringssl/crypto/bn/ctx.c', 'third_party/boringssl/crypto/bn/div.c', 'third_party/boringssl/crypto/bn/exponentiation.c', 'third_party/boringssl/crypto/bn/gcd.c', 'third_party/boringssl/crypto/bn/generic.c', 'third_party/boringssl/crypto/bn/kronecker.c', 'third_party/boringssl/crypto/bn/montgomery.c', 'third_party/boringssl/crypto/bn/montgomery_inv.c', 'third_party/boringssl/crypto/bn/mul.c', 'third_party/boringssl/crypto/bn/prime.c', 'third_party/boringssl/crypto/bn/random.c', 'third_party/boringssl/crypto/bn/rsaz_exp.c', 'third_party/boringssl/crypto/bn/shift.c', 'third_party/boringssl/crypto/bn/sqrt.c', 'third_party/boringssl/crypto/buf/buf.c', 'third_party/boringssl/crypto/bytestring/asn1_compat.c', 'third_party/boringssl/crypto/bytestring/ber.c', 'third_party/boringssl/crypto/bytestring/cbb.c', 'third_party/boringssl/crypto/bytestring/cbs.c', 'third_party/boringssl/crypto/chacha/chacha.c', 'third_party/boringssl/crypto/cipher/aead.c', 'third_party/boringssl/crypto/cipher/cipher.c', 'third_party/boringssl/crypto/cipher/derive_key.c', 'third_party/boringssl/crypto/cipher/e_aes.c', 'third_party/boringssl/crypto/cipher/e_chacha20poly1305.c', 'third_party/boringssl/crypto/cipher/e_des.c', 'third_party/boringssl/crypto/cipher/e_null.c', 'third_party/boringssl/crypto/cipher/e_rc2.c', 'third_party/boringssl/crypto/cipher/e_rc4.c', 'third_party/boringssl/crypto/cipher/e_ssl3.c', 'third_party/boringssl/crypto/cipher/e_tls.c', 'third_party/boringssl/crypto/cipher/tls_cbc.c', 'third_party/boringssl/crypto/cmac/cmac.c', 'third_party/boringssl/crypto/conf/conf.c', 'third_party/boringssl/crypto/cpu-aarch64-linux.c', 'third_party/boringssl/crypto/cpu-arm-linux.c', 'third_party/boringssl/crypto/cpu-arm.c', 'third_party/boringssl/crypto/cpu-intel.c', 'third_party/boringssl/crypto/cpu-ppc64le.c', 'third_party/boringssl/crypto/crypto.c', 'third_party/boringssl/crypto/curve25519/curve25519.c', 'third_party/boringssl/crypto/curve25519/spake25519.c', 'third_party/boringssl/crypto/curve25519/x25519-x86_64.c', 'third_party/boringssl/crypto/des/des.c', 'third_party/boringssl/crypto/dh/check.c', 'third_party/boringssl/crypto/dh/dh.c', 'third_party/boringssl/crypto/dh/dh_asn1.c', 'third_party/boringssl/crypto/dh/params.c', 'third_party/boringssl/crypto/digest/digest.c', 'third_party/boringssl/crypto/digest/digests.c', 'third_party/boringssl/crypto/dsa/dsa.c', 'third_party/boringssl/crypto/dsa/dsa_asn1.c', 'third_party/boringssl/crypto/ec/ec.c', 'third_party/boringssl/crypto/ec/ec_asn1.c', 'third_party/boringssl/crypto/ec/ec_key.c', 'third_party/boringssl/crypto/ec/ec_montgomery.c', 'third_party/boringssl/crypto/ec/oct.c', 'third_party/boringssl/crypto/ec/p224-64.c', 'third_party/boringssl/crypto/ec/p256-64.c', 'third_party/boringssl/crypto/ec/p256-x86_64.c', 'third_party/boringssl/crypto/ec/simple.c', 'third_party/boringssl/crypto/ec/util-64.c', 'third_party/boringssl/crypto/ec/wnaf.c', 'third_party/boringssl/crypto/ecdh/ecdh.c', 'third_party/boringssl/crypto/ecdsa/ecdsa.c', 'third_party/boringssl/crypto/ecdsa/ecdsa_asn1.c', 'third_party/boringssl/crypto/engine/engine.c', 'third_party/boringssl/crypto/err/err.c', 'third_party/boringssl/crypto/evp/digestsign.c', 'third_party/boringssl/crypto/evp/evp.c', 'third_party/boringssl/crypto/evp/evp_asn1.c', 'third_party/boringssl/crypto/evp/evp_ctx.c', 'third_party/boringssl/crypto/evp/p_dsa_asn1.c', 'third_party/boringssl/crypto/evp/p_ec.c', 'third_party/boringssl/crypto/evp/p_ec_asn1.c', 'third_party/boringssl/crypto/evp/p_rsa.c', 'third_party/boringssl/crypto/evp/p_rsa_asn1.c', 'third_party/boringssl/crypto/evp/pbkdf.c', 'third_party/boringssl/crypto/evp/print.c', 'third_party/boringssl/crypto/evp/sign.c', 'third_party/boringssl/crypto/ex_data.c', 'third_party/boringssl/crypto/hkdf/hkdf.c', 'third_party/boringssl/crypto/hmac/hmac.c', 'third_party/boringssl/crypto/lhash/lhash.c', 'third_party/boringssl/crypto/md4/md4.c', 'third_party/boringssl/crypto/md5/md5.c', 'third_party/boringssl/crypto/mem.c', 'third_party/boringssl/crypto/modes/cbc.c', 'third_party/boringssl/crypto/modes/cfb.c', 'third_party/boringssl/crypto/modes/ctr.c', 'third_party/boringssl/crypto/modes/gcm.c', 'third_party/boringssl/crypto/modes/ofb.c', 'third_party/boringssl/crypto/newhope/error_correction.c', 'third_party/boringssl/crypto/newhope/newhope.c', 'third_party/boringssl/crypto/newhope/ntt.c', 'third_party/boringssl/crypto/newhope/poly.c', 'third_party/boringssl/crypto/newhope/precomp.c', 'third_party/boringssl/crypto/newhope/reduce.c', 'third_party/boringssl/crypto/obj/obj.c', 'third_party/boringssl/crypto/obj/obj_xref.c', 'third_party/boringssl/crypto/pem/pem_all.c', 'third_party/boringssl/crypto/pem/pem_info.c', 'third_party/boringssl/crypto/pem/pem_lib.c', 'third_party/boringssl/crypto/pem/pem_oth.c', 'third_party/boringssl/crypto/pem/pem_pk8.c', 'third_party/boringssl/crypto/pem/pem_pkey.c', 'third_party/boringssl/crypto/pem/pem_x509.c', 'third_party/boringssl/crypto/pem/pem_xaux.c', 'third_party/boringssl/crypto/pkcs8/p5_pbe.c', 'third_party/boringssl/crypto/pkcs8/p5_pbev2.c', 'third_party/boringssl/crypto/pkcs8/p8_pkey.c', 'third_party/boringssl/crypto/pkcs8/pkcs8.c', 'third_party/boringssl/crypto/poly1305/poly1305.c', 'third_party/boringssl/crypto/poly1305/poly1305_arm.c', 'third_party/boringssl/crypto/poly1305/poly1305_vec.c', 'third_party/boringssl/crypto/rand/deterministic.c', 'third_party/boringssl/crypto/rand/rand.c', 'third_party/boringssl/crypto/rand/urandom.c', 'third_party/boringssl/crypto/rand/windows.c', 'third_party/boringssl/crypto/rc4/rc4.c', 'third_party/boringssl/crypto/refcount_c11.c', 'third_party/boringssl/crypto/refcount_lock.c', 'third_party/boringssl/crypto/rsa/blinding.c', 'third_party/boringssl/crypto/rsa/padding.c', 'third_party/boringssl/crypto/rsa/rsa.c', 'third_party/boringssl/crypto/rsa/rsa_asn1.c', 'third_party/boringssl/crypto/rsa/rsa_impl.c', 'third_party/boringssl/crypto/sha/sha1.c', 'third_party/boringssl/crypto/sha/sha256.c', 'third_party/boringssl/crypto/sha/sha512.c', 'third_party/boringssl/crypto/stack/stack.c', 'third_party/boringssl/crypto/thread.c', 'third_party/boringssl/crypto/thread_none.c', 'third_party/boringssl/crypto/thread_pthread.c', 'third_party/boringssl/crypto/thread_win.c', 'third_party/boringssl/crypto/time_support.c', 'third_party/boringssl/crypto/x509/a_digest.c', 'third_party/boringssl/crypto/x509/a_sign.c', 'third_party/boringssl/crypto/x509/a_strex.c', 'third_party/boringssl/crypto/x509/a_verify.c', 'third_party/boringssl/crypto/x509/algorithm.c', 'third_party/boringssl/crypto/x509/asn1_gen.c', 'third_party/boringssl/crypto/x509/by_dir.c', 'third_party/boringssl/crypto/x509/by_file.c', 'third_party/boringssl/crypto/x509/i2d_pr.c', 'third_party/boringssl/crypto/x509/pkcs7.c', 'third_party/boringssl/crypto/x509/rsa_pss.c', 'third_party/boringssl/crypto/x509/t_crl.c', 'third_party/boringssl/crypto/x509/t_req.c', 'third_party/boringssl/crypto/x509/t_x509.c', 'third_party/boringssl/crypto/x509/t_x509a.c', 'third_party/boringssl/crypto/x509/x509.c', 'third_party/boringssl/crypto/x509/x509_att.c', 'third_party/boringssl/crypto/x509/x509_cmp.c', 'third_party/boringssl/crypto/x509/x509_d2.c', 'third_party/boringssl/crypto/x509/x509_def.c', 'third_party/boringssl/crypto/x509/x509_ext.c', 'third_party/boringssl/crypto/x509/x509_lu.c', 'third_party/boringssl/crypto/x509/x509_obj.c', 'third_party/boringssl/crypto/x509/x509_r2x.c', 'third_party/boringssl/crypto/x509/x509_req.c', 'third_party/boringssl/crypto/x509/x509_set.c', 'third_party/boringssl/crypto/x509/x509_trs.c', 'third_party/boringssl/crypto/x509/x509_txt.c', 'third_party/boringssl/crypto/x509/x509_v3.c', 'third_party/boringssl/crypto/x509/x509_vfy.c', 'third_party/boringssl/crypto/x509/x509_vpm.c', 'third_party/boringssl/crypto/x509/x509cset.c', 'third_party/boringssl/crypto/x509/x509name.c', 'third_party/boringssl/crypto/x509/x509rset.c', 'third_party/boringssl/crypto/x509/x509spki.c', 'third_party/boringssl/crypto/x509/x509type.c', 'third_party/boringssl/crypto/x509/x_algor.c', 'third_party/boringssl/crypto/x509/x_all.c', 'third_party/boringssl/crypto/x509/x_attrib.c', 'third_party/boringssl/crypto/x509/x_crl.c', 'third_party/boringssl/crypto/x509/x_exten.c', 'third_party/boringssl/crypto/x509/x_info.c', 'third_party/boringssl/crypto/x509/x_name.c', 'third_party/boringssl/crypto/x509/x_pkey.c', 'third_party/boringssl/crypto/x509/x_pubkey.c', 'third_party/boringssl/crypto/x509/x_req.c', 'third_party/boringssl/crypto/x509/x_sig.c', 'third_party/boringssl/crypto/x509/x_spki.c', 'third_party/boringssl/crypto/x509/x_val.c', 'third_party/boringssl/crypto/x509/x_x509.c', 'third_party/boringssl/crypto/x509/x_x509a.c', 'third_party/boringssl/crypto/x509v3/pcy_cache.c', 'third_party/boringssl/crypto/x509v3/pcy_data.c', 'third_party/boringssl/crypto/x509v3/pcy_lib.c', 'third_party/boringssl/crypto/x509v3/pcy_map.c', 'third_party/boringssl/crypto/x509v3/pcy_node.c', 'third_party/boringssl/crypto/x509v3/pcy_tree.c', 'third_party/boringssl/crypto/x509v3/v3_akey.c', 'third_party/boringssl/crypto/x509v3/v3_akeya.c', 'third_party/boringssl/crypto/x509v3/v3_alt.c', 'third_party/boringssl/crypto/x509v3/v3_bcons.c', 'third_party/boringssl/crypto/x509v3/v3_bitst.c', 'third_party/boringssl/crypto/x509v3/v3_conf.c', 'third_party/boringssl/crypto/x509v3/v3_cpols.c', 'third_party/boringssl/crypto/x509v3/v3_crld.c', 'third_party/boringssl/crypto/x509v3/v3_enum.c', 'third_party/boringssl/crypto/x509v3/v3_extku.c', 'third_party/boringssl/crypto/x509v3/v3_genn.c', 'third_party/boringssl/crypto/x509v3/v3_ia5.c', 'third_party/boringssl/crypto/x509v3/v3_info.c', 'third_party/boringssl/crypto/x509v3/v3_int.c', 'third_party/boringssl/crypto/x509v3/v3_lib.c', 'third_party/boringssl/crypto/x509v3/v3_ncons.c', 'third_party/boringssl/crypto/x509v3/v3_pci.c', 'third_party/boringssl/crypto/x509v3/v3_pcia.c', 'third_party/boringssl/crypto/x509v3/v3_pcons.c', 'third_party/boringssl/crypto/x509v3/v3_pku.c', 'third_party/boringssl/crypto/x509v3/v3_pmaps.c', 'third_party/boringssl/crypto/x509v3/v3_prn.c', 'third_party/boringssl/crypto/x509v3/v3_purp.c', 'third_party/boringssl/crypto/x509v3/v3_skey.c', 'third_party/boringssl/crypto/x509v3/v3_sxnet.c', 'third_party/boringssl/crypto/x509v3/v3_utl.c', 'third_party/boringssl/ssl/custom_extensions.c', 'third_party/boringssl/ssl/d1_both.c', 'third_party/boringssl/ssl/d1_lib.c', 'third_party/boringssl/ssl/d1_pkt.c', 'third_party/boringssl/ssl/d1_srtp.c', 'third_party/boringssl/ssl/dtls_method.c', 'third_party/boringssl/ssl/dtls_record.c', 'third_party/boringssl/ssl/handshake_client.c', 'third_party/boringssl/ssl/handshake_server.c', 'third_party/boringssl/ssl/s3_both.c', 'third_party/boringssl/ssl/s3_enc.c', 'third_party/boringssl/ssl/s3_lib.c', 'third_party/boringssl/ssl/s3_pkt.c', 'third_party/boringssl/ssl/ssl_aead_ctx.c', 'third_party/boringssl/ssl/ssl_asn1.c', 'third_party/boringssl/ssl/ssl_buffer.c', 'third_party/boringssl/ssl/ssl_cert.c', 'third_party/boringssl/ssl/ssl_cipher.c', 'third_party/boringssl/ssl/ssl_ecdh.c', 'third_party/boringssl/ssl/ssl_file.c', 'third_party/boringssl/ssl/ssl_lib.c', 'third_party/boringssl/ssl/ssl_rsa.c', 'third_party/boringssl/ssl/ssl_session.c', 'third_party/boringssl/ssl/ssl_stat.c', 'third_party/boringssl/ssl/t1_enc.c', 'third_party/boringssl/ssl/t1_lib.c', 'third_party/boringssl/ssl/tls13_both.c', 'third_party/boringssl/ssl/tls13_client.c', 'third_party/boringssl/ssl/tls13_enc.c', 'third_party/boringssl/ssl/tls13_server.c', 'third_party/boringssl/ssl/tls_method.c', 'third_party/boringssl/ssl/tls_record.c', ] }, ] }], ['OS == "win" and runtime!="electron"', { 'targets': [ { # IMPORTANT WINDOWS BUILD INFORMATION # This library does not build on Windows without modifying the Node # development packages that node-gyp downloads in order to build. # Due to https://github.com/nodejs/node/issues/4932, the headers for # BoringSSL conflict with the OpenSSL headers included by default # when including the Node headers. The remedy for this is to remove # the OpenSSL headers, from the downloaded Node development package, # which is typically located in `.node-gyp` in your home directory. # # This is not true of Electron, which does not have OpenSSL headers. 'target_name': 'WINDOWS_BUILD_WARNING', 'rules': [ { 'rule_name': 'WINDOWS_BUILD_WARNING', 'extension': 'S', 'inputs': [ 'package.json' ], 'outputs': [ 'ignore_this_part' ], 'action': ['echo', 'IMPORTANT: Due to https://github.com/nodejs/node/issues/4932, to build this library on Windows, you must first remove <(node_root_dir)/include/node/openssl/'] } ] }, ] }], ['OS == "win"', { 'targets': [ # Only want to compile zlib under Windows { 'cflags': [ '-std=c99', '-Wall', '-Werror' ], 'target_name': 'z', 'product_prefix': 'lib', 'type': 'static_library', 'dependencies': [ ], 'sources': [ 'third_party/zlib/adler32.c', 'third_party/zlib/compress.c', 'third_party/zlib/crc32.c', 'third_party/zlib/deflate.c', 'third_party/zlib/gzclose.c', 'third_party/zlib/gzlib.c', 'third_party/zlib/gzread.c', 'third_party/zlib/gzwrite.c', 'third_party/zlib/infback.c', 'third_party/zlib/inffast.c', 'third_party/zlib/inflate.c', 'third_party/zlib/inftrees.c', 'third_party/zlib/trees.c', 'third_party/zlib/uncompr.c', 'third_party/zlib/zutil.c', ] }, ] }] ], 'targets': [ { 'cflags': [ '-std=c99', '-Wall', '-Werror' ], 'target_name': 'gpr', 'product_prefix': 'lib', 'type': 'static_library', 'dependencies': [ ], 'sources': [ 'src/core/lib/profiling/basic_timers.c', 'src/core/lib/profiling/stap_timers.c', 'src/core/lib/support/alloc.c', 'src/core/lib/support/arena.c', 'src/core/lib/support/atm.c', 'src/core/lib/support/avl.c', 'src/core/lib/support/backoff.c', 'src/core/lib/support/cmdline.c', 'src/core/lib/support/cpu_iphone.c', 'src/core/lib/support/cpu_linux.c', 'src/core/lib/support/cpu_posix.c', 'src/core/lib/support/cpu_windows.c', 'src/core/lib/support/env_linux.c', 'src/core/lib/support/env_posix.c', 'src/core/lib/support/env_windows.c', 'src/core/lib/support/histogram.c', 'src/core/lib/support/host_port.c', 'src/core/lib/support/log.c', 'src/core/lib/support/log_android.c', 'src/core/lib/support/log_linux.c', 'src/core/lib/support/log_posix.c', 'src/core/lib/support/log_windows.c', 'src/core/lib/support/mpscq.c', 'src/core/lib/support/murmur_hash.c', 'src/core/lib/support/stack_lockfree.c', 'src/core/lib/support/string.c', 'src/core/lib/support/string_posix.c', 'src/core/lib/support/string_util_windows.c', 'src/core/lib/support/string_windows.c', 'src/core/lib/support/subprocess_posix.c', 'src/core/lib/support/subprocess_windows.c', 'src/core/lib/support/sync.c', 'src/core/lib/support/sync_posix.c', 'src/core/lib/support/sync_windows.c', 'src/core/lib/support/thd.c', 'src/core/lib/support/thd_posix.c', 'src/core/lib/support/thd_windows.c', 'src/core/lib/support/time.c', 'src/core/lib/support/time_posix.c', 'src/core/lib/support/time_precise.c', 'src/core/lib/support/time_windows.c', 'src/core/lib/support/tls_pthread.c', 'src/core/lib/support/tmpfile_msys.c', 'src/core/lib/support/tmpfile_posix.c', 'src/core/lib/support/tmpfile_windows.c', 'src/core/lib/support/wrap_memcpy.c', ], "conditions": [ ['OS == "mac"', { 'xcode_settings': { 'MACOSX_DEPLOYMENT_TARGET': '10.9' } }] ] }, { 'cflags': [ '-std=c99', '-Wall', '-Werror' ], 'target_name': 'grpc', 'product_prefix': 'lib', 'type': 'static_library', 'dependencies': [ 'gpr', ], 'sources': [ 'src/core/lib/surface/init.c', 'src/core/lib/channel/channel_args.c', 'src/core/lib/channel/channel_stack.c', 'src/core/lib/channel/channel_stack_builder.c', 'src/core/lib/channel/compress_filter.c', 'src/core/lib/channel/connected_channel.c', 'src/core/lib/channel/deadline_filter.c', 'src/core/lib/channel/handshaker.c', 'src/core/lib/channel/handshaker_factory.c', 'src/core/lib/channel/handshaker_registry.c', 'src/core/lib/channel/http_client_filter.c', 'src/core/lib/channel/http_server_filter.c', 'src/core/lib/channel/message_size_filter.c', 'src/core/lib/compression/compression.c', 'src/core/lib/compression/message_compress.c', 'src/core/lib/debug/trace.c', 'src/core/lib/http/format_request.c', 'src/core/lib/http/httpcli.c', 'src/core/lib/http/parser.c', 'src/core/lib/iomgr/closure.c', 'src/core/lib/iomgr/combiner.c', 'src/core/lib/iomgr/endpoint.c', 'src/core/lib/iomgr/endpoint_pair_posix.c', 'src/core/lib/iomgr/endpoint_pair_uv.c', 'src/core/lib/iomgr/endpoint_pair_windows.c', 'src/core/lib/iomgr/error.c', 'src/core/lib/iomgr/ev_epoll_linux.c', 'src/core/lib/iomgr/ev_poll_posix.c', 'src/core/lib/iomgr/ev_posix.c', 'src/core/lib/iomgr/exec_ctx.c', 'src/core/lib/iomgr/executor.c', 'src/core/lib/iomgr/iocp_windows.c', 'src/core/lib/iomgr/iomgr.c', 'src/core/lib/iomgr/iomgr_posix.c', 'src/core/lib/iomgr/iomgr_uv.c', 'src/core/lib/iomgr/iomgr_windows.c', 'src/core/lib/iomgr/load_file.c', 'src/core/lib/iomgr/lockfree_event.c', 'src/core/lib/iomgr/network_status_tracker.c', 'src/core/lib/iomgr/polling_entity.c', 'src/core/lib/iomgr/pollset_set_uv.c', 'src/core/lib/iomgr/pollset_set_windows.c', 'src/core/lib/iomgr/pollset_uv.c', 'src/core/lib/iomgr/pollset_windows.c', 'src/core/lib/iomgr/resolve_address_posix.c', 'src/core/lib/iomgr/resolve_address_uv.c', 'src/core/lib/iomgr/resolve_address_windows.c', 'src/core/lib/iomgr/resource_quota.c', 'src/core/lib/iomgr/sockaddr_utils.c', 'src/core/lib/iomgr/socket_factory_posix.c', 'src/core/lib/iomgr/socket_mutator.c', 'src/core/lib/iomgr/socket_utils_common_posix.c', 'src/core/lib/iomgr/socket_utils_linux.c', 'src/core/lib/iomgr/socket_utils_posix.c', 'src/core/lib/iomgr/socket_utils_uv.c', 'src/core/lib/iomgr/socket_utils_windows.c', 'src/core/lib/iomgr/socket_windows.c', 'src/core/lib/iomgr/tcp_client_posix.c', 'src/core/lib/iomgr/tcp_client_uv.c', 'src/core/lib/iomgr/tcp_client_windows.c', 'src/core/lib/iomgr/tcp_posix.c', 'src/core/lib/iomgr/tcp_server_posix.c', 'src/core/lib/iomgr/tcp_server_utils_posix_common.c', 'src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c', 'src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c', 'src/core/lib/iomgr/tcp_server_uv.c', 'src/core/lib/iomgr/tcp_server_windows.c', 'src/core/lib/iomgr/tcp_uv.c', 'src/core/lib/iomgr/tcp_windows.c', 'src/core/lib/iomgr/time_averaged_stats.c', 'src/core/lib/iomgr/timer_generic.c', 'src/core/lib/iomgr/timer_heap.c', 'src/core/lib/iomgr/timer_uv.c', 'src/core/lib/iomgr/udp_server.c', 'src/core/lib/iomgr/unix_sockets_posix.c', 'src/core/lib/iomgr/unix_sockets_posix_noop.c', 'src/core/lib/iomgr/wakeup_fd_cv.c', 'src/core/lib/iomgr/wakeup_fd_eventfd.c', 'src/core/lib/iomgr/wakeup_fd_nospecial.c', 'src/core/lib/iomgr/wakeup_fd_pipe.c', 'src/core/lib/iomgr/wakeup_fd_posix.c', 'src/core/lib/iomgr/workqueue_uv.c', 'src/core/lib/iomgr/workqueue_windows.c', 'src/core/lib/json/json.c', 'src/core/lib/json/json_reader.c', 'src/core/lib/json/json_string.c', 'src/core/lib/json/json_writer.c', 'src/core/lib/slice/b64.c', 'src/core/lib/slice/percent_encoding.c', 'src/core/lib/slice/slice.c', 'src/core/lib/slice/slice_buffer.c', 'src/core/lib/slice/slice_hash_table.c', 'src/core/lib/slice/slice_intern.c', 'src/core/lib/slice/slice_string_helpers.c', 'src/core/lib/surface/alarm.c', 'src/core/lib/surface/api_trace.c', 'src/core/lib/surface/byte_buffer.c', 'src/core/lib/surface/byte_buffer_reader.c', 'src/core/lib/surface/call.c', 'src/core/lib/surface/call_details.c', 'src/core/lib/surface/call_log_batch.c', 'src/core/lib/surface/channel.c', 'src/core/lib/surface/channel_init.c', 'src/core/lib/surface/channel_ping.c', 'src/core/lib/surface/channel_stack_type.c', 'src/core/lib/surface/completion_queue.c', 'src/core/lib/surface/completion_queue_factory.c', 'src/core/lib/surface/event_string.c', 'src/core/lib/surface/lame_client.c', 'src/core/lib/surface/metadata_array.c', 'src/core/lib/surface/server.c', 'src/core/lib/surface/validate_metadata.c', 'src/core/lib/surface/version.c', 'src/core/lib/transport/bdp_estimator.c', 'src/core/lib/transport/byte_stream.c', 'src/core/lib/transport/connectivity_state.c', 'src/core/lib/transport/error_utils.c', 'src/core/lib/transport/metadata.c', 'src/core/lib/transport/metadata_batch.c', 'src/core/lib/transport/pid_controller.c', 'src/core/lib/transport/service_config.c', 'src/core/lib/transport/static_metadata.c', 'src/core/lib/transport/status_conversion.c', 'src/core/lib/transport/timeout_encoding.c', 'src/core/lib/transport/transport.c', 'src/core/lib/transport/transport_op_string.c', 'src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c', 'src/core/ext/transport/chttp2/transport/bin_decoder.c', 'src/core/ext/transport/chttp2/transport/bin_encoder.c', 'src/core/ext/transport/chttp2/transport/chttp2_plugin.c', 'src/core/ext/transport/chttp2/transport/chttp2_transport.c', 'src/core/ext/transport/chttp2/transport/frame_data.c', 'src/core/ext/transport/chttp2/transport/frame_goaway.c', 'src/core/ext/transport/chttp2/transport/frame_ping.c', 'src/core/ext/transport/chttp2/transport/frame_rst_stream.c', 'src/core/ext/transport/chttp2/transport/frame_settings.c', 'src/core/ext/transport/chttp2/transport/frame_window_update.c', 'src/core/ext/transport/chttp2/transport/hpack_encoder.c', 'src/core/ext/transport/chttp2/transport/hpack_parser.c', 'src/core/ext/transport/chttp2/transport/hpack_table.c', 'src/core/ext/transport/chttp2/transport/http2_settings.c', 'src/core/ext/transport/chttp2/transport/huffsyms.c', 'src/core/ext/transport/chttp2/transport/incoming_metadata.c', 'src/core/ext/transport/chttp2/transport/parsing.c', 'src/core/ext/transport/chttp2/transport/stream_lists.c', 'src/core/ext/transport/chttp2/transport/stream_map.c', 'src/core/ext/transport/chttp2/transport/varint.c', 'src/core/ext/transport/chttp2/transport/writing.c', 'src/core/ext/transport/chttp2/alpn/alpn.c', 'src/core/lib/http/httpcli_security_connector.c', 'src/core/lib/security/context/security_context.c', 'src/core/lib/security/credentials/composite/composite_credentials.c', 'src/core/lib/security/credentials/credentials.c', 'src/core/lib/security/credentials/credentials_metadata.c', 'src/core/lib/security/credentials/fake/fake_credentials.c', 'src/core/lib/security/credentials/google_default/credentials_generic.c', 'src/core/lib/security/credentials/google_default/google_default_credentials.c', 'src/core/lib/security/credentials/iam/iam_credentials.c', 'src/core/lib/security/credentials/jwt/json_token.c', 'src/core/lib/security/credentials/jwt/jwt_credentials.c', 'src/core/lib/security/credentials/jwt/jwt_verifier.c', 'src/core/lib/security/credentials/oauth2/oauth2_credentials.c', 'src/core/lib/security/credentials/plugin/plugin_credentials.c', 'src/core/lib/security/credentials/ssl/ssl_credentials.c', 'src/core/lib/security/transport/client_auth_filter.c', 'src/core/lib/security/transport/lb_targets_info.c', 'src/core/lib/security/transport/secure_endpoint.c', 'src/core/lib/security/transport/security_connector.c', 'src/core/lib/security/transport/security_handshaker.c', 'src/core/lib/security/transport/server_auth_filter.c', 'src/core/lib/security/transport/tsi_error.c', 'src/core/lib/security/util/json_util.c', 'src/core/lib/surface/init_secure.c', 'src/core/tsi/fake_transport_security.c', 'src/core/tsi/ssl_transport_security.c', 'src/core/tsi/transport_security.c', 'src/core/ext/transport/chttp2/server/chttp2_server.c', 'src/core/ext/transport/chttp2/client/secure/secure_channel_create.c', 'src/core/ext/filters/client_channel/channel_connectivity.c', 'src/core/ext/filters/client_channel/client_channel.c', 'src/core/ext/filters/client_channel/client_channel_factory.c', 'src/core/ext/filters/client_channel/client_channel_plugin.c', 'src/core/ext/filters/client_channel/connector.c', 'src/core/ext/filters/client_channel/http_connect_handshaker.c', 'src/core/ext/filters/client_channel/http_proxy.c', 'src/core/ext/filters/client_channel/lb_policy.c', 'src/core/ext/filters/client_channel/lb_policy_factory.c', 'src/core/ext/filters/client_channel/lb_policy_registry.c', 'src/core/ext/filters/client_channel/parse_address.c', 'src/core/ext/filters/client_channel/proxy_mapper.c', 'src/core/ext/filters/client_channel/proxy_mapper_registry.c', 'src/core/ext/filters/client_channel/resolver.c', 'src/core/ext/filters/client_channel/resolver_factory.c', 'src/core/ext/filters/client_channel/resolver_registry.c', 'src/core/ext/filters/client_channel/retry_throttle.c', 'src/core/ext/filters/client_channel/subchannel.c', 'src/core/ext/filters/client_channel/subchannel_index.c', 'src/core/ext/filters/client_channel/uri_parser.c', 'src/core/ext/transport/chttp2/client/chttp2_connector.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', 'third_party/nanopb/pb_decode.c', 'third_party/nanopb/pb_encode.c', 'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c', 'src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c', 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.c', 'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c', 'src/core/ext/filters/load_reporting/load_reporting.c', 'src/core/ext/filters/load_reporting/load_reporting_filter.c', 'src/core/ext/census/base_resources.c', 'src/core/ext/census/context.c', 'src/core/ext/census/gen/census.pb.c', 'src/core/ext/census/gen/trace_context.pb.c', 'src/core/ext/census/grpc_context.c', 'src/core/ext/census/grpc_filter.c', 'src/core/ext/census/grpc_plugin.c', 'src/core/ext/census/initialize.c', 'src/core/ext/census/mlog.c', 'src/core/ext/census/operation.c', 'src/core/ext/census/placeholders.c', 'src/core/ext/census/resource.c', 'src/core/ext/census/trace_context.c', 'src/core/ext/census/tracing.c', 'src/core/ext/filters/max_age/max_age_filter.c', 'src/core/plugin_registry/grpc_plugin_registry.c', ], "conditions": [ ['OS == "mac"', { 'xcode_settings': { 'MACOSX_DEPLOYMENT_TARGET': '10.9' } }] ] }, { 'include_dirs': [ "=5.5.0", "google/protobuf": "^v3.1.0" }, "require-dev": { "google/auth": "v0.9" }, "autoload": { "psr-4": { "Grpc\\": "src/php/lib/Grpc/" } } } grpc-1.3.2/config.m4000066400000000000000000001065721310511640000141610ustar00rootroot00000000000000PHP_ARG_ENABLE(grpc, whether to enable grpc support, [ --enable-grpc Enable grpc support]) if test "$PHP_GRPC" != "no"; then dnl Write more examples of tests here... dnl # --with-grpc -> add include path PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include) PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc) PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/boringssl/include) LIBS="-lpthread $LIBS" GRPC_SHARED_LIBADD="-lpthread $GRPC_SHARED_LIBADD" PHP_ADD_LIBRARY(pthread) PHP_ADD_LIBRARY(dl,,GRPC_SHARED_LIBADD) PHP_ADD_LIBRARY(dl) case $host in *darwin*) ;; *) PHP_ADD_LIBRARY(rt,,GRPC_SHARED_LIBADD) PHP_ADD_LIBRARY(rt) ;; esac PHP_NEW_EXTENSION(grpc, src/php/ext/grpc/byte_buffer.c \ src/php/ext/grpc/call.c \ src/php/ext/grpc/call_credentials.c \ src/php/ext/grpc/channel.c \ src/php/ext/grpc/channel_credentials.c \ src/php/ext/grpc/completion_queue.c \ src/php/ext/grpc/php_grpc.c \ src/php/ext/grpc/server.c \ src/php/ext/grpc/server_credentials.c \ src/php/ext/grpc/timeval.c \ src/core/lib/profiling/basic_timers.c \ src/core/lib/profiling/stap_timers.c \ src/core/lib/support/alloc.c \ src/core/lib/support/arena.c \ src/core/lib/support/atm.c \ src/core/lib/support/avl.c \ src/core/lib/support/backoff.c \ src/core/lib/support/cmdline.c \ src/core/lib/support/cpu_iphone.c \ src/core/lib/support/cpu_linux.c \ src/core/lib/support/cpu_posix.c \ src/core/lib/support/cpu_windows.c \ src/core/lib/support/env_linux.c \ src/core/lib/support/env_posix.c \ src/core/lib/support/env_windows.c \ src/core/lib/support/histogram.c \ src/core/lib/support/host_port.c \ src/core/lib/support/log.c \ src/core/lib/support/log_android.c \ src/core/lib/support/log_linux.c \ src/core/lib/support/log_posix.c \ src/core/lib/support/log_windows.c \ src/core/lib/support/mpscq.c \ src/core/lib/support/murmur_hash.c \ src/core/lib/support/stack_lockfree.c \ src/core/lib/support/string.c \ src/core/lib/support/string_posix.c \ src/core/lib/support/string_util_windows.c \ src/core/lib/support/string_windows.c \ src/core/lib/support/subprocess_posix.c \ src/core/lib/support/subprocess_windows.c \ src/core/lib/support/sync.c \ src/core/lib/support/sync_posix.c \ src/core/lib/support/sync_windows.c \ src/core/lib/support/thd.c \ src/core/lib/support/thd_posix.c \ src/core/lib/support/thd_windows.c \ src/core/lib/support/time.c \ src/core/lib/support/time_posix.c \ src/core/lib/support/time_precise.c \ src/core/lib/support/time_windows.c \ src/core/lib/support/tls_pthread.c \ src/core/lib/support/tmpfile_msys.c \ src/core/lib/support/tmpfile_posix.c \ src/core/lib/support/tmpfile_windows.c \ src/core/lib/support/wrap_memcpy.c \ src/core/lib/surface/init.c \ src/core/lib/channel/channel_args.c \ src/core/lib/channel/channel_stack.c \ src/core/lib/channel/channel_stack_builder.c \ src/core/lib/channel/compress_filter.c \ src/core/lib/channel/connected_channel.c \ src/core/lib/channel/deadline_filter.c \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/handshaker_factory.c \ src/core/lib/channel/handshaker_registry.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ src/core/lib/channel/message_size_filter.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ src/core/lib/debug/trace.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_uv.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ src/core/lib/iomgr/executor.c \ src/core/lib/iomgr/iocp_windows.c \ src/core/lib/iomgr/iomgr.c \ src/core/lib/iomgr/iomgr_posix.c \ src/core/lib/iomgr/iomgr_uv.c \ src/core/lib/iomgr/iomgr_windows.c \ src/core/lib/iomgr/load_file.c \ src/core/lib/iomgr/lockfree_event.c \ src/core/lib/iomgr/network_status_tracker.c \ src/core/lib/iomgr/polling_entity.c \ src/core/lib/iomgr/pollset_set_uv.c \ src/core/lib/iomgr/pollset_set_windows.c \ src/core/lib/iomgr/pollset_uv.c \ src/core/lib/iomgr/pollset_windows.c \ src/core/lib/iomgr/resolve_address_posix.c \ src/core/lib/iomgr/resolve_address_uv.c \ src/core/lib/iomgr/resolve_address_windows.c \ src/core/lib/iomgr/resource_quota.c \ src/core/lib/iomgr/sockaddr_utils.c \ src/core/lib/iomgr/socket_factory_posix.c \ src/core/lib/iomgr/socket_mutator.c \ src/core/lib/iomgr/socket_utils_common_posix.c \ src/core/lib/iomgr/socket_utils_linux.c \ src/core/lib/iomgr/socket_utils_posix.c \ src/core/lib/iomgr/socket_utils_uv.c \ src/core/lib/iomgr/socket_utils_windows.c \ src/core/lib/iomgr/socket_windows.c \ src/core/lib/iomgr/tcp_client_posix.c \ src/core/lib/iomgr/tcp_client_uv.c \ src/core/lib/iomgr/tcp_client_windows.c \ src/core/lib/iomgr/tcp_posix.c \ src/core/lib/iomgr/tcp_server_posix.c \ src/core/lib/iomgr/tcp_server_utils_posix_common.c \ src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ src/core/lib/iomgr/tcp_server_windows.c \ src/core/lib/iomgr/tcp_uv.c \ src/core/lib/iomgr/tcp_windows.c \ src/core/lib/iomgr/time_averaged_stats.c \ src/core/lib/iomgr/timer_generic.c \ src/core/lib/iomgr/timer_heap.c \ src/core/lib/iomgr/timer_uv.c \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ src/core/lib/iomgr/wakeup_fd_posix.c \ src/core/lib/iomgr/workqueue_uv.c \ src/core/lib/iomgr/workqueue_windows.c \ src/core/lib/json/json.c \ src/core/lib/json/json_reader.c \ src/core/lib/json/json_string.c \ src/core/lib/json/json_writer.c \ src/core/lib/slice/b64.c \ src/core/lib/slice/percent_encoding.c \ src/core/lib/slice/slice.c \ src/core/lib/slice/slice_buffer.c \ src/core/lib/slice/slice_hash_table.c \ src/core/lib/slice/slice_intern.c \ src/core/lib/slice/slice_string_helpers.c \ src/core/lib/surface/alarm.c \ src/core/lib/surface/api_trace.c \ src/core/lib/surface/byte_buffer.c \ src/core/lib/surface/byte_buffer_reader.c \ src/core/lib/surface/call.c \ src/core/lib/surface/call_details.c \ src/core/lib/surface/call_log_batch.c \ src/core/lib/surface/channel.c \ src/core/lib/surface/channel_init.c \ src/core/lib/surface/channel_ping.c \ src/core/lib/surface/channel_stack_type.c \ src/core/lib/surface/completion_queue.c \ src/core/lib/surface/completion_queue_factory.c \ src/core/lib/surface/event_string.c \ src/core/lib/surface/lame_client.c \ src/core/lib/surface/metadata_array.c \ src/core/lib/surface/server.c \ src/core/lib/surface/validate_metadata.c \ src/core/lib/surface/version.c \ src/core/lib/transport/bdp_estimator.c \ src/core/lib/transport/byte_stream.c \ src/core/lib/transport/connectivity_state.c \ src/core/lib/transport/error_utils.c \ src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/pid_controller.c \ src/core/lib/transport/service_config.c \ src/core/lib/transport/static_metadata.c \ src/core/lib/transport/status_conversion.c \ src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/transport.c \ src/core/lib/transport/transport_op_string.c \ src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c \ src/core/ext/transport/chttp2/transport/bin_decoder.c \ src/core/ext/transport/chttp2/transport/bin_encoder.c \ src/core/ext/transport/chttp2/transport/chttp2_plugin.c \ src/core/ext/transport/chttp2/transport/chttp2_transport.c \ src/core/ext/transport/chttp2/transport/frame_data.c \ src/core/ext/transport/chttp2/transport/frame_goaway.c \ src/core/ext/transport/chttp2/transport/frame_ping.c \ src/core/ext/transport/chttp2/transport/frame_rst_stream.c \ src/core/ext/transport/chttp2/transport/frame_settings.c \ src/core/ext/transport/chttp2/transport/frame_window_update.c \ src/core/ext/transport/chttp2/transport/hpack_encoder.c \ src/core/ext/transport/chttp2/transport/hpack_parser.c \ src/core/ext/transport/chttp2/transport/hpack_table.c \ src/core/ext/transport/chttp2/transport/http2_settings.c \ src/core/ext/transport/chttp2/transport/huffsyms.c \ src/core/ext/transport/chttp2/transport/incoming_metadata.c \ src/core/ext/transport/chttp2/transport/parsing.c \ src/core/ext/transport/chttp2/transport/stream_lists.c \ src/core/ext/transport/chttp2/transport/stream_map.c \ src/core/ext/transport/chttp2/transport/varint.c \ src/core/ext/transport/chttp2/transport/writing.c \ src/core/ext/transport/chttp2/alpn/alpn.c \ src/core/lib/http/httpcli_security_connector.c \ src/core/lib/security/context/security_context.c \ src/core/lib/security/credentials/composite/composite_credentials.c \ src/core/lib/security/credentials/credentials.c \ src/core/lib/security/credentials/credentials_metadata.c \ src/core/lib/security/credentials/fake/fake_credentials.c \ src/core/lib/security/credentials/google_default/credentials_generic.c \ src/core/lib/security/credentials/google_default/google_default_credentials.c \ src/core/lib/security/credentials/iam/iam_credentials.c \ src/core/lib/security/credentials/jwt/json_token.c \ src/core/lib/security/credentials/jwt/jwt_credentials.c \ src/core/lib/security/credentials/jwt/jwt_verifier.c \ src/core/lib/security/credentials/oauth2/oauth2_credentials.c \ src/core/lib/security/credentials/plugin/plugin_credentials.c \ src/core/lib/security/credentials/ssl/ssl_credentials.c \ src/core/lib/security/transport/client_auth_filter.c \ src/core/lib/security/transport/lb_targets_info.c \ src/core/lib/security/transport/secure_endpoint.c \ src/core/lib/security/transport/security_connector.c \ src/core/lib/security/transport/security_handshaker.c \ src/core/lib/security/transport/server_auth_filter.c \ src/core/lib/security/transport/tsi_error.c \ src/core/lib/security/util/json_util.c \ src/core/lib/surface/init_secure.c \ src/core/tsi/fake_transport_security.c \ src/core/tsi/ssl_transport_security.c \ src/core/tsi/transport_security.c \ src/core/ext/transport/chttp2/server/chttp2_server.c \ src/core/ext/transport/chttp2/client/secure/secure_channel_create.c \ src/core/ext/filters/client_channel/channel_connectivity.c \ src/core/ext/filters/client_channel/client_channel.c \ src/core/ext/filters/client_channel/client_channel_factory.c \ src/core/ext/filters/client_channel/client_channel_plugin.c \ src/core/ext/filters/client_channel/connector.c \ src/core/ext/filters/client_channel/http_connect_handshaker.c \ src/core/ext/filters/client_channel/http_proxy.c \ src/core/ext/filters/client_channel/lb_policy.c \ src/core/ext/filters/client_channel/lb_policy_factory.c \ src/core/ext/filters/client_channel/lb_policy_registry.c \ src/core/ext/filters/client_channel/parse_address.c \ src/core/ext/filters/client_channel/proxy_mapper.c \ src/core/ext/filters/client_channel/proxy_mapper_registry.c \ src/core/ext/filters/client_channel/resolver.c \ src/core/ext/filters/client_channel/resolver_factory.c \ src/core/ext/filters/client_channel/resolver_registry.c \ src/core/ext/filters/client_channel/retry_throttle.c \ src/core/ext/filters/client_channel/subchannel.c \ src/core/ext/filters/client_channel/subchannel_index.c \ src/core/ext/filters/client_channel/uri_parser.c \ src/core/ext/transport/chttp2/client/chttp2_connector.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ third_party/nanopb/pb_decode.c \ third_party/nanopb/pb_encode.c \ src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c \ src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c \ src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c \ src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.c \ src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c \ src/core/ext/filters/load_reporting/load_reporting.c \ src/core/ext/filters/load_reporting/load_reporting_filter.c \ src/core/ext/census/base_resources.c \ src/core/ext/census/context.c \ src/core/ext/census/gen/census.pb.c \ src/core/ext/census/gen/trace_context.pb.c \ src/core/ext/census/grpc_context.c \ src/core/ext/census/grpc_filter.c \ src/core/ext/census/grpc_plugin.c \ src/core/ext/census/initialize.c \ src/core/ext/census/mlog.c \ src/core/ext/census/operation.c \ src/core/ext/census/placeholders.c \ src/core/ext/census/resource.c \ src/core/ext/census/trace_context.c \ src/core/ext/census/tracing.c \ src/core/ext/filters/max_age/max_age_filter.c \ src/core/plugin_registry/grpc_plugin_registry.c \ src/boringssl/err_data.c \ third_party/boringssl/crypto/aes/aes.c \ third_party/boringssl/crypto/aes/mode_wrappers.c \ third_party/boringssl/crypto/asn1/a_bitstr.c \ third_party/boringssl/crypto/asn1/a_bool.c \ third_party/boringssl/crypto/asn1/a_d2i_fp.c \ third_party/boringssl/crypto/asn1/a_dup.c \ third_party/boringssl/crypto/asn1/a_enum.c \ third_party/boringssl/crypto/asn1/a_gentm.c \ third_party/boringssl/crypto/asn1/a_i2d_fp.c \ third_party/boringssl/crypto/asn1/a_int.c \ third_party/boringssl/crypto/asn1/a_mbstr.c \ third_party/boringssl/crypto/asn1/a_object.c \ third_party/boringssl/crypto/asn1/a_octet.c \ third_party/boringssl/crypto/asn1/a_print.c \ third_party/boringssl/crypto/asn1/a_strnid.c \ third_party/boringssl/crypto/asn1/a_time.c \ third_party/boringssl/crypto/asn1/a_type.c \ third_party/boringssl/crypto/asn1/a_utctm.c \ third_party/boringssl/crypto/asn1/a_utf8.c \ third_party/boringssl/crypto/asn1/asn1_lib.c \ third_party/boringssl/crypto/asn1/asn1_par.c \ third_party/boringssl/crypto/asn1/asn_pack.c \ third_party/boringssl/crypto/asn1/f_enum.c \ third_party/boringssl/crypto/asn1/f_int.c \ third_party/boringssl/crypto/asn1/f_string.c \ third_party/boringssl/crypto/asn1/t_bitst.c \ third_party/boringssl/crypto/asn1/tasn_dec.c \ third_party/boringssl/crypto/asn1/tasn_enc.c \ third_party/boringssl/crypto/asn1/tasn_fre.c \ third_party/boringssl/crypto/asn1/tasn_new.c \ third_party/boringssl/crypto/asn1/tasn_typ.c \ third_party/boringssl/crypto/asn1/tasn_utl.c \ third_party/boringssl/crypto/asn1/x_bignum.c \ third_party/boringssl/crypto/asn1/x_long.c \ third_party/boringssl/crypto/base64/base64.c \ third_party/boringssl/crypto/bio/bio.c \ third_party/boringssl/crypto/bio/bio_mem.c \ third_party/boringssl/crypto/bio/buffer.c \ third_party/boringssl/crypto/bio/connect.c \ third_party/boringssl/crypto/bio/fd.c \ third_party/boringssl/crypto/bio/file.c \ third_party/boringssl/crypto/bio/hexdump.c \ third_party/boringssl/crypto/bio/pair.c \ third_party/boringssl/crypto/bio/printf.c \ third_party/boringssl/crypto/bio/socket.c \ third_party/boringssl/crypto/bio/socket_helper.c \ third_party/boringssl/crypto/bn/add.c \ third_party/boringssl/crypto/bn/asm/x86_64-gcc.c \ third_party/boringssl/crypto/bn/bn.c \ third_party/boringssl/crypto/bn/bn_asn1.c \ third_party/boringssl/crypto/bn/cmp.c \ third_party/boringssl/crypto/bn/convert.c \ third_party/boringssl/crypto/bn/ctx.c \ third_party/boringssl/crypto/bn/div.c \ third_party/boringssl/crypto/bn/exponentiation.c \ third_party/boringssl/crypto/bn/gcd.c \ third_party/boringssl/crypto/bn/generic.c \ third_party/boringssl/crypto/bn/kronecker.c \ third_party/boringssl/crypto/bn/montgomery.c \ third_party/boringssl/crypto/bn/montgomery_inv.c \ third_party/boringssl/crypto/bn/mul.c \ third_party/boringssl/crypto/bn/prime.c \ third_party/boringssl/crypto/bn/random.c \ third_party/boringssl/crypto/bn/rsaz_exp.c \ third_party/boringssl/crypto/bn/shift.c \ third_party/boringssl/crypto/bn/sqrt.c \ third_party/boringssl/crypto/buf/buf.c \ third_party/boringssl/crypto/bytestring/asn1_compat.c \ third_party/boringssl/crypto/bytestring/ber.c \ third_party/boringssl/crypto/bytestring/cbb.c \ third_party/boringssl/crypto/bytestring/cbs.c \ third_party/boringssl/crypto/chacha/chacha.c \ third_party/boringssl/crypto/cipher/aead.c \ third_party/boringssl/crypto/cipher/cipher.c \ third_party/boringssl/crypto/cipher/derive_key.c \ third_party/boringssl/crypto/cipher/e_aes.c \ third_party/boringssl/crypto/cipher/e_chacha20poly1305.c \ third_party/boringssl/crypto/cipher/e_des.c \ third_party/boringssl/crypto/cipher/e_null.c \ third_party/boringssl/crypto/cipher/e_rc2.c \ third_party/boringssl/crypto/cipher/e_rc4.c \ third_party/boringssl/crypto/cipher/e_ssl3.c \ third_party/boringssl/crypto/cipher/e_tls.c \ third_party/boringssl/crypto/cipher/tls_cbc.c \ third_party/boringssl/crypto/cmac/cmac.c \ third_party/boringssl/crypto/conf/conf.c \ third_party/boringssl/crypto/cpu-aarch64-linux.c \ third_party/boringssl/crypto/cpu-arm-linux.c \ third_party/boringssl/crypto/cpu-arm.c \ third_party/boringssl/crypto/cpu-intel.c \ third_party/boringssl/crypto/cpu-ppc64le.c \ third_party/boringssl/crypto/crypto.c \ third_party/boringssl/crypto/curve25519/curve25519.c \ third_party/boringssl/crypto/curve25519/spake25519.c \ third_party/boringssl/crypto/curve25519/x25519-x86_64.c \ third_party/boringssl/crypto/des/des.c \ third_party/boringssl/crypto/dh/check.c \ third_party/boringssl/crypto/dh/dh.c \ third_party/boringssl/crypto/dh/dh_asn1.c \ third_party/boringssl/crypto/dh/params.c \ third_party/boringssl/crypto/digest/digest.c \ third_party/boringssl/crypto/digest/digests.c \ third_party/boringssl/crypto/dsa/dsa.c \ third_party/boringssl/crypto/dsa/dsa_asn1.c \ third_party/boringssl/crypto/ec/ec.c \ third_party/boringssl/crypto/ec/ec_asn1.c \ third_party/boringssl/crypto/ec/ec_key.c \ third_party/boringssl/crypto/ec/ec_montgomery.c \ third_party/boringssl/crypto/ec/oct.c \ third_party/boringssl/crypto/ec/p224-64.c \ third_party/boringssl/crypto/ec/p256-64.c \ third_party/boringssl/crypto/ec/p256-x86_64.c \ third_party/boringssl/crypto/ec/simple.c \ third_party/boringssl/crypto/ec/util-64.c \ third_party/boringssl/crypto/ec/wnaf.c \ third_party/boringssl/crypto/ecdh/ecdh.c \ third_party/boringssl/crypto/ecdsa/ecdsa.c \ third_party/boringssl/crypto/ecdsa/ecdsa_asn1.c \ third_party/boringssl/crypto/engine/engine.c \ third_party/boringssl/crypto/err/err.c \ third_party/boringssl/crypto/evp/digestsign.c \ third_party/boringssl/crypto/evp/evp.c \ third_party/boringssl/crypto/evp/evp_asn1.c \ third_party/boringssl/crypto/evp/evp_ctx.c \ third_party/boringssl/crypto/evp/p_dsa_asn1.c \ third_party/boringssl/crypto/evp/p_ec.c \ third_party/boringssl/crypto/evp/p_ec_asn1.c \ third_party/boringssl/crypto/evp/p_rsa.c \ third_party/boringssl/crypto/evp/p_rsa_asn1.c \ third_party/boringssl/crypto/evp/pbkdf.c \ third_party/boringssl/crypto/evp/print.c \ third_party/boringssl/crypto/evp/sign.c \ third_party/boringssl/crypto/ex_data.c \ third_party/boringssl/crypto/hkdf/hkdf.c \ third_party/boringssl/crypto/hmac/hmac.c \ third_party/boringssl/crypto/lhash/lhash.c \ third_party/boringssl/crypto/md4/md4.c \ third_party/boringssl/crypto/md5/md5.c \ third_party/boringssl/crypto/mem.c \ third_party/boringssl/crypto/modes/cbc.c \ third_party/boringssl/crypto/modes/cfb.c \ third_party/boringssl/crypto/modes/ctr.c \ third_party/boringssl/crypto/modes/gcm.c \ third_party/boringssl/crypto/modes/ofb.c \ third_party/boringssl/crypto/newhope/error_correction.c \ third_party/boringssl/crypto/newhope/newhope.c \ third_party/boringssl/crypto/newhope/ntt.c \ third_party/boringssl/crypto/newhope/poly.c \ third_party/boringssl/crypto/newhope/precomp.c \ third_party/boringssl/crypto/newhope/reduce.c \ third_party/boringssl/crypto/obj/obj.c \ third_party/boringssl/crypto/obj/obj_xref.c \ third_party/boringssl/crypto/pem/pem_all.c \ third_party/boringssl/crypto/pem/pem_info.c \ third_party/boringssl/crypto/pem/pem_lib.c \ third_party/boringssl/crypto/pem/pem_oth.c \ third_party/boringssl/crypto/pem/pem_pk8.c \ third_party/boringssl/crypto/pem/pem_pkey.c \ third_party/boringssl/crypto/pem/pem_x509.c \ third_party/boringssl/crypto/pem/pem_xaux.c \ third_party/boringssl/crypto/pkcs8/p5_pbe.c \ third_party/boringssl/crypto/pkcs8/p5_pbev2.c \ third_party/boringssl/crypto/pkcs8/p8_pkey.c \ third_party/boringssl/crypto/pkcs8/pkcs8.c \ third_party/boringssl/crypto/poly1305/poly1305.c \ third_party/boringssl/crypto/poly1305/poly1305_arm.c \ third_party/boringssl/crypto/poly1305/poly1305_vec.c \ third_party/boringssl/crypto/rand/deterministic.c \ third_party/boringssl/crypto/rand/rand.c \ third_party/boringssl/crypto/rand/urandom.c \ third_party/boringssl/crypto/rand/windows.c \ third_party/boringssl/crypto/rc4/rc4.c \ third_party/boringssl/crypto/refcount_c11.c \ third_party/boringssl/crypto/refcount_lock.c \ third_party/boringssl/crypto/rsa/blinding.c \ third_party/boringssl/crypto/rsa/padding.c \ third_party/boringssl/crypto/rsa/rsa.c \ third_party/boringssl/crypto/rsa/rsa_asn1.c \ third_party/boringssl/crypto/rsa/rsa_impl.c \ third_party/boringssl/crypto/sha/sha1.c \ third_party/boringssl/crypto/sha/sha256.c \ third_party/boringssl/crypto/sha/sha512.c \ third_party/boringssl/crypto/stack/stack.c \ third_party/boringssl/crypto/thread.c \ third_party/boringssl/crypto/thread_none.c \ third_party/boringssl/crypto/thread_pthread.c \ third_party/boringssl/crypto/thread_win.c \ third_party/boringssl/crypto/time_support.c \ third_party/boringssl/crypto/x509/a_digest.c \ third_party/boringssl/crypto/x509/a_sign.c \ third_party/boringssl/crypto/x509/a_strex.c \ third_party/boringssl/crypto/x509/a_verify.c \ third_party/boringssl/crypto/x509/algorithm.c \ third_party/boringssl/crypto/x509/asn1_gen.c \ third_party/boringssl/crypto/x509/by_dir.c \ third_party/boringssl/crypto/x509/by_file.c \ third_party/boringssl/crypto/x509/i2d_pr.c \ third_party/boringssl/crypto/x509/pkcs7.c \ third_party/boringssl/crypto/x509/rsa_pss.c \ third_party/boringssl/crypto/x509/t_crl.c \ third_party/boringssl/crypto/x509/t_req.c \ third_party/boringssl/crypto/x509/t_x509.c \ third_party/boringssl/crypto/x509/t_x509a.c \ third_party/boringssl/crypto/x509/x509.c \ third_party/boringssl/crypto/x509/x509_att.c \ third_party/boringssl/crypto/x509/x509_cmp.c \ third_party/boringssl/crypto/x509/x509_d2.c \ third_party/boringssl/crypto/x509/x509_def.c \ third_party/boringssl/crypto/x509/x509_ext.c \ third_party/boringssl/crypto/x509/x509_lu.c \ third_party/boringssl/crypto/x509/x509_obj.c \ third_party/boringssl/crypto/x509/x509_r2x.c \ third_party/boringssl/crypto/x509/x509_req.c \ third_party/boringssl/crypto/x509/x509_set.c \ third_party/boringssl/crypto/x509/x509_trs.c \ third_party/boringssl/crypto/x509/x509_txt.c \ third_party/boringssl/crypto/x509/x509_v3.c \ third_party/boringssl/crypto/x509/x509_vfy.c \ third_party/boringssl/crypto/x509/x509_vpm.c \ third_party/boringssl/crypto/x509/x509cset.c \ third_party/boringssl/crypto/x509/x509name.c \ third_party/boringssl/crypto/x509/x509rset.c \ third_party/boringssl/crypto/x509/x509spki.c \ third_party/boringssl/crypto/x509/x509type.c \ third_party/boringssl/crypto/x509/x_algor.c \ third_party/boringssl/crypto/x509/x_all.c \ third_party/boringssl/crypto/x509/x_attrib.c \ third_party/boringssl/crypto/x509/x_crl.c \ third_party/boringssl/crypto/x509/x_exten.c \ third_party/boringssl/crypto/x509/x_info.c \ third_party/boringssl/crypto/x509/x_name.c \ third_party/boringssl/crypto/x509/x_pkey.c \ third_party/boringssl/crypto/x509/x_pubkey.c \ third_party/boringssl/crypto/x509/x_req.c \ third_party/boringssl/crypto/x509/x_sig.c \ third_party/boringssl/crypto/x509/x_spki.c \ third_party/boringssl/crypto/x509/x_val.c \ third_party/boringssl/crypto/x509/x_x509.c \ third_party/boringssl/crypto/x509/x_x509a.c \ third_party/boringssl/crypto/x509v3/pcy_cache.c \ third_party/boringssl/crypto/x509v3/pcy_data.c \ third_party/boringssl/crypto/x509v3/pcy_lib.c \ third_party/boringssl/crypto/x509v3/pcy_map.c \ third_party/boringssl/crypto/x509v3/pcy_node.c \ third_party/boringssl/crypto/x509v3/pcy_tree.c \ third_party/boringssl/crypto/x509v3/v3_akey.c \ third_party/boringssl/crypto/x509v3/v3_akeya.c \ third_party/boringssl/crypto/x509v3/v3_alt.c \ third_party/boringssl/crypto/x509v3/v3_bcons.c \ third_party/boringssl/crypto/x509v3/v3_bitst.c \ third_party/boringssl/crypto/x509v3/v3_conf.c \ third_party/boringssl/crypto/x509v3/v3_cpols.c \ third_party/boringssl/crypto/x509v3/v3_crld.c \ third_party/boringssl/crypto/x509v3/v3_enum.c \ third_party/boringssl/crypto/x509v3/v3_extku.c \ third_party/boringssl/crypto/x509v3/v3_genn.c \ third_party/boringssl/crypto/x509v3/v3_ia5.c \ third_party/boringssl/crypto/x509v3/v3_info.c \ third_party/boringssl/crypto/x509v3/v3_int.c \ third_party/boringssl/crypto/x509v3/v3_lib.c \ third_party/boringssl/crypto/x509v3/v3_ncons.c \ third_party/boringssl/crypto/x509v3/v3_pci.c \ third_party/boringssl/crypto/x509v3/v3_pcia.c \ third_party/boringssl/crypto/x509v3/v3_pcons.c \ third_party/boringssl/crypto/x509v3/v3_pku.c \ third_party/boringssl/crypto/x509v3/v3_pmaps.c \ third_party/boringssl/crypto/x509v3/v3_prn.c \ third_party/boringssl/crypto/x509v3/v3_purp.c \ third_party/boringssl/crypto/x509v3/v3_skey.c \ third_party/boringssl/crypto/x509v3/v3_sxnet.c \ third_party/boringssl/crypto/x509v3/v3_utl.c \ third_party/boringssl/ssl/custom_extensions.c \ third_party/boringssl/ssl/d1_both.c \ third_party/boringssl/ssl/d1_lib.c \ third_party/boringssl/ssl/d1_pkt.c \ third_party/boringssl/ssl/d1_srtp.c \ third_party/boringssl/ssl/dtls_method.c \ third_party/boringssl/ssl/dtls_record.c \ third_party/boringssl/ssl/handshake_client.c \ third_party/boringssl/ssl/handshake_server.c \ third_party/boringssl/ssl/s3_both.c \ third_party/boringssl/ssl/s3_enc.c \ third_party/boringssl/ssl/s3_lib.c \ third_party/boringssl/ssl/s3_pkt.c \ third_party/boringssl/ssl/ssl_aead_ctx.c \ third_party/boringssl/ssl/ssl_asn1.c \ third_party/boringssl/ssl/ssl_buffer.c \ third_party/boringssl/ssl/ssl_cert.c \ third_party/boringssl/ssl/ssl_cipher.c \ third_party/boringssl/ssl/ssl_ecdh.c \ third_party/boringssl/ssl/ssl_file.c \ third_party/boringssl/ssl/ssl_lib.c \ third_party/boringssl/ssl/ssl_rsa.c \ third_party/boringssl/ssl/ssl_session.c \ third_party/boringssl/ssl/ssl_stat.c \ third_party/boringssl/ssl/t1_enc.c \ third_party/boringssl/ssl/t1_lib.c \ third_party/boringssl/ssl/tls13_both.c \ third_party/boringssl/ssl/tls13_client.c \ third_party/boringssl/ssl/tls13_enc.c \ third_party/boringssl/ssl/tls13_server.c \ third_party/boringssl/ssl/tls_method.c \ third_party/boringssl/ssl/tls_record.c \ , $ext_shared, , -Wall -Werror \ -Wno-parentheses-equality -Wno-unused-value -std=c11 \ -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN \ -D_HAS_EXCEPTIONS=0 -DNOMINMAX -DGRPC_ARES=0) PHP_ADD_BUILD_DIR($ext_builddir/src/php/ext/grpc) PHP_ADD_BUILD_DIR($ext_builddir/src/boringssl) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/census) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/census/gen) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/grpclb) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/pick_first) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/round_robin) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/resolver/dns/c_ares) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/resolver/dns/native) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/resolver/sockaddr) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/load_reporting) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/max_age) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/alpn) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/client) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/client/insecure) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/client/secure) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server/insecure) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server/secure) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/transport) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/channel) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/compression) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/debug) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/http) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/iomgr) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/json) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/profiling) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/context) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/composite) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/fake) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/google_default) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/iam) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/jwt) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/oauth2) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/plugin) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/ssl) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/transport) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/util) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/slice) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/support) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/surface) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/transport) PHP_ADD_BUILD_DIR($ext_builddir/src/core/plugin_registry) PHP_ADD_BUILD_DIR($ext_builddir/src/core/tsi) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/aes) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/asn1) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/base64) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/bio) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/bn) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/bn/asm) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/buf) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/bytestring) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/chacha) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/cipher) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/cmac) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/conf) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/curve25519) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/des) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/dh) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/digest) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/dsa) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/ec) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/ecdh) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/ecdsa) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/engine) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/err) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/evp) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/hkdf) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/hmac) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/lhash) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/md4) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/md5) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/modes) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/newhope) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/obj) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/pem) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/pkcs8) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/poly1305) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/rand) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/rc4) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/rsa) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/sha) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/stack) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/x509) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/x509v3) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/ssl) PHP_ADD_BUILD_DIR($ext_builddir/third_party/nanopb) fi grpc-1.3.2/doc/000077500000000000000000000000001310511640000132045ustar00rootroot00000000000000grpc-1.3.2/doc/.gitignore000066400000000000000000000000141310511640000151670ustar00rootroot00000000000000build/ src/ grpc-1.3.2/doc/PROTOCOL-HTTP2.md000066400000000000000000000347251310511640000156410ustar00rootroot00000000000000# gRPC over HTTP2 ## Introduction This document serves as a detailed description for an implementation of gRPC carried over HTTP2 draft 17 framing. It assumes familiarity with the HTTP2 specification. ## Protocol Production rules are using ABNF syntax. ### Outline The following is the general sequence of message atoms in a GRPC request & response message stream * Request → Request-Headers \*Length-Prefixed-Message EOS * Response → (Response-Headers \*Length-Prefixed-Message Trailers) / Trailers-Only ### Requests * Request → Request-Headers \*Length-Prefixed-Message EOS Request-Headers are delivered as HTTP2 headers in HEADERS + CONTINUATION frames. * **Request-Headers** → Call-Definition \*Custom-Metadata * **Call-Definition** → Method Scheme Path TE [Authority] [Timeout] Content-Type [Message-Type] [Message-Encoding] [Message-Accept-Encoding] [User-Agent] * **Method** → ":method POST" * **Scheme** → ":scheme " ("http" / "https") * **Path** → ":path" {_path identifying method within exposed API_} * **Authority** → ":authority" {_virtual host name of authority_} * **TE** → "te" "trailers" # Used to detect incompatible proxies * **Timeout** → "grpc-timeout" TimeoutValue TimeoutUnit * **TimeoutValue** → {_positive integer as ASCII string of at most 8 digits_} * **TimeoutUnit** → Hour / Minute / Second / Millisecond / Microsecond / Nanosecond * **Hour** → "H" * **Minute** → "M" * **Second** → "S" * **Millisecond** → "m" * **Microsecond** → "u" * **Nanosecond** → "n" * **Content-Type** → "content-type" "application/grpc" [("+proto" / "+json" / {_custom_})] * **Content-Coding** → "identity" / "gzip" / "deflate" / "snappy" / {_custom_} * **Message-Encoding** → "grpc-encoding" Content-Coding * **Message-Accept-Encoding** → "grpc-accept-encoding" Content-Coding \*("," Content-Coding) * **User-Agent** → "user-agent" {_structured user-agent string_} * **Message-Type** → "grpc-message-type" {_type name for message schema_} * **Custom-Metadata** → Binary-Header / ASCII-Header * **Binary-Header** → {Header-Name "-bin" } {_base64 encoded value_} * **ASCII-Header** → Header-Name ASCII-Value * **Header-Name** → 1\*( %x30-39 / %x61-7A / "\_" / "-" / ".") ; 0-9 a-z \_ - . * **ASCII-Value** → 1\*( %x20-%x7E ) ; space and printable ASCII HTTP2 requires that reserved headers, ones starting with ":" appear before all other headers. Additionally implementations should send **Timeout** immediately after the reserved headers and they should send the **Call-Definition** headers before sending **Custom-Metadata**. If **Timeout** is omitted a server should assume an infinite timeout. Client implementations are free to send a default minimum timeout based on their deployment requirements. **Custom-Metadata** is an arbitrary set of key-value pairs defined by the application layer. Header names starting with "grpc-" but not listed here are reserved for future GRPC use and should not be used by applications as **Custom-Metadata**. Note that HTTP2 does not allow arbitrary octet sequences for header values so binary header values must be encoded using Base64 as per https://tools.ietf.org/html/rfc4648#section-4. Implementations MUST accept padded and un-padded values and should emit un-padded values. Applications define binary headers by having their names end with "-bin". Runtime libraries use this suffix to detect binary headers and properly apply base64 encoding & decoding as headers are sent and received. **Custom-Metadata** header order is not guaranteed to be preserved except for values with duplicate header names. Duplicate header names may have their values joined with "," as the delimiter and be considered semantically equivalent. Implementations must split **Binary-Header**s on "," before decoding the Base64-encoded values. **ASCII-Value** should not have leading or trailing whitespace. If it contains leading or trailing whitespace, it may be stripped. The **ASCII-Value** character range defined is more strict than HTTP. Implementations must not error due to receiving an invalid **ASCII-Value** that's a valid **field-value** in HTTP, but the precise behavior is not strictly defined: they may throw the value away or accept the value. If accepted, care must be taken to make sure that the application is permitted to echo the value back as metadata. For example, if the metadata is provided to the application as a list in a request, the application should not trigger an error by providing that same list as the metadata in the response. Servers may limit the size of **Request-Headers**, with a default of 8 KiB suggested. Implementations are encouraged to compute total header size like HTTP/2's `SETTINGS_MAX_HEADER_LIST_SIZE`: the sum of all header fields, for each field the sum of the uncompressed field name and value lengths plus 32, with binary values' lengths being post-Base64. The repeated sequence of **Length-Prefixed-Message** items is delivered in DATA frames * **Length-Prefixed-Message** → Compressed-Flag Message-Length Message * **Compressed-Flag** → 0 / 1 # encoded as 1 byte unsigned integer * **Message-Length** → {_length of Message_} # encoded as 4 byte unsigned integer * **Message** → \*{binary octet} A **Compressed-Flag** value of 1 indicates that the binary octet sequence of **Message** is compressed using the mechanism declared by the **Message-Encoding** header. A value of 0 indicates that no encoding of **Message** bytes has occurred. Compression contexts are NOT maintained over message boundaries, implementations must create a new context for each message in the stream. If the **Message-Encoding** header is omitted then the **Compressed-Flag** must be 0. For requests, **EOS** (end-of-stream) is indicated by the presence of the END_STREAM flag on the last received DATA frame. In scenarios where the **Request** stream needs to be closed but no data remains to be sent implementations MUST send an empty DATA frame with this flag set. ### Responses * **Response** → (Response-Headers \*Length-Prefixed-Message Trailers) / Trailers-Only * **Response-Headers** → HTTP-Status [Message-Encoding] [Message-Accept-Encoding] Content-Type \*Custom-Metadata * **Trailers-Only** → HTTP-Status Content-Type Trailers * **Trailers** → Status [Status-Message] \*Custom-Metadata * **HTTP-Status** → ":status 200" * **Status** → "grpc-status" 1\*DIGIT ; 0-9 * **Status-Message** → "grpc-message" Percent-Encoded * **Percent-Encoded** → 1\*(Percent-Byte-Unencoded / Percent-Byte-Encoded) * **Percent-Byte-Unencoded** → 1\*( %x20-%x24 / %x26-%x7E ) ; space and VCHAR, except % * **Percent-Byte-Encoded** → "%" 2HEXDIGIT ; 0-9 A-F **Response-Headers** & **Trailers-Only** are each delivered in a single HTTP2 HEADERS frame block. Most responses are expected to have both headers and trailers but **Trailers-Only** is permitted for calls that produce an immediate error. Status must be sent in **Trailers** even if the status code is OK. For responses end-of-stream is indicated by the presence of the END_STREAM flag on the last received HEADERS frame that carries **Trailers**. Implementations should expect broken deployments to send non-200 HTTP status codes in responses as well as a variety of non-GRPC content-types and to omit **Status** & **Status-Message**. Implementations must synthesize a **Status** & **Status-Message** to propagate to the application layer when this occurs. Clients may limit the size of **Response-Headers**, **Trailers**, and **Trailers-Only**, with a default of 8 KiB each suggested. The value portion of **Status** is a decimal-encoded integer as an ASCII string, without any leading zeros. The value portion of **Status-Message** is conceptually a Unicode string description of the error, physically encoded as UTF-8 followed by percent-encoding. Percent-encoding is specified in [RFC 3986 §2.1](https://tools.ietf.org/html/rfc3986#section-2.1), although the form used here has different restricted characters. When decoding invalid values, implementations MUST NOT error or throw away the message. At worst, the implementation can abort decoding the status message altogether such that the user would received the raw percent-encoded form. Alternatively, the implementation can decode valid portions while leaving broken %-encodings as-is or replacing them with a replacement character (e.g., '?' or the Unicode replacement character). #### Example Sample unary-call showing HTTP2 framing sequence **Request** ``` HEADERS (flags = END_HEADERS) :method = POST :scheme = http :path = /google.pubsub.v2.PublisherService/CreateTopic :authority = pubsub.googleapis.com grpc-timeout = 1S content-type = application/grpc+proto grpc-encoding = gzip authorization = Bearer y235.wef315yfh138vh31hv93hv8h3v DATA (flags = END_STREAM) ``` **Response** ``` HEADERS (flags = END_HEADERS) :status = 200 grpc-encoding = gzip content-type = application/grpc+proto DATA HEADERS (flags = END_STREAM, END_HEADERS) grpc-status = 0 # OK trace-proto-bin = jher831yy13JHy3hc ``` #### User Agents While the protocol does not require a user-agent to function it is recommended that clients provide a structured user-agent string that provides a basic description of the calling library, version & platform to facilitate issue diagnosis in heterogeneous environments. The following structure is recommended to library developers ``` User-Agent → "grpc-" Language ?("-" Variant) "/" Version ?( " (" *(AdditionalProperty ";") ")" ) ``` E.g. ``` grpc-java/1.2.3 grpc-ruby/1.2.3 grpc-ruby-jruby/1.3.4 grpc-java-android/0.9.1 (gingerbread/1.2.4; nexus5; tmobile) ``` #### Idempotency and Retries Unless explicitly defined to be, gRPC Calls are not assumed to be idempotent. Specifically: * Calls that cannot be proven to have started will not be retried. * There is no mechanisim for duplicate suppression as it is not necessary. * Calls that are marked as idempotent may be sent multiple times. #### HTTP2 Transport Mapping ##### Stream Identification All GRPC calls need to specify an internal ID. We will use HTTP2 stream-ids as call identifiers in this scheme. NOTE: These id’s are contextual to an open HTTP2 session and will not be unique within a given process that is handling more than one HTTP2 session nor can they be used as GUIDs. ##### Data Frames DATA frame boundaries have no relation to **Length-Prefixed-Message** boundaries and implementations should make no assumptions about their alignment. ##### Errors When an application or runtime error occurs during an RPC a **Status** and **Status-Message** are delivered in **Trailers**. In some cases it is possible that the framing of the message stream has become corrupt and the RPC runtime will choose to use an **RST_STREAM** frame to indicate this state to its peer. RPC runtime implementations should interpret RST_STREAM as immediate full-closure of the stream and should propagate an error up to the calling application layer. The following mapping from RST_STREAM error codes to GRPC error codes is applied. HTTP2 Code|GRPC Code ----------|----------- NO_ERROR(0)|INTERNAL - An explicit GRPC status of OK should have been sent but this might be used to aggressively lameduck in some scenarios. PROTOCOL_ERROR(1)|INTERNAL INTERNAL_ERROR(2)|INTERNAL FLOW_CONTROL_ERROR(3)|INTERNAL SETTINGS_TIMEOUT(4)|INTERNAL STREAM_CLOSED|No mapping as there is no open stream to propagate to. Implementations should log. FRAME_SIZE_ERROR|INTERNAL REFUSED_STREAM|UNAVAILABLE - Indicates that no processing occurred and the request can be retried, possibly elsewhere. CANCEL(8)|Mapped to call cancellation when sent by a client.Mapped to CANCELLED when sent by a server. Note that servers should only use this mechanism when they need to cancel a call but the payload byte sequence is incomplete. COMPRESSION_ERROR|INTERNAL CONNECT_ERROR|INTERNAL ENHANCE_YOUR_CALM|RESOURCE_EXHAUSTED ...with additional error detail provided by runtime to indicate that the exhausted resource is bandwidth. INADEQUATE_SECURITY| PERMISSION_DENIED … with additional detail indicating that permission was denied as protocol is not secure enough for call. ##### Security The HTTP2 specification mandates the use of TLS 1.2 or higher when TLS is used with HTTP2. It also places some additional constraints on the allowed ciphers in deployments to avoid known-problems as well as requiring SNI support. It is also expected that HTTP2 will be used in conjunction with proprietary transport security mechanisms about which the specification can make no meaningful recommendations. ##### Connection Management ###### GOAWAY Frame Sent by servers to clients to indicate that they will no longer accept any new streams on the associated connections. This frame includes the id of the last successfully accepted stream by the server. Clients should consider any stream initiated after the last successfully accepted stream as UNAVAILABLE and retry the call elsewhere. Clients are free to continue working with the already accepted streams until they complete or the connection is terminated. Servers should send GOAWAY before terminating a connection to reliably inform clients which work has been accepted by the server and is being executed. ###### PING Frame Both clients and servers can send a PING frame that the peer must respond to by precisely echoing what they received. This is used to assert that the connection is still live as well as providing a means to estimate end-to-end latency. If a server initiated PING does not receive a response within the deadline expected by the runtime all outstanding calls on the server will be closed with a CANCELLED status. An expired client initiated PING will cause all calls to be closed with an UNAVAILABLE status. Note that the frequency of PINGs is highly dependent on the network environment, implementations are free to adjust PING frequency based on network and application requirements. ###### Connection failure If a detectable connection failure occurs on the client all calls will be closed with an UNAVAILABLE status. For servers open calls will be closed with a CANCELLED status. ### Appendix A - GRPC for Protobuf The service interfaces declared by protobuf are easily mapped onto GRPC by code generation extensions to protoc. The following defines the mapping to be used * **Path** → / Service-Name / {_method name_} * **Service-Name** → ?( {_proto package name_} "." ) {_service name_} * **Message-Type** → {_fully qualified proto message name_} * **Content-Type** → "application/grpc+proto" grpc-1.3.2/doc/PROTOCOL-WEB.md000066400000000000000000000133761310511640000154140ustar00rootroot00000000000000# Overview gRPC-Web provides a JS client library that supports the same API as gRPC-Node to access a gRPC service. Due to browser limitation, the Web client library implements a different protocol than the [native gRPC protocol](http://www.grpc.io/docs/guides/wire.html). This protocol is designed to make it easy for a proxy to translate between the protocols as this is the most likely deployment model. This document lists the differences between the two protocols. To help tracking future revisions, this document describes a delta with the protocol details specified in the [native gRPC protocol](http://www.grpc.io/docs/guides/wire.html). # Design goals For the gRPC-Web protocol, we have decided on the following design goals: * adopt the same framing as “application/grpc†whenever possible * decouple from HTTP/2 framing which is not, and will never, be directly exposed by browsers * support text streams (e.g. base64) in order to provide cross-browser support (e.g. IE-10) While the new protocol will be published/reviewed publicly, we also intend to keep the protocol as an internal detail to gRPC-Web. More specifically, we expect the protocol to * evolve over time, mainly to optimize for browser clients or support web-specific features such as CORS, XSRF * become optional (in 1-2 years) when browsers are able to speak the native gRPC protocol via the new [whatwg fetch/streams API](https://github.com/whatwg/fetch) # Protocol differences vs [gRPC over HTTP2](http://www.grpc.io/docs/guides/wire.html) Content-Type 1. application/grpc-web * e.g. application/grpc-web+[proto, json, thrift] 2. application/grpc-web-text * text-encoded streams of “application/grpc-web†* e.g. application/grpc-web-text+[proto, thrift] --- HTTP wire protocols 1. support any HTTP/*, with no dependency on HTTP/2 specific framing 2. use lower-case header/trailer names 3. use EOF (end of body) to close the stream --- HTTP/2 related behavior (specified in [gRPC over HTTP2](http://www.grpc.io/docs/guides/wire.html)) 1. stream-id is not supported or used 2. go-away is not supported or used --- Message framing (vs. [http2-transport-mapping](http://www.grpc.io/docs/guides/wire.html#http2-transport-mapping)) 1. Response status encoded as part of the response body * Key-value pairs encoded as a HTTP/1 headers block (without the terminating newline), per https://tools.ietf.org/html/rfc7230#section-3.2 ``` key1: foo\r\n key2: bar\r\n ``` 2. 8th (MSB) bit of the 1st gRPC frame byte * 0: data * 1: trailers ``` 10000000b: an uncompressed trailer (as part of the body) 10000001b: a compressed trailer ``` 3. Trailers must be the last message of the response, as enforced by the implementation 4. Trailers-only responses: no change to the gRPC protocol spec. Trailers may be sent together with response headers, with no message in the body. --- User Agent * Do NOT use User-Agent header (which is to be set by browsers, by default) * Use X-User-Agent: grpc-web-javascript/0.1 (follow the same format as specified in [gRPC over HTTP2](http://www.grpc.io/docs/guides/wire.html)) --- Text-encoded (response) streams 1. The client library should indicate to the server via the "Accept" header that the response stream needs to be text encoded e.g. when XHR is used or due to security policies with XHR * Accept: application/grpc-web-text 2. The default text encoding is base64 * Note that “Content-Transfer-Encoding: base64†should not be used. Due to in-stream base64 padding when delimiting messages, the entire response body is not necessarily a valid base64-encoded entity * While the server runtime will always base64-encode and flush gRPC messages atomically the client library should not assume base64 padding always happens at the boundary of message frames. That is, the implementation may send base64-encoded "chunks" with potential padding whenever the runtime needs to flush a byte buffer. 3. For binary trailers, when the content-type is set to application/grpc-web-text, the extra base64 encoding specified in [gRPC over HTTP2](http://www.grpc.io/docs/guides/wire.html) for binary custom metadata is skipped. # Other features Compression * Full-body compression is supported and expected for all unary requests/responses. The compression/decompression will be done by browsers, using standard Content-Encoding headers * “grpc-encoding†header is not used * SDCH, Brotli will be supported * Message-level compression for streamed requests/responses is not supported because manual compression/decompression is prohibitively expensive using JS * Per-message compression may be feasible in future with wasm --- Retries, caching * Will spec out the support after their respective gRPC spec extensions are finalized * Safe retries: PUT * Caching: header encoded request and/or a web specific spec --- Security * XSRF, XSS etc to be specified --- CORS preflight * Should follow the [CORS spec](https://developer.mozilla.org/en-US/docs/Web/HTTP/Server-Side_Access_Control) * Access-Control-Allow-Credentials to allow Authorization headers * Access-Control-Allow-Methods to allow POST and (preflight) OPTIONS only * Access-Control-Allow-Headers to whatever the preflight request carries * The client library may support header overwrites to avoid preflight * https://github.com/whatwg/fetch/issues/210 * CSP support to be specified --- Keep-alive * HTTP/2 PING is not supported or used * Will not support send-beacon (GET) --- Bidi-streaming, with flow-control * Pending on [whatwg fetch/streams](https://github.com/whatwg/fetch) to be finalized and implemented in modern browsers * gRPC-Web client will support the native gRPC protocol with modern browsers --- Versioning * Special headers may be introduced to support features that may break compatiblity. grpc-1.3.2/doc/binary-logging.md000066400000000000000000000052231310511640000164400ustar00rootroot00000000000000# Binary Logging ## Format The log format is described in [this proto file](src/proto/grpc/binary_log/v1alpha/log.proto). It is intended that multiple parts of the call will be logged in separate files, and then correlated by analysis tools using the rpc\_id. ## API The binary logger will be a separate library from gRPC, in each language that we support. The user will need to explicitly call into the library to generate logs. The library will provide the ability to log sending or receiving, as relevant, the following on both the client and the server: - Initial metadata - Messages - Status with trailing metadata from the server - Additional key/value pairs that are associated with a call but not sent over the wire The following is an example of what such an API could look like in C++: ```c++ // The context provides the method_name, deadline, peer, and metadata contents. // direction = CLIENT_SEND LogRequestHeaders(ClientContext context); // direction = SERVER_RECV LogRequestHeaders(ServerContext context); // The context provides the metadata contents // direction = CLIENT_RECV LogResponseHeaders(ClientContext context); // direction = SERVER_SEND LogResponseHeaders(ServerContext context); // The context provides the metadata contents // direction = CLIENT_RECV LogStatus(ClientContext context, grpc_status_code code, string details); // direction = SERVER_SEND LogStatus(ServerContext context, grpc_status_code code, string details); // The context provides the user data contents // direction = CLIENT_SEND LogUserData(ClientContext context); // direction = SERVER_SEND LogUserData(ServerContext context); // direction = CLIENT_SEND LogRequestMessage(ClientContext context, uint32_t length, T message); // direction = SERVER_RECV LogRequestMessage(ServerContext context, uint32_t length, T message); // direction = CLIENT_RECV LogResponseMessage(ClientContext context, uint32_t length, T message); // direction = SERVER_SEND LogResponseMessage(ServerContext context, uint32_t length, T message); ``` In all of those cases, the `rpc_id` is provided by the context, and each combination of method and context argument type implies a single direction, as noted in the comments. For the message log functions, the `length` argument indicates the length of the complete message, and the `message` argument may be only part of the complete message, stripped of sensitive material and/or shortened for efficiency. ## Language differences In other languages, more or less data will need to be passed explicitly as separate arguments. In some languages, for example, the metadata will be separate from the context-like object and will need to be passed as a separate argument. grpc-1.3.2/doc/c-style-guide.md000066400000000000000000000045071310511640000162070ustar00rootroot00000000000000GRPC C STYLE GUIDE ===================== Background ---------- Here we document style rules for C usage in the gRPC Core library. General ------- - Layout rules are defined by clang-format, and all code should be passed through clang-format. A (docker-based) script to do so is included in [tools/distrib/clang\_format\_code.sh](../tools/distrib/clang_format_code.sh). Header Files ------------ - Public header files (those in the include/grpc tree) should compile as pedantic C89. - Public header files should be includable from C++ programs. That is, they should include the following: ```c #ifdef __cplusplus extern "C" { # endif /* ... body of file ... */ #ifdef __cplusplus } # endif ``` - Header files should be self-contained and end in .h. - All header files should have a #define guard to prevent multiple inclusion. To guarantee uniqueness they should be based on the file's path. For public headers: `include/grpc/grpc.h` → `GRPC_GRPC_H` For private headers: `src/core/channel/channel_stack.h` → `GRPC_INTERNAL_CORE_CHANNEL_CHANNEL_STACK_H` Variable Initialization ----------------------- When declaring a (non-static) pointer variable, always initialize it to `NULL`. Even in the case of static pointer variables, it's recommended to explicitly initialize them to `NULL`. C99 Features ------------ - Variable sized arrays are not allowed. - Do not use the 'inline' keyword. - Flexible array members are allowed (https://en.wikipedia.org/wiki/Flexible_array_member). Comments -------- Within public header files, only `/* */` comments are allowed. Within implementation files and private headers, either single line `//` or multi line `/* */` comments are allowed. Only one comment style per file is allowed however (i.e. if single line comments are used anywhere within a file, ALL comments within that file must be single line comments). Symbol Names ------------ - Non-static functions must be prefixed by `grpc_` - Static functions must *not* be prefixed by `grpc_` - Enumeration values and `#define` names must be uppercase. All other values must be lowercase. - Multiple word identifiers use underscore as a delimiter, *never* camel case. E.g. `variable_name`. Functions ---------- - The use of [`atexit()`](http://man7.org/linux/man-pages/man3/atexit.3.html) is in forbidden in libgrpc. grpc-1.3.2/doc/combiner-explainer.md000066400000000000000000000115371310511640000173200ustar00rootroot00000000000000# Combiner Explanation ## Talk by ctiller, notes by vjpai Typical way of doing critical section ``` mu.lock() do_stuff() mu.unlock() ``` An alternative way of doing it is ``` class combiner { run(f) { mu.lock() f() mu.unlock() } mutex mu; } combiner.run(do_stuff) ``` If you have two threads calling combiner, there will be some kind of queuing in place. It's called `combiner` because you can pass in more than one do_stuff at once and they will run under a common `mu`. The implementation described above has the issue that you're blocking a thread for a period of time, and this is considered harmful because it's an application thread that you're blocking. Instead, get a new property: * Keep things running in serial execution * Don't ever sleep the thread * But maybe allow things to end up running on a different thread from where they were started * This means that `do_stuff` doesn't necessarily run to completion when `combiner.run` is invoked ``` class combiner { mpscq q; // multi-producer single-consumer queue can be made non-blocking state s; // is it empty or executing run(f) { if (q.push(f)) { // q.push returns true if it's the first thing while (q.pop(&f)) { // modulo some extra work to avoid races f(); } } } } ``` The basic idea is that the first one to push onto the combiner executes the work and then keeps executing functions from the queue until the combiner is drained. Our combiner does some additional work, with the motivation of write-batching. We have a second tier of `run` called `run_finally`. Anything queued onto `run_finally` runs after we have drained the queue. That means that there is essentially a finally-queue. This is not guaranteed to be final, but it's best-effort. In the process of running the finally item, we might put something onto the main combiner queue and so we'll need to re-enter. `chttp2` runs all ops in the run state except if it sees a write it puts that into a finally. That way anything else that gets put into the combiner can add to that write. ``` class combiner { mpscq q; // multi-producer single-consumer queue can be made non-blocking state s; // is it empty or executing queue finally; // you can only do run_finally when you are already running something from the combiner run(f) { if (q.push(f)) { // q.push returns true if it's the first thing loop: while (q.pop(&f)) { // modulo some extra work to avoid races f(); } while (finally.pop(&f)) { f(); } goto loop; } } } ``` So that explains how combiners work in general. In gRPC, there is `start_batch(..., tag)` and then work only gets activated by somebody calling `cq::next` which returns a tag. This gives an API-level guarantee that there will be a thread doing polling to actually make work happen. However, some operations are not covered by a poller thread, such as cancellation that doesn't have a completion. Other callbacks that don't have a completion are the internal work that gets done before the batch gets completed. We need a condition called `covered_by_poller` that means that the item will definitely need some thread at some point to call `cq::next` . This includes those callbacks that directly cause a completion but also those that are indirectly required before getting a completion. If we can't tell for sure for a specific path, we have to assumed it is not covered by poller. The above combiner has the problem that it keeps draining for a potentially infinite amount of time and that can lead to a huge tail latency for some operations. So we can tweak it by returning to the application if we know that it is valid to do so: ``` while (q.pop(&f)) { f(); if (control_can_be_returned && some_still_queued_thing_is_covered_by_poller) { offload_combiner_work_to_some_other_thread(); } } ``` `offload` is more than `break`; it does `break` but also causes some other thread that is currently waiting on a poll to break out of its poll. This is done by setting up a per-polling-island work-queue (distributor) wakeup FD. The work-queue is the converse of the combiner; it tries to spray events onto as many threads as possible to get as much concurrency as possible. So `offload` really does: ``` workqueue.run(continue_from_while_loop); break; ``` This needs us to add another class variable for a `workqueue` (which is really conceptually a distributor). ``` workqueue::run(f) { q.push(f) eventfd.wakeup() } workqueue::readable() { eventfd.consume(); q.pop(&f); f(); if (!q.empty()) { eventfd.wakeup(); // spray across as many threads as are waiting on this workqueue } } ``` In principle, `run_finally` could get starved, but this hasn't happened in practice. If we were concerned about this, we could put a limit on how many things come off the regular `q` before the `finally` queue gets processed. grpc-1.3.2/doc/command_line_tool.md000066400000000000000000000066001310511640000172120ustar00rootroot00000000000000# gRPC command line tool ## Overview This document describes the command line tool that comes with gRPC repository. It is desirable to have command line tools written in other languages roughly follow the same syntax and flags. At this point, the tool needs to be built from source, and it should be moved out to grpc-tools repository as a stand alone application once it is mature enough. ## Core functionality The command line tool can do the following things: - Send unary rpc. - Attach metadata and display received metadata. - Handle common authentication to server. - Infer request/response types from server reflection result. - Find the request/response types from a given proto file. - Read proto request in text form. - Read request in wire form (for protobuf messages, this means serialized binary form). - Display proto response in text form. - Write response in wire form to a file. The command line tool should support the following things: - List server services and methods through server reflection. - Fine-grained auth control (such as, use this oauth token to talk to the server). - Send streaming rpc. ## Code location To use the tool, you need to get the grpc repository and make sure your system has the prerequisites for building grpc from source, given in the [installation instructions](https://github.com/grpc/grpc/blob/master/INSTALL.md). In order to build the grpc command line tool from a fresh clone of the grpc repository, you need to run the following command to update submodules: ``` git submodule update --init ``` You also need to have the gflags library installed on your system. On Linux systems, gflags can be installed with the following command: ``` sudo apt-get install libgflags-dev ``` Once the prerequisites are satisfied, you can build the command line tool with the command: ``` $ make grpc_cli ``` The main file can be found at https://github.com/grpc/grpc/blob/master/test/cpp/util/grpc_cli.cc ## Usage ### Basic usage Send a rpc to a helloworld server at `localhost:50051`: ``` $ bins/opt/grpc_cli call localhost:50051 SayHello "name: 'world'" \ --enable_ssl=false ``` On success, the tool will print out ``` Rpc succeeded with OK status Response: message: "Hello world" ``` The `localhost:50051` part indicates the server you are connecting to. `SayHello` is (part of) the gRPC method string. Then `"name: 'world'"` is the text format of the request proto message. We are not using ssl here by `--enable_ssl=false`. For information on more flags, look at the comments of `grpc_cli.cc`. ### Use local proto files If the server does not have the server reflection service, you will need to provide local proto files containing the service definition. The tool will try to find request/response types from them. ``` $ bins/opt/grpc_cli call localhost:50051 SayHello "name: 'world'" \ --protofiles=examples/protos/helloworld.proto --enable_ssl=false ``` If the proto files is not under current directory, you can use `--proto_path` to specify a new search root. ### Send non-proto rpc For using gRPC with protocols other than probobuf, you will need the exact method name string and a file containing the raw bytes to be sent on the wire ``` $ bins/opt/grpc_cli call localhost:50051 /helloworld.Greeter/SayHello --input_binary_file=input.bin \ --output_binary_file=output.bin ``` On success, you will need to read or decode the response from the `output.bin` file. grpc-1.3.2/doc/compression.md000066400000000000000000000134141310511640000160720ustar00rootroot00000000000000## **gRPC Compression** The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](http://www.ietf.org/rfc/rfc2119.txt). ### Intent Compression is used to reduce the amount of bandwidth used between peers. The compression supported by gRPC acts _at the individual message level_, taking _message_ [as defined in the wire format document](PROTOCOL-HTTP2.md). The implementation supports different compression algorithms. A _default compression level_, to be used in the absence of message-specific settings, MAY be specified for during channel creation. The ability to control compression settings per call and to enable/disable compression on a per message basis MAY be used to prevent CRIME/BEAST attacks. It also allows for asymmetric compression communication, whereby a response MAY be compressed differently, if at all. ### Specification Compression MAY be configured by the Client Application by calling the appropriate API method. There are two scenarios where compression MAY be configured: + At channel creation time, which sets the channel default compression and therefore the compression that SHALL be used in the absence of per-RPC compression configuration. + At response time, via: + For unary RPCs, the {Client,Server}Context instance. + For streaming RPCs, the {Client,Server}Writer instance. In this case, configuration is reduced to disabling compression altogether. ### Compression Method Asymmetry Between Peers A gRPC peer MAY choose to respond using a different compression method to that of the request, including not performing any compression, regardless of channel and RPC settings (for example, if compression would result in small or negative gains). When a message from a client compressed with an unsupported algorithm is processed by a server, it WILL result in an `UNIMPLEMENTED` error status on the server. The server will then include in its response a `grpc-accept-encoding` header specifying the algorithms it does accept. If an `UNIMPLEMENTED` error status is returned from the server despite having used one of the algorithms from the `grpc-accept-encoding` header, the cause MUST NOT be related to compression. Data sent from a server compressed with an algorithm not supported by the client WILL result in an `INTERNAL` error status on the client side. Note that a peer MAY choose to not disclose all the encodings it supports. However, if it receives a message compressed in an undisclosed but supported encoding, it MUST include said encoding in the response's `grpc-accept-encoding h`eader. For every message a server is requested to compress using an algorithm it knows the client doesn't support (as indicated by the last `grpc-accept-encoding` header received from the client), it SHALL send the message uncompressed. ### Specific Disabling of Compression If the user (through the previously described mechanisms) requests to disable compression the next message MUST be sent uncompressed. This is instrumental in preventing BEAST/CRIME attacks. This applies to both the the unary and streaming cases. ### Compression Levels and Algorithms The set of supported algorithm is implementation dependent. In order to simplify the public API and to operate seamlessly across implementations (both in terms of languages but also different version of the same one), we introduce the idea of _compression levels_ (such as "low", "medium", "high"). Levels map to concrete algorithms and/or their settings (such as "low" mapping to "gzip -3" and "high" mapping to "gzip -9") automatically depending on what a peer is known to support. A server is always aware of what its clients support, as clients disclose it in their Message-Accept-Encoding header as part of their initial call. A client doesn't a priori (presently) know which algorithms a server supports. This issue can be addressed with an initial negotiation of capabilities or an automatic retry mechanism. These features will be implemented in the future. Currently however, compression levels are only supported at the server side, which is aware of the client's capabilities through the incoming Message-Accept-Encoding header. ### Propagation to child RPCs The inheritance of the compression configuration by child RPCs is left up to the implementation. Note that in the absence of changes to the parent channel, its configuration will be used. ### Test cases 1. When a compression level is not specified for either the channel or the message, the default channel level _none_ is considered: data MUST NOT be compressed. 1. When per-RPC compression configuration isn't present for a message, the channel compression configuration MUST be used. 1. When a compression method (including no compression) is specified for an outgoing message, the message MUST be compressed accordingly. 1. A message compressed by a client in a way not supported by its server MUST fail with status `UNIMPLEMENTED`, its associated description indicating the unsupported condition as well as the supported ones. The returned `grpc-accept-encoding` header MUST NOT contain the compression method (encoding) used. 1. A message compressed by a server in a way not supported by its client MUST fail with status `INTERNAL`, its associated description indicating the unsupported condition as well as the supported ones. The returned `grpc-accept-encoding` header MUST NOT contain the compression method (encoding) used. 1. An ill-constructed message with its [Compressed-Flag bit](PROTOCOL-HTTP2.md#compressed-flag) set but lacking a "[grpc-encoding](PROTOCOL-HTTP2.md#message-encoding)" entry different from _identity_ in its metadata MUST fail with `INTERNAL` status, its associated description indicating the invalid Compressed-Flag condition. grpc-1.3.2/doc/compression_cookbook.md000066400000000000000000000146321310511640000177630ustar00rootroot00000000000000# gRPC (Core) Compression Cookbook ## Introduction This document describes compression as implemented by the gRPC C core. See [the full compression specification](compression.md) for details. ### Intended Audience Wrapped languages developers, for the purposes of supporting compression by interacting with the C core. ## Criteria for GA readiness 1. Be able to set compression at [channel](#per-channel-settings), [call](#per-call-settings) and [message](#per-message-settings) level. In principle this API should be based on _compression levels_ as opposed to algorithms. See the discussion [below](#level-vs-algorithms). 1. Have unit tests covering [the cases from the spec](https://github.com/grpc/grpc/blob/master/doc/compression.md#test-cases). 1. Interop tests implemented and passing on Jenkins. The two relevant interop test cases are [large_compressed_unary](https://github.com/grpc/grpc/blob/master/doc/interop-test-descriptions.md#large_compressed_unary) and [server_compressed_streaming](https://github.com/grpc/grpc/blob/master/doc/interop-test-descriptions.md#server_compressed_streaming). ## Summary Flowcharts The following flowcharts depict the evolution of a message, both _incoming_ and _outgoing_, irrespective of the client/server character of the call. Aspects still not symmetric between clients and servers (e.g. the [use of compression levels](https://github.com/grpc/grpc/blob/master/doc/compression.md#compression-levels-and-algorithms)) are explicitly marked. The in-detail textual description for the different scenarios is described in subsequent sections. ## Incoming Messages ![image](images/compression_cookbook_incoming.png) ## Outgoing Messages ![image](images/compression_cookbook_outgoing.png) ## Levels vs Algorithms As mentioned in [the relevant discussion on the spec document](https://github.com/grpc/grpc/blob/master/doc/compression.md#compression-levels-and-algorithms), compression _levels_ are the primary mechanism for compression selection _at the server side_. In the future, it'll also be at the client side. The use of levels abstracts away the intricacies of selecting a concrete algorithm supported by a peer, on top of removing the burden of choice from the developer. As of this writing (Q2 2016), clients can only specify compression _algorithms_. Clients will support levels as soon as an automatic retry/negotiation mechanism is in place. ## Per Channel Settings Compression may be configured at channel creation. This is a convenience to avoid having to repeatedly configure compression for every call. Note that any compression setting on individual [calls](#per-call-settings) or [messages](#per-message-settings) overrides channel settings. The following aspects can be configured at channel-creation time via channel arguments: #### Disable Compression _Algorithms_ Use the channel argument key `GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET` (from [`grpc/impl/codegen/compression_types.h`](https://github.com/grpc/grpc/blob/master/include/grpc/impl/codegen/compression_types.h)), takes a 32 bit bitset value. A set bit means the algorithm with that enum value according to `grpc_compression_algorithm` is _enabled_. For example, `GRPC_COMPRESS_GZIP` currently has a numeric value of 2. To enable/disable GZIP for a channel, one would set/clear the 3rd LSB (eg, 0b100 = 0x4). Note that setting/clearing 0th position, that corresponding to `GRPC_COMPRESS_NONE`, has no effect, as no-compression (a.k.a. _identity_) is always supported. Incoming messages compressed (ie, encoded) with a disabled algorithm will result in the call being closed with `GRPC_STATUS_UNIMPLEMENTED`. #### Default Compression _Level_ **(currently, Q2 2016, only applicable for server side channels. It's ignored for clients.)** Use the channel argument key `GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL` (from [`grpc/impl/codegen/compression_types.h`](https://github.com/grpc/grpc/blob/master/include/grpc/impl/codegen/compression_types.h)), valued by an integer corresponding to a value from the `grpc_compression_level` enum. #### Default Compression _Algorithm_ Use the channel argument key `GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM` (from [`grpc/impl/codegen/compression_types.h`](https://github.com/grpc/grpc/blob/master/include/grpc/impl/codegen/compression_types.h)), valued by an integer corresponding to a value from the `grpc_compression_level` enum. ## Per Call Settings ### Compression **Level** in Call Responses The server requests a compression level via initial metadata. The `send_initial_metadata` `grpc_op` contains a `maybe_compression_level` field with two fields, `is_set` and `compression_level`. The former must be set when actively choosing a level to disambiguate the default value of zero (no compression) from the proactive selection of no compression. The core will receive the request for the compression level and automatically choose a compression algorithm based on its knowledge about the peer (communicated by the client via the `grpc-accept-encoding` header. Note that the absence of this header means no compression is supported by the client/peer). ### Compression **Algorithm** in Call Responses **Server should avoid setting the compression algorithm directly**. Prefer setting compression levels unless there's a _very_ compelling reason to choose specific algorithms (benchmarking, testing). Selection of concrete compression algorithms is performed by adding a `(GRPC_COMPRESS_REQUEST_ALGORITHM_KEY, )` key-value pair to the initial metadata, where `GRPC_COMPRESS_REQUEST_ALGORITHM_KEY` is defined in [`grpc/impl/codegen/compression_types.h`](https://github.com/grpc/grpc/blob/master/include/grpc/impl/codegen/compression_types.h)), and `` is the human readable name of the algorithm as given in [the HTTP2 spec](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md) for `Message-Encoding` (e.g. gzip, identity, etc.). See [`grpc_compression_algorithm_name`](https://github.com/grpc/grpc/blob/master/src/core/lib/compression/compression.c) for the mapping between the `grpc_compression_algorithm` enum values and their textual representation. ## Per Message Settings To disable compression for a specific message, the `flags` field of `grpc_op` instances of type `GRPC_OP_SEND_MESSAGE` must have its `GRPC_WRITE_NO_COMPRESS` bit set. Refer to [`grpc/impl/codegen/compression_types.h`](https://github.com/grpc/grpc/blob/master/include/grpc/impl/codegen/compression_types.h)), grpc-1.3.2/doc/connection-backoff-interop-test-description.md000066400000000000000000000065211310511640000242360ustar00rootroot00000000000000Connection Backoff Interop Test Descriptions =============================================== This test is to verify the client is reconnecting the server with correct backoffs as specified in [the spec](http://github.com/grpc/grpc/blob/master/doc/connection-backoff.md). The test server has a port (control_port) running a rpc service for controlling the server and another port (retry_port) to close any incoming tcp connections. The test has the following flow: 1. The server starts listening on control_port. 2. The client calls Start rpc on server control_port. 3. The server starts listening on retry_port. 4. The client connects to server retry_port and retries with backoff for 540s, which translates to about 13 retries. 5. The client calls Stop rpc on server control port. 6. The client checks the response to see whether the server thinks the backoffs are conforming the spec or do its own check on the backoffs in the response. Client and server use [test.proto](https://github.com/grpc/grpc/blob/master/src/proto/grpc/testing/test.proto). Each language should implement its own client. The C++ server is shared among languages. Client ------ Clients should accept these arguments: * --server_control_port=PORT * The server port to connect to for rpc. For example, "8080" * --server_retry_port=PORT * The server port to connect to for testing backoffs. For example, "8081" The client must connect to the control port without TLS. The client must connect to the retry port with TLS. The client should either assert on the server returned backoff status or check the returned backoffs on its own. Procedure of client: 1. Calls Start on server control port with a large deadline or no deadline, waits for its finish and checks it succeeded. 2. Initiates a channel connection to server retry port, which should perform reconnections with proper backoffs. A convienent way to achieve this is to call Start with a deadline of 540s. The rpc should fail with deadline exceeded. 3. Calls Stop on server control port and checks it succeeded. 4. Checks the response to see whether the server thinks the backoffs passed the test. 5. Optionally, the client can do its own check on the returned backoffs. Server ------ A C++ server can be used for the test. Other languages do NOT need to implement a server. To minimize the network delay, the server binary should run on the same machine or on a nearby machine (in terms of network distance) with the client binary. A server implements the ReconnectService to its state. It also opens a tcp server on the retry_port, which just shuts down all incoming tcp connections to simulate connection failures. The server will keep a record of all the reconnection timestamps and return the connection backoffs in the response in milliseconds. The server also checks the backoffs to see whether they conform the spec and returns whether the client passes the test. If the server receives a Start call when another client is being tested, it finishes the call when the other client is done. If some other host connects to the server retry_port when a client is being tested, the server will log an error but likely would think the client fails the test. The server accepts these arguments: * --control_port=PORT * The port to listen on for control rpcs. For example, "8080" * --retry_port=PORT * The tcp server port. For example, "8081" grpc-1.3.2/doc/connection-backoff.md000066400000000000000000000040471310511640000172630ustar00rootroot00000000000000GRPC Connection Backoff Protocol ================================ When we do a connection to a backend which fails, it is typically desirable to not retry immediately (to avoid flooding the network or the server with requests) and instead do some form of exponential backoff. We have several parameters: 1. INITIAL_BACKOFF (how long to wait after the first failure before retrying) 1. MULTIPLIER (factor with which to multiply backoff after a failed retry) 1. JITTER (by how much to randomize backoffs). 1. MAX_BACKOFF (upper bound on backoff) 1. MIN_CONNECT_TIMEOUT (minimum time we're willing to give a connection to complete) ## Proposed Backoff Algorithm Exponentially back off the start time of connection attempts up to a limit of MAX_BACKOFF, with jitter. ``` ConnectWithBackoff() current_backoff = INITIAL_BACKOFF current_deadline = now() + INITIAL_BACKOFF while (TryConnect(Max(current_deadline, now() + MIN_CONNECT_TIMEOUT)) != SUCCESS) SleepUntil(current_deadline) current_backoff = Min(current_backoff * MULTIPLIER, MAX_BACKOFF) current_deadline = now() + current_backoff + UniformRandom(-JITTER * current_backoff, JITTER * current_backoff) ``` With specific parameters of MIN_CONNECT_TIMEOUT = 20 seconds INITIAL_BACKOFF = 1 second MULTIPLIER = 1.6 MAX_BACKOFF = 120 seconds JITTER = 0.2 Implementations with pressing concerns (such as minimizing the number of wakeups on a mobile phone) may wish to use a different algorithm, and in particular different jitter logic. Alternate implementations must ensure that connection backoffs started at the same time disperse, and must not attempt connections substantially more often than the above algorithm. ## Reset Backoff The back off should be reset to INITIAL_BACKOFF at some time point, so that the reconnecting behavior is consistent no matter the connection is a newly started one or a previously disconnected one. We choose to reset the Backoff when the SETTINGS frame is received, at that time point, we know for sure that this connection was accepted by the server. grpc-1.3.2/doc/connectivity-semantics-and-api.md000066400000000000000000000147501310511640000215460ustar00rootroot00000000000000gRPC Connectivity Semantics and API =================================== This document describes the connectivity semantics for gRPC channels and the corresponding impact on RPCs. We then discuss an API. States of Connectivity ---------------------- gRPC Channels provide the abstraction over which clients can communicate with servers.The client-side channel object can be constructed using little more than a DNS name. Channels encapsulate a range of functionality including name resolution, establishing a TCP connection (with retries and backoff) and TLS handshakes. Channels can also handle errors on established connections and reconnect, or in the case of HTTP/2 GO_AWAY, re-resolve the name and reconnect. To hide the details of all this activity from the user of the gRPC API (i.e., application code) while exposing meaningful information about the state of a channel, we use a state machine with five states, defined below: CONNECTING: The channel is trying to establish a connection and is waiting to make progress on one of the steps involved in name resolution, TCP connection establishment or TLS handshake. This may be used as the initial state for channels upon creation. READY: The channel has successfully established a connection all the way through TLS handshake (or equivalent) and all subsequent attempt to communicate have succeeded (or are pending without any known failure ). TRANSIENT_FAILURE: There has been some transient failure (such as a TCP 3-way handshake timing out or a socket error). Channels in this state will eventually switch to the CONNECTING state and try to establish a connection again. Since retries are done with exponential backoff, channels that fail to connect will start out spending very little time in this state but as the attempts fail repeatedly, the channel will spend increasingly large amounts of time in this state. For many non-fatal failures (e.g., TCP connection attempts timing out because the server is not yet available), the channel may spend increasingly large amounts of time in this state. IDLE: This is the state where the channel is not even trying to create a connection because of a lack of new or pending RPCs. New RPCs MAY be created in this state. Any attempt to start an RPC on the channel will push the channel out of this state to connecting. When there has been no RPC activity on a channel for a specified IDLE_TIMEOUT, i.e., no new or pending (active) RPCs for this period, channels that are READY or CONNECTING switch to IDLE. Additionaly, channels that receive a GOAWAY when there are no active or pending RPCs should also switch to IDLE to avoid connection overload at servers that are attempting to shed connections. We will use a default IDLE_TIMEOUT of 300 seconds (5 minutes). SHUTDOWN: This channel has started shutting down. Any new RPCs should fail immediately. Pending RPCs may continue running till the application cancels them. Channels may enter this state either because the application explicitly requested a shutdown or if a non-recoverable error has happened during attempts to connect communicate . (As of 6/12/2015, there are no known errors (while connecting or communicating) that are classified as non-recoverable) Channels that enter this state never leave this state. The following table lists the legal transitions from one state to another and corresponding reasons. Empty cells denote disallowed transitions.
From/To CONNECTING READY TRANSIENT_FAILURE IDLE SHUTDOWN
CONNECTING Incremental progress during connection establishment All steps needed to establish a connection succeeded Any failure in any of the steps needed to establish connection No RPC activity on channel for IDLE_TIMEOUT Shutdown triggered by application.
READY Incremental successful communication on established channel. Any failure encountered while expecting successful communication on established channel. No RPC activity on channel for IDLE_TIMEOUT
OR
upon receiving a GOAWAY while there are no pending RPCs.
Shutdown triggered by application.
TRANSIENT_FAILURE Wait time required to implement (exponential) backoff is over. Shutdown triggered by application.
IDLE Any new RPC activity on the channel Shutdown triggered by application.
SHUTDOWN
Channel State API ----------------- All gRPC libraries will expose a channel-level API method to poll the current state of a channel. In C++, this method is called GetCurrentState and returns an enum for one of the five legal states. All libraries should also expose an API that enables the application (user of the gRPC API) to be notified when the channel state changes. Since state changes can be rapid and race with any such notification, the notification should just inform the user that some state change has happened, leaving it to the user to poll the channel for the current state. The synchronous version of this API is: ```cpp bool WaitForStateChange(gpr_timespec deadline, ChannelState source_state); ``` which returns true when the state changes to something other than the source_state and false if the deadline expires. Asynchronous and futures based APIs should have a corresponding method that allows the application to be notified when the state of a channel changes. Note that a notification is delivered every time there is a transition from any state to any *other* state. On the other hand the rules for legal state transition, require a transition from CONNECTING to TRANSIENT_FAILURE and back to CONNECTING for every recoverable failure, even if the corresponding exponential backoff requires no wait before retry. The combined effect is that the application may receive state change notifications that appear spurious. e.g., an application waiting for state changes on a channel that is CONNECTING may receive a state change notification but find the channel in the same CONNECTING state on polling for current state because the channel may have spent infinitesimally small amount of time in the TRANSIENT_FAILURE state. grpc-1.3.2/doc/core/000077500000000000000000000000001310511640000141345ustar00rootroot00000000000000grpc-1.3.2/doc/core/grpc-error.md000066400000000000000000000127771310511640000165560ustar00rootroot00000000000000# gRPC Error ## Background `grpc_error` is the c-core's opaque representation of an error. It holds a collection of integers, strings, timestamps, and child errors that related to the final error. always present are: * GRPC_ERROR_STR_FILE and GRPC_ERROR_INT_FILE_LINE - the source location where the error was generated * GRPC_ERROR_STR_DESCRIPTION - a human readable description of the error * GRPC_ERROR_TIME_CREATED - a timestamp indicating when the error happened An error can also have children; these are other errors that are believed to have contributed to this one. By accumulating children, we can begin to root cause high level failures from low level failures, without having to derive execution paths from log lines. grpc_errors are refcounted objects, which means they need strict ownership semantics. An extra ref on an error can cause a memory leak, and a missing ref can cause a crash. This document serves as a detailed overview of grpc_error's ownership rules. It should help people use the errors, as well as help people debug refcount related errors. ## Clarification of Ownership If a particular function is said to "own" an error, that means it has the responsibility of calling unref on the error. A function may have access to an error without ownership of it. This means the function may use the error, but must not call unref on it, since that will be done elsewhere in the code. A function that does not own an error may explicitly take ownership of it by manually calling GRPC_ERROR_REF. ## Ownership Rules There are three rules of error ownership, which we will go over in detail. * If `grpc_error` is returned by a function, the caller owns a ref to that instance. * If a `grpc_error` is passed to a `grpc_closure` callback function, then that function does not own a ref to the error. * if a `grpc_error` is passed to *any other function*, then that function takes ownership of the error. ### Rule 1 > If `grpc_error` is returned by a function, the caller owns a ref to that > instance.* For example, in the following code block, error1 and error2 are owned by the current function. ```C grpc_error* error1 = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error occured"); grpc_error* error2 = some_operation_that_might_fail(...); ``` The current function would have to explicitly call GRPC_ERROR_UNREF on the errors, or pass them along to a function that would take over the ownership. ### Rule 2 > If a `grpc_error` is passed to a `grpc_closure` callback function, then that > function does not own a ref to the error. A `grpc_closure` callback function is any function that has the signature: ```C void (*cb)(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); ``` This means that the error ownership is NOT transferred when a functions calls: ```C c->cb(exec_ctx, c->cb_arg, err); ``` The caller is still responsible for unref-ing the error. However, the above line is currently being phased out! It is safer to invoke callbacks with `grpc_closure_run` and `grpc_closure_sched`. These functions are not callbacks, so they will take ownership of the error passed to them. ```C grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error occured"); grpc_closure_run(exec_ctx, cb, error); // current function no longer has ownership of the error ``` If you schedule or run a closure, but still need ownership of the error, then you must explicitly take a reference. ```C grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error occured"); grpc_closure_run(exec_ctx, cb, GRPC_ERROR_REF(error)); // do some other things with the error GRPC_ERROR_UNREF(error); ``` Rule 2 is more important to keep in mind when **implementing** `grpc_closure` callback functions. You must keep in mind that you do not own the error, and must not unref it. More importantly, you cannot pass it to any function that would take ownership of the error, without explicitly taking ownership yourself. For example: ```C void on_some_action(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { // this would cause a crash, because some_function will unref the error, // and the caller of this callback will also unref it. some_function(error); // this callback function must take ownership, so it can give that // ownership to the function it is calling. some_function(GRPC_ERROR_REF(error)); } ``` ### Rule 3 > if a `grpc_error` is passed to *any other function*, then that function takes > ownership of the error. Take the following example: ```C grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error occured"); // do some things some_function(error); // can't use error anymore! might be gone. ``` When some_function is called, it takes over the ownership of the error, and it will eventually unref it. So the caller can no longer safely use the error. If the caller needed to keep using the error (or passing it to other functions), if would have to take on a reference to it. This is a common pattern seen. ```C void func() { grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error"); some_function(GRPC_ERROR_REF(error)); // do things some_other_function(GRPC_ERROR_REF(error)); // do more things some_last_function(error); } ``` The last call takes ownership and will eventually give the error its final unref. When **implementing** a function that takes an error (and is not a `grpc_closure` callback function), you must ensure the error is unref-ed either by doing it explicitly with GRPC_ERROR_UNREF, or by passing the error to a function that takes over the ownership. grpc-1.3.2/doc/core/pending_api_cleanups.md000066400000000000000000000015751310511640000206350ustar00rootroot00000000000000There are times when we make changes that include a temporary shim for backward-compatibility (e.g., a macro or some other function to preserve the original API) to avoid having to bump the major version number in the next release. However, when we do eventually want to release a feature that does change the API in a non-backward-compatible way, we will wind up bumping the major version number anyway, at which point we can take the opportunity to clean up any pending backward-compatibility shims. This file lists all pending backward-compatibility changes that should be cleaned up the next time we are going to bump the major version number: - remove `GRPC_ARG_MAX_MESSAGE_LENGTH` channel arg from `include/grpc/impl/codegen/grpc_types.h` (commit `af00d8b`) (cannot be done until after next grpc release, so that TensorFlow can use the same code both internally and externally) grpc-1.3.2/doc/cpp-style-guide.md000066400000000000000000000006521310511640000165440ustar00rootroot00000000000000GRPC C++ STYLE GUIDE ===================== The majority of gRPC's C++ requirements are drawn from the [Google C++ style guide] (https://google.github.io/styleguide/cppguide.html). Additionally, as in C, layout rules are defined by clang-format, and all code should be passed through clang-format. A (docker-based) script to do so is included in [tools/distrib/clang\_format\_code.sh] (../tools/distrib/clang_format_code.sh). grpc-1.3.2/doc/cpp/000077500000000000000000000000001310511640000137665ustar00rootroot00000000000000grpc-1.3.2/doc/cpp/pending_api_cleanups.md000066400000000000000000000015661310511640000204670ustar00rootroot00000000000000There are times when we make changes that include a temporary shim for backward-compatibility (e.g., a macro or some other function to preserve the original API) to avoid having to bump the major version number in the next release. However, when we do eventually want to release a feature that does change the API in a non-backward-compatible way, we will wind up bumping the major version number anyway, at which point we can take the opportunity to clean up any pending backward-compatibility shims. This file lists all pending backward-compatibility changes that should be cleaned up the next time we are going to bump the major version number: - remove `ServerBuilder::SetMaxMessageSize()` method from `include/grpc++/server_builder.h` (commit `6980362`) - remove `ClientContext::set_fail_fast()` method from `include/grpc++/impl/codegen/client_context.h` (commit `9477724`) grpc-1.3.2/doc/cpp/perf_notes.md000066400000000000000000000022111310511640000164500ustar00rootroot00000000000000# C++ Performance Notes ## Streaming write buffering Generally, each write operation (Write(), WritesDone()) implies a syscall. gRPC will try to batch together separate write operations from different threads, but currently cannot automatically infer batching in a single stream. If message k+1 in a stream does not rely on responses from message k, it's possible to enable write batching by passing a WriteOptions argument to Write with the buffer_hint set: ~~~{.cpp} stream_writer->Write(message, WriteOptions().set_buffer_hint()); ~~~ The write will be buffered until one of the following is true: - the per-stream buffer is filled (controllable with the channel argument GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE) - this prevents infinite buffering leading to OOM - a subsequent Write without buffer_hint set is posted - the call is finished for writing (WritesDone() called on the client, or Finish() called on an async server stream, or the service handler returns for a sync server stream) ## Completion Queues and Threading in the Async API Right now, the best performance trade-off is having numcpu's threads and one completion queue per thread. grpc-1.3.2/doc/environment_variables.md000066400000000000000000000066251310511640000201330ustar00rootroot00000000000000gRPC environment variables -------------------------- gRPC C core based implementations (those contained in this repository) expose some configuration as environment variables that can be set. * GRPC_ABORT_ON_LEAKS A debugging aid to cause a call to abort() when gRPC objects are leaked past grpc_shutdown(). Set to 1 to cause the abort, if unset or 0 it does not abort the process. * GOOGLE_APPLICATION_CREDENTIALS The path to find the credentials to use when Google credentials are created * GRPC_SSL_CIPHER_SUITES A colon separated list of cipher suites to use with OpenSSL Defaults to: ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-GCM-SHA384 * GRPC_DEFAULT_SSL_ROOTS_FILE_PATH PEM file to load SSL roots from * GRPC_POLL_STRATEGY [posix-style environments only] Declares which polling engines to try when starting gRPC. This is a comma-separated list of engines, which are tried in priority order first -> last. Available polling engines include: - epoll (linux-only) - a polling engine based around the epoll family of system calls - poll - a portable polling engine based around poll(), intended to be a fallback engine when nothing better exists - legacy - the (deprecated) original polling engine for gRPC * GRPC_TRACE A comma separated list of tracers that provide additional insight into how gRPC C core is processing requests via debug logs. Available tracers include: - api - traces api calls to the C core - bdp_estimator - traces behavior of bdp estimation logic - call_error - traces the possible errors contributing to final call status - channel - traces operations on the C core channel stack - combiner - traces combiner lock state - compression - traces compression operations - connectivity_state - traces connectivity state changes to channels - channel_stack_builder - traces information about channel stacks being built - http - traces state in the http2 transport engine - http1 - traces HTTP/1.x operations performed by gRPC - flowctl - traces http2 flow control - op_failure - traces error information when failure is pushed onto a completion queue - pending_tags - [debug builds only] traces still-in-progress tags on completion queues - round_robin - traces the round_robin load balancing policy - glb - traces the grpclb load balancer - queue_pluck - queue_timeout - server_channel - lightweight trace of significant server channel events - secure_endpoint - traces bytes flowing through encrypted channels - timer - timers (alarms) in the grpc internals - transport_security - traces metadata about secure channel establishment - tcp - traces bytes in and out of a channel 'all' can additionally be used to turn all traces on. Individual traces can be disabled by prefixing them with '-'. Example: export GRPC_TRACE=all,-pending_tags * GRPC_VERBOSITY Default gRPC logging verbosity - one of: - DEBUG - log all gRPC messages - INFO - log INFO and ERROR message - ERROR - log only errors * GRPC_DNS_RESOLVER Declares which DNS resolver to use. The default is ares if gRPC is built with c-ares support. Otherwise, the value of this environment variable is ignored. Available DNS resolver include: - native (default)- a DNS resolver based around getaddrinfo(), creates a new thread to perform name resolution - ares - a DNS resolver based around the c-ares library grpc-1.3.2/doc/epoll-polling-engine.md000066400000000000000000000232121310511640000175460ustar00rootroot00000000000000# `epoll`-based pollset implementation in gRPC Sree Kuchibhotla (sreek@) [May - 2016] (Design input from Craig Tiller and David Klempner) > Status: As of June 2016, this change is implemented and merged. > * The bulk of the functionality is in: [ev_poll_linux.c](https://github.com/grpc/grpc/blob/master/src/core/lib/iomgr/ev_epoll_linux.c) > * Pull request: https://github.com/grpc/grpc/pull/6803 ## 1. Introduction The document talks about the proposed changes to `epoll`-based implementation of pollsets in gRPC. Section-2 gives an overview of the current implementation, Section-3 talks about the problems in the current implementation and finally Section-4 talks about the proposed changes. ## 2. Current `epoll`-based implementation in gRPC ![image](images/old_epoll_impl.png) **Figure 1: Current implementation** A gRPC client or a server can have more than one completion queue. Each completion queue creates a pollset. The gRPC core library does not create any threads[^1] on its own and relies on the application using the gRPC core library to provide the threads. A thread starts to poll for events by calling the gRPC core surface APIs `grpc_completion_queue_next()` or `grpc_completion_queue_pluck()`. More than one thread can call `grpc_completion_queue_next()`on the same completion queue[^2]. A file descriptor can be in more than one completion queue. There are examples in the next section that show how this can happen. When an event of interest happens in a pollset, multiple threads are woken up and there are no guarantees on which thread actually ends up performing the work i.e executing the callbacks associated with that event. The thread that performs the work finally queues a completion event `grpc_cq_completion` on the appropriate completion queue and "kicks" (i.e wakes ups) the thread that is actually interested in that event (which can be itself - in which case there is no thread hop) For example, in **Figure 1**, if `fd1` becomes readable, any one of the threads i.e *Threads 1* to *Threads K* or *Thread P*, might be woken up. Let's say *Thread P* was calling a `grpc_completion_queue_pluck()` and was actually interested in the event on `fd1` but *Thread 1* woke up. In this case, *Thread 1* executes the callbacks and finally kicks *Thread P* by signalling `event_fd_P`. *Thread P* wakes up, realizes that there is a new completion event for it and returns from `grpc_completion_queue_pluck()` to its caller. ## 3. Issues in the current architecture ### _Thundering Herds_ If multiple threads concurrently call `epoll_wait()`, we are guaranteed that only one thread is woken up if one of the `fds` in the set becomes readable/writable. However, in our current implementation, the threads do not directly call a blocking `epoll_wait()`[^3]. Instead, they call `poll()` on the set containing `[event_fd`[^4]`, epoll_fd]`. **(see Figure 1)** Considering the fact that an `fd` can be in multiple `pollsets` and that each `pollset` might have multiple poller threads, it means that whenever an `fd` becomes readable/writable, all the threads in all the `pollsets` (in which that `fd` is present) are woken up. The performance impact of this would be more conspicuous on the server side. Here are a two examples of thundering herds on the server side. Example 1: Listening fds on server * A gRPC server can have multiple server completion queues (i.e completion queues which are used to listen for incoming channels). * A gRPC server can also listen on more than one TCP-port. * A listening socket is created for each port the gRPC server would be listening on. * Every listening socket's fd is added to all the server completion queues' pollsets. (Currently we do not do any sharding of the listening fds across these pollsets). This means that for every incoming new channel, all the threads waiting on all the pollsets are woken up. Example 2: New Incoming-channel fds on server * Currently, every new incoming channel's `fd` (i.e the socket `fd` that is returned by doing an `accept()` on the new incoming channel) is added to all the server completion queues' pollsets [^5]). * Clearly, this would also cause all thundering herd problem for every read onthat fd There are other scenarios especially on the client side where an fd can end up being on multiple pollsets which would cause thundering herds on the clients. ## 4. Proposed changes to the current `epoll`-based polling implementation: The main idea in this proposal is to group 'related' `fds` into a single epoll-based set. This would ensure that only one thread wakes up in case of an event on one of the `fds` in the epoll set. To accomplish this, we introduce a new abstraction called `polling_island` which will have an epoll set underneath (See **Figure 2** below). A `polling_island` contains the following: * `epoll_fd`: The file descriptor of the underlying epoll set * `fd_set`: The set of 'fds' in the pollset island i.e in the epoll set (The pollset island merging operation described later requires the list of fds in the pollset island and currently there is no API available to enumerate all the fds in an epoll set) * `event_fd`: A level triggered _event fd_ that is used to wake up all the threads waiting on this epoll set (Note: This `event_fd` is added to the underlying epoll set during pollset island creation. This is useful in the pollset island merging operation described later) * `merged_to`: The polling island into which this one merged. See section 4.2 (case 2) for more details on this. Also note that if `merged_to` is set, all the other fields in this polling island are not used anymore In this new model, only one thread wakes up whenever an event of interest happens in an epoll set. ![drawing](images/new_epoll_impl.png) **Figure 2: Proposed changes** ### 4.1 Relation between `fd`, `pollset` and `polling_island:` * An `fd` may belong to multiple `pollsets` but belongs to exactly one `polling_island` * A `pollset` belongs to exactly one `polling_island` * An `fd` and the `pollset(s`) it belongs to, have same `polling_island` ### 4.2 Algorithm to add an `fd` to a `pollset` There are two cases to check here: * **Case 1:** Both `fd` and `pollset` already belong to the same `polling_island` * This is straightforward and nothing really needs to be done here * **Case 2:** The `fd `and `pollset` point to different `polling_islands`: In this case we _merge_ both the polling islands i.e: * Add all the `fds` from the smaller `polling_island `to the larger `polling_island` and update the `merged_to` pointer on the smaller island to point to the larger island. * Wake up all the threads waiting on the smaller `polling_island`'s `epoll_fd` (by signalling the `event_fd` on that island) and make them now wait on the larger `polling_island`'s `epoll_fd` * Update `fd` and `pollset` to now point to the larger `polling_island` ### 4.3 Directed wakeups: The new implementation, just like the current implementation, does not provide us any guarantees that the thread that is woken up is the thread that is actually interested in the event. So the thread that woke up executes the callbacks and finally has to 'kick' the appropriate polling thread interested in the event. In the current implementation, every polling thread also had a `event_fd` on which it was listening to and hence waking it up was as simple as signalling that `event_fd`. However, using an `event_fd` also meant that every thread has to use a `poll()` (on `event_fd` and `epoll_fd`) instead of doing an `epoll_wait()` and this resulted in the thundering herd problems described above. The proposal here is to use signals and kicking a thread would just be sending a signal to that thread. Unfortunately there are only a few signals available on posix systems and most of them have pre-determined behavior leaving only a few signals `SIGUSR1`, `SIGUSR2` and `SIGRTx (SIGRTMIN to SIGRTMAX)` for custom use. The calling application might have registered other signal handlers for these signals. `We will provide a new API where the applications can "give a signal number" to gRPC library to use for this purpose. ``` void grpc_use_signal(int signal_num) ``` If the calling application does not provide a signal number, then the gRPC library will relegate to using a model similar to the current implementation (where every thread does a blocking `poll()` on its `wakeup_fd` and the `epoll_fd`). The function` psi_wait() `in figure 2 implements this logic. **>> **(**NOTE**: Or alternatively, we can implement a turnstile polling (i.e having only one thread calling `epoll_wait()` on the epoll set at any time - which all other threads call poll on their `wakeup_fds`) in case of not getting a signal number from the applications. ## Notes [^1]: Only exception is in case of name-resolution [^2]: However, a `grpc_completion_queue_next()` and `grpc_completion_queue_pluck()` must not be called in parallel on the same completion queue [^3]: The threads first do a blocking` poll()` with `[wakeup_fd, epoll_fd]`. If the `poll()` returns due to an event of interest in the epoll set, they then call a non-blocking i.e a zero-timeout `epoll_wait()` on the `epoll_fd` [^4]: `event_fd` is the linux platform specific implementation of `grpc_wakeup_fd`. A `wakeup_fd` is used to wake up polling threads typically when the event for which the polling thread is waiting is already completed by some other thread. It is also used to wake up the polling threads in case of shutdowns or to re-evaluate the poller's interest in the fds to poll (the last scenario is only in case of `poll`-based (not `epoll`-based) implementation of `pollsets`). [^5]: See more details about the issue here https://github.com/grpc/grpc/issues/5470 and for a proposed fix here: https://github.com/grpc/grpc/pull/6149 grpc-1.3.2/doc/fail_fast.md000066400000000000000000000000331310511640000154520ustar00rootroot00000000000000Moved to wait-for-ready.md grpc-1.3.2/doc/g_stands_for.md000066400000000000000000000006011310511640000161730ustar00rootroot00000000000000Each version of gRPC gets a new description of what the 'g' stands for, since we've never really been able to figure it out. Below is a list of already-used definitions (that should not be repeated in the future), and the corresponding version numbers that used them: - 1.0 'g' stands for 'gRPC' - 1.1 'g' stands for 'good' - 1.2 'g' stands for 'green' - 1.3 'g' stands for 'gentle' grpc-1.3.2/doc/health-checking.md000066400000000000000000000054121310511640000165460ustar00rootroot00000000000000GRPC Health Checking Protocol ================================ Health checks are used to probe whether the server is able to handle rpcs. The client-to-server health checking can happen from point to point or via some control system. A server may choose to reply “unhealthy†because it is not ready to take requests, it is shutting down or some other reason. The client can act accordingly if the response is not received within some time window or the response says unhealthy in it. A GRPC service is used as the health checking mechanism for both simple client-to-server scenario and other control systems such as load-balancing. Being a high level service provides some benefits. Firstly, since it is a GRPC service itself, doing a health check is in the same format as a normal rpc. Secondly, it has rich semantics such as per-service health status. Thirdly, as a GRPC service, it is able reuse all the existing billing, quota infrastructure, etc, and thus the server has full control over the access of the health checking service. ## Service Definition The server should export a service defined in the following proto: ``` syntax = "proto3"; package grpc.health.v1; message HealthCheckRequest { string service = 1; } message HealthCheckResponse { enum ServingStatus { UNKNOWN = 0; SERVING = 1; NOT_SERVING = 2; } ServingStatus status = 1; } service Health { rpc Check(HealthCheckRequest) returns (HealthCheckResponse); } ``` A client can query the server’s health status by calling the `Check` method, and a deadline should be set on the rpc. The client can optionally set the service name it wants to query for health status. The suggested format of service name is `package_names.ServiceName`, such as `grpc.health.v1.Health`. The server should register all the services manually and set the individual status, including an empty service name and its status. For each request received, if the service name can be found in the registry, a response must be sent back with an `OK` status and the status field should be set to `SERVING` or `NOT_SERVING` accordingly. If the service name is not registered, the server returns a `NOT_FOUND` GRPC status. The server should use an empty string as the key for server's overall health status, so that a client not interested in a specific service can query the server's status with an empty request. The server can just do exact matching of the service name without support of any kind of wildcard matching. However, the service owner has the freedom to implement more complicated matching semantics that both the client and server agree upon. A client can declare the server as unhealthy if the rpc is not finished after some amount of time. The client should be able to handle the case where server does not have the Health service. grpc-1.3.2/doc/http-grpc-status-mapping.md000066400000000000000000000026101310511640000204070ustar00rootroot00000000000000# HTTP to gRPC Status Code Mapping Since intermediaries are a common part of HTTP infrastructure some responses to gRPC requests may be received that do not include the grpc-status header. In some cases mapping error codes from an intermediary allows the gRPC client to behave more appropriately to the error situation without overloading the semantics of either error code. This table is to be used _only_ for clients that received a response that did not include grpc-status. If grpc-status was provided, it _must_ be used. Servers _must not_ use this table to determine an HTTP status code to use; the mappings are neither symmetric nor 1-to-1. | HTTP Status Code | gRPC Status Code | |----------------------------|--------------------| | 400 Bad Request | INTERNAL | | 401 Unauthorized | UNAUTHENTICATED | | 403 Forbidden | PERMISSION\_DENIED | | 404 Not Found | UNIMPLEMENTED | | 429 Too Many Requests | UNAVAILABLE | | 502 Bad Gateway | UNAVAILABLE | | 503 Service Unavailable | UNAVAILABLE | | 504 Gateway Timeout | UNAVAILABLE | | _All other codes_ | UNKNOWN | Technically, 1xx should have the entire header skipped and a subsequent header be read. See RFC 7540 §8.1. 200 is UNKNOWN because there should be a grpc-status in case of truly OK response. grpc-1.3.2/doc/http2-interop-test-descriptions.md000066400000000000000000000177071310511640000217420ustar00rootroot00000000000000Negative HTTP/2 Interop Test Case Descriptions ======================================= Client and server use [test.proto](../src/proto/grpc/testing/test.proto). Server ------ The code for the custom http2 server can be found [here](https://github.com/grpc/grpc/tree/master/test/http2_test). It is responsible for handling requests and sending responses, and also for fulfilling the behavior of each particular test case. Server should accept these arguments: * --port=PORT * The port the server will run on. For example, "8080" * --test_case=TESTCASE * The name of the test case to execute. For example, "goaway" Client ------ Clients implement test cases that test certain functionality. Each client is provided the test case it is expected to run as a command-line parameter. Names should be lowercase and without spaces. Clients should accept these arguments: * --server_host=HOSTNAME * The server host to connect to. For example, "localhost" or "127.0.0.1" * --server_port=PORT * The server port to connect to. For example, "8080" * --test_case=TESTCASE * The name of the test case to execute. For example, "goaway" Note ----- Note that the server and client must be invoked with the same test case or else the test will be meaningless. For convenience, we provide a shell script wrapper that invokes both server and client at the same time, with the same test_case. This is the preferred way to run these tests. ## Test Cases ### goaway This test verifies that the client correctly responds to a goaway sent by the server. The client should handle the goaway by switching to a new stream without the user application having to do a thing. Client Procedure: 1. Client sends two UnaryCall requests (and sleeps for 1 second in-between). TODO: resolve [9300](https://github.com/grpc/grpc/issues/9300) and remove the 1 second sleep ``` { response_size: 314159 payload:{ body: 271828 bytes of zeros } } ``` Client asserts: * Both calls are successful. * Response payload body is 314159 bytes in size. Server Procedure: 1. Server sends a GOAWAY after receiving the first UnaryCall. Server asserts: * Two different connections were used from the client. ### rst_after_header This test verifies that the client fails correctly when the server sends a RST_STREAM immediately after sending headers to the client. Procedure: 1. Client sends UnaryCall with: ``` { response_size: 314159 payload:{ body: 271828 bytes of zeros } } ``` Client asserts: * Call was not successful. Server Procedure: 1. Server sends a RST_STREAM with error code 0 after sending headers to the client. *At the moment the error code and message returned are not standardized throughout all languages. Those checks will be added once all client languages behave the same way. [#9142](https://github.com/grpc/grpc/issues/9142) is in flight.* ### rst_during_data This test verifies that the client fails "correctly" when the server sends a RST_STREAM halfway through sending data to the client. Procedure: 1. Client sends UnaryCall with: ``` { response_size: 314159 payload:{ body: 271828 bytes of zeros } } ``` Client asserts: * Call was not successful. Server Procedure: 1. Server sends a RST_STREAM with error code 0 after sending half of the requested data to the client. ### rst_after_data This test verifies that the client fails "correctly" when the server sends a RST_STREAM after sending all of the data to the client. Procedure: 1. Client sends UnaryCall with: ``` { response_size: 314159 payload:{ body: 271828 bytes of zeros } } ``` Client asserts: * Call was not successful. Server Procedure: 1. Server sends a RST_STREAM with error code 0 after sending all of the data to the client. *Certain client languages allow the data to be accessed even though a RST_STREAM was encountered. Once all client languages behave this way, checks will be added on the incoming data.* ### ping This test verifies that the client correctly acknowledges all pings it gets from the server. Procedure: 1. Client sends UnaryCall with: ``` { response_size: 314159 payload:{ body: 271828 bytes of zeros } } ``` Client asserts: * call was successful. * response payload body is 314159 bytes in size. Server Procedure: 1. Server tracks the number of outstanding pings (i.e. +1 when it sends a ping, and -1 when it receives an ack from the client). 2. Server sends pings before and after sending headers, also before and after sending data. Server Asserts: * Number of outstanding pings is 0 when the connection is lost. ### max_streams This test verifies that the client observes the MAX_CONCURRENT_STREAMS limit set by the server. Client Procedure: 1. Client sends initial UnaryCall to allow the server to update its MAX_CONCURRENT_STREAMS settings. 2. Client concurrently sends 10 UnaryCalls. Client Asserts: * All UnaryCalls were successful, and had the correct type and payload size. Server Procedure: 1. Sets MAX_CONCURRENT_STREAMS to one after the connection is made. *The assertion that the MAX_CONCURRENT_STREAMS limit is upheld occurs in the http2 library we used.* ### data_frame_padding This test verifies that the client can correctly receive padded http2 data frames. It also stresses the client's flow control (there is a high chance that the sender will deadlock if the client's flow control logic doesn't correctly account for padding). Client Procedure: (Note this is the same procedure as in the "large_unary" gRPC interop tests. Clients should use their "large_unary" gRPC interop test implementations.) Procedure: 1. Client calls UnaryCall with: ``` { response_size: 314159 payload:{ body: 271828 bytes of zeros } } ``` Client asserts: * call was successful * response payload body is 314159 bytes in size * clients are free to assert that the response payload body contents are zero and comparing the entire response message against a golden response Server Procedure: 1. Reply to the client's request with a `SimpleResponse`, with a payload body length of `SimpleRequest.response_size`. But send it across specific http2 data frames as follows: * Each http2 data frame contains a 5 byte payload and 255 bytes of padding. * Note the 5 byte payload and 255 byte padding are partly arbitrary, and other numbers are also ok. With 255 bytes of padding for each 5 bytes of payload containing actual gRPC message, the 300KB response size will multiply into around 15 megabytes of flow control debt, which should stress flow control accounting. ### no_df_padding_sanity_test This test verifies that the client can correctly receive a series of small data frames. Note that this test is intentionally a slight variation of "data_frame_padding", with the only difference being that this test doesn't use data frame padding when the response is sent. This test is primarily meant to prove correctness of the http2 server implementation and highlight failures of the "data_frame_padding" test. Client Procedure: (Note this is the same procedure as in the "large_unary" gRPC interop tests. Clients should use their "large_unary" gRPC interop test implementations.) Procedure: 1. Client calls UnaryCall with: ``` { response_size: 314159 payload:{ body: 271828 bytes of zeros } } ``` Client asserts: * call was successful * response payload body is 314159 bytes in size * clients are free to assert that the response payload body contents are zero and comparing the entire response message against a golden response Server Procedure: 1. Reply to the client's request with a `SimpleResponse`, with a payload body length of `SimpleRequest.response_size`. But send it across series of http2 data frames that contain 5 bytes of "payload" and zero bytes of "padding" (the padding flags on the data frames should not be set). grpc-1.3.2/doc/images/000077500000000000000000000000001310511640000144515ustar00rootroot00000000000000grpc-1.3.2/doc/images/compression_cookbook_incoming.png000066400000000000000000002624431310511640000233040ustar00rootroot00000000000000‰PNG  IHDR]™$Œ•=bKGDÿÿÿ ½§“ pHYs  šœtIMEà DZ d IDATxÚìÝwXS×ð—„{QDPE¡îQÜú³*uÕjmµU[[[­]V­uTÜ£-nÅU÷(UÅ*‚¢( ÈÞ` B~ ©*ZTÆûyž>•p“ÜóͽðrιçDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDô4–€žæ»I´qÙ‰î…R×üœ|§IaI^¡^ii©èažDJdÅó%jÊIE¥DW_G¢¥­™§ª¦–®¦&ÌÐk%„* %%%q€ÊÍ '‚£›’”¾9'=ç?e""b袷fØ'ƒFÆG?˜qå–}“æ6*®Z¡U'Ø;ÙÖú¶%ŧàÂñ`\ô ‘§'fJÔEjK2R²~ å'ODD ]ôÚ}øá‡¢TIü¨ð»¥%ej÷Ö CÆõ‡±~móýèÞ~J~ñtˆDU]mYVZÖr9<ˆˆˆ¡‹ª]¯>Mr23Ößúçvg ïû=1øƒ>ëˆëM $ùœüë\Éñ]~9¥òÒ©Ié³¾ˆˆˆ¡‹ªEûNfª*šÛ¯…DöÐÖ« þ /úxõ„º†Z½®KèßWå¾k÷%e¥dŸÍLÏš …G 1tÑKëÚµ«v‰†ô—ozéêk ‡}<Ýt|mË:ÔV—Î^Á¦¥;³¤Ò¢ÓéI?¸ËªCU…j§w;,¾vkŠ¡‰Úè)CÑ¡G[Vå9är9üb˲]g3Ó²§3|C=“[—ÖîÉ iGu t Ç|>În-X”— +*ƉÝ~غr¤¨°è›ÒÒÒu¬ 1tÑ“T[µwÜ~÷ýŸ½§2d\?#þ)Yðž¹&7:26¤@RàN¶'"¢·€¿Ék§]…*‚°ü\I»Ùk¿QéÒ×€…ù´´5Ñó]DzFºV‘aQceEÅ—ij2DDÄÐU?©6oÕtçíîþÖ¶skÑœ?fÂÂÚŒU©Fv-«vëßIïæÕÛÝ$ KŠK”²2DDô&px±°±±1—«È‚²2rO3û¸³(¯Ù¡m'·­ú+¶ ¿`€¬½nìézË5iä‘—ŸsÅØÂØô—õßÁ±M3å pp±×mÕÁÉüÒÙ°÷¥…E1n³*DDÄÐUG5miûmb\òö£<Õ¿üutô´Y”7ÈÈÌPØ}P'½°€k=Ф2û’â’3JX""z8¼øv¨Ú:4Ú™Ÿ+2ã·)GWVä-’ËåX:k]~°ß•di¡´ ¸š=½ìéz ˼¡Ù=íw—øþ,°²±dEÞ2@€wz¹iU…jW¢F”ÊK÷xÈÊCW-\Ú:â¿núAEK[‹©AZ´i¦¡¦®&Œ¸Õ§T^º€ŒU!""†®ÚGÛÌÒ$PMMµÝü ß©pþVÍ ^úFzŠ‚n x¼8Ç‹ˆˆºjSà20Ö»,Òµ\´õ'c}V¤³w´Õ1±4’_þûZ‡ÒÒÒàZ^DDÄÐU+¨š\‚N‹¶þ¤blnÄŠÔ¶6ú†fú‚«á¥¥¥ûX""bèªáŒÌŒö–Êå]m­bÙÈœ©EìZ46–JåQ×¢›+Š“¬1tÕPFz ¤…Ò–ì˜+°¶åUеQk÷–æ·#î'Å%8ÏŠCW £o¤3¶PR´xÞŸß ì³ µXç> ƒN‡Úæfå)„°"DDÄÐUstTÿšçó­>­ýº xGïôÞ¿]‹¤Eñ"Y""zY\‘¾úék‰5cgx®ïÖ¥5«Q‡$Ä$aòày%Å%®î²"DDô2ØÓUÍ´õÄ;toÛ|Ø„V£nÑ3ОNÎåÀk®P`;+BDD/ƒÁ ©©©} (EgŽa˜­£ú¾ßˬ¡­U#ï±DDÄÐõvبðÇÄï>PÕ5Ða5ê°_7ü`£®¡>o+@DDUÆ™ê¡*ÖÑ:eïØÄz⬱œ'WÇiŠEªz†zBÿ³p–!"¢ª`OWõø¨H*k3åç \õDŸáÝ[[5²èÀ‰Õ ""†®7C_]S}‘×ÄÁ\µž™¿á[¡ªp%+ADD ]o€ººêL#Ía±õŒ©•‘EÛN­´Œe5ˆˆèE8öß41¿nüAÍÙ­«QIò$%#;MJ*–»ÈaEˆˆèYØÓõ¨‹Ôuéã!gિĺbÕÁcú”XÀjÑó°§ëÕµÒi\Ürnµ—ˆ¨ßdEÅáñqza´/€+¬U†=]¯H¨&œ1bò.R×PÈO‡”˜ÎjCWõ2VÊ ~^=5Y €>^=Ì„Baæ¬1tUŸá¡7±ÓQÀŠÿDxèML˜1¾¿cõ…øã¸7ŒÍ ñÛŒÕHŠOyæûný{ ̬Là»z/þ ¾M~«°ÉoVXM-öm<úÜ6D†EA./ÅÖ¿×(ŸÛÈÞÇwAjb: <ô&¶®Ø ÷í°õï5eí8¹Å2²3rjÄgáú޳@+ž6DDÄÐõ’„Ba{kõš¼ï:öN¶ÊnÂDDÄÐUu.vÍmdµ½‡â*ëmú7l• Ê奕¾F^v>ŒÍÞj; Œõñ0¯à¹¡±&0ohš  O""bèª:‡f.vµþ¶.¶ÍˆûîFÆTøÞWïÿˆ žÓ`çØp#ôf…m¢#bPX ­0ü÷¦9»µÀýè„ “æ£#bjÔí‘7m°§‹ˆˆº^.tÙ;5±¬ípïÑb1|Wï-X.œÆýètôlˆæpvkóÇ‚péìå6’| Öý² Ð׫Ç[mÇ Ê.øuÚre;’âS°dæêUï­›é1tÑcœH_Å: µ?ŸŠuÄøæ·)XôÕ Lðœ†Vî-‘—“Ȱ(8º:ÀkÒÿ”­ÿíØ¹˜;e \ìa`¬ðЛH1qÖØrW>¾•ìb‰ßÅ¿nÁ]'ÃØÜ©‰éèÒ× 1I¾B`ÖÀÎn- ­+þw3•²9Z-ÛµÀã+/­l,ЩOhˆÔ‘™– = å‰IßUÎçÒÔÁshw›A’_™¬®1åç hßݵܮ˜èWxß'÷çñk>ÞoÛæ6pvkñèK•ò÷_|êûÏ{Ÿ¦-› Ç Î°hh††MÀkÒÿ0ô£ð]³În-àÞ£Ý[ÿ˜æITÏȰg©°U ] ëO-oPÓ—Œ¨/ŽïöCZb:Æ|1¼Ü­‹îG'àÓß`ħC0æóáo}?ÃCoâÛ±sÿПqNW”*J kÊúOH ¤Øãsù†\.d¤daõœ  …xç]·±Ÿz:füĈˆàœ®*Q”*´jÊúOôñꉰ€ëغb7vý¾ÿÑÚaYe«ÔÏ™ðÖçœ=&ÒAEE…iˆˆº¨vÒÔaþÆï…ÛáwQX …eCs¸vtAMê‘|4ôÉsŒˆˆº¨vstu€£kÍ]‘áÑÐg ?)""8§«JT*²ªÜ3èI²¢b(T…¬1tUµH*‚´§W?'z‘쌔–”&²DDpx±ªJ_%W×ÈŠŠ•«ºkëj)ïÏø¬!+*†º† ŒõyT¼BÎÑcì骹\—‘’U'Ûu=ãzNŸžS±î—ÍÏ«>ø ÆõœŠEÓWò ¨‚ÄØälq¬1tQ9Á~—ñ¬¹k7.ߪQ7“&""b誛¢îÝŠK¯Ë ´lhŽÂ)®^¯ôûç¡‘½5„—ý ìé"""†®— ]Ñ7îåÕåº÷l u 5ž©ð=YQ1‚Ï^F—¾•>72, ÛVîÁ²ïÖá¯õ‡UyÎ=ÿþ\°.ØŠÐóÿ °@ ¿ƒçŸ¹}­?h®G+Dðô!""€é«ºnƨÕ労DèèÙA9Ĩ®ños¯^G^v>:÷uÇÖ»Ë=oÃoÛ±oãQ›ÂÌÊA~W°É{G¹ûÊår,š¾§B``¬c}ÜzÎn-z£¦ ­1«ÈW§äøT1€Û<}ˆˆ`OWU…¥%fÔõFv|·}¥CŒ§Cààbˆæå¿€}bð}±Õ-~Ûþ3¶þ½În-°çÏCÊ«"ÿò9ŒÀS!ñélý{ VXˆ¥»æáÞ­ûu¶–²¢bHò%&¢xúCWÕe”ÊKåu}­®6] ©%*7Ä(+*F°_åC‹¹&Ö?Ù+¦©%ÂäÙðóï3 zt¿Êã»Ï ‘½5Æ|>üñ­qààbÑS†ÖÙZ>ˆM„ŠŠÊpEz""z„ËUTZZz=&*®£kÇVºÚFu 5¸÷lWnˆñòù«(,âwÛWØÞÞÉÆæ†ØãsW®£m'´éèG×f°¶µ,K«)YÈHÉBÇw;Tòꪘ¨øôÒÒÒHž9DDô{ºªH¡Püs=ôfZ]oçÓCŒçÂÙ­ŒÍ +l«©%ÂÂ-?¡ûÀNHŽOÁŸCøvì\Œê4 »~?HŠOˆuµ* yuÕÕÀëy.ñÌ!""†®—w4èTh_aüÉ!ÆÂ)¯¡ÛÀNÏÜÞ²¡9¾^4;ƒ|°pËOþñ …Bl]±~Ï+çegäVxn]¾Ÿå•€ëbçyÚC×Ë»˜š˜®_×U×PCGÏöö»Œ '‚!/)…{÷¶•n{íR–}·©‰éP×Pƒ³[ |øÕÌóùp#ô&ŒÍ alnˆkA7ðô­”žµ&Xm—š˜ŽIÀž6DDÄÐõò¤¥¥¥gCÏ_-¨ë í6° ¤Øº|7\;¹@×@§ÒídEÅ8sà<þZ¸Üã1QeW%>^LuøÇƒ‘Ÿ‚?lUön…^¯°üDIç§C’Jå¥ÇxÊÑ“8‘þ%(Š#þG.ºôÜŦ.·³e»æÐ5ÐAvFÎ3D·.­Ñѳ=Žï:ƒkA7`ïd‹ÔÄtD]†­ƒ úxõôù.¢®Gãˆï)œÚ{b1²3rÐѳ=O…Ô¹ú=|¡ÀIž1DDô$!KðRÒ3R2¿þÉ 5 îtjëŠÑ²] ˜Y™L-MÐÈÞ½†t…šÚÙ\pvk¡\ÌÔ£—ÙYCE @fJL-1pLLúîCˆ45”Oóèå×N.°ldŽ­›âã™cÐÈÞ~Ï£“g4mÙ¤NÔRVT ŸÛÔ ÅdRž2DDô{º^Î(pçFèÍ–­Ü[Ö‰Àjfe‚Q“+®—Õ¹{¥Û?½­P(Dç>îÏÜþ\°šZÃó½npp±W>~|·ÀôQØ« ¯啖–ÞÃÓ…ˆˆžÄ9]/©¤¤dýÎu’Y‰ªKMLÇêÙëöÄÄùèˆø®Þ c}´êàTgÚê»foºB¡ØÄOˆˆž¦Â¼4m¡P˜¼Éo•vekWQEIñ)ø~ü|¤&¦C¬#†PU€¼ì|›bæ’ÏáèêP'Ú™‘’…{LÉ.--µ‡‰ˆè)^|yårùæ[Žøxæ#–ãÅ,šãcKqíRîG'@^"‡½5Útt©S ¤þµþÐÝÒÒÒ“ \DDTöt½' ‘ÆÅ½W6ê>¾— Õor¹ïµ—)+”uÁŠÑÓ8§ëÕDÈKäá'/³'.eK‹ï2pCW5+))Y²É{'¯P#ÀFï Å2V‚ˆˆºªß¡ìôœÈ3þÎe)ê·c;Ïäf¦eåØÇjѳpN×c§­¯í¿ýïu êÒ„pª:I¾#;NÊ/–pˆ!"¢gá,ðÿ&K&•é ‚Îí¹~D=´r¶OVÌ­¸ëf±DDô<^üïíÛxD*É“”°õKtD üê)ŠŸY ""zötýw%òùø{‰Í»ö{§ËQü8aA^Nfî)‹X ""zötU³WÃco\¹ÅÛÕ'ÿ:[|ÿn‚8¬HDDUĉôÕÇ\×@çïM~«šij‰X:L’/Á¨ÎŸJdRÙlÞ¬U‡«ÏÃ"©L‘š˜îÔñÝöz,GݵdÆêä¸; Ñ&(eEˆˆ¨*8¼X½þö»œùOÐ KQ7ÝúçNáÅ3—  Ňxñ1t½%%²"Ù' ¾\.‘äKX:F.—cþçKÓ ÅLQ¬½ /V¿¤’b¹nxèÍæ=ÿ×EK `®­+~µ2êö»±&³DDÄÐU(Šs9ybõ;zvÐfEj¿ ¿ù&œÞç}°"DDÄÐUC”––îKŒMñPSW5hѦƒW-¶Ó±œköj+Š®âY""bèªq¹«ôXDXT¿FM­amkÅ+k¡€ÁÒU³}Ô Å0Á¬½*N8z½ËŠ=—~»öÁýè„ –£v‰ ‹’/œ¾RM¡PÌpŒ!"¢ÿ‚‹£¾æšbÍCËvÏkÞ°I–£æ‹¹'ÿbØ÷År¹|€q¬1tÕ¢à%ÖÖô÷ÞõKÆM¬´XŽš+!&I>uÈÌ|YQ±€àz\DDT 8§ëÍyX,+9{îPÀÿ]tL-9´[e§ç”L<#CZX´e+Î3pQµ`Oכ礮¡0Ã÷:Ž® ½5ˆ´@Z2¦ÛgI’¼‚ý¾dEˆˆ¨:ñ—þ›—&——^<"h¨]‹ÆËFæü j€ôä ɤßÄæç<<ÊÀEDD ]uG¼¼Dîwñthÿââ™K{G1Kòö\:{%iúÈŸR‰t €™¬½^|»ôUUU}Z´uh={Í×M4µD¬È$—˱zΆ¸Ó{ýM ÅGv³*DDÄÐU·MÔ7ÖûzÅžù&Æìõz2R²0ëÃy‰‰÷“þà «BDD¯‡k†0iA‘ÿ©¿üÛY42+ndgmÀ’¼>W.üS8}äliNVî]=ÜaUˆˆèucOWÍ¢-T.ujãðΫ¾j!Öa§Wu’ËåX;wcü‰=gX àRV†ˆˆÞötÕ,2E©âHjbzæñÝ~nÖ¶–*Ö¶V,Ë—žœ!™w#cѶ“‹¶º†:«òŠ.œŸ1f޶$¿`?€÷ÀáD""z 8¼X³© ‚ùjêj“>ž9ºÐsXw3¡9¹ªîܸ—´ì‡?âî߉o`xÓj""bè¢h¥¢¢ò³XWì:å§ñÂÎ}=,X’g‹¾›ï=sM\üÝöðð•!""†.ª*;@ð£‰~ëoM9·w´gIþu÷f¬lÅÆÝ»k `;€YRX""bè¢W_¾7k`Útêœ &m<œëuøŠ¾›¿zöú´èˆ{MœDÙU‰€/BÁfÆi½‡÷(~wh÷Æzµ{•UYQ1BÎ]‰<¶Ç/ãÖÕ;ÖŲâR”-nº@?v""b袷Eà=U*}uõuŠ»öë˜>hloks+SÇÚЀ„˜$\8v1ÆÿØÅ¢äøT[…B‘`/€}ùCÕD PvÁÞ" 3»6Ò.ýßÑêäÙ¡¥ž¡®aMØÁÂ).»ë$Py%ʬ°@jàƒ1tQmÖ€'€Þš&›Yç¸wo§áÒÁÉꉕž¦–èµGÊŠŠ‘™š/>&ðdHÁ•€k&¹ÙùŽ2P6þ€ó®ñ£"""†.ª+ô°žœ˜«¨¨hª©«%éh§šZ˜dÙØ7ÈoÒÂVCC¤¦×ØÁFU¨&4Ñ‹ÌŒÍ  €þã ••ž]”ú =;7;O‘S”’*ÏHËVÉLÉ”eeä"7+OWV$ÓQ”*´P6ë.€+(ëź Ž1tQ} cÆ(š4{ôoc6OüÛüÑ÷UŸxÞ”ÝHºäÑ¿ñ(LÝ}ôß½Gÿçx"""¢—¤` ˆˆˆžOÀ1t1tCCC1t1tCCC1t1t1tCC1t1tQíf@@ñèëBª, Qõ;ô(t•8Ër½vdâÌd9ˆˆˆˆ^Ÿ+(ëíêÀR½>ä€ó¹ˆˆˆˆ^;/–€ˆˆèù„,½ª‹çv««ŸJÏÎõ250ÐÎÎÏFÙ¤z""""ªŽ°õA?Ï[†ºº ¯^Ý;æÿ¤ðtw+Õk4±²š@Ä*•§ÂPU\½ÔñÀ¹ó_tëÜÚ_Œ K å÷#ïÅbÉö]Š+7o&×n IDATçêh‰fÇ%§®{¾ˆˆˆºèåÂÖÿónmš7ÃŒFÂÁ¦á3·¼……›}K£ãä1|1tÑ \òYÙ`—À†ƒþ½7R™>Ê ŽMWùùAáX²m—<.)9]UUmúƒÔÔ¬*1tU¶,MŒUfŒ 7Çæ¯üz~¡aX°q›<;?Ÿá‹ˆˆºˆbýèûlÛ·îÀ¹€aº:¯F{ÁÃÙ©Ú^ÿTp(oõ-yX “H‹&gåæžfÕ‰ˆˆ¡‹êeØ™cG¡§›ëk{¿=gü±Ôw·\¡PÄ2|CÕƒ°µI´mwàoG‚>)JÕ¿ý><ÝÝÞÈ{—ÈåØî¼·í,VSS½‘™ûInAA?""bè¢:¶Ò³sÔ§†á½º½•})‘˱ùÈ ¬Øù—\O[|ወˆº¨ÖSøû«.?²oÖ‘ gÆ$¥ˆ§†!Ý;CUøöoLP$+ƶ㧰j÷¾b=qÀÝøÄ‰îòS#""†.ª•a+â^¬xŠ×{øp@Ÿ¶ž&)”â÷}‡àsðH‰©¡þ†/""bè¢Zaí·_N:2ÿjÔmÃO‡Ƙ¾žÐPW«ñû÷PŸƒG±áÐQ™‰þáèøS¤ð%""†.ª‘a+8<ÂpÜÀ¾˜ôÞ ˆ5kß-³òò°bç^ì8y¦ÄÒÄø Ã1tQà;ï‡!/\\qþÊ? Æôë÷‡®¶¸Ö·+-;köìÇž3þEƆz›îÅ'ÎÃOœˆˆºè­„­SÁ¡ ¼zuÇ#†ÂPW·Îµ3!5 K·ïÆñ‹—d¦Æ¾ˆˆˆ¡‹Þˆ‹çv:qþâŸ'ƒBuí„ÉÇÀÔ@¿Î·;.)+vîÅ©K—%FººËî%&Î åAoƒ¶‰âa:¯÷ :/ @s–¡«Þ†­£Á½Ú·ÅW£½`mfZÿ~ÄÅcÑ_EPx„ÔTßÀ›á‹ÞEß_9Õê¶ãß™370tÕ/'W/u”˜ê_`ø"†."†.†®Zfí·_N:2ÿjÔmÃO‡Ƙ¾žÐPWcaj¨¼‡ø<Š ‡ŽÊL ôGÇ?˜ €¿Q‰¡‹º˜ºjzØ 07°/&½7bM SKdååaÅνØqòL‰¥‰ñA†/bè"†.憮ÆwÞC^¸¸âü•Œé×î]m1 SK¥eç`ÍžýØsÆ¿ÈØPoÓ½øÄYrXbè"†.bèzËaëTph¯^Ýñň¡0ÔÕ}îsJär Ɖ ¤gç@¬)B×¶m0Ò³gµAÉŠQ$“U9ü}é½ “‡µ?ØGRÓ°tûn¿xIfjl°‘ዺˆ¡‹^†€%øïv.žÛéƒ~ž·¾\ºzŸ¾¶vƒ >«1gâø.I¡ïÏúÓ—¯XSîÎN°±´À¢-¾ðš5’Biµíc·I_ "&¶ÊÛ…G W"á‡ûk3S,›>§V/QoÛ¬Ù$}M¬¬æà˜1½ë ['Î_üóh@°C¯ömñÕh/X›™Vùù_/_‹“A!8èýk¹¥» ‰èóù×ø _oü8alµì«eïÿaïây¼¥P5ŠŠ‹Ç¢-¾Š ð©©¾÷½ÄÄù¤¬L½Äž.ªóØÓõß©²/ïäꥎÎßøÕân[»àèò…°±´x©×ÈÊËÞ3çðÝø1†ð쬭ðÓÇBCM]ùXhä-¬?xY¹ykŠ0n`_tum  ì¾‚wÀ¥©Öí=ˆ"Y1\šÚá«Q^kŠð¥÷*Àš=ûq?9#<{"!5 ¿ï;„Ûqñ c#Lí¥lǓËóÖoA7W‡G"8<êjðêÕ»tT¶eÍž¸~§lu…6Í›â‹÷‡=÷¢äŒL\޼]m1ÔÕÔµ»L ôy/ºÚbXáÒHH ¥èêÚZ9Ü{;H¤R\޼…¦&pijWé{Ä&%l¾°çñe9Ø4ĦٳT"ïÅj.Ù¾ëûœ‡§èh‰fÇ%§®PÂ3…ˆˆžÄE¢^2l‰E¢£ 6n¯¥)²ZúåŒîû.ôut^úµÎ]¾ŠCç1û“q0Ö׫ð}{;86i ø;ìŒønÜ0³Š‹K0kõŸ076DK;[:ŸGq=úþ×­3[Z`í_œ‘…w;´Cž¤'ƒCп“Ú6w€ššÞýì+éébì€>hѸN‡\ÆŽ“~øhP?Àø¹ ѯ“;¬ÍL1cÅ:>SC¼ÛÁ ÙyùX´e:µv•© &Ì[„ûÉ©ølø´´³Å–£'vë6t~§Ò¶o:rãç.@i©Çƒ±j×>ü}å8Ø4BÓ†ÖøláRÜ{ˆe;þ‚_ȹpÇ.ãýw{@  ý؉Êdøvå︗ðËvü…BY:µvQ¾Ç÷k}0Í{%nÆÄáÌ¥ËØtø>þ߀×r\˜`p×N*m[4]»sϳ°Hö…™¡~aÎCI€Rž9õÂÏö=¾®µ;ïüj<¸â‹Ô›'aÒ´;T•ÿ=ž›xwN/@êÍ“›ØC]lX£Û¾÷ È ²¡gÙub.r“nÀÐÆMÙî´['alß噯‘‚h¿ßjE{_·è³K`Owöt½V—|V6Øå°aÒüŽ7Rñýå'e zUçkUe8rþÆmÔ¥#æö1 «kk…BÌß° ÃzvSö6ûcL ô•½<'‚BÃ{uÃ4ï•èêÚnŽÍy .NXûíWÊÅYuµÅùý\ä=”T:ÙÞκ–LûLùzgB® 8‡Ì˜ €Y‹>0kÑ»ÒíâC·âÁÕÝ«6^Ð6±«Ñíz¼¯ÖmG–ý\Œ8-k4é2EÙî‚ì8ôùéÙ?«³îãÁÕݵ¢½ÄÐU'ÂÖû?ýÚËÒÄXeùן+‰W—<‰ä¹ÃpE²bDÞ‹Å´ÃÊ=ÞÛÝ ÞÛw!.©l‰…±‘2p€–H¹\þÌpàæØ×ïÜŽIˆMJFÀ?×Ëþ’•Tºžn·XS„’G¯ß¿£f®üûΞG·¶­ÑÕµ5Æ èSù_Ê ŠdÅ05,ÛWU¡ÆFÈ}X~Ò~ÿN˜0¸¿2˜zõê^®=3?›†Ow7”È刈‰…‡³öœ9‡á½º—Ûç'kóxñÓ' ïÕí¥æã=‡³öÿö‹Ð/4Ì|ÁÆm[Í ½¾¨6¨j %âh¥¡KQZ‚Ô›' TC.«Ù´Ÿ°:¦ü`‰¡«&‹õ? ï³mߺqó½‡èê—|9¹Ú' 7kd ¸÷ ÆF¾{áéÞ ÷TzÔ$……ÊðRUiÙ9õÃ\Ä%%ÃÅÞÍlÂÃÙ ¡‘·žùás^ÿ·iŸ¡[ÛÖ8‚U{öcþÆmèÕ¾-6üôm…ý25Ї‡³möEÉ9b“Ràå*¶Íý¡|ûDåƒè²éSËï@X¡Ùyù€¬Ü<¸Ø?û/Riq1‚Ã#*„X˜UïqÔÓÍ=Ý\…§‚CÍoõÝbmf:G"-šœ•›{šgÕD&M»#åæ ´,)‚@U£Ü÷Ò£ÿ†L’«VC‘xmoå$æ§A ¦5‘Þsß§0;šÖ¯½=F¶ÕþšÅÒ\xae’,¨÷C’ÄÐõ°ÕwÜ´a¡@8küåYusijK ì>}[9WøþÒí»‘•—‡1}=!Ö!*.¾Üv‘1qe½@æ/ÿWÜš=û‘÷P‚k;6)Ë©àÐWjG‘¬×ÂÑí­rbýÎS~˜¾lM¹áÀDzòò ¯^Ýásà uuË ¾ŠÇC‡ LM”!ìöýøgnoj ½‹ç½±ãÊÓÝ žînª{ÎøÛ-õÝ}\,Òˆeø¢šÈ©?Rož@úÿ ½]É×B× ZF6åW”– &àwÄ®U MkØvú :ŒSnWZR„;gá~ÈÈeÕŰqÒ’"¤ÜÊ Ï¢óÇSail„ؤdxõꎰ¨;HÎÈ|©¹MbM~ýìL_¾‡Î@O,FDLÙ´ÊV³oãÐÖf¦:ãÇB¡½=ÚcÕ7Óª¼ ÿÌ•¿cãáãHÏʆ‰¡Ö};]ù½/Þ†¸¤ôùüX›™*Wâ¿à³úíŸpB!†÷ê†!Ý;«m>r¢ÍŠ…ØZY\ÏÌÎý$·  Œ?’èmª‹aÞ¢O…!Æô;þË$0wì„+¾åž“u"= 8øUù˜±]§G¤ì‚šì¸¤Þ<†íÇÂiÐ"€i³ž0²uGк~ÏÝ'ƒFnª‹‘y÷‚rB|z´?TªPU#=úß^¹´(?¨TaÖ¼wµ×ÆÈÖí>üwZ¦¾u\\ÓwÎ,D›‘ëQ˜€{çWÁØ®3Ú}¸Cy¨©CO\Zÿný΃^8,I ]uŽÂß_uù‘}³>úfå̘¤ñ´Ã0¤{ç—šU]FxöÄn]‹ûI)076„«C³ráC¬)‚ï/?!*.99ÐÑÒ*·.Õǃûcdïžå^÷éÇŽ.[„ëÑwa¨« ;k+„m[nß8Û5®¶cúy*çR…lù¦€ƒÞ¿V˜cõäcCºwF×¶­Yq1š5jXé<58Œ¬¼<\Û¹I9¹=(<CgüˆþÝ1°KG¬5ªÂçwÂ~7~ œí›ÀPWW9¡þÉzýùý7ÊuºÄ"lÕ¬O(Ä„Áý1¦¯§pÛñSmVíÞlglp7>q"€»üÑDo‹¹S$^Û[nˆ1ñÚ^Ø´‡H¯âz„jZ†Æ!êÄ\Xµ3ÕÅxgò)å6)‘Ç ÜpcYpq…‘­‡òÊÉÊT5`Ò´ÒïøCQZ*2î^€¡MYËŠ¹X.ê7t}-ó¨wú´Ü׺NÐoèŠô;þ€Ô['¡(-A£ãË-¹¡"PEƒ6^ÈŽ AæÝ˜;õçAÆÐU¿ÂVo¾šq/V<Åë=lÐç­„­'i¨«ÁÕ¡i…ùOO+  +<®«-®pÅáÓi¨«•›7%ÖU˜KödPz²·«²õôc†ººUºØ :!†ººåB\iiÙRVVÞóÉ+ Ÿ¥*ïgalôÌðWSh¨«aÂàþáÙSí÷}‡ºûÚ î¯êsðh÷ ‡ŽFšèŽŽ0ï/CoŒ@U£ÜcêÍ“P”ÊaîXy¶‰ºN¿„ô;þH½y™±AH¸ì‹„˾hÒe*šy~ÿï¾zª^–±}7¨T•½JÅÒ\˜4-{ìö) +6%–±0mÖó×LE T+KçÁPU>×Ö ‘0†®º¶Ž†ÌÿaíÃqûbùô©Ï]‹^/k3SœY³T9ô§'ÃκÁKà-Tû-}j ]m1¦ö¸}ÔWìÜ;4)=c°¥‰ñÁz¾6¡ì–_âÙ÷²Ü ÀžUÕïÉ!Æäˆ£0²õxæ\&AqaÌZôVGæ&^ÇÕ°¶]¦@ÇÌiQg—Yáj¿ªôþ¨‹ ahㆌ{¨Š TCÏÊ*U¨‰ôinÒ£«+¿–šHs“*,sQ˜“¡º:¦Ð2,{_ã¦Ý`bß­BJŠ$\3ŒêîÕ‹¾ó~2¬W·„ŸÿØ´ÎÁ¦¡aÐÆµ˜>Ú‹«†°06‚‡³›4~éGk3Ó:ÿ9êêbÎÄñ¸¸qjW×ÖCõ´µãš4´Z@¿˜`Þ ¶éÈ3éõx<ÄX¼Î¡A¯J·S”–ÀïWg\Ý1¡ÜãzV.0°v…¢´ ¹΃q}Êm—¤\‚áELz!'> ©7OÀÈÖCÙcfÒ´Ò¢N#ãî˜:ôzm5Iºq¨BXÌŠ …IÓnö¯¬‡í~ðÆ Ï88g8#ó‰+0‰¡«N…­O-Û§¯­ÝàÜ+0}´W¥«¬Õt¦ú˜3q5W¶ŽP½j?›Íš÷†¢´9 a0¶ëüï(¶æ&£´¤æNý^[MâCÊö9/9Éá‡pyóT5Ð´×·Êæ«5hã…´¨3¸ºc²ãB›x·Žý„Äk{al×FM:ñàªçêÌðâÎÅs;8ñÏ/—®vÔµ.ø¬®Ò„l¢ÚÀÚÌ˦OÅ#†ª¯Ø¹wRfvÞ#]Ýe÷çãÙCpµÙæ(FlàáKˆ´ì\޼=m1Úµh®¼¢¯HVŒ°¨ÛðpvÂÝ„D„GßC;G‡J{ô¢ââ‘•—U¡޶Ë]á—•—‡Ë‘Q€vކÛJär\¾‡"™¬B/ÓÝ„D¤egÃÝÙêêÞ7,êìXAZ\ŒKá076ªpkI¡×Â:b-€©A¥· zrxqç)?åþ †\.G·¶­1ñ½A•.jûäðâ¼õ[•—‡'Ï =;“‡APx69¬Ü<ˆ5EÞ«{¹V[¹96Çþß~…Gè/Ù¶k©TVýseؼ…OxCO[ ±H„ˆ˜Xå-€ïßÑ€ H ¥kвårûÿÙoŒìÝ >Ž ±¥9®GßÔáC0cìHe(õÃ\¸:4…ªPˆ3!W «-ƨ޽”s¯žt4 Z"<ÝÝq GƒÐÆ¡ÞëÞqIÉX´e´451n@Ÿ ÏKJÁÑ€ ü8a,Ú84ÅîÓç`gÝŽM#!5 ïÏú_ŒwgGüuŸ.ðÆÖ¹ß£«kë:q,y8;aÿo¿ýBÃÌlܶÕÜÈл„¯ù£l˜qÊæz=©Ùã¿;*yn€8üqÿviXÃeøj‚ºj¢Xÿú>Ûö­7ß{˜®ŽpÉ—“«t›™Ú&!5 3Wþ^.DŸ»߯õï/?ýÛƒq 7®ƒXS¯Y?Ã÷Äåö?¬õAlR ‚6®SÞö&ï¡Dùú_/_ƒÕ3¦a`—²e¼·ïÆôåkÐÕµ5T…B|ºÀ^½º+CÒž3þðÞ¾KùÞ?N‹'Œ­ðø“6>†ƒÞ¿ÂÎÚ ÛŽŸÂ\ŸÍÊ×[°qúwôÀ’iŸfÿ±¡‘·* \•‹DðýåGeÏVdL,‚Ã#* ]Oê×Ñs}6Ãͱ9ºº¶Æþs ¥)¤÷A¬)‚‡³ õta £S玫žn®èéæ*<j¾x«ïk3Ó9iÑä¬ÜÜÓµ°9• 3Õ:5n"}¬ÿýïÆÞÙwÜ´ŒCç/¾?küáÞÅóêdà€SÁ¡01ÐG# s$¤¦!!5 nŽÍy«ÜvO®¤ïæØéÙ9ʆžÀ×£ß/wŸÁÇë’ †…±‘2pe7ÃÎ{(AðpÄoÔ IDATH\¾y É™˜<|ÈjÇ#‡+‡ ›4°‚¤ðß éÒ²³Ë-ßaciÜG¡°*쬔J4ÔÕEVnÞKïcÇÖΩ©¡ý؉˜ºx9öŸ»€~︗»yx]ãéëV¨Ný¾¶¦è¸µ™i´¡žÞ»µ°)‡mP6Ìø¤û­Jž§ýèqÞôŽˆÞºÓÓë¿I´mwàoç|÷ITª>cìÈWZ2 ¶É}(AV^†Î(ƒÔ§ç\ ŸqSî´ìlÉŠan\ù-:$…Ò ó¿²'ƒË]áýÉX?mP—NØvì$lBC]+vìÁÈÞ½Þx­M ôqzí2ì<é¿Ë˜æ½B¡¿ÏúºÎkÃ{uÃî…ûÏ]°ó޶󨾕ÅÌìÜOr jÓ¥O3>éÊ–‡ Àå'ÛO|ô?þ¸'¢zºþ [‹?IÏÎQŸ6b†÷êVo>±¦ÆÆÚ¸ö•žÿ8œeçå?óõŸžŸö¨—ÌÆÒ\ù¼"Y±ròþ«.×ð,ÁápwvÂÁó€ïÆðV>㸤d$edâ‹Cñň¡ÈÊËÃÔÅ˱h‹o½øªBáãð¥¶ùȉ6+vþbkeq½…¯'‡ŸüÙ%EÙÒëœAYX"€~(›€àþ¸§Wõ0ý.bί‚uÛ‘0°iÏ‚Ð+{kË Õe_Mùñ£oVfl<||ʨ޽Ô/ø¬ªW ºº¶F\R2öŸ»Pþ·‹\^åÐÖ©µ VïÙ¯ Sœ‘©|ý„Ô´r¯¿tû.ØXZ CS8Û7ªP¿Ð+ʆ#}©Ö6†FÞ‚S“Ƙ3q<æLÞo8à<‘Á7"1vö|å"¯†ººkjBW\¿ÖÑQ 1ap\Ù¶^øá€¾mÔ5ÔƒíZPÆY3>mÊîÇhà(€®ƒºáõ/ŽJuXQ~\Ý IÖ}ƒþÛÏß·¶–Ù7«Ç7_ÍŒ¸+žâõ6èSéåÿõƒMCÌŸü ¦/_ù·ÂÚÌ ©ièÜÚEyõá‹,Ÿ>ãç.DÛÑ`alI¡½=ÚcÉ´Ï”¯?Í{%–ï܃"Y1„B!6þô-T…BXaÊð!øt7˜™B.—ãûñc°z÷~åëžþ’32!)”"O"Aû±e#6O_Åøöî<,ÊêïãøfØdPP•„ÜÃÜ•ôQSÓÔ4µ,wKMÍ~™i™¦™[æ––•[®©i¹†J.iš* ‚€€ ÌÀ < ŒŽàV. ß×uq]ps¯ç†Ïœsîsn§gPkf|¿†߯1-«WË—¥¼ûÐG·ô†y?l`ç‘£üºä ¶ýv„¶#ÆP¯¦/Éé×ÑåæòýÇ<•¯=k+†tïBßí¬–mÙ´|Û/çÝ]œEÅ^Îãíu·¯§~ÝjUá—/ÆAR£06; !D©ðH‡óÿêƒq#v q2â‚Ë[½ºóú‹LMZO;MŽ–³—£Ñ ¸88àëU¥BÞ` ñZ*®LÁT¥A›—WlnÉ¢ñ´\Š «ÎÒ~9•­-þ5|Š…Üˆ˜XÔ õj+;ÒÔjSÇüÄk©%Ö¼õK¼–ŠƒJeê¦ËÍ#9=ýF€:ʬßT\R2½Þÿˆ¶ðùèÅö›x-•­-ö*ÒÔjô†|³k-iÙÍå¨ÖhLç^4þ˜­••i\·ˆ˜X®¦¦RÎÖ–z5}å5xÓkdù¶|·}G®›³ÓÏ‘±ñ£)>Íçɲ0 Pž6ƒƒk•Ë×ËÕ¤ae瀅¥ùçrC®†¼5¶Žwÿ°¤ÍHÄZå‚¥Òæ?ŸONz6åÝ︯\MÀ]÷u?e`¡P`eëHê壄~Ûƒº½R¥aï{*ë\MùzÝ]Ëê^®­´i€ÊHMWQØšüÕw._zÑìIÂÙ» ÞÏÂRiCÜñµ$GS«ýøN trÝ’#‚ñm;çªÈÉH$*d>9éq´w˜r|H<³¿6 dznw<êv0í«v‡ÉÔhm|Ð56l5áÛÞÇÉ«>͇a©´!þäF’ÎíÆ·í8jµŸ` ©Ç¾îf dV¶Ć­&=ö†\Í]kºþ\ÙkQ‡¨Þò-œ½›Ÿ§%áÌ6®†ïÀ³nw꿺 €ã«_'õòQ|ێéJ=r2‰Ü?]f2­Ç¹ëÜŽRÓ%5]%†­·fͯҧ}¾^pÇÚ ñ¿À ¾™ô?ÒÔj¢Œÿ”jV©,á» pwvbêðA éÞÅæ‹6ŽH¾–>ÈÝÕùû§<|9†®)ÀÀxÊ@'ýrÎ^<÷æzS–sµ@ÎkJÄžé4¹×´^®&æ#÷âX¹žiÙÙŸ?Di­¢Ùˆ¦š÷Úí°uðäÂÞéĆ­Æ»ÙP®œÚJÆ•Ó<óâ|Z¼eܸ&ØØ»qrÝ⯣rƒ>D왎³wž²ÅTU±NGޝ~ÈýsñjÜ›òî$ÛƒG@S(_±6o:ñ¬)üÔë½Ø´/w¿vüñmO´êSíÛ¹áäÕˆ¦Ã·›óĹTøT¢³‘ûçaa© é°ŸMÍ‚ëtäo{šjùn'3)‚”‹ði>ŒÚ&™–W èÂoóš’öÏí“#‚©\¿—)¨\ªqnçǨÏ–ÚÐ%þ»‡òôâÐs—>y¦bð’/˜:|.‹ƒüjÑȯ–®2Æ«¢;óÇfõ´I1± Iý€¿‚§ô @Q´†—€6¥ýVmò†YŸ!k• õº“qå´©Y \³À¥N ';5Ï=M«ˆOó¡X*mH ß@Ò¹ÝÆcÝÒ\W±NGšÜKÕÀ$_ØG¾^GµÀÅú‹y5îOA¾žä Æ!ÕlÊ»‘LlØjÓ9:V®G‹Ñû¨Ð¥ð:Œ]·O ãÊi,,•4¶ÿ®Ÿkû¢“¯×Q¥QŸâÇ|ÎxÌ”È ¹®E­VY?, K%Õn¹¦’”¯èG‡O.™jÍŠäi3PZ«ÌÊÙZåÂÕs»‰ [mj†tönBó‘{©X§£¼éHM×ýÉÖj[çètÓÛ Ýf\¿ÞyC_~ÉU:+ Q6¥«3ÿ4mæÙÐðó퀭ŸŒyJ‹£8ìÅ8äAÊ@­Ÿ½{íbËlìÝФF›B†Ý-¾µê«¦@Qì»Ò[GO´Æ%mFvÎ^f}¼ŠBKQËIàüî©\þÜl½¢¾MEûóï:“S›F¾í}ã5¸ùR) +u»™ÎǧÅR. îϵÄý¹›òî¸Öh…G½î¦þj™IÆ)9#÷ÏåÒÁE·9f"¹š4 òõ%N¾­ºÇ ¹-•6\ ßIÚ?¡d§Æ•INz\±õºÍ6][ø¶÷)_ÑŠu:Q¥aoÊUð‘7 ]÷-¼   {Ž.·þÌ•k?Y²y[óɃXõiäø´ !DY£Óé.ž³ tÇ‘c­0ö_jŠL§ãÌSÔ´Z`Л‚Óݘ{áî×[‡’ŸêsñikÈÚþïO’Îï!9"˜´ËG‰ ™Ï¥ƒ‹¨×kžõµo-Fï#%ò7’#‚¹uˆ+§6såÔf³>Tn5ÛÞ¶ÙΩj#³x«[ƒdI ¹ÂVö#=&;g/+×£rý^8{¹o.×ãnŒ?\)  A>ÍL×v-êéÚ½¾Òì!¡ë~œ*((èž‘™ÕâƒKgLÿnu _¥Ï’M[ñõªrO£²‡=Ïú=ûÌÆ‹KJ6=­8nÞ"FöîqÛ§(o¶~¯±¡oyƒ)¥a+(tÂ¥d ¬.:±ø²¬Tw¨Y)ªÓ¤ÏÚùzt™É¦š!;g/R.†¯×þ b÷4œ¼beçh @EM„7‡¶¼œ ³'ü¼÷ëq?cÓcÄ>þÚ0œKáY¿'ùzºÌdÜk·3•¬”(NoI™mø¾ð¶ŽžÆ0W½y±Nð7³è ɬ”Èbךs×2Ž?¹‰ô˜P³ŽùE"÷Í5û¹¤kK:·‡¿6Œ rß ]O°G5"ýCAAëŒÌ¬W&.úúLà€aWw9¦‘â/Â/EßóÔ?)é×9zæÆÿßþ“§±)8ÄôóÑ3ádhîíÖ†…Ÿ',ü¼Ü€RBoÈ¿:iéòuÕ»÷eÇ‘cEaëe \eß•S[Ì~ÎÓfxzŽ•ëÝq)lÊ»såÔfS(¹9dr5¸Õ 2©ZAäëI8³Ý<¥Æàòá¯P'ž5…‰è£Ë)È×›­w~÷TöϬKÒ¹=d&E°oF"Ì5«ªX§#Vvަm-hÃßö0Û—½›/.…Sõä뵸Õl‹…¥’¸ãk‹óÂÞìŸY—Ä3ÛQX«põmErD°Yÿ+€„¿6ßµŒ‹†˜¸uȇìÔhS³¢òØ7£ÑG–š][¥€.X«\î«ÆP”=ºº)&¿ `EVNNÄ®#Ç­ÙõkWEw‹šU½¬åV<>]Z6£á-cYÝN­ª^ }¹«éçÙ«Öá_ÃÇ4ØÐ—»ây—q½Šì=@Çf2—Ùã[}ýíÏoNùÌý¯ˆÈ` 0›ë~|Ró…÷JÝIå¤ÇqåäF²S£ÉNÁΩ2™Iç9³y 9W¨÷ÊBʹT3¾9]Ž•#Uö¹,,±-ïΕ¿~äZäAlìÝŒÁêÔDì™­C%ê½²…Ò–òîµH:»‹„3Û°²uÀRaEZô1þþé],•ÖÔí¹;§*äf§q5|ê„¿±±wC¯Ë$æèr¢|³wjÿßDlÊ»“r1„äó¿b©°FiSŽœëq\ žEú?ax7†‹ÏóXX*H8½Õ´/C^É¿õÛʻצæ ï¡´-O~^ §·r=ö8¶•Ðë2ùçDù‡Ju¨Óe–¨\«w|)‚±uô$_¯%òÀ??µðÍô7)–¥TÓU£õhÃw˜#-WÁ‡:]>5kÆ ™ó圽h2dk±ý\ ßÁ¹™j€,,•¸ûµÇ¿ëgf5eºÌdÎlkÊÁX[@Ý^_âàaü`V¯'*äKb~_Nž6ô?€.øwŸ…•­ãm÷¥°VáÝtµÚO0õ½ŠÜ?—ˇ—šÕÄ¹Õ ¢nÏ/Íž¸¼tp1—.2;fÅ:ñïú™Ùz)‘!œýùC³²òjÜŸ {§ßuœ®³¿|HlèjSšMyw|ÛŽ£ _ϹÑdðT¨Ñ]f2§ŵ¨Cf×V½å[ø¶{O}觫쇮"o(,-§øTö´’ðõèõzÿ#šÖ `ük}˜÷ÃFÖí ÆÝÅ™;–¡fîúrW>ø:›‚C;o! {~bç‘cLX¸ŒÀ€gйm5À³ãËlžý)Íê0é«åì<|” ÀÝʼnÃaéæm¬ž6™v$t•ްe&;¥XžÜÐU2“"°°T–ø„Þ½ÈN&O«¦\oS8*I®&ì´hìœ¼Š 5a*°|=šÔ ¹š;î/O›ANz–JT|Jœ.'_¯#;=î®ûº×c‚±oXÑÓŒ÷‚ò´d§Æ`eëp×'‹ÖµTÚÜ÷q$t•M¥å¯2ä篊‹ïßÿ£O¦>ëëk1sÔðÊ5|¤·ýc¦V²li<­¨¸+œ<±Øz[4eÚò•øW÷¡M£Åß s´Ì7ŠvÆ'ƒÚ4j@Èñ“œ¾eZ&ég,íÁûwLX¸ÌS›—ç|l—ryz”4ôÃý¸×á ¬U.wÛð^ß•­#VŽw\§(´Üõ/à>ç¿ ¦V¶Žfc=¨u…„®M¬ÊÍ3¬=qþÂÈN£ß›T¿vÍ _ž§‡Ù¦U '®¾_óÇ&9ý:ûÂN“HDLì¿Úx a«>0X%å"„Ooèº9|-0äç}âü…áÇüobë†õuÓF ®êíé!wìxP3Ìûa# ÖÿX8wúÕBe+s->Ê¿¥ƒ'Oï>cŽZ£) [k ÿÆÄSÀÊÎ Õ›aSÞM C ]w¤äé ßí ;1þ·§Æ¶iT_-á«lˆIHdÞ˜õÎ^±ƒiù²ÍÛ¤pmØ >–HØzú8x”Ø1^!¡ëv²€©zƒaÁ¾°cž<ýN÷¶-³' PÅÝÙIî`)­Õ[¦É1.»¹ÖlëC$§_—{ˆþŽº<`Êôœ¤Ôô†À\à¥Â0B!$tݳëÀÔ<½~ÉÁ!“~:phÈËA­®Køz¼Ú6nÀÒÍÛý“CË›–û×ð¡KËfŒš=Ÿ?ï"M­ÆÍÙ™– êqör´Üà [Í€Å@ÿÂ,B!J‰²üèg%`‚µ•Õƒ^ê¤Û·w¥›;‹{—œ~[++ìU¨³4hóò¸9ÈÞ¼L“£%M­6Mû£78y ¥¥%õjù—”Œ»³3EœŸ¾Ezf&•*TÀÏ»*ê, ­× ¤©ÕÀƒëCö4ŠON9Úò´„ÈØøÀ2`OÑÜ€¥H©2BˆI†ŒxºCWo`Š•RÙcp·³%|‰§,lµV3€kR2ºÄ“åÒÁÅäe§á×éc ]OË'àb€yz}£e[~ÞÓðµ!i‹7n¹¦ËÍ“»+ž8éêÌ¿_~ïà †UŒžÆIàâÉt-ò‰á¿HAHè*u¢€ÙZmë™+×þ^ç•×2$|‰'-lù÷à~^ 4- [R½"„º›ð‚‚‚î9ºÜ63W®ý½~ÿA×Öî ÎÐ r·E™£Óé. ›>{ïÎ7…­kx…øÏò´äjÒ6#Ñl~ÃÛíK—yo çjÒLó š½æ3“ïzœ‚|½iÈ;1äjn»¯œô8òõº»n·ãäëïi_Eex/ëå¤Ç™æoOå|m§ ºgdfµø`ÁÒÓ¿[]gòàV}Ú9*2À½(ýakôœ¡;Ž Ê€p)q;!sžÃ# k±¾?§6Œ =îmÿ÷'»§‘w‚g:}ÌÙŸ?$ãÊiÀ8EP@·Y8{71 ‘ûçrƒ)˜9{7¡NçifÓ×$œÚBTÈ|²R¢°uôÀ§ù0¼› 5Í'st9Ñ¿C£×Vð÷Öñ¦ãV¨ÞŒú}–‘•|³?O$+%Ê4u½^ PX«L×çÝtÚŒDþ ]E¾^‡µÊ…jÏ2›$ºèú|š åÔ¦‘ä¨ùÂ{ø¶Kž6ƒˆÝÓH8½ C® K%®¾­ðï:ÃlŠ£ÔËG‰Ø=ÕtŽ k]¨Ýa’i.I]f2çw~ÌÕs»MAÊÙ» Ïtú'¯Ffex~÷4®üµÙ]}[ñLçifÓ2äë¹<‹˜cßcÈÕ °VQ£µÌK+¡«ì9b((h‘™Õf⢯§Í[³¡æô·†”±ESém/J½!ÿê”o¾;°òçÝM ŠÂÖ))q/µ#¹šÔâ>+™œô8ÓϹšT²®FðçŠ~¸ûµ§ZÓÁd§FsùðW_=€6&‚>ñÃ@®EÂë¹þT¬Ó mF‘ûçòÇò´óvÎ^\:¸˜ {§ãäÕˆú½—`©´!þäFÎïšJæÕêöZ@^Žqâê°ï{ãV3ˆjMs=«8¾úu²Sc¨ÚdÕÝj’pj3WÃwP¾¢5_xÏt}—.ÂÂRIÝ_`SÞø‰Ü?—Üì4ü»~fv}§7ÁÕ·ùzön¾äëuüñu7²R¢¨Þò-\ª7#;5†¨ùü¾¤#-FïÃÎÙ‹œô8ޝ~{7_ê÷^‚Myw®Eâòá¥è²RxîÍuœ\?uB8µÿï<ë‘•|¨ù„~×›6ãaSÞÝxÌå=P'žÅ»é \kµ%;5†Ë‡¿âèÒÎ4¹×4Çcøö Äý¹ϺÝñlÐ MJ$—."/G­£ .¡«ìùMo0´ºššÖyÄgsgº:;¹Iø*N“£E——û¯‡qHS«ùtù*>úÆ=ï#ñZ*®îùagϳâç]¤¤_ÇÁ^E¿ŽíËüÚ·„-OàMàˆ¼"Åç͠Vûðm;Ö´ÌÂRAäþ¹¤F¦R@’/ìãZÔ!j´Mí“Lë©\} ý¶±a«ñn6”Èýspð éðí¦Ú¦J]8¹nñ'7âÕ¸ŸYí™GÝT¥aoÒcBɸršº½R¥ao<ëv#xz®]:l ]Æà¦¦Åè}¦¢ 5Z’›Flèjj´m 'yÚŒbç}éàb2“"x¶Çx5îg\XÜj¶áЂ6œß=•†ý¾%5ú†\ ~'S¡FKÓqô¹²’"È×ëÐë4¤Ç„âÓ|>-Þ2ÕØ•«àÍÅ_?'+% ›òîĆ­&ãÊiºÏ¦jàÓ1+>Ó‘ßæ=Ï…½3hôÚ ²S£‰ûs-•ºPÿÕeÆõj·Ãŧ¿/é /Ø'ˆåSxÍ;õùùu¯¦¦xëó/¢[ ÿû©ð\y)SЈ1DÄÄþ§Ð¶1ø€iDú»Y¶e;£gyÏû?rê ½Þÿ•C_WeMÉš]{Ëj±__¼iˆê]_IY±}—gAAÁ ­.ñ°U èbö³Ka0ÒçfrñÀ°P¨Bõf4¹—ê­G‘|aùzÞ͇™W‘¢¦±«gwš-÷|¶›ÙÏEÊ# óLJ¬U.h3ÌÖuõmeÖ$Wt~ùz’/›§~O³Ÿ“ÎíÆÊÖÑ슔«àƒ‹wR.†`­r௟“zé°©éпëg4²K¥ VvXÙ:’pf±a«MýØÜj¶¥ùȽT¨ÞÌtL…µêFÈ+dëè[­ R. _¯#ùÂ>¼žëo¶žcåzfM•BjºÊ²íyzýö¨¸ø7^ýpÊŸÊžV3Gwo^?Àúi®åŠKJ~¤Ç¼pŸïËu?Ò²A]æŽ}€M˜µrÙe$l홽r¿>?ߘ씷$ñ¨”sö2_`aÞ×USØ?ËîÖõ Ã` Eön5Š­S޲ojÚ4OóOþJSß­;qðð/¶LUØ<—sËqŠšíŠd§E£ÏÕðÛ¼¦Åö‘«Ië!'=·šmð¬Û„3Ûýî,•6T¨ÞœJ]¨\¿'–J,,•<ÓåS·ýðmï¾í}+×íVUö6õË.ì`»cæëuè2“Ѥgé°wõ-¶ž½›/º¬dyÁJèzb¬2ä篊‹ïßÿ£O¦>ëëk1sÔðÊ5|J}oû%›¶âíéALB"!ÇÿÂÆÚŠ‘½{àUÑÙ«Ö‘x-oO>òEÆÆ$$²`ýfâ’’±±¶¢Oû ^jÝÂØ,øí*Ó~35ÙthHDL,ßnÛAL‚ñ oOÆôíe‘>M­fÁúÍœ½‹£½Û rßnÛÁÑ3á Tv¶ }¹+-ê×eï±0BÏž';'‡qóñÑÐ7pP©X¿wûB£ÉÑbcmE»&Ï1°k'¾ô"ÎåÍŽáUÑ6§Œ¼Ü,´?ïß1aá2Om^žð°]þ Å£Vvnç~žž»µ–ËüwŠGvÎw:'Cž[Gª4ìsûˆvXX*©ÿê2|Z¾EÒ Pr IDAT¹=\‹:DÊŤ\<@ôá¯húÖNS™[Í6\=»“äˆ`Ò ›I/\Dã7ÖàV³­©æìnÇ,È—§ë%t=]ôÀªÜ<ÃÚç/Œì4ú½Iõk×Ì)íá+äø_„_ÞJÛF èÝ>ˆGŽ2hÚçxºV gPkžaÞš Ìû61 ‰´ù.í3ªO¢®2þË%¤ª3éÝ®- ýj±ãðQükøPÅÝÄk©t7.-š1¢WwÔY¾\¿‰AÓ>'xÉè úLü¥BÁ¨Þ=H¼–ÊØ¹ Íαÿäièòòx«g7ÊÙÙ±eÿoô›4ß¿ÿŠ*în¸;;‘¦°¤iÝl¬¬™¹â¶ìÿ oöÇ«¢;GO‡3iÉ7Tp(ÏK­[й…ù'Æäôë,ݼžAmÊRتLVÉŸžxJúçmÈÓý«}•«àCêå£è2“MOì‰Ü?;窦åÙ©1fO3d¥DÛö¿ÈLŠ(¶ìN5r·Öìé²’ÍúˆÑe&£´Q™jÛ²R¢p¬\ÇÊõ¨Õ~¹š4"vO%þäFNm¥ÚóMÛT{~ ÕžHA¾ž«á;ùkÃpb~_Ž[ͶXÙ:’“götåÍ5] +Ö*T¼ kãbŠ]GžV-/ì'éÃŽA±ðµÀŸ_õÄù _tó¿k>ž[TËS¹;;±tâxz·oËGCÞD¥aàK/2²w^±½ÿ/ˆ°³ç˜÷ÃFü«û°tâxÚ4jÀÀ®øxè›ÌZµ¥Ba 4m5À¿†—â¯Ð.°1óǦ]`#zµbÒ œ½d¬ ßv‚ 1±¬š:‰Î-š2¤{& ~Ýtnij5î.ÎÌw4/µnA»ÀF|9þôç.Çà_ÃOÜéݾ-*;[´¹¹L1˜¾ÚÑ¢~]Þ£õjùw¥ØµÇ%%Ó}ü‡¸;;1uø Rûš:xòôÏ~=û3oQ}m^Þ7G‘—À%xÍÕ­¡D›‘ˆ:ñß4âZ£ §·˜-ÏN&rÿ\Òÿ Å­f[,,•Äüñ}±ícÃÖàV+è]cjÔábcŠÅ_‹…¥÷Úí︭[­ r5i$žÙ~K¨ÉàÐü–œß0>Exh~ ÓðEµUõº¯×’zé0ûgÖåòá¥f5k•:ceëhª%t÷kOž6ƒ¸ãë̃p®†Ã ÛðÛ¼¦äëq-¬‹ûsm±ûWÔ·NHMדL ,ÈÓ¾Ûvbüo'NmÓ¨¾zÚˆÁU½=K×£»üj›¾/šdºF•Ê7–YYS4*ØÙóxUtgÞM¿OIOG¥!*.ž[ç¬lQ¿.Ï?ëÏé‹Q\ŠO *.ž£gn¼‡=Omïªf“c·iÔÀô½‹ƒßLú1 ‰ìcŽZ£ >–{!8·ZA$ÛÍß?dz^OtêD.îŸ[Ø!ýþ?8V 范G{fo0àî׎ìÔ.ìnCªÕ(윽ði>ŒË‡¿âäº!T{~Jñ'7º WßV¸×n÷À®1O›AØ÷½©õ`cïÆ?Ǿ'9"ŸæÃî:¬BõV£¸rj3g¶¾KvznµÚ U_%rßò´ø¿d|¢²jàëÄý¹–“?¼I­ö`_ÑMJ”éº+ùwÁÖÑ{7_.^Š•#.>M1è4Ć­!O›AÅ:Æî>-Grgþ¼5nµÚ ËJ!rß\t™É<Ûã ,,•”¯è‡×sý‰ûs-–J¼›E«¾JÄ®O¤éQB×S% ˜ª7ì ;1æàÉÓïtoÛ2{Ò Une‰F«%þ–Îò}Úacm]bMRÿÉÓH¼–J½š¾ø×ð¡YÝÂΞ7'G•yP»y˜½ÁÀ¸y‹Ø~ðþ5|ð«V•V ë±ýàíÌ[¶e;Ÿ}¿oÏJøyW£^ͦþc7KN¿Î‰ˆ‹üòå¬R¸þŽº<`Êôœ¤Ôô†À\à¥Â /ÄCÐmzmq®5ýó.z‚0rÿÜûÞŸ…¥’ÀA›ßþ>ƒ?çÂÞ週cw“Á›LÅý:}ŒU9.\ÄÕð¦Z·ê-ߦæ ãè5V èB¾^ÇñU¯ÆÎ÷¾mÇÝÓq¬U.4¶ðí¸°wºézlÊ»S·×BÓÓŽ4ì÷-g™ÈÉuCLÛÛ»ùøæ:Só_ãkøû§ñœÛñ‘i+[Gjw˜Lµçš~n:ìgÎþò¡Ù1­U.tŸmöTc@·YX*mˆûs-ñ'Œ«4ìƒcåú¤ý*/p ]O•ëÀÔ<½~ÉÁ!“~:phÈËA­®—µðå`¯¢¡_-f¼=Ô,¼œ»WEw’ÓÓÍÖÿâ‡è ùœZ·•-ë÷î3ýÞ׫2{Žš¿Ü\+µ?ì[äÀ²øyW@¥aüü%%ž_šZÍ´å+™1r˜©ã<ÀÆàâÕë¶VVŒíUjÞT«WŠÂV3`1п0¸ ñÐÙ”w§É­è2“Ѫ±wó5õQº¹SÝ^ L–Þ¬Bõf¼øÙÕbA¥a¿oÉÓfƒu9—ûNÕh=Šê-G I!_¯ÅÞ­f±Nï5_x¯ÄþT·;Ÿ¢ôÍþaY«¨Ûï[Ó5–¯èWì8·Ûû©ÚD®&œëqXÙ:˜D_¤bŽT¬ÓmF"šÔhìÝ|‹õM+WÁ‡&C¶šöUÔ7ëÖ¾[vÎ^4°ÆT†·[ÏÂR‰×Ïðë0‰Ì¤ʹø˜†¯OéÓu®ãôC̓C6–>mùŠ«ê,M™8ùî­[°)ø€i.½ÁÀ§ËWšBPQmW¶Vgª³µ¶2Õ$©³4¬Þ¹×´mçMÑhsX¶e»iÙ‚õ?šŽ§Ë5æxS³å¬Õæ}\Ðh•@Ec{Ý\{¶õÀ!¢â®rK ÔæåáUÑmÞãŸÐ<>9åhëa£7w5þÙ¤Ôô“@M`ª.ñ¸Â—cåz÷4ý²²uır½;vV·°Tbïæ‹ƒGÀ}=eø_®ñßÇZå‚cåz%.³wŽT¨ÞìŽíËÞÍ÷ŽOq•áÝÖSX«pòj$KjºÄM®ãróò,Ûòó”ï¶ïê1¸Û‹Ùcûö®tk¿¨ÒdxÏnDÅ]áÿF¾K½š5H¸–ŠÁ`à›Éïccm…»µ~ÞUðñtú´bä+/ÓçÃO1wgg¢éÓ>ˆÓ£8{)šzµ|Yüþ8F͞Ϧàddið¹©ÏÛ ñó®Jû·ßÅÏ»* ×Riâÿ Þž$^3NWÒЯK7oóãËZ¾˜žA­ÿåbVï܃Z£AekKû&M뉊‹gì¼…lžý)«¶1>9åhÿÉÓ"cãÛaÀ³…Á\!„(þáDŠàð&•³µ}ilß^ùC_~ÉõQô3JN¿ŽRaiêG¥7H¼–Š»³³Yí”F«5›f'&!‘˜Ä«”³µ¥^M_³>QºÜ\-3ìíUu&`Õ§}£R¡R)Cakôœ¡;Ž þÀ8eO¸”Œ(Ôt‰'žÔtýwRÓõp1´ÎÈÌze⢯Ïvuבc)–ÒMoÈ¿:iéòuÕ»÷eÇ‘cå€NÀ˸„Bü’X­ÎJKË™®ÎNnÓßRþÅMUR$¥+lMùæ»+Þݤ   cÍÖ)q¤¦K<ñ¤¦KBWYÕÍJ©œ^Í£’ÓÌ‘ÃÝ›×°–"y¬®/Þ´eÏì•ëüõùù©;Èÿ&Å"$t !¡KB×“ã …¥åŸÊžV¾{Ø2“R,BB—º$t=™”@k+ÅÔg}}-fŽ^9 †ô¶¸/{íÁûwLX¸ÌS›—WøØ.å"$t !¡KB×Ó¾F*,-'Õ¯]3GÂ×C[îÀt`•”‹Ð%„„. ]O'[`¸•R1±uÃúºi#Wõ¾ijñ¯èž<½køŒ9vjƧ0l­ôR4BB—º$t {`¼R¡Û¦Q}µ„¯ÿ¶ž>–Hغ„Ð%¡K”Ä c¥T¾Ó½mËìIƒTy\<—%G]0ezNRjzC`.ð5 •’º„Ð%¡KÜ+0I©P y9¨Õu _w [Í€ÅÀ< KJFHèBB—„.q¿*¬­¬ÞôR'ÝØ¾½+9ØË«ñÉ)GûOž–ßX,®ËËEHèBB—„.ñ_yS¬”ʃ»½˜ý´†¯›ÂV;`%0¸&/!¡K ]ºÄƒæ L*gkûÒØ¾½ò‡¾ü’«µÕÑéêÌ¿M›y64ü|`0 ÿzâqIÄX -Ä“ì* OtIè@€……Åt[k«6ãúõÎ{RÃ×Ma«°ã”=1rû…BHèZ} ‹OìUÍ'`Õ§}£RQöÇXÕét—FÏYºãȱVÀ>ŒÍˆQr»…BHè[ ……Å {{U²¾n [AÀÀG@¸Ü^!„ºDiÓF©PLsur¬9ý­!å_lÑ´Lô¶×ò¯Nùæ»+Þݤ  àoŒÍˆ§äv !„Ð%J»ÎJKË™®ÎNn¥9|ݶâ0Öl‘Û'„BB—(kºY)•Ó«yTrš9r¸{óú֥伮/Þ´eÏì•ëüõùù©k¶~“Û%„BB—(ëÞPXZNñ©ìiõ˜Ã×ÍaËLvÊíB!¡K’cë ¶8ļ5ë󬬔§¦g ËÈÎ>!wE!„„.ñD†­”ôëÖcû¾Bïöm˹è Vþ²›ë48Ú«NKøB!¡K”y!!Ê/Ù2ñ—C¿O¸œpU5¶ï+ôj…Rñø'&Ðåæ±f×^mÜ’çX^u8*öÊp JîšB ]¢L†­ðKѪQ}zòf×N¥"lÝJ“£eÙ–í,ßö‹ÞÝÅé„/!„ºD™ðÕãFì<:ãdÄ—·zuçõ;`cmUêÏ[¥aù¶|·}G®›³ÓÏ‘±ñ£«rGEidïæ[•"Ÿ „xDÏ<¬KèzÂÃÖ±3á._z‘=»¡²+{S"¦©Õ,X¿™u{‚õžn®Û$|‰RªàÅÏäe)DY·ëÃJ5Ièz¬ýtrm‡~_pðø_U^ïÜ‘¡Ý»à`¯*óוœ~%›¶²)8Dçêâ¸âR앉Àu¹ãBB—BB—x,akï±°*}Ú1¦o/\ž¸ëŒKJæ‹6²ë÷?rÝ]¿—ð%$t !$t‰Gbýìi-wüý›=GCýºµiÉÈÞ=pwvzâ¯;&!‘ë7³÷?5æ_ºre •W„Ð%„Ð%JØÚqø˜_û&y÷µ>xUtêÊ!"&–Y«Ö=®uwrž'áKHèBHèÄžÅ_øÿtàà÷?:تA=Æôí…·§ÇS_.g/E3÷‡ ÇÏ]È(_ÎvJLbÒW€^^1BB—BB—øWa맃 Ÿ©Íûúáç]U æagÏóùʵù‘±ñj _BB—BB—¸g,_XeCÈáï¶…nïçSÍb|ÿ>ø×ð‘‚¹‹£g™»fƒ!&!1E©´Ÿ”´NJEHèBHèw [žn®ï¿Ñ@ÿg¤`îÓ¾°Ìü~!=3S—Ð%„Ð%nˆùÉiùš-K:pøg‡òŠw_ëC³ºR0ÿÑÞcaÌ^½VŸ•­Ñhu#Ó22~•Rº„ºžò°e©°TLx£?íIÁ<`›‚CøbíFCAAA´„/!¡K!¡ë© [+l×l<2ç—ÃG‡ekµÖï½ö*šJÁÿ9p…=ϸy‹ض‰×RyÙ¤©ÕŒ›·ˆ4µºÌÝWwg'¦įKæÙ4®]{Dùrå’jT­¼p’W½B ]ÐúÙÓZèÜáü¸/oq²·¯rhùb¦„‹ƒÃÙLÂU6øWÛ¦¤_çè™pÓÏoL™Áº=ûyir´l >€&G[fï³WEwæÍÞÅs­×®=©|ùø•+ H›±B ]"lœ>÷.7Ïï—/g1uø ÜKOHçM ]õµé爘X¹qÿ‘·§óÇfëœé*ߪ•'•W•K“ð%„ân”R÷oÏâ/ü:pðûwg/lÕ ;¾üoOGvüäôë|ñââ®Ð²A=†tïRb'ý°³çY¿góÇfɦ­¤©Õì9Š­µ#{÷àôÅ(–üøijTv¶tnѬÄAZ#bbùzËv¦dÖ\ºdÓV\èÛ¡1±|»m1 ‰¦p2¦o/¼*ºÛß§ß®¢CÓ@³I¼o]vôL8+ÙMZ†G†÷ìF#¿Z·-—ßNüÅÆ_’nìnÕð™ZŒyõ•‡öð‚ŸwUVL™hqöR´ÝÜ6Lºž•5ª|9Û)1‰I_zùKBq3©éºÏ°5¼G·ÐM ÿçêÕÀµÓ?fþøÑ4p±‰0.)™Q}z0 sÖí fÊ×ß—¸îÍM“þ5|°±²Æ«¢;þ5|HN¿N¯ áUÑw_ëC ÿ3¼÷å¶8Tl?>žì>ÊÎß™–¥©ÕÌýanÎÎ$^K¥ë¸  FôêN¿Ží ;{Ža3æ”x^;%&áêm—í ;AÿÉÓð­R™w_ëƒWEw^ÿ!agÏß6p øx~ÞÕÛï:·lƺÝûøôÛ•ý~ø×ðaÅ”‰ß}<Á©’«ëü ŽŽ)Þß‘5âA;³y qÇ×IA”é1¡œÙ<†¬”ÿ>Ôߥƒ‹‰Ø=í©(·¸ãë8³yŒéç¤s{8³y ¹š´'âúäŸÂ=øcùÂ*B7bÆìö~>Õ,ÖNÿÿ>í|N_ŒbÙÄñ´iÔ€ÊݹøÏÝ› Û4j€ÊÎÿê>´iÔ€£gÂÑähÙûe\hV7WW*¹ºÛÖÆÚŠî­[°eÿAúvhÀÎ#ÇpT©hÓ¨>ü}–v™?~´i•-§ÎüW×8iÉ7 z©3ï¿Ñ€fuHNKgöªulžýiñ?Ô¤dFõîÁ˜¾½hQ¿.ñIÉœ¾øèÆ6 ô†­s¦[=î4w͆/´¹y•J«ññIIò_R<ñ'7àÕ¸ŸF)§Iû‡ø“©Ü°ön¾ÿi_×"‡_§ŸŠ°r#u{-@NüÉÔ|á=P¹HèzÂÖ«ÖÞÓÍÕâË÷Þ1k{\Ú7įÙ_²vÏ>Z5¨KçMMAè~T÷ÁÝÙ‰fƒÞ¦m£´mÜvMÝö€¾ÚÑéÿ‘x-× lÙž/´A©PТ~]žÖŸÓ£¸Ÿ@T\¼Yþû‘œ~¸¤dR®1åj†JÜæõ; ËÍãè™pþI¼JTÜv ÅÓµÂ#¿?Íê°uÎtž°•f~¿fu¥ .ó$| !„æÅD‡üäôá ×Öœ1/&,üüÿÍ7ÒbóìOKEàøîã˜õÎTv¶,Ú´•fƒÞfôì/ï{?ö*~ýj>oõìNJúu&,ZJ£×†°~oÉO7֫募wU6‡“HØÙó¼ÒÎØÿ+&!‘ cèóá'¬ÛŒF«%0àß•—.7ײⓒM_.toݲÄmŽž §^¿¼=s{ކ¢PXR¯fÇzŸÚ6bÿ²/3G ¯T¾œÍ*¯Šî‘.ŽŽÿ'aâQÊÓf ËL¾§õþKνnoÈÕ§Í(¶¼ _Ûíu™É%nSÒ9äëu÷|Î9éq÷|ÍÚŒD òïÜU3W“†!Wó¯Ë0W“vO×y³|½Žœô¸{Ú÷½¾îe½;•ÓÝîA®&ížÎùI$5]·„­åkô÷Š IDAT¶,}qàØW,–Љƒ^§]`£RuŽê, Çþ>K¶­éÛ¡zƒ5»~eÒ’oÓ÷|½*ßó¾â’’ù'ñ*cúöbLß^hr´¼÷åmÜzÛš³ÞíƒØrà üjáç]€ë7£7äsbÍ·¦Žë· oEn³Ko0œž€‹ƒJ…‚žAmèÔÊ´NDL,jMÉoh“¿ZN«õøfÒÿLË>X´ÌÔ©þqêÐ4M•›‚C|¿X»q—ÊÖ&Z£ÕLËÈøUþêÄÃ’xf;‘ûç˜úÙ:zPíùÁTo9 ËoýWN¾í}2®œ6~ó  û,þÚ0ŸæÃðn6ô¾ãÛvUÜøÛÝ=ô¸ToñmN¾^‡oÛq8xøs~÷Têöø‚Ó›ßA›‘ˆ[­ ž{sùz¢B¾äŸ?¾7#j¾ðët4íûÔ†¨Ü|‰ ù Kõz-Ä£n·Ï7ãÊi.Ï"õòï¦p`ëèOóaø´xË´^Èœçði> CžŽè#_‘«IÃRiƒG@WºÏBa}㢔ÈÎïøÈTnµ‚pñivO÷© _OlØ.\ˆ6Ãø’½›/~/~‚{íÛ·`¨ÉØ=ÔËG)È×c©´Á³nwü:MÁú¦f¸ø“›ˆ ™Ovj4Ö*ª4|•Ú>4{$ÛCäþ¹¨ÃÍ^/5Zº§ v1xñ'6šB§«o+ºÍ¢\Sؾ<‹„3ÛL¡ÎRiC¥:x¦ó4lÊ»KèzzÂÖ Û5Ìé=êÃaÙZ­õûoô£CÓÀRy®ú|C§ÏfêˆÁ ,œ0ÛÝÙ ¥BqOƒ°ªìlÉÖÇÊú+â"cæ-$xÉ||½*£²³Eeg‡ãöÓ»}[>û~ ijÆö{Å´\£ÕbkmešSR¥aõν¦@u+wg'Ž gH÷.( ¾Þ²]nžé;6kÂâM[hÓ¸>.¨³4¼ýù<¼==J¬qÔææá R™´m”ªá;z·oK VŠ­ùÎ[³~‡Se¿SÓ3†edgŸ¿Bñ Å]ιáX¹u{-Di]Žø“¹°w:YIÔë½€¬”(þXÞ¥ ÿ—fbëàÁ•S› ý®·±F*çε.±a« ßö>N^hðê×X*mˆ?¹‘ðmï£ÍH¤Vû …5©d]àÌæ1T¨Þœ‚|=ön¾ès³ÉIãôæw°±wÇÉ«åœ䎯@ÊÅT®ß‹J]ÈÍN#æ÷o8ñÛÔíµ* {kÁ²’ÉLŠàê¹ÝT¬ÓmF"ök—x¾Ù©Ñü±¼Ö*žyñìÝ|ÉJ‰"ú÷o8¿k**·š¦ ““Ç¥ƒ‹°°TàÓâm¬U.$žÙÆ•S›±°T˜ú¥^>ÊñU¯cçìEÝ^ Q(mˆ [ÅÅàÏïé^Ûù1ÿûw¿öøwI¾^Gäþ9œXó&ÏÙ‚³w“ƒãË{ °²Á¯ã$Tn5I åòá¥\;AÓ·vbeëHò…}œÙüî~íy¦Ó,JþÚÌåÃ_˜úˆ%œÚ©M#qð n¯…Æk=½ {§“s=Ž€n³îXÓº¼'™Ix7„k­¶d§Æ±g:ǾéF«q‡±²uä亡\‹:„Oóa8W ¤ _O™m$œÙF~¾ž†ý¾•Ðõô„­ÙÃRÒ¯[íûJ‰Ã%”&.L1˜)˾cÍÎ=ØX[óSG ¾§€Ñ´nK7ocËþß8þ÷ì>Jû‘ã¨îC†FCZF&«¦MºãñÛ5iLÈñ“tkÕ´|xÏn¼:q A#ÆàîìLtB"}Úqúbbb‹Â1ýz3tú,¿6…B§õjÝèl:ýí¡ ž:“&o §^M_Â/GãUÑÏG(ñ¼ÞêÕIK–sör4JKK’Ó¯Ó½u ¶<‚Þ`@©P”Ž?8…¢(|Y­üewÃë ­^Ùã´„/ñ äjÒˆØ3òýx~èVSL¥€.œÚ0‚+§6S5ðuœ½›p1øsòõ:ßÚIùŠ~T¬Ó‘SFpfÛ]k7ÎïšJùŠ~4¾ÝTkR´ý¥ƒ‹ðjÜ;g/ÓúÕ[¾mÖ<þä&윫òü-¦}$ÛCÊÅTmò†Ù?|ϺÝ8¼¨çw|„G@gÓµåjÒhØï[*t¹KH\ƒ!WCƒÁ›pò2¶bT¨Ñ'¯†ü¾¤©Q‡Ìj—òr2h3þlO¨WiØ›ƒó[’tni‹ûf¡´VÑtØvSmM¥€ÎYԎ̤ˆ;žONzœ)p5°Æ´Ü¹Z ¿Í{žK‡Ó¸„б{*ùzš ¹qßÜk·CåV“3›ßáRÈü:}LrD0 ^]f*+÷ÚíÈ;ь™¯×qöç±wó¥éðífë)lTĆ®¢ÚóMǹՕS[P'†S§Ë§7jEk‚½'× !áÔV\|ššîçÿ³wÞqMßÿ@BÙ{(HP ~R¿j]¸pV«uV­úµjÕªÕj­«Õº¥Új‹U‹ŠŠ_ëÂâªÐ Èž²W  ߦ ä¼_¯¼”ä¹÷¹÷yî½ùäœóœSwþÍœ†áæ®(L¼ÙnîÏv)ºj¯]cî<zå§Ë~\‘ü4‡³xâ8Œöé×j¾˜_dhŸÞèíì(ÿ{úð!Ú§7âÓÒ!‹áloWoðû‹Ûnúlü}½!ª©“ÁÀþ•K‘˜‘…̼ŸÇ”T KÁõY¬t½X¹ù#=2yqWê]yqaPSg*­¨5qˆ> ¯€ch ‹ƒA_'©îjêÌfDZ‘èjcbëÃeÿ]ÁKJá,?Ǥ.ºÖŒÄí§˜àÓD_¯I–-UÛ¾(^¸Ö–ÍŠÓÑæ¨teèè «³Â{u£¾˜$Õ@GGžöBvN/ÒœÔæF†rQ'6ª³¶&4Y˜é7 ùj8}Ö' ø|¬‰Þ _DKHcw´ô¬”ï]sɰòüDyÀsC¥võ}ÁÖEfÅI¸ºI×ë»Êb¥d1J24غ*÷õbJ…Š’ ¨©3åV2…¶Òc«(ÉP)êLÍ&QÊ­ýà?Á³’ òê ¦ç( ³Ž0yV$kUcÈ1j˜…ÜÇ¡Èzt YNAƒ­ ã®Þ0sÓƒ¡¦Î”´']ßÔ;Šùe ù õžÃ³Â°uÍ•›:SSáÔ™šÈá]@QZ$ž¦¢¢8ý•ä0#ÑÕJÙ÷å’¹ÃÖ¬Þô0î‰Á¼±~8¼ve£‚x“Âzé”ñ˜å7ŒâsølHŒ±¾Þ¹„ôÌ…rh„ˆWÁ‹©ºIÕ—mS0¶÷V)Žd–¢¦Cűªþ1¬®Þò¯­’Œˆ<ìQ%tÌ¡cás§aè`h‹ûSšÿC^ür…'Ä"ákíSƒ­‹懢(år_Baâ y•·â#ì\ºðµ•…!ˆ—EG›ƒ¥SÆcúˆ!¬]¿û4¿ÀÏÂØ(¸‰¯£„–Hÿ­¯Í-‡éªQ„­+qIUò³•>“Y§:ÚÈ­C²UmªÚ5¥ƒ.ȃÚë~ÉVW”¶xE𦶠jD•¨,ËSÚ‡ìØØ:ͯò8d-jkDè³PÑ]ÖR‹ ÇØT¦?¨*ÏotûR±ú¬(UI¸¦ý}5"¡ÂŠJÉÜI¬ÿ‚zŽùYq†|_²14´ë C;Iºg…)xtr o $ã|u­\”VªÖˆ*Q%(Rp±¾ˆ–~'$Þ@¨RÉÚwiô¬ÝPõLâ†åz/‘/®‘pe{»º?ßÙ<]Ç¿ùjô¸Þ_<ºßÁ¦“AÄ‘}X:e< .¢M` £ƒõsfàö‘ýÌî=Çêjk§Úu²Ü@¯œþ'æø¦‘6}èJQÆØÞjêL¤ÝýYÉ ‘~÷g€‘]?¨©3aá쇢Իò42’oîor?é‘Jý$\ÝŽ«›‘}¶Eç ‹ÏJûû¨’U%ãÞq¨35›œ’¡.‚üD°8JîÓºñÍÅ1€®¥ r‡*å¶ÊztªÑíeB(ëŶâ*®nCŽŠãÒìh"é3.LÉ}›Ÿp Å0îê¸spnï¤`Íì`h+ßZ±¶^Pgj"ãÞq¥yL¹€ð-=å×Êë «7jkDò87…ÉH¾¹üì¹@4ì¢8gÅJ×Þ»Î;gé:þÍW£ƒoÜÞ5oËVãú üà®zƒÌ ¢µc¢¯‡õsf`¦ß0Íï š›WP<ÃÄHÿHRzÖJ%ïøé/pÀßt%<§(í®BmººX÷š}OØõ_ˆÄk?àÁ¯ÓaÛg˜šd> BÚ#0ìâ%@·ÿð ä'\CdÀtî=l]sä>EQjd,]æò~î›»þ ¡ÑA9¼ H¾¹:æN0sÚ¢s4w‰´»?#éúnÔˆ*aá:ÕÏŠ‘t}7ÊrãÐuà— ¹¨šŠ^'wäLJ#åÖ~˜9ƒ¨J€ìè³H¾¹jêÌf%V•á0dîñÇÝ#þè6ø+hj#íÎäÇ_kt[s'XºŽEæÃ hhéÂÂu DB>â¯nG• ='|Ñ`Ÿÿ4Ý~ mÓn(N»‹Ø‹ë¡ÙÑD¾ÁöƒÙxtr>ü:6Ì[Ç¥YÑHº¾ZúÖÐëä5u&¸ÞKöîñ‡mßÏÀÖ1C^Ü$\Ýmc.¬ÜÆ×{Ö½&!åö!ü¼ÕB>ô;¿A~_XÍŽ&èüÓQ”"©Ù›t}7XÚÆ`²8(Éxˆ¸Ë¬j͉Ë#Ñõ–ùm놾—®ß>´äû=#ôÅ€=­*GA¼ Ö¦&øaéB,š8–µë·Ss ‹ùêèü”•µ õ»àÚ2™Ì q#¾ ¼ÛjCbÌ|¯…g…)*]‚€ÄÕ§o㉮W€Áâ ùúnyÚu¦&:÷ž‡AÏSÂhé[£÷쳈»¼ )·¡¶Fã®>èõñ1D×è±ÈúI¹µOÞ^M Óƒá8ü[•1dMAM ON æÜ*¤Ü>$Ï+¥ÙÑŽ#6£óÿMoÑ~ÇìÄýŸ?FìÅõˆ½¸^"ĬÝÑ{Î9ð‚—£(-µ5¢f·a/¸| ¼àeò¸°†¶pñm£«ÀyìN0µtˆ”Û‡äçÙsÂA¹%LUŸ½¦ý‚Ø5øç÷9ò÷e IeîE ×1¨(ÍFòõݸ®ÔNvž\ïÅ`hh"éún…Ø6ÓCà4rKƒbˆÁâ ÷ìsø÷Ï¥ˆ9·RAPºN8ÍŽ&0w ~6É7÷ãæ®r+!×{ ÔÔ™ˆ9·…)0¶÷~çŸåjïŠØ ¹yÇa g/üwÊøV¿b­5²dÇnLì ÇîØ{ò tuêÍJùÎ]܉Ś™ÓhàÞq©éØx¼6"š'4ÑÓßñމ¯ZI__Ø`¡Š6ÇÔýöýÀwzIÿ.ð€õÍm-:æ¾m}!wµ5" SQ#BÛØ^é˳¢8l]s%‘Q˜t‘‡Ç5YàÈúW ÐÁЦÞUŠ-A\%€ 0êLöKŽ–!,ÍFEq:8Æö-²˜Õ‡,Þ¬)«?_Õy K³!ä?EÛzÏ¥¶F$)yô¬¨Áv2Q_-ä·h«ExV”-=k•ñ|ÕÂR<+LƒÅyesùª¹¸Êìµj£6ké Ýó½ãŸá×üwë.~=]²ó;ØX˜ƒhAaáèíìÇîà%¥ÀÂØ¨Þ¶¼¤„ÜŒ Ñõq°é„£ëVªÅ$¥hmÿõ÷Õ%åå :v`¯KÍÎÝ@ôŽœæ&~@âfü«¶#œ I^»AaáT!¨"(, ¶ükSèp8(Žië6a°—'Œˆh&µA^,{ö¦møó<ÆôÁ¬QÃyÓÖm¢É/g'œÙ¶‘±uÑgfµØ?›d[™šNjã§µI*¾ âsY:oUÉ¥ q9:ÐÕ¡sç‘ðšwƒ7¤aÈÆLô]ôl¼fµ8ž ˆúiµwUʵ?õ~9½ú¦ãôu:2¶/™/g'š±zðèƒ]'NbÍÌi`2¸‹ì‚BŒöé”§Ùp´³ÅÎÿ.”[Žì¬,ÑoÖñù Z‹öž<{.~X*10 pâb$fd©lòÊ5ˆÅb®_ ޾î`0ØpL¡ÝÇCcéÉ2äˆhIž–U3¦Ê ŽwëÜ žÓæàÖ£h˜"4"çwn»CW€™¡¾ù)E|>¥Q¯‡;|=Ü—ïÜ5Ûúóñ@kS“õaåü¢ÒÒÿµÁÓQåf$‚hs´:KWʵ?õV͘òÛGÓœ½~{ÂÊ3Nmý†W#ŒìÿJüýoŒDü„]CßžÎ072„ƒM'Yû%žâÜõ[Ø{ò ÖlZ"ïqñèÛS1®Ã×óýzÛGDóàáÔCAÈùzôRjçéÔ]é½Á½=žÿú62×ÚbãŽ[.¸IýÈS[¿!ÁÕƒz{àêþ]Ì¥S&pµµØ­MM tuÿÓOEæf´ÄÍX—4é¿6*¶Ó–¾Ou, ‚ Ñõ\leo˜ûénÿ«rÏ^¿=aù´IŒ°½ßÃ×Ãf© èè`poOý/•UÕ¹Iƒ%Y‡BŒ]¾C>ÿžGFnž’ª±Ô½W»~˘ B¨ô¹ª—êêÊ—Þ‹E´ëîG‡Ã¡I~ üzãÖὌ¥S&p9š¬.–æt;thk7W]7c]þ†$=ĩȪ‹,‰Ñº ‚xÛ¼u÷bʵ£ì_‚nmó_°uv~q kñÄqrÑ<Æÿdz6nÅ@Ï^`ª3ä¦ß._ATB""ÉÆÊêUÅtÕÅD_ùÅÅ ïeäæÕÛÞÉÎ×î?TxïIZF“Ž?õi¶<í‡H,FBfüÿã]m² %‚NjA«¬ªÆ;÷bÑÄqàZ[Òä7åfg0à?У}úi;Ém×oDv±4*,.]úìY[¨8[×ÍX÷Ù%„$5ÄO ±ˆe I~€ƒtHò(Å]ZÓCäYé(Õ8Lº¾ÕÏŠà0díKõ')s¹/¡µc{Øõ_Ðàu¤oã ë^Š!£ÙÑg‘ûøÊrã U‚ch #n_XõšôJó·‘èjîÍxísçùÓ+?]öãŠä§9œÅÇa´O¿FWÆõÓÇÕ:ÖÃÈ}ä&A… Cn9ª¬ªÆ®ß%µ¾Šøü÷9úÃØx3ý†ƒkm‰¼âœ «wžÆùz#àÏóòÕˆÙ…ØñëïM:þ]¿Â¶ÅŸÉ`àà鳋ÅÔÛ6:Úì=y˧Inð—¯ ôN$6}6‹&¾âk¦ß0|üÑ Æ//»í:}‡k¤31=kZ¿®îjƺ–вï„ÔiÁ¬x,§™—$àÌ|-}k¹èÊŽ> ^ðr \ûDÞ® !ÏŠ3^Jt•ç'âᯟ  jðXž„nB¯©?+q•ÿü>yqa`°8гr‹cAa òãÑö÷axÌø£EùÇÄUÜ9(ÉÂ^·ÖcQrr_BÚ#ðœul]ŠÒ=~²ŠuIûû¨|{sç‘Ji>dcÚ,ÝÆCÛ˜‹Ì‡A0ìâU¯è’]G2!(Øÿü>9¼IÎ1 '°Ôàgó$¥—nÂÿÍ<óRyÀHt½„ØúpÙWð’R8 ÆÁ±áCHl½¢/Óñ}°ó·?àïûÜZ8Ú§~¾Š~³ÀÖÂ)O³á7 /4YÈ)(jpŸô<Œ}‚ó—ÀÅž‹¸´tx9;!&Iu›Nس|1–ï>€µC“¥a}¼ä–µ­žO³ÑoÖB°YxZPˆK?—[æ~^¿S×mBðõ[`³4‘›‡K?WrIMG“¥™~Ã0q¯ÆÓg}‚ÏÇšèÝh⫱lÐ륯 ”¾¸”JÄ»_Ÿ²ysÞÑž3Ï ƒ´L äLJ£ZXúJû–f#ò§Ñ¨ÁqÄftòøXa5diV¢NÎÇã5еt†žµ¢§Ûuü¥âÈà AÔ©Eˆ9·¦Ý+$â4ìâÏ™g”¬M™ƒÀ ^Ž‚æÂ{Ù=¨©3Q[#ÂýŸ?Farºôý ]®Py÷O€¼÷ŽMD¿EÁjÞs&áêð³yè:ðKØõ_ ?÷Ú_X‹´;GwiÞµVnþ°róWØþÚ6Iܬ÷²{Š»§QÁ°pöC6/iwŽÀyì.…6ö~ûk8^\e¦r¼^†ìè³Èá…ÀÊm<œü¶*ŒgÚßGsn%þýsé+í“DW#ìûrÉÜakVoz÷Ä`ÞX?^»Re¼ÑrM‡‰ƒ}J!Y›š âÈ~D%$â™Pˆ]la¢¯‡9cF‚ÉÄVE”¥ï[¹Tþ>“ÁÀî勱hâ8äÂÎÊ:øÊþóŠKЧ§3xAÈ.(„ŽþyÓáסËá ƒ‘a¢¯¯´íîå‹QTÊGqYÞïÑ]!ßñ;üò¢QU] ·n]Ip½"8Zl,2³ü†1‚C|Ÿ ‰1Ö×;—ž¹Êy¯Ú4_êLM•b¦1*ËòÀÔä4Y|ć}‡Ê²<¼7ú{%÷èZºÀÅ/nï„ä›ûá6é§&í×Ìi S"vçŠR"`æ4¬Ñóíä1yqaÈ‹ CiVô¬Ý‘õè “#`é:V¥5Ϻ×$”çÆ!åö!¤ßý¶}æ5k¼òãÃ¥µ+þšPg¢ÇÐ È‹ ÃÓ¨`¼7jÇË Þˆ«°è9ÕB>žF£û° oÅ—#ua: Y§d¥ìüÓ‘ûø o(¹²It½&±uáV䦯ö6˜>â#ì\º’Z¾Fë…“œûõ IDATªÚ“š, x8*®¬[¼î6ª …s­-b§ê›¿¿îÿƒÕûáö‘ý°65H,ÆÏ.Ã¥+W.’ª©*YkÝ>iëëCG›ƒ¥SÆcúˆ!¬]¿û4¿ÀÏÂØ(¸ ‹¯×­ ÆeÌùUÈ¿†¾ ¯È…Pm·vû¢¶F„¾‹þ’[WÄUÜÜí g?tò˜Š;‡FÀöƒÙ°ñš…;‡F‚ÿ”'·®˜; W!9¼Ä^ZŠbI\¦·z ÿ¶A—[µ°O£ƒÑÁÐV¥àª+¼º´®Ù¥o˜òó7ýÚ6wB^\„¥Ù€5qÿ¸Ô Tõ.ý £¹ m{·HÜŠ*–f+•èQSgÂuÜÔ4ãøë#ãþqh°uad×âJòãÑõð$l¼Þ|Ø…l^ž¥¨,ä0d-ª+ø`j¶ï˯uõâño¾=n wÆ×îw°édqd–N¡,âï2#û÷›C7|0c†/^׉3ÀKJÁîe‹ipÚ::X?gnÙÏàÞs¬®¶vª]'Ëý¸ìÚ;9–KÅ×[C×ÒÏ SP˜rGþ^iVÊrãPžŸˆÒ¬(ùû‰7ñ¬0ú6òÂÇÕw¢­×,èX8IÈ2˜v$ßNXš¨S‹`áìç±?¢sï(H¼NÌlðØŠ’ï FT ³C=Û>ó`h×·Éç]QœŒûÇ¡¦Î„~g&oW˜!ùá&‹%éÀÖ5o0¾H³£ ¬Üü¡UÇÛT¬Ü' FT‰Ûû!ñÚN…ù}ÏYëRžŸˆâÔH˜»øA© Óƒ¡ÁÖEzdà[¹&Í]ü÷ŽNBÜ¥ (LŽ@¨RAøvñj¶«–,]M[Á7nïš·å«ñ}~påSj'h²4´ùkÄ¥¦£ˆÏ‡&‹{»cöܺ!2ð Ì i[&úzX?gfú Óüþ× ¹yÅ3LŒô$¥g­Dû•Òð-€u~°o!Hߤ›¤DW~|xÿ_‹c€ê > oÊã¤òžHÅ m½PY¦¸òØÌiòâÂPœ©WT[#‚«ÿOò€{+7T Šð4:ÅõŠ‘ò|‰wWû%Š?'ߨƒ¬‚¿«ž¡ ñjD•p±YÉ‚$®®”[ääÇRˆ¬A(N„a/t4u@EqjkDà¼Æ€îÎÿ7Õ¥H¼öâþC|Øw`°80°ñ„™Ó0˜9 }i l|dó¦ÎÔ„¹‹Ò#Q˜ñÒ¢®¹Û{Ãyìˆ Yƒä›û|sÔ™šÐïä#{X¹ù·k·âk]³6mÐáp:†íý¾AWñîÒœ"äõ¹D‰Öµ© ~Xº}˜êÿåºI†°jÇC ­Ùü )¦ýFaq  oã‰ÂÄÏ-ZI7ad×åù‰(Lº!'Ê‹ ƒ©Ã@¥8›ÆÐ`ë*¤•¨k)zÖ€èªÕï}>µHåJ:ïe÷öÇÏæA© q•U‚"ùñX¹O€•›¿Rà=”d< +)eK¸Ž?ðFçˆë½<¦"76…‰7P˜üøpäLJãÉåè9ñ§ £Ú2AÛ˜«0VnþH DÚßGÞ¸è’õoî4¹CQ =çÂdÉ+áê68ŽØÜ Ë™DW y&ö¯¨¬Ü8`öÂK&ùWÏ5ˆæ ¢mRÌ/ûwƆÍ1‘¼X_g Y9˜ÚN‡£@,€ËþpoÉêgÒm ž\ÞˆŠâ °8(IËßB³£ Ò"Q#ªDYn*Ëò`â0°ù_Z-óNȬÕÏ •>{1ÝAQÚ]y«ºÔ]½X-,EÜ¥ ȸw5ÕB¥”2´ô­aåö\ÿª3ÙÐìh]Kg…¼^2 Yuÿˆcë^“äB£,7™÷O õÎÜÿùc Xz§EÖŸ¼¸+¨,˃[G)G™š:¹CßZÀ:ƒÅ…ëX¸Ž q g=:¤ë»Á ^]KçfÇñ‘èj^mm­_Ee•ëæcÇ¿Þ{*øƒ¯>ª1~ .¥† ˆ¶AeeeÒÂm»"CnÝéIðxoÐÊ@}´ת¹ÓP<¹¼I7Áê`€ÚŒí½¡¥o”Û‡PœþE)PSg*Y¬^ëIc­ o*­ú«+@‰åK•誋[ïÚai62ACK݇nPj×AßZ)5‚*ÔÔ™Ð1w’$ï¬Ôc$Ë;eÜÕ§YÖ™g…)x}&¾J⢣©ºÝ–¶ ž\Þˆ¼'WZdù‘-‹*åñju…^eY2ž¬7ÏVSU êýLXúT"l5¤¹Ëòð4ê4t,\”,lZúÖàz/†¶1OÌDÖÓÐÚ~E×ë.ô¨¶¶Ö¯´¬|Ô—»öG½7á“‚ã¡a¥"±ÑE|>–ìØ]oqmâõ‰­Ù·ž°9rëNC ÉO©ZQ,[C[t0´E~|8ŠR" ¥o -}ktö€š:E)È‹ {ãÁËMÐÑÔ‰7ÀÏæ½²ýºŒÛÇ)·¡09â¥öeæ4 µ5"d=:]o›ÞäðBPÔ̾*J2ö]ƒYæ;šI,oâ*Aóïϲ<äÇ_ƒ¾'¼—ÝSzõYpjêL¤ý}µ5¢¶1åù‰ ðu)Ë“$ÒåÚÈß‹½¸Ií¬ŸRk£¸ž}’èzµÜ×Öö/-+·r÷Áh©³s.Þº#A4ôp©ªFD4¥ºTÞ"qMÎêý'ºøMD±5 F§ubÖc o¢ ñŒ»ú€4`ÛÙÑÁ(ÍŠj4—Õë Ç°oP[#½c“”VîÉ(Lº‰‚¤MÞ'‹cÇá’ZçѧÕ+šB'©Ð`ë"öâz•ÇWQœÇÖ@M Û¾s›µoýÎÐìh‚Œ{ÇUŠÃÚÒî€f­Ü”‘ùð$jkD ®Ôºhv4‰Ã@K³‘ŸðW‹ÆÇ ËW |s¿Ògâ*üøì½å}êY»£ ñ2žT¹ÏÔˆÉ9Ûzµë{öMg¤ÿK$÷Ë),:÷Ûí›ôõŒ7ΛÙñ£>½)Ë%¡„¹‘!"©dÞ›[ë?vî’gmm­€OÜ¢‘iý˜v„ä›ûP-,×{Éó/M[/$\Ý@ûÕà/o©‹ˆwv :{Ècq^C»¾p±CÖàöÞA0âöƒ¡]?hv4 ?ùñ×ÀÏæAM »þ •V"ÖûLp‰¬G§†ø°--.SÄâÀeü^<øåDì g?tñ‚š:eÙBµ°=†}Óìø#u¦&Þý=üò " ‡0ìâ†R×c0ž¦ÀúýÉJ5$›BÖÃß¡ÎÔ„™ÓÐzÛX¿?¹/!=2P¾ºµ9p,FîãKˆû…I7`â0L¶.ù‰xý'„¥Ùèä9Máøü¶àÎÁ‘ˆ>õ92½7غ–>E/ül »x5xÜ$º^D55r ‹FÎûîûÍÍô6ÏŸcò«‹£Ê܉ÅOÁ!(*åÃ@W3ý†ÉfâÀ鳈IJƒÁ€w¯ž˜é7 LE|>¾ Ä¢‰c±%ðò‹KÀµ¶Äš™ŸàêÝû8z0Ƨ¿¼Èø7?âCwœ ¿Ô§Ù0Ö×ÃÒ)ä‰Q÷ž<G;[œ¾zE|>–O—®\œ ¿Óᡲª6æX4q¬|Eb^q ¾ÿõw¹›°oOÌôŽ"±ÇÎ_BXä}ˆÅbØX˜cÿ(ØX˜Ë¾ÿhyÿuû172Ä|ÿÑò•’¿]¾<-(Ä…›`0ìå‰éÇÐE¤š’='O‡n=vÂQTSc`&$ÁáDA¯“;XT Ь&Æ]½‘pu;ô¬Ý4Ö½&É¿ KÒ¼ÑHÒ&èw~‰×v"/. uVZj°uaýþdØxÍj¶ðpþ- “#rûÊZƒMŤ›/¼æ]À“Ë›õè²’ÖÑÔïÞÑb+¡I7_ôžsña[ yqaòÏØºæp±Y¡ædS)NDy~"L{ i0儱ýhv4A^\Xƒé=ꃭkŽÞ³Ï"ö’${~]‹fGtÿhR¼žŽ¹ú.¼‚¸Ë›äiHêŠ\»þ aÿá å Ú#j­ä8¦1ÔÕ×ÙZZhøRäÖ£hLZ½„!^ž‹¼£ç.âÒÛ`nlŸ9‹Àµ¶Â¬QÃQZ.À·G~†‡SZ½ ¹yðœ66æ˜:t8Zll:ò ¬MM` £ƒ1>ýq7&'BÃ~`l:ÁsÚ” ˜:t¸÷Äa×r+ávÁÚÔc—¯AbF&\ºra £ƒåÓ&ádØ5ì9y«fL…­…‚þŽ;Ñ<œß¹Ö¦&òù2˜èëaúˆPTZ† Gáëù>¶/þ {OžAÀŸç±aî§ÐÑæà蹋à%¥ âÈ~äÃsÚœÚú ¼œ°5ð‚ÏcñÄqp´³EÐÿÂqåî}oÿŽv¶X²c7®Ý—®\ íã…'iéØ*{–/ÁhŸ~t1©[b_¸@ÃòRÔ~ômÛNÚ_Qœ¡²Ðô+œ…©¨,˃V#IIßâ*…)W ÐÁÐö•®úW ð¬8U‚"tÆÝµ%dcS]ÁoòÜÕˆ*ñ¬8C¾‚²%EÃßW™½VmÔZ$g ¸¦æxbFæäÉk¾^ÿ—«¶yÁK';Ûv¿Ôqû/¿cdÿ>Øô™¤¬CWg•ò˜„ ·$Ù¨o\+¯aÙ­³5†|¾ Ñ<¹¥iÞØ‘øø#I¦éÄŒ,œ CÈ[ ÉÒ€ÿ@oœ½~Ñ Ir‹Ñ@^X5ýc’š‡Q ‰8vþÖÌœ&ùelj‚Àõ«ürvþv»–~Žýû¸÷ÄÏ—á§à¬Ÿ3Qñ‰8°r)¸÷X™#)SbõŠˆæ¡oOù¶Îövø-ô *«ªÆ_.Àž“g°åó¹˜8ÈWÞÏØåk°ãxެýÐAK ‡×~)OÆz—÷Ñ<]’ßXÂ?®†¬øñ€…°ºÚÀgi\¯U ¨©3¡mÌmµ_¾ çµ¥1`°8-r#¶å±Qgj¶êù~›´&;Ÿ@`UµøøƒØ'ó‡,übµk7ûŠö.¾¢1þ?> ïí^.Iz8~å×èÛÓE¡h¸KW.LôõðO\¼\tÙY=¯™¨ÃáÀ¡s'…m^¬0Øëy.&ƒ¾=]ÿ|áš[÷nòÿ?|ʪj<ˆ‹GBU†"±c%+\¼{õÄ‚­;q<ô ¼{õÄàÞr÷èÈþ}±xLjIN¯g/ôëé"-ÄÍP NL‚H,Ƈ½”Žuç‰?ä»;tUÈ~oejq»_-« ¶\lH?‚h©òÒIaóÁ¬·RpšÆ“D×ˈ¯]âššƒbŸÌºhÙÊþn®•æ~ÚÉÆÂ¼Ý]œ•UÕ`¨«Öœb±XeyM ªjùß/f{×d5ì½Õ×é¨ð7‡Í†@(Tn2ŠJËH,Qüòç"É©‹- t%bîÈÚ•8sí:Â"ïcço`CÀ1Œèƒ–.„ÿ@oØX˜ádØ5œýëö×ÚA›×+C©tߺÅ5: ‘X6«]{ªE×F]œ³i›_ ‰­ãÒ{Œ ˆ&R’þ•åyMjÛÉcê[®ÌIãI¢«e쪉_¹û`é_-àîÊooâËÜÈùÅÅ ï= `¬¯‡§…J"-¯¸Æ-¯cø$-^ÎÏÍÉqiéõ–é±³²ÌôG»ç¾þ»1±à°Ùà— pçߌö|åókÆòi“‘›}=l_ü &)~_¬Â™ðër—#X™KŽ%5 .]Ÿ›¬c’S`ÛÅx3Ä–€ïì%±E-ÃuÂÏW‚z8ÆrëEb±í•»ŽôŸýyÑ¢?fæ·z»Ãúzáç —!;ß¼âì:qb±c>€;Ñ<Üz-o¿á§c`2Jn¸æpôܹÕênL,®Ýˆ1>ýU¶u´³……9¶þ|•RëZbF¦®Û„³7nAX]Y·â̵ë•Ï`À@GLš, ìø5+v„,a®±>È­d2\ºrÁµ¶Ä÷ǃäýÄ¥¦#(,CûxÑSLÊ¿‰Éa='ϸ8qÕ×n|à[»HpA¼}ÚÒÚÍë«E¢½„][ýgø™£|ú•¬ž1ÕÊD_ï åS'!1#̘{.¢áëÑ Ÿ &ƒþ£1iõ8ÚÙ¢´\€gøj9Lôõ‘›×¢> ttàñÉØ[Y‚—œ‚Y£†cPoÕƒŸ×¯ÆÔu›à>e&¸Ö–ˆJHD¿ž.X4a8Zl¬õ VüxGÎ]“Á@\jÖÏý::X5} ¦­ÛÏis`kaލ„Dx9;aœ¯7²_°âY»RÞ­…xÉ)ðëß‹&Ž%±•˜6uÝÆŠÜÂb/{L–þ`!‚ Z jmøØÍ¬`ihL›1bHåâ‰þf:ÚïnŽÕ¸ÔtäÂÌÐP¾ÊPFvA!ž¤¥£› {®X>÷$º$¼ ©aSL¯‰68}nõÏþ7bñı5³F0ª› ÞŠùeÿÎØ°9&’;À]݉…hÙ¼óŠÌ‡A0ìâ%ÿbågóù0Ù¼èY»©Ìç%kcé6^.º ÂQ˜û¿¤_¼Ù¼ó¨(ÎXºŒ– ¥‡ú#È},Y0$Û¾²,™ƒ<¿†¶ø¿™gäYø›r¾ (Jkt߀¤&¡¾'ÄUy{u¦&lzO¯·¨xÂÕm–fCKßZ~ÍíO6/Àdqê=Yë^“PœÙ¤>ÀÒm<LÍ&µ¯{mÈæ¸^‘Ï^ÿR™ýßEÞ¥|ü‰¦? 6;¾ñ‡',™ä_Mâ«yïøV!%ÑêÄ–/€zKpÄA\%À?¿ÏEï9g_ª” ƒÅ¸J€œ˜ *EWµ°ùñáPgjª,jmÿá!V‡*Aâ¯lAzd bί‚û”£-:6ç±?ÂÊÍ¿Éíe%˜r‡ª,ŸTœ aiv½ãÕÜþ åö!˜9 …žµ{#ç² ÎcwÉÿ®(ÎÀµmïð‹ ¯Ö»š±%dóBP˜Rp|Ï 'Së’º‰oÊúØÚQo‡ç|ATSãœSX4wÞwß§ô›µ0óö#^Õ»x¢‚ !‚ÂÂ!¨¾¶>3²(-t˜‘¯ŸÉsc¥>ÍAPXø+íoÉŽÝØt¾žïcêÐAˆŽOÄðÅ+”©¶!Jöœ<ý{—áãòž½hQ[[;€7 .¢µÒ}؆Wâf4wöSr1f=: ã®>õ®$ä×¶½/Ýø¡ž˜‰Ò¬(X¹G×+Z|L¬è o­ò¥¥£:.KM ÓC\Œµ5"ä>¾Ô誽–ô:æN¯ÍÍÈÔäÔ{Lô­_©Àk0Ûñ¹Ÿ­‰Î&fdN›°jÝ:[K Íóç˜|àêĢˢ鬙9Mþÿ¼âb¹àz]ïtøu]·Rž!ÿC^ðœ6'B¯`é”ñmMl…n=vÂQTSã`%€ tE­ ¶.œü¶á~àDŸZ„Þsζh?¦Ýƒ§¾\¾ŠQ&Àܧkp;Ã.^0°õR l èZ:£ƒ¡íK[—þŸ7{5!X8û!ãÞqù*Ƽ¸+¨Á¢×bKû$nÆÜÇ¡H¾¹ÆÝ|_Ùê@c{ïf¯^l™ÕÐÒ¥›§‹.⚚㉙“'¯ùzý{\®Úæs,ìlmáàãRÓñSpRŸfKnDkKÌ÷­ÒÝ&‹qðôY\»ÿ &öEFn¸ÖVrsåîür!‚ ! tu0gÌH¸;tðÜ•˜ò4cã1kÔp¹ÈÔÛ{OJ–!óS B­Æˆhž> A…\kK,Ÿ6 ::HÌÈÂÞ“g0Óový~ E¥|¸tåbåô)øíò„ܼ˜5j8|=Ü¡ÉÒÀ¦ù³1À½§|ß-6¬ÍL^«Ø{µ¨ ÿ»²âÇÂêjkœ¥ÛxSˆ*ê¿Wd. ÆRB¼èfl‘U‰cÃ.^rcNL,Œ»6œ˜ÙÀÖK)eÄÛæEc/ú6ž/-|’Ôu3ž^„~‹þj•×[iæ#@G3GºùÐ>Ý‹*ŸC«ªÅܱO¾²ð‹¢áK¾Lç%¥´ê¥Ž©O³1|É ˆÅb,?“DD4³7©Žøj_þ<‘ú`ò`_lÿõwìüíð’R¿\¼Œë7ñ‹-Œ c}=ŒZº =øp—‹õÇp'Š®µ%4Y¸Ë‹Å]^,45Xp´“<`ܺÂÊÄXÞï—»`@/7 íë…ЈH|±sŸÜ2ŽY›¶Áñ;{yâȹ øÏüÿ"4"c|úÃD_3ÖoFvA!¬MM0}øÔÍ»vîú-Ä$¥Àß·µgÐWþ~ªËðqíØí*¬®> ' .âMÒÑÔÕÂRK³U~^ž÷DòcFšà´!êº-t3Öu1> †Y!mÒ}¥¦Î„™ÓpäLJ£JP„œÇ—`þ‚Ê܌ň»¼©ÕK• Ù¼°80°ñ ,]*Å×.qMÍÁ±Oæ ]´le7×Ê s?íT·Æ_«]Ù9ÜÛS)P}ÁÖ”ÚfâDèY·¾’ È÷»ÃsÚ¹lÓ‘_°hâ8¹›n€{O•ò±%ð„ܺ$‹qjëF¹ð9û×-¹Åi€{Oì :ƒ¡}zÃÚÔ1É©$…ª¹Ö–’_ÒUUØùÛ Çöå´IÑ¿àAì܉Åÿö~&ƒ‘ýûàtøuD'$ÁÜÈPa»Ÿ‚C°!à6ÍŸ—®ÜV{M]uqΦmZ|ÀÀFÇ¥×A¼QŒ¸ý†ø°ï”\Hµ5"$IËìwõit_uÝŒO£ƒ[t<2cÚßGQ"E©… IDAT’ñÝþóe›[K—ÑH ïìrÔˆ*å+4_727cÚ#­Np=8>â*ºú~ñR uIt½û쪉_¹û`é_-àîÊomâk€{OôquFT|"’2Ÿ".- 7ÿ‰VÙö^L,Db1¸»>ÿ•id(·N%fd_.ÀàÞŠ¿F†õõ¬[å;v±Es3üË )<Í/WÌØÑSê¾6‹[ synY_¥/l“”‚ ǰgùb¹`kÅbËÀwö’Ø"Þ&Ö½&!=2™ƒP–ÓCÀÖµ€ ?yqa(˃·Lºù6iuÝŒ-Å1€·žFK¬!¶½_Ë—ô©E*?“Õ)”‘qÿ8Š’o×»¯†ê,êÛx‚­kŽ^Œ¸ýš”õeú“Q×Íø2i/)EIˆµÞwtPr7¶"±å`€ÉRáN­ÍŽ&p» N~[ñ¬8•eyÐìhŽ¡JÑ£ªÖa]4غðYñÒûªêûy/»§ôžE=_Ì/Ö4ìâ…¾m^mwUý©ÂÊÍ¿Y«µô­UK÷¡òŽÕwÍí@£çÞØ<ÕwÌMý\ªæ˜h ¤o–ˆÄbû?®ò˜:»xCÀÑœÝeo PM †dùåü|á²Ê¶î]áÒ•‹uƒ_.@eU5Ö<"wõèèÀËÙ »Nœ”çõÊ.(ÄÑsá×Dk’,뛦4kk 3/?¢ÿì…§-Xú^nañCöÖ“à"Zõß© mc. »xAÛ˜K17A¢«Õ’`IUuµÛÓçBß›ð ÿmˆ¯ùþ£‘˜‘ Ÿ¹‹0vùxÏ]ï^’€÷˜$eóðîe‹QÄ/ƒÃØ)°á¢R>êZêö­\ QM Ü?ž ¿¥«à5cl:aÍÌOšt<Ö¦&0Ñ×ÃÀùÿÅ·Gy­çþ[èl8Ö*Ä–ÇÔÙ=Ò33¼'[%t‹A/¢FCðJàXÝͱxâØšY£F57ؼ¥ñùˆNHKC.ö\p´ØÈÈ̓Ž4YÈ.(„¹‘!ÄâäÃÚÔÙ…ÐdiÀ@GNþÓ°úÓåe| *>eÏžÁÌÐP!¾ˆÏ‡H\£ Ôdù±dV.A…Q ‰°65ŽŠø|w¥ B(¯²ªyÅÅ072”ÇŠ©êCv>u-[E|>*«ªßŠ‹±˜_öïŒ ›c"y±ü`‹Tˆí—Úæºf‚h}\\eöZµ‰®W‹“ššÚF6KcÀ’IþÕoR|5¿\§ñÓ°}ñ|ø”ä´:wýænÞ{ÄѨØò‰U+•F† ÑE$ºHt½=\ÕÔÔ¾ÖÑæ|ðÕ§S5ÆôÑm «þdy­¸Ö–‰ÅÈÈÍÃÚYÓ1}øš±¨¬¬LZ¸mWdÈ­;ý\° @" A¢‹ Ht‘èj=ôa¨©mÒÖæôh-⫈ÏG\j:À©‹m«\™Ø Å–€¿!)Ùã‘!Ht‰.]­—Lcƒ‘ž®ýÆy3;~Ô§7)VŒH\“³îÐáðcç.yÖÖÖþ ‰ñ A¢‹ Ht‘èj; eª«o6Ò×3&ñÕêÅV$–­[42‰.‚ ÑE¢«í2RƒÉÜØÙÜLoóü9&¸:±hHÞ*%{NžÝzì„£¨¦¦ËÖ_4,‰.‚ ÑE¢ëÝaC]}­¥…‰¯·.¶Ä¾p†… ÑE$ºHt½›0Lfi0Ö¿Çåªm^0ÇÒÉΖAÃò:Qþv5dÅ,„ÕÕ| à, A¢‹ Ht‘èj?âk>C]}µk7û _¯]l™Ø Æ… ÑE‰®ö À &ce7×Ê s?ídcaN£òrˆ®?Œº8gÓ6-¾@`+[Ljhh]Aè"´,e2‹¸»òI|½´ØzÀwö’Ø"HtA¢‹P…€ELæç~Þ}Ÿ­ž1Õªn]BB5ÿ&&‡M]·±"·°Ø Àvid]Aè"ÃÀj&ƒ1s”O¿_Š-/{ìPN#Cè"‚DÑ\̬`ihL›1bHåâ‰þfTÊÈÌ˘üÕ†§ é™}° @ ].‰.‚ Ht/‹ €uLæèOG~ô¬½Š¯:bËÀ1HŠQÐåAè"¢µ‰.uâ6K*€éÕ"‘ûÓçBݦÌ,Útº ²ªº]œ|1¿ìßQ_¬úÝcêì. é™™ºXB‚‹ ‚h­¥ëÝÁIMMm#›¥1`É$ÿêY£Fi²4ÞI±5cÃæ˜H^¬/€HJö¤Òôo²tÄ;Yºˆ¦Â«­­õ«¨¬°ùØñÛ®“g +‰ÅïÄÉUVV&ÍÞ¸õ„£ÿTýH^¬@oÓIpAm²t½»ôa¨©mÒÖæôøêÓ©ãúè2m/Á}eeeÒÂm»"CnÝñð7€5x4½D+ƒ,]ñ@ôÄË2€É`l0ÒÓµß8ofÇúônÑö"qMκC‡Ã»äY[[û/$nÄG4D+%’•ÅA´mr¼¶Lä$ºÚC™êê›ôõŒ[³øzAle@bÙºEÓGÄ[Ä @€Î $ˉ.¢ŒÔ`27v67ÓÛ<ŽÉ®N¬Vr\%{NžÝzì„£¨¦¦ËÖ_4]A´VØ `"€ ‚DÑ\¦1ÔÕ×ÙZZh¼eñUWl‰|àMA­™ûø‚Dј&³4ëßãrÕ6/˜cédgû†¢íÕ„„] Yñã auu_8KSBD+c€_!)Å&Ð @ A¢‹xñ5Ÿ¡®¾Úµ›}Åë_ bËÀF4A´RÎø€&€2,£a!Ht/ À &ce7×Ê s?ídcñÊqˆ®?Œº8gÓ6-¾@`+[LjhØ ‚h¥˜Èþ0•QÀPOè"^Ú–2ŒÅÜ]ù/)¾êŠ­÷|`/‰-‚ ÚµôIè"^'zi0™Ÿûy÷}¶zÆT+}½&oüobrØÔu+r ‹Ýl‡Ä,O¿ ‚ ÑEè"ˆz0°šÉ`ÌåÓ¯¤1ñUGlyØ`€rF‚ Ht$º¢i˜XÁÒИ6cÄÊÅýÍt´ŸçXÍÌ˘üÕ†§ é™}° @ A$º‚ Z† €£LféÜ1#²Cwo´ïdõ€b?@b#‚x×DAÄ[ƒ à(€J©Ø¢ÚsAè"‚ ‡A=爷‡: AA‰.‚ ‚ ]AA‰.‚ ‚ ]AA$º‚ ‚ ]AA$º‚ ‚ ]AA$º‚ ‚ HtAA$º‚ ‚ HtAAè"‚ ‚ HtAAè"‚ ‚ HtAAè"Ú/ÛàÚ@&€¤í¬hÈ‚ ‚ €Úf¶#Ýæ©¸RÅRi›£4¼A´ÁçAD«yý!ÝnŠÏ¸*¤Ð¦á%‚DADËFFòTpxá³kÒ÷4°½ v#}hƒ\“Aè"‚Fr7ãŒdnÆbH¬VP½ªqµ´Ÿñ/¼ï$YÒ¿eø½^h Œ¦Š ]A´ç‡‘ÌÍX+MªøW*ÎTqG*Úêîë$Ö06MA$º‚ ‡Ñs2¤û©/…Dµô•¢âU&ÝÖHºýŸPŒç:àS`Aè"Þ&j4Ä+z½ìµ”I\–Z}¤8ÖÀ>v(‘þÿÿŒà‹ç®Æ8½ë´!‚x“Ï9‚ ˆVñ 0¥‘ýÄJۨ ϭXL(¯f4ð‹tÿ“iº‚xKÏ9¢Ce€ˆ¶Â_XÂFªTÿJ_€$`>ááUà”ôÿz4”AA´ç_€Yº¬ I Q`$«G¸'ÝnŒ´]Hb¿þ‘~î ý,Vº­MAoé9GÑ&D ±^…áy|­Tˆ½è2œŒçù²×?ÄyAè"‚FMÄH* ¸´³ÄòEÖ-‚ HtA#‚ zÎí ¤'‚ ‚ ÑEAA¢‹ ‚ ‚ ÑEü?{wUÙ÷ü3èàˆ(ˆ‰‰ä†þ$Wny\p!E \È-151Ê%51÷S³H\ EE…ƒX”$Í$¸Ñ„àfFG‡eä÷Çà(йäÂòy¿^½™sΜùž|º®k®‹ˆˆˆºˆˆˆˆºˆˆˆˆˆ¡‹ˆˆˆˆ¡‹ˆˆˆˆºˆˆˆˆº¨Q1Ãu ÕbÒDDDDô d=¼2Y"j¸ ýclé¢b{í×{¢Y"""¢WC  @9€I,5alé"¢7.¶ö—‘5KAD ]DD¯ÎÿÑCÑk±Œ% "†."¢W$x½Ï€©ŽÃÒMÚ´‘vîÐaV…ˆºˆˆ^rØ2Hj\ìk®þ²fX?Û{­Ä-ï0|CQý4XzV‘Û7[‰ 8Ÿh;°W,pu†™‰±úù´Ì,l¬l­+¾ÌðED ]ÄÐEÿ7Fl¬p뉰¥'âÏ.þ«àºØÓuÆÙ„P xãçVQY…ÀSQø&$¬ªu+qBFNþl¼jDÄÐE ]Ô(ÃVjf–xžËx|8zDƒ[’ßU`WØ1ø‡Ÿ¨62Ћgø""†.bè¢Faç’…'ϯþíÊUƒ9ÎN˜2r´µD þ¼e·åðÀîc•mõõŽ_ËÉ›à:¯(1tC5Ȱ•”’j0mÌHxŒ q‹Æ·$b©L¿àq02ºÚ¤­a8Ã1tC5A«– ?ëwá’éÇá˜å4 ]q£_ÅÒ2ì=‚ÐèØ CƒÖ{2sò—(ã'"†.bè¢7¶¢’’M]ì±ÀÕI“{Ÿ¹EÅØ| §ÎþRid¨ÀðED ]ÄÐE¯EðzŸ§ãÎ~yî¼åØÁ0wâ8éë5ù÷]P¿àõ˯ò6É–ÌüüÕ¼#ˆˆ¡‹ºè•„­ˆ„$K‡¾}ðédtlgÔìêp%;ëöÕœKIUééobø""†.b袗"rûf«£1qÇãmöê®Î031nöuIËÌÂÆ‡j.üçjy«–:ÞÙ…E;TóŽ!"†.bè¢ [Gcãl{wëŠESÝ`iÖ‰…yDrZ:Öî ºw-'OÆðED ]ÄÐEÏìÿm¦‡bv‡Ç&8Xš¿¥á5ÉVÍY˜§8—’Ї”Ù…7„B‘W^QÑAV…ˆºˆ¡‹þ6l™´5ÔXäî[«n,Ìs:“|k•Ò[·¾ˆˆ¡‹ºè¬Ø£zþaßI˜ /i%øt² ìº[³0ÿPTR2Ö諭}G‘-WTÌ--/ÿ7«BD ]ÄÐÕÌÖ¦@S°Ø}†ÚÚ°0/Yht,6…(kjj²¾ˆˆ¡‹ºšUØÚ£’¸áD¹î(ZŸMþÃúÙ²0¯PµR‰#1ñØ\% ÿ(‘–T~çÎEV†ˆºˆ¡«‰‡­Ò2-O× ˜è0„…yÍákï‰Óð >¬l­+¾ÌðED ]ÄÐÕ”~jcc…[O„-=vñ_×Åž®0Î~ „‹ó†TTV!ðT¾ «jÝJœ‘“?@+CD ]ÄÐÕÈÃVjf–xžËx|8zÃV"¿«À®°cð?Qmd ÏðED ]ÄÐÕÈì\²ÐãdâùÕ¿]¹j0ÇÙ SFƒ¶–ˆ…i d·åðÀîc•mõõŽ_ËÉ›à:+CÄÐÅ2CW[I)©ÓÆŒ„Çø±·Ðaa‰R™ ~Á?â`dtµI[Ãp†/"†.–º˜ UËÇ…ÇŸõ‹»pÉtŠãpÌr‰®˜…i¤Š¥eØz¡Ñ±†­÷dæä/PÆÊ1t1t½á°•”lêâ`®Î0HX˜&"·¨›„àÔÙ_* õ¾ˆºˆº^³àõ>NÇý>òÜy˱ƒ`îÄq0Ò×caš¨ì‚Bøÿˆ¨_~•·‘H¶dæç¯ `eˆºˆº^qØŠHH²tèÛŸNvAÇvF,L3q%;ëöÕœKIUééobø"bè"bèzÉ"·o¶:p<>Ñv`¯Xàê 3c¦™JËÌÂÆ‡j.üçjy«–:ÞÙ…E;T³2D ]D ]ÿ0l³íÝ­+Muƒ¥Y'†ÉiéX»7èÞµœ<ÃCC× øÅ›é¡Ø„Ýá± –æoixMrUgs†êu.%)³ o…"¯¼¢¢ƒ¬ Co g [&m 5¹»ÁÖª CÏäLòE¬ TJoÝbø"bè"â TŸ¬Ø£zþaßI˜ /i%øt² ìº[³0ôB¢’’±~Põí;Šl¹¢bniyù¿Y"†.bèbت [šMÁb÷IjkÃÂÐK‹ÍA!Êššš,†/"†.bèj¦akN`H↠ç>º£Ph}6ù ëgËÂÐKW­TâHL<6W‰DÂ?J¤å•ß¹s‘•!bè"†®f¶nHË´<]'`¢ÃÞôZÂ×Þ§á|XÙZW|™á‹ˆ¡‹ºšæONl¬p뉰¥'âÏ.þ«àºØÓuÆÙ„P àA¯UEeOEá›°ªÖ­Ä 9ù³d°2D ]ÄÐÕdÂVjf–xžËx|8zýqò» ì ;ÿðÕFzñ _D ]ÄÐÕhí\²ÐãdâùÕ¿]¹j0ÇÙ SFƒ¶–ˆw5(²Ûrø‡G`÷±ˆÊ¶úzǯåäÍp•!bè"†®F¶’RR ¦ ñc!n¡Ã+O Z©L¿àq02ºÚ¤­ax3 _ýÌ`Åßl÷/“üÀw 1tC×´jù¸ðø³~q.™NqŽYN£ ÑóŠS£R,-ÃŽÐ#Ž­04h½'3')€²&úv…~Ѐ3€°z¶ÑðC½\á]B ]ÄÐõ†ÃVTR²©‹ƒ=¸:Ã@"ᕦF-·¨›„àÔÙ_* õšpøêY¼Êtpó‘ç¿à`€¼3ˆ¡‹ºÞ€àõ>NÇý>òÜy˱ƒ`îÄq0Ò×ã¦&%» ~Á?"ê—_åm$’-™ùù«(šØÛôð€C\z|0€Xg8Žlð[tê°¬•¸eiçVÕ¦b5Tãµ>àXû˜.€=µAiZ=ûŒ‡ªÛQ  @.¯G¶Ñ…ª¥ìVíó·\ªÝ—ˆˆ¡ëI"·o¶š=nìùO×ûÅWTVYFl]‹-^óѱQ£8ÿØ —œšþBû‰‰‡ËÒ¯Ôß'§¦¿ð±î‡¦³æáJvÎ ¶èK¥¯¬^¹ùHÍ̪s¾÷_¯X*EHtL³úÁµ4ë„=ÞK5ެ÷maѩò6­[š·ûªqQ]um°ª°«6,y0ƒªk1ï‘ígøª¿Œ`#€5m·ÀL[ ðamX=U·&Ñ+Õè~AGnßlu4&.`ê ÛÞݺ"È÷KXšujV-« J¥ò¥O~W›% ú=¯˜éÞ¨Î÷u±êlŽ=ÞK5’ÓÒõÖî ÚrëŽbe«–:ÞÙ…E;kCKcõ;_¨ºý¡X@È#ÛéÖ†«Tð «õdí×Ï| »ö‘¨ûÉÈó‚ô¨}M""†®_ü·™ŠMØí±z½ƒ¥ù[A¾_ª³y“¹‰¿§Àÿè Èï* Ñcªã0 ¶éõØvQIɈL:¯îÒ[1ëAÙsâ4"Ï ·ë‹i£G¨Ÿûùâ%Œ<ƒÒrUb¿îÖð?U•XõÃ>ª.Ï[ò;õ®;™[TŒ]aÇpµ¶5ÌØ° ¼&»ÀÌĸÞ÷óð¹ŒÐB‰ú؉¿§`ÿÉ(”–Ë`ÐZ‚G€]wkõ{,•ÉPp£I)©˜è`å=%JËep>T}¾«~؇ñöƒÐJÜpùÏ ì8|¥å2Xtì€O'#}=”ÊdXå¿ \±nßAÜ–Á¢c¬˜ù!~J¾€ HU×ìxûAv([«n8²ÁWó\JªÞÆÀC›•UK…B‘W^QÑÁFüc±€T­WyæÔ³Í¿ ǵmÛ[»ïX¨¦–Ȇª…Ë ªOFfCõéÇ^üS@D¯Cƒï^üÅ›©§Û„¨¾ü:'95ýÿ¶~ö‰FÀ—KšTàJËÌ”/}akÕ ŸNv¹‰1Ü–ùàâ•?ÛÖÔ¨-:¶3‚¶H ýº[C[¤ˆH<‡Èsç1Þ~l,ßÁ²ß#4:p&ù"¦~¹Vo›ÃÓmØaWX8Vý°Ú"-ô¶|GÝjbjÔö±×,––aÄüÏqCZg'Lu†Œ¼|¸-_UïûÙt _ìǨý0ÕqFžÁ—»v«»ÄÄÃm™ÌLÚcžË8tlg„–~…ãq‰€ÔÌ,l <„“‰çÐÕ¬Z늑œšŽØ —êœooËwêœïœµ›akÕ c÷Gì…K˜¿~«ºe,$:nËW¡Ç;;¸?ÂãáôÙŠ<ƒñöƒ`bØž›¶½pkCa×ÝG6ø Ö/ø¸}«:ûÛ·1(4m×έ‘¾jÛ Põ}ZÓ²öëW²ùï‡Úç,j¿.¬ fkŸO°ìZ$¢æÞÒ•{TÏ?0ìÛi«7MЗ´l\8WÝÒÔ¤ý• ±N Ìt m-ìº[ôÄ:¶êl«·Í‘–™U§UÆ@"Aï õ’FÉiéµ­DC[TŒyÇa«3 ÏîÈ.(DZfÄ-tàØ¿|ü÷b°M¯zÃlnQ1ìzXcç’OÕÇ—èŠá¶Ì²Ûò:ÛÊï*°=4 ~^Ÿ`Ì þµ­jVèë>ûAóEÀ~Lq†/¦M ¶éEe%VúïUïsCZ†Ø]~ê¹Õî·š=|¾Žýû¡c;#œKIlôüX}h‹´à¹i[s›ã<SFSÝð¸DDlYm-&: Ax\R®e6‰îê¡¶6jk#ˆJJn¿~оŽíŒVÊsKËËÿ݃×Ã_uÿ‡$¢¶åª>÷» `ÕÀù¡†CÕýøTcžãŸ"jV¡ë~Ø9Ís‚¦@S°tú µµiÒÁÖÊU•°›>{õÀ>½0qèçš9¿·å;uÖ|øÓF@EeÎ¥¤â¿…×q%;Ñç/ÀİÍ3ÛÆò|¿ìs\þ3™yÈ*(D¥ˀryÝÐuùZ**«Ð¿W÷:°GUcCáÍÞ,Á»¾uöa×{ŽŸBŒ^× IDAT±TÕ˜aѱÃsOfkcÙUýoÓv·Øu·è¬þw[}}X¾Õ©ÎRPFúúMîÞÖÏÃúÙ C£c-6…œëhg5Òðõ$÷'GM°û‘çtkÿ»?}„aí×Ýmû/áPuO2tQó]Y±{tC7Lœ÷ÅGw ­EînõŽ-jŠÌLŒ½c3B£c‘pé2B¢c Ñcû¢…Ï8u´´žøÜÏ/ÁcÍ&èˆDèñެÞ6G.qCúlskKË0i¹² Ñ£‹ºšu‚]wk$§=þ‰É;Š Pw{>ÖlQûMͺ=Û÷¿¯¨¬Tµçõ´µ4 Z×=fsZè|¢ÃŒ³(8o±)08B¯ƒñ%ÒòÊïܹØÈßZT­`ö¡n‹ØâÚ0õaívY˜òÐ6?Aµ°¸)ÿQ“]ÂÖúnHË´<]'4ÚÁÌ/*#7¥2¹»a‘»Je2L_¹þGO¼”V¾ÅÛvaˆM/|»ôÁ´EÏ3¯ÕŽÐ#Ý–ã÷ƒ{Ô­oQIÉõnkajHû+ ¶VÝÔÔ~ÚÐ@"P Àõ›¥uöË+º¡@Ð$[›Ì»@p?|‰öž8ÝÛ/øðù·;_näáë:€µµáêtí¿K <¿ª®Å Ú0 ÕšÙŽÕîïÕ˜®¼CˆèU{cékbc…[>·bÆçÛn?5oÒp­xÿoš]àR˜óøÈw½ºkM"C( õßt¯UTVª[ž¦¢²²Î±®dçàtÒyu«Ò}÷[©êÛ_[K¤nI’ßU`{HX½Ûš™î»5VùïE±´ ÕJ%ü‚DvA!Õ˜¬áv}±=4L=¬XZ†í¡an×÷©­U»úß\þ¿`øšé4 |8zdo-m­$‹N~ƒçÍ ¨Æeõ„j¶úKP ¬0Z¿¦A5Ÿ×¨–úªå„¶XÊ;ƒˆ^ùïß7¶¶ž[ú¯Ï?]œš™%žç2{GhV]=úpôHÄ^¸„÷¦ÏÕÛæ(¼Y@€ž×»ý€^Ýá|qb뺧ßkÊX¶ÃiµŸ,‘Ý‚Ó Õ'øª•Jtlg‹Ž0õK_Lu†µó=êì?eä0„Ç%â½é£c;#dÂÅÁ¯ü‰Â›%0~dlØÎ¥^øÈw=zºª&Ò§z¼óàï¹ïdz0cåØL™‰],pùZz[v…ïdzž©^ÛÁÌÄX}¾÷ßÓóÑÖa¦Ó(¸*ÚvÌÞ?üDº‘^|FNþl¨ºÜ‚}µÿ=Í&¨¦…°€jWÿ´ãu šb¬6Œe é-£DD Ôk]Gjç’…'ϯþíÊUƒ9ÎN˜2rØsµl4%ÅÒ2šuÆ.¥efáFYZ‰ÅèÑ¥óßÑì‚BÜ,A.¨¨z|Ôý%}î?–[TŒÌ¼|õ±•Ê{(–JalØBò» \¾–Ã6õν%¿«À¥«ª),º[t†DWŒÂ›%ëè e Þ,‘¾>´µDÈ.(„™‰±ºåÎH_}Ýgcªã0Ì8î±÷Û¾M›:Ÿ”Ý–CQUUg)§R™ ÕÊ{êÇ>_cCCK¥u> 3FPM„:q‰7Nl]›Ú9¶¨á*•Éàü#FFW›´5 gø"bè¢Fº‚V-Ö/îÂ%Ó)ŽÃ1ËiÔsO@Oà©(|¹k7:¶3‚P @Fn>¸N€×d§)––aGè„FÇV´Þ“™“¿õOPJÄÐEô¦B×ý°•”lêâ`®Î/45^²Ûr¤þ¥Cfi։׿Ë-*Ææ!8uö—J#Cý†/bè"j@¡«¥ŽN‰D,nuló×¢‡ÇÙQãu>õ?N\âݾªºZÎkEÍÏuÆ,5¸ÐÀZCCÃWGK4x¡ÛĪYï1l®æ‰;©ìÖÓ}Ö¤OM Õr;+ñä%wˆˆè5‡®ûzjhh|%Ñ¿·|ÆT‘‹ƒ}ëæ<5QcRQQ‘9ƒßùˆÄ¤P͵ g* "¢FçU' ëUTV&Åœ¿`µûø)±¾¤UÕÿ˜›é<º ½|QIÉŽ:ƒA½{"#7«~؇á¬yø"‚£Î þ·ßëÌ8ÿ¤×}Q 7}‹Ž¦ê¥{B£c±~ÿAŽFRJÌLŒa¨×šù…­×nŽœ»~k×?sòŠÌà ”Õ!"zq¯+ù$*kj•ߺ=aé7ߥØNýèú©Ä$9Ëÿj¥ff!"áÕÂÔçRR_Êq“SÓ{áÒ3½î‹ ‰ŽA±T Øt Ëv~Þ–]ááì¹BÑ ãòŸlty™ª•÷®/ûÖÿàÛN®ˆHLj ÕlîïHeuˆˆOèºïçj¥ràõ’Ò™_oü«÷¤ _¯‰å;8¿ï»FwÞò» l ƒ§ë,puÆP[|¿ìsXt4ÅŽÃGya_bØzk”³|ϱS&555Ö†­ßY"¢—çM-x}²úÞ½“×KJÇÎY»Ù÷-ãözkæÎ6z¯§µ/É‹»ügv>ŠÒr¬:›×™Ñ>#7;B`‹×|@rZ:~@i¹ â:o?¨Îr:¡Ñ±8™xò»  ·ë‹i£GÔy½ÀSQ8ös"´µDo?ãìÖ{^•UØv —.úu·®3A®ü®;B 9-â:øÄuBý}½áé66–ïÀ{×n„FǪ—œ–ŽÐÇÀÃÙ vÝ­á¹i~¨÷Ü&-÷AXÌϘê8 ÓÆŒÄ™ä p÷^­^°û£Õë—ˆ©ŽÃ0Ü®/æ¯ßªÞWÜBSF«³¾crZ:"“Îc¼ý`^ø[‡:ŸûuÀËê{÷–ÂÀEDôj ÈyìSÞ»”‘›7iÒŠ¯V¾ka¡±fÞìÖÍùQÇg´#ôzt±P·d ¶é…b©¹ùm›r-°àƒ ·Ð]wk´–@_Ò pG¡€Ç uËUÿžÝ‘pé2._ËÀD‡!‰XŒCkVBÜBCmm ¿«ÀÖƒ‡ÕKÿÜw&ù"’ÓÒq~ßwêàô¿VÝÐ×ý#ü”|íÛ öÂ%DïØ «ÎæT ZO\â]ïû<“|sÖlÄTÇáOlY£'ÑPŽþ)bñ¶]&Šª*K+c]ˆˆšWè€jû*«”AÓ¯Î1ÿ³e=»v¹Ëðõl.^ùãíÕylHŸÞõ†®ÿµê†Öb1úºÏÆ>½0 W ëg«ž5~ÅLw”Êd8“|¹EŸšý_\ˡEÇóaÚZw«³~æà>½°5ø0r‹Šë¼VRJ*Z¶ÐÁÁÈ3u×ÖÒÂÅ+Wa¤¯‰D¸àÿ½kUï{,•É0gÍFxŒwâ’B/¶zð°u!"j¾¡ëáðå§¼wﻋéWg;.ø|é Þ=+|}̈ O׉í%ºl¹’ƒë%%èúV'HÄbÈär¶AEeŠ¥Ò:æþ¶-utУ‹^”üþsmõô`ÕÙò» ”ÊdèØÎHÝ©-ÒÂ¥«¢…Žl,ßQï+»-‡\¡¨3̓ü®—¯e ²ª ]ßêTç¹ûÏÿúŸt´‹acùr‹Ša¤¯_çœd·å(—ËŸÊš£¼âç&-÷)¸–“×À.¨ZµØ LDÄÐõJ˜ð …ãfŒy‡á‹šYØ `/T‹Qßdeˆˆº^ ËZêèŒñtu¾7ëý1†·’5RÙ­?¦û¬I;Ÿš>À!ë ZXžˆˆº^;k _-Ñà…n«¾¨‰…­¡"¬ÍÊ1t5=544¾’èŠß[>cªÈÅÁ¾5§ Æ¦¢¢"sþ¿ó‰Iœª1ƒ•!"bèjˆú 44VëêŠÿ‡á‹aزð TKö¤²2DD ]Á`¡@àc¨×º‹ïœ™­FöïÇÑöÔàT+ï]÷þ~wÌÞã§ûÖÔÔüU7âï¬ CWcä(ÔÔ\c¨¯×–á‹hØÊ…ªe+‘•!"bèj ÆŠ„Bß·ŒÛë­™;Û轞ÖZ¼è (Û¹~ïA«ê{÷J jÙú™e!"bèjŠÜššÞæLD _ô†Â–Àr'Y""†®¦N`’–H°ò] 5ófw°îlÎÑöô*~䇣ŠX¼m—‰¢ªª%€¯c]ˆˆºšcøš+ÐÔ\Ö³k—» _ôŠÂ–_ûX""†®æNÀl‘P°tPïž>3:™™³*ô"ªã~»|jöê -dr¹ymØ PÍÒ1tѺ¼„ç`›ž2†/zÁ°õ.€µv0l1tÑßÓ°@$~â4dÀeÓ§šéë±*T¯?2þŠžêí{·¨DÚÀFßP°2DD ]ôì , 3ß·XÆðEO[v¶Øà6+CDD ]/®=€ÅZ"‘ûô1#*<]'¶—èrŽÕæ*¯øÆ¹IË} ®åäõ° €€2V†ˆˆº^3Þ"¡pÜŒ±#ï0|5Û°5À^¨£¾ÉÊC׫c`YK1ž®Î÷f½?ÆP[KĪ4QRÙ­?¦û¬I;Ÿš>À!ë\geˆˆˆ¡ëõ±ÖÐÐðÕÑ ^è6±Šá«É†­¡" Z²'›•!""†®7§§††ÆW]ñ{ËgL¹8Ø· 8ÇjcUQQ‘9ƒßùˆÄ¤Î@Õ˜ÁÊCWÃÑ_ ¡±ZWWü? _:lÙøÀ ©¬ 1t5\ƒ…¡^ë.¾sf¶Ù¿GÛ7`ÕÊ{×½¿ß³÷øé¾555@Õø;+CDD ]‡£PSs¡¾^[†¯¶r¡jÙJdeˆˆˆ¡«ñ+ }ß2n¯·fîl£÷zZk±$oTÙöаÈõ{ZUß»WUËÖÏ, 1t5îMMoó&"†¯7¶”–8ɲCWÓ$0IK$Xù®……Æšy³;Xw6çhûW{Û+Gÿ±xÛ.EUUK_8ƺCWó _sššËzvír—á땇-#¾ö±.DDÄÐÕ<é˜- –êݳÂÇcF'3cV埩Žûíò©Ù«7´Éåæµa+@5KCDD ]¤ ÀK(x¶é)cøúÇaë]kì`Ø"""†.ª€"¡ð§!î,›>ÕÔH_UyŠ?2þŠžêí{·¨DÚÀFßP°2DDÄÐEOc`™P ˜ù¾ýÀ2†¯§†-;Ûlp›•!""†.z^í,։ܧQáé:±½D—s¬æß87i¹OÁµœ¼þvðPÆÛ…ˆˆºèŸ2à- ÇÍ;òNs _…­¡öBµõMÞDDÄÐE/›€e-utÆxº:ß›õþCm-Q“ÓRÙ­?¦û¬I;Ÿš>À!ë\çí@DD ]ôªYkhhøêh‰/t›XÕTÃ×Cak(€¨–ìÉæå'""†.zÝzjhh|%Ñ¿·|ÆT‘‹ƒ}k¡ ñϱZQQ‘9ƒßùˆÄ¤Î@Õ˜ÁËMDD ]ô¦õhh¬ÖÕÿOc_…-{¿X •——ˆˆº¨¡,| õZwñ3³ÕÈþýÅhûjå½ëÞßïŽÙ{ütßššš? êFü—“ˆˆº¨¡sjj®1Ô×kÛÃ×#a+ª–­D^>""bè¢Æf¬H(ô}˸½Þš¹³Þëi­Õ@Ϋl{hXäú½­ªïÝ+ªeëg^.""bè¢ÆÎ] ©émÞÁDô†Ã×ÃaK `9€“¼^""bè¢æDÀl‘P°tPïž>3:™™¿¬cWÇývùÔìÕZÈäróÚ° še'""†.j®tx ÏÁ6=eÿ0|=¶Þ°À†-""bè"z@À‘Pø‰Ów–MŸjj¤¯÷Ì;ÿ‘ñWôToß»E%ÒÞ6ø€‚e%""†.¢úX&f¾o?°ìiáë¡°e`;€Mn³ŒDDÄÐEôlÚX¬%¹O3¢ÂÓub{‰îƒ9VóŠoœ›´Ü§àZN^»ø(cÙˆˆˆˆ^Œ€="¡°Ücü˜ÂÈo6žïÒÉô0)€-PµŒÑKb`€ŠÚ°Õž%!"""zujX""¢¿§É1t1tCCÑ#ÆBõIȱϰ §¤ ""¢fée|zÑ»ö8R¦OÙÆŒ%'"¢Æ†-]ÔÐèø–e ""†.¢W룸¿À¾¦tYB""bè"zºùnØŠ'w3>LªÙðoÈ­ýš`0KIDD ]DOv€TÝŒþOÙVÀiž@ÕBæ ÕrDц±œDDDÔ”¼Ìôfµß®ý~îßl3·ö{ïGŽÕÀ ×xiˆˆˆˆ¡ëïC—ampºõÐcn   õãú¦vÛ>¼ÄZZQ7¤å.FúúºÒ[·’ TODDDD/#lMu–n ‘Ô¸8Ø×\ýeͰ~¶÷Z‰[ÞéÜ¡Ã*:¬Q],=«Èí›­ŽÆÄO´Ø«¸:ÃÌÄXý|Zf68Tsá?WË[µÔñÎ.,Ú ¶|1tÑó…­£±q¶½»uÅ¢©n°4ëôÄí“ÓÒ±voнk9y2†/"""†.zŠ_ü·™ŠMØ›à`iþ–†×$Xu6æýÏ¥¤bcà!evAá ¡Pä•WTtU%""†.¢z–I[CEîn°µêöÂÇ;“|k•Ò[·¾ˆˆˆ¡‹(+ö¨ž`Ø·Gc&èKZ >ì»îÖ/íøQIÉX¿?¨úöE¶\Q1·´¼ü߬:1tQ³ [šMÁb÷IjkóÊ^/4:›ƒB”555Y _DDÄÐEÍ líÑ IÜp"áÜGw ­Ï&€aýl_ËkW+•8MÁU"‘ðiùGåwî\äU!""†.j’a놴LËÓu&: y#çR­Tbï‰Óð >¬l­+¾ÌðEDD ]ÔèÕÄÆ ·ž[z"þìâ¿ ®‹=]'`œý@o~a‚ŠÊ*žŠÂ7!aU­[‰2rògÈàU#""†.j”a+53K<Ïe<>=¢A„­GÉï*°+ìüÃOTèÅ3|C5 ;—,ô8™x~õoW®Ìqv”‘à­%jðç-»-‡xv‹¨l«¯wüZNÞ|×yE‰ˆˆ¡‹dØJJI5˜6f$<Æ…¸Eã[±T&ƒ_ð8]mÒÖ0œá‹ˆˆº¨AZµ|\xüY¿¸ —L§8Ç,§QèŠýû*––aGè„FÇV´Þ“™“¿@¯81tÑ [QIɦ.öXàê ‰¤É½ÏÜ¢bl>‚Sg©42Ô`ø"""†.z-‚×û 8wöûÈsç-Ç€¹ÇÁH_¯É¿ïì‚Bøÿˆ¨_~•·‘H¶dæç¯ àADD ]ôJÂVDB’¥Cß>øt² :¶3jvu¸’ƒuû‚jÎ¥¤*Œôô71|C½‘Û7[‰ 8Ÿh;°W,pu†™‰q³¯KZf68Tsá?WË[µÔñÎ.,Ú  šw 1tÑ …­£±q¶½»uÅ¢©n°4ëÄÂ<"9-k÷Ý»–“'cø"""†.zf¿øo3=›°;<6ÁÁÒü- ¯I.°êlÎÂ<Ź”Tl <¤Ì.(¼!мòŠŠ²*DDÄÐE¶LÚj,rwƒ­U7æ9I¾ˆ5Jé­[ _DDÄÐEdÅÕó ûöhLÂ}I+Á§“]`×Ýš…ù‡¢’’±~Põí;Šl¹¢bniyù¿Y""z,Á·€eVìÑ,±@´gÅÖï÷ý™“×}É´ÉšK>œôÔO$Þ,A«–-ÁQgÿÛﯭE¬T&ÃÛ¿‡EGS´~5s‚GAjæ_x×âmªå $§¥ccà! ·ëûÔãXtì÷Q#4[ëê\L¿ê&‹§…«w+*2y Ñë É¼áÔ«¡1ÒÜÄØkâ¼/ŠŽÅý`‘»› zÇf µµyê¾Çã1~Ñ õ÷ɩ鈽péµ»ü®!Ñ1(–J_Ùkdäæ##7_òΚ§~½ì‚뉎y®ãMt‚ÄÝ;^“?°kkE¼ÝÁøbë–-mx'Ñ«&d ÞŒ¬Ø=:!‰6ìLsëLtò\Ǹ–›¥RÙ¤ë´b¦{W,ýç“Ï Lt‚qöE{Oœîí|øüÛŒ/—HË?*¿sç"ïN""bèjjbc…[O„-ñù¶Å\·kc€^]»¨Wâï)8~ ²Ûrˆ[è`Šãðz[½’ÓÒ™t¥2nú+f='§¢‘¥R‰¡}û`¦Ó(ªžäÜ¢bøÿˆì‚Bhk‰àâ`1ƒú?ñ|3róñCø uk“™‰1æM|¿Þ¹Áª•Jžú7"όвÛrXt4Ű~¶€Ÿ/^ž㧠¿«€Ak f:Rw‡GÜ(ARJ*¦:ƒ\¡šçtX?[¬úa`Õû0Þ~úu/^ù;BÔ¾V|:ùéë!#7;B`¦Ó(øú¥å2t5ë„/¦MÁñøD„ÿœøê£éé­[½¿ K²0ÔOÈÈÉŸ ƒw+½I"‘VFUUegV‚ž—¦Pxí^uõ;¬CW³[ÿúüÓÅ©™Yây.ã±wô|°ô+hj¨>Ïp%;nË|à5ùü¯•%’RÒ0õK_ü¸~Õcƒéôõб o” _wkh‹´ÔaL ÀipÜ(Áתð6rr‹Š1Ús1úu·Æ<—qÈ-*†×Ö(¸Yñc;çbiF|òFõ·ƒ‡³îܽ‹­Á‡1TèR IDATÕ{5âý·?¶½÷w8ös"艛BFn>¸NÀ°~¶ŽÅg[w`ÞÄq°µî†èóà¼h¼—b¨­ ’SÓ}þŒÛ¶­U7hki©»KÇ ìÞ–ï "áz[¾S£¶(¿-Ì_¿³Þ ¡@›!·¨A¾_¢X*EHt .^¹Š©ŽÃëö!9- ÆÛBRJ*nþñþßÀuØPÑ®°cöþá'Ò ôâ¾èMªªªì|)ç AÏ­W§V]X†®fkç’…£V,[ýÛ•«sœ°ûË¥ÐÖ=¶]ʵLHÄbÌtq Øu·†‘Ä::mkfb «·Í‘–™U§[²­¾‚|W¨[¶R®e áR ¦Œ†õûÂÌÄß.õzpør×nL=ò±súó¿9jÛþ{êœÛ¼‰ãÕ5ºügb/\Âém 0Î~ B¢cðÛ•kg?^“]0Ëi”Ð?<Â~÷±ˆ´¶úzǯåäÍpw21t5à°u2ñüêå;wL3[½æCÜBç‰ÛèÕU•èë>}û`@¯7dÐßîó(scu@‰¹EÅTÝpFúzØt ¤NX’ßU õ¯,up¹¯Ïîèß³;.ÿ™Ì¼d"áÒåz_÷×´+¨V*1ئ—ú1cÃ6°~[5‘knQ1Š¥eܧWý†ÛõÅÁÈèÚO%–fo©׳zø¼Å::¨¨¬ªó| °4뤮Ñý¯Õ“èŠá5ÙÓÆŒÐò þѹàÆM'“¶†á _DDôOðÓ‹¯@Ъåã&8 Éýê»=ßZšu28°^“]žžŒ Û Þ;¦:CFn<7mƒµËTD%%¿”óR*•+È+*Vÿwç®.öh-~<èäcà¬yp^¼#£Q*“=qÎ0ù]ÕØ«Gߣ¶–Vï%¼NKmÕþµc·êkÕû§êkU| VÎžŽ³ß Ûôrn­«›Ý¹S‡oèñ.'"¢çÅ–®—¶ÂãÏúÍY·ÅÔÅÁ1ßùÁ@òìóWe俣X*Å"w7,rwC©L†9k6cãCêèÿ„DWŒ],°Ñócõc¥2R®eÂØ°ÍcÛûÿˆjå=ü~p:L‰‰¯÷Øÿó¶U÷]w,¨Z2róЯ»µ:Ôeæå×Y323/ÚZ¢z_¿¡0Ò×ÃÊÙÓ1Ói”öæ!Å7¥Ó õ2sò—(ãODDÏ‚-]/AðzŸS‡¥/ܼ=LOW×4Þ;VΞþ\ ~OÁtŸµ(¼Y@ÕÒ¢£%‚ÉIk]1**+ëtý{‹K@Zf–:­òßÏÛêtIÞWQY ¡@SÝR$»-‡ø õ¿fiÖ 6–ï`ÕûP*“¡Z©Äæ!ê)$ºb8ôíƒíµŸ2Tõ¿ýñœ x®:•–ËÞÈuîØÎ[¼æ#jûF­>]»zèµj•×¹C‡UtøS@DDOÖ®¶NÇý~®ïFK‡¾}pb뺧Πÿw܆ ÅÉ„s°›>=ºX ðf ª•J„¬YYïö½,ßA©ì:9:ãàê/ŸzüGÀ•ìŒøäsôèÒ7KPQY…ï%õvÁÍt—/¾ÂÀYóabعypî€Ëf « ð±Yè¿_¾Ó}ÖÂz¢jú ‡¾}`¤ÿ 'nƒç\¸{¯†Í”™ªü•[«nðýxÖ3ÕÇH_Ɔm0â“Ï1ëýѰzûÍ,ümfbŒ-^óq%;G¼n_вâ2©—‘žþ¦ÌüüÕüÉ "¢úpíŹ}³Õј¸€ãñ‰¶{õÀWçzç­zÅÒ2šuZÅÒ2³PXR }I+ôèÒ¹ÞV¨û o– « Öo›£úžÕÊ{u‚ŽªÕ©îc¹EÅÈÌËGKôèbñ·cžd·åHÉP­”Ó«ë;·ÐAnQ1 $hk‰Px³Fúúµçrf&ÆêÖ-#}=ØLž‰9ÎN˜é4J}ÌËf@zëÚ·iS§«±¾s-•©Zµî×G~WË×2б $”Êdu‚®ü®BýXEeŠ¥R¶Q×ðIõ0Hžë KËÌÂÆ‡j.üçjy«–:ÞÙ…E;Tó'…þ¡NA/¢W§VüûÎÐÕtÂÖÑØ8ÛÞݺbÑT·:¡¡9«¨¬‚¥ó$|9k¦@µÈô´•k³Ë¯YÔ)9-k÷Ý»–“'cø"†.bè"†®ð‹ÿ6ÓC± »Ãc,ÍßÒðšä«Îæ,Ì#OEaÙXtìÈ*(¬š‹s)©ØxH™]PxC(yåäÝA ]ÄÐE¼(϶LÚj,rwS/YCõ+•Ép%;€jpýó~˜ )9“|k•Ò[·¾ˆ¡‹ºˆ¥>Y±Gõüþ=“0A_ÒJðéd—'ÎOEô4QIÉX¿?¨úöE¶\Q1·´¼ü߬ 1tCCÃVmØÒh »Oªw±i¢‹ÍA!Êššš,†/bè"†.†®f¶öè†$n8‘pî£; …Ög“?x)“‘=ªZ©Ä‘˜xl ®‰„”HË?*¿sç"+C ]ÄÐÅÐÕlÂÖ i™–§ë„:‹GÓó)––Õ™ŠáaQIÉÈÈÍÃ܉ã^Êñnú®Ã‡6Ú1vÕJ%öž8 ¿àÃÊÖºâË _ÄÐE ]M_³œ‘¾&6V¸åÓy+f|¾ífÀñSó& wЊ÷ÿ†ëHü=΋–?ñùÜ¢b¤Ö΄ÿ">Ûº'£Ô߇DÇ » ñ®=-0Ói.þ øpôÈÞZÚZI:üÀ‚wQÓÔ¬f¤¯‰n=¶ô_Ÿº853K<Ïe<öŽñ·“Ò³)¸¡šÝþIf:ª3AêóÊ.(lÐë3¾(m-f:‚ë°¡¢]aÇìýÃO¤èÅgääÏÁ;‹ˆ¨éh6Í;—,ô8™x~õoW®Ìqv”‘Ãþv&ö7é~W\[}}„ÅĆÛõUÏw•œ–ލ¤dôèÒûOF¡_wkxMvAnQ1v„AF®jéñöƒ1Î~ ú¸ÁQg‘p•U06lƒ™N£Ô‹S?ú¼EÇXà:AtVý°ÿ²µARJ’RR¡­%‚‹ƒ=Æ êä´t|ˆ´¿²0ª¿æN§ž«ëÑ÷4wâ8däæ#8ê Æ |;Ei¹jù¥Ó§ÔÛ=¹#ôüž@[} ìÕ+fºÃdøûðñ˜¬‚B\Íθ…f[çS¦g’/"ðd$äw06lƒ®;¯†Fµ¾ev‹¨l«¯wüZNÞ|×ù«ªYb÷"½v/6\M¾{qç’…ŽýíJ–ïÜý­¥Y'ƒxÿí˜é4ªÁ.HÍÌÂÖàÃØsâæ8ÅxûAø:`?6d\Çþ“‘X»ï ºšuR/Í3Ús1Je·0Ïe†ÛõÅâo¾…_ð€ãq‰Xé¿£ØÁÓm„œ¯P/Ùóõž@¬Û„áv}1Ïe o–`”çbõ2< çðñšM(¼Y‚‰ö0ÒׇǚMHNK‡‘¾,:šB[¤…~Ý­!Ñ×ûžb/\K¥ŠŒÆœµ›akÕ c÷ǹ”TÌX¹¦ÞzXu6‡DWŒŽíŒÐÛòõã«öCGK ì“–û¨ <…9k6ÂÖª<Ý&@[K #>ù ¹ù ú~•èŠá5Ù‰»wh ¶éå,n¡“Û¥“éaíùëª^{lø›ç k·ËRÑ›Öd»ƒV-Öï«ïö˜NqŽMž×ªj¥_.Q·4)ï)ñÅŽïá1^õ·C~W ßùêäK¾Ù…¶úø~ÙçêcˆuZÀk«*dÆ_JõÛæp6ðÿÞµ‚™‰1”J%r‹Š±=äöû,WO‘Ñ¿gw¼7ýcì9~^“]Ôág£çÇ€‰C}þ’RÒ°ÀÕ¶VÝpéò3‹“Ý–c×R/ ¶éÐiÁsÓ¶z·lÓ Fúú°zÛŽýû©wî€3U‹k;öï‡.ï»â×´t ë׫±Ø}’ºK³ÏîÈ-*†_ða|³È³Á_‰+gOÇ܉ã„;B8—–64h½'3')€2þêRû°ök6€õ<¯[»M6€c͹PÞ^0³èŠisò®y—~MBø¡}púÀ½þ·ßK=vYi ô Ú°È ]7lÍY·ÅÔÅÁ1ßù5ÊYÑ­ß6¯3†©ß»V¨¨¬Â•ÿæ¨{¸Õ'9-ÚZZêÖ0É娨¬BÚ_YpÜnË|`7ýc éÓ Cúô†Çø±ÐÖáx\"à·ô«¸üçƒaDâ:øíÊUõ÷=ºÔã-n¡ƒj¥ò…ßc÷.Õÿ6m×ö¹÷ø|î/V­¨¬Â•ìÿBv[Ž+Ù9uê¡T*qñÊŸê>0Ò×ÃÊÙÓ1Ói”öæ!Å7¥Ó õ¾³ÀÉÚpEõ8~8}ú `èzAyÿýK]×ºŠ óñùœ)˜0yF;Ob‘ºàõ>NÇý~áæí–c@¼ÿö'N_ÐhkiÕù^P;Ø¿¢²òÁÅ{èò» ä×ÙÏÅÁ ,:vÀémz&±~Þã§`lØûW.ƒ¢vüý®¹‡CÍÃc /ù¯* Ë uèT> ;¶3ª3†­1éØÎ[¼æc«³–_ð%RÙ”6É–ÌüüÕÍü÷X63¨ºð|‹ŒëÐÇÍÑ›ýþøíWL˜<ƒÅ`èj\ak®ïFK‡¾}pbë:tlgÔè/LÁ#è~ 271F^ÑǶ76lsclñš¯~¬T&CʵLéë!­vº†•³§cåìéÈ.(ÄøE+x* Ãíú¹»Õi]KNK‡D,ntµ3©}ŽQg`}ZfUUú¾0«½ÆW²sÄëö-+.“zééojæáëçÚ¯X`Ó3ìãà+–µß_°Àºç mMÚ-Y9*+hÓ¶ÝßnwG.Ge…ⅻȞõu*+¨¨¨@+IëÇž+¹QTïþ%7Š ¥­Sï>žƒ¶¶6´´užùœ<õ¸Dk´é#·o¶š=nìùO×ûÅWTVYFl]‹-^ó›DàTS$Üïö«¨¬‚_ðaØu·~â´ c@x\BÀcÍ&üù¶B~Wõw¹­¾>„ $ô{WuܯÕÝ…W²sà²Ô‰¿§<ó9Ëï*þvÚˆêþ þg &=Þ±Àš€@õû-––aª÷jGži÷‡¥Y'ìñ^ªqd½o ‹N–µiݺÐ̸Ý'hfÓÀþÿÊêjüðÍ µ±Pïóþütªî°¾%ó¦aɼi8°Czša€uG„Úÿ·ç|óF1<ÜÆ` µ)Z›âƒï!ùìÏu¶yÒûß²z9í¬Ôïkɼi€Í¾Ëàhg…¢Â|Þ|léjxaëhL\ÀÔ>¶½»uEï—°4ëÔä.ŒDWŒÕø6ìŠK¥·ÐÁþ•Ëž¸ý”‘ÿ‡´Ì,¼ïõ¬:›£ü¶¥2ö¯\q |:Ù.K¿B_÷Ù°4ë„+Ù907i¯×õíR/ÌY³ }ÝgÃİ Rk§ø°všŠ§éúVGÈäÿŸ½;‹ªúã8þ–EvAQPÄDÅåç..¹ï[ii¹¤¥¥fe.e’Kå–™æRn©¹§æ&)&i.‰ ¨ Ž00¿?FF—´P¾¯çáQ.wîrærùÌ9瞣­ç@Ö̘òÔ§Qª[ÝU?ÿÂŽ#G ݾá¡ë/ùpÃ}çâýúH<«¹qþj^5Ü™9zø uÔ­îÆšSÊœ ¹dýÅÚ‹Òïfδ(g6#2.~Y)«±¹ Œöæ§V8{`> øä/Ðu²ÿx X/­vm^ÏÌÆâ^³3¾Zе­ûvnfù¢9D„_á‹ou¹46&Šáý_ÆÄÔŒ÷§ÏÆÕ½&ûvnæÝ7¥Îävò­b÷³ÿç-L?’šuëá»p9Ö¶öÚ³…³¦Ë3¾ÐÕ(¥¦ŧï¦N½†˜ššâêîÁÝ»wˆ‰Âwò8,¬¬éP¯!öºš®iFqhÏv|:u§[ŸW¸{÷›×®äƒ1¯1mîbú®¯‹»‚ÿ¡½´nß™[‰ñT÷(~–‹¥ó|iи‹¾ßLzÚm–/œÃ;¯÷aÍö_y©ac}Ùuþ·“o£ë—ëÝ´%·âY³l!>ºÓ q3,,­/¶çf?W}Sy³À»ü:Ör«ZfÒAÔ­îöB¾) 6la«ßŽ­ú–À ÁX˜›ãU£º¾—*#“ä´´"kõân%qùzåÌÌðªán04†F«åüÕpÒU*l,, õoRge|-‚ŒÌL*;TÀÕÙÉ`»æffO€Þ¿,îV±qxVs+ô¤hÚ™ÙÙ8ØX£ÎÊ&!%Åàø‹Zv¿óWÂÐääà]˃èøl--õè"—¿FJz:¬­_Øë¥ AÁÌÿq³626.Q©4ž¿é?å\`-ðfÞ÷kòj¯>@×Ìè D kJœ‰®Yqs^@[qß¶¡kf|·$œÛÓ§«A 5kŪ-û¸Î]•ŠÎMkbmkÇæ'(W {ÁŒIcسm#߬ÝN«vð<ŽŸZÇæP³n=ýzùË{ÂÌË‹ÜO–:“ÞîØUpdãÞcûÉý6¿“¸×¬ÃŠEsY¾h¯¼1šÉ¾óõëý²}#Ÿ¾?†šuë±ñ—£(”º:„SüÎèW{Эï+Ìúz•Á¹ ëÝŽ¨Èk:е­£uåt`¾€AÃÞ*¶üò÷÷RÃÆ¬Ùþ«~ñq7èÙº> 7cù¦=ú².êüóË0ÿ}=À¨A]ñ]¸ü©v¤—qºJ®ß¼øçªo*O<àÐ+ŸÎ‰:|éå¯?x¯ÌêO?.@MMŒiëÝïZæÍËš=0œ8ÙÛÑÖ»MêÖ.4™R¡À»–m½Ù¡ÜÔÄïZ´¬_Ï påo÷þ uÿ2'{;š?`œ.ËòæúLMŒ QËîçåáŽwÞ›.ŽáêA˼<ÜiëÝ T\/Íëy²sÞ,ÅWãß©hQÖl}E;Û¸ÊŽŽƒKÑ=íaÍŒùË.ñ³Ó÷­SêœúãwÒÓRðÚƒ 0zâTüýÀá}»hи™AàúÖ{ÝÏé?“ž–JßW‡ÚO~øtMŽo {š± È¼«ñºüOu¥vÎËüiŒŒží|´YjÝ.­ÛwƹrÕ"×yÒðrgÿ‡)WîŸ?¡­Pèþ”ššÿä£öŒk($t=å°µÆìÇ-Çç 7õ­»™™& üÔ;c?/,Ë›?W£ç‹’o`Gú¶k­Øyä˜û‚Úk]ÉéBRJê[©wïžyAOy"ÐwßòßÐu° lݳýè¼—Öë¤J^mRø•K4jÖÊàgùÀ*aWÁ K+Â._*´ûk¨Š’´êÔkX¨/U–:“”ä$žlžT×jœ<îOdø•Bµnq7tçàìòä_ÝIO{à9;T¼wÌñq±…Ö‹¾.7£Rî?ïÓá¿ÆÌẅ%Ç}•ºzÏþqC:w4ñ[º°Ô.!žÙ',…‚}øcÍwÆoôèÚPi¬áÕôm×ڠøâÙ„¯‘½»óz×NŠ÷j¸dËŽ@w{›€°¨£y±šÖ 63ôI^(›ä÷ÎξGWCöµv…“Æù³ü9G½÷Kçù2vh_†}+k[öïÚÊú‹iиzô`ìŸàh/㇠ÿk#qq­FÀáœþ3à¡Çamk§ßϘ!=:z<ŽN9ÄòEsp¯Y‡®}>Ñ9¶j׉¦-}ØøÃR´Z =úæNz¿_ʹ¿yó÷Ÿ¸ Àÿ׽̞:þC†“ÇÂϧ¢V«ûÁ'úuš¶ôáðþ]̘4†n}_áVB<ËÍÁÂÒŠ¤Ä{c燴ÍkWÅàïÈ`«ºžMØjÿáû“ƒÃ#ÌÇ êÇÚ]JmØZºu'¶V–ú‰¨K’ŸéZYJⱉÎÔĘ‘½»ój§ÆËwìn·j×/—l­=gáëaſɽá$ Z,ÜÑMƽ1»^XI‰ñìÙ¶±ÈŸåÏ)8òÝ155eõ²…Œ~µ&¦fô0„ɾ ôOîYÛÚ±~÷ÍšÆÏ?­E­VÓ¨Y+}¿™Ñ¯öxè˜S÷óÞýõË}:ugÚœ¯ydø¢,\õó}'³ó§uúŽúÖ¶v¼?}6¯?ÂÓ•Åyúl6¯]¡¯ùsq­Æ²ÖÑðñçóIOKe϶ìÙ¶S3†Œx¥Rɪo¾Ò¯W³N=Z·ï̱ßr1è,ÍÛt0ØŽxñü«ãx,ûxâ˜}ÇOÎ>zÙöíþ½y½k§BÔ6oÏ]€s{>9¬ÄÛç߯ÓU ”ÀcO_Ú«víå‡Ý{³*ØXï¹ó.2'á驎Óõ¸´ Ñׯ¡ÎÌÄŵz¡'üâãn`_ÁÑ`øÐõoб)ïMñ}¤Éµµ ±1Q¤§ÝÆÅµúS­é¹«RŽ©™.U«:Ö"ìòE”Je±Ok&%ÆEõšuŠ}BòvrZ­æ¡Ó =*§«”‡®ü°lûfÏ®Œé׫ÐxJBˆ’!9-Å?mgÓA?sû]¾ž93Šž7ó? ]3vh_þþë~§Ã Å7_Ì`Ͳ…¬øé—ÔwJHè’Ðõ˜6~>½ï®c,>zú\å×»ufTïîòTÞ} 6/ :¥Baмx*ä…\ÂËÃU?ÿ‚*#/wÞ2ÈàØ¾Z·‰¸[IT°±fdŸlØwˆOF ÃÖÒRÞìçLBÊm–nÝÉV?µ½­Õšð¨SÐõ…O9çGÑõ1 y^Bס_vðñØ7p¯Y‡ž†`bjƹ¿9´g;M[úèGgºÄ=Ϥ#ÕÆÏ§÷U(¿.Þ¼cT£Ú5-¿›2‰ö½151‘¿ÏWë6qçn›7e÷Ñã¬Ø¹‡k‘ èàCE;[–ïØ:;›V ¼HNK£ó¸I(JF÷ëEE;[>[¹ccÕ©ÅëŸÎâÀ2ºo/š{y²û÷–ïØÍ€m)kjÊG‹¿c«ßj»¹Ò¾±7±ñÀ¯9}–>>­q¶·ãÛ­;156¦IÝÚ¬Þ½ ·èܼ)œfÁ†-œ f@ÜœX±sÑ7ãéܼ)iwT¼<ö}Êš™1º_/rss™²tgC¯0¬{¬¶C#£8vö<)ééDÇ' ÎÊÆÖÊ’„”Ûºi†Ê–å÷3s3)Y?b}ÁŸývê ©*Î÷M®Ñjù3ø"AWÃ1*c„­•„¾Çe^Ö ŸF èÕ¦¥òzìÍFQ7ãßwqr¨”’šþÇjfÄ“ùÝ(øc€Qy5_§écòF/‰ÜkÖ¡Fͺ\¾Ä¡_LÿF IDAT¶sì·ƒäæäðêð·™6çkŒŒŒäý¬X4tÓ^‰æ™t¤5{þ*Kss ¿¥ :µ‹¸ï#oZþËëk£ã< Àû~E¡P°~æ4}_8UF&‘±qœ ¹„ÿésøfž~ŠŸ–õëÑbøÛ|ÿó^>¦› ƧQCf¿3 [+K†~:‹í_}®íÿLè¢o<ðØö~ý…~Š Ô;*¶úÑÛþCÇÖ¡‰7J…³WÿXlà<x’n-›3Ãf´Z-ÀÝ¥¿Ÿ>Çî£$§¥ãêT‘À `Æôï͘~½øýô9~Üw¤´t¼jT'à\£úô`ü«ºÎ¸‘±q žþ9v–¸:;±~ß!¶ÌýL.®'äâèÀ¢IïòJ§ö‘?ž1Ý•¥džº\À˜L]§§Ùéikßµí»ö’wNˆÿ2tÝÍÌl“¡VÏjûÖ»m'˜=ªOOûÒÞaþQ9ØØ4ÁV°±!!E7¶ËÙÐË…æTÓOwÃ[ºu'6Ös*š—5£U/΄^Ñ/«YõÞ €åÌLõTóYÓÙÓÖÒÒ`NÆ‚¯;r‰æõ< Ž­}“Fņ®ïvìbï¢/©[ݶ0ìÓÙOJž ¹ÄÆYŸÒ¤nmv9Æš=ûôçz=ŠÍsgâ]˃AÁ ›1[º¦-[E—æM倧$%-ýÂpß¹!'ƒ/uvæ}‚Ž”’yªa눮™ñoà R’—¢„„. 877·w†:«þܵ?[º}W‹é#†êØÎJÆázrªŒÌöÊÌÊ.²ùV©P<µ©'Š{ø¡¨c{ØÃæfeI¼­ë"t#>[+ ƒŸ{Õp§IÝÚ€n.ÁªÎ ~–?ùµW wT™ÄÝJÂÉÞŽ€sAÌ=âûm:l´þÿ kyðÝ”IrqA­V‡¿;oñɽÇ[£kNlF)ž"ç²AúÊ !¡ë)ø;77·wjú–/þnö¬Öבðõä\ˆ»uË`Ù©KìlÕ¦ ›Z”ñq7°°´.vZšô´T´ Ö¶vÝÞ㬠º9‹“”OÙrå‹=¾ÇºØ““P(•O4½V£!þf,Ž‹º#)1à©Mã#^\%eôºuÚœ°è˜éC>ù,®ÇÄ£‚Ã#´òö=˜³foÍžÇÂ[øàµWèÛ®õê­µôÅz"e2·ùÙ^­ÇÀ‹sVo¨¥ÉÉùh ëÅwW¥bÑìéøÔw¥sÓZ´¨]‘áý^æbÐYƒõ~Ù¾‘ž­½híYY¿î+¿1XgÓêetk^—Ë!A éÞF¿noŽÒ»nÍë3– ³Ñ­y]6­^¦¯ùùxܽ9ȇ÷{™E³§³ÿç-tnZ‹Þî´¨]‘1ƒ{y­Ð~ãã »,\¸oûù¶¬[I禵ð©ïJkÏÊôññæ·ý»©¼¢#¯ñþ¨Wi^Û‰nÍëÒ¼¶3&1èŸwƒÇ½I‹ÚéàíNowZ{VfÑìéh5¹èDÑ%èX4Àº¬líÆ3—.íòîÓê׬‘1wÜèJžÕÝäQÇμ¬Û¿úœÐÈ(’ÓÒ073£nu7ô”ªR¡`L¿^úq·G[ï´õn …þXaë·½“¿Y]˜¬“r)=ÆÀéÀú¿6‚Öºwƒå ç0fpO~ö?ƒ]G¾_2¥ó|y©acÆLœŠ©©;7¯cá¬iDE^cÚœ¯HOM%6&бCûò¿V>¼òÆ[ÄÇŲfÙ>ýûOcai͘÷§²pÖ4¬mì>ö} 6ºÚ- \¥Ì±Ãèÿšá€ÁšµbãÞ£¼þÖ{9„V£á•a£ õ]<âüÝk°¼S¾ß»V«@ltÔc£µ­]¡¾^õèžZ­~¬mÕ 3àuÃóU(•ô0„ô´TNÿùà‡s~;ˆ{Í:úÀ•ïÍwÞg›ßIê5hLþCðÿ;’ý¬“¥ÎÄÚÆ­V~ÍDÑž‡9&î35ZíâçΌ?zöü{½}ZÝ6|he‡aÐO!ž'®ù 1+#>)¥!0è‰LN]ªE†ë¦s®\¸ºN½†$%è:‚W÷(üNÍ:º§ ó;‹ß JöOíË•{zO‡]¾À§ïAq_÷†»wUEžKAñq7x©AãBË-,­ :㛘šñËöM;Elta—/ê·ëæî!žxnCW¾ÛÀÌlfé6?ÿi?96²O»Ö·%| a¶šßCò>°ñÈ^¤¹;tíýÀ'óû—=©Ø˜(†÷{™ø¸Ô¬[×ê 9–úþÇôñ#åB/DèÊw ˜¨Ñj¿Üæç?y÷ïLJ ïÙE=áÕe,¦çÇž£ÇiPË£ÐâñÄ$$ž2Ý7öjTLK`90 ™VFàèT  È¾Q+ÍÅŵVºpr=ü*î5ë¬~ Ë’ñáö®Êð³DV–ºÈómßµW¡&»*•® °˜á-¬míˆ)ÜDš”Ïú•Khûr7vl\M|Ü ¾Xº–N=úþJL0xP@ˆ‚Œžãc¿ LÌÊÎn¸|Çžƒ/½òFšïª57ÓîÈìBσ٫$:>A â„­6o½»½Éзê\Љ^B7¸©.a y›ìÿyË}aê ËÍáÜ_´j×€› ?Ôúóæõºí´íðDûW«ŸNëvþ¸]×ï,øí Á÷ÍòÎw˺•…¶1}ÂH|ê»ráì_ÜO‹¶¹tVß,›ïÐ/;X¿b1©)Éúa+|^îfx,G‘¥–Ö|ñ`/B]r$ðf¶F3{ùŽ=ÓÖïûµç„WûçŒêÓÓ¾àÄÏ¥UBÊmv9ÊåÈ(Ê•5£W›–…OÝsô8'‚‚151¡[Ëf? `÷±ã$§¦ã]ÛƒW;Ý»ñæO¶mjb«:èŸ\ &!K v9JÆôë…yY3ž"8<‚T•Šm~þ…0ªww5þ¤¤¥_î;7ädð¥¶À)täoJɈéÔ£ëW~Ãâ/fèCIÌõÏý”rææ }ë=\\«ñÊ£Ù¼vŽyÁ#ÞÁÔÔ”Ÿ7¯gû†hÚÒGÞ‡µ­=—C.°lþç4iÑö¡£§Y›0ks?™„Z‰½ƒ#þ‡öâ·o—Áz 7£C×ÞÚ³€AÃÞÂÔÔ”-ëVâh/>º<…y¿‘ï~ˆÿ¡_ûzÞ›âKuÚœùó8KçùR³n=ZµëĹ¿9À¼™3dÄ;(JŽdé<_Ê™›K¬8ñq7Þïe*±zǯrÁ¾àŒ^ s Þ¼›™ÙfîÚÔðZê·[vÜRge—ê7øÊõ(T™4«ç‰³½ƒ¦Ì 4ò^Õù»_}Í’­;©[Ý w—J„ÇÜ»Y>u†~“?Áܬ,MêÖ&61éÞ§¾ÀSLX°ŸF ©åZ…ÞLÕo7äZ$3W­åóUkñòp'àÜy>^¢›gÌÆÒG”F *ØZãâ耋£C¡¯¢pØêóÁÔÍuu:|)hL”À%F¡T²týN|^îÎâ/f0 cS&Ž|€åÁŵ|úc?ü”“ÇýÞïe†toÞm:z< WýôDûõÞG¬úæ+¶o\ýÎýf¦Í]L–:“iãG2úÕœ àû­û ­ûÅ·k:z<þ‡öêÏåàžôm³¾þ¾Øý¸V÷`ùÆ_°°²æã±o0 cS¾ødÍÛtdéú(”JFO˜‚O§îlßð}|¼éÙÚ‹m?þ€ï‚tèڛؘ¨b;ë¤Õj‰‰z¬ &ž_/òÜLõË”)ó™eyóÓG 5Ô±•Rþ°Óÿ£Oر;úE—÷>àÌ†ï ¦üÉ×zÔ8ÞîßÛ v+_—÷>dÜÀ¾tk©ë31cÅj4Z-³ßÅV?¾þi~Kb^ÖŒóWÂèýÁT"ölÕ¿¾é°Ñ,šô.ÍëylW£Õwë^¸351¡4?(¡V«Ãß·øäÞã­ÃÀì¼âÅ÷Ôç^LOK%:2k[û"ŸfÝÔ7áWÐj4¸¹{¹nE©ý…ÔhsnÎXùѵ{4ÍÍÍÍ[Ë­J!žF¥è\×hµ­o&%3gþµ†CFÜÜ<ð…Ô19- 7g'” ûŽrþê½–©Võ둪R±tëNÔYÙ¨22 ú{unÞ”¯ÖoÒ³ðƒŸ}óÓ6òŸUedRðÉQUf&ê¬lÔYÙ|µ~ýÚµ18.[+KŽŸ  íŽ ¶tÏo®ÑæÜœöݪMU»÷W­Ù½ß977÷  .!„xq”æ6ß^ÆJ嬪N­çŽíТ¾§É‹x’‡OaÚÒ•$§¥Ñ¹YSÌ˚Ѫ—¾/Ö™Ð+|¾j-!×"073cÜ ~ŒìÝ]Øæ¬ÞÀÁ'Ñähi^ϓ՟~¬YÓ—­â@àIîfdâê\ß1#hëÝ€­~þL^òVææ˜š˜Ð½UsÞ2Hßܺ'§-[ÅåÈ(*;:°kÁœÒÚwëö·[wüjí¦ºšœœ$tÃ>ü.·&Á3èÓ%JéÓ%¡«$¦02šáVÉÙøE_ÿ¦­~þlõ;Âö¯>—Âx´°¥¦û¤X„„.!¡ëÅe$EÀ:mNŽGXtÌô!Ÿ|×câÇQÁáZ)ñŒ>çdnó;²½Zç¬ÞPK““ó Ð@—B”‚¿R”ÀX…‘Ñ´ú5kdÌ7º’gu7gâ1…„Gr-’}¤0 ÂÖo{'³Ü93;Û˜¬“rÅš.ñD¤¦KB×óÆ m¬TLiÓ°¾Úẅ*®ÎNR*âIhŽž=¿ôìyeÓT*·¼°µÐHÑ ]BB—„.qOy`’R¡˜ÐÖ»~š„/ñ„aë%à `©„-!¡KHè’Ð%Šg Œ7V*ßëíÓêî´áC+—æQÒEñ.„]ó:cVF|RJC`>°Yp…„.!¡KB—x öÀ4¥B1²O»Ö·%|ýû¶úù³ïø T™¸8:0º_/ýDÛ%(l5¾wä]º„„.òôâãºLÔhµ5¶ùùoo2ô­ßUknT<;‹ÚÎ_/¥a­šŒêÓUf&]Þû€óWþÛ©cO´yëÝíÆMz)>)å,PÝx[¸„BèIþg\ÆJeß½ºÞðêÀŠ–åÍK]!ÄÝJ¢÷¤©Ó÷¨22yeÊ ú¶oË›=º<•ýÔèó*^ÀØ}õËzL˜ŒS{VNûð? [C¦ûÆ^Šé¬E7õ-ùµO‰Ôt‰'"5]%—Ôtý3‘À›Ù÷ò{6|mdò·[vÜRge—ªBÐhµDÇ',S*˜š˜`eþôBè§£Þ g›–Ë*;: ÊÈøWÏ7%-ýBŸ¦nn2ô­jW£bb€ÚÀD \B!Š#Iøéò,S¦Ì,3ã¶ÌÕ§§½©‰ñ¿zN…\"%-Æukë§ÓQge|-¯Õ9þ·nžÃ–õë¡T=AxÌ ª:UÄËÃÝ`»^!õŽÊ`»ùân%GJZ:£f}EìÁŸˆŽOЇ0Gƒ ³ó—›š˜ðgP0U«ê“u&ô 7â°ÏÛßýÛÈw*䃦Ì`Á„qôm×ú_ [Ã}熜 ¾ÔØ‹® 1R.{ñŒHM—x"RÓ%¡«´©_¦L™Ï,Ë›·˜>b¨ñ Ží¬î:O‹:+›!Ó}151ÆÕÙ‰}'øvòDZÖ¯Gt|=&L¦¦kUÌËš‡»Ke}Sœ:+›á¾s‰ˆ½IÓºµ ‹ŽaÙ”I¸8:r›W¦ÌÀÉÞKssüÏœcñ¤÷èÔ¬ K·îdý¾C4¯çIt|'‚‚õ¡+ °è^ïÖ™I¯ Òï‚ [8z™èø¼j¸s0ð$ßMù€M¼x{îân%Ñij6[=‚­•%“‡ Ñï·`à2Ý—Á;2sôðgúfªÕêðwç->¹÷x`kà0ºfÄ0¹Ì…„.!¡K<¥Á3ñwnnnïÔô;-?^üÝìY?¬¯ó¬ÂצC‡151fã¬Oð¬îÆìÕ?rà›y$¤ÜÆwÌz¶iIhd/}_ÿÚå;v“vGűUK Õ~}µnÍêy2ûQìL\°¤ÈcŒâÀ’ù8ØX3gÍêŒ:+›¶°`ÃN_"4òºÁ:ùý ÌËš¡ÑÞ›VòDP0_nGQAðDP0›6Òß©Yân%‘r›¿.^«†;O:\Fë^úך› Í;&Sc” ‰))€®)ÒÖʲˆsA•ÅGC?“7M£Í¹9í»U›ªõ~•½ÇóÃV \B!þ ©éúwü®Ñj[ßLJî6fÎü¹ö6Öf½=Ò¢kËfO¥—¹eys}Ÿ'G|5x¤×iµ>¯wþºfÆÆÜÿ Àãl§8æfe©ìèÀ )ŸéÃÖ’'ZÏÕ©"Ó†åi×j´97g¬üáÈÚ=šæææ:oÇåòÿÉ'b…"±A‹ RⱯ#£„œœ) ]¥Þ>MNξ›IɽÞþbᬪN­çŽíТ¾§É“nЫFuüNž¦o»ÖBÖö`ÇoGØ¡ùþ5Z-J…ïZìþý8m½un‡ÿ1¼<ܱ,oN-×*|·}—¾ÖÌ÷û§3oó™Ð˘—5ãÀ7óz.–æOuhŽÛßnÝq𫵛êjrrœ‘Àïr¹ŠÿRŽVë ¥P¬\¤ßRÑ׎. ]ÂÀîlfwXt̰W¦Î˜áVÉÙøIÃ×=ºâú-†¿CÃZ$§¥ãåQý‘ú:З!ç}i>ümÜœˆ½•Ä–¹ŸáâèÀGÃ3hÊgtyïCl--‹¾¡ï7ö¿—êââè ï6¸sGž8©ß ,:Sƒ‚7¨¯>À=ˆg57¢ã¨Ò­?¦&Æ8ØØÐ°–ó'ŒÅ¼¬™~½ƒ§X°a3;ú<ͰU ˜ì“ËS!ij ŸJFðbb¬˜ù’»{™¹ãFWò¬îöØífaÑ7HHIÁÊÜw—ʘš£Ñj‰»•¤oz¼ÿûû_ëæì„“½~¹F«%$<MNžÕÜ(8ü…F«åüÕpl¬qqt :>A¿Ý„”Û¨³² öaki‰yY3Òî¨Ðäh±µÔ5üþ§C‡ÙtÀŸÌA©Pr›Þ“¦2ªOƒVÓî¨HU©ŠFâ/ûÌm~¿íüÍrçÌììrÀgÀn¹…x®HM—Ð%þQø«02šV¿fŒ' _ϳ¥[w²ëèq–|8ó²f\»É˜9 X=ãcšÔ­ý4.÷‚a˘¬“KO ]BHè*Ì€ÑÆJÅ”6 ë«}ÇŒ¨âêìT*N\•‘ÉÒ­;9r Uf&Növ íÖé¡Í’@sôìùý£gÏ+›¦R¹å…­€F.7!$t !¡K”&)Š m½ë§•¦ðõ [/_K%l !¡K ]¢(ÖÀxc¥ò½Þ>­îN>´ò“ŽUš\»æ7tƬŒø¤”†À|`)%#„„.!$t‰‡±¦)Š‘}Úµ¾-áë¡a«9ð-°¸#%#„„.!$t‰ÇU˜lblÚç´¸¼/×¼õÜóÂX 0(o½yyûØ&o•rßBˆÒzóËofL~É UžE¬7-o?ƒî[Vå}Ÿßÿþ'#W¡«BÈ}G!JíÍ/¿™17/4åB^8+J`^h+¸-tµ\fòö!÷!„›ß=ÑÙNvÞWD_éy¯µG×,ùS—®†k„0!ä¾#Ä©ŒxJ7¿z-E ë—U¦˜}Dk‹ÙÆbàvÞÿÿt:äý hV`!Dé¾ï!D©üÄñí\BWV”ÊÜÏK‰nœ¯‚ìó¶?BÞ.!ä¾#ÄA¦Ï‹Ãyáª_êº'A×aþ†ÃHܶçý_š…BQª?q>¬¦«2º¡!ÒÑu¶oôâÞx\ùa¬%º¾_ò–ÕÏû÷jÞk+ÊÛ%„Üw„BBWñÜ?îu’ÏE×ä8ä¾õq¯c~þ×9îõíBÈ}G!žî€ç•ÿÒ¾íÑÕt¹>d½ÊyëIí–º„â¹¶;ïÆ§~“âBHèBˆgÃÈB7”Ãd)!„„.!„xvNçÝü¤¿”BB—Bü«ÈcºúÛ|bÎná#wRÖÆE¿Çs+ì6U¼±qmbÆBý°®â‰¹íS/·Vo|oéä‰kSâCýˆ¿tÜ ®-Þ¢ŒÑ½ô2FJ*7DŽF]ì“¡B!ij }ºJ° >(LÌõO1êØêöœ[äú?ævô®,ãZÀ2̬œ¨àÑŽÊ ê•*) ÇZ…^onëj0¬CQ*ÖéÂÍà½ÜŽ>ƒU%/’Âpm1 #¥ ¡~¨ÓÈÍÑ’LîŸ?“r)oïþÀcÏLÓŸã…ïc¤45X/¿ÖP•)˜B ]BÇHiªob|I£&þâArs´8Öî\t©àNÛI’xÅŸø‹¸~Œè¿6ý×Fª·y—š¦é×ÍÍÑÔ=*û>”1Rêkв3S©à¡[vù$GêŸ(|M‹SÆH¡VÎõz£4³,r=k—†r !„Ð%î©èÙo'ñŠ?±A»°woýÀ&;m–ŠìŒ4}&Ð\vÓH®|Gµ6ã(_¡ ¡~¤Å…zÚïQFz71·ÅºŠ7·Â0Rš¡01Ǫ’eŒ”›Y‘q‚Œ”è¼§+ÝžI™d¦Æ<=  JŽDabŽ©…åluûµ÷ð¡B ŸBe¤Q«dÌ0!„ÿ:éÓUÂå71æP_éÃäæh8<§g74XnUÉ ors4äjµ8×ï ÀõÀÕë%];¡‚á¡A°NgnG!þâìÝ[ëkÌtý½Žtíju|fe{a·Á÷éñ¡ÜŽ:CŸ¼ãh[ä9ïšÌosë‘Tà L!„âß 5]%=+MqòìNÌÙ-)M‹¡tÄ«6Ƶ€emK£Á(LÍI  .x/µ:bbn‹‰¹-.‡ý×F²î&ãP«#)ÑD®~äîkwæÒþ™ÜŽ>cÐo˶Zsbƒvé‚™g·gV&Q'×£41Ç©^/T‰á„š…‘ÒŽºŽõ•"æìÎn‰[óQ›û÷nü½{÷ÖØUo%—B ]ÂP¥ý‰9»… íP˜˜?p½š¦¢ÉRsf31g·èØcÎxõ_¬_ϳח”µv!æìBý(_Á—zEôé¤D=¼¶«œå+¸s'1 ûÍwùMyfVNX:y>³òð꿘Kf~t  {( áàï F¼©ïL-ˆ \­묌‘—ÆC¨ÓÍW.*!„ÿº2/à9åvs³T¿©95ª¤r4jÊWp7jùÜ ŽŸï¥ÈÎL£í¤À’ÿ&çhHÅØÌªPÿ®¢Ê"7Gƒ¹[±¡õy±jÅõwWˆÇº ÈïxÞHŸ®ñMUšbáX «J^…BFRX~¾5‰9»Õ`yz|(iq!ظx?ŸŒ”X:y¸ –…¥“ç ¸„B<¿¤y±”±so…©…!{¦Œ…“'wâC‰9»#¥)Õ}&H! !„ºÄ?elfEó1û¸â÷%±A»Pÿ±S *ÔhGuŸ ý¢„B!¡Küem\ðø­„Bñ/’>]B!„º„B!$t !„B ]âE”y’ íãI‰<)…!„BB—ÏŠ*ù:1g· J¾.…!„BB—B!„ÐU"dg¦’¥J~èzYªdrs4…–k³Td¦Æ=Ò¾2SãÈѨŸÊñd¤D?t[YªäGÚÖã”AþôEO"K•üHeõ(ç&„B<)§ë_r;ú ç6¡N·Ï¹þçjn… |wjuý ‡šôë®ì…‹7Ù™©Dÿµc3+¿¹ ko’®àÊá/õ}š&æTi<Ž“ ͱöÛ¢þÚˆ6K€½{kêô˜c0jìß;¸òÛ|î&EºÉªk´ÿ—Fƒ ^Èž©ÄïÕo˪’/¬Ÿä âøwDü±RpL-¨ú¿áTo3Ž2F÷.µ¸ Ý\ýmwÃôût÷™H•&C Ê,éÚ .íû”´¸`ýñÛUoýHå­ÍRÝ6=A÷ CiJÅ:]¨ÝÍS } =0“Ø ]úÀeíâMÍ—?Æ®z«çí2³nËo›BHè*Õ´Ùj2R¢ù{ëX¬+{ÑøÍŸÈÉVsõ·ùœùñ š¼ù“þ|fj,1‰WÉÕjq®×URæÜI¼êÏéu¯cfåDîŸSÎÎÄ+Gˆøc%·oœ§éð­)MÉÍÑprU?ÒãCqm6{î&Ezp'¿ïK뉛Yqü;.퟉kSjvü#¥)ѧ7raçû¨ÓpÏ›èüöñ$„úáî3›*Þd¤Æ濈Óë^§ÍÄÊÙ¹û÷.퟉s½Þ8Õë @ôé\ñû‚2FJª·@Ô©õïúko¼²#¥)1g·¼ë#2Sãðè8YRO­ˆ™•/õ]ˆ±™%Q§ÖsÅï‹G*ï³›Fq+ìÕZ½kS´jqÁ¿´ €ú¯, hÇx’® Fû±®ìEFjWüæò׺×h3ñøCçv,Aak 0 &…BB—(gãB“á[õ5?6U›ptA3BÎ¢ÅØCúõ²TÉ´{«J^úe!{¦¢41§ù˜}úš‡š0³tæò¡YDZkóQÄœÝJZ\0µ»ÎÀ­åÛº×Óò8»i$1§7áìÕË¿~kSþ7r‡þxëtæôú× ó_„K£Á˜Z8ñ NžÝõ! À±&vN"-.$/üùSÆH‰×ÀoõÛr¨Õ?¿ïGfZ, «}»¸÷¬]¼i6z·Á>Ïlx“ð£K¨Òd(fVN\ñû’2F š½µ3+'ýz~ßï¡O.¦Ç‡’xån-Þ¢f§iúåNõzñû‚f$_¿÷ú„P?*Õ﯅e­+z`&iq!%=t9ß=c¤»€B”hr“þ—Ui:Ì ©ÍÄÜ'¯Þ¤Þ8oÐ靖›AàJ‹ ænRÎ úéW>·£0Rš¼W$€BÍuŽu:Óbì!ª4JâÕßÉѨqýßpƒãpi4„šÄ«¿`jQøP?¢N­×£U%/Z¾{˜ŠžÝóÖq 7GCÈ/ÓH½q€2FJš½µ›º=æ@ŽFKã!…÷Ùx¹9.û¡ÍR‘tíµ:êWþö\ yh[8Ö¢ÓgáúZ³|Ù™©(MÌ ÊÙÄÜ–›uj½¾Ò®ZsZŒ=„cÎ%ùR\úi~—såK¾JÉ×Mù‹"¤¦K«¼CÍBËLËW@•¡e „ €Œ”} (”œ•¦˜Z8™›·n4em\ úx凖ü —‘ÀÅ}Ÿzh–Ázù}›òשÛc.oKð®ôÇàX§ NõzéÇ­å¯!êä:¢N®ÃÔÂûê­qòê­ï¯– À¿/ó_Tä>Õé ú‡ÊW¨QD ªùhŸ&”¦Ü ÞGòõ“ÜMŠäNâU2R¢ ­çÙë+ý¹ïúHn•¤œ[I¾”¶G6@[ 3à ”‘ß2!„Ð%þü'ï¯!*nÝGáX§‹>ôÝÏÖ­¹¾†Ìçÿˆ¿t„P?’¯ ÌáG—àÕ1Îõuµo-ß=LâÕßIõãVØ1nü½oǹ^o}*€ 5|ØlgëÖ¼Øã¿?HE›¥âÔÚÁ¤Dž¤¬ V•¼¨T¿?6®M¸zx>·£Ïè×­èÙvn͹²—Ä+þÜ ;¦?7ï××<àPÝÌ _[òOG~S„BB—È£N+󇇸“xµÐ¹ÞMŽ|hGZOJäIÜ}&jb¼ò«aGüüs«Òd(Uš %7GCüŃœÛ<†«‡ç•ôÐUTBQBIŸ®Ù¿w|Ÿ™ÊÍ {±ªäeÐé~–Nu1µpàÆßÛõÃ6ä‹9»m–Š >úP“›£!6h·Áz·£Ïp-`iq!ú0qýÏÕ…j–.˜Éosë‘pù0éñ¡ž]‡«Gæë^ÆH‰cΗµÒ¿ö袖üù}_ƒm•¯àŽ­kÓ¼P•I…>”1RrýÔúBû¼|h6¿Í­G\ÐnŒÍ¬°woMB¨_¡ñµbÎl~hçEáP«C¡åiq!åqxv"Žgpn=»cbn+cv !„xª/à9}V£ý%î 2R¢¹qv w“"¸›IYëJ¤Ç_"hûx2Roà5àÊÙV òÄ*ŒËZQ¹á {a ŒfÜ8·[WbZ¾‚.Xý½KûgbfåL½þ‹Q(Ͱp¬EÜ…_ˆ»°c3KŒÆ$G´c< cSêõ[LYëÊdÝM&îÂÒb/`Z¾u:Ç—ùÇJìª5ǣǘZ8xÅŸ„K¿b¤0AiZŽŒÛÑ\ñû’”ë§pmñ¶nÿÃHaLìùºmYTD›¥"þâ~Â.Á²bj´›„ÒÌ‚œìŒÿ·wïÑQ”yÇ¿I:KC‡¤ÉMHÈ ˆ¡¹0`DVsDÁÑò¸ã(£¬::ÀÑ9»3ÌYW‘aPqaE×q¸ÍÊza\pd¸ÄÀ‚\$Ë%$ HHB¤;Îþº†&„«ŸÏ]ç­z«Š ç9oýê}9±÷Δì$Ô‡ÇUKñÖ…Þü=rëØ—ÄÒ=…ÒË©8´ŽÐˆ[ðz(Üø'öþ4{‰Í¸k|¿6ïu“ë'÷¯¦áìI¬ñýð6ÖsºðKö~<…&w4{IýšÜÎ6ûh¨)Ãëqµ»¿oíÈË©¯.m÷XíÓw<ßZŒ"""7›æéúx=.9ó)Ù±·³ €ˆ±?ôšßR4ey«(Üð:ç*@ˢͽnŸLꨩÆÚ€Å[rdË» }ü¿É[ñgJwÐ-aC]Lý™RòVŽþÃX_1çõ¡ÄÛ ÈNQî¼W›‹Y篙Iué.Rîx–=ü ¯ÇEÚè_Ð'{:Mn'×Ìäøž4¹š°¥ŒàÖ±3ý–;:Sº‹Ÿ½hœcÙBlz6·Ži¬ éª-çàç/ròÀ#HuKBß{ƒ-e„_p+X÷*%_¿o„Éîiw’~ߋƂ޾ éÈ™ÏѯávVd¶:jšBQèú!ؽüIÊó×ÑsðÃÄõ·³ŠCkgñÕÂñdM[O¸-™£_-fÿ§¿&¢Ç@Lx“àP+ÇvHÁº98+ œøõ5ÔW—²ý½ñtO½“Äá?¥æø7ݶˆË£®²˜Äá“H‰îMYÞJNîûŒðÈDÒï{hý9º})¦ ö‡^',"žã{VP”»€Æ†³Ø|·³’s'óÉ[ñ¶”‘4{=tMÇëq±íR{*Ÿä‘OcKË¢®²˜Ã›ÿ“­ïŒe䔵t‰NÃU[Îö?N$<2Aß&¤k •‡·R”»×¹rcâØ½O¥ºd½ï~n=RW]JÁº9|½äÇŒúÅÿ™@³×ÃŽ%p¦d‰Ã'“žM}u)E¹ Øö‡ÉüÙ*#xøüEŽn[Dœ}=M þL)Žœy4ÖŸÕƒ("" ]YeÑfÊó×Ñ+s2ý˜mlïÛ—-oßËѯ“z×ó\ý]cÓ¹ý©OŒQ©ØŒ1ìýh*Ç¿YAâ°ÇˆLnìgg¯çà‰Tï æø^úýèwôºý z ÏúYý8íØäwN^‹¡[j g)Ù¾”Ô;§™ÐðjHÉú¹Ø e¤ílÙ>ì½Fâ°I-{CLß{Èw‡Öþ–!.¦²h3Mn'é÷ÿѽGý4{=TÝaŒvl¢çà‡I5µ¥ ™@þ³¨-?DXd%;þDuñv¿kˆé›}¾ÏÙ }|9õÕ¥”l_FLz6ƒyÏh•œÉ–·Çèa‘›J5]7Yyþ:€¿”ó"z d䔵¤ÝýÏTmÆëqÑ+s²¸|’F>À‰ÿ[å·=&=Ûï·5¾ñý4¶š0…Y[ÕcE% ó{%0ô'œ:ø…ßö[÷û}êÀ‚Ìn{Äo{Xd¶”‘Tl¤Ùë1^®ŸKEaŽñê°ï½¿!óéU™-šB üÐ:Jv,3êØl©YŒœ²–˜¾÷PQ°‘€@S«>C#â‰î3šÓŽM4¹TæÐìõ8ü§Ý;QIÃô0ŠˆÈM¥‘®›ÌYyÀ¯ÖéÂàp®¢K÷´K¶qž¯Ñò±D%µÙŸÙÕî9uiã\ºÆô=.þý‡Føý®;_ìþå™­ŽávVáõ¸h¨)ÖšEA8þÍ ¾^ücM!ØRFgGœ}¬qÜþãßà›¦°oå/Ù·ò—XãíĤgÓsðDÂmÉÔžÊ wÞmöÙìõàvVÅú]º§¶jg‰îMåá­z EDD¡«³jö6Ýãú Þ¯F)ôšú6[¢è9øáK?daVN|‹ä¬g8¹ïsN;6qÚ±‰Š‚8ræ1òçk1[¢ˆ³ct¯aœ:ø9œvl‘3¢Ü yl‰1Úe2[ÚíÓ÷¥b[÷ÆtÑ¢ˆˆˆBW'nK ®òˆ1rããÈ™OH×Â"¨?s¬Õþ¾Qž‹÷½¾Ñ7¿~ÊÐ%:í²û‡FP_]JÚèç[…·³Š àãé¹ Öx;Öx;}²§ãvVQ°þUJ¶/åøžI¾ãYÜÎ*M$›Dâ°I4{=œ:ð{>xÇÆyÄô½‡Ðˆ[8ë¬"uÔ4M!—ìÓøÞR,IDAT÷JÓW v¡ºê=Œ""rS©¦ë&ëžz''òük²ê*P¸a.U‡·Ò=5‹€@¥;ßo5¯TÉŽeç“uÝÎé´cS«y³J¿~€Ø[/_p“žMcC Çvä·½Éídó›wñå™4{=䯙ɦywPs|¯ÑÆl‰"6£åøÞ¦&*oeýo3(ÞºÐhh"6c ÁaV£,º÷hšÜÎV3ÊûúÜ8g0^Ë8÷’íKýÚ¹jË©(ÈÑÃ(""7•Fºn²˜ô{ˆLNᆹÆïúêcZ;‹@S)£¦Oê¨i8ræ±ë¿ž yäÓ˜B­œøæÏݶ[Ê#¬\Mn';ýé÷¿D¨5Žâ- 9u` ½2'·!ºXrÖ3Ûýû?ý5ngÑ}îÂu®‚ÂõsqÕ–3`›šè1x"G¶¼ËÞ¦Ð'ûWt‰MÇYá0®;Þ>–p[2Öx;E¹ ³bKÍ¢Éå¤tçrÜÎ*zßý½2ŸàØîÙÿé \µåÄfŒ¡±®šCƒ«¶œŒq¯h !,2^™“9ºmy+ž£Wæd\ç*(øëœV“©6Ô”±íÝ™0„Aÿø{=¨""¢Ðõ}hâ¶IËØ¿r:…æR°nÐòºð¶I2 ìûdO'8ÌŠcã|ã‹Ç@S CBÆØ™×TÃu±ˆ±Ø’Ù¹ôQ£ŸÔQÓè“=½Ý}ƒC#È|úSöÿe‡ÖÎâÐÚY@Ë(VÿñÿNÏÁ–†<¶„}+_`÷ò'ý»D§1ä±%ÆëÒ¡/gïÇS9¸úe£MÙBŸì_ÓC´ô¹Š}«Zî¡/Àš-QdŒ{…¤OûfŒ‰ÉláÈ–w‘±[ƒÌ–µ¹QTH/"""¢Ð%7š-eD«ÙèEDDäúÓëÅ8ßBÓ"""rci¤KDDDD¡KDDDD¡KDDDDºDDDDºDDDDºDDDDD¡KDDDD¡KDDDDºDDDDºDDDDºDDDDD¡KDDDD¡KDDDD¡KDDDDn´€NxMe@œþi¥; Äë6ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÈÄÿÒ±ûÈ ìFÅIEND®B`‚grpc-1.3.2/doc/images/compression_cookbook_outgoing.png000066400000000000000000003600571310511640000233340ustar00rootroot00000000000000‰PNG  IHDRÏ\ay.bKGDÿÿÿ ½§“ pHYs  šœtIMEà 9ÌçÜH IDATxÚìÝy\Tåð†e`ØeQ …Ü0ÃÅ]3—4Í,5KMËÒ´ÒJÍ\pË¥Â%qÅ}WEE\A1P}_–™¹€“Z݆áù~>~ræœ9sÎoι×ç¼ïy_€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆêšK@¯J`Üvá¶5gzI\ ó ‹ÄÅ-Åņ2™Lø´@¬å¥eÚO ÅšŠPM­ÜÀH_¬«§S ¡©™©©)ÈÒé&ª ÔËËËãµû—Ï„ÄxÊ Ã35(Ó~Ø'õIÚÛ驙ݲÒslò³ ôÓ’2 ÒÁÐX¦–&00Ö‡±ŒM ajÙzúºÐ7Ò‡ES³*ÛËÍÊCiI ;=R©Yi9HMHCJB:2Ӳʤeå2cƒ"u _GWx%73w{ò“´@þDDDDDÄðLõèÅF¥½›ž’=(+#×%!6Ñ2/»@ݱƒ:¸;ñ½ ŒôaP˜A­ìGiIRÒž’…˜ÈGˆ¾#}WjneúP¨£}üÞ[Äó#"""""†gªs¾›jú$1uÞ“GÉo=¼c_W¨fkoî¯Ã¥[¼þFèè •b_GÇ#úN,î…Ý/Iy’š-hÜ/))Ù÷0á(ØÝ›ˆˆˆˆˆžéU;y¨ENþÓEY©Ùƒïß|h«©­‰Žî¯£C××Ñ¡‹sµ®ÖÊêqt<®ž CHÀâ²òòL}½ i)™¿çeæ]æ¯LDDDDD Ïô5uظ„˜¤E‘áZ¶±SséÖº8ÃÁÙ¾Á[JB.ŸÁÕ€Pifr¶XK¨¹*+-g% y"""""bx¦—zÿý÷…é℟¢ïÆ~˜‘’­×T/Œ˜4ƦF*{ÌObq|—¿ôê¹P±†–æšœŒœµòx6Ã3U1`Ì€–yÙY[ÜzØ]MM]}à;žþÞˆôE¦âB1θX~z_@žL*Û“ž’¹ˆ!šˆˆˆˆˆž n}œ-4ÔtvÝê£g RþÞ@ ã -mÍF]—°K7¥»7JÉI˽™3@Ï"""""bxndzöì©W®-ùõÞûc Œô£¦ C¯!µ6TCuýB8¶¯Þ›#‘”œËLÉú@,«BDDDDD ϪO£[¿.+îE<˜abf¬9~ÆHtéÓ™Uy ©TŠÀÁرfŸÀ…ìŒÜ9 ÑDDDDDÄð¬¢\{ttOMÌ8i`¬o2áÓÑhçÚ–EùJKÊpÆ/¾ë÷‹KŠK¾”Éd›Y"""""†gRÜœ|£ïƾ3ö“·ÕFLÄîÙÿAVZ¼çmÌ‰Š -#""""j´˜¬T„sÇž5õˆÂ|ñ‹6}©Öc`W¨««³0ÿ®ž<ßê!4lbÐ4*"zbiIÙ ¬ Ã35<m:´ÞûðVìÊÎÝ; ¿ÿu¬l-X•W¨UÛ½w3¼óa/ñÓ"“ò²ò`2V†ˆˆˆˆ¨ñ`·íÌÎÎÎRªVz-'+¿ÅÌï'£ûw¥–Ûy&yçÏ⊠‹ÆHbEˆˆˆˆˆ¶<7PÍ[6ïZP˜njej¾dË8uzE©Ží :tq¶¼~!âIqÉcY"""""†gRB­_·ÿ*9>u×w½´>ûqô õX”:ÔÄÂDÐ{X7È+·û”HJÊËÊÏ(geˆˆˆˆˆT»m7,öŽÍ÷æ‹GÌ]9CÝÉÅ‘©GR©«ço. O•KzHcUˆˆˆˆˆT[žPp¶lfqYßP¯ßªÝß©7µ³fEꙺº:Þìëª-ÐhF†G•Ieû?§@ ”!""""bx¦WÃCM]p`±ÏWšN.ެF§®®Ž^CÞ4z‹ÅhdÌ›6±êÜ­ƒ.€‰¬QÃÀîÂõÃF] þxÉ–šº°÷nc$.—ë6-¥¬´¬=€GVZ¾ûe.\<ÚW[çê¹Püôùz˜Zšà×S«ño»˜ïÞx»7Äö€ŸÿSëucõ$&Óßš'“ÊìY """""%Ëu,A­ó0659~æ¨zÜùÌþ ¸tò*Þ™öúêSã:ÍZÚ ?§7¯Þ…©e88Û#7+WÏ…@µ®ØWÏ…"35ÖÍ,|a—n!).f–M“™‹f-më†Ý©½ç|P«ØVЩ«Õ¶››•‡ G/ãÜáK¸wã>är9¬›YVûÞÄGÉŠíGßAjB:,šš!Ø?§ýpëê=He24µ³ªvœ£ãqrÏ9\9{¹ÙùhÖÒ×/†+Ž¥¾51ÄÁ-'äååå‡äðÒ!""""Rì¶]û¼ÞôêRVß;pÐïí^/]oð8/œØí«þ¡8ƉS°zþf¼;cdµi¶¶¬Ø‹¦fpñh>Çp7ì~•÷ßìç†Ò’2|ÿñ Ü ¹cS#ëã¨ïixx¹!Ø?´Êv¯ž Åêù›QZR†æ¶ÈJÏÆ¡m'ÑÑýu|³att…ŠíÀ›ýÜ|ŽA*•á€Ï1DE<„©¥ r³òpÔ÷4¾Ó3}¨Øç}¿ï:?èè aÕÌG.áÄ.d¥gÃÎÁ¶Æùºôº[ÛÜ—n°Ž—‘òàTUµ¯C§7ÛÕ{æGÑñé‹þ¶;µ­½5Dú"<ŠŽÿWÛÿiÇB¼;c$€Š¼ž=÷|`Ë1Ü ¹‡÷fÁî+¿`óñ•øiÇBD\¹Såó) iv?í G~¾k>˜½ÓÀŸS[Üã@€Y‹§B¤_Ñ‹ÞÔÒ³OUšó¥M‡Ö–jêjíxå1<7&Fô”að,àŸ?Þ.•Jñ*æ£Nzœ‚‚ÜB´sm[mYwç*¯£ïÄ@¤/ªqÝÎÝ*bÞyé÷ýu„p¡®v•×QÑÜÁ¶Ú³ÛöŽvJ3ǵ½58óÒ!""""bxnLœ›Xšd)K(KOÎDq‘ä¥ëI•–›ÿ}JêüÊÖkÍ‚ø³–ßgr³ò^Ø2þ,ÿݾÿ—}dzç©ë›Ž®::Â޼|ˆˆˆˆˆž‹ö­ÚØ•*ÃŽ¸õì¸~!ü¥ë]>èÜí¿œeXÙš+.(ª¶L\(®òÚÀXÿ…Ḵ¤ì•\SKE ¯é¦²°lfžà5^>DDDDD Ï…ãkí[)E“f¿‘½ ¥­ ßu~ÈÍÊ«qܬ<ìÞpZÚšè7²—"p@YIYµð›žœùÒïlî` c}Ü ¹WmÙíÈ*¯œ[¢ ·k¨ì^å(ÞÍZÙþ§´su“˜ÄjÇùXi €­›ly&""""bxnLáÙÁÉÞBvĺ™%¦ÎŸˆôäL|ùîw¸}½jx½}=_¾û²Òr0uþDÅ ]†Æú¹pCÑ:+•J±eÅîjßñ¬eøIl’â½áï Ä“˜Dl^²]Ñ‚|»7¬òÙcú@ `Ãw[«´J_=Š`ÿP´sm ÛŠçÿo#& ‚@ À³×*tJBVÍÛ T'M›­õž‰ˆˆˆˆ” çy®åúªÿ›‘ºjÙÀ1žhðÛ;°`ÒëCGWˆ§EŠ!ÒaÖ’àõÜ\Ð"}†¼ë…£¾§1És&ìl‘ø8zºÕæ}¶oSñú»iËa`¬}×|0jÊP$Å¥àÄn ‚PWˆ‚ÜB¸{vF°(´´+"·w´Ãä¹ã±eÅ.|è5N‘›•‡è;1hî`‹yÞŸþçã·w´ÃG &â×wཞÓaji‚ôäLô؉S”æ¤QSSðÒ!""""bxn4Í_Gv®o^o÷‚{ïθ|&QÑÈÍʃc{#8¹8¢×7« äSç¿Ç»tÅb †OˆÁãúáê¹Ð*ëuè⌯×}†ð+w £+DiI´´5ñÅòé<®îß|pñhüÜBû‡ÂØÔPñùaï Àë®mx"‰S`ÑÔ ^£z£×`*£o`•ïõ|«^¯a”n{ÇæxwÆÈ*s[×oôèˆA·ð´@ ÇèÐÅA§¯AY~+K[ 6¼‚ˆˆˆˆˆ”‡KP«á9q‹ÿZe˜ªª¾ü¶ÌömšÃsx*ïó=ƒ_—íÀÛ¿A‡.u33Ói¿d$gb¬ÑU¦îz“ˆ‡~‰ÑS†áýÏÇÖ{Íî†ÝÇW¸ ¯""""""åÀ–çZ$“ËL”eþàú’—ŒÓ~çaljм£ïÄ`¿Ï1˜Zš mǺTZR$Á~Ÿcê 1jÊPd¥å`Ã÷[!Ð} »RÔÌÐXêêê2™Œ‘’`Ësí’Ÿ~°¯q‡çÇ)X8uÒ“3a`¬i¹ âB1,ššaÁÚÏààl_gûR\$Á’Þ¸rZÚš00ÖGVZ´´51uþD ã©5KOÎÄd¯ÙIR©Ô–—Ã3Ãs#QZR†Û×#ñøA<€ŠÅ:tq®òs]ŠŠˆÆÃ»±(.’Àº™%\<ÚC™zd¥å`’çÌ4©TjÅKˆˆˆˆˆˆá™á™¨ly&""""R>œç¹©©«•>›Û˜èŸ*-)ƒ\M^ÌJ1<7Žâª©gäfå±ô¯äfåAV.Kf%ˆˆˆˆˆ”GÛ®]åR©T%¬´¤ Ïn èèÖ8?ôóaðÙœÏÊ6ïµr’KY"""""å–çZ$•Jã³ÒrTòØ¢ïÄ`’çLLòœ‰ÍK~Y ðñÐ/1És&–ÏYÏ“âHŽKÍÏJ1<“ ¸=Û}ïÆä²HDDDDDÄðL/ýèA|¦* u3KIp3øN˃N]CsýoÄÇ$€-ÏDDDDD Ï)<ÇÜ{T ÊèîÙZÚš>ZmYiIB.Ü@]külTD4v®ß5 6ãÀ–ãx]s^ º…ß–ùâ·e¾ º…â" ޽pýÒ܉‘ˆäåCDDDD¤<8`Xm‡çû5Uù…ºBxxuQtÝÖÒþópoßAAn!ºt‡ï:¿*ŸÛºrm; SKX45ǵ€pl÷Þƒ±À„OG¨x^zùœõö…±©ŒMpÔ÷4Ú¹¶ÅݰûxwÆHØ;Ú©\MSÒEòò!""""Rly®]ÉYƪ~ýÜjìº|.Ží`Ý̲ÊûObqhÛI o |7aå®ïà{i#Ú¹¶Åþߎ)Fñ>àsÁþ¡ûñø^Úˆ G~Âê}‹ñèÁ•­eiIÄ…b3Ѽ|ˆˆˆˆˆž‹,™T&Uõ¹ž;y´‡Ž®°J×íÒ’2„ÔÜe;¿r±ç[©ut…˜¾h2¾ûe.„ºBÀi¿óhî`‹ ŸŽ†@ 8¶wÀø#U¶–IqÉPSSû@9/"""""åÁnÛµL&“ÝyïáâÑA ªÇ¨¥­ wÏ7ªtݾtÅE¼ÙÏ­ÚúÎö0µ4Á~Ÿc¿r»µG'öpry ¶öÖwÒr•–~]j ëªêqtB¦L&‹â•CDDDD¤\Øò\Ëärù­;a÷3Tý8ÿÚuûâñ`´sm SK“jëêè ñÓŽ…è=´RÒ°ß羚øÞí6 û~9HIHˆ tk ëªêfð×yå1<76'¯ù‡IUý Ÿïº]\$ADðmôÚí…ë[7³Ä˧cï5ü´c!FO@ßu~8¤xN:7+¿Úg_4§´*¿rG ˆ— Ãscs5=9Ó¨ ò9_U¥¥­‰î»"$à.Ÿ ´\÷Þk\÷öõH¬Y°éÉ™ÐÒÖD;×¶xÿó±Xìóà^Ø}˜ZšÀÔÒ·¯ÝƒTZõÞËæ”nèÒ“3Q$.çeCDDDDÄðÜØHd2Ù…° ›Eª~ =uEq‘¾kýàÒ­= Œõk\¯´¤ çáÀ–ãUÞ]1Švs[Àè)Ñ’†ß–ù*Z›#‚ïT›öJU\=š"“ÊNñ’!""""R>0¬Èåò'®¶÷ÞÃN•óõ7ÚÀÀX¹Yy5޲ýŒkŽððrÃé}çqûÚ=88Û#=9Ñwb`ïh‡c<ƒÇõCôœØíÿƒ!Ò!7+^nöU¹ú]8~¹ÀY^1DDDDDÊGÀԉ̬´ì¯FO¦©®®:ýz"¼þF[X45¨««ÃÜÚ ÍlÑwDOhj>woF hçÚöŽ÷ºöuEóV¶PSWGvZÌ­M1tÂL[ð>„:ÚŠuíë —níaÝÜm;¶Æ”yÐÜÁGƒÐÍ« Z¿ÞR%jYZRŸe;µärùt^2DDDDDÊ…-Ïu# r<¾v¿M÷×UↅES3¼;½ú|Ëݸ׸þ_×è>Àý…ëÀoË|Ѽµ-¼ÞîÇöŠ÷OûÌ+C»*ˆ¾] “ÉîÈãåBDDDD¤|øÌs)//ÿeïæ#©¬Ä?—žœ‰ ‹¶ â¹Âb"c÷†ƒ065B‡.Î*s¬»7Ì”ËåÛù«)'5– Îè ‚Ôí?ëÕ4÷1U—’†¯?XŠôäLˆôEh¨£ ·¦–&˜·êS8¹8ªÄqf¥åàý>3re2™5Øe›ˆˆˆˆH)±ÛvÝy*•J?²ãÔØ)ó&4a9þžu3Küzj5n_Ä“˜DHË¥°s°E'öÐÒÖT™ã<°åX¬L&;ËàLDDDD¤¼Øò\·œµ…ÚW†o38VR©o¿1)»´¸´'€HV„ˆˆˆˆH9ñ™çº)-—Þ½rözKApåÌõì2IY,ƒ3Ã3=§¼¼|Õvï½Q™Û¼÷<•ËåkX """""†gªêXnf^Ôù#—òYŠÆíÔÞóùÙ9ù±DDDDDÊÏ<×VzFz».m¶Q¥¯èŸŠ1ÎcZaYiÙÇX"""""åÆQ«êGN©¤Ô@]]ݦ›ç­j„Ö/òÉyü þ€ù¬‘òc·íú³üжq¸œ¥h\b"#ðx°¡\.ÿŽÕ """"jØò\Ê¥åÒ?%·é9èM–£ñøvò²‚¼ì|ËY """"¢†-ÏõëBxðíÇ÷¤²ÃÙÊžÄ&jƒÝµ‰ˆˆˆˆVÿ, Œõ/møù5]!«¡ÂÄ…b¼Ûýcq©¤toV„ˆˆˆˆ¨á`·íú÷´DR*OKLoëáÕňåP]«çoN‰{˜ à#2V„ˆˆˆˆ¨á`·måðëõ‹…·®Ý+e)TÓ÷b‹®ø_7’Ëåïà qDDDDD Ïô(/-)ý`ÙgkÅâB1«¡b¤R)~˜á.—ɈfEˆˆˆˆˆvÛV)åeR“»a÷_ó|«‡®º:ïk¨ŠŸ>_ýðnìÓY """""†gúäry@^VAפÇÉF^]ôX‘†oëÊ݉çÀE¬Ã3½2™ìPr\ZWM- ã¶^c€nÀo?•·gãA=¹\î ž!""""bx¦WšŸe§"#¢5om [û¦†,IÃsåLˆäçE>šr¹|€«¬QÃÆk•ÓÓ²Ò2/ïy›RŸÄ$f± KTD´ô§9ë5årù"§X""""¢†O%Pj–:"ckü·iÖÒFŸåP~ÄKgúºL*•î0‰!""""bx¦: Ð"=@ï}Kš5kÙT—åP^‰S¤3GÌ+,-) 0œÏ™ˆˆˆˆHeð™gå÷´¬´üÂÅcWÞrrqÔ7·6eW{%”›™W>}øÜ,IqÉ.18©¶<7ÎZÚšW–nýZßÉÅ‘7=”ˆ¤HR>¡×')â‚¢Ã>cEˆˆˆˆˆTCXÑ!•Ê®¹6²UÛêÖÍ-ùÛ)ÌÔ,ñ´¡_Ææ==ÉàLDDDDÄðLÊ!AZ. ¸z.lpYYyi{7'KR®_O™3n¡ºD,Ù`+BDDDD¤ºØm»a2ÒÐÐðiÛÙ±ã¢_´ÔѲ"uH*•bÃ÷[ãÏ 4“ËåðcUˆˆˆˆˆžIy}dbfüÙ¿Å6fV¦l…®Yi9˜ÿþâää'©rogUˆˆˆˆˆT»m7lÅE’Kþß°jnQÖ¼•­1KR{Â/ß*ž3n‘$/'?@°*DDDDD[žUƒž@S°Ú¹“ã›ßüüy[‘>¡_%©TŠM?lK8³ÿB3| @ÂÊ5lyV ¥r™üDzrföi¿W[{k5[û¦Ú,Ë—™š%ž>l^âÐ(5TtÓÞ ÎáLDDDDÄðL ZTYIÙÑ€ð±QqèÜ­½ž–¶«òº|&äîÜ ßë‰ ‹xì¦MDDDDÔh±Û¶jÒPWW_ª©¥9mʼñÅ^£z[¼OòOýqïQÊšo~òGB3ÓœbUˆˆˆˆˆžIuuPSSûNd r™±ðA÷]­X’‹¹Wè=oc|Bl’€ŸxxÊÊÃsãÐJ]]ý[c3£Ž_.Ÿ.lçæäÀ’ü)ö~\éºo~‹ô ÎÀ.ó¤±2DDDDDÄðÜHC4€¯-lÌ[Ïü~²Y§®íuˆŽ¹W¸aÑ–Œ˜ÈG-œEÅU&‰ IDAT(Ú‘¨Ò’2„^ :µ? ëÁÍ?lËJËd6Ø ?;1<ÓÿCàMžjêj ŒôËzòÈ6±¿­eSs§†p‰SpùÔÕǧ®–¤&¤ÛËåòLÌŸ˜ˆˆˆˆˆžéU³Ð@m¡¶E«¶v’ƒßÔíæÕåuCeØÁâ" ®_ <,Ž ¶(.’˜Hb`&"""""†gª/]x语£mÖâ5Û<÷Þoh·ïâlbÛ²©¡Ž®°V»y—–”!;=7-áQÂãೡEáWn›åç:ÈBÅ€_×¸ÍŸŠˆˆˆˆˆžIUiOÎ,ÕÔÔt4µ4S ŒõÒÍ­Ìrìl [¶µ×Öj¶p´Óh ÌtEB SË&ÆÃèY ÎÉÌ-IOÊÌÍÏ-PÏÍÊ+IKL—feäªe§e—ædå#?§À ´¤T_.“ë¢âYåXá¨hU¾ ž?1wa)ˆˆˆˆˆˆˆjæ |Þ™ˆˆˆˆˆˆè¥Æ°DDDDDÔXªk{WüÐM¤¥åŸ™›?ÆÜØX/·°0ƒ‡14¿7Èë‰|LßÞò=KʽÜ]eú"Ý¢–M›. d•ˆˆˆˆˆH©±TÛÎnXítäbж㗃]»wlYcGÂÎÚJ±<êQVíÚ'¿ÿ0__W¸(>5}ØMDDDDD ÏÔ˜Bó‘À ×Nm^ÃÜ÷ÆÁѮ٠׋z€Ÿ~ß-‹IH*`ˆ&"""""†gRi×}ÖÛì ¼²õhà•¾Ž-š«Íyw œZ¶øÇŸ¿v7«vî“Æ§¤fjhhÎIJOßêÃ3©\h¶63U›;q\ÚüßÛ ‹À²m;¥¹…… ÑDDDDDÄðL [\à#Ÿ‡6¹xe”±¾àóñcеó+Û¾HVøî.Z$‰KJ¦çäçŸcÕ‰ˆˆˆˆˆá™\hV¨ æM|ž®.µö}ûÏbõn?©\.cˆ&"""""†gRòм]¸Ó/xå‰+צI$Z_Œ^î®uòÝåR)_¼ ï{Ë455îeçæOÍ/*Šà¯BDDDDD Ϥt¡937OköØQÝ·W½ìK¹TŠßOœÁº½¤†z¢; ÑDDDDDÄðLõJ¨±öÄ¡ù'._÷8%M4{ì(ŒèÝA½ï[IivžöÇÏ~‡Ê õEWb’?Ë_ˆˆˆˆˆž©ÎCsä£8ÑŒ1oãý!”"4ÿ•¸X‚_ƒÏÑåæ&F—¢‰ˆˆˆˆˆá™jݦ¯>›v*8téÍè‡&Ž ½ ­¥©ôû]ðT Ÿ£'±õØÉR3c£ã1 I3¤ñ%"""""†gzå¡9än¤É¤¡1ííaéÜqä`ÝÞƒØsö|¹µ™éQ†h"""""bx¦ÿl÷âoF½|u]Pø-› ƒúcÊðÁ0Ð5øãÊÈÍÃÆý‡±ÿ|`‰©‰áöG Éóäñ'"""""†gúסÙ?$ÌfLßÞ˜5v$L Tî8Ó3°z—N_½^jnj¼!šˆˆˆˆˆžéoí]ñC·3AW;{-ÔqXÏn˜>zÌTþ¸ãSR±nïAø_¿!nb`°æQròRžD¯†žY+ùÓLŽÕGªKפEYQNœ+ADÄðL$4Ÿ¼âØ×­3>?¶æ®Ññ X¾c·üÚÝH‰¹‘±7C4Ñ+#ø#‡ Õuz%ÿýDDÄðLªìì†ÕNG.m;~9ص{Çö˜5v$쬭}]¢ÅaÕ®}òðûóõu…‹âSÓ7(çCÄðLÄðLDD Ï04 ríÔæ5Ì}oíšÕ˾xïòÃè¾½”²¥;,ê~ú}·,&!©€!šˆá™ˆá™ˆˆž‰ë>ëmö^Ùz4ðJ_ÇÍÕæ¼;N-[Ôë>Y÷ W,F×vÎJ[·kw#±jç>i|Jj¦††æœ¤ôô=<›ˆž‰ž‰ˆHƒ%PÍÐüÎÂûZ›™ª­ýâS¸:µaaþ¡®íœqxåA@X„å²m;}-›˜x3DÃ³Šˆ Clb2¤R)f¯Zï]~urÞtmçŒÃ+—VÌúÄR_GèkÙÄ$ÕÆÂb¯(""""¢ú§Á¼:qGŒ|vÚ¶æðrwÃ[s`Íœ™Šeîíœ1güÀ×›|°ñÀüöõ—ð Õ[wpnÓňßs'þ}n314€¸¸úXW‰é076Blb E"ÅwjkiâÐ… E‹ø³÷½wíSì7ØZ˜+–…ÜDw7ŒîÛ«Ú÷<[çß²µ0Çá‹—«móÇí»0¨[W,ýd  [gŒœûMιíéêOWH˜å ßÝ;l-Ì¿KJ¦çäçŸãUFDDDDT?ØòüŠBó‚Æï8ivÖ± «ïÌÿ`‚ààŠÅ¯<8À¡‹A˜òÖçç%§gÀÊ´É —·°¶BIi)àè¥+x»OÏ=U–®PbIExÞ~⌢%ûEûŸ’úÒ}ª+ï òÂ/‡ŽV{?0ü&Fôî¡xíâØ†"ÂîG×ù>z¹»âÂæusÆ¿ÓJOGxÚÖÂ<ÆÄа¯8""""¢ºÇ–çÿš· wú¯=cÁÔ"‰DkîÄqðrw­ÕïÌÉ/@K›¦€E¿nCÔ£8À¦ùsÁ÷“eÞIY6ÍŸSåób±¢›³Ï‘øúƒ €ÌÜŸñí‡_®ÏÚvüôŒwû÷ÕºìósgG»f¸v7`nlTeäêg¬L›(žö9z²Ê²)Ç tǯ8êýc•àÜʶ)B*·ûoØZ˜#5+§‚C0¦oo¸:·Á^ÿˆ„Â*ÁÏÑ®VÍžßSgŸ’ª¿çhÏÞHLÏÀÍè‡UŽçftŒâuNA’Ò3àdo§û¬!`òðÁß¹Eðþ´´µBZ5kz@+^¡DDDDD ÏJšû|ùyÞ²í»~èÙ¹“èYhÖêt_>z{|ŽœÀñ `””–¡à%­Å³Ç‚ÏÑ/]ç™÷‡ D`ø-xïòCNAr ªMõ"ÚZš¸rëzºtÄ`®ð;wf5<;meÚÃ{tú½ï=ëB©YÙŠ¿ÿS϶SðïºVkkibÊ[Càwþ¢â½qýûbÕ®}ˆOIEÁS1¾X» ý»ºÁÎÚJ©ÎIm-ML>×¶mÖÖ½[o=цh""""¢ÚÃnÛcÓWŸMüí×KoF?4ùxäpl]8_ѽ·>tmçŒ_æµ{`ÆŠµ0‰Ð¿« E#AÛZ˜+½G‡vhïÐ §®†`¬—'ÌŒ`ø‚£íšaß²ï°bÇlØÚZZpsj£˜?úeÚ;´B k+hkiÂËÝk÷™ieÈÓª2@Øäáƒ1eéJdäæÁÜØ#ç~«Øï™+Ö¨ÞÛÌØ¨Z·i ¶æŠÏÀàn]ñí䉻¿Ï·ÖOè¿óÝ̧~ 9èÿé—J¥ìÑK*GÞVF"!挃)Ãkø=Ù{뱓QfÆFÇc’fàd»DDDDD¯ˆKðâÐ|*8tiÈÝH“ICbÚÛÃêý¹W¢¿“SP€u{bÏÙóåÖf¦GU$D{ø@€o_²^ãܰŽgC½‘ü‘÷mHu^`É?1<ì^ü͈£—¯® ¿e3aPÿ:ßWYyïò{á2e«OÁSqµç¼Ÿ÷ÿÎ ][Û­-¹yظÿ0öŸ,151Üþ(!y>€¼z j¸ €‘Õ°Ž€{Lt jáùîÁYc[8ôùâ…ë¥Þ=†Ì?*Ñh7R¹ï­<ÍŒÅã ŸaÛyŒíÜP*ÎAô™ïaÑv,ÚöW·±l;{ávÃ÷ 7>Té÷?l²r”@KdÂðLDDµŽÏô¥ÛÉmÇû_n2\Û<x!QhôÏ<ï]ñC·3AWûlõÇa=»á²Ï†jóü6vÊÖªú2z¢ZÙßÚÚnm³µ0Çš931kìH­u{NËÎ-˜ÐÄÀ`Í£ää¥$ èPnXà;?ûܲž¦À‹»kâï»°Û ¢…þ)¯ü†C %‚´TŒôgkl‰-HÄÓÌX¨khCV^¢üÿ;fí·É‡¡gÆñÿ^&/ñ&ò“ï°DDTgmËóÞ?t{o׃éKV].)-s<±v9¾ÿègRIvÖVX3g&¯\"jÕ¬é×ú"Ýœ–M›.® ” ÅÒÊý€A•ïéØ^x'Õð™·QÑ;@*€Dsþ²Ž€Í +—¸UùYjŒlÚChh…Ô»Gk\žy Úúæ0´éðÂmç&þm°–•—@’_ûSíi Ñľ+´õÍ_évK 3þÑÍI~*¤¥â½}¹¬üÕñŸÖûùý‘ËÊy¢Q½kt-Ïg7¬v:r1hÛç+Ö¹vïØ'×þ¤tÓÕG»fؾh¾ZÔ£8U»ö}÷ôé }]á¢øÔôM¨è­Ìžuß¾ŠîÛm,`W¨“þ²þ‡¶¯\þŠ­BE×ïù•ë­ð>€Ÿ\Ÿݿ÷x£2°“’³r‚øm(çT{þ5åîQX·^¥Û3PÑ:êø¤FžT„E#[8x~3‡^UBgä±yȈ>¹¬BC+8z}ƒŒèó€ïüRã>EìšI~ Þœî_e[×~]c[¸M>¬x¿(;¡ÛF£e™0°r­}ÓÐfÀ"X:þϵÉx€û'¿EQvÔÔ5`îØÎÖW ç²òüq~9’nîSt7¶sCÛA?À°iû¿ åQ' #ú¼"Û¹¡Í€…0²uQ¬W&ÉÇCÿ‘|ë ¤¥b¨©k ‰}W´ôô-ë®|-Þœ iY â‚7¡Tœu mX9óðåh‰Í±kÑg¾CÌ…•èõå ^DDT«MËóÙ «>1,ô½oˆ|’–æº{ÉB¬™3“Á¹Úrô$¢ÅÕ¸,êQöŸüóu¥eµ²âbIƒ®¡SËؾh¾ÚÖ…óŒ,MM×414Ì´³²øÊCíY÷m>fW†Ü¿>Ø©W’#t«\~ ݽ÷ø¢2tƒEÅHÞìðVågÛóŠk,A.+Gúƒ³UÞÏKŒ@Qv,Uû̃³r÷(Zö˜ · ÝÈõ(-ÊAøŽ (ÊŽSìÐ-#}-{ÌD牻`å<wÎBzôy”<}ñÜôúŽÈO¾ƒ§™±Š÷²]Aqn"²_CI៟Mpʉ0mÙ Ò²ç&¢¼´è•Ô&bçû0kÝ n@Ë3‘}¡[FTiù ÷€ÇW6Á¢ítž¸ íF®G™8×6B^bÄË·¿k2ÿÄký¾‚ÛäÃpº¬âfÀÖÑŠc”•— Ôçm$ÞØænñƤ½h;x1žfÆàÚæAŠz­Ò‚~Æ“ë[ÑÂã¼>b5LìÜ|û îŸZ0iá‹¶mÀ¡Ï—¼ˆˆ¨Ö©|ËóuŸõ6û¯l¶tE_ÇÍÕv/Y§–-TæøÓ3p*8âb ÌMŒ0¬»‡b³¨Gq«øG—»+횢 @\O׊ø”T„EEc‡;D:Â*áÓÜÄÚ)掋z€ø”ŠÇF…ZšèéÒQñ}âb N‡TÙ?;kK¸:µ”K¥8tq)Ý]Ú´FO—Žþ,úߺ‹r©&†çåYãœÚ>GNÀ@$ªñwŒOMC`øMŒîÛ ±‰É˜¹r-ά_ùJkþÕÏ¿ “ãkÝ·Wƒ?\ÚàðÊ%ê×îF­Ú¹oµ¤´l¾††æœ¤ôô=J¼ÛK ÇŸ­Í×°NT<çü ª?Ûý{åg‡¡âéxž¨èÎ}¨òu4*Fí¦ÂØÎMÑuûùçžS±-Œíܪ}&ýþYX·ŽV½fÿy×Ŭ%"ÎCAjt›´@|Èv<ÍŒE‡ÑaÝ¡¢'¿ùkžÐmÒQÇç¿tŸ,ÚöGlàdÅ*ž_Ί½ ¡¡$ù©È‰ U»a€ŒèóÐmÒºMZ øw oÙc&Z÷hÒ²„†Vˆ<:‰á{мË$¤Þ=†¬ØËhÕë3ÅzÏŽóÊúžˆ:¾ JëùóJ 3—ûnŸ …GÅ¥ØÄ¾+„Vˆ \ƒ§™±ÐÖ7GB˜/ R#á<|š¹¾Wña‡ŠïZãhÿ¥è4n‹b»eÅùè9ç:„†7¸m:Æ%ow¤Ý;‰×ßò†•3Œ›»!ñÆn7wƒM§Ñ¼ˆˆ¨Ö©lËóuŸõ6³Çògá a‘ú­ýâSµm ¿R©àÞÓf!61¹"ØF>@LRÅßýCÂðö¼o!–#§ >ýÁ·ï¶?)K–#§ @ÅTT³½×+^Ïö^¨ÇqˆOIÅÒm;1䳯-¸{Ï`ÿù‹HLÏ€ßù‹è5m žVtwÌ)(ÀlïõHLÏPüÉ-(Tç‘s¿…ßù‹0ÔA¨¥Y¥õø—CÇðÉ2o€¡ž±‰IÈÿûgîy¸cóüŠGZ3rs‘“_ðÊëþ¬Þª¤k;g^¹D°bÖ'–ú:B_Ë&&©6ã”twËlx.×4׳> ßˆûËŸgÿB6Óg•{UåòV¢bj,j@¬œ‡ ûñµ*£n§Fž@Ó#k\_[ß i÷Ï !ÌWñ,³‘­ ?o~ð üCB1´‡À½³bäéc'áRÄ-Å2 æÑ¹£Å!,êNT´b?Ï÷”?~˜ö!¼Ü]ÿáƒp,ß±b‰Ý;¶ÇšÏgB¤#Ä©àœ¼r §¼O–y#§ n?BèŽ_«mcñ–ð;W1ï«­¥9~šñÚ·®ÈS;OûÃ{ç>#m¯™ó)\[cñ–ˆˆ~ˆèøˆÅ˜<|°JWž®.ðtuø‡„Y®ðݽÃÖÂü{±¤dzN~þ9% ÐÏÿ÷¯ž „v-É5yö,ó%-P1@˜'€þ¨èÖý*Fñþ•ÿWÑ0XwxqWSŒº I~*,Õ¸¾Óe¸½:"ÎPÑÍÚ¢íXµ¦x·8/"3Ê%rú IDAT‡jŸU×ÐþGs ›µîä[!+/8;%…0mÕO3c‘[ž3¢ —•ÃÌ¡ç+¯‰ÐЪÚ~ªkhC[ßâÊ®ÒE¹‰€«ÿcï¾£¢ºÖ6€?0Cs轈‚ ¢ b ‚5òÙ1öØõªW‰Æ%1¢±›Q£Øbï„€b,QQ¸€" Uf`¾?F¬±PžßZ®„™3§¼çPž³÷Ù{c—ŠßhŠe-È•ÕÁ±÷rDž©ü§gÕ&:¡n+Ô1Rܰ–ä“çŒË—HÔgŽüÚ­—ÕYZf¶òæç=Îʆ¡®n¹^k3E‹Afn.Ò²²ÐÒ¡Ò¶ï‚ÿÑ“Øôí DÆÜ*·Ž”Ç€ Q#þá#x´l®|o_ày„߈ÆÃǘ1ô ekm×ã•ÿ?¶o/Œñê C]]l_4 ñÇÖ£'1ðÿ:aêÞÊç¥×Íœ†yýà>j"<]?ÁÔ/¼_ÚÅ~²O?åg'z{aÌ’X9í?¯ÿG¶H„”Çð;|]ZcÎÈaÊ÷œ»€®î®ii")5 ÍÚÁÒØ¨B {màãÙý:µ<ÑÞwÇîãúV73²rÆåäçGUñ]†¢Uz€=ÛB=«4Yº\<€†=³Ì9qP LFÕˆes/Ä­†ôIEƒû¸.[ÖÅØºÍ`X·Œ’bÒbÏâï=ãq÷ÜJ˜;õ„–¾5Äéq()–• ¢Å2)¤OÒ^*ÀÈÖuÇ]DnJ 굆ªPC(ß AÚí@åàWïZÙ4OÏî{I± …âL–†u-kKÙnj _ç~ƒ0ÿM°±4GÏé³”ÏhWÆ@WGùÿõ-Ì•Ï]¿.{k+¬Ÿ9 á7¢Ñkú·h=t vœT ˆ“ž•Ș0ÝwòŸ¡®.$ïiäîªN(Àdz#.mݤöe¯î­„jˆVQzuêTå® ˜zª €SP´$;C1µÕ·PtÙ€¢K÷i(¦°ú¾tù6xúÌó6þš¨^ʺhß:±…âLX–Èõ¼'©±8»´)î]øYùšŠªfM»BMKOùü­e /Irt¥üz÷‚×½Ö<ŪB ˜4ꈴØ@d'FÁ¸a'€¶‰=4õ,pé×Òý|?Ï;—Ëð(úD¹×\;y¡¦ž]Ë !|k…ÏFüÖç–5á³Æéwƒpnysüï™Ïª 5`åÜu‘²Ž¦ž(’ä 寑rŸ/’ä t}g\ðu{㹜B ^ðDDôaÿ.®n;\$üùØÙ£¿Y;ëþÃG¢iƒ _§v•>G[“ÙY[!.éÒ²²ËÛ²0™ò8)3”] ¯ÆÞµ™) uu•ÁzBÿ>Öãÿ* ܇}—)[«Ÿ§+Áù9¦ €›·à¢ßú7ÚwÇ&X2΃FáúݸrϤ[aÎÈaHz”†ÃBááܼò?|ÅO§pù_Ê£ 5x•´¬l4ª_ûW|q»ÏœÅÜ ~ÊÑÊ[4²Çü1#”Ë_¿ksÓÚýÃB À¯žÖ½‹`ÇÉ3­Öí=nol—ø`<­´UÍ|(ûÀÙg^ß` ž¶F°®t¹y¥¯IüŒ§sAS5¡ká„:F¶xxã°²wetÌ oÝ áþP×6…I£(–I‘ñ;¤OÒPÿÓQŠŸ§ŸŽDrÔ^ăœ×aPßqñ¨t­× ôM»áÚ¾I£OŸù5¶k‡ä«{!PÁ þû¹ñ«*ÔÀƒ_AV(†žUsdƇãöŸ?@ÇÌA9x—u›ÁHŒØŽ;?@&ɹSOÈ$¹¸² ORcÑÈóÛ¶<Ûµ…¶‰=PCC[7ä")òwÈ ÅÊ®ï6îc‘t%7~…‚œ˜4êi^:îž] é“44÷^ûZ]ÌŸ¥©«xd(éJ ²a×~ T¨‰ˆè=ª6-Ï%AAÂÕ_Mžÿù7_e/ߺsq‡6­DýÖÁdzc­ ÎÐÚ¡Z4´Ã¸%+s/ÒÂ"\¿‡”ǰ63EÛ–-0w£róÄÊQ³'x+Z6Rg@¤¥ u5ê*ž13ÔÕ…´¨ðöÁ§s'俉q&<²ÜëÏŽ¶]Ö┚†Ø„DÈärÈär\ˆº†\±XÐÃnD+[¡cqû‰hÑÈî…Û^¿÷róÄÈÍãÇmèÿy‡JÃ^ŽXqüÏ·Ä߸{_Ì^¨¬…¥êhiBC]ƒ»z"àt ®ßQäÁÐk7àõõ¤ef—;Æ7mí®)4ÔÕ0Æ«'Âü7©õi×¶“®¶è–}=«sx:zõ‡°€ €E¯X΀€&>``ž>ïŒÒÿÀŠé©š•.7/Œª°²V\«–Þ/ÿ9:t+ŒíÛáö™%]×a›z %ú8ìÚO]ûÉ­Ñ®c nëHýçnü ùÙIp½ïµ÷ǸaG¨¨ ¡¦©}ë§6ŒíÛ)Ãõû }:¦hÒ}!bŽÎFèºÎøçø|Ôk —Qû”ÛTjÀeÔ>˜5íŠû!›piCDl€ìÄ(4î2¯ÜT^ÏSQ¢ÕÐmЯÛÿŸÐuñ[?żÏ]æ)§¥RÂ} 5øLYïË[¡ ; Íú­z«©¦ôê:ÃØ¾²"p÷ÜJä¥ßåÅODDï•JuØÉßNŸp"4béÕØÛ†½½0¬{—Jçÿ­m2ss±Ì'N‡E W,Fc›zØôí Ø[[!-+ßü¼ÿ¾=‘cûöÂ$Ÿ~PéèÓßÿ¶ÆFãÕ®#Æã°ï²Jîzv9øíðq„݈†ÿ‚o‘ò8^3æ”[¾g[wÌ3¢þÆ‚Í[”ª˜î¤EC{L<@9ϳ礯’žÌÜ\Ø[[¡§˜äÓ·Ò#^3æ u“Æ8|!b‰^í=°hühh¨«)GÛÞ4{Ä ™·1÷ãq~óš -é¾;÷Âïð1hª©ÁPO‹'ŒV¶to>p›÷†L^ ‘–f¹‘À÷aÁ/[0гUë¯ÃÜ<1üÇ–#Ç M ôÞMLžò\8¥Ú¥¤û²êuú‹$9ÈÏH€ªP"#ÛrAöEÏã–Ëpj^]X9{£…Ïú*ŒòB1òÒã ©kQé¨ÙÏ.'Έ‡ªP"#›7j .g¢ ; uÑK?[Vo5MÝö xeÏ®¿ÎèçïÂÉ9æÕæï'""ªEá¹,4‡ßˆ6Ù»;&ôï‘–&ÏQ½™³f÷~ì:(³41>Ì]ãiBѽ½Ú‡ç—¹ubâ/ýŠvÓC¡mò´sEbäïˆ><޽—£þ§#y5Ô" ÏDD ÏUJÀ÷óú¾xiMð•¿ëëÑc½z*GV&¢ª--+öľÀ ©±¡ÞÖ{‰fCñì1Õ,Ù–Xû\ˆ®Qá97%—6t…¦ž¬Û †Ž)r\GÒ刌lðÙ¤3%ºv‡g'-´‡b`BS:¬Ãó ÍgÂ#ëôì„©ƒ¼•ÏäQõ’”š†U;÷â䥿 M ü¢kœrR(¦ú𠝦…gÈJˆ@Ü…5ÈNŒB‘$uŒlaæà ûÏg¼t 'ªÑáyƒ jÈ-ý¯*«CDôÑÅB1ÖMÍÏu453tE"#«–©½h¤g"ª^"¢ÿ¹ãóíBó"™,œ7¹&Jƒ¢µ- À@A5-<UžU| `)€¶ÔªêßVDDµLÉûü9\¥î’æK$íS33Ov7%gýÞ¥µt^]¢š +÷É;_ÏÙÓ÷빆E2ÙÁÒ?0Uø¯Æü€[vðÐÀ^ùT‹üEWí:¾Ï’ÕlUõî¨³ŠŠÊwºÚ¢Ïæ®6г“^mœŽŠ¨:’J¥÷¦ü´&âxhx;(æW^Šª94ý;ú¨¼~ [ž©&{Å€a6X%"¢æ½¶îÑÉÐp1¯‰êcÙÖŠú&ÐTãÜÜ5‘L^ühî&¿] ¼áxhxÝôep&¢wé^ðzÄžZÌBÑGS]F†¼ “ËÛ=ÊÈ3aÙÊû­†Œfˆ®&n'$bp×Θ1t §«¡¡¹~OoñÖ#'-KJJ¾, Í×X"z×ß=”èc,1<¿¦²ââæ22'LüaU|»±S’/]‹.äi¬š&.÷ETìmü¸m&.÷ì Bë¡càä3®#Æãld”ry¯s°bû.Ôëáo×mf«®ìõûìiÐk@zih #€P–†ˆˆˆˆž«–#E2Y³¸¤äy_ÌYø€!ºjÚ4{Z;4Æ‚±_bÓ컿lÿ‚o½o;|§OÂØ%?"æžb€Ò”ÇˆŠ½ƒ?7¬Â„þ}XÀ*šëu̧ƒ¬¸xvih¾ÀÒPMP$ÉA¡8ó•ËIrR /¿r]Ò'i¯µÝBq&Š$9^—>I{åvJŠe䤼ròBñ ×U•„b™ô•ŸÕvJŠe¯µ®×ÝfÙr%Å2^œDDT%«ùþo—Ä%%2ÿ»EÍìíU–OoådgËQŪ £Á¡èß©=Z4²x87GÇ6­päb(ílÃ{tƒM=«JQ‘üxîø¬µ›-%EEP v„u¡ª*è§O`áÔ Ý”{ýÚž ÈJŠBÇo.bO-FVRšt[€˜£sóà:@×Â Ž½–ÂÀƵ\x¼{ÎÉW÷(¶+šöX =«Êå’¯îC\Ðjäg(n jêYÀö³q°q Uů܄0?Ä_ú­‡nÅ̓3”Û5jà监—v1Gg#/=*ªB˜5íŠÞk P)ÏÆmò³’t9Å2)ÔE†°q»ö“•Û);>[÷±¸¶oJŠåhøù×°ï8 …âLÄžZ„”è㊡¢*„±};8öZŠ:F¶Êãɸ†ØS‹”û(PÁ©'w™ SeÈ¿ubýsJˆ l\ѤÛè[·.WÃ[§ãÁßû•Û4jàŽ&=CÇÌ¡\¿ø#Âý!/C .‚]û)¼°‰ˆˆáùØ^X$ˆºu{R·)_Ïunܰ€!ºêIJMC+‡Æå^³06BzæÓÙn tuX¨ªš,°u¡ª® + …⌠¯KóÒP•¤üºPœ¼G±¸¼u0ÌšvE}·Ñ§ßEü¥_qå÷áè03jšz€¨#ñ8î"¬?³¦Ý Éyˆ»çVâ/¿~h7õ´ ¬ô3îþ}ëÖhôù×Pj ùê^Ü:¹yéqhÖWñøJQA ²’éPßm4²“¢±W~†üŒÔsŽ& ñðÚ~<Š>34üükåñÝ ^U!š÷[ S$GíÅÀP”Ÿ‰&=—;¾ëû§ÂؾŠeRh›ØC^(FÄoý—‡m'°;ò3´á¿öû„Ð2°FAV®ü> Ú&öpöÙ S¤ß Âýæ¥ã“/w®î‹Ü‡ÑhüßBײòÒn#.h5"¶ø ÃŒph蘢X&Eø/}ð$5¶Ÿƒ‘}[äg$à~ÈF„mêÏ&¶‰âÆjô‘YHºËæ^°lé qú]Ü ^‡¢‚\hêYð'""†çw¢×È‹‹‰ºu{|©ßÌnßÊYºxÂèz6–üe[X›™"=+«ÜkÉ©ipl`ËâT±ï¥à«×OŽ_ú“V®X\šJ¿Çˆj”"Iw™»ö“•¯© 5p÷ÜJdÄ…ÀÜ©'ÒnŸÅ㸋°k?»ÌU.'2¶GÄoýteê:wÏ­„¾uk¸?¢lý5wꉫ»Æ érê¶ô)ךmÑÜ Ž½–ê¶òAVBr\‡³ÏX:÷X6ïƒÀ%M‘V~¿ rá1嬲ÅÖÈ®- ó3‘î[‰ÊY$É}Çéhä9KùÙ{Áëñ$5ͽעn+Å‹ ëYÓ·N-B«Á¿!#>òB1ºÎƒ‘][åvä2 òRcQR,C¡8Y hÐö?°õ˜¨X¦;êÙàΟ? /=:¦HŒü¹)ÑpòZz.ÕÛ4mÜÁ«=pûÌR´ºùñÊàìüEéØ;ྠÂ6õàKDD•j <& €5E2¹ýÙÈ(ÿvc§d_°$1áa ÏöGÖ»½‡âú8@赸ø÷uôðpcqªNh>êÐhР9ß¹äŠÅ'4¢µ™Á™j,³¦]Ë}­_OÑÕXV˜H¿sž†¾RF ÜñÙ¤3°m;i·Ï¢¤X·QÊà\¦A[E¨|s¢Üë–ÍÊí *my}vT…P"ÿ™s0iÔ±\Wç²ý+)–!ív`¹×-š—ßNê?§ ¦©+ç~å^×6±‡Qw¤ß ¨‹ ·ÿü÷B”]²{-ƒë˜ƒPQBMKu\ÛÄÈß•Ïy›4ìˆÏ&Qw@JôqÔE°n3¸Ü6µ ¬aÔà3¤ß9_ºïgÖŸ )N¬[—ëNDDô1kð±åX$“ËלŒš|õú½:¶ÍŸ;jx]S}žùÄÄ@"-M€{s',?£ÿia õtà7o–òyg c#h¨«³hÁ͸ûÃ.)HÍÈj`%€ÞP܈"ªñDF6å¾Vh”ûZœ§ zÏ+{ÞY’ó°\~–®…T@LSϲü/äÒgšËžm~™çƒó³Û~~;ÚÏí“8=²B1.øV¼qY(ÎTfÒ°,›{ááÈØ2ªB 5ø æN=aåܪB ¨ 5àØ{9¢ƒèÃ3}x&ô¬ZÀ¤Q'Ômå£|~Z’óÅ2é ·Y,“B’“‚¼ÒZ×1´©°œ¶‰=¤yi¼`‰ˆˆáù=ʰ¨H&ÛðG`ÐÜCç/ŽéÛ©]6Cô‡±iöŒr_ûxv„gÇJ—=컌ûx¡ÙÀzC ¸ñDTk<ßRü¼7íYEõà µ¡*Ôxëã“Ë$ÐÔ³@ÝV_øF¨¨ áüÅfضˆÔNãqÜE¤ß9ô;ç²nO@MSu[ùÀ¤a<Š9´Ø@d–v?¿¼mFì€ICÅÏ|u‘áK·)ÔÒåÈÚDDÄð\E<0]&—ÿøG`Ь#BGŒêÝM:m¹®¶ˆWÕ*ÉiéaCæ-~x71ÙÀf# ¸ÑDTcɤâ·úœ–¾¢ÅYú$M9Ât™»çVBË ÔEFqú=eKs™'©±Pá³ÿFYkxe¯½j;"#[HóÒ”=Kú$ B ‘²õ;/=zV- gÕ®éÝÄädÍ,bp¦õ‹M¨Ü”˜r¯IrR*¼öºLu<¼~ Üëùñ¸{n%²“¢`Ú¸3TT…HºPáóIW£RÙ·{gǘ~'¨ÂœÔIW ¢*„icÏWO¡8)7ÊÏ8W$ÉÁÅÕm¼Ú€bÔë‹«=”]©Eë±E /@±LŠŒ{!8·¼9î‡lR.£¢*„¹S¨iê)[’Mx¤¹SèZ8!öôRËå0uèŒüŒÜ>³uxL€–5lÜF!þÒ¯¸ºk lÝÇBUMÉW÷"1b;ŒíÛÁ´qçwvŒE’\Þ6 ; mü/Üi±°ýlÜ+§sjÐn2\Û¿B~VLu€$÷îžý E’8öV2 ·Ï,Q†Ž)š{¯UN“¥ká„VƒC̱ٸºkŒòóeÇ]ÒÛ ß›‡fàŸãó•˨iê¡q—yÊÊÕ4õà6î(bŽÍ)·Mu‘!šõ[õtÊ,N}~„ªPI—|u/ n«Ð³rFæÿ"xÑG£ÂTଢ¢ò®¶è³y£‡« ôì¤'XªV¤Ré½)?­‰8ÞÀYK¡¸QDô¾•t_V5:5HŸ¤A’›mû×ÁúuIrŸ‘õ:†•޾ (g$ X&¶IÃ7ÜëuœœcŽº­¢¹÷HrR ÍKƒŽ™Ã[m§Pœ‰‚ì$¨iê*oTF’“‚‚¬DÔ1²}á3Õe먋 2²yá@le5|öçÊÈ Åx’‹:†¶Êi³ª‚“sÌù÷Qþ;ä}þŒæÿó¨¨,ÕÖ5eˆ¦jš;ø À|Ѭ ÕÆð\S=ž‰á™ˆˆ>\xf·í •—”´Ïy’×aöº_ûîØÓpÉÄ1:Ý=ܪÄÐÜ¡×n "úÀÁ¦zx(æÎܤ\ÆÒÄÎÍ•__ˆúi™Šq¡4ÕÕàѲ9 uuË­72æBþ¾hÑÈ]Z¿ÖþÄÜ‹ÇÙÈ(ªèááKEw¾„‡)ˆŒ‰U.×ʡ쭭^û8#cn!üF dr9 õt1²W7€¸@‚¡áå–µ±4‡‹cå6;»¶Vß…¨¿acaƒrŸ³41§Íñ:7FÊÖÛ¯S;å>¸8:(÷c‘É‹-üuËùmGO¹–””ÔÐ À5~½ª,Á+]ÉåíedŽ™°låýVCF?:þцæ–Éå±p)f®Ý iQ!är9üS¾?Íw-bîÇ#.93VoÀtßuÊ÷Öï=ˆ}ç‘”š†Sapõ\¿ó´'ï”?cÊŠŸ•ë]³kßkíÓî3g1dÞbˆ%HJMƒç¤¯s«4üÆÂwç$¥¦!æ~0¶<¿¾²ââ22ûLüaÕ’úæúË'7ýÌÙIýCîĶc§ÿ0VA¤¥Yé2c¼zÂÚÌ]Ü\ÑwƬž1Eùž[s'Ì:0w£6üq¿ÎýgÂ#ò÷uü¹q5L ô3G ~åþH ‹°Èo~›7SÙÊm¨«‹eþ;pØW1b«µ™©r›ž®m0lÁLòé÷Êuï ¸\x~•©ƒ¼1ÝwÝK»¯]¹ŠÖ^}’Ko ¸86A˜ÿ&èj‹ §-BrjÚ{¹¦‚¯^?9~éOZ¹bqYh(½Öˆˆˆˆˆèã3Ïï–Àš"™Üþld”»±S²‡/X’˜ð0åm`|ÿ>ð;t GƒC!-,BîKZ‹§ ¿ÃÇ^ºL™/{uGЕ¿á»s/2ss‘™›[a*¨…ù í0w£ÄÄ%=ÀÛ0¶o¯}¬‘1· .míMHDô½x´hd_n™gGÛ®lÄl÷æNÐÕUx;åqb±bû.8üZ­á)3 YzC ,ŒëŠDK$ï:4uè?4hМï\rÅâš@ÑÚÌàLDDDDô‘°åùýȰH&—¯955øêõÿzul›?wÔðºo: Weapóì¯ñóî?0yÅÏЉÐÕÝz"E«¯µ™©rÎbçæhÑÐ'.…cP—Î01Їž¶è…!xÏòï°bû.¬ßwêêpulòZÏ'oY8Ó}×Âiàp˜`dïîÖ½ E·n“·<æ¹ý’žÌÜ\Ø[[aH×ÎÔ¥³âÂ`mf ï™ó•Ë÷lëŽùcFTØæ¬C0wïii*?7eÅÏii¢•CcœZ»òµæž61Ї•™i¹×DZš¨¾›{P7ãî_¸¤ 5#«€•z—Þ!""""¢L…%ø ŒÌ cúvj—ý.B4ÕÏ„fwëøBq†¨:*é¾ì«@5ÖÉ9æüû‰ˆ¨ ÿò>Fó‡ÿ‡e`–ºšÚˆQ½»I§ ò1×}AKpUâ»sï ßëÕo{ ïk½o+æ^øÍ›¥üì‡ ðÅþºåü¶£§\KJJnBÑ=û/cbx&bx&"¢êž…¬o•vA&—·{”‘Ùc²•Ë ôM>Tˆ>‰Óáèêæª|MZX¸~'Cæ}þŸ·‡½µ’RÓ”šk3SH ‹Ðsú,X¡C›VÈÍ#êÖráù¯›1˜»ñWèŠDˆÚù›òuq#.Efn.ºº¹BV,Çš]û”x±ß6¸7wBÝÒ®W:•Ufn.vÄE¿õ°·¶R†ð­GO|ðü\h¶ð%€P^¾DDDDD5ÃsõpBV\|âQFfŸ‰?¬ZRßÂ\ù¤ñ¦Ÿ9;©¿Ï:5°ÅŒ¡+¼¾ûÌYtuwÅ¢ñ£*¼wýnÒ3³¸aÕ ×{øB(&ô÷ÂÖ£'s .ŽMköüia!þܰ /ê¦>À³c…Öj‘¦Îo^£ Î —Ëñººg¯ßwàôŠm»eÅŖƸÀË•ˆˆˆˆ¨æá€aÕË‘"™¬Y\Rò¼/æ,|Ðnì”äK×¢ ?ôNØ[×Åو˻Qñ1^ c#dæ>ÁÖc§PÙ€g2¹§Ã"ÐÕÍž®mp"4üéÁ]Åo¯7½êjp°©÷ôNCh8üÄWC¾Ïм§^÷þIËüw:ÈŠ‹gèÈàLDDDDTs±å¹zÚ./.ˆKJ2dþw‹šÙÛ«,Ÿ<ÞÊÉÎö6µ +û.ƒ…±¾ìÕ â F-þ¶–ëÕ ý:µX›™â÷Ås±`ó¬ÙµÃztÅ„þ} ÒÒ è²­«-‚£-ºº»bΆ_•-ØI©ipl`˜¸ÜéYÙ€ý+¾WîÖûBC]ÑàÞÊ¡6ÍžQnŸC¯ÝÀŒŸ7à÷EsÑ¢‘ý;.»ŠäÀsÇg­Ýl))*r€b °#¼‰ˆˆˆˆž©ê’Ø^X$ˆºu{R·)_Ïunܰà]†èžîX=cJÅ‹F ÀÔAÞãÕƒ‚±Øo+â¦(»xwhÝýÖ#ôÚ ¬Ü±'BÃpjíJh¨«áð…PtswU.—++»n ää‰ Æ~‰¤Ô4x͘SnÛgϨÐmûY~‡ŽaÚ Ê®àï!4;X`;/A""""¢ÚƒÝ¶kFˆ^#/.®uëöªS¿y<|Á’Ä„‡)ï}Ã"-M ëÞ?þw"öž¯ð¾‡ssì]¾± ‰¸~7NÙe{ÓþðìÚ¶½} .àl䀣-ÂoÆPtÿ¶06zã}rql·fŽï¬¶ÁW¯uè?$dªï:gIQѯš08Õ>ly®9$ÖÉä[ÎFF͸umZ‡Öι‹'Œ®gciñV+K$Êé¦ÀÔÀêjˆŠ½k3S˜è#37ÇC”Ï'¥¦AZX{k+å”U"-MØ[[ᯛ1ÐPWÃÃÓ‡”ë:¶i…Ÿ¦MÜK~€9üòø1„Øbû¢¹0ÔÕEØõhôÿ¼}¹ítqsÁÊ{ð0=<Ü -,Âú}1q¹/ uuЧ½‡rY c#,õßQîëþËÊ­ÏïÐ1ôlëG;Û·*Þ͸ûÃ.)HÍÈj`%€Þ¥7&ˆˆˆˆˆ¨Sa jÝókkˆ~&4w° ÀRyy1<1<1<3<Ó³ìÌ­£©Ù{Ú ïâ±}{k¨«ÕøƒÎÊ}rsÔâå1Ñ·:ØàGüKŸèÝI¢§ QMõ€Ë@DÄðLµ“ŠŠÊMuµÓûÕÔýLhî à8€Exú‰ˆˆˆˆžžéM8«¨¨|§«-úlÞèáj=;齃)Ÿ>:©TzoÊOk"އ†·pŠîÙq<ÝDDDDD Ï ÏôoxTT–jk‹šVçýLhîà/óDóô1<3<Ó»ÔA(,6Ö×k¸dâînÕbT1™¼øÑÂ_·œßvô”kIIÉM(ºg_ãé$""""bxfx¦÷©‡PUu¹±¾IUÑÏ…æ$(ZšCyúˆˆˆˆˆžžéCê£&.©oa®¿|ÒxÓϜԫÈ~e¯ßwàôŠm»eÅÅP´4_àé"""""bxfx¦i„@Uu¡­•¥ÚGÑφf9€yNðô1<3æºÚ"å›ÉiéaCæ-~x71ÙÀfkd³lDDDDDTUÂ3чd`«šP˜3¡ï”ÓëVF4¬W÷YVCÑRMDDDDDô¶á™¨F±°€´44›³$DDDDDÄðLÄ‹›ˆˆˆˆˆªq¾Pe}‰ˆˆˆˆˆˆž‰ˆˆˆˆˆˆž‰ˆˆˆˆˆˆž‰ˆˆˆˆˆˆž‰ÞZ(FîîóËp*,""""""ªvÞÅhx Kד î+–±aɉˆˆˆˆ˜/Þ[ž©¦Ð°‰e """""†g¢û @O#Þâ³uh³„DDDDDÄðL5ÝüŒwß~–6€ÕžH*ýo8€,%1ìÒªIcÌ>6õ^¸|dÌ-ü°- ønbr.C41ȶer9ž¿ß»‹ÔÔ„73²rÆåäçGñ¬1<3M4ý:µƒP øèû&-,ÂŽ“g°nï"=QH\âƒñâxÖˆˆˆˆˆžžéƒ‡æè{ñ¢ÉûãË^ݪDh~ž¸@‚ÍŽÀïð1™©¡þE†h"""""†g†gzï6~;}‰Ј¥WcoNôö°î] ¡®Vå÷;7O ¿ÃDZåÈñBý£w“§xÄ3Jµ‘†¶qº4ï±1+AT½ µôSdÙ–µí¸ ŒMÒ³§ógQ5§£«Ÿò$÷ƒý cx¦šÃoDŽìÝú÷HK³ÚGfn.ÖìÞ]§e–&Ƈ¢©–*龌—=QuwrŽymý›­äïÄ'¼ˆª¹–õt>äϰ÷žUy: ¾Ÿ×o€gǤï~ÙºÉÁ¦ža˜ÿFÌ:°Zg0ÔÕÅ¢ñ£pÉ“°Cë–ÞzÚÚ võ¬6ÐçÙ&"""""†gz«Ð<ñÇÕôµµëžÿe f ]mQ8>S},? nðÕhÓ¸ñ:uR¢‰ˆˆˆˆèM±Ûv-µ{Åâ¶§‚/ýz:,¡O‡¶˜äÓ¦5?O&ìÒªIcÌ>6õX˜çDÆÜÂÛŠï&&ç2DÃ31<3<Ã3Ãs-ñ—ßÚº{‚B¶ ñt°­¯2cÈ@8ÚÙ²0¯v#+wì‘'vñÒ¬û‰¦ €~ÚA(°8‰´°;NžÁº½ŠôtD!q‰Æˆceˆá™ˆžž‰ˆá™>bh޾/š<°?¾ìÕ¡¹ H°ùÀø>&35Ô¿ÈM ÏDÄðÌðLD Ïômüvú„¡K¯ÆÞ6œèí…aÝ»@C]…©¢róÄð;|[Ž/41Ð?z71y &bx&"†g†g"†çžUy:«fhîááž1oã–M6õ /ú­Ç¯ž ÎUœ®¶3†Dè– êZ·ôii&5¬W÷æ¬QõÆð\…|?¯ßÏŽIßý²u“ƒM=Ã0ÿ˜1t DZš,N5b¨«‹EãGá’ÿ&a‡Ö-½õ´µìêYm Ïê1<Ó¿ Í\}@_[»îù_Ö`ÆÐÐÕ±8Õ˜©>…?7øj´iÜx‚N:© ÑDDDDDÕŸyþˆv¯XÜöTð¥_O‡E8ôéГ|úÁÔ€¹ª¦Jx˜‚5»÷ãÌ_—ÅFºº«ï=x°€„•¡÷ˆÏ<Õ|晈ª3Fï$4 wðtmƒ¯†„µ™) SKÄ&$âÇí%a7¢%¦ú¾ ÑÄðLD Ï ÏD Ï ÏôŒÓëW9:ìôb¨K»–-0u7l,-X˜Z*æ^ìÒªIcÌ>6õXDÆÜÂÛŠï&&ç2DÃó›¹±*@ËÀ ?ÿú…Ë¥Ü8‚ô;çͽ×TécÊKÃýàu°n36®(g"öÔ"˜5í³¦]•Çm`ã ë6ƒ_¸ž¤+»•Qå÷_]àÅ2äB]dÈðÌðüZn^½ŒC{·ãvÌMdg>†¥u}´üÄ ½¼‡ÀÚ¦Á[¯·P*T*…Ž®óT“Q§Žú†FÞËHOœܨØ5ªuuÉ‹qïö?J%°´®˺ï&¯pª*z-ù­­;mð€3–®¸ù¿G\–,€ÿ‚oœ©Ç&8øÓÕ_æ~­onl¼ÊÜÈ0©®™Ù`V†èÕ’¯îEòÕ½ˆ ú…âÌ.w÷ÜOÊe«:é“4$_Ý qæÿòB1’¯îEnJt¹ãÎJˆxéz²"ªÅñþ›› a›z íöY~#ÐkÙºi5†{u‰ƒŠï Këúxœ– ¿µ+àíéŠ žxë@îíéŠÛ17Xäj¢‡»#V/[ixìÛ±5úvl+á!µª&+}‹ŽÎ6îÕ cvGwÇZWƒ×!d ÞOhÞ²å‹Ë<-MŒU~þú¿pqlÂÂÐK¹7wÂÁŸ–ÎFF™/÷ßñ»¹‘¡¯P¨6#95u«Côbuä…b¤Þ:]iKlnJ4òÒã *Ô@±LZåG×Ò®cBÛÄž'÷%²“®"çÁu‚^KÜí°vù4mÞ k·îƒ‘‰™ò½+á!˜:j|5§#n£ŽèÍf; >‹¤„û,r —Ë —+:ÿËkÍqïðGÀ– ð:CFÿêšx˜ô?ØÚ7âEñ¶<¿CñA‡ô猺{äRß„Èè[ÿ·rú$•ý+¾gp¦7ÒÙ¥5ÎmþY°|òxs:Û­ÍLïêéý+CT9ýº- ©g”‡+}ÿQô hè˜B¯®ó ×Q•ôÊ`],“B’“òÞGMSF Ü¡¡ón’”>I{­›’œÈ Åo¼þ’bÙkÕñuëýìþ”óIúw"/]LøjN¹à mÜÚbø¸©x’›ƒðàÊ{2”u奚MGWF"àx0\>ëPkŽ;äì)èèêáÛÅ+ac×–uë¡[Û ß+Ä–çwšývØÔ}ä´ªUÁìQÃÐÙ¥5 CÿJ7tqsî ²_°÷¤HS#^,‘NÊÌÉù“Õ!*Ï©ÂýQ(άðüëÇaÙÜ«\·g@Ñ:æè¤DW†E}ëÖhØùk˜4ìX.tF™…´Ø@”Ë ©g‡.ó9´ IDATpþbs¥ûµs$$9ñÙ¤3åÖ¶¹êXÃuÌAåëùñˆð÷]û)еpÄß{& I·…0wêù¯k“vû,þ9>ùñPQÂÔÁN}~,΋eRÜ üÉW÷(»¿ظ¢iÅгjñÊPslÒb•ØÀÆMº-€¾õÓß…E’Ü>³ þÞy¡*ªB5pG“‹¡cæ \.è§O`ûÙ8È‹¤ˆ݈Bq&T…°pê'¯!P!!ÌqA«±§¾ÃÝs?¡ã7—ù@/¤®¡ @ÑݶS— ï÷0-]Ü`×èiƒ‡\&Ãï~ë°wÛ/HMyhìØ¦ÏA‡ÿëøvòH„]Tþ=›ð?ðò_Óé©úó2ÒRadj §ûá=p;æîܺ‰^ÞCð$7gŽ@FZ*\<: å'nÊåÿ¾Ž‚|1ÜÛwFÜí|2¹»õyá3ÜI ÷õW(§§Â²n=4kùÉ¿zÞûJx®]ù ¡۠͜[Ûrïÿ}99Y™èð=p;æÂ.žƒP @‡ÿëù¯ö1_,Æ…?#)á>êˆDpkßö›Vº¾„{wpóïËJ¥0®$æ‹Å8wªü X3 « á1)á>®] ÇçݼPŸ‡3ÇàINZêQḠ;3þ<Ô”Îõçݼ޸—Ãû’Ÿ/†Ž®BFC†ç÷š·jîØú“Ïä9ãò%õ™#£‹› Cï”gGôëÔNpðüE{ß»ë[YÜÌÈÊ—“ŸÅê)˜;ö@ü¥_+tÝÎNŠB~F<Ì{TÏ×÷OEZl ì;N‡A½Ö(ÈIA\Ðj\Ù> í§‡ Ž‘-ä…bDüÖâŒصŸýz­‘w×÷O…ªPúu_,uÌúÏ)ä¥Ç)»`gÜ AAV ²’þŸ½3Ë)ûãø[=zÒÓžJ«RDš£©‘ÝØÉØ—aì fÐë0Œ¬cmì"&dÉ2–¬õË.2¡ÔHR©Tžöòûã©«GY"Ær߯W/¹÷Ü{Ï9÷ÜÛýœï÷|¿d¥Å 6îŸÃd$GSÑÆŒ”X2’£ÉÍN/“¾¹´å{,ûRÉ~>‰w‰8µœà„;4u‰âCîâæïx~‹/{clßšlywO-#pU[\†îUÁ%M¤Å…a÷Í´Mkñ$þá‹ ^ׯAHµŒÈÏÍ"Ø«3iqaX=[7Ò£ˆ(¸†Û¨chX «tÄ©å”SQźÁ¨Éô‰ ñ#æª/*å¥|ÑÉ}kŒãˆ¾à±}kô*;‹ÈKiòM[–͙ʊ3ˆ¸u“–ºP»ÞWB€/SsËbÁ‘fMÍží›hÒ²~÷$++ïu+3¨sWl¤eûÎtèÚ›ì¬LŽ C×ÞÔttzi=NþíÏäŸRACkÛjÜ Q²hŠç“û³zñlÌ+WaܰïÈHÀêų÷ÛÍÎÊdÂÈþ9€­=éò',›3ׯ-XìµM˜°ðóÙÄÅ 3DGE°hæd yœœÈÒ¹ÓØàû7_8}©TÇÂ~W•H0®dʃû÷ŠÕñÊ… ÆîÉã¤DLÍ-y”Ï¢™“éñýPÆÏXXb›µ´uP“ª“˜W\ä&'2uì0¥m^;ÏW/1uì0TU%ÌýÕCq¼\V/žÍ°1“:f¢RêßU‰[;{"Ão+]»îWnŒxÅó{Íó‡$$?Vݳ+ÝZ4;FäÝ=¨ªª…"ºüÆý‡œ–nÿ+¸Š™É5QD‹ˆ(гr\·‹ŠçؽTг@Ϫ¸¸Š»ySGwl›Œ¶iÚpÃo<©±¡hX´' áÔî¶ÓÚ0²kކ5¡û&¾´NÆö­XÌ£;‚x~~u2SbIŠ Âı#ñaGÑ0°FÃÀšŒ2v ·i4Šj-Æ``ã†ºŽ 7ü~!úâ6*՟ؽ< ?m“1B¹ÂvžYÖ˜Ð}“”¬çEÉJ‹çqô%ª¸ý€uƒáŠkTqE]Û„ð€Å›SÇÅÊÆ¯ÑÉHLˆ£w»FîÂŃŽìÛ‰îý†2lÌDrsóèÑÚ¯eóñ ŠÈÑ+Ì}TÄmúvlÊ‚ßÆ³'àÙ'ÂÜ©?³ï/oºôȘɳÐÉH—˹|öútÅ™œ>~˜5Û÷ .Î~>›™þË6¯]ΠQãž½o>`õâ٬زG°’÷hý5›×.cÁê-B¹…3&°gû&ºôȦ£¥­Cº\ÎÕ‹AB™Ä„8~êßCc6ûÀª ér93ÆÄgãìë“ gLÀÏf,Z-l‹‹¡•su¥¶˜š[RÙ}¿¯w1!ý@UMV, [= ª|-¸Ä “!–uá PNE‚¶‰9™âšS‘7ç §/Ùsâk¶ï§÷ÀØÕtäVhV.¢k gNŸ ” øû½ W:‡ªDB›o{˜ÇÍ+¥º~ø­›¤¥¦ÐöÛî‚È104¦ywÂoÝäqRb±czÁ¦£&UGC&£IËöú;:ê.ÍÛ¸+µ£ywâbc„r¥aÑÌIL;ì…?“Ku¾þ?ŒeÆ¢ÕÌX´+›jèêÿŸ±h5c§Ì_%}‹‹]ðz¢yÉþ]›;þFD¤ld÷Îll߉ªêV§°¨{øŸ ÂH_—ïÚ(¿ôB#"9tÇš¸::¼“ë§>‘ãåwk%WuyF&² 7Ï­;°06úà&²²sª•/qŸ<#“;wŸü˜ŸzvÁÂØèƒ“Rµò roGÏ–Í˯޵·©—ßþŒôuO‡ß‹ „‹O­ÈçˆiíÎJ®ÛÉQÁd¦ÄRÉ¡m‰åk¶ŸÃÕ#¸á÷  p³6¶o‰cGa nÆãhd†U‹«"‘¾VnaÃjM‰¹âK~nòÄH²Òâ©hÛ' á< Wˆçø°c<ÍÏŰjã2ïu“bõT‘H‘j!OŒT|'GpneñèÜŒTÁ‚\R?Ôì0‡~¿?:fµ0¬Ös§n‚+vfÊòs³8ééRìÙò$![= …¨Öµ(.ÔÕµÅA.òÖ¨J$Ôÿº± ø פz-›‡÷ºXXU¡{¿!‚8;¸ªÏ}不+b$Dݽ­ärü* ]€#Ão+mŒ¸†¬äœÃî=ú)ý¿{¿!¸5mIECåçñùàVv5¿Dœ…U®^üy¹¹´ìÐå•õŒ‹a@çâqJÇN™M³6 o™[7CÈÎÊ–Z¥÷Fn.Q·‹ÿ¼U^*U'/÷Ù¤ÙëÖñÊ… 4d²bçS“ªó…S}Ášz+TQÇz_¹•ù8**æTU•%•–¶.ª‰Ò$@ô¿wQ•HÞ(xY[‹¶aß_Þdge*M2ˆˆâùX9a̰v¿Nžu9ì–þð.:ñ…Âë}²tû_ì=u‰ª*Íë×äâ³nèÝ(<·úàѧÇ;Ï)r9ž[}èÞ¢)-]êÏÏKVÒ¹i#A,{nõÁÕÑáƒÏI©©´5ŽàMkJîWŸ¿8LÇFnè|ëPdÔñèÓÁîí$^~š®Û{ ÔPOwß{÷GÅ'XäsBǬÖÜ¿¼‹z½ˆ¹¦H÷¤mRò{ÐØ¾MÆ] îŸÃć%én ዉ8µœ:=V ÖçüœÌ7®S%‡vD_ð&ùßó¤ÆÞ@E"E¯r}ž$„wóÉÑ$Ü>ºŽI‰®åoK9•Wÿ™ÏË–£ª&ÃÜ©û ËhèY¼pŸE½^Ù5ça¨¿¢£‚I‰¹ÆÝ3+ù²ßV l®R-×^CRAÇ"ïŽmëW¢¥­SLèêàÞ£/.šÑökü÷øÐ½ßAvèÚ»˜0*¤Z/JUc3š´lÇŸMèéð…S}O%ðäQ†™ôZç(imöëPØ£J¦¯,+•ª—è~®_D°ŠÞà³\¿|¾Äz––´ÔǯulZj ºz%îÓÓ7Ús¯`Âäý»4d2:tíÍžíŠ{íÜ  W.á¿Û‡.}¾‘xŽ‹!/ïÅ鳌+™Š¿Dñüߊfÿ³Á³¦¬\§ß¿C–xŒ,ªÿ5©Oä FªVž¬ì¶>†GŸîïµFzzøÎÿ#==‚BB9så›6ú ï«<#“è¸øîOHzLÇFnï½?ßmM}ºÓ¿Ckµ¥Û}»Š8Cü­£Û·~'ýQ˜æ©hÝŸæç’-OB¿@¬Wг -.Œ*n˹¢gË“(§ªJyõèe¥Å£R^Jå¯úSù«þäçfñ d/!¾?r÷Ì* lÜ(¯®CFr4¶MFôYiñH¤²WºÁ‹ˆ¼ Þ® =]NËö…@VÏ []=2äráÿÍZwÄ®¦c1ñ–—›[¢¥øe$&Äq1è õ¾r#àÈüwû «_‘ ¿{Ò½ß2mï£Å·Žà2¬¡ Àý#_º.»pBaºçêWŠC€?Œå»!?–Iµ´uEDk^ò9©«gÀÅ 3dge»—‘á·Wn3Ë¡¯,8Kr/k²³2 ÇS¸öΣÏÖþ9÷Ê„å«2k¦­:Q·Ï N^º"ü¿vÏþœ½Rb›b%Òå—_qèÖê]ú0jþ²²s„öŸãIõ.}¨Þ¥Cf-@ž¡˜…t÷˜$\;ö‘òËó÷?7qàl ^~û>Ç€Ý'NãÜo(µ{ö§nŸAì>qZ(ïî1‰ikÖcÝ¡£æ/ù Ɔ¾¶6Ó‡àÜúU’ÆuëtÑÑÔŒ²±4[è~Äåÿ€ÚÀ ó‹þ–ÀñMöùRè¢ýÿT²åI˜äzž´¸0ŽÍ²'âä³g·œŠcûV”¯ #¬¿5­åNNf Ñ·)qjùkå)V‘H1¬Ö„ø°£<¾w‰ŠU› ih‹ºŽ QçÖÔóݬw~šŸËÃþJÛb®î&/[ŽQõ€Âµ *hC±cƒÿü–ã³_¸Ö8áNÇç8òo‘cU$RÌj‹ªšLèG£ê-ÈÉL!6d¯Òñ9™)œý£9'=]JËYU"¼ÈkS¸Vxñ¬)J®Â…Ù¿‹Ä„8AXº6V<¾Þë‹•0²?Mj[•èšü2‚Ïž$-5…Ÿ§Í寣Áø†â}àT™ ç¼Ü\ŽìóÅÂªŠ üêÔCU"a·ÏÆÛ_ZlíìÑÉðß³£LÎP»ÞW¨J$øn]÷ÒsÞ£#ûw)mŠ¸Í­›!87Px·tø¼ÅæÝ[4åÄš¥èk˜.dÛ¢/‡FD²ëÄ)N^ºúÂÜÒSVzqàL Ý[4¥¾C –lû‹è¸xRž(fW÷:‹ÇâÔ´±fj‡ï ¸x…Yë‘GtûV°ÖnØw÷Fn8V³%7/è¸x’RR1ÒÓ¥¾C Sß¡õk>Ë‘xív8®ŽL6y›¼™¼r-ß6mˆDU•è¸x6ûaxwÆ÷ëͼMÞôš<ƒ^­Z0yÀwÌZ¿…Yë·phÙ‚bmZºý/ì¬,ñÿ;òŒLÚϱóiÛÀ…1‹–“›—ǵmйŸ—¬`ÂòÕ,ÿe4~ž³qî7´D·í_õ#)%sc#<útçRØmÆ/_Ŧé“qut 0ä½§ÌÀÜØú5kû(‘¬œŽ®XüÒÉ‹ÿ#=]¦À ÷vÒE[w ‹”<À¨¢Þúˆ{1ÇÙã™ ô.«SÀ£çÊÌÌÑ@˜øFû|Ñ6q@ÃÀš!~‚wIhWG×¢.QAëQÓ4°Zcòs³¸¼™¬´x*5€Ê_õçþ¥„î›DJÌ5ô*;“~š‡A¶^KÐÛ·æêÎTy¶æ·¢MCî_Þªš ½Êï&Í¡ŠDJÈî±äfËÑ1s$)2ˆ[ÏE˸º¼Ë¢^/îoâöѹäf¦PÉ¡¹™©Ü=³Š´¸0ªµ˜ðBËsE74 m‰8µ‰T†¾µ 9©DŸßL^¶\p}·rLôEoBv%#%ÃjÉz’Àc ÉJ‹Ç±Ë²×r1/Šºv%¢/z“‘|›F£„Ô[""Ï3tÌDÎ<ŠÏÆ5œ;y”&-ÛckWƒ´Ô‚Ïpúøa :ZEß­iKœ4Á· øT›N ´]Þë  Ýû 7<[UQxlaZ*5™>®Ãü¹±w¼RKµŒøâÛEo”jJǼ6mò(ü4ÉQÁÛ·záúv-m6ï=ÁšÅsØ÷×V6¯Yª$;tíÍ?ÿªäнÈk; gŒgß_Þ‚ˆV“ªÓwèOü8þ7¡œk£æØÕtäôñÜ>~˜Î½–˜2ÈÎÞ+›j$&Ä(\ˆôcõâÙôÿa,?N˜þFí[0}¼`­µwtbÙ†¿Šµ3y&FÆìظFHŤ&U§a³VotÍA£Æ!•JY¿r?~ÿì}«!“1nÚü7:ç?ÿŠ–¶ÞëV uT•H”ꨥ­ƒ×ŽƒÌš4šE3' Û4aòì%JÑ´gx®âÇþÝXðÛx¡Ìêm[èÛ±©Òu ójeÃÊEÂï¥ÏÖ6Õ¨ó¥ 7C. ¹ÓRSˆŽòcÃÊEtêÙ©óþÌrŸ»h>p&¨z çzŒíÓýƒ¬\” ËW³ÙÿÚš2td2róòˆ}”ˆDU•àMk0©hÀΣŒö\†GŸxôéŽi«NÔ¯Y?OÅK!0ä]~ùUØïÜo(YÙÙ\ÝþÌíÎÝcçCÿáÁá=Âù–xü(ÿŠŽ‹Ç¹ßPº·hÊbQ%–1mÕ WG|çÿ®xi{.gÇÑoZƒ…±Q±ý¦­:aal$X…û (ÑJ\ÛïÔY¢ÄR¿f ŽT­<Îý†R¿fbÑÐWNô +;ç~CypxO‰ý;Æs¹`y.ú{!ž[wp?.žÅ£pî7>=>ªTeaQ÷˜·Éûi`ÈL#]=ÏLDKPXŸkí@¸^ Ž¿@±.º( wáõ}` àY¤Œ&°ÅziÍçÄú®üU÷´Íl1nÜ«ÈÉL!=1 ‰™µ’}Ñzܧù¹šbŽYí.ÔêöáåeËy’Žº¶I‰Q³‹–“'F¢"QGf`U*kp¶<‰ŒÇѨªÉ^zla—W×~¡g@i(\»þ:ÑÏ?VNªô¹~³=-̽[Ö<¸Ñÿ¢¥­ƒµmµ×A c,+“{)Ÿ,­ª¼°lbBjRõƒZ8}ÞëVà}àöŽNÂö´Ôz·kH\ì‚ï$”ªÓ<†±ï/o®ÜKãÁý{èê¼V®ßÇI‰¤§ËËlla0+©TZ̪û¦¼NÓRSHKMAK[ç¥A¸âbcJÕK½NýMùsùV,˜Á²¾J©À²³2Ô½ ×/_àôûo8ìc¤ ôûz‡=}—×úì,χÿXTsωSëÇÎ_Z¿aZX2+S“¢îYÙ9ø:‹¬‚:Už}pÈ*¨óÂÀaúÚÚ„ÞÒHݼ¥´ßHO—Ka·‰O~Œ‘ž.YÙ9„ý{ïƒu[ˆzË÷ÚðK¿^DÇÅ3aùjfoØÂòq£˜õÃ`jÚX B;ôn$Fzº/ ö<Úš2ný«˜á~\<Ðú÷ÒRÝÊ’ Ó&– ˆ¬°p«ÏäÇOžŒÔÒPŸ·…{ô‡ÌóîÛ5€i€еÎÏ çÀŸÀÅ‚ýO òB "0± Übà{`.p…õyà|Y ¤E>aÊ«ë cV«Ä}wOÿAä¹µ4sMÃgéÔ ×@ëZÖý(Ú¨ª&{aŸ/÷¦Ö[5™þk Ø—õ÷›^WD¤´”&jµšT[;ûW–{•h¼u3U‰;{åd2òrsÑ{KaW!¬«oP¦B²,r'¿I_%šßeý^z¯C1{j×ûJù«*!/7 ™ 1HâÇÈg#ž Esß_gÔwªa‡÷Ì©T·ú¸"Òí=u–Ô'rzµj!¸6Ã3+ð¶ÃGù©gq7Å^­›óÇŽÝ´3»Ê– ~n .…ݦ÷”´kàÊ™+×H}"gêàï_»nêé»v=ºZy:4jðNûb©/2uuŒþ“Šèkk#« Ž¬‚:íÜ\™¿yËÇF£‚:¿ÿ¹‘kw"”ÖN‡FDbgeùÒ\ÝÝš7ÁýçI†ÜÖ<û:ÃŽ9Ó?ú硦5¦M,w>ôݹ½§¥gNÿHDtQ÷m/ KÈÝñ\9Í‘|pã™u½0rÒÏÀ ªà‡QŽä lj‰â6Ê E IDATùóÆÌ©QAë¹°±'õz#Õ2"%æÑ¼Ñ4´}#wc‘Ïׯ-¸t†ÞíÑä›v˜ZXò úÇú÷ð³–þ)vÒ'BÃæ­8vп¡ywL-,y”OÀ‘ýÜ ¹Ìä9KÅ´R¢xþ0ùŸ×2sŸ€3ë†Íšß¢ºuårÞ3§ É3W®aalDÏVÊkX,ŒhçæÊµÛá\»¬‚:ÆFèh*f´~éÛ‹¼¼|Ž_ U.gưŒ_ö,AÏ–ÍÉÍËc•ï^æmòÆHO—©ƒ¿gXgE”ÚÂó8.QUÅÂØ}…uú+Gl-Ì ¹¡ž.5ÀÂØÃ"ëÇõu´±06ëóû-Œ”òUýýyfþ0˜Qó—àÐ]±^ÚÕÑ_ ÄþÜQC™¼Â‹úß+ܾkUµeýÔ Â5Z8×ÃýçIxÏœªܬ°Ž…ýVÓÆšy£†3Æs9)r9:2ž£G ǘT4ø ¢°¿ õkÖ`÷‚™*!7tnñY”™3Q")ïq?.nÛ\íY€;ϬÍÃK(Ó …+÷Š»¥o,8¶#Š5ÒQ@sÀ…›vŠ cuÄ?"Ú&|5há'—yf9™)hXcå2Ûfbz%‘צÿð1˜š[rdŸ/‡÷ù’•‰–Ž._8}ÉÌ%^ÅRb½V¶v¯L=%òþiߥ7ºúñßíñƒ~¤ËŸ !ÓÄÞ±?ŽŸ.Þ³˜OvýL¡hö 8ÓÂÔ°b¹_úõ*&”>VìÜMRjßµù+SvŸ8ÍÈù‹™1l ƒÜÛ‰OˆÀ±ó—˜³~K^rZZÂ.¢ ]²gRrîçñ(ܰQ<ø—…köÀ(Çöð,Wpðæã·:‹kžED>Ä5Ï"""3âšç˜È€=º^[v­ê?˳«ž¶–êÂ1#„hÉŸ+™Ù9¬òõc×ñ“X™špíN8² ê´mà">Í"J4¯_—æõëª :_iþfïMÆFÓå™Y#’RRþþÀªšûÜ¿ÏSèp…%¹$ …ñIÀEp±æ@+nÝ?£ˆâ½F"""""""""ŸŒx.Ímúª¢:qÀw/LÝô¹áѧ;µªÙrƒ¤”TZ8×£m——ºE‹|Þ´t©OK—ú’Glyï8(S—F~ "úEæz> ¬{nŸfÁO¡I¶bÁ¿ëŠ”mø¡pûųˆˆˆˆˆˆˆˆÈÇï°A}ËŽ³ öŸ ’ž™©ösŸJy†EDDގܼŒ"…Õïåë¡Èû\»@ ‹ˆ¼7ž$„âûÉQÁe~‡ ñý‰' áJÛ ó$þâûq7´í|…m,L7VR?Dœúƒ°C3ÄA)òŸ“.—³púÒår¥íi©)Š|ÕE~>ĺèuù¤ÅóÓ€Éâ±#8nÙ£BÑ|Úk9ÝZ4麗È;уÜÛqqËŸªß·oã¤&U ²µ4;Ø~ UþźåÚÀ1–äßP¸c·æ™5º?à[ ª/üŒ–ð,´ˆÈ{!+-žû—w Oú·ÌÏ{ƒû—w•ö,ßýµ# ;ôÌy#/[ÎýË;H½ñѶóU¶±¨pxã§<•ã€<ºs‚ØûÅA)òŸ’•ÉȾ8¼Ï—Ä„8¥}ÛÖ­¤­kM¥Ÿã‡ü>ø:Šˆ|’â¹P477öñœ [g4®ç$+Í/ËÕ+ò y†"cOt\<úøÏëó§ß¡©OäxnÝÁ‘ ó/,Yêkì< t\VvŽ8Þ©Zy¹·#pýªòº5ÕÖ”ýóˆèM(\r^•tÛ0j_z@Wž­w¦à÷®(ܳë_”ÇóZD¤T˜;uÇyÐn´MŸ}¼Æ\õýüÞaZF8ÚM•F£„mñaGÉÉL‰ÈÇ‚é¹rÅ^Û±°ª¢´¯}×Þxí8ˆ×Žƒo”æê}àÚ¨¹PGׯ-Ä*"Šç÷ÁÊ c†µûurÜüÍÛg4®ç$ Þ´–AîíDÑ\ &,_ÿÙ A<{íùïgÓ½öìê‘"—ã¹Õ‡Ã%»ð8HTlé×n\¼,÷§ßVïÚ+†2BVA>Ý9¿q¤cC·¦ºZš¡U-ÍÿB±ÞøC"E±‹Àã—”{ŒÂûÅsCväeËÉL‰}e¹Œähžæ¿zŽái~.ÉÑŶççf½Öu²åIäeË_Y®¨Uµ(9™)/ÜW”Ì”ØW^'[žôZçzÝkæd¦¼áVAσ*®”W×yíc^tßJsìëÜ·’ÆUYŽÓ¢cCE"Å Š+š†¥›ïËJ‹­¶äd¦s/7¢@) çÏÄwë:†™ÄN_ÛojnI=7깸¡¥­óA¶ÁÀÐX¨cEC#ñ¦Š|ô|ÐѶWN3Ìÿlð¬)+×é÷ïІ%£UPïÚƒSu»¶þ~ž³ßè¸U=„ßC#"17_Üe¶¦ >Ýéß¡µÚÒí¾]$ÍœŒ¡1}‡Œ*“óEGÝå̉䥤`e[&ß´EMªø®NKMáäß01Sòç9~Pa|hÖ¦ã³wgn.§sóÚe4d2\5ÇÖÎþƒè»t¹œã‡ü¨]ÏSsK¡žÆ&f´éÔMhwQ®_¾ÀÅà³äåæâèô%õ¿n\â¹Ü¿ÇÉ¿”ØEûKßЈ:_ºp+4„ÀÓÇ‘¨ªÒ¦Sw ÅÁ-Šç²Åû÷)ßú>·ô·5Ì¿kÛ ÏÑ? ­)ïÖòûŸ›¸v‹°¨{¤ÊåØW±"+;›Qó—°÷ÔY¤jåݳ+#º}«øPH~̨ùKˆ$7?÷F ˜ùÃà-ýòŒL¦­YÏÞSggdRӯ𹣆Q·z5róò˜²Ò‹]'N!ÏÈD[SÆðÎîüÔ³K©Ûàî1‰ÁÚÓ¶ î“èØØ?vì"öQ"nuj±jâXôµµ‹7|Ž'íÜ\8p6UUU£ï³j¢–¯æÀ…5ÞÚ´‹=~ÄÖÂL0oˆ¾¶6Ó‡`D·o%+vîîŸô¸}E} ÷b&òr‹¯ÈÛóØÌâYš®Ò çˆ3œßГ z8¸Ï§‚ž1—v°˜§ù¹ØµœLVZ<çV¶$'#…*n? kY—´‡aÜ=µœ3Ë›ã6ê˜  3’£ ?±Imì¾™@9 á‹ Ý7‰˜«»°o÷;9©„,æÚŽ4pU59)d$GsaC/Œí[Q³ÃÒ“£¹}t.ÿ[Ó‘£ŽQAÏB°nÞ:2“r*ª˜ÕîBvzåÕuˆ¾¸ë»Ç¢cV‹:=Ö *•ñàŠ/ÿœN¶< »–“¸é?•û—v`ÓhzVõÉ‘'°˜ËÛá:Ü]‹º$Ü Ä÷G «5¥Fëi”S•ðàŠ/wϬÄVlÈ^®ø EÛÄÇ.ËP“é{Í[Gf’ñ8‡ŽóEÀ¬ÿy}‹D*£f‡9¨k›pïüfB÷Mzé=R‘HQ×1åáõ8tœ'Ùø°£d$Góðæ¡bâ9/[޶IM¡L^Nš†¶Tm6ŽßÑ6uÀ¢^o´Mž¹sGž[Kª·š‚ŠDʽàMÜ=³‰º6¶MF¿°~ñ·ŽqyÛ tÌjáØeR-CR„°˜K[¾§É¸ ¨ë˜”xìŸaÄÝ<„¹Sw*}Ñ^W¹Ùr%;\Üôê:&Ø·û knŸ òÜZÇ\ÃyÀNT$Rr³ÓÉHŽæúÔ4 е¨KSaÌdËï×ÁDz‘LÕfãéW®••Ï•íC±r@ê¤Ä\åß õ\Üü=? ¯sÉ»?ºuùâÛEб°˜Ë[¿''3cûÖTvÈ£Û'xâÇ­#³pì²ômžùz(â:4ĤOë—/p+4„㦖(ôJ˶õ+Y4s2ºzT42&|ùMŒ+™²bˬlª¡¡!cÅ‚ßÉÍÍåHpª‰’èþyXºô(ˆçÄ„8†õê@dÄmììypÿ_ÍœLÿÆòã„éÿyÿ=NNdêØa 3‰€¿p+4]}'%ò×ÖulØuDè×¼Ü\¦ý<ÿÝ>XÙT#//— fPÏÅ¥ëÿBCöìÛ±i- ¦WêÇŠ†Æ¬Þ¶+›jE&>&QÏÅ SÇðZ6CcâðZ6ŸÃ˜š[Šƒü#åƒrÛöþ}Ê·][4‰>oñ.]MMók–âѧ»(œß’_õ£nu;¦þžAîíìZË{þ¾l˜6‘Yë·”š @¿i³°µ0ãêöõœß¸†ðè–n/y]Ü´5ëÙvø(›6bưÄ&$2pú²²sØ}â4›ýб‘K<~ÄHO—y›¼‰O.½ŽŠ}”(¬ÙŽ}”ˆÿ™@V/%Ìw+ ÉÉlØw¨Äã’#ÏȤmÚ5pe°{{VMôàØùK†Ü xÓnìÜ„S ;VìÜ-–2ÀHO—éCð÷ Oi=;»aZq6–f«]±wÞ:("†_îÃQX£KEØá™HÔd¸ Ù‹eý¾VmBí«1¨âJä¹µäe˹s“¬´xœz¯£Z‹ñÙ5ǦÑHœï"?7‹Ðý“•ΙŸŸ‹ë0¬\Sù«þØ·ý§ù¹äÈùjÐ.,ë÷ŦÑHª¸ ''3…Ç÷¯)oX­ Ž]–b`ã†E½^Ôí³œÌ"Nÿ¡Tîi~.n?¤V·?øòûmäeË ;8-ãê|5x7&Ž1²kNí«1ut'âÔrÁ’v}«úTk1êM0­Ý§>Ñ6q -î€}Ú©—Æö­„sU´m(ˆ°üÜ,núÿІ5.C÷bîÔ #»æÔêö–Îý¸¼I°€ß>:—üÜ,êØIå¯úclߊ/¿ßFEÛ†¯¼OÆö­ÉÉL,™‰á§‘j‘‘-¸‡Îásèi©)Ìš¤˜ S•HèÔ£‰ qž>®tü~_o:té-l7ì;’“ñ9tï§8v1œßeÃÊEBÝ?¼–ÏGCC†`(W£1n*7C.³cÓZ¡Ì†U‹ñßíÃÜÙp‰}§¯1wÅF.aåÂߟMð]bÁôñtí3#ÁaB?fee2adÿb×>vÐÝÛ7±bËŽ] gÅ–=¤¥¦(][DÏoÅàY ½Î\1>ºbÓ‡(Ñ’(Rv§gK…û\ƒÚŠ áÑ1„GÇpív8ßµiIì£DRär:7kÄÞSgJ<ÏÞSg°25aî¨a roÇúiX;åTUUèÖ¢ a¾[™4 ¦†˜T¬Xpûo]ÿþÚ ­)C[SFsçzÜ‹/ÕñzÚZÄ>J‘M:€Å£ÄQ†X±Øc›gLŽº÷ ®W°{*þ¼“ŸB²`%Š<ׯµ¶”˜kÛ·*æNêØy) :)ˆ' ëbî·Ú&TqåQøi¥u¡U\•Χ¦i(À¢‚®‚^ɳðÖnË -ãêćý­´½¢MC¥µ¼ÂÏ“™‚Å—½7^al~©øL¸uT!$5H¾w‰È³«á©ihKƒQǰ¨×« Œ¢Þ×w{(Ei®?`§`ALŒ $+-‹zůY(T ExÂíô­ê îç…Tvðjñ\£•pPXøŸ$„cå:D±ýŽb{RÔyò²åÛ·.ý߈ê-”ÚP^]MC[²Ó“^zœË½4ö*¶®ZRðÿ¼Ü¬{ê¯hÿWý‹Ýï¢b65ö鉑˜Öé\lœZ=‰”ØÊ1M¾h÷JWó~$I¤Û·R®“e]á™Qáí•þ_xo‹ºþTÐ1yíuÚ…¾pEÆõçžûÏáÝöÙq3ä2ZÚ:JÖÌ7eóše3âç_…m¶vötèÚ‡‹Ag„ôQí»*ÞûvnU:Þ·¶vöºëë—/påBFŒÜ´U%FŸŽªD‘}N B[;{þؼG°ôö>-mÎ|&ð½×­À¹AZ¶¶l¦eûÎ87h‚ÿaÛ¶u+‘J¥Œ™êé2y@_¾mÚPeDrjÚõ3æ„ßø§9°Edì(±gÞ OQ¸nçP>»$¿®h(´¢Uг(¶¯è¶¬´øŠ1m…Ÿ&[žD…ᥦ¡ÿBQò:u%.DfhËÃç’ì¹àOéIŠuÉዉ<§<Ë_8¡PØæšígqqs_þ98NGÓÐÃjM1sꆶ‰V_&îæa„øñ Äòê:VkB%‡vÛ·¢œŠ„¬´"Ï®äÞùM%^3=1RJVA·x_k½:6…ºŽ Ú&$Ü j³Ÿyq†r*,¿#*p-Iw±¬ß—„[ÇP‘H1¬VúTŽêÚÅ]«%RÙ+Å3@vz÷ÎoFž޼ÀBûª@[ò‚uäÏO&€Â2^8a‘™úð…åT$R¤ZFd¦}êž‘•]{ÎFïßVøú}=e`ßòÝ[4Õ#k¿td2²²sØ4}²œ-)5•è‡%[veÔ ¾On^UU¶9Fxt ƒÜÛ1oÓ6CnphÙjU³eÚšõ„GÇ”(Üß7ñÉ©VÙ?ÏÙÈ32ÙrðKþÅs••1jÁÒàgƒ¢bå„‹=óNÑã=®+/§òþÞÇ%‰ÿ§ùy¯<./Ga­3²kQâ„@¡ØE ®Æ¿œ'îæÝ>Á£ˆÓDž[Kä¹µ8¸ÏDz~_Ê«ëðõˆÃ$Eñðæ!ÃO Bº¢mCêØI~®bi‰aÕ¦hX½ðš¯ë ð2Œí[°„œÌÃO£cV‹òê:T´i(¸?¼yÃjM_{¢¢,(\·­"‘¢k^ ]˺X:÷CU"åêίVJù¹/µ?ÍË}á¸(Ü^ýû¡ê)À¿à§ŠâëïÓ$;«ì’>¤Ëå<¸Õ‹Š_55·DZdMõ·=úxò(Göï¢Kïì÷õFMªN›NÝ…2i)ЍñûþòFúœÔÐ}𱊶÷Q¼"wöÅ 3%Z„ý#-˜ÐˆCUUòÂ~ÔÒyõdGIQÓEDñ\\}úô©{JÚ“–®š5sÝf{QD¿=Ñqñ¤>yùìMkAèÎúa0c<—£¡®®¹ºŽÜØvø(?Ì]DÍ*Öü±sÚ2¿ôíE^~>A×Cù7ö!»ŽŸRˆ«ììÿ¤ýÚš2BïFŸü˜ÿ…Ü`Öú-øyÎÆ¤¢Ö¦&èÈĵõe$š›¢X‡×EÚ'‘wÏ[ ç AœJ²,&Þ $1⌠"å %Ï…ÍÏ%+-¾Ô)¨>A-ò bdbÆõËçËä\ZÚ:ØÚÙ³~×߯,Ûø›¶èêpp·ºôâØA?š´l§d×ÕWxsÌX´ZpIþ¨¾‡£î nÜ…¹³;õüž1“g¾ô8SsK´´uñ>pJ Ÿ1zžç³yOŸ6JI{Òuâò5!õûyxðl\¼m¥§s³Fxùíg©/R55L**»±Y áUÆO­^ý©Õ«?R55Ž.Ùb0}èzµjAÀÅËÌÛäMõÊ–¬ò RµòüÒ·¶fÌðÚÈ­>ôïÐ c#îÇ)\M*õ¨ªbal„¾NÉÝ& K¸IE%뵎¦ì…Çêé ǵt©ÏånñÃO:4j@+WgIížý™·É›µS~Ê›—ÿpò*¯mUÜ{ràlP¡hî$ ç k4 ¬…èÌEù÷ë‰8µ\miqaJiˆ@±îöQøit-ê–*ð«ˆyNt=޾DZ\FÕ¿yéq6nQ¢7³D†,áļ:D_ÜFFr4GgØvhF±ã+èY_`ÁþŸ×·œ]Þ\©o4 ¬ö§y¹èU®ŠDÊýK;Š®S òœ'æÕáßÿmP¼›ª5!)ê|± S1¯™Â{Ϭê:&Dz‘•OŪ ×ìŠÂ>ìào”S‘ë£ßÙò$òs³Ð5«¥$œbë‹}”ÖVd{ø7h}±‰›¢cMÛ¤&R-#b®ú§÷/ï$/[Žaµ¦â-òÑckgOZj Q·ßú\õ\Ü ¹B\lÌ+˪J$tèÚ‡+‚ð^¿Št¹œ.½•c1Ô®÷G”y»âhå\¶®5߉û÷Å 3ÄÅÆàÖ\ñî661ÃØÄŒ€#û_iíwtªÏ­›!„ߺ)ÐÏÉGRÏ“¹yy &&µ6{ᜊzº†3‡ÒjÓÀE4¾&=[6„Añ¼ÉÁ›Ö¿[™š°cÎo¯u^YuŽþ…£(þâ·0ã´—rD\>ÝK¬ƒIE¥:¶G¿ô85™>6FqçøBίï†m“1”×Ð#>ì§–£e\³Ú Bµ&æª/ê:&Bp§Ø½¤ÆÞ Š›âÝfå2€«;GpyÛ`¬¾Œº¶ )1!Dž]I= tÌk£"‘bÛd ·ÎåÂÆžX. [ú IDAT»ý€ºv%nŸäöѹhÚ Ȫµ˜@Âí.lìIõ–SÚ²—{Á›_»oŒªýàM¨H¤è±R×1AÓЖ' áèY9±Å>”ÕdÄß:Êã 1¶oõVê:&HµŒˆ ;JlÈ^t-œÈNO"òÌ*!÷qNzb‰Çj›8`ñeo¢/x“ž„Qõd$G´U5™ ”Ë©H¨ÑzWwŽà^ßbÛd V<ºÀ­¿çRAÏk·a¥®»ªTñ9q}z•‘ÿН7góš¥;¸—A£Æ•X&ðÔ1nÇ…îÇ…ëv «ðwC~äôñà èü ÃÆNÂÄLauMIN"=ý í‹DÑèÔ£/›×,eõ¢ÙXÙT+–÷Ù®¦# ›µÂwë:òòriÞÆ55)ùùyD†ßƵQsÁ¢[´ŽÑQw_XÇBDßDþŽMk_i ~Ág°«éˆ¦–6Qwï°bÁ ¬lªÑ½ïgß‘?þ¬‰?1¨{ú ù =Å{36æÆ&fB¾çï‡áð>_†õêÀ°±“°ªRõ¥ý("ŠçÿÜü|ÿ‡‰I‡Ï]4³²I%Ý9#†}]ÛAM¼•""ïÇìÜuxþÆm5sóóMAÀI±[>~*9´£v·„™I𺮀"XQe—ؤø© gËн„îŸÌõÝc•Äcç¥J‘‘Ë‚m¦qçØBn PG×ó•nÛU›ýŒD*#âÔr¡= ˆôíÐqž°¸v·?¸æûwϬ,ì…í¶k©È»lZ»3)±Ü=µœ ·Oç2¨âJÍŽó…sÙ6D*#<`17õ)"t[ðE'O¡œ¦¡-ÎwâûW|†ŠàTµº,}­µÁ&í¸¼ ƒ*_+­k6°mÈ“„pLÚ½òU܆°„;Ç¢"QÇÔñÍÓâ”S‘àÔÓ‹«ÚTNE‚±}+¾q„³Ë›‘x7°˜K{!çQAׂû—wvMC[¾pŸOôEo’ï=³>›LzÜôÿ•K[¿®cT½5ÛÏ~£ s§î<¼q€è Þ$G‹âYä?§þ×±²©†ÏÆ5ô2ªÄ\ÏV.âbr6”©c“Gõ\ÜaZçK–mø‹es§ ûAaenÛ©{1ÑW(˜/¡C·>%ÖoÎY¼,ú°4åÞªj2!µXYQÚ ]‰ág¸¼mŽ]–)Y}ÓâÂH ÅÔÑý½ô]YN ˆˆ¼-¿iKó6î¬^<篗I¤f]}!àW™¼?$’2á…ÂõêÅÿ±~Å"¬lªÑ¡K¯²ù{&“)Yš_ÆëìwÑ"ŸÂ4I.°);'ÏûÒ?·F´õóäÚvU3D-"R¦¢¹60Ø$ö‹ˆˆHYc`ë†TˈÐ}I‹½–‰Oâ¸Ù‰›&£ÅNù,™î¹š(÷¦ŒÜ“ »þÖŠ èü âiÕ¡3?N˜^¢«ºˆˆ(žËVD/ÍËÏ_séŸ[CÛþ4nb#§ÚY3† ´´25ï´ˆH)ž¥S—¯:kA…T¹¼P4{øüÉoËú]£§oP&¢Y*•RÏÅ S Kq‰”)ŸòúMÀC¢ª:ºqÝÚ©Ÿ¢ˆÞy4€šU¬¨iór·µÐˆHBïFÑ­…"•Iê9Úš2áæÆ†¸::”êïLµåå‘•#¤—zýQxP¤ÈzYÙ9ì  €Õ ÎDDDDD ¥ah¸s³e²uû|ý\œ9?¼{ÛV).ÃU234(Ö,ÿÆoÒ¹estnÙó<ù/ ¼ë:¾”[C¿Èû¼kø Á­G¡¸¶ý_è•¡Oû6HJMÃöã'1̈šÍ™——˜ÜÀß@qቈˆˆˆˆJYxÎóÀd™\¾xŸ¯ß´Cg/ Ö¥£tR¿>òº07£.ÇOö-йesŒ^¸ßÖ°û#ˆ}žˆokØ`£Ëo°27ñ 8ê€f8cÌÂå€fƒGáàòpuß‚Fµjbx·Ÿ —õî¸ó8 Òì,X[Z`ío“`kýæûEþúw+ ø!42Míjaæ°_0uÕ:ÕïžófCTV2¹K¶íĶc'!ÔÀ®Z,? Ö–­Ü¶1 —cþØ‘h×´1\Ö»Ã' Hq° 40mÈôë ˜ðÂÍ`Ì\·I©é°µ®Œ¤´4Õ6Å'§`úZ7\¹YŽFzzXå<Míj¡›³bÞÖnÎ3±qÖï°ý¦2¦¯uƒßÕm-M¸:ýŠÎ-›ãÛê6ð]·¯#:ZÅ{V´¨ø„€³\cEDµà`0šˆˆˆˆˆ¨¥ð3?09+;»¡›÷aŸº}‡¤¹º{9‡Ï_¬Û{þ7‚qÞýo„ìÝŠõê`ô¢^¶‚¯ŸáŒÎ-›ã߃G…k;þEÈÞ­˜6df»m ¸o{ø¼%˜:°/BönÅ8ÇŒVmÓÂÍÛ¡/áæ®Í¸ïµ[4Ã_î[—/PýßȶÖíÝøäÕûŒîÕMõ>¢²:j÷7»yB`p†wû©Ø†æÖ#Ç{54²ö£ˆ¨(uÌep¦/!þÁ)ýÛ~K›àÚŽ¡,z#Ij,¤éñ…>—-IEjô-Q1”¤ÂoŸKLˆC胻Er»â°rþ,Èe¼«­´*Í3z‡š-“Íwó>ì²íØ]&õë•3¢{m-Íbùú´o‹¼®èMíjáò{ïõúµ¿O‚žH™\ŽÐÈhéëáÁ;voþɾ…*d¶¨W¦F°0QÌ×Ì®bä¡sþèÓ¾-¤YYˆŒ‹G×ÖßcùŽÝ¸ó8¬À@_¿tê€_:u€¶–&"ãâUàìµ034@—Ö- ©]-Õkg û"Å c¡‘Ñ(§£ƒ×Ýï>¼ûOpÒ@[Ká1±Éå…ÞýïÁ£p?p^Kæ©>[q‘œ–~{˜ëÂ;A!÷\PKy!‰è‹¡kÛ‡ Œ†ÆU¿‡Ž>gA 7 ÜØå ­ÐløþϹ÷DZlìº,Ä7ßñB QqÓ¹…ºô€¹ËÝÔÏ‹áøã÷HLˆÃ†]GÐô{‡"µÝwoß„ç¦uHLˆÃ¼UîÜ‘ Ï¥R(€¡I…[<ç­Ü¹×arÿ>ÙÅ1Dç…Å9¶ßT†ö{tM.÷Ê{kkþÚȸxxŸ9‡SAWUå½ùÅ'§Àe½;®ß+s3ØXUR[™¡¡ÚòVæf/¯ŒÄÄbΆÍŒ‚U¥e“_Rj:¦®Z‡;OÂ`miË×c÷G°xÂhØXU,Ž¡¹€kšCqáˆè‹J¾…Üjušë#X ôQrdŠ ©2©˜…ATÂdf(†^‘ÁÖ]û¶ðÛœÅXô‡3j×k€þÃÆp‡1<—Z!¹¹¹Ý2¥Yõnñüs×Áïgý:HÓ±}[ýw™Î¨¸gJ0bÞb,Ÿ4=Ú¶,Ùºó½[¯ßÆÂÄ£{vS½ ”«°©Ÿþúw ,MŒ±mÏ6hkiâ~xŽú¬--Ÿ|æ•°¬úyôÂåÖ¥Fõì ¡@€]'OaÕλ O^¾õjØÀkÉ_ ¸p3¾ùÂ}žõê ¡mõb±?¥RéãñKW½Ø €DšCùgN_K¶D1&PGÿ5aH ¹LÍBžÏLŽ„¶®Ù;Íùœ™ } ”Ñxùõ–›#ƒ4=­Ý%H³áû‘‘ƒÊXD%H9‘û|/#%é9j×kX$·ÑqðHœõÅê…sàð¿Ÿ`Y‰sI3<—n7sss»¥¦¿h9}õ?óçmÚV»$…è¼ÖÚûáj-¨Òì,Èå903Rtû‰…÷™sj­¹ŸB×ÖöX¶c7š×³ƒ…‰1Öíݼ!hëU¸~û ßV·ARjl¬*A[KÒ¬l,Ù¶€bŽf‡F 0möŸ9m[! 8þ7‚ѵµ= M,†©¡!„â“S°íØIõ_ Àƒ§‘034„X"‘ž„Ò^ˆá~àH¡ÛÞ¼^Èä9Å%4·P@G!ü³¦¯Z©îvÂóÇçuω?ñèôR4èë†g!Çy ÕZÇ­=c‘-IEµÖãQ³ƒ ²ÄIxðß|ÄÜ:y–¢uÑĦjvp~ÅoUëö[ÚU¾ y¶OέE¶$-ªµj­ÇáÁÉÜ„™Z"#Ôîü,ë÷|‡°ŸŠ¸»'‘™-‘1Z/ 4­îm]3d$†!ééXÔéŒ2B< 9 qbô,êÀ¼öªåÓbC{•ö$5Ïî…L*†‰= ¬ ’ÔX$…@œ†²†•¡_±tÍm?x¤ÇÝÇóG~IÅЯT¦ÕÔ.0ä߯ÌäH<»sòl)Lk´Q+oµú&=Iax‘ðe +C×¼fessdHxt©Q7¡!ÔUCWmñÆÏ,ËCSG92ie¢®ïUû][× åŒÕoù‘g‰r ¦Õ YVÑ7½!I®¹-Ìkÿ¨ö¹ó.ÜÄÝõÁ‹„GÐ,«¯v'o_e7®âÚ¥ …°«× @WçW‘”:uŃ;Á8Ðæa]­F¡ëŒ ‚k—.àyB,+UFÝM`e]Um™ ±þg|úåD"4ýÞ5íê½v}7¯B*•ÂÄÔ¼Àób1NŸ8¨ö˜¹EE¿²lÞz~èØ YR NñFJR"ê6l‚­Û¬ûÒRqö¿£ˆ‰Œ€±™9´µ_^„ý¡c7”½¬Ûo_¿‚›W‘!£œH+ëjpø_çB?ÏÔ9‹Ñ½m#lX¹ @×sbx.­.Èss[§¦¿p˜±vƒëòí»«Ï=\·SËæEfhnSCˆÊêøôË‹`ª¼ÿYTVGõ³•¹ì|‹Ž¦âÄše054€~yŒôô0{Ä »Fzz°27Ã8ÇØésªÀ:^e¤¯ý|£Q¿é÷‰ýz!C"A§‰j`ajŒ­®.ªmïæ`™ë6þ1ã—¬‚÷é³Ð+/¤~}‹á°«V[]]0yùÌ\¿Õ+UD×Ö-UëY<~4f»mÂâ­ž°41ÆÐŸ;aÕ®}feC[Kýl‡Ñ —aù¤±˜=bœW®Ãöc>052ÄèžÝð(2±ÏÕîm^¾c7ªYUDQœâL&Ïy6gã¦3[Ÿh–›››šoòÏ˜Š‚Š!Ð!òŠ'Ìkw„á7ÍPÖÀ YâDˆ!Økô+} ¡6ÊW>,qjuú92 žøÿƒ[^aT¥Å[¡S£oáê¶_ “ŠaPé[ˆà IU=ßlø~hëš!éé{M@Y} Ü=úĉaj‹%NB¥†Ž¨×k5 î®^¡V9ÜÜ;e4„ÈÍ‘á¡ï"Ôé¶•›R{ÿ‡¾‹ñøÜZäæÈPÖÐ ’ÔXäæÈÐiÁ‡ Spÿ„+žø¯GYC+µDxtzô,ê Éª`øê6 µEIÅxè»õz­A¥†}ÔÖê· N/CnŽ :ú¦'ØÆ ¡¸¾c^$„BGßÙ™ig‰abÓ z¨]ÈûÌe4Щʻ¼©Úû{MPû½^¯5Âs–8 Á^`×e!žø¯G–8 BdKRaY¯ê÷}y¢›‘† Í} M‡aåFÈHŽDfrd}MTÉe2¸L“‡½`]­²¤¬‰Š@³–m°Æc/´´çDwoÅÕ@Ä=‹ÆŠy.004FJr"Ö-u…›ça4nn¯¶Îù.“p`×V„B˜W°DLT,+UƱ€;jü7§_¨ ×Ïâ‘5ÏÝû Æìź>]=}hië 1!®ÀgIINÄì)Nj¹ï9^ <ß¼ˆÙSœ ±tî4Èe2Èå2dˆÅpš<£&ÏPÛÆ‰C{jÚÕCXèCµ÷nô=ʉDËd˜>n(N?cSEÀNOKEzZ*nD¤ZöVÖUñ}ëvð9ìi®ËÕB8•leXדּPCc¡‰¡iQ ÑTz½š#üàK†”r?4p}jQ×÷"Øk‚Z öšˆ¨ë{ðMóa°ûyZ0+,X¾HÅ…µ? ¼iu´¯¸°w|f”ÑÂ~âYUÐJBàÆ®ÐÖ5ƒƒs *¤=½ä;‡g Aß °¨×õµÛzq]HÒbÑrÜ)hëš!G&EÐæ>xñì>ÚN¿®Z_ÞgÒÖ5ƒU#Ôëµ B-®léç¡çÑvÚ èè[àÑéextzZ"Ôh7Ö-F@–%Æ¥ ]!N CûYwUë pÇÝ£À¼vGÔéºXõþ‰a0­Þæ½Ë=òêNÜÞ?µ:ÍA•–£‰OpeK?T¨ÝQ$ó¶QC¨ ». aÕ¸?¤éñ¸ðw;hêè¡Õä—ÕJÄåm9ø;ÌlÛ£n÷å…ncnŽ þ«•‘„&CvA¿â·ÈÍ‘áñ¹¿ñÐwªÚmÇÙjë«þÃTTk=Bmd‰“à¿ÆåMm 0,ñI‚þíQh°ÏLŽ„ßÒ&€J a×e4„Ú¸¾sâƒs *p_ÙÒIáAø~ìI”7µAnŽ ×v ÅóÐópp¾TdºúŸY¡´ž³å¾.¼°fÑlÛ¸k<ö©Z]xybö'µ 9ÇÙ Çì¶¶6­Û û¶þø!üßµtÀj}jëôX¿½þŠ ÓçBWOb1Bn^Qµh§§¥¢K«oa`hŒ5û`e]YR æÏœ„Ãû<1ý¯åp<°rþ,xnZ‡Y Vãç^ý! ›Ù:`XþÏà¾ç¸Z°Ïÿœ@(Ĉñ¿cøøß •J1¬×ÿúþ!‘ª‹]Z} ¹LÏ£ça`dŒ ±ƒ»µErR"Ž„¨–Ë[§ËÂÕè5`˜ê½âb£anñúqnò^·òßݯm¡&…•u¿d–û9ßKƒ»ó“åäÔ{–˜ä4zÑŠ°V#ÆG]¼’Åb¡¯$åï½Þ»«þÜ;ÁãÐqËÜÜÜáÚ08SqdYW=È> 9 M}X5î¯öxySXÖ놴صÖA]s[µJ}K€IµVj­›åÍjä…tÎ/5úL«·Qµ8jµQ±~OdKR‘Upz$«FhØßš:ú(£!„E½nqb˜Úr5ÿ7UZŽF !4uôQÅ~ rdR<õWÎÇçÖ¢œq4ìï®öþœ üâFèYÔQg0®Újwij»' t®ÕéOU¹këšÁ¤Z+¼HP.!Ôo%ÊZ¡aÿ_» ÎâEB(j´Ÿ®ê%PFC›6“ _ñ[D^ñT-ûÄÿX5Bõ¦ªîk×½Ó=îob^»#êöX–e4„¨¨ì®Ÿ™¯AJÄ5˜Ø´R?e4„¨Ül0rdR$?½Ì?N*²²¤ìÙºí:uSë®üs¯¨iWÇìV[^.“aå¿»aß¶ÀºZ ØÕk 6%TzZ*<7­Gƒ&Íá²`tõ·0äuÉÎS’1cÞrUWn-m¸,X#cÞ§øû΋±{‹b»õPÑáõMô] øu,FMžPˆr"Úüï'dI%xž ˜%1!‘áOЮsw«>G»Nݘ§Z€jÊ,CCõcß¶µê6Ü ¾Î²a·í÷w([&;5¸ïÌ9sªT´Ô\8v”Ù÷õëh±hè …fŸ%[vÚÉrrlÌpŒÅBÅY^ØÍ#N ƒže÷¦@YC+ÅIYr¤êgͲz…®·ŒÆ‡S!Ð!3%Rí±¼°^¶–Hë#Ô¶Õ¬f;4¾z–vê'bµ~|åb@5ÅgIR„ìô¸û¦Ç£Zëñ…~öWåµ®æWåû‘ªÑ̳%©H»Cëfî–ˤȑI!MW•cÞ¶¿© _$„B’‹ªöcÞnS£n*/`Øxθê÷H¾…ÌäHhµ‘‘† µ;~òãʼvGµrÔ,gT`M‘Ä ÔKv_y¬Uâ'YîÜF†X ¹L†#^žjÏ•+'ƒ;Á^óê½Ðya6ÏÍ«—%• C—^o|ïàëW  ѨYKµÇµ´uРIsœ?í£ØÆ»ÁÈ’J ´ y^'¯‹xdøcµÇc¢žªÊ(O§îŽØºa ¦‚6ÿû í:wƒ}ÛßÚÛ²Ò7-ÔÄðLo·Už“ã5`ÀέkcSfá¸QëT«"`ÑЧWF²Ï÷ôÑikÜ,%ÙÙ¶PtÏ>Är¡’(7G ¯W•~Ól0žø¯GÈ¡i0­Þ©Ñ·ðÄÿ˜×îXàþÚÂhëš½Ó}²y­âòlEëov¦bDòwmq5®Rpà­²/ƒ°L¹¾´˜<:½´Ð ïÒó“¦Ç+·½Ü›—{‘  ßÂB>÷Ë׿µ|¿m}Ÿ‹uóa¸{ôÜÜí˽þì>BýV¸j‹×æFTH¥ŠéÚ®^ò/´åóCF€NIz®–o ‰ q004.¾óB«\9ÅTÞÿùéúR´´uУß`ìÞ²‹gOE ‡ö¸q9ÇìA÷~ƒU­Ñ`ljÏ£çðïÚ¥8uü N?-m 3EíêuýWø\Äð\ÜÉlÍÊ–{^»÷`lÇñS]ê׬žÉMŸ)4×0ÀV– •d"ã*H»_èsojþTÁ=ááX5BZLžPK›6“P­õøOú^™)Q^Š¥%R´ŒÊ”Óz½MÞ€d¯=yT®Ïܶ½Ú Y£œ²•:/¿ŽŽžbÿdKRQV…îC-‘‘ê‚<+£À~Èeýsйuºæ¶ÈL‹ÅÃ3 jã›fƒQýgþ!R‘–×¥º÷À_1fêŸdF&Ý·ßÄÜ¢"®ú«F¥Î/2üIîÎR©úí!o[ÿ§%•àü©hФ9‚¯_ÁùS'PNTc›A#Æú™\¬Ât×eºxëWÀmåXZUÆÏ½^DE¨^K¥ïyþt!zµ<'§òµ{VtžøÛóA³çE„ÇIJd胩s×o¶í9Àâòµõ%ÙÙÔbp¦ÒÀ´F[d‰“ð,ä¨ú Xz<âîú œq•wjþ©Ñ·wU¾‰£¡ÍoW`?ñ¬Úý¸ŸJÔµÝÐjÃHÙ‚¬kn m]3ÄD¶äãO.Z"èYÔAbXÀ'Y"Ç] IDAT h­ÖÑ·À³#ªVèÂ*ç_޼ºSíñlI*âøÂÄFq?ºŽ¾´DFH R[îÎÅteŸ“$5)‘×P¹Ù`4ym~»‚V“/À¶ãlµ{削"›šµ¡«§ó§}T-¼«~ãï ¥­ƒ»¶"KÙ²]˜Æß)ºaÿwÄ»@p¾qö?ü¨ÚF¸è¯Z&odëÏíæÕKˆ‰ŠÀð ¿Ãóè9 ¸ƒ}¾A:zr¡-æªzS(D‹ÖíT#†‡>¸÷ÚeïÞ¾Ev>jú<Øòü‰¿‹¬Î–É7º|Íùìµ›“ÕOsuúµ²µ¥K‡Þ545iÙ4±¸)€EÖ)/Е U[CôM/ÜòšIZ,Œ«ÙCœЇ¾‹-I}k‹ëÇÐѳ„†P!GlÈ•!*oDm3ÛvïÝÕ9OÄåm0±iˆ¾á…g!GQ£ýtU 1Ôì0 Á^pqݨj?"HÓbß÷ƒZmÚLÂõÃäÞUíGC[Ù"œõ"e4¨Pç§÷^§m‡Y¸¹w,Ü:£ªý”7«‰¬ ˆ¿ï‹oû(N8«ÙÃк"‚¶A ÔiÍvÈÎHÂãsk‘™†í§©ÖW©a_<ñ_û'\aZ£ žmEòÓ˦©Ê›W€ê>åä§/C·EÎïz5ËêASG÷}æ!ñÉEÕ¾ÖÃÀªa¡sB¡CÇ:cÍÂÙpÐ~‹òºŠñb£#`nQ±À=Îo£«§ac¦Àmå íÙ}‡Œ„EÅʈz†wƒ1Íu S÷>p_³KçþŽääDÔ­ßñÏb°n©+Ê•aè˜)#c´éðN?ˆí ZÍÚðX¿)I‰¦ zp'ïÝ ˜b ÎBl´¢u÷u­¿¯cVÁ¡³§8¡qs{UkcSs4nn¯6ÈÚ/OdˆÅ¨bSdeI±gËÅ…‚7ܯíwò(´´uÞ»œ‰á™ z`®L._}êòµ‰ç®ßšÐ­}†Ë°A•ŠâÁT4Ü}â;hμ̸Ä䆖袼 CTªh‰ŒÐ|ä!„š†»G_vG,ojƒÆƒwÔ꓆g} ˜Öh‹øû¾ÈÎHBvFdR1âîúàñ¹µæ ~a7âñ¹µ€rÆUP·ÇŠ#ŠWjØ¡6BýV"äàïªÇóF¬~_êü„}7àï"ÜÜ;Võ¸†PUíÇ|Px¶¬ße4„õ[‰;‡g¼vÚ†»‡]vq£j.n=‹:h:l¯ÚýÄÕpÆ‹„Gxâ¿Oü×CÏ¢š ß;‡~W[_Þ¼ÚùE^ñTÜm\¥9ʾGxh‰`^ûGDßô†ôE²5û:3E1w¸¡u3|7Ü›šŠ¬¡£'C(ÀsÓzLÞWõx9‘“g-ø P7jò cÛ†Õªy—B!ZýðrÀC-m¸ï=×ßÇaÍÂ٪Ǜµlƒ©s©Ýoí²`â†öÁŠy.ªeÜvÆ ®mÕÞ÷ìÇà¶rÚcëW¨~~ßðlõMUU—í¼¹ÓÓR~ëW¨M“úÛ6®QkÁ·²®Šù«ÿ}íÀd‰ qð;y{8rŽçR†ó<&\„Áðîm[¥0DÓkBs X®¼Cô±ŠÌ<Ï*Kœ„Œ¤0èèY~‘9wóæE~u.èÜ.oîƒÄ'ªù›ßUÞÊm~» ¡644µ¡©£ÿÖ×eKR!ËLƒŽ¾Å' pÒôxäȤ(£!üde™·Úºf¯íÖ.Ï#Kœ ¡öR“¦Ç#7GþÅæVŽ»ëƒk;†¨Í·¯o퇘àƒh1úX‘8Œó<Ó[çØhÈårhkkhÕýP)I‰ÈÈ¿qð±ô´T¤§¥BWO_uöë¶O(~²m{›í×`Å<¬Ù⥀³¤ wì„ÛׯÀïf¸ÚÀay÷0—+'R{¼0³&€ï±ƒ8àwíƒg+mJÒ<ϼœúe<0Y&—/Þçë7íÐÙ ƒ‡ué(Ô¯O½ò¼ZUZEÅ' ˜åó("ª%7ƒ¤°dˆ^Ò©ukþÜ’•÷Þ–7¯©öx ¡êŸ@ûÃG†~—Q¸óhêè¿SÈþïý)·Q %z§áϱ}o’¢Ü×¶…îkÐ*gÄ?B*>Ç UFÆo ‘o ÍŸsûÞ$oþêÚuë«§hë@(BK[§@‹ñ»†àãöàØþÝøíÏŠΥÃó—õ Àä¬ììÕnÞ‡çl:t¼Ç¯];e0D—ÚÐÜÀeu¡¸ÀBD_û´vGD]߃k;†Â¢ÎO™VGvF"žÝõArxlÚLþ¤–¾“jöõ[…`¯‰¨X¿D¦6IRñ<Ô Ï r³ÁŸm`:"ú¼Z8´Çá}žpêßö?üˆ*65ðÙ Ñ%64·pÀ\á,bx&"†g†g"†çâž9ÏsÑ’››Û-Sšå°p‹çÅú†=÷ôñM•Éå,™bL*•>9oÉN»>ƒ ƒBîI40”Á™ˆˆˆˆ¨øax.ZnææævKMÑ}úênÕí;„!º‡æ*]ûŠŽ^, £24‡²tˆˆˆˆˆžéÓ¹ ÏÍmšþ¢÷Œµ‚›ùìø…@1‹¥h“Ésž¹üã¾³j·~Èš»aéo¼Ó½h;+“Ë[=KLêì´`ÙBCÓy£‡ëvjÙœCs±ÐK¶ì´“åäØ˜à‹…ˆˆˆˆ¨äbËsñ´Už“S#42jÖ€?þŒýyòôˆÇaUì³+#Ùç{Æ«êÏ}î.ؼÃV–“ó€ ÎDDDDD ÏTtÉlÍÊ–Û\»÷`EÇñS“¢?whî}}âòµõ%ÙÙ•¡ùˆˆˆˆˆˆá™ŠOˆ^-ÏÉ©|íÞƒ'þö|Ðìyá1±,™OP¶ç®ß:lÛs€¾Ð\ ÀV QéÂ{žK €ÕÙ2ù¦S—¯9Ÿ½vs’C£úi®N¿V¶¶´`é¼h>>jþÒ²ibqS‹¬ƒâB1ìS·ï´Ò¢óBsÓA#k?ŠˆŠPWšÙ4ODDDDD Ï„pC³e²FnÞ‡}žô÷ïçÒ¬ìRñá“ÓÒowŸ:swÓA#«*Cs-“¡h¡'"""""bx&5¡†fH$­nñ¼X»÷ÀÔ’¢óB³]ŸAA!÷$š+Có3 DDDDDÄðLo’››Û-Sšå°p‹çÅú†=÷ôñM•Éå%âÃI¥ÒÇ#ç-Ùi×ga¾Ð<Šx""""""†gz/7sss»¥¦¿è>}õ?·êöR¬Ct^h®Òµ¯èè…Àr:*Cs(w5•$¹9œ‚žˆˆèK(Ã" ×p ®&úÕç®Û©esQqØh™<çÙœ›Îl9|¢Ynnîm(»ÉÝI¥T,€ ,¢bï ÖaDÄ:ì­r?gÆex¦·é,ÔÐXhbh`Z”Cô+¡9À.p÷Q WÀ9¦, "*¦uØi”΋CÄðL%XWM¡pÞ7 Žeö}ý:ZEd»RþÞëí³dËN;YNN"-Íg¹»ˆ¨”Ø ;sÔó¶"*nÎh ØSž©,ÐИS¥¢¥æWÑùC³À,Ǹ{ˆ¨”É ŘÞ,"*F*ˆ€¢{þ «Y$ÄðL%‘À-MÁܺ66eŽU±Nµ*‚/óÖe$û|O¶ÆÍR’]ÀŸq—Q)4Àf2ëLb‘Q1â`Oø™EB ÏTÒCôX††KýšÕ3?oˆV ÍfæØÊ]@D¥Ø]µòýlÇ"!¢b¢€Hå¹$d±Xˆá™J£4…‚­Ö—º:ýZÙÚò“û ;wýÖñQó—–M‹«(C³'--DD<ñTH`Àb!"†âñÄðLÅCyÎB`’C£úi¢ó‡æºAÑ-‘¡™ˆˆ'žDÄ:Œˆá™J5… ÝÚØg¸ TÉÌðÝDn‡>ñ4g^f\brCËl a±ñÄ“ˆX‡1ö ËŒUþ>ç•uUàw •²º”ˆˆuñx"*eáÙD€Óó=öê2¾²Qø}Îk•Ë6æî!"ž(±#OyØm›Jš¼îÛåñúîÛ6¢¼(乫Êÿ«±(‰ˆˆˆˆˆá™J2o^P þ5–ÅADDDTbX+ÿ ß²\årœQ…ž‰Þb4­Ð‹ð²»vž(e…ªSÈëê(ÿÊ"$"""*r–àò†el•Ëø¿æ|ˆ¨Øù÷<ç×Sù\î+ËLSþ>ê•åˈ…âžiV´DTšêR"¢âR‡åo“  þk– T®—3¨ðx"âÁýŽáx9úvþeʸ§¬t§)+Þ®®(—û•»†ˆx¢@DTdë°¼’(Ø};oV•µ,ZOD<¸ß/<ç]|u™ @½e:Àî"â‰Q‘¯ÃòHœó=f ÅŒ+÷Pø½Î6Êå=”ç…µ\ ¡hTY À]¹¼5w¿‰xpPLKÅJ‘ˆX—Ÿ:,¯$SŠÀŠž…ß²üXåséPtëNV¾÷ÒW‚³¯òñGÊå2•¯ëÉ]ÅïD"ÜDD¬K‰ˆŠc–×}û½s¡hQ~UKås~P4œäå•ÊÇ¿²¾üãâT‚bð±Hî*~'ñà&"b]JDT\ë°¼îÛy-ÊÂ×,“ Åm{ù •¡øŠòwgåº ßÜUüN,Ãò¥¯|pó$"b]JD¬Ã>” -ÃåÔp¿eb•Ayj!ÏM…bªRM(n㻠Ŭ+ø8 à*w¿‰ŠÂÁMDD¬K‰ˆuØÇ{Ëzrß៵rÙï èž õAesWñ;‘ˆ7ëR"¢’žóºt¿òPŒº½/kÌÝÅïD"ÜDD¬K‰ˆJjxöƒbÔl“Bž[à/åÏŽ¶£à}ÓŽÊõOäî*Ý߉,_"""""*Áþ…â>fwåÿy˜Ž—]¶­ „úhÛÀËù ï³(‰èkak ëR"bö±ÂÞa=yÓRÅB1úö åï·ñ²Eº|¾Ço@Ñ }[ùû>î*~'r$2úÚ7A""Ö¥DÄ:ìcL„bþæ¹oY®%]°m<‡bDí­$ù–Ñ¢Eú;(Z¢ï8 `w¿‰¾öÁMDD¬K‰ˆuQ‘?žxÏ3}iÖx9ì? ýˆˆˆˆˆˆˆ^–/@?fq}¶Úë0¢/p<±å™¾†¿•ÿçðeq$ ÀÑGa« ±#âñD%ØiåÁ]‡EADÄ"bFÄ㉨p߃…ñDˆX‡ñx"z+Oˆˆu'¢BìZâj?¨s‡{–ÆÆÉÕ*Vü ŠÉ艈ˆ' DÄ:ŒˆÇQ^h6ÒÓËulß6wçüÙ¹š7ÍÑ•Ë`ˆ&"≱#*ÊÇS–/}n>¯°;pæÜæÃç/4mÕà[Lì× Ö–ªçï<ò»s¯Þ}ª[NgNxlÜz2–Ñ;Ÿ(ðûœˆX‡}æã‰*}öÐ|Àï\Ó†µjâ÷Aýak]ùµË_¾s‹¶xæ<ŠˆJcˆ&"â‰'±#bx¦í’ûšJ»ýü7ôóoo[å›2ÎaW­Ê;¿> 8˶ÇÄ&…šÎQqq;YªDD<ñ$"ÖaD ÏTâB³¥©I™ß÷GS»Z¼¾S—¯aáæíòäôt†h""žxë0"†g*ÞÂü¸o÷þçÀÿÞ†zº‚)Ñ¢^O¶þ“—±d›§ìE†$\,‘ŽMJMý¥NDÄO"bFÄðLÅ.4k4Ó@»¦>Ûûíõõà Ï=òÜÜÜ0†h""žxë0"†g*â¡ÙCgûž KøŒÌH´¦ì‹Í›~‘÷–É娿<–oß•­©)¼˜œ:25#ã÷ ñDˆˆuñxbx¦"š’S´&õë>íÛ|•m‘ÉåØräVïÚ'×//ºÅMD|þBÓV ¾ÅÄ~½`miQêËåÎã0,Û±;÷êÝ©ºåtæ„ÇÆ­ ãCDàw®iÃZ5ñû þ°µ®Ì‚yÅå;÷°h‹gΣˆ¨4†h"â‰ë0âñÄð\J\r_Si·Ÿÿ¦ƒ~þím«|SÆy€#ìªUaÁ¼E@p–mß-‰M 5£ââv²Tˆˆ'žDDŸVÞ­„ûÏœÿÆÜȈ·ÐÃ3}ÝÐlijRæ÷ÁýÑÔ® æ=º| 7o—'§§3DÃ3Ñ'âá:½‰_Ðmyãïtuh‰­G}r‚C$ú¢ò‹£âã3DÃ3}Va~ Ü·{ÿsàŒoC=]Á”ŽhQ¯ æ# ¼Œ%Û24{èlßsaéÿ€‘‰ÖÔ}Ñ¡ySÌg$“˱ÿÌy,ß¾+[SSx;19udjFÆ5– U†&¦ ÉÏLXDÅ›®žAlzZŠ%K‚Š“' 8K·í’=}öœ·ÐÃ3}thNHNÑšÔ¯7ú´oÂùÂ!zË‘X½kŸ\¿¼èC4å/é,¢b®Ae]ž³Q±qdÃ2“Óç‚÷ƒGdfF碉ᙈž©ô„f÷í§=¾Ôø;yãÐäää¾2KS“ƒ ÑÄðLD ÏTb¾Xüü„îÞ¶ìø…K£¿öø;ùǡщn†ÅÄp“{‰á™á¹ðükVƒç/®>wõF¥_:ÿˆÝ~‚^y ¦˜ŠONÁº½û±××Ojb¤ïñ8"z€– 1<Ã3ÇÐ\TÇßá84Äð\ CóÉÀ˕۷ÅÄ~½`¤§Ç‚)!"ãâ±bÇ¿x)ËÌÄp3C41<Ã3'Ë&žyÜÿÒÌ¢>þNþqhŒõôýÂbbÆ0D3<3<—»–¸ÚŸ8wq£O@mW{ŒíÓf†,˜*<&«wyáä¥+bc=½•££ç°dˆá™ˆž©(*®ãïp†g†çšúÚ¶oÖS:ÂÊÜŒSJÜÀâ­ž¹Á!3Ãå ÑÄðLD ÏT”¬ž:aè—®.+îãï䇦‚‘‘÷ãè˜I Ñ Ï ÏÅ„Ïß+ìœ9·ùðù M[5øûõ‚µ¥ ¦”ºó8 Ëvìνz÷Aªn99á±qëÈX2ÄðLD Ïô5”ÔñwòÆ¡Ùã{Fbjd°…·Ð1<3<ƒÐ|Àï\Ó†µjâ÷Aýak]™C€ËwîaÑÏœGQi ÑÄðLD Ïô¥ý;sZç“W.»•ôñwòCcd »ñiLÜ Ñ Ï ÏEÄ%÷5•vûùo:èçßÞ¶Ê7eœ8®Z * 8˶ÇÄ&…šÎQqq;Y*ÄðLD Ïô¹”ÖñwÂcb±j—WΗ®dr†g†ç"š-MMÊü>¸?šÚÕbÁÐ;9uùnÞ.ONOgˆ&†g"bx¦OÎÃuz¿ ÛJûø;ùǡѕ_¿˜!šá™áù ó;`à¾ÝûŸgü{êé ¦ tD‹zuX0ôAN^Æ’mž²’p±D:6)5õ?– 1<1<}(Ž¿S¸;ðtÇnùµ»Òy Ã3Ãó Í Á´ÁЮi# }{}ý°Âs<777Œ!šž‰ž‰Þ×%Uó¹tu'Çßy³üãÐ44fÆ''»3D3<3<²Ð졳}Ï…¥GüFfH$ZSöE‡æMY0ôÉÉärì?sË·ïÊÖÔÞNLN™š‘q%C ÏD ÏD¯Ãñw>L@p–nÛ%{ûì9o¡cxfxþ„¡9!9EkR¿ÞèÓ¾ †¾HˆÞräVïÚ'×//ºÅM ÏD ÏD¯:²a™ÉésAžçãä‡&Sš5!õÅ‹},†gz×=áç'\uÄ{Æ‘ó§=‰y&šÔ¯7z´m¡@À¡/Jš•íÇObíïl}]‘hDô(¡,bx&bx¦Ò‹ãï|'/cñÖÙâÌ̧¼…Žá™Þ#4‡<sì‰!?wdh¦¯Nœ)›÷!¸<"3328ÏM ÏD ÏTC³‡ŽûöÓçóʇ&''_±®Ô IDATçIrZúh±Drš¥ÂðLù¬Ÿ>Ù騅 ù×ï?0Ý«~éÔÚZš,*RÒ^ˆá~ð(6:šejhpøQDÔxÏX2üax&bx¦’š9þΗÅqhžé ¡908Ähh—NpêÙ¢²:,*Ò’ÒÒ°z—vúøÊ,MM–²íÅÜŒ“ñú9=\°‰á™ˆž©ØVî~~Â?wo[vüÂ¥Ñçë…è¼qhôD¢›a1±ÃÜdÉ0<—*žÍêqðüÅÕç®Þ¨ôKç1¢ÛOÐ+/bÁP±Ÿœ‚u{÷c¯¯ŸÔÄHßãqDô )¥ ²€e~{Ã2[ ex&"†g*Ž¡™ãï-‡†á¹T‡æ“—+9¶o‹‰ýzÁHOCÅZd\÷ƒ‚˜ËÄhФ9FMžÁ?ìb`„c'ÄD>ű€;ž›8´7ΟöÁˆ ¿cÌÔ?XX Ïô§xá84%;< K{h;o™mûfqdÕbX™›ñp{ƒ¤´4x>ë÷@š• ctu°çhŽÅ€µ¥V:ÇýðÑâ­ž.ñ)ÉÎf†ËK`ˆð/€?,0þ^ó€E+OQ®cn!á›ÞB.“aƸ¡„ØvðŒZ«b\l4œúwÇúhѺ7·¯u‡…>Dпn¹¦¢!#CÌB zƒÕS' ýïÒÕe³Öo2Ú¥V9çø;Å€^yœ:bh—ŽZ«wyõŠIxÞ­‚‘‘÷ãè˜I ÑÅŸFiûÀ>¯°Õ£kД%«ÏK³²m®Z„•Îãœß!8·5ÞgÎÁ®Z4¯W2¹ƒfÏÃ’­;Y@Å„­uexÌ™Qfÿ’yem*Wt1Ö×µ¶0Ÿ€’u!m>vŒàð–e»ð¢ÅÙ ÀO¼Lp¥øã_½xpq±ÑèÞoHî¸æ1{É߀Ó'úúô´T$&ı Kî»à¾ç8FMb/¢ü<ÿšÕ£wû6‘ó7mÛlk]Ù(`óz8tdp.fŒôô0wÔ0\Üü°mÓFŽzåEaÕ*WüGyÎAÅT©éäó÷ »gÎm>àw®iÃZ5ñû þ°µ®Ì#à¹yª]ûpmû¿j•·›÷!,ؼWwüËîîÅÐå;÷°h‹gΣˆ¨4Ýr:sÂcãÖCqÏpq” à,€6ê¸EìºxÙ‚œ¿Û¶@¤òñP¿ü€Yð,Æ»ø‹wÛŽ ‚.­¾E ‡öX·mçå2Ο†Õ7U`]­†êqÿ3'±n©+Ü ›šcÀð±4b<B!vn^ÍëV 1!ºzúÐÕÓÇfïÿ ½—6O–T¿ÿŽ!<ô!tõ¯ÉÓ¢u;›š#1!çN¡Eëv004†ÿ™“xp'Ö65ЮcW„BÕçºy5?÷€Ä„8øýw ‰ñqhÚÒáµ-á)I‰ºx‘áO`bjŽj5j}Ôý½áÂÿ´ª;¼ý ¥­£Vö7¯⇎ݙñ'x#C,F£ïZ~Ô6Êe2\ º€àëWõ6AÓïÞ¸¾ô´TèêéÃcý ¤§¦¨uÛ>}ü22^vê¨Q«.jÚÕS[O†XŒÓ'¢~ãæ0·°Ä©ã‡þVÖUÑ®SWµÏ·yûîÕ}]¿qsXYW-Öu5»m—ÿΜÖùä•Ën§dÊ?‘îÆ§1q äæúµÎÙmûC]r_Si·Ÿÿ&§ùKÚÛVù¦Œç¼Ù°«V…‡Õ{JHNHG§À=6}Ú·8S¹\®zlÿ™óð>sÒ¬lX™›aÊ@GUËþº½ûñm ìùï â“SP§Z˜9ôÕëer9¦¯Ý€>íÛ ©]-„FFcõ®}ˆ}žQYôÿ±½jÃËwîáÊ{Ð+/¡³`ßà[Lì׋;ì5µ«…ýKçi‡,Û¾{…$+{†P¨éWÜ»Ü0oî¾ÝŠû£¡`7ªÕÊðÜ·˜‡ç/Îʺ*ê6l‚€³¾áØ ]z@ÓïT!W ¾mµ×œ<âéc‡ ¦]=¸®pƒ‘ Nöš…³ù. V¡Q³–xõ+и¹=Útø ºzo ñNýÆó„xÔkØ1‘O¡zÞ}Ïq›š#,ô!fOq¢u[°mÃ<¸ ]=}¤$%ª]¸y5³§8A bþ̉ªõ¸­\Pè=»^ž›±ôÏiÈ’J`nQÏâ —Ép,à,+½ÿ…[VbÝRWÃÄÌn+À²Re¸í<¢ †ù·qÑΊP)—aÝRWŒým6†ÿíÛ˜œ”ˆ,©Dmâ0vP<¸ cSsdI%HOKE݆M°nÛµºgëF¬˜ç015S•÷«Ÿwż™jûÂiòÌá9%9³§8a Wß¿áOPN$BJR"ìÞ ÷=ÇUË&&ÄÁ©„=~ˆz š 9)᪞w]áVìÃ3•ly·ÎügƒmW{œwÿ› %ñûÑÜ +Çcb¿^Z«vyIMÏZ‚Ç¡)±Jl·íKîk*MêßûdßÙ ".‡Üûߪ©Êlž=ÁùõhÓ É)è8á7x9ûáŠ#==8t„…‰±"qìò´µÿÀ¾Á·çØ2¹?Oš†È¸x€ßÕp^¹Iii°41FÍo*ãï=û«z¯ 7ƒ±×÷ l¬*"42'L…P À8Çh^¯Æ-Y‰íÇOÂcžÁýÀüãu5­+ÃH_—;ë´¨Wû—Î,™8¦‚nYmŒb+™›÷/æëmÝ·k*ÿ¿_ÈsÏ¡tÌ–GÇû[é¾ ÍZ¶ÁÕ@Ìžâ„›Ù¢s ;¸N‡€s§Ô–Í’J°ôÏi°²®ŠÍ^ÿáç^`ß¶æ­rG¯¿ÂkÇ&„>¸‹švõТu;ÅŽ«]?÷€r¢×O#¸höT¤$'bÏE¸ï9ŽÃço¡Õ?BK[>A÷ Üo=ÆDãdÐ}øÝ Gç}pÖWÕžg¶³ü:~7Ãá{õ1ê6l‚ÍëW .6ZíbÀüaW¯Ÿ¿Ÿ ûz˜÷=ÇÕÂæ»ò?skÎÆˆñ¿ãÔµPì>q»O\DzZ*\§+°ülg' ë ¿›áð z›šµá¹iÚ2§*°÷b±Ùû?µmüÍéD†?ƺípêZ(ün†Ãeájܾ~‹gOU-wö¿cXô‡3zô ÿH ¸ƒ‹÷žÅp,ànD¤:ˆØ«Ö-u…•uUÕ{wé=Wýq[Ù ë–ý…°Çáyä6{ÿ‡~×Ð¥÷„Bìó ÂϽ¼Wy߸ˆ#^ž¯ýþ„äôIx¸No2¨s‡{cç-;/Íʶ=²j1æŽÆà\ÂY[Z`•óxýKç‰l*WtÑ•Kªdf6ûå3<ya~ f¸kèüåá—CîýoÙä±e¼–ü…¦vµ¸·?‚]µ*8°|Œôô0ÇmÚ:MD>ƒ1}­›*§½cÕ®½puúN=»Â¡Q¬ý}¬ÌÍàæýòþFm-MxΛ•Îãѧ}ØZWÆ^_?ÕóÞ§ÏáÇÍ`¤§‡å;v£©]-¬t‡F àÔ³+f„Å[vB¦líŽON»Ëo˜?f~éÔ;ë#´kÚ§ÝV ŽUA·œöV+s³GFúúÿû?{gOUúÇñOîµäæZ#ëh*e’Ò6©¦]*%i™¤RÚ¤©¤!m*mC¦EFR´ÓžÃRJE”ADÙ.—{¹7¿?®{rCCQèy¿^^qîsÎyÎsÎ=Ïy¾ßÏ·‚ðl€#¸i¾ŠUàwü‡g›¼Ï³'±a…cƒ?bÉ—œðEýwÖî ˆ'þ;ß/µ}hzèh¯o§>4íŽvsr^E‘  ÿcÌœåSÄhb4Wû™Äº™1PïM`•±û8wáÜ­h\Ž‰Ã¥½;žýÜÊ*<ÏÈ„Ï_¡Ìû÷ˆO~Vk;ú"Û:ÂÇ"®`Õìé`Wpp1:ëVb“ž@WSCd{Ùyù(d±‘óFDÜš‘¦&ijB?y-Jwgph$CJò›Ãu*,)¹ÚÆåãðíÚü[ó¯v=ëuªY~™\ Ÿ¾!ô ±®¨ärðO4Ž؉„ػز~%¶ûQ"ú˜¿/‚þY_˜’•‘þY>ó£´”§5õºaÓ™J!½Œú! 4]uõDÚ}œë«£'x1[/8Ž‚·yÈHOÅDÛÙŽö“µ0|ìD8»yR''%¢«®"Ï†Š´+ªÍi)OEfÒ?î£d˜Žg)«)ÉIiiýÉ>>NL ²Uç³¾¦ƒpçÆe¤§ý”x£,­Eư90d„È6ÅÄêÖ´•SPD~nø<Õ6÷ufÍgJMÞ§»Ü}üȘÐìœÙö»ÎåŽÏZïaÒ§»>‚=7ÿ tºâèFWZ|ò3¹-Gƒw•–sÜibbkó‹ŠÐv}hˆxn½¢ùˆTPhôö©‹×Î/çp$VÍžNåÚ“×¢`bÐ Újª`vbÅ–ÙNÁû…8y- ]Õº KX`•}(AÒí-(È6lx1Éb6B|ò3¤g¿†,ƒsãÞ‚m±JÁãó‘]3»-Äf„õ;ySÛrL1“,ÓNß¼£ërQN]õqAQÉü’òòûmè0¼XA¾]› 0ê˜À¢e©Ôü{\MãîÍ+xúèA:Ì’R02ý˜cÚè¸yål6ø< `>š?üØ o*SfÎÅöM«±fñŒ4 i)Oñçž­èk:¨Q¦]2LÙ&—Ò.— Pé¢Þ¨ö½ú˜@³ðȲ®:¢‚½’ËAVF:üvn®³¾š†%ŽK)« T3ËÞÂmEe•z«àx9(.,Wí›\svs°ÆéW8Íš„i¿.@Nö¿Ø¿Ýºú=ÐÀ&o¯¸°à“e´ää?™2@ |ŒÐÇy×~â¿ChÚ>4Û…ìë°¡øÐñܺDó¶ùo‹Š%–ÛNÁÔCÉm!v‡œBÿšðéÚ(ËËASE,6?¨ ijƒÕ8ü¬§Kµ¹ÿ<Rââ n[Y^Ãû÷EDt,žgdbò0sÐkÂt5Õñ³ž.ÜØSísß åßLhª(ãÁóTrrZú&A£ E´øÑ —úø†œŠûQ]õQÑÂðí{Ýó8”¤úÀ5f¨_ ÁLõsþä hQW.àLH ̆ ¯W¤Òètèè÷@ZÊSTr9”ÓïÑ 3ç/­#‹ >é¨Ý×#ÎBW¿òs_c˺”‚õ ‡f/‹$œq–‘ÌàJK D•p–û¿¨=ÃÜÒ z÷3«×½üsÎ6<ãý1BÑœ‘žZÇô+-EM¤¢ªNÃÚÆ‘ ð–äzÄY*ô|û¦U Ñé3qœjÂë›Ê./7œ?Õ°O ÇN¿&çQ¾O.øïPºq;.xÚ†Í#Ô:+uؽr)I#$ü'f†=qf‡ýzüý.Þ‡ƒŽuQTð©àV.-)+;EF‡ˆç&SEß}!Üuîo{V¿ÌyÃXn;“,Sb‹Ð2Ø[ŽÁ¿CÐVSÅ̱¿@É»‚¿ðsHËz½¿-‡NWèjªcgp(º­‚¤„8rß`ö/L=ü“oYmFX`õž?PÈ*…×¢yÔò±ÍpölGG7m­'n? Cw9óMcèÈñ8ˆí«±çð)JX ÉHOEÌ­kÐÖуœ‚"z÷ý$$¥pþT0lfÏ;Á‡ÿÀï Xó»lfÏotHp^îk$Þ‹¥ÖkI„¡ÔÂÐf9Ehëè!æö5äå¾þ,áÿ1½û™!!ön³mO†)‹†}pçÆeädg6èþÝ÷Çx&”Êy¾ÔˆºrÚ:z”hÕÖÑCb|ŒHèôŸ{·#-åég¹‹7–RV ®Gž­×ñüs™³hÅ'ÅñÇ¡üÂÇS Wyï"Ï”¡ípv‚™aO20„&1ÜÄÃMŒiWbã»l <ÌdHon£)tD<KÑ<ì·«Ÿ¤¿b,¶™Œ£ãGÑü•p°‡’C°­ÞÈ3;1°c¹%ŒopŬ^0žá]Mu&°æG€\Í1º‹ŸÉ ‹‘;i"NŸ€åàŸ1ÒÒš »~šô§CÁçó°ÃÓ‡›ó–®Âþípœn‰9N.PUפê>këèaâ´Y>”<ºy`=Þ2ø‡raÊbÏ– Hˆ½K…ØÊ)(ÁШÌûÙ¹¹‘gCñþ½`†5êÊEœ8껹N"¥–¹zÀÙaf[ ƒÝÜEèÞË%E…øûö5,XîÚdÆ §O £4#ÆZËå☿/r²3±çȇIË©3°Ç{¼Ü–cŒ• "φâÊù0ôêÓš@ÕÕ>ÌJ§^¤£”ÍFEE3Œü¢bÐibP`ÖÍþÔg9¹ÈÈ}i))‘}²+8`±ÙT©,ÂׇUÆFÀÙ‹8tîbegy¹ó/2³— nÝd·¡:1³ô«ï”Ïã!,ø0%²jÓàP8­\_'¤;4ð üvm ó_g6¾1ÄܾŽí›V‹Ô/¦Ñé°œb‡ [÷‰ô1 4R$_Û—7üvm®Sc:æöuìßþ;ž&=ŽG¯R},g³±Ãc5"N‡¢’ˡڬX¿Ydìù<§oÞOPH•¸8½-úÐ|•gŸ–¼_¶ê±P4Ç&=Q˜c9Ž“'€Ñ‘”@#Z#…,|CÂpüò5žZg¥³DD¿â¹6oó“%ÐÚºzÿé@•ñ¥¬bhjë4ض”U‚J.§ÁÊ[W#àì0 +ÖyÕ¶kÏÁ•óa8vöf£ŒÃ>ÏBnÞ(\Îf£¸¨J•›EÀÕ6³j®pèÆô±’ËÁ»·ù””üä̰°-ª]›Ä{±°Ÿü f-XV'|‡ûÚ~aؘ D<šÿEßtâØŽÈè¶VÿŸ¿Báó× ÊhµÅBa ^¤C_[ ¡Þ›ê´¨?Ï^„×ácXn;Ý´µ¾XPúüŠØ¤'Ûö;`ð¼ÅزıÁwµQ9—Ï|Õ±s™1 .3lZÕyåñù8zá|CNñ™ ÆÃW9¹¤¨ZX<·Ê°íàß×M:{çoßMþG4fŽŸå‹| E Z L&ÜØÃiê$úþ“§­ó ‹Ç+)ÈIÏ|í ýÝ¢ØY¥Ia¸µÃŸB ªáÂÙ^ýuÿÓ« ×þœÙßÚÇÔX¤Œfuf–SPü¢¾n%$¥%ˆ[¢Ÿ"û_A92£~¦u>†æ+t&Í/š…©„mÅçãÙÚç™°^µköúã ÛoÚFrú+wÓÇ2[ëécZÖkrq5VÀ‰úÐï —•a´š¶=ö­Q4/ܺKÃf„núû6úm@h(ËËÁ}=¬ÆIîü+Ô1ÿ]‘½²’üa"¢ _ “æØ» V8bì¤i誣‡RV1þ‰¾…˜[×`=cn£D:¡õÓ½—¤ ¸¯rBâ½XtÕÑCyy’ÜÕóa>ƪ^aM |.;œ®öÛŠµmݧ›¶\fNƒÛþƒÈ}WU%Eðø|E^Åõ¸{àVVág=]8M&ûOžF\ò3”WTÀÙg/œ¦N‚¶Z‘öŒŽR˜l1–CfƒûOž†‚,¶#?Ö· ø’½ÿäiü›û¦ÎçõÁãóñçÙ‹ˆJHŸÏ‡‰Aw8MFG)¹p I©i˜`>æÆFÔ:köú[YWû™P–—ÃõøûЏ vªJŠpš:©MÕޮχF‘)õ*'gÑ-ƒXkêÌ<¯w$©\Û¿î ì‰p&Ú0š*ÊØå²Ç<Ü22sò¦x A( ù©ûóŒ\1͇Q?S »ŠæÃ…€=[q:$ÒÒ ìúóÜ6ïnò6;« ¯é ÿ ;'|]tõ{ ðìM c…„Ø»س'Žú£‚]/ß?±eß2H„fáÀgDZÍ |‚Nz™÷íÈ <«qmÚ¼tPo™£°ì§³Ï^ø?‰ CÁÑÚ RÓ`å²ÜÊ*èt…²¼˜05ì f'Ö€ïñ“7È ŽÖVÐPQ†£·b’ž¢ÿDô¿·ú–€iM¨¶NWèh4ÎTqöF/xEJÆ¿È/*ÂîSï¼ÜÊ*(2ezí&vÿ`lý0 Ç"®àÑ‹4(ËË!äÊuÌÚà‰;‰Àæppîv4Æ;¯Frú«6w.¥à2ÃñGýé“,“é”ü“–Æ)]È··yiU3ÏåÎ .×Ó|þsçéS«æM´T"Æ`BÛ¤ˆUúØÞÃ;9îɳáNCàtAF¦^ªÉ4/½úôkRNóa6d¸H¹&BëПóB„@h ¾+—ιúOÂŽu)̱ƒÝ.KÚÿަР¥]ÁArú+„ß¼ »·Â¸›ÀmÞ´—úÏ^€“×ob昑8w+tÊë.)cc÷Ê¥ÔÌîpc\Ž‰Ã½äçM.Í5uÄP,÷Ùsc£FÕÂŽ~˜„¨„DèjªãÒž`t”ÂBoœ»ÓQ·1iè(0™ˆO~†Œœ\h«©"üÆmÀ̱£À­¬‚{ÀQÀ¥=;ÐM[ §oÞÁâm»àŠÃÖ´ÉsÊìÄ€Ë ̱-áfóöU…ðô×9ËA|hÚŸx𤺺ڪ‚[ÙÛûhð¦ýag¬›;KÜf„…,)KD ´ ¸\nú’í¾q£cà0 "BB˜JèuèX»õß)d±¨ßc ño%$âVB"µœÑQ ž¥b昺• þpuA~Q1®ÇßGV^>’Ó_¡ÅÏoñ¾ÇÕÌ^+0™ˆˆŽ­ékGÀýg©°96¿Xà°³8y- NS'ábt $%Ä1yè`<Ïø¬26˜L$½HGÒ‹tp«* Þ™ñ¶ÆG>46o¯•Lè¬ w”¤Ðµ?ñ,äauuµUIiÙÀ5¾xy:Öƒˆèo1ž¨ IDATÇ•ØxÄ'?Ãz‡Ù­¶ûOž†®¦åüø<#þáç•—FG)ŒhÖê0Û±h¶ `4€'ddÐVøsíê±WîÅû}þ;¯rrÚj]p71 ŒŽRÈÎËicfØ&=ëŸ ÞxûNž†®¦:t55Ч›d_çC9GP:ïù¿™ðùëµ\SEÜJ¶9„ÅÙÛÑÐÕÔ»‚›`vb€]³>‹Í®³~{¢–”ЇFANæà¿9y뉈n_âYH4¿ºzHIi™¹ë^Ÿ ?y.t3ДXoEž¤¿ÂÅ»1­Zæ£.AY^}ºé!;ï-¸•Uð\4O$,=&é ”ååë¬û<#»CNÁÏÕ…2€}¡§©ßiõLx …í—¢ª$põjl„?\]YyùàVVAWS3­«©Ž¡}•ˆÝ!'3Æ fÐÕjÖ—î(…¿F«ŒW9¹ÐÕÔhwçZèC³ÌÖZbwHØ¢’Òò9ŠLæ®ôׯ½ ˆ$4±6ÒÏ[<>ð›‚BÇÍ;^ö±›û&2:–MN¡>öŸ< MeX³ÃMŒ±ÌÖkígÁ/ìXeä²iNÑìöGÀñÆY³œ‹T«®®þÀD"œ -EÁÛ<äå6O)“r6O“ !ö.²2^¶x¿s²3©Ÿâ‚V5®•\r²3QÎn÷ÇRV‰Èx7×5ChŸñXÓoÖØ‘Ïœœª*÷/¦xßÉðËÛŽ7཯ÀÀ-2,„–fÍâ9ÈÉú1É_´ÿ]Þ8|`'*¹^¶„F¢¯é ëwBìÝ}Sìàîã÷I± 4­žô—ôàæÙŒÇN?Œ·¶kó×ÉñCà·k3õ·š†Ö_3„öÇå}; Îܼ}xíž“ÁF?ãâî-"Ï<íþ³ÔQûV9c’Å`f2áçêGoD%$B‘)ƒG/Ò1u„E½ioÆÝô0ÈègÌÜà ãnú(d±ÐY^&Ý©Ðo¡É˜ñLhª(ƒUÆþ¤˜q7=,÷Ùƒˆèº»}òx”åå°o•3\vïÇê=~"b¹vGšš@Y^ùEÅ”²Ûe fmô±ˆ+8q€Àí{ËÇvýwÓÖ‘®’Ó_uÜþ׉õ\îri©¹yðÈ¢a:´ñþϦ‰‰m쪮&NDô—á~>ÀrÛ)0ÐéŠ#ç#ñ(5 wö!àìEø†œ‚¾¶f ne¶cú¨p_`白t%lFX`”YäcwÈ)hª(#Ô{b’žÀzÕztÓÖÂÔíÄÀagÁã¿GÌႇ›Q¡ª¤›ÐVSEPÄe¼È~ûA‚ÑQ ¾!aØw2.3¦¡›¶B¯ÞDlÒ\ؽš*ʰ^µ¦†=á2æα±+8˜æºÒ;"Ô{9ÙÍ#šùÖˆ ÃÒ,T·Ðý¸:1³´Ý Ò<›1_,žoDžÃJÇ>Æ œ]!Íè„‚ü<¨ijµ˜XMINB)«„:†O‰çÄ{±°ŸüËW² ±wÛ•xÎÉÎDNÖ¿€kPZRܿų‘–L{xfkœÙö»Î原‰ºmÒ§»>VÍšÞ¦êú6V%E•HJH48³Î®ààÑ‹4±Jað£¶È Ø{‘u¥¦áßÜ7ÐûA Ý´µÀ*cƒÍáPaÕì b'CJBýzt›SA‰uVœª*j{ÜÊ*&>ù¶ ~ÿ"3›E[›_TІEtK=Sh{3ÏÈÿ>8-+ÛÎný&÷^ºº¼/Pï©Ó•¸Š5ŸÝ!§°Üv œ¦N˜öê »ux‘-w£ÑÄ꽉2Íx•“KÕñËÎ‹Éæ"oê¸U•ð¨) d¹í*/¦³¼8ë6º-ŸG^ø)jZÔ9•aÊ¢´„xâ€öhœˆº{Èy×þݺþÐ!Øs tº¶ûãfvjšðct”j°ÌT}Æi?ëéŠÎ÷Çè(…á&Ƶ„»¸h[Q/þÉ™éú¢ ¥0°÷§ï±Ÿ Á§ÓhuŽásÇ®-cbЧ·{ŠÅ$=‘Û~,d˜X‡ tº¸Kv^Þqr÷h_â5oE+«øÁ÷Ÿ¥8^²Ò­·þODD7ž´¬×`•±1̤¯È ,lÛïe ”ååEnšÂ7†€ ®Ÿ¹qoÜžŠô¬×HËÎFTB"•ã"Äð'êwi)IJ¸ éÓ]Ÿú½ö›Ã¤´tp+«ð<#>…~8ñïß×›‡S›5{ý€ªHølÑÜ€'€@2.„¯E)«ñÑ·ðîmž@ÕÌÞ~L9›—Î"'+r Š4lTƒ‚¸àmTº¨Q¹>r²3ñ8ñ²2^‚ÏãAW¿  É÷”ä$¤>{Œa£­D¶•x/Ùÿ¾lò îÈs(//ë´Tj;µÑëÞ«I"üc2ÒS‘ðO4JY%PÓÐB^FÐÔþ±N»J.W.„#'+ú†0ÿel6)ÉIxöø!òr_CBJ †F0`.Ò&ñ^,*ÊÙ02)ÉI¸{ó $%%aþË8‘ýfe¼ÄÄXŒ·¶CÁÛÈ0eQÉå`Îä‘(.|Gµ«är°lÎÈ)(âÄ¥¿!§ ˆr6®‹Å–õ.è?ÀšÚ?bžÍÃ.€Ê!ý°ÏšÜpUuìúóL˜S¢8,ø0¼\—áÈ»àìæÙ"Ç,ÌÉmîücÕ‹q=ò,æ-]…_®€4ƒRV R’“ê´=r`'†±‚»$%%á4kΟ ÆçµÔK‹î½Œp8ü* úF§ƒÏãaˆ•ûën]À°1DÎcfÆKø‡\€ÉsäËCÀ«¨#RA7ŽŒ™³|ŠMŒæj?S$l˜@ 4ž‘¦&ij"~òZ”îÎàÐHiI‰—E¬Ò…lçÆ÷:&bíøØÊ¸óøü®×ãï2iá2Ÿ=ÙùE$÷éc˜L˜öÄagÁ­¬ 0ØzL†ô®Ï­¬„tÇŽ”pÎ/*Æáó‘ÍÖ¿Ÿõt¡­¦ŠÁ¡Tÿ2rr1{ƒÎ݉np=vš*Êà× 'ÔÏ㴗׌ìì#m×nêÃb³#tàK„3á[tp¤¥ðò € S !)U'ÔúÊ…pädgbéwjFXšÁÀgWðy<\¹˜³h’RØîD…t÷0ìm½zKG9ý¶š=–aÊbèÈqÈË}M9¢Çý} )ÉIpúmTTÕ©í _fDž9I¾8D4Ky8ÎÝ;uñ¶’s·ÿž¶jötÚµý;‰p&š©#†"úÐ~ÚÊ™¶?)0e.ý¨®z_VZú»ürÑ¿ƒc,à^Åãí?u-ÊíÌÍ;-»ÙÏÒho5ü¾„ËaÖF/ôŸ=š*Êxòò\fLƒ‰AwÜMLúäºó&ŽÇwo ž·Êòòx•“ +óAø#ì,rß5O=Ócîn˜µÑ Æ3 «©ŽG/Ò`fØ˦MipB Ë}ö`·ËR¨ƒ†Eó¬žyEfö°«yñD |3’ÜC¯>&"9Æ µŠÄ oƒ©å\.·f¹ ž¨ÙáÔgçO£’Ëùä¬n%—ƒ˜Û7ð*=•5µLù<žHi«¶Àý/ÇNšÖ¨öCGŽ£Dñ'ÿS-,@Üß·Q“ŸÝP.ºRgå:yËJÊõ;š÷îû?‘¿åä/C޽͇š†לë¼79¸\W8¥§’/ÎwJuT}Ó‰c;¦.Þ¶ðmQ±ÄrÛ)õ–V"_(i4L1“,‹½p©oÈ©¸®jª_åä:xHÄsûãgŸ¿õÔµ¨ÕçnE϶·Í]n;µË÷â¤÷)´ÕTqÓÏ^¤£‚ÃŽ†:å‚=Ïj¦.*˜k-376Âý¿þDÒ‹tHKIÁàÇ®`t”¯ãGƒÉ`À¸›>âý©í¨³,.ÐÊòò"û¨½LWSwöâÑ‹t”²Ù袨(RÆà€«KnU%EÄú×ëù½“ÿ6ÆnG΋Ììü̆àEðÍ)x›¥ÎÊÿÙN(fùûÖùLMC r JMÞ÷ã÷à<Ï¥¬èô‚d€ ò¶„p†·cGéfÛæÈsX»Ìt: “æ~…— ïjj_‡õ¯ãŸ¡¦¡U5òÅùEóî á®Ã~[±úeÎÆrÛ)˜d1tñŠm Ô®¶ò1<>ÛŽǃg©Ð×ÖúdU·ÑVã0sÌHZPä㽡áñ²2Œ»i™¯H#â¹ýñ€seU•¯_øù‡ÎENš;aL9Ñ‚/ƒq=ùÁõYõ¼LÉ„¹±‘H›ÚùÓ—”ÿäçõ-k¨@ýeè4Z½Û%¢Ù#çEföpñzAðb‰@h5È)("/7§Îòòj•J3:‡_¥By¿/·å¨är¨¼Z!cÍ ÚÜ8ªi ^0¼Ëo–핳ÙX»Ì]uõp8ì*ž“Ùâã#<¾‡O~‘ë8¡}°ÃyáÚa¿­Xû$ýc±Íd?šˆæ6„Û”Wp°ËeI½ŸŸº¿°sp´ž] 2`­I q8XƒíÈáâ~áç,Î^x¦È”z•“³¨=‹h±ïøœg˜SÅãû…Ÿ¿Üg†Cá¾ÐðwœZ¡=QÄ*}Œ¸Àƒp°G„s#%#ó“Ÿç¼-€¾¶ÖΙIBðÛŒŽRp™aƒø£þôIƒGÈÉtJþIKã€.íñxéä”# Àœr§§÷Ñ`Ï]ÇOš;OŸZ5o¢¥RíBîB[ÍöÞÉqOž p€)/Ž„V‹å;lˆ½‹5‹ç`ºý"ܺþèaØGÄm{øè ÐÕïß-QÊ*¡Œ©*+¹ÈHOÅ+ÊH¬±è"éÁ=Dž …r5Äÿ} þ{@§Ó>¦‚ݽ[6Âaé*äçæ`»û*È0åDfÈ…5¨k“•ñ’ÊÛíÝ×T¤î±¾A/È0eqä€ä¡ýãO()*„B=ùÃÿ…¦ö˜h;gB1Ïf l~]E%ed¼|üÜ×X´r}“¶''¯ I)Dœ>†} !)‰+çþø…Ac0`£~¦8æï‹J.CGŽƒ˜:׃,FQãsû: j¼ßå硼œM·Æ?6y ßß•Kç\ý'aǺ‡æXŽÁn—%¤å7„Ççãè…K¸—>Ÿm5U,³µ¦¢ýx|>þ<{Q ‰àóù01è§©“Àè(…+ב–•œwøýÏ@¬w˜-²í+×q96o ‹àì³¶£†ÃÄ ;®ÇßGPÄe°+8PURį–c¨hÄ+×ôY¯ñ(5 ŽÖVÄ(îÀìÄ€Ë ̱-áfóöU…ðô×9Ë!ˆü%â¹ñ¤ººÚª‚[ÙÛûhð¦ýag¬›;KÜf„…,y£Ihkp¹Üô%Û}ã.Fdž |›)¾ƒ<Bû`¼µR’ãD ?¢®\„Šª:ö9…Çîáü©¿¨v4:~ÇÏcËú•8|`'öl£>SÓÐÂÈñ“›¼o7¯Ýp[î·eá›}ÿĉ@‘v= û`ÞÒU8|`'œfN„4ƒGçµàr¹Ø¿ÝƒjW\T€ +EÖM¼‹Ä{±~"âYBR ¾GNÁcÕbx¹.£–¯XçõY¢ÏÍk7Ô4~À‰£þXãô+µI¶³›¼-i›}ÿ„û*'8;L£Æ! 4vㆴ¼€:r ;ÜWãtH Nýp>TTÕaÜ õ÷‘;ë”&žË)vD<·!‚_7éì¿}½Ó˜9v|–/ñ©ùöì?yÇ".cã¼_!ݱ#‚".ÃÊe-âýA§Ñ°dÛn‡¼79””„bg•¯~]÷ÊZ Ë™µgjê’7Ïl®]=öʽx¿+±ñ6#,°ÌÖš˜¶"l\7ASE;– Ê˲XЏ «qHLIÅÔ5søUé„UƆñLø,w‚å°^µš*Ê æ<ûüŠØ±Í­¬ÂÏÓç`ád+,³µ¦Ú,ôöAv^>.ìÞ gŸ½¸‡GÇ€D¶>²òò±ó¯PDþýO¥‚œÌÁsòÖ·°ˆn©g*dæùSD󫫇””–™»îõ÷ð :ñ“çB™1MÉ+OB«ƒÇÿfãÁC7ž¿Ô¿ººZÀh|Ge퓦# I©/…µiì¶ZR¼5÷¶›KèÒèôfë¶¶B˳t§ï1&ƒ!smÿNbüÙ ±2—]ûñèE†ö5Âp“¾”°½ÿ,ŒŽR¿yGd&ƒ¸äg°2°IûJËÊ«Œ‘¦&"ËG›õ‡£·õwÏ»áÜJ¾(™6rXÆÔ5gè ADd›„ˆçÿæÏü¦ p¬ãæÞJòr‰ˆ&´RѬàWÑddÐV)çp†Tp¹žæó—˜¯°›Ví`5NŽ£ÖƒíÈáÐTQFøÛ8w+ûBO£›¶¶ýŸÈÎuùlô3zêtmò¾Jj<$>Îq'áûm‡¢Ò²öî›ï×øïœàÞ–‡ˆçÆÁ{ÿ>âMAá„…[vzþ ÚEÎÛiò€Þ=%ÈоÅûN†_Þvô¸ïý{5n‘a!B;€ò¡Ùì±ïÔiS’B×zˆO~ åÎTØõý穘æº'¯EA¶4 Û—/qAIz5%Å&ïKWSPª*=ûµHÂóŒL" [9íÕGŒœÚ&s®ŠÇë•–•½nÚÚ¯Ï[’ý÷Ã'•dX_Q4ŸÐ39kóῺñÞ¿w0”g@ ´Còø|Ë’Ò²‰k|ÿxÔkÚ¯ïB._/În¾ ›ÁãÏ@j–Y(je;10v )¸••ð £ÚG?L‚õªõHù7 € >0›ÃiÔ¾”åå`fØ>A'À®¬“û®GÎGª‰!à„¯CEeåëùžÛŽw0q1:V˜J8íĸ–†}tvâ4÷^ºº¼/Pï©Ó•¼%´ÄW•sêÚ‹«÷ø©qªª¤lpŽŒK»†„ùÞ Ã>9Nÿ]I–©KRè¾RÓ`·îwHJˆ£«š*½Hƒ™aOÚ°t ѱpÙ½ L&™2xô"ŽÖ°vÎL€_ø9x¼:²N®rmÃ0ÈÈÉ…½Ç䣛¶î?OÁ`£Ÿq` ¥àì³YyùT{·á£TÂÇ„g ÿ5 #7âæÑN411·Þú?UMh!Ѭ À@ "ž‰x&ˆxþŽKóV’—ëìå4_a´Y’B÷•áVVáþó¼+*†ÞZè¦-jâÇ®ààÞÓgàVVÁð'¨~²ý(5 ܪ*ô馇CñYelpªª ,/WK˜ññèE:^çå×Ù_!‹ÿ½H{Â×ÍüâGÖˆæ,*½|Kÿ"žÛRˆÓi®Cúôæz8ÎÕÚôM½Ý~ð(r×öŽ,6»khÀ#CCÄ3ÏÏÀ qº—V—.²Ä‡†@øêÔöß)€`¦ùV;~¦"â¹éÀ…N£-77îÍ""šð™¢¹€-öÑLÄ3ÏߎÚu……´D]çæ¢àmŠ  «ßã‹ù{©£LÄs›g6MLl£Ž†šÄæÅ º˜ö$ÑB‹Ñ³ïdØÙÑ̰@ÄwðLEÄóW@À2q:}©ÕÐAånö³4HH ¡!§½¼6k£gE^AQ;øCàNH ♈çoHNv&Æšˆ, D_ÓA­®¯ål6,ÿŒ‚·yð¹“æ ¶MIN‚¾á'ÙÑy-8»’‹€ˆç¶€¸8ÍÝøÐ-"šÛˆÿN‹Šgâ¶Ý²p¯âñôO]‹ ë;ál™Ïžìü¢b22Ñldg~äb£¼‚¢ºð%™@h(uVF@h$B#1gÑŠVßߊò2×pÀŠÇêŘ6z9¹„ö@`U_÷þ³”£—¬,´\±&+9ýá ¿[á×£Îü8~ʃe>{{sªª0Âwj\Kê<Þpæñù[O]‹Z}îVôl{ËÑÜå¶S»uß/ÙùocìÖyä¼ÈÌ%V¾š IDATÀÀl^¸„V„„¤5Ëœû:³U÷UšÁÀ©kñ(.|‡†}lÇç‘LB»Ѿü÷ïýž¦,½ì7WsâCC |Öwé£TBâ¿CÄóWç çʪ*_¿ðó‹œ4w˜r"¢¿[Ñ<@<€^¼`!_™ŒôT)ÉI(x—¾ÿˆ°àÃaÊb¼µ2ÒSq=ò̆ û¤ˆ'Z_èzü}—[÷.ÚϘí>ÿWu"¢ „Os÷aRļ߷I°ØlÿHþÌ·E€›´””år[ë÷ó&Z*}\ëŽÐ~(b•>¶÷ðNŽ{òÌÀ [k^¨$çùy&nË@£Ó¡ÒE ¥¬”²J`ÔÏ~ÇÏ×kv!,V86˜ó|üðìôtƒš†”:« 9)•\A†š†"b’‰÷bñ›ãL¼Íƒš†Þ½ÍG%—ƒ‰¶³±aë>j{þ»¼á·k3ÎD݇Ó̉(.*FG)«ó–®Â¢•ë4./;!ö.æÙŒùä˜DÄ$CMC‹ÚžõŒ¹xœx¯j~qaúšB@h$Õ¿;7.£«®þ¾u Å…ðØé‡žnàóxàóyˆø;r Šä‚ûHÎs³@|h¾€+×ÿäF™õÇHS“VÝ×+±ñ¸“žÝa;Rð’1-ë5üÂÏ!#'ŒŽR;Ð SG %'ö#Ú‰ÿÉynǤ˜SÎá ñ>üw)3Jö…†¿ãVV‘‘ig¢yâʵ' ¦ÎR{òŒÀ€3ηEG¯;üC. æY."b’õ0s­@â½Xœ;Þäíee¼ÄNO7Œ²´Æ™›÷q8ü*B/ÿ I)Œ´´¦„s)«+æÙB†)‹ów!"&wŸdÁrŠ΄"4ð`mÏš`3óˆz˜ë÷ÓÐðý÷ œÍ¦„ybf)3Ká±Ó¯Þþõ5Dµ±œb'ñ5 Ô4Dkµž9ii"cž êa,§Ø!!ö.bï~ø,å)^¥¥âzBTTÕ±}ÓjÌZ° ûA9›ÔgÉÅFh Ôñ¡Y¾s_.ñ¡iñOž!ôÚMDNl OÓ3îÿ"žÛOª««­*¸•æÞGƒÿîmgÿ.øòµŸOF¦ ÃårÓç{n;n0u–|-Ñ<@áÛ£o`“æÔ 3N§ ÁR’“𼽇 ±àóx°œbG…5këèÁÀÐÄSí.„£¸°®ž>ÐÔþ€ ¯ÚmónÈ)(âü©à:Ûii ·Í»!!) I) k…J.Yé-:F= °ïØ*ü{¼µ@t×Îý®äràìæ Mí!!);û…PT¬“—ûš\l„քЇ槓Wo„šÌš_äpä «ŒMF¦â~ L&ÝÝ0Éb0–ÙZcü_ávßûyÏÎ3dþ’°áNÎz5¢ù'ê5—‘+§~HÎsëâauuµUIiÙÀ5¾xy:ÖcÝÜYâ6#,dé4Rm¡-‰æ%Û}ã.FÇZ0À22B룔U‚øè[x•ž*b¢% µn r J€ÌŒ—T‰(>‡¼Ü×Ôgôàht:ŒûY_BR FýLqçÆå:ÛþØåÛÒz:zõî 5ÍZt| Q'º>j‡‡0Þjk`µ¨ãCã0q|å2›ÉJ߫ͭû‰8~ù: KX †6óù|ì?yQ ‰”ÇBk+ ì-ðjàñùøóìED%$‚ÏçCRBÃû÷Üñ£|§ž2b(RþÍÂå˜8€Í L²\§MÒ‹t\K€¤„8lFXÀrȇ{fôÃ$> VªJŠp°‡Ÿõtë=®qƒL1ʬ?j?Kkª(ƒÇçƒÍáà{<߽߯»?}­û+â¿CÄs{!š_]=¤¤´ÌÜu¯¿‡OЉŸ<:ÈŒhJ\ÅZ1<þû7ºyôü¥þÕÕÕBÑüŒ ÐJ¯F`ÊàóyÐïaøE&a`6x4µÄ.ϵ¨`—AS[gBŽ"';+Öm¦Ú¼Íƒœ¼b½û“aÊ6Ê [±³Šˆ@øl2Ì©âñ¼†Ÿ[xáÒ¸ïчæôÍ;X¼m%,ó‹Šp-.o‹Šà4uÕ.àì0 0:J!-ë5î&&áêþ覭…þ‡qä|$˜LtUë‚ûÏS•:M 3ÇŒ¤Â©ï$>·² Ê rxž‘‰»‰  +sc#ªMTÂðøï©6Q ‰è¢¤ƒî8;ŽÞ>”GÏ»âÜíhœ»°m¿ÃÄ {c376ù›]ÁÁîã§`ÜMªJß—ÃGþ;w!Ï&i„M€„m·òg;Ÿ?øMA¡ƒãæ/ûØÍ}KâŠZ¡hvû#àøã¬ÙGÎEªUWWÿ `"ÎBëÆ}•äq9.‡Ã¯Rµœ?—§I‰ÈÉÎDÿCq:$Û7­By9{ކ‰¸l«¨ª£àm•¯\›¬Œ—PQU''‡@øú¤ñß¿Ÿ]Û‡fÿÉ3Åß‹GÀÀ1uˆ ôGØ6O0:J!>ù™H»n?h!.ÐwöÁ̰'x|>¢&Q¢{Ü 3Ä>€ »·ÂÍ~àÁ³T‘mHJH .Ð7ý|1ʬ?àn¢hªŒ‚,“j3Èèg‘6îGAëpa÷VópÏǶÀÿöª`Wp`·Î…,mtý~DsiÙ â¿Ó<™ç¶Aïýûˆ7…nÙéùƒj9o§Êz÷” CóM)Þw2üò¶£Ç xïß«pp‹ ÐF¾À…R¯‡âÄQü¶p&ì¹ “ Ùÿ¾Â°1D^&´wo^¦ú|ˆx&´Nòø|ËÚ>4æÎ–ž2b¨t{Ñ%5Q0Râ_¦¾ùHö…ž££Ì {¢›¶²òòë´Ó¨ÝŸBZêÃ}˜Vk¼ X‚ò‹t > – …ü€]ŒŽ×¢ùí^8WTV¾^¶m÷mâ¿CÄ3A@ ÿýûà´¬l;»õ›Ü{éêvð^¼@½§NWâ*Ö¢tàœºvãâê=~jœªªnÖ8GÆ…@h›xìô‡ûoNpv˜&¹:zØì46º8Š´»u5~»6‹,;r`'õ»P˜ýe,öxo@E99ÙÑú.?gB±»<|ü0f¢ $$¥pòŒ˜[×–òTp#VPB_ÓA°™=¿Ùf¸ D<Ztvââ4wCâCChaÑ\+•PÀ&ÿ"ž ÍŠ7:æ0Ñbp1Ñÿ)šÍìà ŒŒ ˆg@Ä3¡ "Ú‰&&æfÔí'Ž·ÓM®dTÍ/üzÔ…ß|ÿPáTU)ƒøïñLhqºX-!.>ÛÞr4w¹íÔ.µC_¾W²óßÆØ­óÈy‘™=€_Åär!ñL ˆx&|&RÐé4WsâCCøBÑ\+•°+ˆÿÏ„¯Ž6€âtú¤¹Æ”¯"º–hà(/ïÈåA â™@ ñLh&(š¡ýŒÙîóU'"šÐXî>LŠ˜÷û6 â¿CÄ3¡u  ÀMZJÊr¹­õûy-•SŠ ­SÄ*}lïá÷ä™9€¶xC.ψgB A|h†øïñLhÝôìСƒ§”„¸¹óô©UíUD×ÍÃ\à ƒœ~ψgÂW‚ò¡™4̼t휪DD„4ß+ćˆgBûf,]LÌ[I^®skщæ,fš£Éé#ñLÄ3@Ä3¡@ùЬ°›Ví`5NŽˆèv$šKË^Ø»o¾Oüwˆx&|L§Ó=Pí"çí´@y@ïž­¤_ÅûN†_Þvô¸ïýû‚šÑ-rºäFOÄ3@Ä3¡Ò›N£y0¤;š¶'šïâ¿CÄ3áûf6MLlcWu5ño,¢k‹æÿ³wçaQVoÇ¿Ã̰!"‚"˜$š¹§A˜€’ûnîIn¡©‰Rn¨¸‘¦’ššûš+îkú£\IÒ47Hߤ$qÅEQvÞ?žaEEEd¹?×å¥Î 3ÃyÎÜsîçÜç<©À(`§!^’g!$y…„~š1½¼‹}êåQL’è‚ãaRÒåASfýw$yBt5Ԫǽï訚4À§¬s‡<Šæª„õ!¿îöÃ<Û„ääbÀX`«!^’g!$y…”»F£™`UÜܱ íCSTÉþ;’< ñ¬$º¿ÚÀÀ¿ú»¾Þ$:KÒl L–Ë!è%yB’gQDè÷¡ ìÿ…e׺†Ò$ù)iN½°`É.ÙG’g!žÇðÑjÔ#ê׬ž8¾o¯råmËäZ,:ðç©]>SMââãtIó* Eš]H —äYIžEÔÊP« ,Wºtñ|¶MQ%ûïHò,ÄK1ü4jµ¯{­êq¯˜DgNšß&s$iè%yB’g!Ý>4ìl ¿àSÚµª³,ˆÎSª„ÙÁ¶Èþ;’< ñª,€AZæ«Öõø÷ìng]Â"Ç?|&òßî^¿[˜Ì¤Y…zIž…äYˆ,4@W­V=®jžïCSt“fÙG’g!^+À_£V÷nãùñç%Ñ™’fW`6Ü—fè%yB’g³‰ç&ÑýÕþ5*WL˜ÔßÇÞ©‚ƒ´JîJÙøË¾íßÌœk#ûïHò,ÄëTf¨Õz÷lÙ$Ñ·s‡Òæf6мsãp×Q㯜¿xÉ ˜ÌîH³ ô’< !$y/ÄðÑhÔ#Üsš"›4Ëþ;2¦’äY¼ å­FÓ¶W«¦Z»|qàÔÏ_¼ÔX†rÑø›ÒLB½$Ï"çRSRPk4Ò’< ‘™~jÅûâó²’D¿¸C'Oïì3aŠ¡ì¿#c*IžÅ›äø]€ï€kÒ,B}®»ŠRù!„(Ø®’ùˆ—ñJûÐU²ÿŽŒ©$yE®s !ŸQ¼JIS!žA¿MÛî÷FöèVF’è'ýõOÔÁ®cÆß‘ýwdL%ɳ„Aù,ˆÂgШDJs!žã™ûÐU²ÿŽŒ©$y’0!ŸQø=’ÀFi!D•G·Mï6-’ulgU“èË7oï2rÜÙGÆT’< I„Ï‚(ÜzKP6¯™øJ“!^£ÚÀ`´‘¡asßÎíÓú´iied¨-ô¿tlܽ3=ÇOŠ8~ÖX‹ì¿#c*Iž…$ BÈgAj(kž3þí,M"„xIÎ*•j¢±¡Ö}H×Né½[7·(ŒItì½ûç{Žûöø‘ð³ À8 J¿Œ©$y…±sOEÙðb&pò)Ñèg!QH …Xi ZóîêâžB¼Šêµz¼i1—Q½ºk;zyרÕþ—JLLügàÔ™Gv„†} ü‚Rž-ûDȘJ’gQ¨;w;`ƒ.qþ€ì¯³ç‡rIe(%BHò,¤ÿ!Ä‹qS«Tff¦ïéå]ìS/b1‰~˜”tyДv„†y¿£p9¼ò(ɳ(*{=Ћ2³œ™#peÍÊûÈ¥„z!ýG!^…»F£™`UÜÜqb¿Þo5us)»Š¥¤¦] X°xï²m?×MOO?£3ž”Ã)߉’<‹¢Ö¹­€³(å‰ïç2Ý·p¼€ýOùùòºäúYº7Ó=ÿ%9DB’!ýG!h¦10˜dU¢T`ÿ/,›¸Ö5ÌŸIsê€Kvé’æh”™æP9|ò˜[ ¤}Es苲Îo)ÖûõÜÙ$ÎVºÇ>.÷€í(3Õ™5NèîÖý½P÷óB!„EÕΔ´´ª×nÝîÛoÒ´ó÷xé·“áIùèýÝ™¼qí;-:D/ݺË6==½7à!‰³Èmr¦Z¼I¯rf(£|{°e6:’'×B›èåɺĺ20Jw¿ ʦbŽºç8¦KÀïQ.ý²øT—ȧŸ!¤ÿ!òš·ÚÀ  ‚­á·|J»Vu~C ¢U ³ƒ7l™²lµSJZZªn|·S|'Jò,¤sg•Q¾­A9«ØP—?¾žÅ˜tÖeºÝe–yЇG} K 3,D)õö’Ã%$ùÒ„BOtÕjÕãª::ª& ð)ë\Á!’hUÂú_w ûažmBrr1”½p¶Ê!’< éÜO—±û6À×@P69ƒrI—RÙ܆2 ]"Ósí×%Û¿ñìuÑBHò#¤ÿ!„’D÷Wø×¨\1aR{§ ¯ëµR6þ²oû73çÚ$$'[ëÆlËåIž…tì-Ù_º*Y÷wv›Y¡”u—B)Ó^´ÖÝw_—HoVI"-$ùÒ„♌F=½fõÄñ}{•+o[&×’æžÚå8Õ$.>ÞA—4¯zÊØOÈw¢$ÏB:÷S\@)«V=ã5¢PʳŸf¦.yøh…R^[wÛ9”’ð;rÈ„$?BúB<“à§Q«}=>¨?î‹Ï˾J}èäé}&L1Œ‹eÿš9’4 Iž…tîד<ŸE9š]ýÊîÝ (%GåQ6Ë`Lºéþ¬’C&$ùÒ„"G,€AZæ«Öõø÷ìng]Â"Ç?|&òßî^¿[e_šùH% xÃ߉r©*QØí×%Å­»Ý e=ôÝÿçÉzùª›ùÊï¿+17?¾VIÓ‰"è%‹¼ê?í€ ÀIà”Ë>Θ,úH !ä;PH’Ž*^¯ZµzžS…ò¦?÷+SÞ¶ÌóŸ²ó·ß·÷ œZ>%--è„K3 ôBäzÿY´Æã»¯2p¸¼Ü—&BÈw þ$U¼vÓÌŠ™|2}ð“&}hü"?œ’švspÐ?oÜ{  ʬG  Þ„z!rµÿXg3 p.Ó}a@mÀ}ÊÏ—×%× Ïx Ýó_’C$„ÈÅ6UÃf¢TÐdG£{œÊ Â(iféO¹AvÛ¹I ÓhÔá}Z7oxjõÒ/š8hÔV³†ú~öçš%Q¶ÖV•u¼ŽÒ¼B‘kn}c”uÍ— ì|ÌÈ&q¶Ò=ö!p¸l{\#”™ëX Z÷¸…ºDZ!^ÕïÀçÅ®Ç |uÿ–ÄYä™é¹åEK´s*£”»rJZÚe` YgH„( dæY¼©þ“Q¾Ý؉r²2’'×B› Ì8Oö£”wÒÝÿÊ ³£î9Žéð;@s`Ê:ëOåp !r!†=kéIy]’¥'ÒŸ$yùÎ+•hç8ƒNM»ùåä _v:Ü)åè…È­þ“Q¾­A™in¨K„ßo˜tÖeºÝe–yÊÆb} K 3,DÙµ»‰.!D.İg-=Ù¸^('ú²Så„_Êöz’ IDAT3^ÃL÷çš"Se²mñ²r¥D;Ç/¦6°ZàÿM§?V.ü¯´•e5à ÐJƒB¼’Œòm ”âQd¿Qc'Ýc×=v{8ÊšÃöºÿGéþž4@) G—XKâ,„ÈíØ•ÝÒw”Ê—ýÙ$ÜKQ–’\@Y‚ò¬¥'÷P.¥š±ôD.§*d¦C¼”×U¢S)Û„îðÝôwSÒÒþC)厔Ã" 0™yoºÿD£Ì ?íy’ug·ùWiݶJEÐz µî¾ûºì”K&ÈáBäb {|éÉ”“x.Å›Œ¥'ŽÀd”Jg”Ë£¢{|”îþ3('gè’tYz"c*IžÅKQJ´ML¼¾Üߨ©›‹é›|3)©i×zŒ<ðë‘?óPJ¹e`&$Ð é?/îJ£ê¯…Ržý43QÖ8ƒ²éX+ 1P]wÛ9”rnYr#„È­–ÝҞ܅;céI7”y^déIy”Rp!ɳϤü´õˆÏ[4MÙã³RF†Ú|󿢮^ý£¥ïð›7ïÆUA93¸S™@/¤ÿäjò|A÷·C6÷Ù¡ÌÎ$è¾/ìȺ»­0 ¥ôûñ5ÓBñª1¬ʬ0(3ÉAÙ<æ„.6•Êæ¾0” Kdz®ýºdû7dbFÆT’<‹Ð@«VÏ«òŽC±y#†Ø¾íœJY³ç—­Ãfέš’– F.M $Ð é?¹•<ÏE)‹lNÖ”¥y´«mà'”™‡Çbp+”ÒíÞÀb9dBˆ\ŽaKO´d¿ ØC”“{Ù-=±B)ë.…R=#KO¤?Iò,^X¾*ÑÎqý¨”»JÙM:!ɳþóÊɳÊzA3”MÅ~* \&¦:ÊšÃ(;ÜîC)™œüà„²Æ°4PÙ¹V‘÷1L–žH’äY¼ùºD;§ÎG_:ÖfÈȸÛ÷î•C)åÞ#‡VHò,¤ÿ¼ôÀ”²ÆY(k 3\†“u aW]²l—é¶“@?àw9\Bˆ7ÃÎëÆ¸Ù-=)­Kš3&[ɺmæ¥'¯™’<‹"¬ ”hçTÊŠ{¶œ3¿ZZzúŸ(¥Ü—ä0 Iž…ôŸWb¥\ÞäÙW:(¯K #‘Ùf!Ä›Mž3–ž´¶>ÏÎë’g”KY}ŽR%“9¾e,=Ì‘C&ɳ(Ú d‰vN%$%_ï1îÛƒŽŸôàQ)wŠv!ɳþ#„E"yÎnéÉÛ(KOjóô¥'@5Ý¿í¥'’d€qa+ÑΩ‡II—»Žä÷ðW”mæ ¥ÜB’!ýG!$† éO’<yEªD;§þú÷Âá6ßø§Þ‹Xe'ØPé*BBúBH ÒŸ$y.šŠj‰vN¥ü°fãöïV¬ª“žž¾¥”[Ês„ „ô!„&¤?Iò\DH‰ö ¸ÿàáån£';qö#”]¥”[ÈÀAHÿB‰aBú“$Ï…˜”h¿‚Óç#Ã>6†{jÈΊBBúBH ’&­"r‘œu/:à¤Q«}ÝkÕ¸×ÄíÃsãæ/%.>þ}”Kïͤ™„ÄŒ©$yèK´çûmë`[F-Mò:©¾[¾j÷k7|žž¾¥”ûŽ´‹äYäcÀG£Qp¯Y=q|ß^å2U¥øóÔ.ŸÀ©&qññ(›®B6=BH 2¦’么³¦š3iøý†ÍÝ\Í¥IòÎ{÷.~:,àLÄ¿j£€ÅÒ*B’gñºœjÿêïV|8uЗå*—/÷´Ç¦lÚwpÓ×ß϶KHN¶–¨Bb˜1•$ÏE•”hç#¡'΄y 4y˜˜˜€²+·”r IžEnÇü®Z­z\UGGÕ¤>e+8ä°ÂH•°>ä×Ã~˜g›œ\  l•&BH 2¦’ä¹(í|I•0ná’_lÚþAzzú`RÊ-$y¹0àT8”µÕNõý²L]§*/óïÏß°u[à’理¥¥ÊT!1LȘJ’çÂLJ´ €;÷î]lûÍè¿ÎEýç G)1B’gñ¢Zj5åJ—.>©¿õGÕ s+LÍÞ¸{ʲÕN)ii·PNôí—æBH 2¦’ä¹0Ð~jƒaÝ›7º?¦w{)ÑÎÿüyrÿçc'•LLJº‹²+w¸´ŠäYädÀ©10˜`U¢Ôä}->ùðƒ×uÉ–›þsþoÙ¶Ÿë¦§§GËT!1LȘJ’ç‚®ÆÀ`nÅ·íµ‹F³—í‚%%5-a̼…{–ïØã–žžþRÊ-$yOç®Ñh&X7wœØ¯÷[MÝ\Ló(N] X°x¯nzF§NÊáBH 2¦’ä¹ ¨xž¦&&u¿2PÓ¢žK‰×ý¢Ñ×cÙ‡KU'\«:çêsÇ?LÀÔ$û¡'O³e(NèÑ¢É+ÐT4j5‡O‡s/þ\ê¼Ñƒ´r&ÆF7Öì9þÏ¥+5€CÀäì¨äYèœj•jœ™™é{£{u7êÒØë­7ñ&’SSÿë?)è·¡ažÀï2BH 2¦z:iß|AL¾w­êì¾ny©¼Hœ3’ç •k ;‘«Ï;'xó6f¿ŸCÜýxºøÇÔÄ[«’¯üZŸôÂÕ›·;ÁîÃGÞø Z¹–½G—:´hNãnM>¹´G¹¤UeéîBiÕ5jõ¶âo™­Ÿ<¨_µ3k—Y½©A'€V­~{Á¨¡].l]ßÜÍå°X 8Ê¡BH B’çü¦ÆÀ௒ŋ×èàåiYÖ6GF_~ê}wããIIMeœOÏ\™!>u1_·Eí÷*¿ àho—¢R©BI€™t}!ŠÖ€S¥Rm112Ü?Ì»ËGgÖ.³êÚØ«¸F?VåUX0jh—ÿÛ´*®®sc L B‰aBHòœ_ØkLMLÖÌñµÕç-šX<ëÁ)©©øÿ¸‡–°m܆Ž#Æêg[ûM ¢®·1±wômòÕ7´ð@L쾜J¹fíqhÙSfÿ0!GorÞÆ­8wð¦zç¸öü’ýÇOèïÛv”ºÞ>Tï܃ZÝz³'ì(‹¶ì`GèanÙ΄E˳<ßÕ›·hí7€ºÞ>?÷·þýUnßÊí»ñEàTýï²34Œžã'Óä«ophÙá‰D¹ß¤ Zûdgh˜î÷¥ãˆ±Ø6nƒsoýí§þޤÉWßè§§ÍŽg´›w@ åšµ×·yôõnÇÅÑuÔxý}Õ;÷`ÓÞƒÏlËVõÝ*ÿiaÜÛ¶¥ëgvò1¢ÐsT,/flüëˆÏ»~ô×ú•Åûwhk™_œ{«X±÷6Oû¶SDðŠ«ºè!`:PZ¥Ã$† IžE^ÓÃÔ§{´lòQNK´§¬XÍÒm»èÒØ‹Àþ_pê|$=ÇOÀ£vM¢¯Ç°iï@YO|êïH\ª)k˜¿™1‡Ý‡à×­¾;°õ@(£~\øÜ7{‡ï–¯"äÇï9¹f)¾?%pÉODüsS¦3Ýo '×,eÉ˜á ˜2ÈèËônÝœæn®ôi݂ѽ½³éœw@ ûŽ`PçOæÝ•°Óá šÀœàÍì;v¿nÜŸ”Ô4Fþ¸à¹mZÚª¤CØ’¹žKF\0Ôj¿~FΊ Q(œÀR­Fsü‹6-ŸZ³Ôr@ÇvV¥²¨„ù[ïožöm§«—üW±œÊ ?€ !1Lb˜äYä™*UÄ»o—ûâà¢Ùæ_~‘ãËOÿo/–ææôm׊†ujѺ¾§þŽ$2ú2­ê»anfJpÈ^ÖýOùû³¦¸GÈ‘cÔ¬\‰¶žÓÖócê8UaËCú¶žÆX«¼·y·r4â,m=?&dÎ÷l=J§*ØÛX}=ËâæÔqªÂž°[ow?ž}ÇN0¦·7F†ZŒ µŒóéɾc'¸€u :7jH­Ê•rôœ®Uq«^€F.uô³Ø‡NžÆÈP‹[õªD_!%5•Æ®uY§k·Ì"£/sêïH»Öů[GunÏŠñþú“£{{¼œ^Xš›cjbLÜýøÿÞ\êԋܲ¶\/Ïd”Ò¢ €±|D„(ðJÓ µÚ£}Ûµl|fí2óÑ}¼­Ÿ¶yb~gcY¢î³Ú]±à/ÝôXÈ¡Bb˜Ä0QÔh¤ ò„0ÕÔĤÁ÷ƒ´øØõ…wÉÊHëzû±8qö‰ŸÍ(û~s3SVMÃü[é8"Scz´lŠ_·ŽÜ¸}‡sQõ3±/ën¼’p–·-£¿ÍÞÆ@_ZndhøBÏi]"û‰üèë1Ä'$<ñž*8dÓÞ±˜?ú²p¯UCÿï£gùzÆ"£/ãTÁĤ¤ÿð© Œgø l1¤[§ÈöCý?ºtýÆYÀØ*! ä€s˜F­îÝγ~Üè>Þ%,ÍÍ Ï—˜u)× fq.*zogÿ€š×oÅžf3‘Kñ !1Lb˜äYäRûú© †umêugܽJ½l¹‹u RRÓVÖGF_ÆÜÌëʉ³Ïš6bé¶]|=c‰IÉtiì¥$º3…õjTcݤ±€Rrmoc¹™©>¹ÎNÜýxŒ Y>ΟĤdö?Aq“hææ‚¹™)µª¼Ëÿoô?u‘âf/vy¿â¦Ê㣮\Õ'Ðï)·ÏrÚZ•ÄÒÜœ S&dM¨³Yÿ‘€_Ét‚!hå:““Ú½ ÃgÍ#&öÇW.¢ŒUIZûÔŸàxQålJ9]¾Àqó¾Cû|§Íœ–œšÚDÉGHˆ|ϤÕh¾jíQïÏîfÖ%, 톀•ËÛ{žXµ„3‘ÿ†t˜Xóú­Ø3À4`> ÝA‰aÃDa&eÛ¯O–íÉú:ä$qž¼‘öCGgùЮ;·ãâ4‹5{~¡µßH<}é¿ÊåËQ«r%"£/c]ÂB¿‹µ¥¹9µkpèÄ)‚V®cÑ–4ùê:ŽûÜ÷råæ-Úʍ‹jy»Li4j5ÅÍLéÐЃ#è7;u‘ƒ‡ñÿ=ÚÐëÒõ}éõÓ˜›™Ò¼ž+ã-'1)™Ä¤dæ/Á£v rzÆÓÔĘÓçÿyî&hîµjp;.Ž9Á›eæ½ãˆ±üzôØu´/K­Ê•8tâ_Ïø‘€ùK˜¹f=žý›ŒM2mZ³ä'º4ö"ó.ˆÓý¾bÔ ™¼‘ÔÔ4\ª:3k¨/ ”DÛÛXg;c\¹|9Æ÷íE§¤¤¦ajbÌ졾”±*I«’ÌôûŠ‘sr;.c­–1}>×—6·rwÃwÚÜŽ‹cù8ÿ¬N­Ö—fLü²£~\Hµ.=ð¨UƒÉûêã2Ϲt/O|ƒ~ ðË/(nfʃól_+£ }ì¼ÅÌ ÞDjj*]{áÓ®U¶Ï»8`ÃgÍÓ¯%¯W£*Óý¾`LŸÏñ›>‡S¦S¯F5z´lÊîÃGˆøçÕ*9bocM)Ý©‰ñSÛøqjÚìÇ~M†÷ìÙö둟\¹qós`°G>ZBä Æ€F£á^³zâø¾½,ÊÛ–)²kç\«:µ:·qeÊ?Oíò œÚ,.>~0X¤HwBb˜Ä0Q˜¨¤ rõDDæm‡Âp½fñfmøõÀ¿ïg½œšzŒ”rVé Æ€Sm`à_ýÝŠ§ú²Üã»ÿ R6í;¸éëïgÛ%$'[ËT‰aÃDaSÉ`-w40P©~¬XÎ^³$`øÛ¶eÔÒ$"·$$%Ý4í‡ÃÛþV˜ I —@/òŒèªÕªÇUutTMàSÖ¹‚ƒÄøg-Ö‡üºcØól’“‹c‘…&1LHò\äÙS‹{N2Pý2»h ‘S®\û§ýPÿkWoÞ.‰RÊý«´Šzñzœjƒ‡²¶Ú©¾_–©ëTEœ/æþü [·.Yñ~JZZª @…&1LHò\t’ŸÚÀ`X—Æ^·Ç÷íUAJ´E^YýsȾa³æ9¦¦¥ý|\’V‘@/rU+C­&°\éÒÅ'õ÷±þ¨º³¡4É+¹3;xãî)ËV;¥¤¥ÝÆû¥Y„&1LHò\ø5P©Ts*–³Ó,3Âî²eŒ¤ID^KHLºûEà”#¿=^å RÊ-^ä€Sc`0Áª„E©ÉûZ|òá²ëjîºé?wáÿ–mû¹nzzz´ @…&1LHò\xéK´¿<€–õ?²–&oÚߣÿn÷ÍèØ[wïšý€Pi ôâ…¹k4š VÅÍ'öëýVS7Si’×'%5íZÀ‚Å{uÐ3ºèIi!$†I ’<|R¢-ò½å;÷5gÁ;©iiPJ¹¯I«H ÏpªUªqff¦ïîÕݨKc¯·¤IòNrjêý'ý¶#4Ìø] BH “&$y.ؤD[ñÞí8õýÇNTG¹¼Â¤”[½ÈNuZ=Þ´˜‰Ë¨^ݵ½<‹kԲΛ’˜˜øÏÀ©3ì ûø"¥e„&1LHò\0H‰¶(°þú7ê|‡áwoÇÅ}PΆ IžTW©Tc µîCºvLõi×ÊRœùǽþê>fâé#ág;d*„Ä0‰aB’çüMJ´E¡1óÖC®pLMKÛ ŒnJ«Hò\D9ª F6÷íÜ>­O›–VÛ󝨏{gzŽŸq$ü¬;°øYŠ"$†I “&$yÎW¨Tª9Žve –ŽYNJ´EaÿðáÝ^¾;rðÏS5QÀb¤”[’ç"4àüµMÛÞ­š' éÖÑÚÔD6Ÿ-(®ßŽ=Òaø˜èó/5–ÉTH “&1LHòüæÙSMŒŒ<¦Ö²¾[i’×/8dÍÜ\/¼qêïóFŒK¹Ÿ DJ¹%y.ÜJà µZïž-›$úvîPÚÜL6Ÿ-¨.ÅÜ8ÜuÔø+ç/^ræ3;Ò2Bb˜&$yÎ;úíNŸxÆLüò‹w¥&ïØ6nÑåó±·‘åäy釵öOY¾ú½´ôôM(¥Ü¼%y.tNZÝ»gý¸Ñ}¼m-ÍÍ¥U ‰sQÑ{;ûÜ¿~+Ö˜-P!1LH ’<ç )ÑEÖÝûñw{|{ì÷ˆ¿œxTÊ-$y.È,€AZæ«Öõø÷ìng]ÂBZ¥:ùoH÷€‰¯ßŠ­ Læ Ò2Bb˜&$yÎ]R¢GNýÉ÷«Ö±|œ¿þ¶Ÿví!î~<ý;´¥ýÐÑü8Â넞<ÍŒÕ뉾ƒ‘¡–Æ®uÙã3iÄ×~ŒÎGt16ý^üƒû(¥ÜǤU$y.ˆNZíë^«Æ½Àþ}쥚¥è8|:bkÏq“ŠÅÅÇ¿L–¨&$† Ižs‡”hç±”ÔTjwëÍ‚QC©ãTמ_òmÿ>¸×ª¡/Û624¤®÷Ìñ5\êpüÜßtÀÒ€¸U¯* ™¦þ´úÐÌÕÞ•RnIž cÀG£Qp¯Y=q|ß^åÊÛʹТúusàÏS»|§šÄÅÇ; \ã~²1¢&$†É˜ê50( Ø@¥R…W´·ëu`áìbS}ûKâœg+ÔjÚ5p'8dG#Î’˜”ôDBljl̆)iäR[«’”·-Õ·¤óÈ7Ÿu©±þ'£š•+½œºJ«ˆ|<à¤60¸X«Ê»Cþ7û{›ãGÉ ³ˆÝÔ¯Y­å¹+=fü§±Vû….Žy£œ8Bb˜&rMažé°¦º ˜ÒÆÝÍNwÞ:u‘öCGs|å"æ/ÆÜÌT_ŽyðE[v°.d/Ñ×cp°-ÃÕ7Ù³;¼<¤óØï§#Îzû6õ^üƒ;@? \Z%OÈÌós@W­V=®ª££jÒŸ²ÎÔÒ,"›aMÂú_w ûažmBrr1`,°UÚEH Ã^»V@k`Ë3ÞsÆc¾nÄ1UaœyÖà TªS5xÿìú•¥%q~3*—/‡}ikö„aËP:4ô|â1Û„2cõz&ìKøºåüüÃT,‹ËÎ’oʇUªü߯U•ûwh›¦R©öÓQÖd ñ¦â¹·ÚÀàoG{»‰Á“'ØmŸ>¹œ :Å3ÆLÆŸzy¶ÿw{pÕ€ÞŸÿ¥10˜œÐ Ø„&$†½>ÕÏQ®im÷œÇ˜Ô#TØ’ç*•*ÜѾlÏC‹f?x€“”h¿Y]7$pÉOT´+‹£}Ù'î¿róÖ–T«XZÍáÓáDF_–†{Ã_öþ=?ûøôÚ¥ªª+ÔBJ¹Å›ÑÊP«9ého7qí·ãÊ\8Ë®®SpŠœ2óiߪËÅ]íGöìvN7ݸKÓ‰aBbØkeÌ-¬¦°” J‰v>w?žj]z0¾o/>kÚH{FÙ¶©‰1퇎&!)™âf¦ØÛX“˜”„£½£{{KæOœï=á;õý.£ìÊ}NZ%×IÙv¦§ÆÀ`‚U ‹R“öµøäÃŒ¥ID.¸é?wáÿ–mû¹nzzz40Ø/Í"$† ‰a¹&¥ÌüwàC”æåOyŒ•Ís”G)羟_ÇT}°¦ü Tª¡>ñ¼:©¿Ì4PWoÞÂÈP‹¥¹”lçG©©i)“—¯:üãúÍNééé ÀW lB’çǹk4š VÅÍ'öëýVS7Sé"·¥¤¦] X°x¯nzF7=)-#$† ‰a¹–<üŒ²AÞû%ÉÙ%ÏfÀ 7ʹ¡¬‹~™’ÎSiá;Œ/§rüÜß8ËœàMLX´œ5{~`ÿñô›D“¯¾¡ýÐÑLX´\?“|4âì%ãÙݰfÏ/‰8Ë‘§Ü_X½U¬Ø{›§}Û)"xÅÕºÎUŒC(—ê+-]!1LH {)7¾(똗>ís¥K”³›|É(C»÷# IDAT¯ŸÚ:¿'Ïúí9C}M~[òc•wÊÚÊŽRBä#6–––{çÍt]|$¼ß¤ IÉɃÉ~³ˆüÄ¥ÄèwùÊ}aÀ ­FóUkzü{v7³.aa&Í’3áÿ^ £—'‰IIÄÅÇgÙ¸«¸©)í<ëgû³‡O‡ÓsüdŒµZªUräÝòå¨V±7bïHÃæ’Êåí=O¬Z™ÈCºL¬yýVì`šn°WÐ7J”¸'1LH {Ý2Ê·Û?vû]B=°B™l)‹²ûviÝ}ùª|;?”mùí”ÔT¼úÃ<““HMMeÅÎ=™’ƵÄÅÇsõæMü¦Ïɲ‰KpÈ^ÂN‡“”ÌχðQÏ~œúûÑæzƒƒf1pÊ ýóÎ^·1GïiÞÆ­ œ2CŸ´G]¹ÊÝøx@™ Z¹6ÛŸ‹¾CÐʵú m2ÞcÄ¿QY~— W®¸ä'>é?„Ûqq9n«8ÝkÇéÞKæ6ò›>‡”ÔT%yþ7ŠÝ‡dyLÄ¿Îf_æç}åw¸í±9g!ó6náhÄÙ,÷í>|$Ûļ(iâZ×ùÜÆU¶½<­U*ÕIÀŸü[ʱ“ãR”3ž/ å`QphÔê ëÔîºxŽåL¿¯ì^ôºÅEÙÎÐ0âîÇÓÌÍKss4j5í<Ý™î7Pÿǧ]+:7n˜íÏÌ_ÂÇ5ªqrÍR–ógdϰ,n®OÄŸóÄ‹{ßñ¯«–´Ü0eâqsSÓfÀ`g‰Ê³âÞ‹þ…%îI Ãò&†e”ogvå:Ð[P®ÿü‡îßVºD{y~kÃ7=ó,%ÚÀ²í?sáÊUBæ|ÿÔëuönÝ{kš}äB“¯¾aºß@ý}.Uõ3°ó—ðýªu,çÏž°£ì;ö'ÿûq:/ú%°bçÆ÷íE#—:O}LÆk>yv«[„2¤[§l_7ãw¡t5ž)ËW3y`ßç¾'¿n‰¾ÃÂÍÛ=G&¦&ÆlÚ{ð‰uzNpªà@pÈ>âîÇgyß®Uq­ê¬ÞǧF.uhäR‡°Óá4v©ûÄsÿ~&ËâoQÇé=ö„-’³ÌÏcl¨ÕL÷è:¨Ë§7ºúosáÊÕŒRî_óÙ[ G) LB¹ÞàscÊžÚºÿßãt_…úÐ>z„{Íê‰ãûö²(o[FF›Ïq3öѺåø‡ „‰àÛ%+hìZ—:NUhìZ—k‚q«QëÄÝçËÉAØÛXSgœÿÏÿ0sÓG—¸:u‘­ûCõß'v6¥¥ºÉ­zUnÇűzwÈ3ß狜Ô,Š\«:µ:·qeÊ?Oíò œÚ,.>~0XE>Ýä&qoO/ß.ŒqObØKºÇÒm?s4â,©©©”*aA»î9®l…6†ÓýyêW P*›Û¯ŸêNd•×=îR~m»75ól¬124üé¿Aꢾ‹öÖý‡èÓ¦9ل⿫מy]O{kýìë–ý‡hå^—9{jocÍÂÍÛ¹ª»žè‹°47§¹›+ó7n}îc»4öâ ®¤üUuoÖ˜ÙÁóôØmÙJs7WZ»»±ãÐa‰ÆÏP¾LéR¿-ù±Ö|ÿoR µÚ%Àò߬E ÊÚš(;C>K+`·.Ø÷š£”$} l'î)‘[ÎAjƒ‹µª¼;䳿·Y1~T¹ò¶e¤“ç@ßIAÔõö¡®·ž}ñí’toÖ˜¹Ãýô™øeŠ›šòQÏ~´öIÏ}P«ÕLõÍ~£Ò~í[²—&_}C ßaxÒ¼ž ·ãâHLJ¦ŽSÿqïëĽv… îI {ÅÄÙÓg÷ Z¥ úXÒ}ÌD¦,_- $1ìUÜÑÅ¢KùºÑÞÀëù¨TCÛz~üßÔAýËÈVÿ{‡ veeæ8B·ÆöÇ~úÄ÷ËIʵÃãøq„_–Ÿ‹'úz Ñ×cX²mý»p#ö®Õ^n&tÖP_æ-Ƶg?!G{;Š›šÒ·]«lŸ¯wëæ¸U¯J\|<ò³ÏF[;´õ¨Ÿ°>ä×Ã~˜÷EBr²/ÊlîÖðþ_$îÍ.ÀqObX.ÙGBr2¿-™›eÒ§Z%G¾]òŸ·lŠ”¼K +Ô•‡¯Õ@¥RÍ)WÚ&eÕÄÑšwÊÚÖæäAB¢~°“˜”D]oŸ,ëÕF÷ùœÓçÿaáæíTÔ%ÚÖ…ìe÷á#”±*Épï.úÆâî¿Üº6ëÌáÇÕ›·Xº}Íã§ñ£²lV–Ý@0ƒS\«:óÓ®go²œ”œœkAV­V3°c[f¬YOM_û1ûýLF†ZýI…Æ.uÙ&Ésj5óüý\¿¾ÔéZç‘ã:_޹ñ9ÊZ˜ýùàíD)]ËÓË·?DÙÈbr¦d†™ºAd§B’ûí?ŒtDfVƪ¤>ù}ÚëeNÀ3ߟÝó=íµÅ³¤êåÙþS/Ïûó7lݸdÅ„”´´±dZ˜ãžÄ°\t#ö¦ÆÆOœXëàåñD¥Ê¦½Ù¸w?ñ°·±Æ¯[G2føço¢Z%GÖýo/1±wpÖ¥F÷ö~tV'5•á³æÓÁ˃:NUˆŒ¾ÌÌ5뉾Cq3Sº4öÒ//<q–?"ÎbnfÊÖý¡Ô«QAÛË+:1,ÏäEÙv–í°¥sŠr‰öÓHG#þÒ'­Ù °ÊX•¤wëæ”·-óÄN×}Z·àÈòùl ú6Kâünùr>þJï­ŒUIFöøŒÆ.uÙ²?ô…~¶wëæ,ܼ]_Fž#ÇžY>ø¢ÚzÔçê›üyîÿ^ûqÛ²?”«7oaÛ¸ ¶Û°qï)Ý~AŽveKÿ±bAµï‡ L4Ô¨W?égoÚóÊ·+èþ>—Í}7Qvw,‡¨•¡VsÒÑÞnâÚoÇ•=¸p– :…x.3Ÿö­º\ܵÑ~dÏnç4€}<¿$ZâžÄ°|¯­ÇÇ܈½C“¯¾aéöŸõÕ’–ææøu먟™¹fÃfÍÅ£vM|»| @k¿‘ú=ö;ßô9ÜŽ‹ÃÖª$ï¾]޹¶d©F =yšà½8Ú—%2ú2M¾úZo—Oq©êÌ€)Óõ“4QW®±póvænØÊ»åËaYü-9XE/†øäY¿‹vûõß=·ae™v ë;J“?©‡¶,ݶ‹M{ÿ0ᙳŃ:·gá–í9šQþ¬i#8MÐÊuÜŽ‹ãv\;CÃrôžŸ׿ƹ¨‹üß©V©B–Çd”ŠG_ÉvsתÎ8ÚÛ=qmÒ«7oq.ê"3×l`ãÞ êüiŽÞSôõýì«7oépfF†ZtlǺL»jÇ?LпÇĤ¤§¾ßìÜŽ‹#úz ‰II™þ (»io˜2+»7se÷fÎo^Ãí¸¸,»g.©¾óÌ EY§O<«Û´Æ¦e=·wt»râÍ®Ë(cLáåvß.ðI³ÆÀàté’–óø­ppá,»ª;JOâ…X èЮÓÅ]ËôhÕôŠJ¥Z”Ï …)îI {Mœ*8°9è[,ÍÍ ˜·¯þCpîàÍðYóô㲸ûñÌXÌø¾½èݺ9îµj0k¨/ö6ÖÌË´Ž‘¡–UÇ0Ýo ¼<¨\¾Á!ûô÷oüõ]ëbinΔ«©ãT…é~q¯Uƒ¾íZ1²gw¾[¶Z?¶Š‰½Ã’1à ü²Ÿ5m$«èŰ<ñº§R¢ýê8Uaᨡ|·|5~3fcjlBc׺×ížjoc­¿~°kUgªUtdëÁP>kÚˆR%,(nfšíóV._޵“Æ2eùjfoÄÈкNUhææòÜ÷4aÑr¢¯)I¦£}YÚyºÓ¹‘r™Z½5퇎Ö?¾y=WF÷öÆÈÐR™Ê°û¶oMôõýº{kN™©‰15+¿ËŽéßáh_6Gí”ñzÏJÇ3·Q‡†¬Ø¹ËâJÃþã'¿pY–çÉx¿ú‚îwzÜœàÍúÙä¥Ûv±tÛ.~ᇱV‹µ¥E–mScZׯÇ£Z%G,‹›³ãÐá,—ÌÚôí¥•B‘QÊíõéµn£Ç÷ºrãVo”RîÐ7ô–/cÌ,c3‹òÙüœ™îöÝð0¸k4š VÅÍ'öëýVS7Sé™B¼2«À~}ºŒû¢×µ€‹¯,Ûöó¢ôôô3(»ÒžÌgïõUãÞ‰a…_­Ê•X7i,q÷ã ;ÁÁ§Øº?”݇ðó¬iüsé2‰IÉœ‹ºHÐÊuÎΤ¥e¹¬g­ÊïfyÞ^ž¬Ø¹‡¡Þ]ˆ˜ÀŽÐÃ,5 €£ááho—åù.é&C¢®\Ë2öE:†½vª\~>;`ª‘¡aýi_}/3ÍBˆ—µ|ÇÏgFÏ]\*%5õ`0O^07¥ËPf]2Ó l¢S]÷ÿŒÇWuï©Y7×ñ¦¡ì>ô¯¯zƒÍí®V©Æ™™™¾7ºWw£.½¤ÞMˆ×$95õ¿þ“‚~Ûæ üþ ¯#îù¢¬–VH‡ì£ŽSeß<&ö÷@¿v­q´/KŸ‰ShçY_?±‘Á²¸9£{{Ó~èhìm¬³\z5&öµ»õfÔ üsé2ß-[ű•‹Ð¨Õ”kÖžš•+áÍ®èý;´åÏs´rí3÷ã….†½‘1•&ŸÇO¥R}ÓÖãã¨i¾²‹v~—ùÌÝãú´n޹YÞž¬øç»Ÿ²K¶½õ×W…Ÿwó&ï·oà‘2hÚLÇŸ9—žžî,&owåμ mæx™ KŽ!(35—Q._5 eM`Aø¯®Q«Ç›3qÕ«»¶£—gñÇ:BˆÜ¥U«ß^0jèÛ‰‰‰ÿ œ:óÁŽÐ°íÀ/(kŽ#óÁ[|•¸·XbXá6cÍzêêʧ3³.a­UIââã±³V.åÛ»uó,?÷7ÆÚ§çÖ%,hX·6;CÃ8u‘v ÜõÉ·£}YªUrdœOOýã¯Þ¼Åÿýw{ë'–Š"Ã^«ÜXóÜ8S®´M·ƒ gÌê[Kg!Dn051Ö,=ìÃ_çÎH¶±,1CÙñ5/e”1>n1Ð ¥âfpB7€\ xý¥^òMÒ¬R©¶˜îæÝå£3k—Yumì%ƒÎ4‹ÁA³ò䵎FœepÐ,æoÊr{æ=2³fÏ/ù¾í2ö­`ddTaÁ¨¡]þoÓª¸ºÎUŒuñm)ùcÓ­gŽÏyT¢ý¦âžÄ°7¤g˦¬ ÙËÌ5ôûÇÄÝ'hå:"£/ÓÖãcªUrÄѾ,߯Z§ß'æêÍ[x dëÁg¯ÄêèåÉÖý‡;®_.ÐÌÍ•u!{9uQ9ÓšÊðYó9g!jµ‰ayæU¦´õ%ÚS}÷iƒúïJ7B¼N ·ì8=~ÁÒ2©ii[¼ÞRîáX Ì¼¼Ìà1¯Ê¶Õ£ ›ûvnŸÖ§MK+9Ùùâl·àÊîͯýµ‚Cöáô®UÙ0e‰IÉÌ_ÌÁ§9¼äÇ,éèåùÄlP~âÿãB-ë»Êeñ&,\Ž£}YÌÍLÙøëjUy—F.uX³ûíËÒ¹qC†ÏšÏŽC‡151¦¹›«~£œŒä¹^j¬ ÙKbR­ÜëÑ£EÖìù…£ágù¼EvþFØ©pJY–À¯kGf®Ý@ÌíXœ*80²Çgd—˜¤¤¦²hËö;Áƒ‡y·üÛ èÐFß.ß_Çù=uj¹™)köüÂwËVQÌÄ„&®u³\í@dïRÌÃ]G¿rþâ%7`ÊF\wŠX3H BbXLž¥D[‘/ÍÛ¸õLàâ¥SÓÒ6¢”rÄÁåËúXÀ¸ˆrÝÅÍÀöÌNZÝ»gý¸Ñ}¼m³;ƒ/žuå*^ý‡˜”LµŠ¸w¨+W)cU’ã+e›<{rä¦&ÆT~»áÿ^ÀÔØ„ÛqqY>{k¾]ú³×)ë–ím¬¹zó)©©ôkߚѽ½õ3Ê–ææúu„}Ú´Àé}Ùöt¿ÔõöÉò~7L™À¥ë7ð úScÔj5íÊr\·yÎ졃iëù1ƒƒf±.d/Ö%,02T.w}=ëÄ'$àhoGdô%â&УeS¿ìóDÛÌ\³;wÐçsÌÍLYºmáÿ\àð’¹jù"p*áÿ\àën073eæê`’“Ù1ý;Näës°47§O›9ºd¢Pœ‹ŠÞÛÙ?àþõ[±®ÀìB–DÇ{Q6:À£{%† !1,_&Ï9*·6P©ŽÛÛX«ö-˜UÂØP[FºAá´rîµkP«r%6í=HJj*¼<ˆ»ÏÂ-Y/åè\ÁF.u8|:œ°ÓO<ŸKU'\«:g„ÙÛXÓÖócýmÁ!ûˆ¾Cq3SÊX•Ä¥ªÓ%;‘Ñ—Ùz ”fn.úòŸèë1‡ì{â5‹›™Ò»usýÿ3voÔ¹=²©HáÑ·]«÷;xy$Öë= Ã¸{-Ò¡lýUÒ_òçÊ£làÓHfiµŸY¼eöÖ¶é“ím¬Í¤—äÜÝûñtðò¤ZEG:xy’šJõÎ=¹zóÑ×cž¸ü¹¨‹„9†‘¡–Ÿ˜†£}Yö?AÿñYòÙë6ad¨eÕÄ1¸VuæÿÙ»÷¸˜òÿà¯Ì4•aºŠ"j…,?–l}Y·¢u¿Sî–‘–6—¥uɮȵÜrK)¥ˆHDI)E.m­ÐM©4ºNMMÓLýþHgw–TÞÏÇÃcÛ¹œsæsμçó>Ÿ[RzFü²ûü0Ñd ³ÂA@€ V?Ã|¨ „""îÆ3Û©íªýºnÛ  ÏAè]ÐTUa’õˆ»÷eâ¬NkMœqÞŒ q%º[Ì¿°v3§Ân¦.DFÃr““Ì:¬uEÅ'``¯žLkyNá|b1nýóç#¢ud/Ómô­ gÍÇ…ÈhL4MUUè´Ö¤Äùèê˜Þ=qáwî]›µvÓ2‰T:5MÅ0=ìDM×Îi òò¾Ã¡ö‘>kñ÷šžnäÆó9òò¬©öìÚYîHSOžO2³» ËEXµg|CBk*—B!œ=O¾×6Bá+Ç&>€‹¯?Vï=‰TZ'yEbjŠK…8‰~óãJlœÌ{=‚.a¿½”¼¿¼×Y·ÿ0öûàæß‰t‚›ØÄ˜¼r­B;ÍVeÃúõ›€š»_ÿºä<0€Ýv[ë]ݾѕŽY¶ ‡ÎËLêBÞ®gg}¬›ÿÔ”ypr÷ÂTû?^ÇjÅ?N©I»} }šû6ƒ {ASU…yMmØ«'sÑ@·=†÷5\‹»+³ÍY#‡÷â&â‡0êÞ•Ù¯~»××K÷é 6‹®’"4UkF^ 52¨òj–Æ”¾þóN2ŸP˜Z-Åæ£ø'5 '¯q«¤ÿÐëpöô³§Ü΃Çå"6ñº°þƒÚ™ŒnÞÖ¿}›Ö· hbqL€jzÐ pb!ÃþÿÏÚÐû^-Ïç#oPÙÏxׄåk¬ÍÍLXv3,@ãNš¦ÚÖ•û’Q àJLôê‰ä̧2¯³›iñÊ{ûõèÎT=ObþøÑ¯´Ô\ˆŒÆÜ±#á57ÿNDÿïz0Ï ïkÌÌÔèt Ëw¸à¶ç!¦¥ø|DVÏ› g“øËf!Ø,tZk2ÇŸ ³º –‡ƒIÆ}p-RfŸ¤q*°ùˆ'BbnUvíì»þïäÔ¯©$X"˜£ÎVk§ŽÕaa[vúÛ^¿±êȹ î²iS0Ñt õºx‡Ä”4ÌvpDN^>ºuÔcZ‰k»R¿ñÇô¥¥Rj»F5­Ù^éI£øâ5¢—f¬ýØÙƒ•¹÷›¬¦ü~ÝaÍÍL «Ý§CÃqöZ$\|NC_§-üœ617BŸÖYB«ö†AÝu^Éû«WÂ#èöøøW*·äFJ… ¥Â¦¶†ª€'j†ÜP #„bXƒ÷A £EÅ,ý¶£v‡„”Ô»ƒ.­>IWF6¼Ÿ1.EÇÂ7$³G ûdw~ÏGDa¨Q ïgŒ€ko¾†Ì‡š¢@P‚Ä”4&ÀL€ó!-È"£1~PŒÐÁQ1tr9ïKW0`þ’êôìgáÝ:èjGÅ®ÿ ‹A€6€xM%9‰ív—W·nWY8aÌîÁ!â–6ð “éñAd¹øžFN^>ÖÌ›…×íX¿pÞ[_¯©¦Â$ÝÂr€šá%u×a®b“ø@¦ì^ô’©{ƒñcàúŸMUüec…÷¸¸{+ròòq*$Ê/n¦ÿec…v6Ì¿IC¡ïÿu£ ë+œ‡ΣϬùÒcAwžõNÎÈ ¹‰Æ±¹Ã¡Ö$“gˆ¾ÿ(+:>±wŸo»˜oq?!°°ÿÉ™Ytt¢é IDAT¥4!Âr´4Ô1ÑtŽœ ‚P$BÇvm_ù±2ž³ù÷¦nÔ/«M€ºuň~ÆŽŠyã GZêŠDLkò\'ñKË~¦Îf±±ýMêäîEcRšˆl †Q!ÃÜÌóbAúZ1î˜u'æz› ‘Ñ0éÓ˜Döm-ȵÇR›×N43z@_\‰¹õÁ ;›Å‚IŸ^¸M'º” ápà,ìÿp¹J[Ržfµ ¾yû•ÌûÓ3™+Z·ÿ°Í—õê“My9¹{Iͬ¥ èK¬§L¯gÃ#1Ðr ÎGFÁ¨[WÿŽo®‹Íbáøú5ÐÕÖBbJöû……™©ÌxeŽ<|þ\nõq÷>–9ïÆÙðHô쬛Ö}P7m- uèë´…°\„uûãîÃGõV6ëÎCbJúÌœÉ+×â‡y‹Ð¯GwLjMUì·_Ž#A0ž³#~Yék6`‰ÅD ëkÄÄàà¨hŸ@õ…×T8ûÿl-uö<™\((1KÍÊ1,.+‹£Ò¡Ö$¤¤á|DTƒ>ưÛw‘ð¢ÇbRzÆØ®‚P$‚ÕäñèmÐköÄæ£t2)†}´O2w¯®zš˜›_Ð}ã¢ùrµ?”¤qŠŠOÀvOø9mD@®¢RÍ×XsdŸa–T©]¦åM´‡O`–i©e8sþ+IøìQÃð—&¯\ s3Sf¼rä½xÌZ· >Ç‘˜š†ñv«_ÙG€óf¦b à•m€Ã#p;øJ´vÙÒ° „ÃÁ£Uí45b!ظGò¨Tþ»´°3*nþû΄FLQåµdý:ÓBfFü¯ýfMBj8ôìÔeå" …PærÁkÁeºdë´Ö„°\„»¡f+@+UUp•ñÝ´¹à!ÎóL"˜’†b¡\EE™±À©9yù`³X2¯–‹P @Ãa&«W".é!Ø,º}£ æF#WI‘W]û¾ÚÇ ËEÌgÀ,—¥¥¡6‹… q%ø……¯C]âJÜœ ‰T 5é’^÷xSÓ ‘J¡§­õÊv’Ò3 ‰Ð³SG»Šš–¼-î^•Âòò'BQ…uAqñeúR k¨œ=}àÊÌôßM^¹}{t‡ÝL Ø8íDbj.»ngâÍÑÀ‹pØ >î4wŰÂþ¹û í €C¾ÿ~Æïû8~!˜û—Õ+E‘ÆáY^ó÷ËÜÔí¾XwL_ÝJÛ›Ä&>@…¸ü˜ v):«]â/›·Ÿ™ËÇݤGX·ÿ0–Ïœ ®’".DFcúp3l[¶˜ÙžÓN\ˆŒ–Iž_ç|D|ÿZÏLV»DKlâƒw¾—|9É™YX³× OržvÔÒž•pJåÓÑ3™P`Zv` “÷ñËw¸ši·Ò£ hM÷âºeÀkÁ•©dÕým«¨cúš H¥˜>Ü ã÷Çõ»÷Á/,‚–†ú+Éc·Žz¯ÿ1~1ùá˸JŠà*)Ê<¦À‘å½üš—ß§Æã½£_>6Žü;·8òo›\%Å·>ÿr²ý5W8ܽ¤…%%Ï«ª¥KøÅþT*Êӡ×q6<Å¥BfRÖÚ%耚^„^Á!–‹`Ô½+–NÂÄ›¤ô ð?‹´ì°Y,èë´Å¯3§BSUÉ™Ypõ=¥Ó&c‹»ž¿ˆ“u·oë¼ 'á€óHÎ| 5e–N,s³ñtèuø‡^ƒ°\ÖšX9gúkcפ!ƒ0iÈ ™uzÚm ‘J!ª¬­N1ìc4û”»zëÖ‰,þs•J‰ôøÖvÒ]Þ~Ô5«RàÈ¿¶‚§ÓZâJ¦’7yåZ柫ï™×¾¾nÀº•øã÷—yl°a/p•‘˜’†Vª*8z.öÀ?4Ûl—ÀÚ|"àþ£d™µJ`Üà¸ÿHvîVª*2ÆÄ”4(·à2]Äk?߸Ap‹Æ=7HâJ8¹{a¼Ýj‰¸¢bwƳ\MJœ?í1còvzvrÃêöFÝ»^^¾ÃµzÞ†¿˜‰úÈÛ©ñxXoõ38òð ùopñ9 ^ .v-ÿ… ˆÈˆŠOÀ„åk$ö.ž•”‹f?Ë/ТębXC²ßÿ,VíÙ£n]±lú„BŒ·[Í,a—“—ßÓÞÏ£ôÃÑsAp:îÅ$Î#~YŽ<–MŸs3S\¿§~a!|BB1oÃ_èÙY“† ÂýÇɘþûFfÿ>!¡˜ñûhªª`úp3o|ÎrühBêUN^>ÖìuÃݤǥºZ­-cœ¤Rù2úü´0€q°ËöngBÃÌvp4Ø«'–N›,ÓmÈzWweòuJLIÃVϓҸ–´l®è_\¼5kŠa Nrf¥B 1êÃ<¦À‘‡ŸSMËpÄÝxhªªÊ Qãñ˜Vé¡F†løâ’!%3 ÉOŸ"ìö]¦Õ¸VN™¿›+*0‰{­º]´ëž³øäTˆ+‘”ž!S•TUáNÒÛ'OümOÍ8í‹»·½2Ì…P kÉs­ÐظC<ó‹‹=†,Z6ÑzÊ„f '£‰B!H¥8à.¾g¤Ûµ=ž[P°8· @D%óå _òk"ãÀí[ŒN] u½ì73ã>T%ä=+œÛÀÊ]ûªªª«’ååäÆÞIzøJ¥áóëªX]½6 ¸~ãàx»Õ〵ùDêöFÈKÒ³s°ÓÛ¯êòÍ[åê<ÞŽa™c‰°ŒnR kôuÚžä<“™€kóQuûöïß|Ôšª*¸qd/ÓHv(àü';¾ZmóÇ–iŽKzEù·“Yb> ½ :ÓI¦öŸ5«ÏÝyø0þᓌŽZj6 ·–Û8í¿°ˆÎ!_‘¶Î{0wýæ2yyö¢ä̬.y%%”87pÓV®‹8~áRW—å¶£‹JKŸ´\‡Gš| ¿‡¿oÀä•k‘žS/û´uÞ[ç=¢|6r‡­ó$gf1ù†„aŽƒ#&¯\ [ç=HJÏø**œ¶Î{0lÉrñí’ö•”´IÉÊZ €*à 5ýztÇŸÓÌ„¿±‰j&Aä6çû+Äb4WRbg~aŽœ údÇ׳³>ôuÚbû æøÒ³s0g#Î^|ãûjgå–ÖéN(†5Šä¹V使]ù…š™¹ü³ƒØT ¼(3ÖÒ4y]Âó¬¥ñÉ©¾…‚ÒÖ‰)i©Tó5N…„éì[e;©¨´ôé‹máìé#Ó…®©¨WÂrÓÀ¨ý޹ߧ⠟ÐFQFç#¢à ~a!€šù4Öì=£n]a5y<Š…BŒ±]õÊÊM¿°Ž`ø/+D·>Ü_RVÖ:5+Û@)E ŠaѶe‹‘“—ã9 0fÙ*XØ;ÀnæÔ÷šÓÁrÂÄ&þƒ–K0yåZŒ°YŽýŒÔÌmò)YgÇ™Y0œ9ãíVÃÄj)zvS§¼ñ=–9ïFlb`Šaÿ™Ü—>€úú½ËÅþJ œŽÖ ä ©Kù¢âðOj:æM…рܔŒÕ.¤ył̒Ráø"¡ð>•JÓphíŠygÂnlŽOP›;vd“šp03—ã9 áç´±^×Õ>|¦Á—‘ñœ…ÈÌåÃÏi#zvÒGw‹ÙX3o6ƒ%R)Fü²úíÚbŸ½]“ªpºúž†Wpˆ¤†úé”Ì,ky(†5©÷§ B,†ž¶3Ù¯ T¡H$3ùïËHJÏ›ÅB·oôÀURDf.j<Ø,ø……ÐÒPgZ§+Ä•2eæò¡©ª*³ZÁËÕ=>5Ofýx~aååeΡD*EN^>Ôx<óL1¬ñ'ϵzwí²"õiÖ¦‘?ô嬛?‡f{&ÅÙÓ¾!¡ˆq?@…ÑJ…p>áŸP‘¦ªÊêä̬T*MÓÞßl­.DÆ8ÞIz¨¶hòxÌ9¬Q/Õ”œ™§ã^8“>½Ð¯GwX›ODf.®¾§‘˜’†æJJÞϳFþ6‹…äÌ,¸úžÆ¸Áý±Óë tÛã/«W¶-,áPÀyDܽ ±ºÚZ°6ŸÈTk“çën.pö<‰œ¼|èë´ÃÊ9Ó™1šÉ™YØå} éÙ9`±XÐÒP‡Õ¤qÌ8À‡ÜQP,À¯3-àäî…Ì\>´4Ô±jÎtf²$[ç=PSæaÖÈáìéƒôìèjkÁn¦óšÚc »}0 WOXMÇT@_NžO‡…cX_c™±¤ ·¢B,†ûú5M"¦¹œÇá³çÅ­TUÎ=ÎxjàEŠa„P £äùKPémÐÙ;ãYîösg6«»†!ïÃ7$ Gƒpq÷V*Œ/ìtèu88,USæ?Îx: ,û ¸®\¶Æ?4Ü>!%»ÄbR£­€ò ‹p:4ÜŽa‰ÅDôëÑ۵Ře«ÐE·,'ŒAN^œ=Nb@¯žØ³r³†©®¶ÌŒû€«¨ˆ•s¦ËlW"•bòʵˆM|^ .”¹\dæòÁURDèþ]Ði­É$Ï\%EthÇOk–Ы'|þü‚R!úÍ[Œ=;ë£B,FRz¸JŠˆó8^ .“Ôjªª •š*ž‚_X]m-DÙË$é¼\(ÊËC«•2ŸñQ À@·=B÷ï‚D*ÅTû?ŸÖšPàÈ#93 FݺÂÏi#Ø,–LòüºÖùØÄ˜¼r-\V.cÖumÌN·€@‰†²òµÔ¬lKéô§FŰ¯ »OѤG#zýŸAßÝÞ~þ'.†´q\l)WwF=òy$gfÁûÒËËÑJU`nfÖšð CßÝÿ8Wbn£w×Θ5ràRt,Úi¶ÂÃ'™ˆ¸{FÝ»âå›—¢cvûX,Fô3Fÿïz¼×1EÞ‹Çùˆ(°X,Œêß—©˜%¦¤á)ÿ94TUp:4Ê\.¬Í'‚«¤ˆnßèb@¯L¥mùNWJ…H«0wìHše¼ž®¥Õ®«RŸfå4“k6ýqÆÓëT*_k§ŽÕaa[vúÛ^¿±êȹ î²iS0Ñt`£Z¢PSU£ú÷Å·clXÓò¼f¯x-¸8±i-óYô´µ`þ›¬Í'2ïýmÎô7&ŠA‘шM|Ýöܱ\%EØ:ïALâÜJL’™ávƒÕϘ6l(’3³0Ðr "îÖŒv(0iÈ ¦µ̬EbJ’ždÈŒMœ5j8ìfZ '/†3ç#=;™¹|f?‚R!–[ýŒùãG3ÝÔ“Ò3À/,ÂݤGˆŠO@·Žz¸¸{+Ø,8nÅùˆ(EF¿3¾%N;`9aL£Mœ+Ä•ðº„=>þ•Ê-¹‚RáBA©0™¾éáFÉsƒq÷ï¤hÚ*-×M[³~Í”¡&»Ô•û3áa´í*¬š3zÚm°ÚÕ Ý;êAÃø†„b¿ôuÚÁ¤O/8ö€–††"8*qIÑí= ìÝ[Ž« æf&‡Gs‹&×T𲟿߄A—°Ïï,l,&BX.ÂGì´û£ú÷Ebj:6¸ƒV+uÌ;ç#¢`»}®YnõЭ£`Í^7,›fމ¦‘™ËÇ›˜d:ÖwüŒz—÷)>{A¬®Âû+;/#Zð+$gb"°±:,ìÏ¿ü¼O‡Xíô>ÅiìÐ;I`Ò§·Ìñ÷ÿ®¸JŠˆœ‚v­[ztêøÆmÄ$> 5îÃt}ÞagóÚ׎ú¡/€—©×ºÚZX;nþˆ]Þ~ˆMüÉ™Oà•É7Gõ¯Ù†–†:tZk"3—ÿÊ~†€Lâ^!#*>¹‘p:´æWQ‘ùoKˆù…EXæ¼ËgN•¹±ÐØ*œ»¼OI•[pï?/,šó¼°(¾ÝÃ(‰&Ã(yn°â’’7Ø}3!ѯÿ|k“?Ìk6Ñt µOìVâhk¨cI¦ƒðôEw¿ZݾÑÞ•ËÔ´,Ö]²¥Û7zÌD0Å¥B\ˆŒ‚¹™ Ò³spô\bÜÈL.ñ>¶óÂÁßWÈtêÁ,^_³äÊÛ[,¸JŠ0éÓ .¾gà¸Øb1öùŸ•i ŠD¨W¶{ú`Tÿ¾¯tO\æ¼³G ƒÕ¤qÌX>juþïb`™ónq¹H_RV6¥¤¬,J…|=“ E¦eÚ8y?±|‡«™v+ ¹_gZÔëzÊÊÜÌÉOŸÂÂÞºÀ/(qøí½×ÕÕÖ‚ËJ[ØítÅ>¿æñ¹cGâ}‡%ý4f®E *>-—@KC&}z!ìö]Ä?Nùde¨«­…}öv°Ûé »®ÌãK,&¾³µ-8:Ξ'ß«%ýKV8ܽ¤…%%Ï«ª¥KøÅþôí$M9†‘¦—4S «rùà;ê¶^VRæÙE·ƒÚfkK9šêã$gfÁÌÚ–Iv³óò¡È‘GÀ¶ÍàµàbÑŸÎ= ^w“ÂÖy.FÇ@™ËWIV“ÆËT–î?JÆÆCî¸ÿ8\EEXMÏÌû6üÂ"¬ØéЍøp1}¸³ä‹oHÖì=È´4›ôé…µóz¥ò—ô¿íÙÏLcafеóçÐD©@ ÀÚ}‡¥Wcã„rrró‹KKOQ©Oá¦Ûîv'Ã"„E˜èu³›aÁLü÷%I¤RääåCSUUf©šœ¼|¤eç@ÃA÷oô˜ç*Ä•àBKCýqFX.Âý]·õ´µd†·ÔƬºxÕ>V»íÚ÷³Y,ôì¤/3tEÇCN^>$R©Ì±¼üØËÛ|Ý~Þu¬µÛ|¹Œ¥B …2Ÿ¡¡ˆŠOÀÖãÞ’'9ÏòØly»§¹¹^ô-$M1†‘¦‰b%Ïÿ»G§ŽÛÒsžYÏ3’½tÚZï-pÜ ÖšÌXf‰TŠï¦Í{e®ױuÞƒv­5ëu (ß0ø†„ÂÏi#¼zJ ¼/]Á¦CÇÅ-š7?š“—·@)• ùÔn;ÐÑí\×™°p£Þ]»€* äSW8·yœ¬zœñT Äá¬}úü¹ • ¡F(†‘J<›BÝ>þqÊ2Û.Þ¸é:ìºá_6 Yƒ {ÑÙ}OºÚmƒv­5ÁUTDt|Ô”[ÊLØõ©9{ú¼ñ9Ëñ£©{uqÿQ2VîÞ_‘“Ÿ—ZRV6±¤¬,‰J…|.}~Z˜À8Øe{·3¡áGf;8 ìÕK§M¦%æÈGKLIÃVϓҸ–´l®è_\¼´Œ¡F(†‘ ×Ô>®Žö¸Ò¡»a×.¼ V?Ë5Ä.c Ñ•Ø8fÂÖš7¨ÿ{µà_ŠŽEKnóãó_’çÄ”4$¦¦7è±t TˆMG<¤aáåÕÍ`#ŠŽQ©ú¸}‹Ñ©«¡îç#¢ ÌŒûP”|p…s›çÉê¨ø‘º2okzö3Z{žP #Ã%ϯ¡ØõÝí9Ï,—M›Â^8is%ä=½‡ý‡Er,¹3y…Å‹Q©/ÉÛiÀ‹á7GÅŒ<ÖæeÖ¡'¤®ôììôö«º|óV¹:·#%+Ë-ÏA(†Ša„’çwÐíØVûtª{l±±b½ïR"„|’3³`·}èqVöÓ"AÉ,7©THCâë¸~Ô©k×ö_ŠŽmgafJPòJ…s—·‚nÜ·RU9”𕽠4?¡F(†Jž?L»Ö­§—‰Ê÷÷ÿ®G‹ V?ËQ "ä_âJlóð–9$F3¬)/¯pu " ؉¿O ¸~cWøí»ífNó$|åø…Epõ= ŸPQ+5•c)Yö 3„b¡F(yþO;ë´sy^\<Ûvº¹üOcF4ù®ÜÂr„"ÝÕüDM™Ëmr3¹_ŠŽÅª=ûË++%— KJ¬<£³M‹CkWÌ;vckt|‚Úܱ#©ú•V8½‚C$m4ÔO§dfYÈ£’!ÃÅ0BÉó'¢Ö¢E7.—{JQA¾óö_mX†›ìg¥%>N¦ÁÜÌŽ‹-›ÄçÉÌåÃÞå`ù­Ä%ees\¥³L«½¿ÙZ]ˆŒq¼“ôPmÑäñ˜5r-YØ„ J…p 8ÃgÏ‹[©ªœ{œñÔtãP #ÃH=øêfÑ*‹Ÿ „B×–ŠJÙÞ—¯IËÎáôù¶ ”šÜgMLMGbjÌÍLéJÿTy-1°÷wÐÖPoÔŸC"•b¯_@ÕÇ­Ïžçm--/Ÿ …Î0iÌ.DÞ¼ý8#ÓiË’…’‹7no>âÁa³ÙèöûW¢;IDATMÙÄ*œ.¾g°è/gIFNnhN^þÅ7И@B1ŒP #”<^ÅBá‘X¼»¬\ÔqÏiå–ÜfݾÑC³fÍêýX|C ª¬ÄnïSÐÕÖ‚ï•0Ü~ð}¾5P³ÖîñóÁð»z w>‚¾N;´lÞüÂ"ì÷? Cƒ.LpMÎÌ‚ï•0ôùÖ€Ižuµµ°ÇÇw’á».À‘g3‰”OH(Žœ½€ÄÔtè¶ÿ ›çÂ#q40aqw¡¤ €ÚeÁ„å"¿ —d¶+(âlø $¦¦ãBd4:uÐÁÆCÇ ªÌƒ¶†:SÒp÷ác¯=^ß0ðZpq56OŸƒ´ª Ûë0Ç›ø{|üwm[µ‚†Š2ó\f.®§NãtèuDÿ}¶P~Ñ5ªB\  Ë8~>×â’"óY¢âàa¹Zêxy鳤ô ìó @àõ(”–•£«^&@z]F+Uì>é‡Ë7o¡c[m¨´lùÅ®ù¨øL^µNxã^|´°\d&–HTQ$MEЛ©'¼ä›ËK.GÇíôöã´lÞ]tÛ‘ØN> q%Ž^„՟ΕéÏrÂsžç/,)ÙH(†Ša„’çz%.,)ñSâpÎÝIz<ô\Ä ^÷ŽzÍÚ¨«ÕëA88‚k·ï¢µºöøø¡º:<.c¨ñ÷PSæábT ¸JJèÜ^Òž`»—/~7 \%EØ:ïš2Ý:êœOøàya~üß÷HLM‡h8î<|„a}q÷>BoßÁ˜?ìv¸âŸ´'˜1 '§b»§fŒøñ½´ÓNEÝ„™qh¨(£DX†ÿÓÿ©Síÿ@IYLúôFBr*6>Ži?A±PˆÅ:CÃAĽû¸xã& t;àøù‹˜>Ü ×âîa‹»n%>€Ùÿ¾GpT n%>ÀÈþÇ”“ï•0ˆ**лkgü¾ïúöèm u\ˆŒ†ÃØ=j8Zr›ÃÖy7÷é eËEºhŒº}‹!F†hÖLºÚZLòlã´Yüç7x4TT Ò²Új¶b’àŠÊJ\ˆŒB³fÍdÖ³¾ÿ(3߀þßý:·×Án?$?ÍÂï Á/,ÂG'„ß¹A†ß!#'{ýÎ`îØ‘õ~‘ó ‹ðëö=e;¼NåÿT!®¤‰(H“µÞݽêRtìõÔÞN¢j±Šï•°^®¾gXTm¼Ο7ü%MJr/‹Ÿ7¢ ¸d€*B1ŒP #_›Š( ï …XÍšYMµwØ>nð¥ÕsgÕë¤ ?š¢ƒV\‰¹ û¹3qÿQ2ø……Ð×i‹¹cF0¯Õ¿/ôÆšƒ_XMUÌ5 ¾!¡073D*ÅÙk‘pß°†y½G~[6‚«¤ˆ^]:ãGë_Q!®¿°á¸ïu¼\ôÿ®Œç,Dä½x 6ìõÖcMJÏÀùÈ(Äy‚'óܵ¸{àÁÏi#Ø,&š„©ÕRGÇ¢onŠDX7–†:¦  ÿÐp™mœüs=¸JŠøVO㗯ƞ•˘çzvÒǶe‹_$¯)HÉÌ‚¡Ag¸øžÆ:˹jdHHIƒGÐ%8.¶„P$¿°ƒ ¿CÏÎúxyɲä§Y03êƒÁ†ß½Ò=ª[G=të¨‡èø„WÊÁõÔÌ5Öæ]:è`üòÕX7ÿ'5-ð{V,ƒn{ 6ìã9 ëõº–H¥ð ¾RµÁíX…\uõ~aE…¨kùJÈ™˜H,M ;ºÊÃ'rë‰ànœå3§bX_#* L"•âtèu8{xWÊ˳ÿ–TJ¤fåÄQÉŠaÃ(†JžL>?€“á·ï Œˆ½Ñj¾üDÓõ²ïZm:­5_Ià®ÄÆÁÅÇ9yùÌcb1`Š™)¶¸{!3—‡O2¡¦Üu'AÓÓÖWI` Û©üÂBdæò!•VÁÌúWæµüÂBð ÞÝ ÿ8=;é¿’8@bJzvê(ózvÒGf.}Ñ j<sSBW[ë•÷kk¨3Ç«¦ÌC…¸³/£n]™×Ö&Ñ5‰t2VíÞÇì·X(Ĉ¾ÆMUl°ú«ÿ€NkMX˜™¢îlëÙXÁÖy7|BB1¼Ÿ1–˜O„Ö{ŒmNHIÃôáCÿýœõ™µ tÛ‘kùþ£dØlÝ%ÈÉËO*‰æH¢o8ùé™Ì°á‡ùÚ»ž:àäîe±Íó$‹*  ·Â¹ý„´ºº:­PP2¿T$ §’!Ã(†Q #”<7\EOrs'ò””Œ7q÷>¤ã´t1ûK%A‚R!æ­ÿ^Žë˜Síá˜ç5UU0¼Ÿ1¼ƒ¯ 3—‹·L–ž6‹MUUð ‹ Æk‰÷|L\%E™D¾.^ î+Ïñ Ñ»ë‡Ïj.,«¤øÚ$ýuû=¾~ Ó}ýeóÇÆ¬‘Ãp-î.GA±+çLtÆu7$¦¤ÁÅ÷4,ìpÝÍåûT~é³ò ‹Àf± Æã¡@ øb×Ë Ï]¿QQ&ýà}¥ 4MÌKÌH ;cíæá¿ÏÉÝkŠÛ™@Ö¯3-d†c/ãRt,¶¸{U ËËŸEÖÅÅ—©T¡F1Œ444pâMIHyy̳¼‚ÎOsŸÿ6Öö· ‡G ,ÕûqE"H¤RtÐja¹¹¿òšé/º>GÇ`ÊKɳP$B…¸âJìòöøAý¡À‘G÷oj’Ìýþg!‘J™äï} ø®Š…BìòöC…¸Âr’Ò3C qÿq2®ÅÝP3IU\Ò# {Ñ ü>Ÿ·öxŽ{a’é ÷z߈¾Æp>áA©I¼kÿ” Á/,‚GCŒ Ñí=E"™› @MíÑú1¹|E"„Bdæò™ç‡÷5Æñ —À/,‚D*ÅvÏ“ÞϘi9¯oþW¯I¿Ÿe) ¿~²L$êH‰3!¯Ò3™P´ùˆç´«{\Úuïzyù×êÉ+×"ê5C3HýT8‡X-“Ú»xV (š–™ËïD•NB(†Q # µ<¿äYA3÷ËѱG®E Ûhõ³üØAý?éNZ©ª@Ãaþ®û˜–†:,'Œ©ÕRð¸\XNCƒÎ2Ý¢kÇ(èÕš/ÞÔŒÁå**b å’šÄÖ¸VÏ f,´ûú5p8p[ÜO€ÍbAW[ !®Ûßy¼¼\œØ´ÝŽÁÅ×<.‹&‡n{è´Ö„Ûï«°Áí¦¯Ù€žõq|ýhªª '/Ÿé­¦ÌWIlK¦‹tRú ´\‹…ýŒñë ™rzSbºi±%–ït…ÑO QV.‚®vl°úƒ {!3—KÇ­xšËGs%E ìÕ“§ köº!.é*ÄbtÿF‡ì™ç\}Ïà|D€š®ÐÁQ1°œ0ódžµù0]¸•b 5ꃿÚÔ|±X,™™¹_þÿO)93 ‹þÚ.HËÊÊ,Uüà6}u y;í1cò »é¶»ÝɰˆÃËw¸šèu³›añÆ,äÓ‰ŠOÀÖãÞ’'9ÏòØly»gù^T*„P £F:9*‚÷×RI鎂ü)ƒZý¹d![_§mƒ8®Ì\>Z.ÏŸëeÆ76¾!að …ŸÓFºØÞƒ°\„­žÞÂcç.V‰++W8 @B%Cȇ»}ì@G·sA^gÂÂzwíª€~¾ ç6“U3ž ”8œµOŸ?w¡R!„bÅ0BÉsÓÅn«¡f_Z.²Ÿ;v”ÒÒiS À‘ÿ"’˜’† ‘Ñð ǸÁý™VåO‘Äfæò_ûÜð¾FŸ-Sòüþ‚£b¤v;]…墊`‘X¼À3*B>ÁwËe{·3¡áGÎ]4Ø«'–N›üÚÉ É‡ÿ^mõ<)ûçaIËæŠé9¹{A7û¡F1ŒPòüÕh£­¡îYU]=àÏ% 9_bÆÃÄ”4GÇb@¯Ÿ´ÅùK%ω)iHLM‡¹™ ]]o™ËÇÒm» î>|\\!ÏpJ…O/pû£SWCÝÏGD˜÷¡ èˆëÛ Wå?Ìe×]Š©!©W‚_XPàpêídN^>³¶´–†ºÌ²[/»ÿ(Þ—® •ª*ºwÔCKnsôëÑý­ÛÏÌåãRt,æýÚç=}d~,Î…G"*> FõïûÅg,—H¥8z.¨ÔñˆGµ¸²rê*DHshíŠygÂnlŽOP›;väW[­­pz‡HÚh¨ŸNÉ̲GW!Ã(†JžÉ‡Pl­¦²EX^±ð×™ óÇ~k’ø%$¦¤ÁáÀ …Pærëm–ëE:ãya¢âã~à­ë7m.ôê “>½‘˜š- õ7&ŵ¢â`ë¼1î^û¼öð Ì~ܽ‰E“ÇAP*ÄNïSp\¼à‹MZ÷à‘tÉ–íYyù‰‰d€$ú*ÒpíýÍÖêBdŒã¤‡j‹&Ǭ‘þŠa;‚R!ÜÎãðÙóâVª*çg<µÍúOÅ0Ša„’gòé·RSñjÙœÛc»­µBC\‡9*>Û=}ê}‰¨ºIìyÍÇ&Ïj<º[ÌÆ‰Më˜Öì£áq!¡ûwÕ{ÿÍõ`î…ˆìJ‰t)€ôÕ!¤ñp]¹lh¸}BJw‰Å¤&[­­pºJ4”•¯¥fe[‚æa „bÅ0ò•`S|vÉÏ ŠŒJKËÌg­Ýtpˆ‘!÷…óØa’a¹A—ð0=]tÛcÖÈaà*)"93 —¢c`m>‘ymlâ¤g?cZl“3³à}é „ååjü=†~ðþç,Œ·[ V?ãNÒ#¦åY"•â÷½ntÆ»_^ÛõÜ#è¶ó›Õ Ãû3+pä⺺Úmd^¯ÀáÔk9{‡”¬Ý{¨ª\,>`-hŒ !޵ÓNÇê°°-;ýí¯ßXuä\wÙ´)˜h:°Áõ:úâJx]ÂÿJå–ÜA©p¡ T˜LgžŠaÃÈפAý(‹}KÊÊÚݸ÷÷þóWx]bÆý6Ts‘œ™…ICáNÒ#,pthªª`›çIÜôoÌqr÷B@À$ΓWþ}¶Ы'Öí? ß°ÞmËq€ófŒêßÅ— õDbJb@‚;ôuÚañŸÎ¯l#*>ŽG<àç´÷¼BKCƒyŽÍbA_§-ó£y/[ÜO`ÕœéõR¾IéÒ–6Ï~s9ø°\, À†gB/9‰ív—W·nWY8aÌîÁ!â–6ð kðñþmÎCçÑgÖ|é±À ;Ï ‹z'gd @•NB(†Q #_jy®_¥Ï‹Š–pÙâî}òXàÅ.NK+tnpŸ€ì¼|¦+÷÷ßv…ÁäHÏή¶F÷ïß+aèÙY™¹|Ä%=ÄÁßWÂüGSL6 •J±Ïÿì'G|"8–?¡X(D±Pó¡&0;~¡lîy!2ãõ‡n{€Õ¤qØéíûÊöâ’aþ&'¸¬´Å`Ã^Ÿµl…å"l<ìžíu1¤¹D*ýÀaК̈́4© (€¥iaGWyøDn=²À- ³|æT ëkÔ(>ƒD*ÅéÐëpöð®”—gÿ-©”,HÍʉ£³KÅ0Ša„’gRß’ Š‹¿+++›=õ7—ñƒ(®?G¾!Írø4÷9ròò˜®Ó5Ip²óò¡«­…iÇbÁ¦­X¿pN‡^Çð¾ÆPãñÔ´<'¥gà쵚.Õbñ'ï -(Âëbü¯†3õëÑ‚-ÓµÊÊEhWg¼´Gšªª¯lïØ¹ Ì5죺—ˆó‘Q[g©°¼<€-hFGBš,=“¹"6ü0_{×AœÜ½,¶yžd5ä hm…sû iuuuZ¡ d~©HNg“Šaáäù‹UVGeå¹Ë7o9FFMw°üI±¶µö‹_,º£‡À[^û|¿Ý¡¦ÜWcãàŠÍÖ–Ìs\%EØÍšŠ¹cF|¶ããµàbéts&Ù­W".é!tµÛ0Ëo@s%E<ÍåËÕÚîåu èÕݾÑýlÇ›™ËÇ϶d&¥¥‹$UUóDÒ7€¯ƒ¦‰y)€iag¬Ý<ü÷9¹{Mq;Èúu¦Å;—Þ«O—¢c±ÅÝ«RX^þD(ª°.(.¾LgB1Œјç/¯èyQÑÏ‚Rá€M‡Ž'ý¸ÄN””žQ/;–‹™ËG^a*Äbdæò™nÏý{õ@Ò“ \ˆŒf^ÿr—h 3Sló< ©T*ÓÕy¨q¸ DzvÎ+ «D*Ef.™/Úœ¼|æï1Étvyù2Ç´Ëûl÷¼ò:ó¡&8…Ä”4€«ïË_¿dr±PøÉ˸B\‰M‡Žgý0oqQBJª«¤ªê[Jœ ù:é™L(Ú|ÄsÚÕ=.mŒºw½¼|‡kõä•kŸðÅ+œC¬–Ií]<+MËÌåw¢J'!„b!¯¢¥ª˜æÍ¬šUËmµøq¨âŠYSÙŸ³+÷…Èhlp;&óXoƒÎØgo¸gÏ“HLIË…a×Îp_¿F&™³l,'Œ‘Y{Y"•Âé¸ü¯†#'/ZêX5gÌÍL“—ñv«_9–7-+ev £Û¹ ¯3aáF½»vÁ简FÅ'`›ÇɪÇOJÎÚ§ÏŸ»ÐY „P #„’çÆîÊ-Z¸è¶o·uéâæú:m?è͇Î3K;½lx_£z½;ø5H¥Øã㟹ÓË·y¥Dº€#• !ä}»lïv&4üȹë‘F{õÄÒi“¡«­õɶŸ˜’†­ž'¥qÿ<,iÙ\Ñ!='w/h¦BÅ0B(ynBØJJ KPÇycGr–M7gs•)yn`nýó Ôr£Sþó¢âäêêê%’¨T!#pû£SWCÝÏGD˜÷ùÏÐÄ”4ló1àú]á·ï¶›5j8,ÇFÝø…Epõ= ŸPQ+5•c)Yö ›z„Ša„PòLíTZr÷)*(šn·µn^w­eòé ËEX±{ï?ç®E¶©ª®^ à• !¤¾Z»bÞ™°[£ãÔæŽ‰qƒúÃ#輂C$m4ÔO§dfYÈ£’"„P #„’gòªa\%¥£ÆÝ»*o]º¸yÝõ‹É§qêJXÆÊ]û”**+/XAAò¥íýÍÖêBdŒãÕØÛÊ:m4Ï<Îxjà• !„b!”<“·S|Ñ•{å²éS8‹&g³Y,*•ÿ(5+[0kí¦¬ôœgUÕÕÕV"©T!„B¡ä™4~º-””Ü•[¶0ܵün¿Ý©D>B…¸ßó ºÜ¾ªºÚ €3hYB!„B(y&Mθ把M¿ïÝ|Ób˲4À×.$æVúÂÍÛØ¢ ñm6žR©B!„BÉ3iº9öF–kño?ÍPœ;vd3êÊýfYÏŸ æ8lN~öD½ººz!€KT*„B!„Jž¿-›+i¥¢Ò}×Êe- :S‰Ô!‘Jñ×±wöû´«ª®>À€ˆJ†B!„BÉó×É¢¹¢âÞ‘?üOá…s¹j<ÞW_ Ññ‰Oæþ±Y"(+K°@2]&„B!„Jž‰Š’‚ü&99Ö¼ V?+L>´Ù×XùÅá¼ þs+1I Àr>tiB!„B(y&/ëÞ\Iñ˜NkMý¿Ú(÷ì¬ÿÕ|ð^¾±Û=}ô¤UU'¬PD—!„B!„’gò6?+p8Û&›b¯?§¯·É~罹™¯v—”£¦‹ö=:ý„B!„JžÉûRQTߦ Ï1ß´h~óIC7©)¹KËË…?oÜr7âÎ}¿8L§œB!„BÉ3ùX}8G;¶Õn·g¥­ŠnûFÿÜ£6<¦'­ªºÀ@fB!„B%Ïä¿bø™#/¿õ§±#š­˜9ËURltâñ“¬ÔÉö¿ç?/(RBMíH:µ„B!„JžÉ§¦¡ÈáìRPàŒýËzÒ¸ÁEWî q¥Èf뎨 ‘7{VWWÿ ` NB!„B%ÏäsꯨÀ9ÚC¿£úN;U]m­{ §C¯EýºÃ¥­¸Rz €-€§tú!„B!”<“úÂ`Í‘—ß8üh¹³¦µPàÈ7˜ƒ{šËOŸ²jÝ“'ÏrÛXà2B!„B%ÏäKi§Àáìj®¨0t×rîP£ï¿hWn‰´J´r÷Þ«>—CÿW]]½€#&B!„B%Ϥ!¢Àá¸õù¶ o»íuÖšõ~¡·â®ÏÛ°¥¸²2€ €d:-„B!„JžICðJžÍ^½ÄbR•íô)-جÏßWTœ6aùê‡)O³»XÀ‡N!„B!„’gÒÐér8lÕ-ûí^±Œ7 WÏ”AˉÖís»xø\P¿êêjok”RñB!„B(y&É(Ç­ÿw=8N¿X©ki¨² G'ü5}õz¥ ±¸€%€*nB!„B%Ϥ±R°F‰Ã±Y>{ÛrÂîéÊ]TR’anÿÇý„äÔïüà01!„B!„’gÒTè³Ùl·V*Ê=öÚÛ)wëú´œÈÙÃ;h»—¯quuõEöò¨X !„B!”<“¦ÈBžÍÞ=Ôø{¹­K­Z©ñxï|Ã?)é×Ç/_Í.-/硦‹öM*FB!„B%Ϥ©k`G~ÉÚù?aö¨a¯•[$®x2e•CL܃‡¦6p ¡â#„B!„ò5éÎf³£;´iÍÚ½U’|¦ºæ_@ù¦Åó½äää’xhGEE!„B!äk7CžÍÎo2ðÙ¹E(·ä^ðÀ0*B!„B!ä_*ö(à€šYº !„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„ÿo ýí °¡'ø^ÝCdÎIEND®B`‚grpc-1.3.2/doc/images/load-balancing.png000066400000000000000000000666511310511640000200300ustar00rootroot00000000000000‰PNG  IHDRÀÐ_w´mpIDATxÚì½”W}ç{×ÈXØÂ¶l„-›ÁÈf°e#9–mC,âd#Œ òa",@8ZP° ±‰aÆxØÌ%+-‹DVlPˆÑ& «åh³"ˆeŸ²GÉÑã(yJž õê[}š;¥ªêî™îžªîÏçœß™éîú{»n×ýÖïÏuà\Ŷ6¶ÑØöÆvÔÛÉØ¢Ø‚e÷ú÷òŒeY–eY–eY–eY¶JËžôãžÅÁ²Ëüë ª~Ìg¯‹mkl«ýb~l}±Í¦© Ë™íÇ=¡ØÝÛÁØNĶ-¶¥4@õè•§÷Hlkh€Bæù±“ÄðáØ†^a€J°ÒÕÂ{vº‰!>PŸW ££)Ê‹ž\îrµ'—Kh€)1‡&('ƒ±m£#\ •(µl{lsi €r ‚ 4@[ØàjΆ~šºÕY9†˜4•ÑZš c¬rµY6‡è C®ör>MÐQÖÇvÀQw #ô¹Údí‹h €iaGl#4@ûÙç}˜NfŶœfh/Ê;Ùï¹€.f¶«åý.¤)Jc3€6 ïïÍPT ú¤£*4@[˜I”Š-Þºšy®6CÇ,š 5,u¾(+šiÍ0uô4ñ”ã©"@YYÛš 5?¨»i€Ò¢:-*†5›¦˜›cÛ@3@…èm ¶EnjÑ+3ý6´­4+”9,–Ñ Sÿ1¢ Iúb‹ LžŠ]^`†Œ¬s<¶Q¿í4ªS ‡uÇRëœöëÌnòØÇüºá¶´ítŽÝ°ÿl8uÞÛܾ³ù~0‘…9¿ÐG]Í›0|Ô‹Á´íöŸŸJýƘÞáÿm „CA+/ï>ÿÙÞØÖ¸š×v¥Ùzÿ°k̼ÄÓ/œWÄ6Û:.ÚÖæ<Ï/·¶Íí{ÈŸ+´ ™ÿ&+€‹DÚz¿ÌH†îËYÇ>S3¶û÷6å¬ó˜ÿ¼Þ<™Õ'¼^’ñù,/<#/°³p§8Šh=M z*Ïè|/% ç6!€³–©'€øÏ­8_¿}°`?zˆwÜ/S4¥Û¿­uËhZ¸ÓO à™¾úrÚl½_w0ãXt.‹ýÿ‹ý²ëƒ÷ÂíÛù„m½~ ¶Ó `hò‚îqãy¼²3nÜ ;Ü„ðË위Þå_›¹^Èq#‘,ý¶æ4±­Fr€5(Ý´Ùqÿÿ”xչ˳këÐFSÛm˜Ë\íAäIš ­ÃÄ™„§y0WyÜ¨Ö MžÔ#~™¡&ðXJðÚëÅ-87ñ&×iDïñÛ…ªÎ_¡Öû3ÎMùÊ‹‚íð¨ Æmü@‘÷Wá¿YsƒæÁz• Wçܬ"X‡Ý¹­öÖÌÍþÞ5+*ë àE.?ÿx“ÿlIê܇êì ŒÛÚ¡u` ¸üpã¡!V–4¯ïˆË®Ê\4 Ò1¿^¢¼ÃÖŠjõÚΡ àunÜc>2ûl]êÜçæ´;À¢¨âñ€k,:œ²hmîkð˜,$»Þ|åÌ,}ªåf7!€7ºúžð©s¯×¶`@´™¥Âu©k<XÎþó¥SÀæy®7Å‘ m)äz~Á2ÛÜÄä<ñ«0ð=M àåþ³,›0@9£ À£Ðã3nbÕfc³k® ôr7"=k X…¸Ž{q;/g™þ¸ÔÙ– Íݢ }¬Alç¹>c[‹ýrý`@ðC åÃDÚÊà=Íi{Ú5? ÒN¿ÌÖ)àPdª8VÚ{»Èç/o`[vLòÏM í5^HwãyÈõ°ÍA|ÂMÌS–è?è·7’ø—#dü^ZÄl7>_îQ/:%âöMBËckó/ž‚v8¼àÝëÆ«FŸñŸ7B8Ïñ/2÷úã´B\ ƒå™I¢ü”H`Õ­m.àµâ¿¼/8ž5\–`hò†®pµ¼ÛM^š´œÞ9^Э¯³­©åVù×s&q\ò¤növ¯7…*O¦Bô?ÛÎ./VÓÅ´–øå–¤Î{YƱ=loÌ멱sOÓŸÚ‡mO±wûõ -f³Ë±³ÜØ4À´Am0´…+|7,8¥<Û“®~‘)`ÜÀ)T…+ŸUù±Ê>æÆsQñþ0nà‡º UGVá%UoV^«ògÒ,ŒÛªÎ0M€@ €ªÃM€à‡ÊÂM€@ €ªÃ^š À¸ ø!`Üü0nè†i0 PÆh0?¤Ph0 PöÒ`ÆmÀ)ã6à‡€q@Ï0ÜÆm¯ˆm#†uÈVÐ ÓÁ ÿ#a4D0 € ãÈ#-¹å™Ñ‡Þú k«é:óƒ‚t=@@cíÀ'?ûÞ­ÖVÓu†0L×)Cwrí1rçé‹XïôµºC÷ª&×#wž¾ˆÑ׌!€{‚¤Ÿ]wËs£{Þö2 kÊtÝ8RZÚ_yeô¾¿Ã&˜® úÃÀ-êg3[ÿä#Ö”éºaPÞÚ¾(±óÓw¾Ã&˜®‹öµ½t70†F#è00ëL,0†F#è00CC#€1 ŒÆÀ0ŒÆÀ`  `  ` ŒÆÀ€ÆÀ€ÆÀ`  `  PÆÀŒ!€Œ!€zŠ`a`0†0V <@w@c`0‚C#€±^À€ÆÀ`†Fc`¨¨þÉ®›£C_[ýŸï,¬»Ì?ì½¥RbÍŽ;ËôY™ŽõÿþÃ…Éqéo ๱-Ccà–3;¶Uþ†ê,;ÓÕ¦îÛÛ0Ö£x/CW€.À+å²äf±l`vÝe$Ъ$€í¸óì’YO‹Þ¶lN)DçȇŸ›“þö°žÛ>×¾‚q`¬Wð¼ØŽÇ¶Íáضˆßƒ±íòËõBŒQ ºG˶mº¶+ðûWÎM„ehyû•Ñõ×ÌL>_>ø,ðô `y™ûA:C·–M±íHyƒOǶ cÙa/Å~Y0†€îÀ3žöo¢Ë.™‘\uüŸ».7ìøÚ«.H–ù_߸ <½x$¶å~»` ÜZúc›Ÿòòžòâ6‹YÁÿKc;ÆÀÐ,ÃeÀ=ðìÜPè<ü'ÿî…ÑGW_ ¿zNôÎ×]}öƒ×Dó­#ì´œÞüýW'ÛÒ:&8õWÞXmCŸg…#k¿_sU²îÃož}gä-ÀEËØ>u\Úç·¿p}æú¿÷øü¤í´œ–?ð;7d.÷Í-×%žh[.Ý–¡V>¶þæ÷أϋ¾öéçOxO¯u éV;¦¿}Ú¦ò¸?õмäû*j—iÌFcàÎ\ÏŠ¸˜Q°LŸ0%ñ;T¶¾ˆÆÀ½KK°Ù’[ž™ %€%´ôž¼ÆwÜ<+zö¥ç'¯õ7\Nï­¸ûÒèÊËÏOrnÃå$õž¶!Óû7]÷Œ Ŷ$ªåžùôó¢Ûn¼èìú{­ÀÚŸ– …ëèGú’ý¥÷©í…Ǧ‡z_^dµÁEÏ8/9Vsèe~Õ—œm«[ú/<»íÐÛ›ö+<[m–.<¦ã Ï_ÛXTûÞ®™ûôdû:µk(ÚM¸Jøú›zôê—ÌF#€±ÞÀkc;é²ÃŸCúýƒ[å +$z6C@W `™D\::-€åmÔk‰àP É³é|Îm(€eï¾ÿŠ³Ëšˆ’P3Á§Ïl?ÆzOž^-#qiM-§mi¹Ph›<¦é*ЇÊýÕ篸ýâ žRÛ§y©µO;fyWÍ£«×òfÛº:Æž÷ŒD|ZUmœZßÎÿð×oJ„µöcÞì´¶¶Ô~Âs’7Zïïÿí&¯åQN·…¶/­ïÑÚÍŽ_¢ZÛÔyÚ6À`¬'ð ïÑ=æÅm3ë‰m5C@3´kPß2¬×x. ^FUâ7/,Ñç¼§4À„¡P>¸ýÆä}yœÓa¼¡”çØåäËë*‘7•*РÁaص­£cLoOû“—ռġ ´¦ÎWÛ5/rz[Ö:Ç,,ñ­ã³ÏÍ$`m{j-#szûÖ–v|&\%¬K> C·GüªÖ~W›j¬ˆ•±­K½·?ã=0†€iù!m©–¥C¡‹Š`ÉÛ(Ágù½Y8-tµôr2…*‡"P"W^Ìtg™B}µl:×µ¨ ´ÄŸ„»D©Âš%V³D®{Ö>åÖö$<%På-×k Rµ:7Y¯õ¹¼¶YÇ'1­sÌ+‚%a«}˜7ÙÚǼ½&rÊœ>Vó [›pM{”À`¬'ðzW {V.ï@`Ö¬BW6ßï›"½ÂÕª@ÏGc=&€ºôˆN‡B§—‘wS…«,oW¦å-×µU¸È{kVT™:/X¯å9Mç+›(mtŸÐŸÔö™<´*2•u>iS»˜G9Kÿ‡OÖ®¼Íî¬}™è·uŠÌÚÞ„ëd _uX+?ñ10†n){\m>ß´Yè©O w>á…ða/KÕÀX0ôŠN‡B§—1¤ÜYy!CaÜJ,ª"Uí˜É<¤ò$‡áÙ¤õB«³¦SRX¸r“í¡€^+ÏXÿëaAÖzòþ `—¶§ òë!C8g±<ô®\èŠ à²‚Æº© tš…êÓ`  €n½C¡åÕ —±0át…â?~ª¿¥X[žÚ¬9zÖÛjVëØºìR…¬¬²sV{HȪú²Ö•w6?†%ëû§Vǯ*ÍY¡ãZÎòwóæÖþ¬²´ „…yÄ¡(?“ÇØ–G#€1pªö<<}öã·¿=ú“7¾1úïoyËÙ÷ôúÀƒ–æÿâÍoNŽÉ^ëXõú¯V­êV¼—¡+@ `½'¡ëR¡¿ªt¬P\‰¸°²åȆÓëLE›˜”H …¦ Ê𳏙i4¥M±dE¯$í˜Ã}š·ÕÎmëúçFYínQ•§ÃB^¡° §F²ù|ó°*5;?…’D¤ÏÁ¦@²ýÙöõð „®`_ì6,!™>/½^|å•¥9Æ×__‹jJ‹Í¯¾úÕÁ€îÀé9gíŒF7/€?30ß·–/G@u°By-\7ouJ/#!¥ŠÊ{úkžLy"µ¬U.ÖÿiQ§íè}í;-Œõ~º:³ri5Ÿ®¼šÜ ¶í7rnE…²´…6§—S8·rzå©•¸U¤Ã%rå V¨±´þêüÓ¡áz­6 ×9h»ésÔë¬s·¶Ög¡Ç=}:µ¶¯¶R›em£¨-Ú$€•[¸)¶U%ëšêeƒk¼²m)pÖñÈ£)qªÏCqg8KÚgÃÜ;Ác¬÷n~É ÎzdÍ›+/°>»ï=¯,<ÆÍ°.ºøÒY‰=üå·Oøì=Ÿ{0ºàOO„užÖ_yÛÑ~ÚvºJ$€ËÚoJÓÀÓ/€™ ê1\FŒamÀ6xÿIàa,›çkcpl‡€wTKdJ0Jümú½µÉk ¶0\·èx´œ>—°­'€Më³…/áÙý_>ïÒÄòB„录7¸èMØúÍ‘Šô›NöŃE}±XÂWÛºøéOn¸ì²è‚§=-ºmîÜèò /LÄ^(Dï¹öÚè¢óÏ?{|y§/¸ôÒèù³g'ëèµ¶¥íHè…ûzäÎ;£ç—lCûÐrÚŽÞ/À}_œl[vóå—'ÛкãEç&!©õ_óüç'ëÜrÅÉqê½Ák®I„¾-û_ßð†è9ÕŠBjíSÿÏ{æ3“ÏšÉþäK^’œ¿Lû¼tf-EçW.œ°ôC–]rÕU`@c¥Àõï¡íõë”Åö6pÌá¼cøšþç$‚L¹³z-ï©„d––È“X MËHtJ$†Å°Š°Š\…‚×^+Ly²ç!a«m¨ðU£ëÔÀË×.­U>ÿJ´ËtÌzïÝŸyÓ„¶ÑùKðj‰uµ«ò™-ÏyC «ÜoJÓ§*€å 5akžN‰P‰i,“`–p3/ª¯ JyZõž¼¡Å€æ•@Ôr/»úê³Užµ¼^Kœþáë_Ÿ+€eò¤š`•×UBQâ4±yX‚;ôÀÊC­÷õ×<¿¿Z.²òë=µ‡í§žÖ±™Ø–×Ú¶w_­nˆŽÃÚBžá¬ïCžg0@÷0†ÆºHo`ÐÚMö×À–»ê㯟ð¾*5g àSq/åõZ5éz9À ïV~sèuÖÿÚN(Ö+(€«ÒoJÓ§*€U€Ja·æç ଼Õt°„°Dµ†J{B%0óp–pVåh×`°ª2å›÷5k9Ë5¶i‹ê `û<ë¬óN·¡åÛ_k«’ འ]ÀS2‰ÄÛn¼(zøÍs;¾oW_vKÿ…™¢|å¯\–|¾l`vîvm™PÜê<zàÙŅ̃Ÿwξ–ÜòÌsÄîGW_ÝtÝ32EtÅp×y©:QÚ ^IнòÁ»’ŠÎyU óŽGâRÓþ¨š´‰Ëf°„·òƒµŽrlu,ÚŸBšõžŽ«(ü9ËÁ:MˤmH8ëø®Vª®'€5=“ÖQá.yÕVÅéŠ×`µ‹ÖS¸x3•ª; €¡8¬ÌlÂTy°yU ó° ByÍ£«)•$Œ­8–U8Ö6¬¢²þš'V¹¶EU mª$;Æfª@k¹P¦«@ëxµ=ynÃ<`yŽí}óÞÖÀÖ¦üáCó2ëÁ@è%WiûY¢™"Xà®ÀŸzh^ôìKÏO<£Ó!€¯™ûô¤B[q÷¥Ñ%³ž–|þþ•s3Å­lÛ¦kÀo[6'yo`Ñ3a-/°<ÀzÆÓþMÒòÛòò0ë½¼ýJ0øl5h‰Ey~åÕ?i¬bPEÞKåÖjåéêµ¶£×Í‹¬ŽCbZ&á«m×›8´õcïH¸Ä¦¶!«ó31j¦óÔ1Z/_ú˜µ­¿âƳǣPìtÈxVÛ¤·mÛ׃½ßÌù €«/€Ã¹ye6®‰ÒF°æä•ˆ“p–ð“hÔöÒó¿í¦›Î RM½dsíZ!«<ló+¼XÛ×ÿÍ̬ã’ÐÔºÚ– ÔP<+÷VËhÛz  ðd›o8ÌËmd`{Oí©ó´ :ÿô1ªèUò`xŠsÿ"€À¥´¿ùÖ‹¡)oçtìßyïkÖg‡¿~StíU$ËH¬¦Å­Dëe—̈þ×7nª+€užZ^žî,îÇ×\•,Ÿ»z8 öÑúàÞÀ ¾ï=¯<'gÖBŽ­XV-C—S›ð”–GTbOÑ´àÕ¾l* ´– Õ64G°ª>Û\Áy^gy‹%øä …£ö«ý¤Å¤ö+o¬ÖÓö%˜ÓÓ. `…t+¼Y¢WâÞ™Ӧmj­2µGz?:–°Ýu¬z. ¥vÔñJLëPÈu: \aµOÙ½Ààö `…+4X^MË™Uegå½*Ô1‰†Ö`å¾fM#$Ϫ˙7O·J¼µÒL‡‚ºl&q,/óTçþEôè` ìøúkfFwÜ<ëœ÷¿ý…ëïªÄŸò`µœ‰Õ0TZ×>Ó_…3kå纔çv2X¦m*o×Äw(n%~õ¿Äv‘–H—'Wö{Ïoª2-O4¸w°U‚V!,äŽKüâýECë°Ä¯¶ó±»î:,Ï­Bþ›çÅEOÍäéVÛÊ­ë¬Ðh0T^›WT…¡ÒÞP‰_å¿îÿíž}_y³·ÊÏ Å¡Þ“wØÞ“5Ð üê—ÔÄ´© ŭ¤MØêÿ¢`y©u¬zÿÊËÏO–ѱ֫:-ï¯Ö9ð;7 €{X[&|Rί Z!"ÀÐZ¬ÂNš~GÛ ‹1É#™ÎßE·Îlj%çó¡Ó•±ÀÝÅX¯ `Ò1Ž~¤oÂû¿ÿêÜSËŸ•ˆH…Kj¹w¾îòÌåZ%€MÌÚ¶ÒâÖw %€eßyA"¨Ó• þœçÎk'pï `  íÀa«Âµ=y%ÓÓ"ÕsõŠQM—)WçÖÌùtÂkyÞ[-~Àå£g‹`Yá§´H5ñªÏ%.C³Ï$%ó„²r‡[%€-œÚ<°Yâ6 '€Ã¼e›¾…€›–—8/¹Ìß%Œ!€»IcÝe-Àt7ð”DSZ¤Jº‚ùyMhªrtžÈ5¯l+°rµœåg‰Ût(t=œ%r/zÆyIèwºÐ—Šz!€ÀÀX)0 €[ë¶œÛzó›X¹ÁíòKÌ:¢\/¼9 …N/£0m½.ªJmÞíôvñ#€10 €10¸âØr[ÓÖÄTVh³D¦¦D’0µà°(VZDOUkÛZF‚ºžC¡åÉ —É›ç74…B+¿9-üUàËeTšF#€10 €±Ž à½t7ð¤L9µ:ÆôÜ··*¥©ÂÊʪ­0aUPV­åçJ4Zî¬Â‡-4ºQ|Û%BÕLÂúkŸ~~2÷¯}†% ` …¶ýÛ2ªl­ªÖ:Vox^ú_ó»œy‚­ ´B¡À`  `Œ"Xà `™Dn–VÞ_‰`™¼ªšîHÿK\jŽ`[NÕ ž¬sµ\‰d¯à"“À–x-šã7/ÿ8½Ì?ÕŸÌ)lŸIËìµÎ1+ì[ïKô30CC €+,€åÝ´iÒŸÉ+o©Â™%Du.Y9´òÎÊc«m)TY˘ «ç5ÕriÓv–'p’¬åÒÂ8´O=4/sy®•»ü¶es‘.S~ð7·d u­/áÿþ•sÀ`  `  Py†{YK¬Jà)Gv2ëJHf‰G+(U$R«`ôjŸ¢âY`0†0†`0P,“—W¡Áéé1…k]y‹Ãdy•å]­²øU{(Dü¡ž]úcE#€10C¸SÞ«DìãéuŽlE§$†•ÿë|᪲{M뙄¼r«àÅF#€10C@#Œõº–)WWy³“YWQ9»:W…R×+|U¥ðgΪ±"€ÀŒ!€`:H+%€±jŒ!€ÀXàºC#€tŒõ‚0†F#è00CC#€1 ŒÆºE糧 €10A‡!€ÀX· àY±¢» €10A‡!€ÀX· à¾ØŽÒÝÀŒ ÃÀ`¬ÛðüØŽÐݦÆÒØf"€1puÝ×ÝòÜDÌ`çÚÀë)|ã´E†éºA·¶/.¾òÊDì`Xhº.ZÔ×9Àå €1p[YíÏæb«¹eѱJô5­?Fw@cà^öd­öçÝë6Ûwcû‡`°ùãØ~Ûgb;¼<¶ÿÛçh7Ä/}±m¶ÕÕ 6e ÁÓ±pµ|Öƒ±í‹mwlÛék…l‰m-] `j,ò?¨`  Ucal›\-'.k€ýÛÁu±À‹áôr|opµÜ:h-ýþS£Ò-4Y!ú½ZL3L9®ö„vF;ð’[ž™ˆ k§é:C÷¼èM‹[] æõ=æ㶤–ù9b £"øçâW­æÒ\…,hÃx  'QèÑP‹·I>F.#´ƒý¢7 q¾3õž~ãTðïïrÖ ·µ—A&@ÛDp^¿ý"ÍB¢aG›¶KF.#´z ýÿÕ±«\Í“~¶Ë¯¿´ÎCy‹ñB´Wÿkªß‰ígþ·|6M•É,š uèf£bóh ¨ë ì!WóÞîÏ`ÛoÜïå¬ûÏ®V:+‚ü!|Êû=H3´–-ŽâP îŠí_\v>¯<¼ss®åˆëórÙÞß4/@ÇDp˜û«üþáLÔ.kh€Ö2×ß(þeF¡îgÜÄgó$íñˬrùáÍ3‚턟ý½ÿ«¢€Ã43@ÇDpúá;Bx"K\mº¨™\6­GO‡h(!Ês§KyØM q^è—Ý™!~M$‡¿qîÆ‹^ÍNmŒ'@ÛE°„]^Î=B¸öÀN¡Ï+¸\z‡ù~hÚÁàp X­ÿèòs„wÛ]1öû°i‘ˆŠhvêe!¼1õ›m„œ( ý€Wß#îÜÝ~ÿ¹‰ØzUžÃbXyð…n|žáS޼`€²üô’pµ0q ”tèG÷plsh ˜f$Púož·¨/øÄÕŸ/zcƒûÝÛnÇœÀáΣšƒ|ÝcslûóÎÀôÓÌøpþñ½n<Çw²sF“ €€a‹Áx‚ Šlt{|!<Ýô9ÓŽ<Á ‡î§) Í,oñà¯]x®ß&¡ÑáV±ØÕ¦j[ÎW 0ý¨*ê‰ØVÒÐf<ê­Û* €-´Z2¨@O•u~œµ”¯ <¨ êÍ-¦/¶n¼âòpðWóÔD ZÂSÍÕyÜŸóv „U×`¾«9ô°OùÑôÝ…ÂW¸ÚÔI»SŸEuŒeY–e{oÙͦÍX–eY¶›–Õð#~<ôXlËÓÀ4ÓMóL;ä „ ËQ¥x†ZÐÃm 0ïÓ±­år@@wb…¡¬:r¯²1Hïd €€îb½›85Мi:Ž×™*ÐõXæÏíšïÂÐaTåtG0PÜä¦wŽðNÌÜ(}±ôÇ£èÕ\.a¨&ý±†C%8¦2 `¡¹AG‚ôz.„0TSŸr5/çü’SÙ°±Â?, :4B*ÊbW ƒ. eÀ€@BÊC?¸-¨`ØVWžr@ô4k]mŠ£Uà–³Þ¯r©Wp© „§H_l+]-=e*èáœæv_î¦oZ;€Ž¢ÜÞmÁ`nsŽyÀ•càfÚx{ÐÆ[ÝôN#Õšjí„ÿÝ>ä[&ó{¢ß%7Üç·¡m.åk€nf¾@™wr9MÒöëßÞ\Í‹áfD«~«—¯OR¸®÷â7ü}:À× ÝÊ2?мî§I:¢؎åe4 B¸Aføý„¯¿#z½Ùÿ¦ëý½.?LZ!Ï}Áë•~=CŸm÷Û‘0â+€ª²<¤i€3‹&é(³ƒ2•¬“A‚uwl»Üxô7]¢ý¸Z˜sóýzG‘«íiNó­~;zÿ´£T”™~´Ž¦˜V9@O–M±¹š‡vA°Ï¾@ÄûÏ‹ðÇuØ f±Äo˜[¬0ë¹|­PU(ÂP}!<â·ï¼øÝæÅ¬ös l($ú´ÄÃM¬M"oC3¹°®ZU ›Ea†< @§‘ÀMWêWñ* sÞçpŸ=X dB.žuÌÕ¦jSÈóñÔgKÝÄüc€Ò¡ÜÞM®Ü9¾sü@k¬‰uª6p3Ìóí±Çn€>÷7=¬Ø¯×Q¬<Þaÿ¿¢ÙôFÆâ@+ï÷PpXá·=׿wÒçÛïô_” rúÖ¶§‚GÀ¨Çýù1à@§YæÆÃ›Ox‘;Ó¶Ú‹Ø}^ÜÚoåÿùÑàwsf øß›¡Ô~ŽûÙÌWee© ià#À‚’ç*W«`º<y`öøsÔ¼Á빤¯}° ™í?›™soX“zϦCÊJ»˜áÆ+J”Ž8Œü ª¬áÏTõbœý]n¾ËÝ9ƒ]è]!Ü,›ø€naŽIæ5ÜPrq·ß¾Bç#Í ¾¸ÌÂP+Šy±4XòcUžš¦éö¦ÁÞ>×ø¼¸½$€Å<ß>\æaš ÆZ/–ÊŽ<¿c©X—r•C „º™fC \wÏ €ðÌì²ó‘çú1¾ÖI¡\ïÕ4B˜¦€nDù½Gý z›Á Xóy΢IÂ4 t òöñƒQšbVÄvÊ_‡\yç|„0@Ch ³ËOqDñ'é÷â7òbx˜&@÷¨^áÏòl?åG½#Á€f)M(üy,üêÿ4 B¸‡„ðŠà¼1,ÏÁ%fȇ·jª >š$aÀQ:aÍìF „{L'Sä]ÕWtû²_ð ¦ëÂ1…"@é™ïÅŒ¼y3iމƒnb…ß94ô˜Nî ;ïý­6Át]0v¨óh0BŒ!€ 3×F€î^!ŒÆÀ‚âVàv¢|à½~°»Œæ@w¡Fc`€  ê½;üòšÜÆë,ìnvÉ€îÂ`  Pr4ÅÑá`Ð1D“ €ÛÌ:W›KZí·Ï‘cÝ#„À Ä,wãSrµŠÏ€îKb;æÛð„#üºC#€10@ QØécÁàb›«…§Bã 8æž*š&i·¿O;Šc@õ…0C”uþXa¨äüBŒëhè!ŒÆÀ%dfl»b[LSBŒ!€!ŒÆÀÐv]-RaMÂ]!€ïY3–X™Žiù‡~?zŪ­`(d¾Pà ª† µÙô\ª½ˆ&€ á®ÀϹ:±2Ó ïz ù~À‡æóµ)޶Ò-gÀQºÝh~àýn¼`ÛZšJ.„À`0@‡‘çlS0Øáð·mÃM¬#×ó–àzÞéª1(ô¦F#€ÀD¹’{ܸnj©eÀÝÂ2?ˆU›‰­Ÿ&€ ážÀoýÌ£o‰žõœë’uæ>Qô²?­ùòñ ˽ó ?Žn{Í¢+úžÝþUýwECïýÊ9Û|ÍûþCtåu·'ËhùW½k ç Écþ‡õ¸#4Ü}ôÅvÐ_çsi(¡î)üà'þ4ºð’+¢§AtãKLÎ[ÂUm0ÑkÎ.÷î/ým"Ãån|{ôŒY—&ËJðÚ²/óãÉ{—]õÂD0K\k=í !+üê~ĸ‹ÑÖx ¬B¸§°<¸ç7#©Ð¾/Ѫv°ªÍ&jÓUœïß°;y_Ëëõ»F~]pá%‰øÕÿ¶Ü½üº}g`˜€ÂDgÐ `h‹ž‰®ÙðoüEÒ~/¸ãþs>S¸³„ñÕ7¼,y½jË¢eøZâ —S˜´¶¡ðf›~)K(›ØF €¡†ü,¥ BXS *ÊjøDôº_ûFÒn/}ã'2?—7½ ­³dÅG“ðg‰cy{ClQžáôön}Õ0@Cˆ3&²Ùc®¾‡`2BxÌW£Ÿ® àÁ·~6ósòmȬbVZþü .Š.¿fAâ9ÖºYX¹Åyâ ЛÂë´«½‚écÀ1p™vãó^«PÖ|šZ(„õ›òóà³Çz]¯xdOÒ/¾gmæç*p%/°þ¿þöûΊå°:´ò|C¬êÑ.UËLųÀ½…nÀ»ÝøGkh€s¯G|‘^A“@‹„ðŸ¯áÿ®îe¬|^…0_rÅóΙòÈŠVYq+mK‚8kº#TŒ–ç7Äa®ð¬g]‰è±›ñQÿ£y"¶Aš åæmª[…á`êBø_ƒß3=Œ^Ú­XâVç‘e6w¯òyu¾×ÞzO2°‰_MY¤PgÊÒ{}/º;YNóùÚ>´ ›ÚH®ì}ók?ÙÚ®¶¯¢Z`€Þ@¡§ýæØæÑ$uYí§y^€FùÏâ×LÑ& ºQœóíâ×}8™§7ü\^á°•<»æÁ•°Öòú«gå ë3ó"+,Ú³™B©mj%0@w³!¸Œ:ùT=œ¶X Ÿ˜1cC ê‘6w)sû"€¡sߟU‰ÞãÆ Ø@ ×%±mˆm[lûb;Þ¬ðõöß/¼ðÂMŽh  ËJW›BA?†cë£IÀÐ14Ÿöqÿ=êïMÐ]ŒŽŽÎ{òÉ'c[522’ÙÇŸzê©Mi1¿÷¯MŠß?ñÄsE°00@& ¹ÜêÆ gŒ9Š]!€a:Ѐu‰fÎàîa±«=XÔw›Îù£ïv¸±Ý‹Ý]ñßñN‰Ô­YëÅïÿf,xÿ%CÔjý3 ˆßÿ'¶þðÞ€ÆÀÜûp#€¡T¤6ûþ8@stª«pÂÕ¢lÄ2W‹¶™ƒ®ccc³cº0¶å±¸]ÿ]™µœÞϧ gþÓØ¾¯ûHÎzËý²GbÛ¿^/»(ÞïÌøõÖ¿gRžåR`ÍŸ›e÷¬;gßfìÍŸú³d;ú‹ E4ÊcþÇïXl‹h0”†>š kP¥ïM©÷$€—XŸû>ÿÍ£££‹3B‘ŶSëŶ"k=…!Çv*ËKë…ðæFŽÓ ß-BíÅnNý ÿþ¦ŒÕK#€ç>Q4üqÖxtot÷;G¢K®x^òùýv#€Àç°Â‹(¨zÐxÔ‹]EßÌð¶`9y€O:¦Äj)Þ#»ÛçãfåÒÉZO!Ïò¬ª:³/,eï+$y‰ Zå¬7Ó Õ£±8Ý¡Pf-¯÷'#|uÌñ¾~[ÂÝ{¥Ãcßž³™Òà«úïÊülÙ¾–|~óàÛÀ`€ ,õƒ ÔÒ•ÂëЍþ{î£©Š‘8U~¬¼°ÊÇ…àhžTXqJ4S²Öñ¹¼Ë‹öå=ºÂ[ÃPf™Ž#ïø&y^Ï'á;&á›:žÝþó}¢ºôøÁOüi¦–GøwÜ=ë9×EϹ:ñ¿ð®ïq‘~÷—þ6zé?]yÝíÉz2yŸÓaÖ _¹:1y¢¯½õž³ûÐq¤ó’×|ùx²Í+ú&Ë]vÕ £ß³6z×ÈO',·üC¿õ½èî³û½þöû’ígíWÂ_ç¦m ½÷+`€6 »*â9¨.}n¼’ðiGѺª "Xý©÷þº3GÏDçãsdñ{ôÑGgäˆØ¡‘‘‘zaƒõå…2ÇÂyDÞåVŸ§¯>GøÞ |$ôJWMKX.xKòùë~ígß¿÷ƒ_Î;oF"H%4uüó½&YnÖ³®LDnž¾ú†—%ïI|j½[_µ&£z/Á:½þEϽ闓ýH4k9m#½Ý ,(/ iVØsør·ÿm6†@ëåñ^i‰UÖ»4tk|ØïN‰Î!kâ÷”¡;|¯òyóÖËBbX^d…(ç Y<Çüßu>zÚû]V±¬² ` =‰¿Ð$%@_þæÇ',/­–O{bM,ËÓš%€%œõZ¢7\OÛQ±­PØš¨•g7\Öô[?óà Â6݆¸z_âuÕ–%Û—‡8ô ë b‰vʶ_;F½oŸ!€¦Žž ïuãS­¡Iº†^TÙ¼² h’R#Á{ÀÕžw¹Z¬p$ ÞÑØ6¸‰S&u5Þ“[4­OÖzò~Öñ|æâÅöJ/´¤ J­ÎÉ­>÷ Çww›¸4XÑBƒÍäuÞ“*iË+l8«(–‰Qó§°§Äq¸-3‰P‰ÑPkÿæMN‹BÛ‡¼¾:öôrÕ*â¥ly–µŽ¦uJïwÉŠNØž à0”›`€Ö°ØÕ¦6ŠüÀj MÒÕ 8ª@÷"ý^üªŸï¤9JÍ ÿÐBýTáΡ7x‰ÿ.‡½®d~·¼‘ª˜¬|Üøÿ š:Hù©~îÛþ:XÞÕ= '¶|\‰ÜV Oï%ÎÚ qM͡۲Š[åµO7 à¬h‰Jyõ¹¼§ágïüÂAi!Ç—_³à¬`ÎÀf+Ù“xv•k++O³–“èN‡@ç‰BÛ‡åüŸy¦uŒi/·Âõ™y¹MS  µhpuÆÿ¨É<—&éz˜¸wQ¦Bi™Ê ÚNAHòž:žÜ¡<1ØL¸r½cS(³Â¨ó ZyÏïq?…Ñz…Kw*”9§ªsnŽo/`3‰T-#áª×¾ Ö{¯ZWbVª\°òyõžÄ²„«r‡å¡Õv&+€•\t~*Î¥u´/ýŸe–ç‹hËýZ8Í €êŠH_íxÈòqc‘¶ËOt:OȪò²ÏË= |\Íq«é$0GGGçµãX•¯+¡ëq*”yw™ÚÕWî¤ð­”6)Ñ)ϯ…K«Bt¸œy‹óðâ×}8y­üÜtȲB '#€%¢%ž³Ž[!Ù:FåójtÅç,C´òÀ3iH#gž×Ó‡-yr;–#[GP.É e–¸”à,S›ûŠÍ¾•ÀòÚJ`Êc«¼Z O—QÈJf• -×6-€­€U:ئZšŒ6¯sZÜ*×ØÚ¶h.cy®u~–ÓŒ@C{Pô‡R ¶:"AzËÇUÈol›$l½—ô„„¢*ç5-{DTåãªâq¼Þ2MÔ©Pay¡½`\­ãÉñ eöÞé ª =Ù9w;øàa:Ò‘J#€%6u¡Iäª0U(%^m $«Ä,¯°U]oZ›'Vž`«¬,áiy¸“ÀoþÔŸ%•ªµ ÑÖ_½Öû&¶U¹ZÇ}çë?’ˆzËoÖ{Ê NWFL~€»ˆf0d BxV @Õ‡ûh’îBžÄ‚i{6xqŠ[šß …H+”Ù¨Úç§6:{¼e¶¡ÀU8v‡=¼•Ày&﨎/œ H¬¬à•°R‘¬W½kôlˆs––Y!ËzOâTyÄ §Ö¼¼*¤e^æf°L^;Žð¸m:&îæMÂ8ôH#€& Þìñ\D0 €! ý6õׯɨ–Ñ$Õ‹ª!ylã¿[å™õù¸g¼@ÜšµžÏU…åíò¢*×Ï][º¢ˆæ•N™¼ÐÛtÞe˜o·ák9¾ sFO4Mù“eYÓ™Éû+Á+qkžWÛ–­'O«^‡sïJHK¼j=ž2Á+/²–µÜ`mÃ<ÌéêÓáraÅjÍ3¬íJ§?7{Ó¦ï%Ó#i¹¬œ`í· S !€ ŠƒÚpŠ£šÌM r÷l§÷Hlv„D—y7U¹X–#dWxrÉkZæóS(³ߣyžQž½Ë{­‡ªæñ¦âV•ÀX9  UASö?Xûc›G“€c`¨Ï:7qz4Dp‡…® 3ùÛíÞ;{¢^ÕbŸ +¯ïVïR>n§‹N5*•/¬ Ðñ±îM‡2—­0վ˙¾`  •Gƒ17îÅ¡° 4ËW‹Ù@S´‰bÊ›&ÈÏO›åÅ•H<˜Ê\%|Ѭ¬Pf…a¯-©@œþ;+³ðEc`¨<ÛüÔ©ØVÒ0IæÐ“ÇW^çÅÞn/ð&¾Á4Çç´nRX³*4—17y½{D!Í9"E¼ÌŸs,Op×^kz QAÆÀPYú\­’ëBš õØÔA^È­ÉZƇ2gæãzñ7Ò "_Ö‡kï‰ídê\wöÈÃŽ¹±ð¨øi €10@®ÇrÈ}®êŸ›y‘æ£ÍZO…§,7¶þ¼åªJ|~ƒYß·Õ:=$èváäø/c¾5CL…âžpµ"Yë«|"£¥^œ®‘ɨÓïHôBosUª7)úû}eiM©´-kïå–çw³<ÁU Õn¡ð=[ܪâ¡Ü`  ¥G!Î[hh’Gh˜<ˆ›Ýx‘=U$®Ì _BÍ ¶£9áÉý9ë­V¸³<šÝ˜¯ê ùé…vgx¹Ï”}ŽÝé¾]R´ Œ!€ ÔhŠˆSþÇh˜æ€f9ÜÄ`Š,u5O°®%U‹^4¢DÂÔ{+%à¶ŒŒôe-‹•ý•‡wûBUëzŃ™#òOfä*ïT»(¿µÛ·'ÙF»Pø"€10” @Fܸ÷eÔÕ¦=@C§ÑÜâûýõ¤èµÚ±/ºt0cþX³¼)†5‘„K¯:«/Ö%Ïå<ѦÏ}ÎòòÑÑQæÏ@!ßzXÒeÂŒ!€ ÔƒÍþè´Ãó `˜~$"·¸qOð¤raU<ÈOŸ3ä‹Fmõ¡¸KrÄÚ¶T>î?‡¬¦ÕYÕãžÜ%±mˆÛaWFîr$1Ìe[L^?ɽáªþ»±ƒa¡éº`ìfЇuLq`(Ëb[ÒìJ±[ïCm³¼¸‘ÄpÖzËš_µ‹Oµ@¦Úñ„e–($—·XøZޝŠzõØé¯vãÑe–g«ù¥€N±ÕU°à €¡'„<Ã>Ly»÷ήÎk,§2¶ÃÞë»UÂW„PÜ ¢¿OáÉ^ íË›Xí¦e´l^.4ä ßàzÜЃM±Úß0,Ë¿ÐQføž4 €¡løi„òòqe[ó„G—æSNŸ»»Þ{oOd´éNZ©õ· ‹[ €ÀP fùcy×ù¸GT(k_d) ·õ•–·É|ï½÷î¼á†þúÖ[o} -ÛôC…¡t(³ÏëÝ B^„O ?‡ñ)„/ÀôàÚÉ€c`ÿcc™Õã}ˆmT`»ó¶—!È´C®öÀEÓ¶Q¸/FaÝz¸à+.ï•åà9>”y%¬mF¾Ó‡US=‚€V-ÍߪªÈñ@s,¤vø|\UMÞ“µŽ KY>®÷6nñU™åìŸÄÔA*¸4æÆ ¨Œ¹›ºMuïIß™SðëtÞ €nES.ìsãóiÑ$P„ÄhÞt-^Èyrvøpåý=åã´ïžò¸¥ò£õb·/6D(s[>ÌõqFh €ò0Ûq7>æ"šLäÆƒ÷…>4yòòÞÆvÔ‹©£YëùüÆã¾Zð6Ÿ7ºrttt±Bk§ét4}Û7½ êâÊçIoößÉ©¼ªÕþ»[)/:Wuç„oPÜêô4^÷°ÎÕ<¾*$q.MÐ[h`.m-ò䩨é*$z»«MéV9$b}(yÞÜÅDï”KøRÜ  DŒºñ¼¸ÍŽ)Žºšx >¨ùp}ñ#‰¨ƒahl^~­÷âîôû5ª¬ý$òqËD©s^•·›ó]lK…2ïQ(³÷ãaœÞ‡k¾åf™«….£) ƒ 8ª@·1Rx«Ï霙#žNäx %¤äåóB{ñÕ–‡|N®¦{:)1•µ¬Ó4Q´\¹ð!¾%‡â'Ði˜xê‚i(d¯×*šÂ&›'Ž|þî¨òq5o®Âž)€4¹þºl»g[B6þ¶+„<ë¡E“ªIü½öÑ €nŸC¸$¶á¼‚F±pÝŸ!šÎx1µ›BG“f¯¿6U^+6˜÷€Á{ í»;¥ M×ûyß;”£ê{âÁ@¹‘WƒÂ(€.;LûüÚC©©j"}žµžòpýz«-—˪%,qµJøº>OĶ´Y±ëç+Þèç0Vhù¾œïP…ÇV©Â6Í^ á›*nÅ<€’²ØèÎøÿÀmF9¸ Cö^¾uy"'UÐÈì„÷ðnÏ«Ì mE…¤v»ñ9Ñ C¢}þ®¾ÇÃ]R%Š…/9¾%fŸâH¡}¸pðžÜ1_-ùx†Z—#ž’\^ͱ+‘LXeé®Ó³SÄ­\¹ò¶¬…T ;GòàïóU¶—Ê\]¼7á P4}ƘŸâh‹cŠ#@7ŒUÝÀ› B’7däãöa°[´ ¾öj‰Mµ~ýúßzÏ{Þsú3ŸùŒ}¯™Ó © ˜`T|Z(˜x Ìô³¾%G7éƒ^`hŠ£4 €Ã{dwù|ÜÓVæ•øñóëâõ«.>¯úPN(ó‰ø»%¤·®‡A„/@ùÙãÅÅáØ˜'ÊÈ€ëà<ÀO<ñÄ, T…¤ú|Ü‘¼dyòR¢ç¸ÏÇUŽç<¹ÕG(òBÍãkc‡ÿÞOûï}‹® DP÷¢_ ‘T›>ñ\-  WEÎb/`Žçxóöä †æ¬±„3-Yyq3K^4U?éE°æû%—´¤øß „/@Ñ€.œâh)M¾šRäDŽ7±<±222² BJˆ8˜p2¶í%8Ì>7^yÿtl«ùæÊy-!|ª‡ZÜøGÃ4 L×`ò©§žZê§þyÌç×*ÏöTžXõøÔç?ÿùŸ|ä#9üÈ#|Uëk; J{yku d}朜ñ&!¼5¶a=)Ùièšqã&×óÍNy¾ zh€xÂjDÎÌ«„„ŸfZž8‘Ðñÿ–v`hÿu¥Pf¡ò¡ÌGƒ€¼©‰V(@ó®k º9|Û%ÌñeZ#€ê#¡pÆ‹†]Žb+Ð$H•Cë+ænð9rûlª˜7Ư—e­'âňBQ7û|ÞÁL„®8 Iöռׯ×Ͷ؎ØÃ Û¬uŠÆôÈo¸r„g-úÍCøt) ÊiËó¬iðWàÉ=®ùOKvJà 㧯:Ê_k{ó¸ô8ëÝxñÂ4ÇÔñÓ§!|*޼}4Coâ++¯ôù¸Û|®íñ@`¬ËÊó»Ç{t5Oêr/˜ËêmC—åqûˆ‚̨F>Ê`ÔWò^˜W4 Ô·»ñ*Ñ[ýï=L®7€ê£°Óý±uTíJªã¼ ¥Þ³–åÅ•·íÂM»¤)À% eöQÊ|8eÞ•µŽ¬ôp(óTÑÁVÐPSÚõÑ$Ù9¾›i €îCņŽûA‘0…a*Œ÷ä® òq‡Õoå©ÍZÏ{ݶkÀ§÷×åaŸG¾†P採éÂvúßý 4UzYÁÈÂAx–l@ ‚MòÊú|Ü)A»'k½øýþضJèª ¦zQÕ\ZÚ…D«Ä«Ä®ÏË=^«y4|«esÏwr@*¼ÙÏP‰iòôÛŒðè=ä…Ü \6».Ï÷Õ GÂT9Š~J‹mšó6OÈúùpM ÈãµÇ‡&Þ1å÷ruë¼à•íõýboðžlmõ‡¡œPfE,Œäy€2Ð|ã'|Ÿ9PöƒõžßÓ_€Þ¡?¶C~°r*¶eÝ|²àäåãÊ4nŽ@Ð\¹ýDé¶¹ñBy¶¥ '¢dÿ°g­ª„ç,3ÛZSxþ:_Eœð|˜,*Œ¥FKXvÚSU˜á Ð}XŽV8¨]æEoäEp•NÈòqå½òó2nñÓ«.²£^ìJ°|\å2jêýô"ñ«4¾2¸Ÿ3z¥e> e>CŽ.”ì¾$/qÛ#h¼§·Ÿ&è føA†î;‚÷í½í)a\z4…Pž×Ûº<‡|\h‰ÄSxGYÜ[K÷‡ƒ~ ­U`(Ñ}i¿ïO[Û,|“_M%G³ô›Sƒ÷ þ}…©­™îƒó”%òZ)DSù¸ñ@}ü÷DÞœ·zßìU˜j·÷v­“çWy¼xr¡d…AÿÂÿ]ÜéƒQă¦òÑÛâë¼/G+Ÿ}§úQ PB”?¿:¶Ñ _ý|²}J÷ Ût†¼ªÎ<è~–ºìðÍ¥<ˆ¼"QÍ4àÉô0¨‡vcaÐÿšê?û;±s \å&úÐþýÁ@Þú…© j,pÙ”d?tMæ{‘kÕù· _r|zyxÿÞe‡pžŒ­e=U—çUXï¡Úê=³G|âhÖzÄËÓës·{ð°/Â3—¯¦‘¼0èåuäÛóª‰7ƒ÷ä¦ ò…ÜVçy€Jί»üÔ‚uMŠß¿ ý\ýÎ×u@øô>úè¼·¼å-ÿûúë¯ÏdØSw¾jØ“*/îèèè¼![”“»o*H: ú¨ËñRI”Z…ñ¼Ð}ß7gÄýea¼Ü ÐååÍÙÞ°eÞ/3ÈT[Ðè¡æñüÿºŠË¥Åo`ûÔ·¾=„…}ñ‹_L*¿Ö›ÊeGJäΔ÷UÅr¼7v»÷ÎÚÔAû²ö«'ï¾ú²ª0oõ^à!½OÎT˜t5èµY×¾QÓÿ8èS³ý¢-~>ét(óšz€°èU‘ý~÷¸ÿY6³’¦è!á›\¯\¹rÂàâ¼ó΋®¸âŠèÚk¯ý?»»Z.ðY–÷LåyqU]v7­ =Dý3L×âm¶i†b|& Ç´ÄyM+Â¥*Ò—ô@IQÿXG/ŸŒøõvœh €¾ñÀû_ÃÁÀÇ>ö±D¿ï}ï‹6oÞŠãã9Û›å½YœoÔÓôÑÑÑÅL=Œ…Ao±7â~±4îG³ú\ºH•úŽŒPZÊà`‚Îʳÿ;—š¸Añ…± ‡„¯Ù¿øÅ_d¼¯ûZ !4PWåô>+rô¥Ÿ ÂGi:€I‹á­©ûÝá:¢÷Ÿâûà|Õô4+TÝÈ6b5»òÊ+{衇ö[Žo#ö¶·½í;wß}÷ïÞpà [g̘ñÑ.k:ô»vÛ¦Ø>ðÀ»¾ð…/œn´ß}ö³ŸýY—· }¾×޾¦‚‰šétl£ºç=þøã'RvÿåŸøÄÿ¥{á}÷Ý÷õ <ÑCmD¿è@„M´¹sçFwÜqG4<<}üã¯;¿ñÆ»½MÐïÚjÊ¿úê«£»îº+Š…pôá8ŠÅp”uqöÿxðNßúÞ$íâ‹/NúÚÃ?½á oˆn¿ýö^èSô;€GO;£Ew¼$z×û?ŒåØ»×mˆÞð±èÑ:zü7?ŒŒL?²éS]yÞº.ü``#]…~7öþ=mxô“ÑÇ?õx´ås[£‘'Ÿ¤ï}¯E¶æƒ¿N;Ðïzs0 þƒs kÂöþßÑžý?Œvîþ£h÷wÿ¬+ÏQ׃ú]™ì/~ú³èûÿão¢ÿòý¿Œ¾ñí½ÑþÃïÒ÷€¾‡Ñï€ÁÆ`€~‡Ñ÷€¾‡Ñï€ÁÆ`€~‡Ñ÷è{F¿`0€a èw}¾‡Ñï€ÁÆ`èw}¾‡Ñï€ÁÆ`èw}¾‡Ñï€ÁÆ`èw}¾‡Ñï€ÁÆ`€~‡aô=úF¿ƒúFßúF¿ƒúFßúF¿ƒúFßúF¿ƒúFߣïaý€Á†1 ßaô=úF¿ƒ ßaô=úF¿ƒ ßaô=úF¿ƒ ßaô=úF¿ƒú†Ñ÷è{ý ` èw}è{ý ` èw}è{ý ` èw}è{ý ` èw}¾‡aô;Æ`€~‡Ñ÷è{ý 4m+W­‰Ýñ’L»sà•Éç;öü`Â:_ÝýýÜu^¾ôÕÉ1çÏœ¹?½ÿއ~-šÿ‚¢§Í˜‘ÜÐôÿš‡‰¾øï>î'¶íŒ^:øªè™_’lCo_òòèSOü{Pú~WÔ‡dK_ûúèc¿ùdôß~rrÂzz?o×?¸*éyûÜòå¯&}ÚúÌìK/KúëW¾ñG ÷Þ¿üiôæÕk£¾ç_o×_Òõž>£ïAÙû^QÒ=å­ïþ@ôÍïýðœûMÞ:¯¸çÞè¿þ‰è{ÿão3÷§mé>j}F÷½Üxsô𣟎~päDÃÇ­{›öwáEMè¿E}ž~ 2L7Tí'ëÆ~å¼kÎްÛìèüÖYÑ©eBÓMÙnÎiáüùÿŸÎ¾%V5hÖÀ@ƒ½§BžpíßnúÌÙýkðñÚûW&mÛÚ.ƒ(s¿³>¤>“îw7Ýz[ôô f&Ÿëº×Óòêé~g}U¦|¸Ž,©¿é³g?窤¿èü´míGÛÓ`¼Þ1ûÿ3ºìòg'Û¹å¶;’íÈn¸ùÖä=}öú#ú”ºï©¯èºÏºçÙõ-‘©‡T¶ŽFÙ}-Ýïì¾£¾•¾}âs_>ÛÇôðI}ó·¬>+†Õyð«{šõ1 x»çÙï„î‰ô;`0Ф.zêlâ4=xÏ;¶‡>ô±äsÝðí=‰a *tÏò8é ºÖÑ࿞J7}yÒOÜõÚã¿õõÿÂ`J/€óö£´= >Ù ;k{ÿ<„kðᓼZzOï´GY‚ÕDu=Oð}oN¶“e!%Øé{PFœ×‡òî_&€õ7½¼ú”ú–>W û¸ú•îê›éuôðWëHЯú²=¤N‹e=”²þÛíŸèw š µÔ8ï)s=,3QiO·ë Þeˆë¦ln„iû®Üu4àÐ2Ú~=á AJÖçò2gyÁ̦A¾Äq½§î°üîïwRm®mkÚW½ýhp“ö”3¨~¿Óƒ]«éo£8|ø.Soðn’ô7ÜO8˜ÏJ'Ð2 §,:§«û®MúuÞçèëáT^¨Ž%ZšÕw´\^8i=S_ÒúõÄ€¶_ô»Hß«fßÓýF¿ÛE¿ñõúLjÃk¹HËʬ嵞½§Xºæý¾ëXí!WQ¿¨·ï¿ñD®X×y£÷"&s/ û“Ú¾^X·–©÷;@¿`00©’nx°úFrsÖ X7~…O5#€åmÕ2–ã×ÈàÝD³nºº9j  ííG7Åz7`Ý<¡N{³lP¡Áo˜¨÷”wlábÖi˜ÚEícÞ,{êîrª%æõ™…š' ½Ÿt;Y¸Dº-§hÕïwºÞuY~»óQ æU2aÖH²oxmÔ¼Û:¶]K½O&‚ë uEzy£ÒÂSýÕùfz†—j;f AU¿ÑrŠÉPë·$l_ø{ç|xi8ж6—P°°Uí/ëw„¾W½¾§‡Ÿvý8Ÿ"“îô!]ZW×^£"T¦ðh­zmuŸª÷À&ï!™ÙãOþN²­ð¾ßêCáC#½§{Qø;¤óIßgì^d!Öö{ÞײĶŽÉ~ï†^÷À„ý¨ ÒbÜÆòvÛrEmI¿`0Ðô@@7C 7ÖJƒ@‰_ݤdÍ`ó(i0Ù¨÷Jû·<ÅÐär+ö5àÕ1èxŠž:[¨™nÔxkÀaâ3 YS»¨ÝdZGÇ«mk°-ÏWz l7~Û&6TŒÈ<»öžxxüún´ &K?¸Ó¾‘¢ý4ûà‰¾Wξ^ºßèÚ z6*€óB“ë `í?¼OÚµ›©ÔŒéÞf9Ãz(¤mjEnìwÀ~‡Â{QxÍë^¤þ Ó=Q÷"õ/‰yýneÝ{õ™í[_í®¶¶¨)Û÷†ÍŸ›ÐæÖµµmÑoý€Á@Ó7L °ôÀY¦RúIr^,ÝÈ­ •n^áSjHj;úßLbÝ\-Ñn€YOá§bY^6 tt3Ö>C1¬›¬–Ó€7¯ÌKd„ô“o{zÑt Ü[Σ=ñÏzJ¯}‡BÙÚ|*« ”¯ßé:²-éð@óL¥pV,­ºfÒhH†ýN¢O×½¥h} Úò­ÊÃÓ5kýÛL‚V¢!Ö¨¾‘å1Öo‰=( °Ž5Ô[K÷](Ö–ê÷êÿéµµ±=|²×Y{ú^µûžBü³®{ЙÀYE°äù´Èõ¡° •Ýô½°ïéA‹®/[ÏòõíiÖË™g:¥(„ýÎú†údØoLŒ[ÿÊj§ô½È<ºé>öiµ­ÞÓgaºQøp7 íÖøÁîÅV¤¯(½‰~S h€ªPÖ“äzXÂצYÐ @7ð´wÕ’y¦Á@8poµó,µm ]vÁ´,6x±'ñYbÓ<Ó&xM§CÒ´Ÿ´ç\xÚ,Ä5kJ ;dX›O6Ï‘Á@9û…Îg]V$§H›ÇWךÚY¡ÆáužeƒáÀ½Õظ:~£ŽÛ¼l:îpÀ¯ß‘<±©>ªó pV„ˆ=è²»ö­óÑ~M$»‚üåГemžU€¾Wí¾§k0+ÏÝJ à°êºîúN{Wí7<ÏtMê^“¾FZ%€Cª‡]ò †áÞa, R—SÒ‚+#¼¥#D,Ê"·z¸­÷,}Á~Ó²B¸mY+¬gÕ²éwжÁ€Ýó €Ô –0 C¨ò ø¤=ÀV#=x°å[]riÇmžÙঙké|ɬpj °Ã|D 0ÐÖ-2{(ÐHÞ5ƒêõ»´g2ëûª­Á·¥dm'Ël–5¯åß63ßèd"24°Vÿ°j´:–zýÁú@˜œ÷[c©ì¡•…EÛºEfá®¶­©Šú^9ïyy9²®h]¯¿yS‚åy€e„é{ž= mEt½šv?1Ïl#÷"ëWÇ#l'…a‡´ljµ"³~ÚHá1úLi0 ›xž–G¤‘` jmðæò4ZÀ'½­FŠ`)ÄXOãÓáXépä"!­HXÖnš¸è¦ŸeöDÛEÕ¥uC·°êðá€M£ã«·pwö; ·ÌòÜ6*€Ãy®Õ_Òµ٤…ù× =T(¥®ÿ¼¼B ´õyÑôbæ]Òñ›VÎë6/ÀV}Ú¦GSxyø ÊÖUŸÊÛ‡ýž €{O[ÔS#9Àºf-¼ß<¤ÍÁÊò¬k³hÊ{È\TѶ¦6dMÛdØúK–¨Ö±¤ïEym¡êoò,ËÂÜá0:ëØÕçþæ#€ ­ƒËE ï$à¬Bm3U í¦0'#€%ÿÿöî-·#èå—; ÕÏõ¸ÞÏÑΤãiÔç3ÎYûÑ´Y¤g®Ù¼šÏŽ»¹µÚ\Wxµsm¾+fÂlü¾Ù›Ûø¬k=´ÍζÏmfXÇÉG&ÀsºþÑXµ®6}u”xŽÄvŠöÑ$xÖŸ˜S gAÆÆ™5ïý¹çøX®Û=›ÏÙQñjÆÔ}çÂþïMzûl¬œ÷k ÀË›u «É¬9hÒ6‹fÜ3^oÁ0ƒÿ#àYjnÅÔ ßÏwz×ìïý]Ýq½Ö²ç™Ï×Þèi{žµáXO)íÏ}Žiš×[]\M€§±ø88-|]|¤Ipÿ¿Ï; ØzÔÊø=sW5Ù›=m§ítªülè³×™YëN¡GÉšÐÉp?ÛûêuÛögñŸ£ënõ2«Ý6n›.¿5À³pÞú÷XaWàõtË9ʵï|êˆ]Ï9¯SçVpûïÜø=w>µm´­õÝÞ˜Ð6:¹»gÜΜ¹Âìzd¼NNËYyë}ôÞf¥÷ÞóÙ‘ÝÏç ’ž§Ï×vÞå “ëþ»±žË1êö±h=«äj<“øeÁÇ£Û¾•Ï^£×šûßsÿr¹à)x× ¹­Jƒeí>nP¾˜ÚÓÛcjÄdk„ûû-MóQÝ>ôLXkÊñ9;ݲÏ6÷Õóôø™ ÏcûÝ®{Èk ®~MÜk¬>[Á¹`š›™pÔ­¯sËï\3ð=s7y©a­)­1lR<;Wæ6-·d¨m¦Ÿïq³˜L ízOî{&}LÃü±Ü:ìhÕê³{Œ÷]²Þ éìyú¼M”'§³ZïzH¹ú]”ß³Ç4 ^'â½N_O?ßùÙ%²÷}³×wr;>š€5Võ}¾ß3úÖ u$yVh/‡³ý=²í”‹ò±ŽU=WïéÖûs÷š|¯+V_=OcÑš÷»^Ã;cÑÙï¢×mܬŽÎÌêßÊäº:}¯¹ï ~ô{Kî47WƒþÑB grpc-1.3.2/doc/images/new_epoll_impl.png000066400000000000000000001507031310511640000201720ustar00rootroot00000000000000‰PNG  IHDRŒ?<ãWÍ€IDATxÚì½mhe[zç÷øÞs»ÕÝr·Ú‘mMZƒ‰BÄŒ˜ˆŒÌèƒBNÐADAFD¢€ú ¢šA4Dåö‘\3èƒ>ÔA)ß«ºŽf¢ å¡Фœ©¶k2²]NW»«ÛåvuÏíîj»²Ÿ»Ÿ}Ï:[ûè¼í}Î~ùý`!söëÚ{¯½þëyY"ùäÐ+%çóuèw>ó9ÍŸ¯œÿGù\¸ÏçÎç¯LФC™ñʺóyÑ+û|.ìç9¯l„Ú(€Lpæ•çóŠWÏeª2@)$ǽrÏù<ä•aª dÊÞ©ún­8ŸCïW(ÚŸs>oze‡j€4²êTé ŽQ.È;³^©R #úîÜ }¥Z  \.mŸ*T ¤u‘˜¤ à¨«à4Õ]²& ºB<è`^ÐT2ªPŠÅªÚdË+ËT$ŒºÐ?‘z $@b”‹"Àm¨p<£ 48Dè5Üs;ê"S¡Z‚5¸íÞØ¥Ã}æTü,«±¡®VÞtÆ ¸ E' ±P¦ bA-JCTC¡!v ÒŠf»§ t¾1\ªº‹…AH'ší~†jH…lªE±¹`œŽ @¢à¹Qˆƒ,¡–ðm!¾š ÙP©€®ÙóÊ*ÕbÁ4ûô>Õk+#ä„1ª §è(>î©Ö~!!JP×iÑìmŒ‚tZŽËTCW¨XYI‘hÑI£±Œó܆ýgÈ:£´£Í ls¼²cåÜþVÅw×Öú[òJ%%Ç:,þtc=E-(‡Tˆÿ+ŽH þWO¨r Û‹šºdÀÖm$àƒm—ny>‡íÿ“…æ(—²Š6¬ç·4’ÐÞ{Zg-B0NY £¦ìÚ²w¥>ƒç²W®Ä·èêr{¶LÀª}¯BûS¶l¿«&ÇBBòЖٲc8mñ¼6ÄõÑãQ×ÎuÛ~9ƒ×Hë`‚[ ØLS± ±‹+TCGìD|W1Á I¢–BËh}_ÈÍXG]v3ô ÙûíKǵ ªØ{ÖÆù< ­@€f)aš €ÌÙ (\´Á—Z|EÐã:hcy}ê(éeyñ–ú՗멤Ç}g½úvÎE;Ãöÿ2´ñ<#6ÁX/+!ѶñÜT"ÖÝ”úÉ{ÿ­Ûï%[&°La7b›í¸¤F-[å2@–(S Ù³ú™±—MÙ^*å/°4¾d1nÂl§Ç»ïÔïfDý®¤ìþlµ®†œûeÀã™`ŇÖQw8bÁ`\ÆÖD%ÊÚ¸zW…¹ßÆùÜ—›.ʾ>$q( Ú‘¢n}i•ÿWB‚Q_DÛ&.gCë/Úzú¢˜´ÄlHX£Û/”ŠÔF;W#ŽoÆ~ß3¸ÓÅ9ö»~W"êwÅîÍm«ƒpý.;õˆz·³0lëiÙ’›®4óNýE¥HŸ³ŽÂNèhçÜô4ކ9¬ŠÃ,êT Fµ ª•Ï„™tÞ)Î{gÀy/»ïrw_A\b;ý¬{O©÷Ìa›f–¤>6 ðŒGƲÓÐÓ…#ô¶uA¸i‚dÓ^Z Îowب½PÜNÆ´óy^êã5œmØ>N;8Ç”ÔïJDý®Ø‹6¨ß]©·8KÍÕhÍêbÎùíž#ÔÆ¬~K!Á]r^‚³!1ºêt Ú|I"ó\ˆù('<÷±,õn£Aû=úÎuÁ{d+´îFhÛƒ¶Ìžµç«Î»&ð¶Ù·÷̘}v§¸™·ß÷íݯï§õ6˒íDBP–ÖF<+=⹱€ÊN™—ú8·!†Á6ÜcØ m¯”AÁ(‚1\wc·Ôw°LԄ›&Ýú] -;lõ»,7G"ê÷¼Íz=´}îñA̶yÏ@z2‹v–-J^0–#ÖÕ‘Î ¹™ðeÒ~WW̪msÜ~k„¿›CÁXnA0–œ×ZDýtÚnoBn&‰Š/9l³^KξH`íR¢}È<: ùÄÞ y‰c×v‰ic Ô¹G5ôM0NÊM—q:ˆ‡Rï>9:ýÝuyR—Ö ãçÌÈÍy¶Ä©³½ˆåWn©_í»¨×}#€B° $,‚|£<[T@½ Qkӥ܌©8±¢ÿÙÿ玀ٶÏA:ï°€Y5á2o¿U¥?ëü¦ ó];†™Ðþ—œc¼×@$5êÔì8çåž[/Y³c?·ctDdPwƒõİÜV¿kö}P¿w¥fÁ ÞI‹‚cF€Çœú]3Áw*­Y çœzwöw(d%†ö)Q™b]êcÙºbPj™ÓÂhŒ]Enwý˜¢sr+AÕ±ˆßFì·¡[:êÔ/ô“ Ã/@ÏYRý@ëè`*n×AÝfƨ€ØØ¤ ç¨X¼¢Òóùe‹ªzAÙ+Ϩè¸Í@h²0æÍ/Ä0Üf „çWH’,̹ª“Éë´AÎÅ<ÑÂ2ºýrίõTß/Ä0„kª _‹?§%@/XÌбî$¸žN •ç9DÕ‚úBü9v ƒT¼ò’—9ä÷ò‰ ªm_Z¤Þ…sÚ+{â[,ÝvL3œ/ÙoúÿŒ-3ãü¾`Ÿu™]kÛ~“¶M]9ô›nÿÒ9n-®{â¨ó}Ô·%ÛÆ®•²óÛœø»9çØ‡S*_Úuè;¸T¶Žð¿v:PiB…Ô¡#¨tNäÇŽxRÁ´)5 Ý’Ôòè2ÄÏž»e¢Jl{½²á|Þ”hËg”`¬Ø6KÎ;h·E¡é²"Ñ.©â»rºõà.wîˆÔIŸ‹o 7 ~Ã"±ˆKeûbñ…½ÔzM+G-lá8ÀIG¤4Z`ÜqDY%BÄß²~3áWµ}¸eOê­… ÆI¹i± Òð¶ORtmG‹ŸC #@AÀÍ)ÝTìÅ4GU ¡Ð0’Ÿ½v¨*ŠnË ºÛ`¡ã݈õ[Œ'¶ÝpŒA0ê±F €îe@0ªX|†X€4u8p©l9Ä"äFòóÙ^-F’@`íÛçµÙ§ rõ~hè·ð°C¯.•s!ýº5©¹…jJö »a Z4û ZòÔR§®O㎠ÐD šAð®•5©Í¥¦ÿŸ‰Ÿ!qÝ>ßm ¾vˆ9]wÓö¥ë΄ŽÛÍ vo 2-j&ÄJÄögìXƒLˆûޏÒåïÛþWí÷Õ6êtÜêjÕŽ_·óÈö5:¦9[¶kA–Æ©ÏÒ¸"õ.hÛR? ú So«õ–„`d$?[,R¹áS!RÀ[^H]¡BàEJ;Õ“rÓ­sÝu;¡ãvçZ©¥ªW7Æûß3÷CqPZŸœ[Ý"ÃVÉ©·4¶:×ZX0†ÎC™–úyàN¥>ë`;n³‡¡gFäÃ[Ž©â|.Gœ×œS¿Qç½ú¿Üäx⌠îô‡‡¡¶ /¼A0v ‘g)[MDA”¸[wÎc'Bðœ4t»- Æ{Ro=Ü17ƒ`T‹Û|IJ-вfD|wÒ¢` æ­Û‰(­Ûiƒzk÷ÞÃ%ŠLÉîÿ”§ŠÅç”QàùÀÃ=D]*—©†®QKžZÓ”±SEÁT›Âg×éœ4Œg¡ŽLØBy›;h¡³Ö©`“›IœBb6NÁ8lÏQ+‚Qÿ.µyÞîg×µ¶Û{Á˜Oˆa¼õ6ÜÕ÷%ýÙÁµ½¹/ ì†Áó€‡zÈŒ :Ý££Á/%Ùi$ÚA“ÜœJ-±ŠŠ¦-©Í饥m§#¢®‘›B¥‘`<´ÏsVT,Ž·(üÆlù!çØ4&Ïuq]wxÉêw°Átš§œmÚ>ãŒA‡3pÕ½kâÙ}¦–ó¼:ÆÃŸ’z·³=ç¡£¸¯$=.•YG_î/s*Â×MïÈís0æÀ:ùPˆ†t´ÅlTnf_.·!÷¤6‡iPôÙ™kQ0ž„ÖÕÒ‰[é¢ÜŒuÎKö^)zöT<xØ¡.•¤ê‡èNÉkél®<è=síJ”4»ƒ­ÜrÜ[] ÈÓ o_ãr×Bß´!õݲj÷«[ÆZŒë¶;È™U±è^ã g¨K¥&ê ^">¢#Âeª2ƒ{F]hI÷›Æ{Îÿ•W’ú8ÆjHŒ„çPÄ;«UV¥Þ u £×@rtpwÛú‰¾ôusœªèÍ~’áÎ @À° •ªÔ2»"qFj–Dý«®UrÍÖSá¨Öot-Œ{¶Ì¶‰Eµ*N:ûÖýnJmjŒVã©Ud=’zëûe†¯Ãˆ‰Æ­Þƒx>ð°CŠÐ2.•ñ ž%ªä^Ÿö»!*Ë·,?h¿7šæ¶ß±¤Ë}NëA=Xæ vÞx>ð°CÊÐxˆüXêñ>Õƒç>[L÷x0TKàÕßfM4RÿÐWÔýG]yH„Ó9Ú©º¦òÃ_øàÿ|ÿý÷_¤¥|ñK_ü_8M÷ ñ3ðÁ¿ÿÞ{ï}ßÊŸôû(•Jç½WºÅ ýF§X¤:F3Ð>¥òÃðÈ/¼ýøÙ?z—–òµ_øê® tI[Ùvù¿˜šûù¿øõw|PúQƒcÏûtQñu‹ž<ìR4þ—ÊÎ 8‚ÁIÑÓÆ4 F-_þÊ—^ôº—¥X,x>ð°/¤Ü¡‰4tŒª@0fL02¸—-zÈ`L ÁÊ}EÓšãRÙš&þ”j@0fP02¸Æô£,‡Ü‘ѳK5´ÎQ¦˜ªÁˆK* Œ1£Éè4KêdÎÏvHcߨD.•í¡s=’!ŒÐˆa,šŒè¬`çŒç;¤MÙ½O5tÔy«R Fb¡GÃX,ÆÅÌ-së@?Ñì¨j% *ÚBG}SoFb!¯ ûо[žxe;ú‰f^Óð$UÑsâgEÅ:ƒ`Ä%ŒÆ$PÏŸ{½õ¦yúŠéô£IZÔ²¸LU´Eà"Ä Áˆ`„^C c1X?kù ÷9äÜœÒÍ€]#²¢¶©!Ld¯PFb¡ØfÅ÷`)s»@?ÑŒkŒàµ‡¦6($B0ÃÁØsÔƒåµWf¸û ŸX'±DU´…ÎSyA½!qI#‚1©AÈ@AÀÍ)h\Ä3¯ Qm1/¾‹Ð0U`D0B!†1Ÿè@ä¥&Ò—ûúnNé=eª¢=Ýà•—‚‹‚‘Fè?Ä0æÏ÷>·7ô“ .7ö9âŒÄ0BA0ö„`.äAî8èÁä¿«TEÛèü”/­ÁˆK* ŒqR¶w s!×Ãà6@AÀÍ)=¨uìŒjèµ.nP F#¤bóŹW¶¸­û{Ÿ@ÿÀÍ)Œ‰?É<ÉZ:ã u‡`$†R1Œù¡"¾+*™· ¯h =£—óŽ—9‚‘F(*ÆDQ–5î2è7úr%6¢»Îô,Õ€`Ä%ŒƘÁƒ¥1Ä0ܜҲîÐÑßGBö:#‚Ò1Œùz?C îsè¸9¥ç:`!ëŽ`~,D#‚‘Fè7Ä0æŒd~_è;XȺG-´'^¹æåŽ`$†Š‚1Q4¿À)w¤ëQ]±(þ|Yw½2Bu qImÀ:ªŸé[–ig*ЩX;—$ó¶Ck -sØævu~Ü]«“ÔÅ›#ErŸ‰o¢ †  àæ”.´óÂ:VÐ9CÖ±ÓN‹ŽP%FcËÂh6ÔYnÄNÛ]ñÊ‚Wöî¼n„ÚFœ´y쳎ð=æ{Ä0毯ôžèÓ}ý7§ô±h/&íÐ`!ëßòÌês™ê@0Ãx+eCe+áögÐD_Å„ÓNûØIèØõX7½²ä¿KÉDß¼ µ#ÃÅyi>¨G cþ>ƪ¤R@`!{-XÈâ@;wêRôP°ª#‰al„ZÒÎío`t;ËÚQž³ï«ÖF¥E0ê1©úžsün{zbËÌÙ±wZŸ%[?UñæÆž¾›5¹Úc{&úN`!ÓD.KTGW‘¼èŒ¸¤¶-è¤Þª¢/)Œà­4ØçH¨-xÞar˜ÆöÁØsÖÅyX/xóK #@AÀÚ’ ´ôTü‘MÜT»#pù£*ŒÆ–]5⻽·Ÿ¤`Üøî¤Ím·+‰aÌ?z/<²“¢ö¥ˆa(Ä0fuKÝ,dq°-ÉgkcœôªCz›…1ÜgD0îËM·þGmlwPÚ·,ÃX ÏÍÌ=Gk i!°•©ŠŽÑŽß3ªÁH c]ÇWç/=1ÑU µ1ó6ТÂkØÔY"ªlÛ ¶?#ñ&™ßâ¹aÛŸp~So‚»vÜvOmVÐó\rêe9´ý¾ƒ`ì;´ÈtD YçèHðÕ€`Ä%õsÔŠ¶*3¡e&Mlmšøš“Ö­*3Û3™×rhÛ ¡ßÕ•ËŽÜŽ§ÕÌɋǞªÐc*ÐA‘gRŸp)ïÃPˆaÌ&XȺãÌ:½€`D0BÃXÜwó ¹9 ÷9db³ ²Î™7±ÍT%Fb!)ˆa,.ê–z—GúfK]§ÚFGunË)ªÁH cl¨«çNƒ²–òÛgå–cßÉÊ3€`LÝ{æ¹ôŠšá¯DU´…ZhÔUh‘ª@0â’ yÁ˜*fÅOªTˆa(P'²sv~Ÿ«*ìŒFèÄ0ͼÍ}y‚Æì‰Eæ`l­/Ò#‰a„^B c1©xEÏ}ˆGzÍb±c±¨õF¼'‚‘FÈ-ÆT½oæ¸# ×èdÔêN‰…¡³—71‹F\RæW¼çl^ä·3ØY.ý5‘;;ãY-Œ}GçåÔD7«;ob "$ůœŠoY¦:Ú¢,¾êU`D0&ÎâßyýwüD:H³'ÙHÊ¥ƒJþK‘ïyÇþ÷cÞ61ŒÅ‹E‘'†  àæ”^±¨“ËëôƒTG[ nŒÄ0ö }Î^þ=¯ãxäÿ¯ƒ[:Gì#¸I#:«N™ñê?ù½ã~v'~K c1ÐA‡kÞ7Ð/±x!LÑ :âɤÉFb“g×gF=Ñu}\c­h );æi;æ³1‘Ã;æçÕÄœ!û&Õ¢¾&}è„iç0M–Åާ7Ún]oµãw-XeŒ¸¤&‰dŠoEñWùÈw3eÏ㡵!ýdÐŽãó¸f¼rž‡ ‚`ì›X,zŒ<1ŒÆô5¾¯St]~Í+¿ã•å•ï´ èt~ÈO¼ò¯ü¹øI0¤…uÔšúc¯¼iqF<ôÊ2·‚Á˜¨XTˆË``ÆŒkGþÜsQèôjõ"ý›?vÞ:÷wíxôµŠ¾ª&ç6K #b±ÃPˆaL*œÒäÞò§^ygåS¯7Yþ¹³¼–¶°ß ­ó£.Ž÷­ ÁH cR šP<Ç]Þkîye¥ÉºÚ®½êñ€Î°uhµ]ª¸?û1—» î›Æ|¢ n®…Iè#oí…”Þ…Ê·püîò?iñœÝu~Úᱪå@;êÜFFbé(?ß­³.¶Ú^¯?l­Ýš?“ê‰$ï6¾bu/Ü&xbqFc.OrÔV {†êî @ŸPÁóiÊÏw¤ÞÂø[M–ÿíøûÝöñOCë|«‹ãÕ-#¿F\Rã¥,~¢˜ðžðš:òk•AŒOM@&q¬­-¸±ý;žØõŽ÷i5gî„Æž°`σ’5ˆa(Ä0¦ M"±’¢ãùu¯üÀ+?óÊ?‘ú,ˆQü{âêëòÿ·Wþíö1ã•ïÚ:*0ÿ.ŽWc•Ôý ·T#‚1‚x­Èi,qÌAÛ]¶¶".|µznÚ67¥A†iú£ê ʤ!†1¨•Ÿ¸Å>ÞçÐßÒC xF¨ŠŽ9”ôe™c·ôc$ÆXÃN²'À.»˜–B“à<±NçPÇ©–DlÓøÊr£…޽[EÝ7øÊÜõB0öõ€a0RÆÜ>€ žyª£c´³©É5ªBR!#.©Ê€‰±‹vž O€-yå<ácÓ²ÿÇ+?ßúÙöüw:åÇ‘ÿ¼çco›\9æd$d  ØMÁsÈ‹ªcÔ•M­5‹2Fu  ,Žo[–BÍ8z,²žà±é³© u~Û+Š?X6׿1Nè4}JtC c¾´çæQÁûQÄ0ð°CO™êè˜`’ïªÁXÀÆkC:r­ó„ØuBó–œgsòúœjüâ^«âVã=Ѹ֧ےÆb°c÷å,-1¤Uð4M}·R2Ñ"‹èÖ;ÜîdeŠG~Û7S&bÕ=¶u©í·GÒd°Ì\fß)HFKc_™µwñŽARú¢RÁ3IUtý²'¡‚±.©ãv¿wìNªV»£ÏòÉĆº×ï[[ÖÊÔjyTA™ÀêC‘A´ß,Ð@‚±ïèûC]¨J‹‰£rBž±áÚ«Á¬Àñ²ˆàéí¬îQ Æœ FõFxmmFÇh²›£ø&0¯ˆ—}ÚfÇmJÄsëüGýŸú€ÆâáN S”¾UVÚÔËB“výØ+?òÊ¿l¡ýù5¯üŽW>õÊw[l¯tÖæ:<ìž®P«ËsªÁ˜ãF‰/M u̯S쉱×v?@¥±Ø'&úæ»ØF]+ï¸Ætû?€F cq æO^H+ÿ—W~â•wV¾%ͳ)¿r–×ÌÍÿ …ýü‰³ÎÏ$^Ï OY´N' óø"¾Õ£ë¹ÕÍó¨ûg%ðŠPë`nZkÖ™[öŽíâØï.ÆÔ1i4´Ð©Ä‹Z¾×Bê/Cë|»…ý„×ùUžlLļNU sè’ªVµâÅ’Ñ´*²}ä»pw‚N?pß+O%~ ÜÄßùƒÿ^äÏÊý™FÁˆ` 3b#‹9>ǬºÞ>ßJ¹ïJs ã9Ë¿?fµ×Î:á•Âc<ìÐoÁ³BU´ÆœhÃ!U`Ì¡`TWõg£{¦'/«m·h而Z\É$y"2à×ÿû·üŽ  Ò~'#†Äjô¾Ï뜿Y kÒxî?ßøÆÚÊfíÒ(~ øÏLøµ2§îÉjëü’ÌTD<ìÐMöp)Î¥VpÊ^y,~r R¡#óÃXò5”\IŒÖ6Ë>ªñ‹í¸‘ŽÛq;òa3Ê&â.¤7“gÃʪ=ƒT$IÁÓê’§ÖŽÒYVG@0f!†qÒîñÕ$ë¸êÏqxUý&¯mp¦gxdzqä ÀvÚ„=«¯™<=ÆT¢Vöׂ7$,xö­s3Ou´…Žæž[¢:Œ9uIUÑóJzàþé ³“êMï†eñÝO÷¥Ç³x¾ú°³é æ¬]MdŠ#‚ÑpôË{ØaM‡=½b1Èt8Lu´Z™.Á˜gÁ¸hb±'–2Oœ½pÄYÙÚ&ÍBÚ—d2&`÷ºØ„zk<´’„ç1ŒÅ}wë¼¾O\Ë"aM‡=½‚ç ÁÓ1Ÿ"´Œ9Ža ¬=™œþØëøù.§Ú­›PÝêWû¤‰wLÀvkÕ ¦þP+iÜnëÄ0½æl0Ï@ð¤¦A0æ5†Q…š&¸é™õÂŒëÏÀÒÎð¥ôÑrrÇOtó¸ê»ÃÆÅŒ ð=Éè ‚±ï,8)ž  uw-9Kl…ŒŠzèü†½L~5ðߊüÞßùsIA†f£êÝpW÷ï ´.³‘ÆÂoˆLªuñ¤wm Šf¬ÓL°ciŒ=ŸhÔ Z_H£Öi$¶±;Ô•Mc”Î¥Ç󯂱ÃNéA¯ªÑ’ZM*Á—/è•Ù~_c;Ž~ öhÜ¦ŠŸå4?Æž¢ƒ){Ê"UP ˆaÌšFÿ‰uìpƒé ­7k¼¢Œ)Œš…T]"{eÁX1Q¤àÏ]0uÚ O¤½9éÜ-34#jŸÝbu I“ é ]«MÄ0沘×ا Š1ŒÙ<šâþÁÓš¨`j@0¦L0ê Þ ¹éIÄà^Yü‰ëUŒÝ˜ÓñXd¾êÿÞ7L´¾üfÿ7M0>•Öæ¿$†1¿àé™Ú‘#¯s&ìÅÆ´ÆŠÝ“Q:ïÅÜ~lŠoUÜ”OžP;8êó¼r?Yõ]ÓB}9UƒMÆž¢×^]·‹8 x ‡ZrÊT‚1‚Qc4¹UÒSé¨uLãx/›ÝûžX|vÔÇNñ±È¸·ÿWövÞÉVÐ$8Ah@*‘!û"õy=-ø;„F€‚@ c¶¹– dðK1Úi®P Æ> Æu¼O°š4Qcµ#ßÔî®Èè‘ß!îê{”ÞL”ZŸ·MØN cþ‘ZóIßÀF/HS ã´=Z4Îô¥ý¯ƒ;êµq–±ºÕg¨×RêµL]´+¾+þ€Ëmè ädBǤI çívâi£IÛæè)u1Œž"4D€`ì—`Ü?j³Ÿn÷*¶í0µ”¬ãØ•Ç}|?xBqÁ+Oï¤?N{Á:SaaK cq1áôÊžgr ¤Cl¹mêždk”Qk³{N?¶,µyFÅîçÛÚ³’ š$uß¿°÷V§×ðq‚b S‚‰jè˜Iyº|hÎ×þµ¯þXEc·å+?ÿ忈c;#õ—¿Ýâ¡«U≴f™èD¼ YàE»#žX;íÓ4úPxû¾®fg0¬,¾EñBú”=óëÃCoÓô |í¾ú{lŠô>8·{i›ú+¶ÂÞMp¨%L­ŽÁTAóöÝ•ÔgŸ×Áøžz]Om93  î›È ænÕmÚwÏ¥6EÒ¤õ=ªöýyÄöm_RŸM÷sfÇ«Ç5¸mçzaçº`Ç-5ëaÕ©ƒ!©e¡~bç§É½ÔB«1îê~½%õó_Ûßà|Ùÿ³¶Ì•ç`·oç~ßYfÝ~{dÇW²ó}î\Ãûî¡sÝ1¸jëkÙuÎóS« €Bs.Ñ 2 5´±ªP `\÷h?%祟TÇrÁ:‡Ò[“f&­ö)6ëØë¨gÏû¥d´’|jžM:û\’zWâWöû¶Ô’±ézwá¬aÇ6%=È3Ä0f\R©?ÈVgyÐ^èg’Ìü†£¶íg ¯§1q\Õí)*R5ÑÍÝ»tÆÈœuÿ0£‚Á÷%[.²ŸÒcÚu>ÂÐô¨»2a£åÜþ.ØõsÎŽSÂÖËq‰n/‡LLí˜püÔÚÿS©yo4м õσ¨OCÇþ Çx:Üuö5cïž!Û^À¶mkZjÓ(=tÞܶ ÆÛDzÕù#çØN¥f…tż;,î‹ßïšèÔ:~b¿M™p Dª8ïTw{+Îu† †1Û\I¶G³ûÍc!5:$ÛYvEÈ=³ÕÄD+ƒ{«ÖùØéFŒj¢™#ÿ{Ž·ßój}§$‹èuþß­3Â3PHÆ…,æýâ¡Ô{^-KýÔa[P®Îò¬#"´±×ávnܳÎÏ#§sÐh»¨öÁÕÌÛï¬Z6O’±¼öš’už^J¶2ô!ãã¥d×Rže^Ký@Z÷Vçò•Ôâ ×Fƒ{.5IG¬½°ïK&šÖCû›’Z ߈-XÁJVN­ I½Eq#â mø[§-¯Z[XJ¬Ü—›9V¤æ;ÚWàZê ÃEÛ×°ߢ‰¿ áμ#._:õµ 5ÐWŽÜwÎáZn˜=tÄû„SçWR‹³Ÿ±uáz`â[ß§®»w v/¤öÎ â?q>Î#à?¨ÃTCW/–!ªì,ß•šµ!nµ F%ÈÒÙµ äožp{sÒãçÂöû¬š¿ôç3ÖÜ“l¸¨"ã£!i‹a“›q}çŽø—š»i<å¹ –`™püéš-£e§Á~ƒfás×Ë™=ÿZÔ"x³suºåÛ¡s<ÛöÝ3¹(v|ËŽ¾k#ŽP{lâ÷Ò~¿0\¶ß÷ìÜ×¥–5uÏþ^ضÜ} Ù÷Ï¥qBžWR‹«¼rÄܸÔ=/ìó¨Ô¬¯gvÜ%©Å»ÉqÆíós©÷ì¸g×€ÌÅ1@ c¶yGPÚβæ|ÛCÜn1+Ð…Äh%×̤GµÑòžáísë(_™ì®B÷Á}ëД ö í¬Îæü÷¹Ì… Ó9Ãbþ U™í ²Ë§Tõ©í,ÿ§^ùK¯|WüÕnFãƒÁ½뤩Å2ö)a4Ciµs·ÙŽøPdDÝ|Ø|.Ê,动VàW’îÌÖÆø’‚d8æ± Ç’@ÁB–¿ú·NFPt„ºwвÔ2”EuZgì÷“„Ž¿›Nÿ”[¿²âî,ÿ®W~jb±Û8 ­“Š£^ÛD\ÑÕºØëùmÎÇÝ‚´9SR›-±šÆøÐgvžjõ7*òt4/Èø5gâ®ÝùúVäv÷·„Ž¿!:cç¹Ó§º³³¬‚î‡âÇkt?1$µÉ’ë€jÜ¢'Ü^÷2é̱wͽ}¾ÈI¢›V41Lð`Ì'Ä0@n †1Û¼¡ rYa±§å®ûᄉʃ[žáN£Š ¸Wב5©e‹ ·}7 Ö¿’z i'–°¶ã_zï÷ÞÿâϽ궼Wú¹Ʊß׎â”Ä“Mëô…Õ÷`’7'ÜzGxÇOtóä(ŸiÏ[™,ZŸ¯WƒkñßûizJ?w!PÁH cûŒPEˆaÌ&C&vÔÝíG^ùçR¬ú8êïGNýýnÊê/,öq¦.ª»RK­½Ù ÃÙ©`Ô¬c£Ž8Џ6#VÁµ\wŽÉ›WöwÇ~{,ÑÛA»6Om{»¡{K÷ÿÌéçœ;×dÀê>·.ÇÄ0f—ÿØÏUÑÿ‰Õ_³3Þ&ööCmxïÆ$µ!Pî…þoæj‡`l_0–¬Só*$Ð{Ʊw¿÷(DÁŠS–è&Ï]º¾s•Ýkg Á˜JŠ”.M1ŒK¦vØ_:mëc{–žÚóµèˆÈ’-«ïµ-GЈÔÜ+Ïq¥ƒ:oMÜ•ZüõºÜîê ,±ý¬;ïêÀòøÊyîBßFˆ›Wޏ|+µ˜ÙCÛ˜GUìû ß0.7'·¯Hí} ë¼°ãZt„÷©Ô»¡žF ̘ ñ}Ûö¶³ÿ’µySVŸ' ®íc§n‚}ê5[uê#˜*í‰ÓWÙ³åÖíKÎ>ÃIÇ–þ‡{oìØòCöý§NgÁ湎é%†1»ŒØƒˆu1_õ7m£VKêHÄqkC;oåDê­Qk¶ž»Šóû–}w)5 a°~Ù¾_¶uÖB‚zÐFÙÜßï†^d‹ÖpV¬!oÇŠ´:¶mi!2ã‚qÚ^Ö÷›ˆñD÷T,÷hÎ8ºã¨ö’Ï+£]¬;`Ï͵DÇò ³óüömCg‘óØéÌ»âjÄÞQÁôS¯í=sîÀ!I#öWqL>?o‚b_š[•\—Ò`ÛÁ»-påµw+Æ7Ll=i"B¥fuû~ƶ{æ¼ë/í=«çñÈ©·¹ˆ+]vÒ¶uiýƒÀJ›‹ùTnRo„úhj#O¬_q у¦çŽv®É˜õiv¥f´ÍœÏSkS¯­¿²ãÀJDÿ*|ou´à,ó܉›vMŸÓ‡4³Dä®þ¥yÒ˜’ ˆ¹™¬gXnƆ:²áßBÕ kHÅ—¿7r›kò{#ÂÇÞR§;£‚qÐ^Ž/¥5·®D÷ÔµÚƒx+¥GµŽ Ü΂urÅK•Œ©†i¯zK` bëfMàìÚÿ÷­Ý½6Ñ4a¢/h^Hͺ8o"¥"õqy*jª¶Ÿ!{¶î`‹bvVê­«Roµ xdïøFÞoJÍ(WùÚ9×`Š®Š×ˆs¾‰N<6è¬9;®m©Yÿ®L,±˜b Ï¡å.^ö©]«ƒd/16/µäzÏ­ÞÆíX‚zÚ²úp­žïœzêb(✃{cÁ¹ö,¿ó¶O}—¯ñ¤˜ Æ9{1H F$5ÑÍ‘—‘(6Ïã‹£­fðeëD]ÈÍ)jfŒÆ>“–F‰Ïñ1ãtîÏM\íÚó,7`BîÀÖîloÇDǘ#‡lÝUçÎÀ‡…;ÅÊ–-? 5WÙIÛgàÑ£ÛÿTj‹QV·{RôÖí^([»X»±èˆ]w°î‰Ôâ£x.5ë቉¦1G8‚,äa®¥6ðë.óÒÙïŠs\ŸÊÍAððµÙµëéZUƒz\w®ûÃØæˆÑ-©Ï/öÛçÞxhbxLê-¿®µ8­a—Þ\B # “Œn‡jØ^¼×ng¿ßxnëØyIz?Õè‘ò¯ÊMOˆ!©O>ã.\£Gv#N»y10umÁÿÈ„«›1vÌÞ³nÖé[6HZevï C½{o˸ÚéSémvÚ¾A # “Œú²þ–ý¯/² Þ¥“̉‰ îyBîâ¨ÖiIOŽë4Ç7­dye4mΙh ¦[ùžýE0¦‡ë¨þXüy~ßX”y’‹Mt%-ÖÒ.M×mòÕ€`ìT0jG^G3ÿTji¿»qÅLdpïÄëÈzBî͇ §ÿ¯Š<¬ã— yhE]gŒ©#pßÓëó;’¾y~¡÷ŒIz 4ë6¨±ÊeéŠ{VcT‚±SÁ¨.<fÆ?÷ʈïj£.9“i©;OÄU’NBãmÉ+Oï Æ#AÔB¥V`u½úC¯üÈî­ßD0¦Rè3ÿ3¯|Wò9q‘G³­Áž4 ƒƒÃ\ŽX®g¡<*\s@0ÆÙY~O;ó×ðûâÇ>,¤µÓè Æ½ã- fÁ¼>¾“w®Üö¨ <è>Ô‚]B0¦Ž õy·.î ‚sÁ·Œq Æ8¢Žd&’YT­‹Õ½íïÕ§Š/ £=ÜÏ ‚1uü[âg’d^6¸`«¼ß'Ï_nsInÈ­`lqÆv_¶±äÛ4oî$ä*ú¡È˜&º¹Û;ñTXŒ©„éc²Š–Ç n_·­Öèå.¶áÎßøJÚ7iûœ¤%\ÏMcýÂ1œænt^Q·NU€`Lšª×Ñ8J0Û·íûG~v@@0Bþ”üÇ0jb˜ƒ„¶­ž#/bØŽ&n˜¸êDÜnH²®ÅêÉ8ñ}£¹49ïQFÁÁX8Á艹êÑ͹³â£sÞ¶ŸÝ)n¢í¸õ,±‚ú€Z¦vS&`u®DMâ¥Y©ƒ¬Ì:Ÿ`àò©Ö·+k[öœ>rÓ°‰9:·a0·_0Iýû>˜°â,¯s5î4†¶ß`ÞŲýÿ*BnÛ~5²;gï´ï¥Ôæ_ ÎoÊÄía­ þ|[ÎúW¶ü¥ƒËK[nÚêì±µð…Ûïq;®`Û3Î1ë½ðLê§ÑãùÔ–/[ý<µ:¯ÚçA«?·~AÉÔ)bVH­ Æ4 ÆyI`Ú KF3÷v5Ñ·ÝçÕôMf¨‡Oí<Ücw–©XÝ [àPbNŠà‰¹ò‘ßq‰uC=òGŒã{;¡ÒŽwLÉ:wÖ©j´ýsi?9C+LHçiõǬC¥«5;#@ ®jÓ&Wl™çö÷ÊQЖ\Ú2;Îó5 µ»w{¶Þû]Û‹YgŸCíÇ„‰,—kkoJt±—R‹C,ÛòúÜß n]ÛöŸ„ÄmÉÎG­xµnÕŽ#8ß©Y^Ýgußêh#bà,JÀ½³¿¯¼£ø4$@¯M\Ø>Ï¥>›öœÄÿ#.©mƵ£Ú¨nlh‚MtSMFtU±7`¸Ù6·Qn VŒ+Òy6Úpçm+|ŒƆ\&t=[aç–kުǀÞçKmî·W^c }¬Û0“R?Ÿì€#bVLèHÍMõÚêµbeInZ#gLÔ ˜ Q+á¸Ô¬~Ê § ã@¨ÍrEϰ#Ð^GÜR³È‰Ô,‰ÐsëþÜÎíÐöùÚ~w×ck'wlÐ)8ßE«³yçøF­¾&í»³ˆ6ì$B OHãi„\+ê[çû;Ï’Ô¼:VL,Ï:íÜ=œt1!Ñ©Æ Æc‘{Ç· §Ž·{”\\S%Bì¹ûR‹ã¾}·Û SÞ©`±mïX'&œŒaÊ:¤;¶ÜätÄíÿ§ã×MÊxcëÌIîÜmˆ˜‘Æc+-‹ÎvóL¬HͲ”$)Œ¥,¨ï}§Ž§LÐ<–zÔE§¾ÁãZ÷6ìYuÄÍ€‰ÊCûþÓÞ“›Éc·ÍA[_I-˜ê5ð´Ømç1hÇ·e¶œ6ôÜl˜Œ8¾Y§ƒzX³}4J ôPjVÃg&ÆuýS;Ÿa©wƒ­J-®þÊ™%ªŒ©Œ[’Lüâë;w‘l$g4.ò$¹¹}ÂQ;"A‚…‰x•ZbŠ8ãžÔ»\¹£ïö{ÉéÐýÃÐòÝX%tÎywI¶º²ómTwzÿ.[ ='Á6*ÒÞýX²u\׸Aûn:t-Ù±4ØFEnºé Ø÷Î2:ÅÒ<‹qÉ:ò3¡ï.¤x¨H~$µ$6ƒÎõ» ÝCãRsÛ¼g×pXê-h›Î:‡¶ì™µÉR³òݳß%:þyÍ9®mçþØŽXöÐÚ±‡¶üªsMƒc¸rúì‡v. N[8'µä6÷¥fÁ;tŽcÎÌzf¢7Hh$Å™‰8¾mgåp]Îë0gB÷ÂÚËåPý\š4]Bü" ÛŒq‹Å©£›q5]qÇëxÛ|ZM6Í~Å:B'&לÚ^DgM;$S1 Fw4&$Bì÷ŠS6¥>éO‚qFXos&Gìz^XÇ8gîÀ˜Õû¸ ö»¡ú±Ï'ÒžlÀöãv€‡ì9\sȺujÇí¾‰…×|0B0Î48½všÔÓw¼ò¯ü©øV£g@£ÌÛ!Qv%þ,Ó…¹Å„î$ÕÆ>aIibÞæFÕN’Ê-b/*Öe>¢3Þ©`t…ʼ ‘¡[cÅ:ôå˜cC±˜CÁÔ×jÄwÁÀ„ÔRò+Ãm1ßé@8ÍZ–š«â¦Ü´Yw+ ®må–kÞJüðf“{Uì·Åw‹Ôò}gBÏ;I·Ô‰?pÖxx‹Øï7±È¬ ³7dBÑS €`̯`Tawcܺ·­aMt“ÄmÆ%©·èñB1 ư¥G;ã+¡þ]ý®Bæo8‚c¹ Á¸(õé÷Ãç•SÁ®¯I©¹±‰‰Ç 1ÆaŒ‚QëwÛ:­û¶_W¬OÛ½µaËœ&$·šÜ«[ü© þÂÊ÷½#ÉZûW$9×s(6#TAú™”âN² ém8ú¸ÿ8ö=Öf‡%ÈR-RxïG|åýO»-ïὟ–¾üþ»ÝοúþÆpZë¿»Ógs$zâî͇1ÆEzôn5ùlvALâ©u†£Föƒ9Öv¬Cï ØÀ½oßÙ†Û_µïNmÌ…:ønÒ›ýÐûr9ôûA¨ã3,µ‰ªƒõ[µÐó²í8ÇX÷öÁ—ßëê¾-}齿÷ÁÏýìý/¾÷Ó8ž¥ÞëÖå9*‘†kÕš‹yû1 F1xàˆGwÀ ¼Ÿù„ã‚DÏÓÜo/lß*,ÿs©¦Ã÷?@n–b¸Ú Ñ¾ud»ÕÑ[ ˆo7é ƒ7}A;‚g)9–AI`¤ÕS,sGS ·Í7=á¢ó9žÄ(ñ)·Ëb— ½.X@Τ·£ÚúR ÒLq*ÔÇCu±oËêHn8aÆ’‰­ó:gºï…Ⱦrê8pO ö½±Fû®Ø¹œKÍEl®qÿ¼©{é'^ùs¯|×+Ó¾ÓŽÇÍQ_ÐàKé_ê3TEOÑ‘ìKª!·$ꚪYO=1Xnôû±ÈN3 dFÐN|ó«óáqkAŒhh€zàeеv]Q =¥‚`Ì5‰¹¦zBqâØÏÚè÷²'(_ÝÍnLŸºÐ.y呸ƒYêÁ@÷=¦šM—)WZDc‚˜H¾wŒ› €ü’ˆkª&±9ò§eiôûyÕ·œd ­'&DÝZ{Ä´7:˜sf÷Ø ÕÐ:ôœZÏ( 骋@쮩ž ¼¨6°\z¿Íªõñ$[‰`&ÄÀêvªY›'¹m !T ª7Í=Þu¡.’«TCÏ:.o¨†Ü«kꯓë‰Â7'.šöÛ³jvÂÌ‹oåQ+¬ZD‡¹] AFìY< *:gÒ:o¤©ï 拓B›kªf==òcûnà}¿¥ÖÇ”×…”hL¢z3hü˜Æ*bé¤Ñ€’ß9IzÊ©Wv¨†žðFˆ¡) ±¸¦jöÓª?I}ŠŒh¢›Ó›ETK-;:ïë=ѽ@3€ë€ÍU_ÇN;u¸‡%Æ0–©†B‹kªZ£æVô¾?=òç)L:}̹uØUèŽr+@Y´{o–ªˆ—!Σ0ÿW±èÊ5õC‘A‹_¬s?™ñ¾‘¢D7z ýÔÊšàæ½Gï;uC¢*âG;´jed’ìdÑ$Cª¡Ptìšê‰Â…pŒâ?ÑÍ“£t¸ÛiR‘=k;î VèVÁ€@^¸§T‚b¥c×T{ñXdÓý®*²Võ3öµœj\¢N‹¡ž 4A¿(ùÅg •F¨€ä;¶ê>ÇœhÉq╪¡pt䚪Sfü†ó ]S=ÁøO=¡¸àý×i4Žã‰#°Ž÷S+«‚¤ùVk;s}¤uŸÜ£bCÝ S \S½nÀ‰?þPd°*ò°ê‹¼nµgX-šjÝÆ¥²€ÆÐª•]cj±€¤}Q¿æ…e¯\S `ÜpMõzÈO0~ß+K^yz§s+ n[ãÕK@ã±Ð@Vßú~aÿ@ÊѹIÔjíyA5€Ckê±È?öÊkO,þ¡÷÷ª¶7ÿ¡Ze4ƒ¤Z±5iÕnÈ¡YºO…L½™z«„‰»ãáUu®©žPü ¯¼õÊŽýiZA-”ÛöœêŠóT+d{ö© €ì¡– ²{"!>wMõ„â;+o¼ò­ê-ÓoˆŸ5R3¨ªÛ¸Æ{1¨YeÜž2sdµ‚¨‹[…ªèa,S â3×TO$þ¥YûØïD‡Q7=žE-‰êÞ¼%ñdQèjI×XÛEª Û,‹Ÿ±Œ?ï‰üþ&òVça¼s3~K]Ã7ìþÑçpIˆñJ+C<ã-£"Q-‹ª ó0W*|Æñ­Ð9ÚÙŸ¦zïŽþâ·ñë?ÿ& åW¿òÅOiàƒŸFýö¥/~á§_üBéí׿úå¥åxí¯ÿêï¥ð’küæŽStZ’vÿLÛzOü¾`¿ß–¬bËÀíèµyA'3½ü›¿òËßÍJû™µ2þ«åwbjn»·)~’½VµõÎ ÞLÙïÍæ‘fžiø ÃM]S±ltÎ¥0šÞ3¾ñK_û“Çÿà%þ¢u›ÒËîŠ9uëÕ8Ï.¶Åm‚P÷5ÄÓw+š}[Ü0ÝKŠù•¿2L[—PQÑóåZ‘šgƒ&:ìàùZiÒ?i6Ælð9;µF5tŒN¡@¬‚ÁØÁ¨ÌI}ÆÙu¯ìY‡j.fÁXW#~Óý©tßöNð2dëï™ š³mæè‘,™€DçÁˆ`LL0*êY±í|žµ6hßÚÀ8ã²µU[¿­[ŸqÓÚ¶}©÷ú(Ùoú½ÎOF $­çH0›XÖwGÚCÔÚ¡î²ßöÊw¼ò'-ˆF½¯¾'þ7oZ™Wüì°í¬ƒ`D0Þ&¬mRkݲó[µÁ=;Ð#ÁxrËráyW'è_äõ‹W+#.Eí³Ccˆ`D0&.£jðìí¥T0®åD0ŽšÛÏÈñþ^ù‰øsæ¾³w]µÉ:?t–×ò?·°Ÿ7¡uþ#‚±KÁX¾e@#j`dÁIs`Úc«Aã Fc²‚QQk¢ë©IqvS ÅDIபƒqypI7Á•%¯ŠŸ„„Ü¿òÊ¿h²Î_„ÖùN û ¯ó]#‚1!Á¸#õóú6é‡`Ü–š»ªzàÁ3tdJÝiÈr×~£~B5 Œ‰ 1a¥fÉ»\XGiCj®[¥Pçe'´ gÝà»sçÿÀÓbÂù.XÛé í[ghÌ<:uÖ²e‚mdÝ%U ©»eÖ’|Ý·w›+þšYÿ¹³¼ Îÿ­…ý—´#£¶eAÖã’‰?õ$[q~¿”;¡}\·y>S¶ýY´C0äml^ #Ñ·5ˆLA‚`D0&/UðŠ??€­ˆ²[WWKå~“õÜÏQ®ùw3&KÖ^]Ig {ÁHé½`Tªâ[uÐj¬Á2ã€ÔâÂ7¬ ½­M: µ{¥.Ú½`[‡N{‹`È1ÚÈܧŒFc£+ü´c¤#å³-®[¶NWÐÙí Æ½˜Ï+I­ ¿/éÌÔ FãíÞ\:x¯ÖºMøjE0ƒDÓöÿ°Ô[+› Æýˆýìwp>z\ F€ü£ Ís!V¯QÁˆ`L^0ª+å@Hí·¸®º¯N„äA›‚ѵÊiœÏEF£÷•uÞJ´$FJ¦ã‚ ÅfƒUQ‚±—Úfžµ!—CƒrƒÖìæ|è/äm8S F#‚1!¦çé\j.TÛâŽËÜ•ú8¼ÐºZ‚  Ã¶|ðF·¥®YALäš­Ä#ÏÙçŠÓQ:ú„;¶^+,D[/ÜBµ~ž Ù®ŒÆ´ ÆQ§Mxèü?ä´U©%¼©J}fãçûªÜœ¶"HX$½ Ü[Ýv.hÇÆí–Bíîž³þ¶í£ÙœK¶-· ÚÙUžH€|£I!˜¯«žUé,– ŒÆÎ’Î燉aß©'µ¨¾uØÁHÉæ´]´_ݶ[œÜÐñÝpkªÑîÞÐ!?ÿ•/¾þúW¿’‰2üõ¯þpdøë?ù…¯ þ Çû¯ÿÒׯ¹Ãr…Z ^3À_üò²Ò~f­ }ð[ÜaõhÜÎ:Õð9š­‘„@ð9þøã§^µÏ'^¹GÍ@P÷SuCe$è+ê‚I¢—š€~B5€ ÄŠkQôþxðàÁ¹WƨHML¡ nÊTôí¼&ê‚ø¯s~~N2è'Á\kW´É&4Uó!ÕðYí%ÕPL>úè£IWüøã§›-{yyY \UbB­Ù÷­&©B­*jeÄÕNäUP<ú裩vÖÓ¤8^y¨ÖFjº ,~¼â.UiF'sUwÌ©‚×õh¢ˆ¢±ÔÉ:>$‚NÑ ¨š •é èÄõEŸVÁX ¨VÅ­8¶óÑG‘œ:AçVÔP€Eª²‚ZYžŠ?}QÑ8¢ ·B~Q÷àÁƒ'ž`¬âN }BEâk™B“~<‘âÆñ]"óË'Ÿ|2¡™P=Á¸ëMã»§Þ#s*´À†øn¨ãTdY4­ôÜïye‰[ Ÿ¨ k5jÛÞòDãcuS¥¦¡{â'¸a`2ÎC§#à<÷“‹åÜÒ+×SO0žj¡Æ!DÉÚuyg*ÈçâOµQ4ö½²ÉåÏPüøã5^±Gûðã¾þ¥öÁP‹ó}kS±>@n?ƒßPÁÎ{Ç d_,j&Ôû:ïn¢Ð'4ƒî#¯Üæw€¢V™ý‚ófÏ9—¨U±Ÿ™P5^ò“O>!±IqÑA7WÜ¥* ¯èè¸ZË:g_<áÒgŸ~»…z‚qùâââÙùùùW£pLоNU@ÞÙ)˜€Ò ©÷¸ìÙÄhs:ÏbŠŽgß\bqG,ñÚ© (jÑ‘òÉuö.¹ìÙãÁƒë:Ç¢'Ss¯ÚüŒ ™w‹ŠÄ×^™¡* H¨[Õ‚Òˆ“ õ©Æ ¦ðøÈ˜Z 6¼òÒ+Ä­@áPwºç&¦òNÙ+×\òÌ Æm2¡BÑDYšàf”ª€¢¢±}Œ¡ÉoÔ š¦KèL;õÊ•W†©(:M8æ½ø–Kn4NñâââqÖ2ª%T7Õ\ muÕ?·ÿ OE|×Ô¼g||Ç¥N/<˜÷D×KïïBß;öS-\ÉL£VâG^¹[€öbBƒÝ¯â¦ÓÞç7~ËÑo:¢¾ã6§ßî¥ä7M‰žã,Üo¿þ뿾f™P§²zßøÆ7þ}£±Ëm^…~å·žý¦P5^q‡zÉäo.×üÆoý ÕRçy2rm˜Ë\êtrÿþ}bÅ ßíßUИñG×óÊ)μ“©G³Ÿ~üñÇÓy<·,~òÉ'Là *âO›±HUÜNY|·Í¼f{¼”bL!’z4£¨'ªž\\\ìçñü¼óZñÊ3¦I=‹ÖæÍP­¡øjNÏí¾Wæ¹Ä}‹š õ…'7ó|žüñ¡wž:Ÿ$W=•h޵,b haÔ÷±ž›ºÜ®p‰û‹§¡Ö²š µT(ª`TÌUO:0¦ n˜; ¶ÄÏ&š74Uþ*— °¨µW§>Ñ ›CT@gèäãš10o Iv$ßI}R‰ZÚÔ=SçY,r=œŸŸ#Pú‹Æ“êôAgö?tºn^"¡K±¨™Pï[,_a;éŸ|òÉ„W/5ÙwE_Ðz$~|61¥1 *†"O±f*‚O¸´½ÃI<ÁX%ñËgIp¶µ>¨‹ž£Im4^‘Á"€˜Q§’Ÿyca.Âúž hj¢gL‰ï^¿FU$Ã¥ä'³èœø1L d½åaº¼T÷Tj¢'ÌŠ?mÆ"USÖéÈÁ¹T$q™©âÁƒë:Ç" ^ Ï,‰?=Ð U<šUp+ç¡–§\Îø 2¡zå©WF©‘–ÄõWƨ‰ØÙ wh€¡Z­ÏºÕ¨ì•k.g"âgìâââ¬È™PÛÅ«¯U¯<£Îbå@ü7d£è1‡ÖË2Ã^yÍ¥„´  ptÚ2§vÖß=¯\Iö¶2‰ŽØ«•±œñóxÇ¥ŒMnsqq±OMtŽ E¯ï2?cW¨…ö¡ø®óXkúˆÎc–õi)>•|$ðé+<˜×‰è½¿ ÔôÚ½¢S•ÕJ«íYY²?˜—Õû¯\à{à:z¯É$²³sÔDboÁÞö…m_lßÁqLšX|mõ·âˆò` Ê%55 ÖÑs>kpÞÁý´åÜO{Îq¾±õ×ì˜Þ8P@4ÑÄrû4£ÇÝ/±¨™P_x‚q“ÚèшÖÜFl˜P§*êÄЩuâßY»ìZ}žK½»â´-[²ú [(Ÿ5h!8äˆÕ@´Ÿ9¢!¢oM¼Tl®=4qQ‘z—Ô@0겟†M4ÇòJjV¶;÷(+ã Ót„`jĘË+o¬ý®ÀÝ7ÁíŠÎk§.ßÝòÞ´óucÂï9‚1jÛ/ópC·±Ú¾k%ŒSvÊN}ÎßòÞ_ ÕUP÷åˆëðJ (4ëŒdÍuîD’M¬+tŽ@2¡B 8°Ž?ñ·‹Ç=©Åé Xþ‰‰ -WŽ€81áqéý•DhØÄÂ[©Åî 9"äYh;*€¤f±jô‰Œrsú£aGŒDm³‘ëhà²*mFWø^G°(Áx±Ü©S—·Å NEœïº#/í8Üú}í·p ㌉Ìs{G7Œ@ î•]ùÿÙ{ÿÐøž¿kî÷n¯«níöºì‹®v‘¥D›+ÑníÖn ×´¦%Õµ„6zךÚ\i¤ÑF]!ÂþqÑ A¢ä€Q"F ÷›ïmÀ¥I%Bþxc†’?òGÐ Q#}«ëÎçýœž×¾2çì9û#?Ÿ’=?f^óãÌ™çÌœ™ð…áºæå4Ó;øSôÄ#IzBù¤œ˜É}ô?)lƒjƒYGÞ;N'm¿güâ+§¦Ð˜µB‡£®ýØ)uÏñC÷ ^véÒ$ÇžsÅ¢ÔÖŸßL0:y‘¡ýÉ#ìsåGy&ݨUZÝÓ…pL"»!Î'Š ¦”Ï öcF;MTÏÂ8Š)§q>"Ï |ÃòIÚa§»>À–9ˆÞ8‚Ñ ÝWL0ºê{Þ¾{Òè‚‘BH¶§ñÞ|ŒùMóµ—á$RRöû¹““~wò°ßöòãÛ¢šAcùÈpïTvÔõÊô#–…˜sßûÙóò{ØŽ¥pÍ)ˆ;ߌ+$vÄo»ðÐþ?0ýß¼Yáu aÅг°ÑMÕœƒ-w–‚©+å¾SL"M3¯„R iµC0n™þé½Yø5C0º)¦2ÝO…`ÜB¾¤Äsq%„›´c_åSaOGÆ*üþw5ñsÓ?b[Eþf) !„D±ÿÁØZä¥XÌØ)¨=‘rÊoèÞ•hܳùòÅ¢mG§.ÑøåŠ±á‚ºc‚…F¬Èx„xK Á`ÙQÇmüï¦N¦qß7!xÎCÄyQøÓ‚ÐÜçî~ "A.z³±çÂ8÷}G˜y%|Þüz4Á^ƒãŒMáW içÒãçÒ1£ê¸÷Úôw8h ß6ÒçZFí÷7\“‚ýï¶E”‡üºPÂÕ'Ó&˜RÜTy¤™QåéA”' FB!¡ðù(ß5Lüý­¾ vDÑ®„Ú&»ÜÒáÝ ù”]tè åK X® 굆y9]ЉïE|(IAˆÙsóĹôG‡cEGç*6ê0¬=KEzÆ"îYRÇó¦û #„Oœ´Êª0´_s1ÓCÛ›Â=¾4¨™Á3qJ¸wþ–Cüžõt,Š<‘i†Oü¥M2ÿfؙ堨Ê@m@zBù¸ý·>ö¥xÄ,óŠ’:S‚¼1¶ÑkGK–™„B!Ÿ÷½ÆGXœ£fÂWíûŠB‘߆} ~ë·~kÆnuòI£gGVô·\„B!ä“`8þvÚôÏ™]Æüâ¿X===½dJ|¨<«÷òì¶'?ÛöK‹Uæ2!„BÈçÄŽTÝ~€_Ñô/åþåÀJ¨;võÍž+°è~,z‚qëǺDŸæ›FÛÙd§¡–™»„B!Ÿ›¨Mš)ßàhp%Ô]5õ“|sjWr´ Ü䙫„B!Ÿ·oÕ{ÿ©ûÕ3Š+¡2ÿÞA]aŸ²ÓÃÙqA!„ò…° W\›÷½wÚ—Œv¡”ÓÓS~ö9ÅãG\nÿ@+¹è!„BÈWlÚ`Cã÷ˆ]\ãË|»÷‹_üb¾'ï{¹úäçëÈ÷òö®çŠÄd;õÔÎB°²s”û}Ð|Ãúº†ð}$éYQ¿gŒOJB!„¼f ÊÞëèý†±ø2+¡ÞÙíX,?o÷ÜÕi´‹ÚÜôÜ&sí]a·iy«-‘òßÇ~L?*Ñé¦<B!äsøŽ†—æ‹ô>Ûn¸ê—È罞{Ï dÛ¨·+¡.3·ÆFÍüèø²bÏŽ°ÙEt'íDXÄy+Ì JTÕà’.:4ƒû²âXÇœ öÜž ).¾s§Â¾š q´ïšœç¸}ÿ̱˜B!ïÛˆyy‘¿54@>%\Ðæëaó¼'gß©y¶Ñ~oÞÿbXQ0^@• Øö•ˆÛƒX³¢lÕôÚ9ÁheÒ)©vß̦ Ëúu „Ý2„Ÿ {>D06GŒVœž…Ø8øB!äc¿Sj¿C»Ž?kãß´]ÚEnXüÈ;À ‹;óþ÷gý¨ªßÓ?³cÏôàùê…â‚1-„ÞÂöÔ«9øŸ1áß*†3%u*â:+ˆ;,"„BÈûÆNs²# ¥wf×¾yß‹ò +íJ¨w¿øÅ/ÖYô¾.ö›Æßþíßžz¦Ørh¿.3W&†Olm©:xÇvB„û0‚ÑÒ‚PÜF^¯š`jkbu~oNH0Î ¸Ž‚‘Bù šƒwfÓ®y¹ªÞ‡æøø8 ±Èi_œŸÿüçK½²p{rrò–ÓÁíÌ‚o&ù·q$6åt;ýw ÿ—ÌËïwÆ(·  ðW ¿ •÷é F+L椖Mü…s!„ò†Ø†‚e|OS$›”-Y܈¥'·z®óß³ºÕ)ÏM²mÈpØÎ87’×Â_G y1QXWõ^Ùß0¶ð’zÚvNàû½â®87c6ÜYظo‚Ù&y|›¸¿zôs¶Y?ì7a‹¨ÿŠÜˈ3!„B>öÅöŽì± ­ž¨Xè„«’°²±ÿÊSS­@ì@¤pá¥×¡)˜M¶©Ñµ á&)™þEej—Iò»èùßQEÝ?o‚v|‚±"-s°}!¢bÁøWße9$„B>ö¥}ãi°¼vúÕ‡žªd÷ÜûùÏ~rúc‰"òÖXpe~LEey|}ÁÈtèÇŽHrt‘Bù`, AIÁ8"v%T»Q{O0îR,’8ôÊË$žr#>vj£íÚ`J¿ºHjã/§ÿB!äS`÷ [zvؑγšˆ=Á8Ók,Nä Ë‹Qü_zîϘÛf4˜ÒŸ ·ª©Ï-1y!„2)jæÇHDúØñ‘–[¿øåŸýìî#¹ŸýÒ/=2ü÷“ó¯¤þë1—Éÿ¬çº=÷›O¶â0!„By[ìŠvo=:f§Ð] 4»ýëÿÖj÷#¹Böw2üw”¿ú·¤ŸÆXíèâÿÁhÝÿl8%’B!„Œ;²ø/õÜ_ë¹ÿý í(šŠS0R°Q0&ç¿ì¹ÿ§çþžûO ÷Z$„B!cÀîïõØs¶ájG%þ_ó6{3ºo¯ìÉÿÙs‚‘‚‚1Ñóc;{þ} EB!„2nì>[ÿ“ ¦³ý¥7²ã¿CøÖŽ¿LÁHÁFÁ› EB!„2Ir=÷W{îÿ빿òF6ü}æÇ§]Ýñ#l@ÁÈðßÓ”TB!„B&οÛsÿë†ÿ?˜£Œ F 6 FB!„BÞvŠjáÂþÃ=÷¿õÜGØøž‚‘áS0B!„2v«»©´oñ εMÿB;‹ ð~·àOØFås=·ïÆ[=·LÁÈð) !„By;šçjpÃ`…æê6ØÔº­Œ Ÿ‚‘B!„ö{A»ÈŒËŠãv® qeG WÌË•íÔÑùžÛì¹ÙWŒÓ°kMø!§²f§õž+EØe[îÝ Æÿþ_]îþÅÙ?Ðý ä÷wÿ‹öŸ|qþ?þÓ¼»½0[0þæŸþÉ/ëç_ù—ãÅùÖŸø#Ýÿô7þd,Û¬=ÿÞ?þë‰Û¸løÿþ§kÿùZ÷?üS”‚‘B!„!Ù€,šKóQhãiÏmCpYád§uN ±¸¡hï·#víw"s°u¶o".Im{0?ö©|w‚qíÿƒÝ¿ö—~ó§ÿ¿ýk>ôš¸‚í7ÿàßÿ7þwþj§¨ÏýçÿÌ?Ñ=ø§º«h&±`”ö†Ù ãäsÿöû‡»ÿí¿Òøéÿý¥?ñ“£`$„B!$)IV ¨CuÞ ²þ·£wz5ÓEã_átRSRÃîÝ4/GCφŒ p# F;ZæFí(š=öWÿŸýI€9ö_ý¹?õÓÿƒFЬ8´×ýzùïî»ß¬Ùß6,+ÜâFgÇâ¯ýÞŸþÚ‘I9Šù¯ÿúüÉÙ8ÄŒQÂ.L°Yq׆8‚Q è«¿øç~ºwÁhèßù«¿«o´ÒºæýCÝâ¯f_·×ÿ]ûË㌄B!ä#a…Ö¹ù1'ÜqËsßV„Ð*ÿÂ3¯-› l˜è7ŒVäØÑ6+朘p¢ÑŽ|Y¡˜dô,êZ+HÝÈš+ì÷þžØ#|Z Z{í¨£é³vÿ›sÕ‰Æ0lØ6í¤ IÒÈÆÁÞoEã(‚ñoý•ßa·zéþ¿ûoë;žN¥º¿óoú•îïÉýîþã¿#ÕMýìg/ŽS0B!„„ýÆo{À5W¦¤ÎNG]Çÿ¾ÑÄeó~FõÖ çCƸ¡£ݲÂË é¤Èsßï ‘ŠdVÙoö¦™&Œv„òäÏ/ö‰/gëk F+¨¸v2®`tbÑŽ Žú £MÇLOZÁ*¯üC¿æ=v=#!„BùhÔ!˜Êƒö{F¹ê¨”ö»Äœ]tß Ú¿;ð£±(Å—õ³wŒ¿uq¾b‚-1Zø?‰p\P÷J¿íÔZ;Zêî±ñ°ß0.õ\çµm>¡k¿_|E0ZäFý¢ÎÛi¤nrAf§ajòÿÀß;´`´#ŸV4JA:êhRÁhÃÆ›Z,òFB!„B†£!e]Ik q˜ ¹6DpåM0蜭+yΗØ=á·0¬#^yˆÚª8§Ã.y¨Š{†ŒvTÌŽ8ÙÑ:;=õ?ZüÇú¾Ñ³çÿ¹?ðkG£¤²ß9Ö_ù§¿r…T;eÔ.8cñ#›ÿÈßSìþ7ÿâ?5ðFëµÑþ•#zö÷ÿ¾ŸìþËÿŸùé¼µS‹0ß\iß ð}6ØðÂl°þ²Á^cÓØúeÝPÿG) !„B™M&A(·I¾¥sÛ\HA&·“[é4L0:'¿”[ZXQe…Ö Áf•‘þIûœÝVpYaký¶×ÇŒÎ%Œ¾{œ vº®µÁždƒµSúç¶è `$„B!d|ØÅoÚE&Çð‚ñ½¸·L_=| FB!„BF' ‘æ?»`´ßíÉ2ßÈÛ[ &=")Ý QÒq ¶(Âöo¤`$„B!„P0R0R0B!„B>¯`ä”PNI%„B!„P0R°Q0B!„B())) !„B¡`¤`døŒ„B!„P0R02| FB!„Bˆæî—ö³å~öK¿ôÈðßO~¤~ù—/ùB!„B!„B!„B!„B!äýRì¹&\Ös¾Šsk0n©ž›í¹f3!„B!„ Oâ1ŒæÙµ1Â½Öæùž;`öB!„B>3¥ž«õ\NKAä¥qÜž/„Ü?ÓsÜóÚ‚q¶e<á§`׌çœKvY—2ü}B!„BÈgÄŠ¨móc¤m®ç¶L0Ų 1´ƒkìhÚ&œÃЬ=ÂE\_~EÁhÃ^†m-峿.ls¢0ƒk;&˜2»IÁH!„B!ýB®ªŽ­ qWƒX”XAYÁÿmˆ/)@w_Y0JfÕ99ª˜¨G¸Œ„B!„OÏž FØœkC(:ÁXS÷!-[?·^Q0V![¶2ŒNHÜ( !„B!$v4±q¾f^ŽÊ-™`„qÇsÏÎ+ FëŸüæÒŽ ÊÑÍÝ~P0B!„BHv«‹=!Ów!í* [øß L¹²è޹©ŸË&}´ä!ìì5Uü/·×(à˜\|&Óöìra—Lÿ₲­„ß’¶°ÇÚZOvÎö#3Ú¢9„B!„ònÉ@HmÁUĹš VO­ÿh¤]¥ÔM ­©s vÒU”èÓ®Óî¢ F@[ˆC&Ä6;]uÕ¼Ü ÒÆkSÜ_HnÚî:‹!„B!ä+Qóˆ@B!„B!_»-Å.Ü*“ƒB!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!dz.óÚ\Ï#Îg{®¦\¹ç2 ì±¶LveéSI>„|E&õìB!„7Æ ¹«žkĸ6Õsg=׌¸Æ ÄnÏÝ w×sÏ=·Ó&kK'æµÖϺûvit3}ÙG^ŸÊ-™,“zö!„BÈ2Ósßzî{ ATê¹ \G0j–qovÌ‚±#lO›£¥ïI0vF¸÷³cÓe¿çv‡¼¿ãšý˜×‘÷-›ÈË5Ï9Ûéµ×sÇf2£œt<B!„|9!ä|¢f»çªâ÷CÏ­÷ÜÁ‚±ˆã²A·j~ŒXžÂŽ0ÁXGcÐ;‚Ðu"ô¾çÎ{nÁü˜úº­ñ!îÛUbÒ^7 ÿìù‚±…kÏ`·¤"üÙKiß"¼njk^‰™ ~»Ñ°%¤‹ /¥ÄûÂÛS‚hö¸xoš÷?ÂÖò¾ýהё@ü̉gëÏ„®ŽBÊÒ"Êè1ê†Û7.+5¸IˆavúB!äKâÒqcV4ÒãÆ¢peÜw'´ì°îN-ç!Vg… ¼bà ~Mÿ(Ç”ù1 v×í"ü¬WšuˆçÅÁxƵµõFL+JŸ ]8WhXkû.D:/!V„(>ÇÿëH9ø?œÐ|Døeä…Ž×7Äki58ƒ4ÚÁu3ê¼§[Bˆ:Þ[°}×L‰øUñ{×M%%ˆ”6Ò¨N„s¤§sr(/އ}?»ˆx¯™þ‘ï « ìµ!DçîÝ„-u”á)eS¿óê¹\†m«Êþ‘iÜ;’gíª‚²4²´…g&#ÊÒ¥*K ‘vò™¸ŽŒ®,L‹²PòÔE+ˆórD'ǰ‚qAäǬÊO¶Nïi<{{¢<ñ[MB!„|9’L›Œ+¥³ÐÑHLãXEÝwïŒ3êº)Ó?‚)m—‚qNr%ÄÓ­éÿ¶0jäôV‰®ºç Mɽ Fj¤}›¸Þ¥£9¿×Äý ªÑúŒtkâ>É…Š—Ì˶ ‰s£šE!À¯• háº4ì[ç® ÒšiL/-˜`T* ?ÂŒ/ÝgL0Z›‚@Yç­ÿGªc"¥D@÷=þo‹<*¡¬dEçÈ îM¡Ìµûç¦zè|„`teaC”Ù‘FœË"ûcŒK¢Üfð UzO‡¤wV”=Wβ†B!äƒS1ý‹Î Zte‚Q6üïU㲈kîLÿÂ8]`LCtX‘t£®‹ŒOCYÚ~«—û£¼¶$l°á<ªô~6IûlýAˆÂÜkp¼–6EØù¤Â{ŠˆW3¢ñ½l^ŽúÕ”ØÔ´E6E~= ú£¡G´ÍËQ¦¦éý‰3%µáŒS¦ ´%¯ìØJ TÅ1kú¿ÓÔ65Dº×=¢§¬ìmFØæû´eü#v)<—'&!Ô‚±óù)šè)©‡é´,Ä¢cμ9V0Κ`„;‹¼N‰ô®Hïšá”TB!„|2ôÖƒ¶„˜¤`t 6{l¿ øhäwDø~䄨$O 4%ÇâXRÁ8§ùþ?3þ…8ÂÒÖŠ^;Úq%~¯ˆß)ÄoJ5ìv4d'"¼$‚qÚŠ¸'Ž`l‡ˆ—8vœà¸vÙ1Æ…aÑŠ)ÊÑ "£ãÒMǻӶÓ鿨Dù›Ã³˜N ¯Mÿ(xy€`ÜŽH§¦GÐCê¤a§¤ÚΘEÄyW¤ÇzŒô¦`$„BÈ—Ç'ÃöF0:¡#¿µ»Vþ¸ïö´`ì(á· ÿ³âü²G0Úo‘ì·|Ñ µ#Õ!㾺öHØ#Ã)!œ}NDÝ 1e¯Jœ©ðlz<š`jæ½È›,~/!Mÿ"'ñp~ï˜þ½” F°âÆo¦äh&D\7CÄê o÷†ŒOgÂŒzFŒ;êÙi([µM"ϦLÿÔÛAB?¥:Z&þž¡'JÔ7Æ6:`d¸Q‚Q—…ª fØŽ$= bÕø¿yF0êºmÊôúJo FB!„P0zDa[I +³Œ;BÚß—ÿAˆ9)íÿO&X©q¿gDãÜMÉ”‚Ñ6¤ñûþ7Uü’ÆsØz‰Æ¯k”§á¿ çÑô0Iûdú¸Ë:~O‹{lÃÚŽüØQÇSؾ „Ò³bñÀ#4Ic ÿܳ¬ÄNaÍÃÞ]Ñè_`p‹Ë8!¸-ÂßBø;&Xp$%üv‹ˆ‹ÿ³B¸Úð–Dƒ}ßô”ÕMðý_C‰Ÿ!ÔÖÍËÅJ–E™YÝÎ6·r¨‹Ç´I¶eC¶ìÀß%U¶ÜâH5¤É™*3+¶yø5¯:MÜbM»(‘n{"ÝVn¾…æÅ³u&Êñ\ŒgÄæÃž…ž(Á¸e‚ŒÚæåªÄMQ×MÿJÄSž²²¤ÄgiØ2/:BØ5QŽ‹ ÒÛ}ë;‹ã-órq(B!„OMÞÓ ,„42s&zч´ ß÷.§Î¥ÐЭšþU å(—³¥&îÕöNÁoß>Œ%Ü›óÄ/3^îÚ)Øëû¬l§ÿN‰ðS¦–THz¥Ð(­†äCá•Ä+kï!ç?)‡ØáË£¼ˆGF¤»LǨŽoíÂl [aÕåï´§Lk¿³žk|~çÔõ3úb'ÍüË©ô“6Ô<éîÒ®*ÊbÞcÛLDžúÂ)‰4É&xFfàR&zD8έËKíOÆ“—UÆõùœª“¢ÒÓÄ8Ÿç3|eB!„2:M&Ó‚ñ'„B!„hÖM°€Hé §CU¤ÃâMƒ ‘>„B!„ÏÊ‚ñ¯Bê§+B!„B!„B!„B!„BùbM°o™sv¥Ét?Ê&|EÔAa—'§ZBû †aË=!„B!û½•Ý3°#Ü=ŽÍÆôcОŒ’Ó¿¹ûþâÔ¡!@@&Pî¿"y&!„BÈçŒÏq»é÷õÎRÌÅÙðµã(÷¾vß=»é¸Ý8|;¤ažÁ¹µW²©: `ç÷&~ù òa’‚±¿mFaˆô•©1øÑò¾5ÄmÒew é[ák€B!$¹`œï¹ïb¯=1ý£²ál7îÞì¹3\+Gì¶!ÈŽÐÀ·+M. –zî÷m›`¥É~×áï®}«¸î÷™p6a³¶ÏÚ¶£Dš;3"ÎøÓ¿zÛ„Y¤™/^6íæpŸµ·#ÏvŠŽ×.OƒDÖ[„+˱+ó¤e^ˆÎ ”——²œçp}eãèÒ·1 cRá#Ÿ¦_)OGMß_„B!Ѳ 4J³£—h;΅гç^4¦¥`܆SpV( ÑÕ… Êšþ’ø9‡ûŽ! œðyƱ4è»&|T© {§!üžà¯ çÄ)ˆ‚=}y„Y"­+Á6ž-ü¦àï­6!ZËKÆ«‹û+²ßMøˆG Üsüm =´¶a¬!¼8îiøeód÷/ !혃P²ñ.Y0–àï.ÒNpÕv[ ‘ l?i²4 üSQ>ÏÑ©áÂx† 6Œ-”'ðÏpmåè{H|]>pÝ>òCoµ1…øìà™§`ÌAüîÆOØ.½çÕ¹º*c®l$Š OG´m3¶¨¸¥Q>Úpeå¯K¯-¤ë”§ÃÀ•ñ:#!„BH<ÁØUîÎô„UÐp– Él !(cM‰‰U()æŠ"l' ¾©†~÷!¬äÔË[ˆÁ0Á(ŠÛBüJ1gШÿ.ÄÒ¾cL‹»°Û¿«Â¶œjä_àÿS¤•lð>Á¾¢Gø^˜ðQÆ4î9â>«â9+ØqLÁ˜Eã{OĽÿŒÚ ÑèÞiè+Dy›Uþ,Ã¥Jäa¿K“¨MáçÔy+:"ÎB(§Dy(£œHÑw<@ÔtD•o)aÇ&®M¡œ-Q0ʑӒêü©©ç{é Ÿ‰#Õ‰”JP§dqÏvLÛŽÄ­ Ò42›ùÕ†íYßñL£œ•D\R0B!ä+S@r®Ò(“SR݈\]5Z¿+¿ š´`´ º4Äî!>ãÆ®§áv‹F´Vú\#B0êFwGœ»WqéŠF¨´o‚Ïþ¾FÃú Î;Ñøî*ÿîEœ]ZÉóßá—‹—lŒwÌài©û! é u¬jâOëkš—£1ëð7†¸$"†Œû.íóJL•ÛI®e_”Ï[%o=e©r®nÍ#«BèîxîÙ£`tS¸ËÈ¿¼Jk_z¦cäSÒÎ(íÛâÜ_0ÁŠÎ»*}šªÃJ¦ß’y9z¿AÁH!„¯LÖôo—‘!Px ¯ºHݸt»K4ðÝÖ˜‚ÑŠª9†=6;¤`”#Akz–górú_:ľÒa S÷ÛŽ í ð¤DŸôï›ÇNwÞ¯acÕ“~Å„‚Q/@´Œ|´þ¬xîÙ£`L£Œ.Ã_9z|!Ä™skC Æ;–)äÙjLÁhÓ÷Ñ#Ê¢£Î²‘¾û¶Æ( :A–ÌËÅN<éÙ4ý£Õ“ŒÚ¶Õ÷¯âùsuÚ‘G0CÒoÓ¼œÌ)©„B!1uZ0¦ÐHïáô¬ñÇ¢Q)£=›þ{cÙ#íßC!¼Ñ@Ï )]#4Ѷ&ì>×.‰p´}–sÓ?:{)„¬:Ê–}!P·á‡‰ÓH£â˜cÆ#8ªÑ]3áߢéѲŒ G‹Ã|ˆÀF0Κ—ߣÊðÚæå”ÈÔ‚Q~‡š2Áâ7ƒ£Í¿{Q2¸6J0ž*;wD§Í¶/)ã_ÌhÁ˜óˆÕ–ú¿0¤°U0úlÛNp¿.‡í‚±j^.HµOÁH!„’\0JaãÄKÂÈŠŸk§¼G0náº#5Û “ß?^@ -(Á˜‡Ÿ×ãAÏaãºUBÔŽœ~{)ì³lÀ¿¬hlëï9g!&lxWæÇTÝ’§&˜úø(ÄlRÁXAš] '§‘ÖMðã:lí˜`DµÑ8nâ¾6þo›þé*ŽÍ™`a)x6EYr¶9XǤí!Ú‘æ5œ“«çºi¤uظ©˧†ˆ{Ø– È«cز'Db”`tçD'ÂùÁ¸¢Ò³¢·‹Ó<ì¢y÷ ?jB\F¥wQ”£Ê[Kuìªó;*?ë"ÌOz‡1ªmq»M‰]—fmäA¶O™`%bOýiåcuÕ!ò¡ÀW!„BˆŸ¬ ÿ†(¯ÎeРÓËåçLÿÈU##~Ë…DŠ8çÛ‡q a¤U#´¨®+˜—ÓËdø–¾’ª 'ãiðMÿB•¾ôJ#¼iã_ ¤„4ɈW>"^nÑéRž¼¨Áfç¿KË]¾ÕAœº4âà[ì¦0À¶¢ÇÉtpùU i¼§Äù|DžFw”EÞ§„­iOØ:¤+óÙÁX‹!®*žòîòQ§W&Az§ÏÚ€g fÂG0‹îcm©Û|e\çç ò ô/¨ç© â÷<‹5¤gƼÿ}W !„By¢öol2yÆJÁH!„B!Bܸi€‹LŽ‘)›ðÅy!„B!„OI3±³B!„B!„B!„B!„BȘ¨™þ­$3çܦí™?Ó!÷UL°¸ˆsSCØœ"®6ìì˜ÓÏ®æ8Íbôêe6Ëd „B!dòtáôÖ¶Aþl^îqç(â¾?‹!÷Yÿì~Šnóu»'›Ý#ñ2ˆò_b…èž »6æôkÿž˜fûHüü¯1!„ByÆ·ÝØ\¯ ¹ !7H0~÷4Þ ƆGœÞ™›‡S0j1gEqzÌé7Š`åÞ×dÃüØ|½eÂWµ{ì›×ÙL}’‚qÁüX ¦r~ÕLv%UŽVB!„w'í(×¹:~ÖsJ0n@HJÁØÄ5™£Ø£mVœ˜£‘JˆHÿË8ÿÍü¥´ö¸MÆmœî{n×n›`Óq»Éú.î³×-*Ѱd~Œž^ör„è;‡ßÖ¯Cóc“qã Ǧ鼰[Ú·¬lØPédʬG°M‡—°»‚ÿË*^+ÂÖ“e*8jFäûŒ°ù¢çÖUçD½çöEœòª,œ!N ó:#ŒÍÏË>«$B!„òÞ£1ÏB”å ì–cÆò; ã:Î!œ¬Ÿv¤rNˆ”'ˆ¶"ç7&tþÛßwÂ?+" Œ²B8UDØNh\Bh–!Äî…@k"üUœ?‚È ŒÖžMØÐF8i‘6{u.œY}K"ŒÂÿ&~?Âþ_Ax+ðÓMç=‚œ‚¿×"ÏšHç5ÄË ´0œˆ;ƽ›ªc €ã-”¡0Á˜Q6Ï"~sB$=B0O!q®„²YÇÿG‚±Ž¸M0"º ®I!­­hÞ2á#¢Ã ƪ{ÑÓѰ$ÎËsyøye‚-/–Y=B!„÷ khˆ»‘¤UŸ†<%Õ2mú§¦ŒøûŒkåÈ›ÀÒßö]ChÁXפ!7…˜ë¨°­3,rzêŠhMˆ.‡¢a‚Q‹É{ħ!”ç6‘ÖÚ¾Ò0‹ûNac"Ä »œ¤#ÄX×ôÎ-B„¸xI[Ë"}äp¿øRàì ¡º„ôóå{VåoùÔ‚qG¥iGÄ÷Hùõ=D0æ`ÓŽ°kŽm¤§»~7D4#Kð?%Ê”%n ‘ìF‚§…-"®.­ó¬ž!„BÈ$9„H²î|€`\ל£QW0º´›šwJj üoªqÜ1Áb<ÒmxiâîBíQ4æÃ£/^5—}u®!÷=®a‚ÑGí®Bìë@ 5×Sü¶ÂbKˆ+ŸŸMa§vÏ!ñ*ŒF¤—fÓ¼\¤h/"ߟ[Ñi c3D0î{ÄYÔâE»æåwªnJòDœ³[cŒ9Ø;ñ˜iT€EáJæå·’œ’J!„B^il]Q m#û ×݈†{\Á(§¦&ù†ÑÞw©„Ó‰§ŸU6[ÿg †ÑXw¢k`œ‡¸”ØcwC Æ#uì 6-Š´tdL0¥í[G¸ˆÛDØ5~;A´ë*×|W‚)-~S0†‰,_¾ÏBÈÏ [/b Æ]ór%Þ‡Á¸akÍ߯‰KRÁèò×v¶,#ï*âYÜ ÎÍQ0B!„÷Œüìâd+D0ÚFo9Bl”M0Í4®`tþ~ÇWp]^ù[U‚q Â/%®{R‚ñÂ#Ý7uu!ZÏL0 6©`´~ĵÏFyü¿޶¯ÑꦿNÁï;qÍλðòHƒEøoÿßPäl‚qIuB¤_¾¯™þo%§‘.qãâ”Â>jÑ›]Ó?Šhïk‹N‡–º~ƼuV0.™—£›-‘>¾-TôõÜf…B!„¼[Á¸€ßÓ!‚±#G˜ØX7í’Ú‚8ʉÆõ#Â|4ý£@Î+¾™`_G+Xäj«N˜<+Á(…׎Ÿš`A—¤‚ÑŽÚ‘Äsø)¿«¬‹pnð7bŸ1Áª¬+–vBÒÊ¥q¬B`^‰´))WÌËEo¤@´Bl"ÎÚpˆcåOiìV¤=Gz·cFßÜw‰4©E¹º –i){ܹ9Ø.¿9t Ï4M0RÝbuÊs~S…½‹²5|“#š”͸mØ óv ç7Mÿʹ„B!„V3æå·rF Û/…œ·÷†­„™†hÇÞίLĹbBû¢È"mriR~…<*A Úß2…4(P¦MÿBa‚qnÚhié‘B¾TCÊ‚;_ 9ï:ªç !„B!„ A“I@!„B!DãV˜µ®Êä „B!„B!„B!„B!„B!„B!„7§f‚m$•ã»gÔ*¦E„!]Ò Ë&|›ŽIÜEÚ„oé@¾“(c„B!„¼ì>|vo@½]AØ~‰º±ü4@@ÙHÜžÎÝàX\á¥÷é ÊÐÓ!îKBÑ Þì>ʾ3¹OÅ$ÊØg¢Â$ „Bùø‚ñ{Ï­'ŒË}Ý‚±Òоs£|1÷‚ñ5ì{Kæ‘Wa¢xçw&þÔ'ŒSðÿjÈô~éy;ä}íž;2ƒ;­Æ!hÏ G‰ !„B"£mð>«¢Œyˆ>7Eµ±73‚`\QÉ<¿7¸~>¤QžAcò®=½cØcï·›Ÿoˆ8ØÔ54¾¯á‡›; ÖàïUDCÕ‰¾®µ£³uq>ñ}…ó[&½•ö­öܸ¯Žó޹žÛÆÿvÓú]ØmÃ[T65püb,#Òôç=W(SÍÏO*\YÖvE:eÛ¦ûfϵžVL̪ü?DÙ݃¨i~ñôŒ¢0½ÅW*¯ FB!„hÁXƒÐ¸âF ÆD[Nˆ"}T£ó 2ëì4Ö4ÔÝHSZˆ"è÷&ØKO Æ=«ü:A£ÝR=Eø)ïÛB3â¾S!€¿CDØsËø]ˆŒ'°Á Û'aëÒq~Â_m_^…qˆßeü>0Á¨ïâ]B8÷HC[oq¼„ëN…­ßáWB³+ÂÌ#­ ˆÃüÖS•— ¦¶CüEàTàw áè錋wÛôﳘnÆÕˆðO‘N®<^ Á‰‡gøQD:<"R¢³Á‰™nH|¦p| MüÕßîVEœ«cNOg¿ »ö¼:·©Ò³i’}wìÊÓZ ÛÖCâ&sèpr¶—•@mâYpç§=÷7qn‘‚‘B!$ž`Ì@x4=‚1ÎýQÙgøw‡ëoÐL‰Æå½ºo‚O ƪY)Ѱ•bÎxî{PâœO5üŸçïCâåÂȉc; Ƽü6s ñO{ì;iü!¼‚x= Ñ;A*m[¢ð÷82B”úl½5ý#fò¾6ÄmV¸m%"æ„Èßö4Ƈ8Y¤£+sêº ‘nWüµE¼£lª‰4I#ÎûB0Þ„¤gUˆG™‡¾ø8;ÈGƒ¿‡âþ%ˆrwýšy9z<Š`ÜyY2ýSë°ÏÙ²`ú§¥çUz&)Ìà¾íó{¢LkÛ Ƽx)uo v;ÿS*¬,òÀ¥Ë,ž! FB!„|IÜÔ9ëÎc>û÷;DÀ8£œ’º´ P×ã:ág˜Q¼†¨ºŽ)»žFá VnÕßZÝFF-n7`C!$ZÀ9ÖGV˜]@<B˜\ ãóÏÙûr¾füßLFåkÓ#´6ѸÎ!žZµÆ$p܈ðÊ_Ú#Zˆº¢r; ÃuÌ  ¹Å—n”`ìxʸ/ºœD}ÃØPåÜ ³štšöc6T‡r„Зž{C¦ç°b¶¼ÈÿJËň²:…su‘w2L)ê—ų¿ê¿- FB!„|U¦… ªÄ|njêÝ„£;ö$iKæåÂYŒ ÈFùx®Ñ·S0>«4HáØÌ‚±«¤-4ÎM©pr!ö!XÜ”Å"D°õo ×Ìã˜$#ÿ·Q’ /Ž`L«c«&ÑñÝ7.ÁèÒjÆSOD|޾tõ!ŽKó¼¸/Ž`\ðt Œz4wVÄË—v»cLO'¬Pžä¢/=¯(µm« cÏý” ¾?Ž SN9õÙ³LÁH!„_𹩩]ÑXs{¦Ç$Sˆ'ø]€x“Ó/L0Í ¿,« [/„ÿnšiÁ#ѸwBoâ35¤`\bæ¢×r†p]8k"œ<î•£xW¦ú«õšq|4ý‹÷Ø0ö„À舼Y@Z憌²A3Á(XÊ#fJæåêºÃ œ9O£}[‰ý=e:âúAe¾,:&¾‰2%]^H!û8@0 »]:±/^ry=®Æ)ñ<ÉÎ )ôóžŽÉÖ„ã”GH·FσFF¥`œ÷t4œR0B!„ÄŒÆßô5”H*ŽI0ZìhŸþê¾Ùª£ñ}u*°RøµL°¯ã74D£ü 6Í«ûòðûÆ«cVD|“ Æ3øwoúGŠl8—ðÿÒô/Þ£ísrùâ.â¯ÅÔ=ü»E¸yÑÈ?Å=H‹º²5‰`¬¡ñî ‘S«‹Âò›Ã´œr±WfÊ!çÓ¢Q!^7ý#Œî~›6+¿e^N‘Ý0Áw€nÊÇÒ³ƒüh›à»Å(Áh tÖ·¸?J0.‹ôÜ1Á÷Œ®¬ìŠëö”ˆ[ó¤W%fzWPFW‘›JÜg`K¯ •ŸÇ·Äù͘uÊ Ûªè,’¶m¨ú§‰t;öäeéÕÀÿ§¢,Uæ†Hãc•G.¼%Ü¿ƒ¿y¾!„BÞ7na˜A 77z– 9_Œ¸·`Æ7šP0ý ÊøÂI%´/Œ”‰^|ÄMMŸfÌ<š1“‘™B£?q~&â|qÀý:½F)§ƒÒº1 3Å1mü‹«ŒÖ"Êi.‘NÕˆû'iÛ$Ó,r’6„B!„¸éE“lû.ðíˆÞb„#„B!„Û7¯i^îÉG’3%Òs™ÉA!„B!ä³cGŸí·–û!n‰ID!„B!„B!„B!„B!_•šñ¯¼iWŒ³Ì|uÀuE„¡]’…@Êf¸-‡½ï£2m¸Ÿ!„B!dŒØ=æì^rzû‡¨ýú¤X|2ƒ÷atû&:÷ ÷ÍÅ´Qî§EÆôï¡÷¾ÏBç‹ÅwAM!„BI(¿{„F”`´âÒ®üø€û ÆŽç¸Ý°ürÌ‚±h^nT?I–ëìFóé›Ncˆï÷.gW!çqþb‚á#}†ÁæïÑ+äálÏŽB!„w&›Ó!‚1ƶ›zZÃïéã ÂÂêǬ\Œ94à¯qí±h`ÃgÛ†ˆƒ¹›æÇèæ üpû N#ì øû-¦8ؙƵÿlšÀ¦[ÄÕ¥ólÞÆùKˆ GbÔÞ·‡ó“aäÿþ„‡¿ùî-¾’èoP0B!„÷&­ Ù1ýSS¥`ÌB(d…øÒ÷G Œ+Óÿýbþ·qM¿[ÃNu½Ç_-­°;‚p´à¿-ØS„Ÿò¾„àî;‚Ør‚® XB¼¿G4Ü+"^n¯=)¶3Ÿ[æÇæísbãéEx—ˆFر‚sÖ¿‘fw”9\Û tÎÞ"þnÁ¾ŒºnéÔi?.ÁX†¿.Mªaχ”¡¦péeÜí1–S°Ë¥K-`Ìãg{IÅÙ• çÿ´Ç_wn‰‚‘B!„¼WÁ˜hkzcœû£ã3ü»ÅõvoUψI âP Æ ’Mr³hú§¤ÊûLÿ7“9\[‚QŠûñ G)O·çiYB\îqçã•.~s°Q5%Õúul‚Q¶¢²Ùôï¡·fúGyGŒG"}‹è ¶ÉôY@øqüMB3Âæ´y» c^å½s çR*y\ïòŒ„B!äUè@`tMÿôÏ0Ágÿº©©ãŒrJêd][W¢Ò9Ÿ`œø¸ƒ¼Š)»ž†ø­ F=oCÎ%G¶Ñ¯GÈêii¯?…ø»ƒ˜–‚±"õ9_Ÿ`¬zìªàÿÏ=ÛcŒ;¥U$9º¹‡¸I·ûŠ‚1ʶA‚Ñà>{nÑcg3â÷¦èüp´) !„BÈk1-Q%¦àsSSï&$@| c;²õM]“5ÁÈ‹BVXm‰†öjLÁø¬Ò q<3fÁhã2¥ŽÕBÒ2 »VD\[1£{7Ê¿£‚Q/3/DdËsÏÖ£¥„0­¿rñÄ£ŒÒ½–`´”…m+ cy^‚ £o$s‚‘B!„¼'´àsSS»¢œÆ5é1 F;5ÏN½;Ãï<„Ó‚°áRˆ'ü²¯ª®sþ»i¦E`<„sÓ`7ÏÔ˜cÁ#´Ú!bÃ-TépS0Ú´°Û•Ì Áó<@0Êø»é¯ia£Ìß\ˆˆF0N{Òr[¥^Fò펡¬ûlŸ1/G^·Fׇ ã‚é¶yÃUR !„BÈ»ŒÆßô5”P)ŽI0:ñ]„aÏvôÐŽnÚ©¦ÇB4èÅkžàçµ öytBè6Í«ûÜJ¯nÚçµ  I*çÌË…X âüDGö¶Ÿ)_‡ˆï9ü³÷}‹! âèÒì~D ÆYø¿› JèZQfG×Vñ¿œ.¹!òÒŹ"Ä]3"Mªˆÿ*ìУx„·.Îo{ìw ×lž8HÛ:1m[öäµËæ²½ß+H×cØçüî ^.;ê~—ÒÀ•—,«&B!„BúIAå\—3Ñ£0ùç ¯— b&Ƶ¹lri–p]ÜÕ7Ëfr#\9ˆôlDÞLG¤Y.Aš&%?À¶(J#¦Yéžb@!„Bym¬Àr[Y䘄B!„BväÌMÅ\drB!„Bùìd…ö¹y&!„B!„B!„B!„B!„ò*titÕwm½ß%/©ãÙž[ê¹fÏ­uƒm)Üù9ÜçsU\S»&ÙUÓ¿w^ÑüØš`ù%½ï0«}ÚÕ<ëï,.\ÝóuȘdÏɰäG '¥žÕi¦û§À¦ÁRȹyU/ÙíhJžëæ<å¡‚úÛºYO˜a®òn˜~éô‘êöԘä !om¦™ „ŒO0vᕈìJ1ø(®wî ‹—FïoÇsÞ¹}\svM³÷MÿñvOÅŽ‰¿7ß;Iú¡¶b¨™—{F¾%¶¡Øæ“4ÑÆç†èé¾B˜µ±ߕ^ªgµùÁóàµÒý#ÔY] ³âèYÕK‘ÝQåáÀüØKö@ü&„HG8ö•ø=ònh¾ƒtú(u»~^“0mú÷ ¾eÇʧНòŒ-f!ãŒ÷]ìA§cïo±çžzî{Ï­c²Ús¸®…ë¦{®çüt¿ËJ0Ö´A0ÚôkölºåíFíë!׸MÛ‹Ÿ\06U^¼çF¿µõ8$Ý«âü$¨ yŸlÁ¨m¦ŸÁ³åž±°Q—Å æ×k ÆÕˆç(…sí 5ÆÝ~±q…Ð ê?‰u¼B0Úp¿›þ=h3‹!á×CL¦=þÞz»4šØ;¹ÑÊ| Áèzž/B^VeTÒ·p&Ø‹°ÆÏ>Î]šþ©®>l¯êJ1%­Ð¾†[QÝ&Ž[»vM0ÅI7*æw{ì\½ÑؾÄù}Ó?UjC„¿lú{‹7Døa"kçïÅ‹ÎVÎG8þm@Zé¼ÑöM‚Æ€ÆÜ¤›Ã¼lç¶·H_׸k on”½)”gwn[¤ç4ÄW ç¾™ðé…N06qí•jÀ;Aw#Âq#B¸×–¥<âmŸ¹SÄãÌ î©^2ñ§6äõ¥(‹ËêÙXç#žWêûl“hŒ'ñ·‹òu£ŽŸàxRÁ8ÁXô4®K#Æ]Øt‹ðʪ“ÁÕ—6o×E˜ʯMQf¦E¾4Ñ+0wÅs(ÃðÕ­{êösQ·W”ßuõn鄨ªŸWY‡8û²žûò¸æYøíÞUçÂ&y¯|F4ä3÷eÍÖ5iuîÆSŸL£ž”õVÕóÛ ‘§ã¢9âù×|ÿ莫Qöp®½‚`ôÅÓuîBÆ$íHá Fg<‚ñ ¿g<÷ŸûÎ Œ„ÒmˆköqM1†`tèjȋ핰}áðÒhŠÊù;¨ET,wɵˆpM°uCN  ^p‚ñ÷Û´{/¬&^`eœ?‚Ó {ßîK!Ì'ñ"¾Eƒ`Îþ^ù¼D]§¢Q<ƒt("ÝöÐó½ØÛ°-kïPI§!^ïMø·¥7h”¹¼ùfüÓŠËH“)\¿‡0 ÕF£¥>fÁXDÞîáš9Ï Ñ…½bú¿íYåι|ŒÇ3ƒ´mãzWÖÇU4ØÜ‹xù]@žÃ^gßw¤[yò=ä™q‚ÑuTÌ¡\9w„òCXç¸ÖÀ&7Â’Âóò DÀ‰(Ë>Ö`·køéòPÅóÕ6A¯½{Ý£ ê¥Ø•ÏÆ%â4…²×eäV<g‚q ×Ï®OÃÓõ²ïyêŒqÆ‘&«ªleEØ[ªìWp¬Ï ¡Yäç´ˆÛ=Ž3%õeøi95 ü8‚ñöEg…ßÏ¢Sm~N¡œ? ñ‘F\ݾ Äbaî‡ÔíÓ°gAÔíªn[~#ʯ~^]RïžÓ±.ÞFˆð„ýÍÌ.ͪHà \ïûÆlaf`ÕÝî]”Åùñnru\ 6µ‘ß›â÷…x.âæéœx—o£®ÛPu|J=‡3cŒ²~Yõtl/îõnrÏ¿|ÿ$ýtǵe"lk#ìµN÷0Á8…2â:3óª~Zƒÿ»Cw2TL0eÞS‡Î{:¸!#F+Øf…x\V‚±&àĹZBÁx«\’^ ß”ÔbÄ 1-7ÇâÞ¦xTFƒFj! ¡"^fiqÝÍÁXP=a®áp¯ny\ŸUŠ!§xAº¸j‹¸_(!7%âîÛ !S/¸}Ñ(¿÷4¨/bæÍ)â–î‘fY4Ò¢÷zE‰ûµ1 Æ]– [¾”ÖÕKlkL=¼¾)©²Üœ‹òø¤^Êe4 Ò8þà)ƒÅ´~R¹}”Ÿœç¾4ÌÒÆ?%u[¥ÿuŒJ1¤a²¡„ÒYˆ9Õø›KîÙÏqKäÑ™ÊÏ™õ‚I_6Áè­ëpÉ »ä¨Ò¨‚±®êŠ–ˆc~DÄŽj”E Ñ0Á¶'Ê·k¨Ö†ŒF4¯M0[$?‚`ÜUý[ñÜê2q/üÜñZ@¾ºrvå©ÚéTTuʉ(wuUN»ø+Ó°í)'&ø&ëÖôÏå·QaT½V®ä¹G•ÆÎ¾rÈsª§¤®„¼ŽÌËwümHÅ&Ò~eV>+ÓâYÊ ŒŽ¨·žÅ»ª†ø Oš§MÓ?Ò9¥ÞUÛ¢# ï™1 ÆœJ»u]SåÙŠ§ÃtŸÄ±­r]˜`,ˆüͨg×ÕÅ«!çgLÿì–EO‡¿+ß“ž¹DȇÇM×ìšo#œ`Äÿ‡B4JÁxŒßóžû¿á\)‰`1^Iã< x Ý*Á¸óÅ:H06ÍËÑš‚Q¿|;âœû&Hº‚zéy*g™6·ª’nFœÓ6­AðÚcQÓu¤Ÿ2¾—´f!"o|é®_‚3☯á5FÁ¸ 1‹|bê@¼ÓÓkÇ)§a^HPnâÆÛ|öÙ~ùc3¢‘™D0úòó Ä×h»Fùê(Á1èÙhxâ†oÄt[ÄEZL‡Ô!ÃÆ)Œ¨ÏÀÖ”“ëª\.(1<Œ`¬š ×þ ¿}‚q}€`LyêÌꄽc3¤,§P†¾¡Cä\u²Èk…ýM\§Ÿ«í1ÖíÓ*|ß·˜[cªÛ££¯N¸ I÷Aß06•ˆ}ðÄÛ7Äul<@žšþi§'úw&XÉWoEýNš§¾™ë8–´¾:`TÁ˜B=·l‚™TRd…¼^C0¦ð¬úl‹#Sh[¸˜ØÝTé›òtªHÒføoŠ ùRäE#®C0æÕJ¨N0®â÷YW< X9Õ¿ ñ÷­£=ö=OiϽãŒ[!l”`ÔßL¹ÊN¥ÐJ©—ž­¨ÛžÆk+F£âÊô0ÊÑÕŒ(/Eø÷lüÓ‡¤ŸuórôhÙ¼ìÉuá}G6-ÿQ‚qÞÓX^ŒHÿq Fc‚Q€uÕ@82þeÿ_S0¦ž3êeé+7q£tÓÜh·žŠíÊók ÆV„ÀÿfúGFâ F+XV=ñ ã0¢±¸a^Ž–eZذSRÓhH×á‡ë¼s ièrYQ0:!Gïtù:6þÙ·¢ÞiÿT÷UãÿænTÁ覃J¯GÔnP'=‰2¾î±'o§w•^WuûlŒº}×¼m9õ}’ò[L å”]ÙàžQ0žzÊ|)D\äDÚÎ íäw’-‘¾ËC ƤyÚôغ*ÚXË1ë¦Q¾a,á™Ûï½ÒG?ã¯5Â(ëHmÛ ÁèÄæÒ°œP0nŨC‹žç‘2 R0â÷ŠG0¦ÅHâ•]ü¦çö°àÍ÷‘ÇASR÷=.‡k¶q]aDÁX1ýß-Ñ39 Á¸`ú¿HA(E ƦxQÉ)F‡x ¤ÅËíÞS oE˜" ýNT£bÕSf3¦ÿ;—Eœ“‹1D Æñòz/ ·d{3"o²"íÆŽ°)…UV¼¤3Â5¸OUã.®`\ƒØtemg@½p­:3fMÿb)«ž†æô˜£.¯ŒŒå”#£ü]ŽÿºøiÖ6Á‚G¾Æù’éÿ¾:Áð$žÓitrlˆò2c‚…†Æ-wLÿæ%Ÿ›ÃǪ1ü,„^ÖôU·çN aß™¨KWBêv÷M]YÔíO¦Jõ ºÝ ²ƒ‚1§Þ=ºñ1ÛS1㪠f;|=òì*\å»xÏfL°€QRÁ˜4O›ªÎÏ«÷Ë®ªï§Œ„}Á¸à©·UØO§”‰ùþE0úlkÇŒz¦EÆÓ%WUùq+,Kªžc„qF»ðìØƒ¨{‚Ҋǹ££ÏqM’Eo¢¾/ËG¼X.P™)7Ñ=Ç};žóne½]„}Ò‹Ú…w°¯¥zXOpü/ìjÈKp×ÝBpÉoH¢nzÖ*Ô–ˆ»Îß{¾ˆL×Ý‹F„›rõèy‘JA}Œð/M°pÊY„`\„Ûp%õ²p ¬Âþ¼J§}„s„ÿe#Ç®Dùšp×CîVÖ]Wqi©óm%°ga³[@ ­ò)l”g ›Ë‚1o‚©_®ÜÌ„”›A‚ñÞ+>š—#n—¸æÁ+,Äùü® !wT­{:ÖaË3_O~ip<Ý1ý+Ãz6öijq< ^ØÇ3ïÊ¥^ØíÖÀßeÕhråíÆS¯¸QÃ#QשׂÆâ6ü\ñ”ûYLsi¦;¶ÜBM«(—Õ‚Ñ-–2Q¾6!rÜg׿åûbÞß.vqývH1ª`,!¯QöÌËѸ‚ f>%.bÔkÎÎ=Q··U>uû퀺ýaˆºÝýöÕí¾zøJ¤mϽ»÷Ê„¯j\@ºBp5"ž©ˆw•î »õص°Áu:\ˆŽ…'àŽ# “äiÓßÌm£ŽÏ¨úfÏÙ¦*îÞÒï—’hwì«óò;ç%[Eúê…µœx]õ«kH+W­Æl"úlÛ°mO=ã®N:…ÛeDÖ=ë&X”¨©:®WE]y¥îwq]1ÁêÈ;ê‡X&„ !0SØ—ñ# ñçL¼U)ÇAÖ$›/Ÿ3ádgMø(«Ä-6’Jî¬éåpÂϨÆMqÈt(˜xšËéGQÔL¼e¹ó1Ól”¼Í8ïLÈùÅA>¬ãJƒ¼ñ,»s¹7xžó žç¢~ÁƒlÌøí'xF'µøB1"ÏS8Ÿð¼&h[>F=´ÅžÌ+Ü›PW¼VÝîVÓ~ïÌ$ñ ³!3æ²'O› üšT覿¦œO½Á36ȶI¦Y.¢<|3ñ·h"„âÁ}Ï3gGŒÞë~EiˆªÅWþ¯IsÈ-y{lCåh„Æ!ãfMÕívÔf‡É24VÜ»}pù-ÜÇaÁDoáD!$nß(;eÖN]zǶÚuØÇü„¼%uQ6‹LòNX2Á'ËæuFn?+ã_0мoÜþÅ„B!„BR4?f·„¹ “ˆB!„B!„B!„BùªØ}hJ1¯µ×E­eç{ë `—Œ¯¤¨0æ\ŸaOâû´z‚ô!dRåü=P7ÃÓaë‚LŒ4á7¦„B!ï»÷Ͻ ßÃM‹A»rZÔòÐ5ìèœÝׯîwMkK'æµ-a» ûvit3}H¼2ÄÈ“—ó÷‚Þ»- Q{Ê4¹eÑ „By,A,>ÅD &Ø,7Ž`ÔÌÇl0&mHw^A̽'Á¸b^nÚ.qç&a¯šÑƶU·×XvIùc Æ7Œ•9”Ï㈼Žzn'‰Ýªƒ+3B!d(®Ðð‰®CÓ?]î¢oHÁXÆñi!>v!X­³£)OC:…ð®!lí&ªnÊšÝðçðûP â+\snúWìrK…Ãù}¾šm$ïÁ¯ØQá8N×I•Å Æqø›1£m<Þ|¥g#l#õʪ+Wx.dÆ2ž—„”*ó¸o/B0fpï ¹B-ò»Š²y7 ]:¦T·-ží äéìºPåw^”ûm„Uó<Ãwê¶þoÁß[”'—<©°æÄ3lÿßifŸ±U§tð܉¸¼%ÍwR~õsÛ4„B!#àŒkÆÿ­b\ÁXn Ñ+%ØìTÕÜ© ¦¬JÁØ@C±€Æè*Ð÷Y×ÍÍpk&˜Î6‡†d÷-ã¾¼ø[Fƒw5B0^£áåÂÜá<@Œ:ûîBÄç*â3k~l‚Ü6/÷.Ì¡¡mϵ`ß8ã*l߯ÿÒÿ¬ FAÚJ8TpìØKfÏјn†”«ÊÜ6ÂY ‰{X¼pïDFZ ú:ÊÉÒW‹Ö†H—éÁ¸Šò˜ƒÍëÈGi”Gš=ŠtjCØd‘G7‚ѦºpZ(ƒ.¿CpfQÆŸMøæzdO>ïû°ir l*á™™7]!W÷ Ÿ©gø;ÒkAÙQƹœÀÏø-§¤:?–a›{öSÈß;äu 6>x.æ‘ÿÛêYŸÇ}%q~C•!Y>w"ÒzR‚qU<ë*?3H÷ÜÊYS8ÖÏß"_y„B‡` #®`¼…{B£y[×ÀùŽF^®Žë´`Ì›`Á™4ŸÝÛ¥`<4/G1:hl983^·ª‘eï»Çÿ¶Á¼+âQDCv!į4€Öß¿}‘NY4à³cŒ *Î&˜ªæÂ.ˆß;ªaZ4£à„ùQW¶mÿ4º°x—UêühH—Õùu&' ¶O>ò"M2°»«ÄÙTHù|4ýÓ9£¦¤E^dPFnŹ®é5¼ŒÈ›A‚qO•í[‘'J4¹8dñ ÏŠr¿¨žáë;Î…h“S€µ`¼VÂÈù1‡<•D”†êœ©!~²\í‘8…ߎm‘¯®ŒT^I0Î+ÛWE9J©çÖ€ëç#Œ„BñŠ6ç5ò'!eûÚôO-*Q)O0îC Ù‘³˜‚Ñ'i»þk`¬yìwáõÆ0q¦ÏÕ"c 6<@{cÜgx`l*›nÅ9nnjl’gØg‡í4¹ÀÿW¢ƒ¥Óß¹fDù8Te»¦ê¤¦§cÆ–%7zºóYž„`, èDÉš`êoâUÆËŠé#!„B¢H›þ¯AߌMR0ZlÏü³>9O#6c‚^qÙ9RW0ÊoÓRQß0n™—‹QåTyh‰¸<õNJ\?m‚©ä“Œ›*ì´ð'òÜæÔÿ[|ÍB!dÍË)”çÆ?­r[4d}TŒµül AàVfÔ«3ÖM0]¬j‚)Ÿ7ß„ˆ²©ïhÐU†lœ¹{õw…zÕÔ¨x›`Z¬m|)±…ãnÛ‘å ÆEÜÓò4:ëhºEX¤˜2Á´;·øÌ¦ŸMÜçF[VTØm[Cšå•PÚÅùuz½±üD£[¤³ŒÍyl[ްmOÙ¶©âÝB¦ˆëH×M”-7*¼ŠßnÔeþL‹²¸ë6áŽÌˉ ü|åq âNvDBž­ „ßÊҞ韩Ë+»×&X5ÿoc<ÃR„=!Ìs¤=¤ÜëghEØq Á\¢ªã6!iã:—¦U¼ÏcúQ6ÁTÝS¸0A–ecñ–ÑÞ7ƒc[æåˆ£ë„X[¦õÛ¦§|DGï|:æ³ÓÏÝ*ÊMQåÙžz.çBêí5„`´…ô.L0nÃ9ì(áJÌJÙטH¡q$MæÇÈã3¸ùÁhmû†c÷¢±Z‡}„}z„ÑŽ ]ôÜwórï·CøãÎwLøT-7Jê®=S –*Ätv·Øw¢ó7e“õßܬ#.ϯ¤*Ê3Ør«ü°y¶ ¿ºø[öÄ©€üxifÿ¶`×3ìuûÓ­!®zµéTø!·K°£){ã;Ò§*Î/à›>»ð³&Î]‹ô\É—â{‡koLÿtkëÿ2λpRʾ'ï0Á˜Á½÷ž<~¯ »…KÍLfZ÷g¦Qv\]¶fúGèR¸gWÔ§¾ç&ØòÉ=W¯<©z¯wŽºíev%D0ºrý·küS=+¢®8u|[ÔQGâÞ5œ»K¡^;G]p£ÊX÷?âü¹ª³–E]ÑT‚±ÿ\3‘OHW·åE}z*ÒôTœ[Cº‰z.êÙ_BÝ¥ã¡ãx!:f(ÇÇþ÷5 ·¼úh4b øê#ͦ‰·RíŒQçæEÝxÿQß®…øsˆgÿuxu–¬[<í¿k¢ón ÎÕK®lˆtÜÀñmÜ¿œP0ʰu¼×Qÿ‰çJÖ‹9qÜ×ùš†Ÿ-Qo˺ÅÕ7®Î-'¬÷\½ÕFžo ½f”Mós°Ë½kä§kjP`Gý–å-¬¼D‰,÷þåÉ(Û¶DºL«Nø}qÏ’x¸ßç¦ÿÓ§0ñ§óD–׃qÙCX9äõhÿÕP?lâܼ‰ž¡G¿‹wѺ¨[\ûjS´¯n†^udIäëHGy®*ÞG²Íçf=‹¸ºß®~=Hð¾ ŸL0º릦Æù†1‰`¼Âuwx(¶Mÿôo¨€\#§Œûʪá”`Zôvׯum!Ð:ª‘·¯}U‘fN ᜋxñPmyì«Q¸!„¨{)º‡ï ¬ôÓ‰¨:üçvE¼´­Q Ÿ`\Ry½/þ¿P/ÂGeÇ–hDç@N‰¬Mór´åA ƤWÔ‚A9Q¦²H›®*‡ò%tb‚ïIïUch1¢üçÄ ‡xÔ”émõÒ^/>'nÒÂî}ñûDtb\àø‚xºÆXZ¤ónLÁèÂÊŠçi×ô—S3ñF}iI ±YÕ+Ú@Ú¤„øÌƬ·ª¦ÿ[àŠG4#-Õ XTñÔéÕPy¾'K®§5Ží²N’ÓR÷PçLJ0fUyÜS~dP/ωûæU‡Ë Á8§ÒZv.©rq£êŠ=aSIØ›9®»«êÞïB0>#o§ÔgBк<ur!ŠÃˆz¯ñìk[Ó¢ã«Ǹ‚Q?Okh0kNñ®saE—¶H§²AØP#s&þÔó¬ª×R¨ËŠ!¶O«÷Ô%ò¶.ÞrTèX‰Ä9Ó?£%J0ÖTÝQ4/§#Æa¬ÿˆÖ®¸×Íz™QùQç“L…\Wa®«gKÛ$§UÇ—³­‘^MUÞÖ¤[ ÆŒMOe(_ÆOƒ1J0.‡ÄqßÓ¥ÛöØgi„å nºÖ¬xH<~Öñâ{öœ; /©`¬EÆCu¯ÏŽ3œŸAœžÐƒ&Ê—ïû« vÅS]”ÈÈi^·(ÇZ0Cµú\-¢ü—E¹»A¼¢㦧º(^øú»‹Š¨¤÷=/oÙhzî_õó Æe¼tkÂÕUCnÁØp,J” bËSvb Æ´ n?¦m«¢qRi´’P0® á›2Á´îIF-¤×<õž»çÖãò1c-B0êrUgUD]ñ ÿw„ÐkzÒD ‘3zº•¾'¬\/!Ü'4 /U½×‰)£¾WŠc\Áè{¾csqÑ#D¢ÑÞ©ûâ°h^Žâ…€lyîÙ":¬® {Öy9&÷=ϾîÔV0–UG„l³Äeƒhˆc”`œÇ»HÆ{NòA¶ùÒmÇÄÿn°aÛ‚ÃÒ¶¦çÝÖö¤qÁxq.Îôo߈ჰû6¢Î$Ãê–Æ€:S3o‚)ÿwBè»Ooîaó±G0Ö"lw¿“¾/È ­z$21_Þ /LB0ºBký>P±ÞÞcFÄAŽ~S•TÜFÝûÚ2ÁÈVRÁØRñq•HÓÓëS/a݈Ø3Á´¦z'·ÑH ñ´’6‹Hýb.¼‚`”/—Œ–: ¢b½Fš¥EƒâV4þÔ½®W.-zÉÜ'㟾x²"Ýã ÆGÓÿ½Ó|Dùïà^90J0® “iOyi$Œù!£OøÔ<ÂyXÁ¸"ôÞZ0fPVt¼+1m[‡¨ˆJ·8‚1‡²¼ ê¡A‚ñ~Áø]•1ßc÷L©zm:f]‘D0®˜—=ù%”ãžÅU‘¿«"¬]•Ï)¤aQÙ›Aó=$çªNÍ›`†‹›rjD˜ÃÆ]ór´ß‰´G÷´H“I Ææ‚±5BÛcÍDoײå9&ë­×Œ5Ó? ?¬`”}ayõV‚±îe5%”£lÛ‹‘nà F×Qe›»nÏø?ÇãEŒûŸÕ»"#êÎI ƺ§ã¯RF3¢w[,9ûš¨{ ¢þF0&}_O‚OðÕEï£jú‡áGŒ²‘='*ûKñ²ZÆK5£œ^ö²1Ñý|„,ï+áA¯‰ßB¤&Œwâ¡“ßãM«pŠ*œ]e×ÈŸ3ÁH©ROJL¯™þeòë#o‚ÕfÝÔ¶,äæ‚ц}#*¡$‚1ƒxl;.ÅK\Ûx!Ê×4λé%Qfrˆë¬hØ=†TÀg"¼^,]Ñ(ŠŒmäû¦è,B0ÊôM‹^:Q^Rª‘;/â¾êy¦Š ãŽð?É”Ô|HÃ-¯@ËC Æ–ò+§z£ƪé=šö¼P[J„ï«Æe6"Þ Õà•ß)–<ñM‰ûK"[ Œ3ˆÀEO}ê¦Ízž ]gµM°P˜Œ]Q^‹&üÆSÓÿñ®¨×|åéRÔII£®³r¨wÖLÿT'wí• שáù/ ãâêêø)×gãsY‘¿g¨ƒä7=î›Ïa£«Û‹âv'â8¯âx‘P0êiy+Æ?%5J0ÊÙz1ß" 1ŸÏ)órЍÜ~g]56õÔÌA‚QOIÕS\£ã’yù-fVÅusHÁ˜òÔ÷5eë(‚QOI]3/§¤Î*^qô í‚ÊsùN?VÏüì€tV0ƱmYÔ“uÏ{sÑD/reD=ç¹)o„Ñ}»ç[aÁ¸$„]XÝ’E½·®ÚW¾NiUï•M0m׳¾dý™T0&}_OÂZH¯ä¾xI»êv‚ûõCáûyHJ8·²Ôµ¨rµÀ ¥›¢ÙF…¹,^&X¬E/Üsg‚Õ7TÏl]‰æ°xm㜛*z¡^.K"œGóò;€G‘¶iÄuETzÞ¸›Òò(ü]Pï5âäV«J [×bÆË¥—‘8Wù&?Š_󔇊²ãP¼LÜ÷±·h­¢‘˜iö€¸"+âÞ‘ÞÍq?nL°δ(‡•kâåx$ÒxW•Ýhrö¸¼»1áSs¦!^×LðÝPY½HÝ4›Ѭ¢rŸ¤2ÒeW46J&X bS½ÀÝJƸ¦©^ssUˆÏUöv…ír¡„ ޹m;šê™r«ÉmÂíÛ¦„M®Ü„ب›[ôbÅsï^°Û°ëÌô¯RéÒcÍóœQºU1·•ÿó"ݶðÿ´xÆnnÛÜó“Òÿü÷Ž’)3ø»Â¨ú<; ¿ã¤Û¨ïÉì÷ª“Sæå'0F kB!äÓ`_ªn%¹ÜN×€iîFÁøµ° \;Ú[†pˆ»5Mî×aûWÞ÷-#ê=.4’Œ%Jís4Ëd!„òY_z ¸ê':a.íi47„c/q§B“Éðiɉr_Lp_EÜW™ðó9n†ŒóGÿQéêË—o-v²vSÌB!dìLðÝ‘ÏU™D„¼ÅÏg…I4ÕéZxǶ/Eؽɬ%„B!„B!„B!„BÈx±ó×ë ®wß?¸}i!„B!„|Rj&zŸ*‰ÛÈRHp!„B!„O.íF¤\ÑB!„B^ ;µó°çž{îÑüØœÔm¸jW3»è¹ï=wg~Œð9¶{®Õs׿Ç>^'=7­~§ÅµÖßËž»ï¹sóc_(Ÿ`œë¹oóÆûFÙi«O°ÑÚ[ˆ¸Ï—ÓUíõëÂ6§Ò€ô¸Gø-üvéq®®?7Áªovzíì|RiYþý6=Î=·Á¢I!„Byk¬ˆ9†¸ËBÔm@üXѳ„ë¦ dÜ÷†û<%Üw AV¿ŵðÃb§•^yc ‚i¿g`ÔðÇ0M°á´»oAÜ÷(üéÀ¶ây¿|ì ±›…qkð»†ÿ­¿âÞˆeÛ÷IûÓðg³±Êo4 !„B!oÊ3–2V°¬@CK­ì{ë3èL+wF˜9ûâq„¨uöýܵq%nZyô(ä0梜›çw÷í}•чOÙ.‚íI9Áí¸O+–V]†¹>û_OÂå"ƒtÔËœ»Z%õ6Ûö‡ûÜÉ1_²ýéäú÷3$n²íªUfþ¬m~âg«‘Œü„xÌô`K¯}Ö¼øw^ÙI›f³·Â’IEND®B`‚grpc-1.3.2/doc/images/old_epoll_impl.png000066400000000000000000001304361310511640000201600ustar00rootroot00000000000000‰PNG  IHDR†‘9?­€IDATxÚì½|dYYç}º»¦'3S3f† 4hd£DŒÖb%@”†OÀðÝQ²– qÍ®Y6¯oxßàæ]¢F6hÀÞµe[7ìÛÐ=C¯d±—m¥q£´ Ñl¤‘{°…꽿ÔsºNÜ[u«êÞºÿ~ßÏç|R©{ëÖ­sÎ=çüÎóœç(E!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„’|&ÔiüÎI=)úÿ²õ{ùtÿ÷Hùðÿèþ?aü?ÄÿCÿ] q(8©ËøÙIãÆÿ«N:àÿ'¤þñÿèþ7Ç!gœÔkü?褎ÔËÚcŸÍIj”¼“¦<ž‘±3Ê¥Óv¢Ó¨}l6I»˜NJ³è¤në¡É1›!¤aÌÁ^·5XœvÒ³(3ä­~ö˜%óÌ¢ÌÐcµ ÛÖ¸«+¢ûÚsRÉh§zäÿé:ŸÃù»MŠÛi‘0q|\^/ÊdÉñóœL¤Ä L"ÎÊkäÇ0Ò®jÆIýÌBi+9k08ÅÎ?µ Ÿ]f6Ÿã³Kªýò"‘¶ä½qù_[ {¥7D Þ;/÷¬­Z}rÞˆuýbÑ{MU[RWE¸¡]få[·œ3n‰Ö‚Ü_Ïc†ÀRÞÖ9ý=æ½tÊý Èwå]¾Äz¯ ¿iPîwT¾·`ä߆9U±höJþ ÉuÍßT4Þò¸mî¶D}Nò®ÈÇ/›Ì²ƒ"„ØQ´E$Ùƒû k€fèWí™0ˆå7Eð¬È뜴[Nºè¤ëªl]Ä9›ò9¼·hœ§¯³&×?f‰L›¹†ÉY'í¨²Ål[U,{»òÿ†Ü7îeAŽŸ‘s†å^ñþº¼V"Âðùy'rÒùîY¹æŒœk»°ö‰ø]1ô9É­Ë’Wk"’õ÷ïI~lɽ*É£³"H'ä:›rÞ%ùܤäÝ’ÜÛ%ù,î÷¤¼Ò¸æqù^~ÿ%ëÞsòþ¦ü¾KR¯r"ÆËg÷$H0g:˜„k:dpÂö:¹å·FAH hM2„Å‚·Aù;+Â¥WÄÞ¦œ; çh³’ˆ™‚œ7/çÍ‹ÀQr¬Xãû‰ð1¹!÷¦Dåå;ú ñhºe_1oÑ¡ò™œˆ8ma¤ä·-Ë9ƒªÚʧ¿gÜúHžóãýˆ˜4Þ¿"·Ue­y—uïë’§ò;”|çIy}͸/¼Bþî×XRÝog­÷fä»ð=WUe-ãF›ê‰AuAU”!„oº™‰+/ˆ a–E‚eW^ChÀzt]„Ï”ˆ¿~£®—DàLÇôyWE ]“ÿý°ªª½Ùp½‹Æÿk"h† Ù)‚oÇH{"ÌDÔž”¿»"Ô.×4¯Õ-ypU ÀÓ©Z3ÏÈçÏ©êåX€c"jÍûÒV¼«ªân: óŒÜçu¹¦nJDçœkÓ¸,Â[[5ÚjkrJU[@gDÎߣ$¸´ŒB‰9+Š.>qgBU‚E°…áIpEU,‚ª²ÞpR„„é:¯*AjÖE™Ÿ!3®¼×»Ùع)K´œ—ïŸW‹d·-þΕ9ã~!„ŠªÚº¶,Bª¨*ÖÌ>hvÆ+–P¼&o¨êµ—ä7Ÿ7ÎÁ×cˆo%"µh\ó†”í¦!NϪÊËã.ÂÔ†9¹¾íz¼£ª­µÛRVæ÷t¸ˆ_’"úTÅôL!$Ù£VBÂA[g ‘ ­}½r¢á²Ó[†H5ꦈ¬NjçDˆÝ§]Ok¹)B™i § Ás]þbl;b‰«y„zm`Ÿ¹A>¸§9CÐéIœrþˆª¬ï‘ßi··äƒòû´Ëçu¹×ƒc’—å·O¨Š[é1C|kÁ¦¯yRU¶óÚ‘ß”—ûÅ_ˆG£ß“ëOecßû¼ˆA|Ï’ª¬¼¨*ëÚ‡D„’Cs0!„¤tä=̆X0#ƒ?BÚM‡ˆ – D0Œ÷Ž©êítô9ö:´~UYgž‡÷ŠÆ9KÊÛ=¿ÁÞãÕŒÒÙ©*Öøë7CLÂê·¦ª×ôË=Lªj‹à œ{L¾C_kDÞ_Vî.áú׌kM×ZSÕ–º‚\kŸ^QU[P{ä¸Îûyã^t~i18iˆ¸¼%‡åÜÇ®GOb[[œÍòPáïI"šõ!„’^¦TõšmŸË~—D£Gˆ:¸±Ýì‰F;t\ÑX ijB!„P¥²ñ=À Ò³ª²ï!!„B2\‡èVÚ^à vœÙ@b\5Ï0! nÛP rÞ”KÊKãu\ùR6˜]Ykà|ø‰/²®É”GðƒßŽÑ½¢,W}ž[”ß·øçäÿ9‰Å-¢ À, 1ƒ.Í„}¶c$´”ª,ÌÅâä-y½bt¤Sªö&§íf©s!lºüLÖÐe>'©(ï5“ßíº_?èYüžœÔg¸n²È !„ßÀÓ¡Þ–]Ƹ+Ík)Ç=Æ£êà¶Qҩ覚:bv?zà_0^OY‘}iÝ¥â¨j ã¢õÐà}Xú°èwÆå÷C$/ȵÝ", ˆxÕŸ–ZøÄ;oŠÆÀ’u\‹ëU—_G ÓeiûðwË{ëê`èëœÔŸe)ã!Æv]Dk¾ahŠHÜæª­MHÔý@‘Ù*ÌcsrÒ¯Æy¯·`¨ÅŠÑ¿¯¨tGÙÇ–öörð¹%c¸”Ù/Ò,ý.°WUöUÁ ––i¼V¬—ˆÆ%I"tå<®*®S2@7Á1Uq¯QÕ®~ZvÈ÷¬«ê=e( ƒ+Sö[y·.e¤7r5Å}4’‹R~(óq£Nm¨ŠĘ̈ªvÍKywxÔ­yCt仆}ò9î)GâDŸjÌ-ž4ΰ¢Û.‰?S-ôOÝ"ÈÌqS‡Œ&TõÒ¥aù_o£“óFþx@úó³øÜYCÈŽXÇõ&ñæÍ ¼oŽ)äGd¬POëû,Êwš[I˜ùÐgüþqUmåÄ_sâ¹ ª·Ö˜ï¨w/øØKÐÞbÞI—•»qCçAÑjÿ»ä>{äþŽ)oˬþÝݪz e¼7büÖ¹O¶1&')Î>åe¯Ë*ªƒ³°z-—ͬKÅ,ZO‡4$EUY僧דáÜfÖ¼QÖÇ­\uÞ嬲.¸07Še—oÆjÔ:ïž4î¡Ã¥ü{†§Dl.(î]F!$= ‰ ›a²,bcW^ÏËñ.4×dºd¼^sÆD¤\‘>sM„˜“ëé}µÏE¹6Æy×åZý†hÚ”ñÚ´ªldöŒïÖÆ{ñà ¬Ëùúw^±Æ)‹2ƾ`ü^Æ/EhNªŠKèžäÕšñÅ´Ü»ùÝ£rí«ê WÒŠˆê9ù«-Š;’7òù=9¶¤Ü7­?&¿kSòíš!˜÷¤ ¶$uÉõÏ*ÆTˆ=q/ Z°èC¯Ñ§"¢¬ã8_Oæž1„Ó†ŒwÏ[â çtÊwë1À¼ªí~¹h}ç®Ü똪vç<%ß¹iNJÍ‹ Ô\’ßÁ÷ì©Ú"µ(F^j«ëEù}—<„¤.×qU1lÜP•%W'­qïY—±Êª5ö¹.×½¢ª'Úµ8ÕÂ—Ø ÃaU{3QÛ·~Èz@Ö¬ã=ª¹£†ÑÃYU;ØË²õ¿½&hÃå›Yc¨Te-!q¢OÅ+òo˜qi[‰3ƒÊÝRT‹«.ï]RÕÛᬂqÆ—™{h_1qÖê¯wEtèkž—÷v$áõ1Kt­‹ZWÕ·¨ŠëŒ%Üj ˜ –HÚ•{]¶ð5t7D´é{¼(ãJ-~•|y×-"uÇH{ªv,‚ ’r½ÉãIupÝ¡Ž‰p^Ž]TÈ)šoºÜ³- Ï©ŠWV¯1)pÞ¥Nt¹Ô3ºUüg/õZ¾mUíﮃv¬È{òzEUÜb§ä½Ì~Èç%åØšQÁ'T%æ¼æ\ò×Í C—±›õp@Žu×ÏYeXTÕA’:,{û÷B!I沌-'Dà _<.cN-Ît°83ª¨)äÆD$i!¨Ý@w亣ªâѰ,ŸÅñ†¸Ù±Õ%`"ÿ¼ŒÛfETvʵÆ\D©:àܨ\OßËYbòþqã·­çk+é5¹§iUYϧÅî¬ä‡v õã—]#ß®âX[M$Ÿ$ïnªJ@¾cÆy§ä¸¾çi—1Ò®%²u ¿Ër­¢qÿú5—ÎB! ¥GÑ’Eæ#I0D‘,¨J =YžѰ¦*–§.U½înÆ8HU¿éx¦WתXæpí)upë©1ãÌï1·šÒ“¹³Æë‚ª½ÔHɳ¼ *ÑѵU®WîsÒø úü99fM\S•(¬}FÞè­¸êm±1`º.—z{Ñ¥ÝÉ©JP›|Ý’‡ÝÖoœ·òݤ_U—Ìå<U±Lêûï<ãCB!$¡¬+î¹›Š®¹$™`@AE³ôhMU¯ l'd ­3*ü Ž÷Âõz$0ÆTü6´'„B!ÀbÕÑwoy¤añÚò½Œ{Ü ב@+<…!!„B!„B!¤&X+C7Èæ‡NÙ@ ,b}ÌB!„lƒ€Ã̆¦™å š$œ¢ªÞâ 褟YIHü@ô"ÎþB!„vPoÓxBHDdmö3TEìâ`ΞGCwÿ !„ý¸ Û ïaOC’9f¡:ä½ cœ6 *q0 Ƙï ªÊ×øl ÑÅ,'„ø Ìœj,äz·ª½ ç³5p&êG‡°l½Çˆ\„„O^Uo|LcžY@N‡%òj5µçDêÍÜ!Ün©ràÃ9‰¸¶[ÀÆîس{î]”ï:e|ß®|NÉgÑï#èYãõ‹ˆÖèQ• w!‚: A¤­0ýò{×ä/ÄÒ°:¸ŸM—\¯WùßÄ·C®Õ¯FHí“ëuçvËûy=(Ç:åÿ¼q6EaØ-ï÷¸Üׄªìcâöž¯æìU§ªìA3¬üGƒÍIÃ8h”A‡ªÞGÇ,/e”[Ñ*³Œ;]î¿Ç%ê g=sç& Ýî¡Ó¨GyëwôHã^0~§Í¬QæšqE×B¦Kq¦–˜$á ÿ>áóÜU‰|¯-„c"õØq[•7t‡{é´ñÙrþ¦üxF>{IÆçTeÓú~„&y‡yÔxSÝó¶ÔA+TÑ ""”‹ÐðqóªÚê¨ET¯:èR¸dˆe‡‚!6¬ÏÌY›0\5®SPÕ· ª¶ëé”KCh» ™ù:ëò{j<è±òtʸ·)—ëõÉï6Ó’Ç÷š¯×jäC-a?ær½iÌÍë-çé{\Q-ËõòeÛãýS|¤ !1æ³€dŒ´vÕ“ã#Æû—äuÉ vˆ`ì‘1&ŸÏÈ1¸˜^P•e>¬1Ì4³žæù ëÿEt[Xubg®‰{ðZ£7ì"È–,1æ& ׬Ï̪ê`3nÂpÓxß>Þ¨0ìvi˜æ<Î÷# íÅÔ}>„á ä«ù{|ÃõùPK]®§­Ç^÷ ­ÏËê ;r½|ñ\ä#MHèp!!ÙÆåc•«ªìI4$ã…kƘlÜè·OÉxã—mU™˜Æçobò¦1Λ–q‹æ‚òg „xð^U¶ötÈ ~Ù§0Ü’‡¾K>Ócˆ¼nKå|s½Ø˜\O»Pæ ¡1åC1˜—Ï,Ö¶ZŒÿïí±B=u„¡’<Éã| °Sò¡[¾û„qnC”TÅ•2'Ÿé0þr™ÀµÏYïw[yÕ¬0t»‡aKêu­¶8\¶®os\¹¯måÚ'B‡Ï!ÙÆ¯å[/#YU•è¢æxÈ4äe<³.bÐs™„9cœ2jm Ђ«Ç9y­×°MYbnžãê 5+'Ÿ™—Ô煉rþ¼%2ºkMBAo³¡×%jwÖœ-G­ká½IS†ÈËÉ{úF­û›–÷çFH»tÎy”78}þŒ!bFåü‚œ3§ümwÑ)¿BU[ Í{Ók û ¡4o¤>K|ÏË÷÷“û[Pþ7²ž6~c¯\³×¸‡ãÌu„::Y¯|çˆqÍ!ùÜœrPêhfVq¦o¸ÆBH"Ð"¬Eå‰3¤=ê[A¹[)³†]Μ)$„Ä®1$„[ôF¢:êS=·OíÖW¿ÑþÜÓšüžŽ–×äýªâ†î„èú BHv¡å›”ÒŽµ"Ú…Ó-õ²ö)zäO`y–!¤Íý!$¾ÐòM!„BH ÐÒB!„B!‡–B!±…kE!„°ß „ø…–oBR ׊Ba¿Añ -ß„B!„´--„B!$³Œ«rÛῃV¬Æé’²!í#n––U‰2Ýb=›fÑ7¶›“vm€Ùãù‹áûFB‚kE!aÓ-ìV“Ÿ_Hà€;î`Љý^7Ùodšœ<›ØÏ¸Øä5f|<ÿ Ìê†Ä:žË)Ÿ… ‡¬X¾óò|¬5ùùAIµUñÜ<ŽŒ9é‚õ< }¹è¤YfO0p–l 8zjï”äF—ÇkûœŽ×ßjò»·øí…:Ç{Z¸¶À5;0oå»»jä›–ØoĆÎ:eY«žuÏx¾‰g XGv×x¶—ZüÝ5ÚýŒt·ð|u‡X&a´ (§~뽕˜ÕÕ(&âjÕÁZíhÎ(ÃNòè¨SO–|”Y3Ï•ß:˜¯#^›­£ùëww>?Œ¾oÙIëÆÿóNÚ`÷A!1/ú%iD7­Æ}CÜituG´.ƒ€ù̦\gF:„%9f~~Å£óÝòèXÖÏm´¾þ®ü]ré ‡ä½mß=.×׿Ûtœ’÷ôqÜ_oy:,Ÿ_’k,Ê}å{Ìß;ãr°¬÷6lýî9cбd ²Ze¶0$Í3ä18[“²\–r]ð¨g8O»eöJÚº±.iS„E¿›—÷ÜžzØa©Çºþ™÷Õ'ïïÏæ¤õùIçV õs¯Ÿ¿>ãØ0ê¶¾÷FDÖŒÑæmÊó¹ª*Ì%càm[Ïu™¬H™lí’ÎW]–£Öÿú½M£ÌZ±˜mAé3ê¿î‡Ì:<íÑŽŽ8é¤Ño­I:.õkLžŸYãó›FôÓNN×è_ƤNoÏ€mùÕuò˜GßèÕÆ÷ɽëϯÈsÞˆ(3Ûœuãùî¶îi@þŸ³ÊdÓhÌ>Ìêëêõ}›RVôYsÒ/æŒgœBˆO&ÔAWs†mÕ=Òáèã”Ñ ë¾eãüKÖç‹ÊݽÌM®«ê™Ú¼:h‘òc1tëúßažgŠ¿³F‡¦ª~èPg)ç¬ûXªqÒš¬Yù¸T#6¬s»­2¡0Œ'n––—g`Í-ëÖùSFÝ1ŸÉMUq ]0žE»ž.«ƒ7a˜wùlÑEü-5YÏfTõú¹œõ}EëùuyfjMÚLY×>kýîZÏ×j2qË/óÿn—2;¦šsì“kå2ú¼äÔAww³ÕÁõ«(§.£ÌYuyʨKқ߷å³þ¹ôs‹Vóšp1)(÷5Œöd_¯õ<ØBsYù·þÍ[uö|{*y3Ú³¯õÙ÷¹´!«ª¶×€}­Nù½(»AöcÁµ"þVá.@&,ÿ°¨çú·ì1Xµ;6/ѳâóšnîEU™UÕéb@ÂpÁ¥£ìUÕ3ŸKM ¥!—ö³Ð€0ÜtùÝg¬Ác­«[¾m“0d¿,ë5ŽÁ1Rãùt«of=t˜ö¹ ÌÜÎÃÿ;.õl3 a¸ì!{jˆ¯©êµ-¦¦†çë´Kµ„á„<Ëöç×S$ ÛµÆpPÕ\´æ’?†Øs{>lah3«º8.yÔ±Vo[u´aX¯_uë_ >óu¹Î{µ„á€Çóq²Å¾ïX϶¾ßú1Ò䀑TB—#G±ü“ÉJÁÅZ‹Âð”õÙN†z«ÁAq«ÂpÖ¥£°ÅÍ C·€# C?³»µ®kÕ ®1ŒžZe9¬º~vƒ8?ÂжjL¸´enØ~U?°L+ÂÐmà ‹HWÂpZ ú±Ú€0¬÷|Õ†Å&Oân)l×Ã>U;¨È’K;Švx´aØëRO:|ö/} Ö“V…áZ@ÂpÅå7žô) »ÔAOœzÏ»]]-Ô }­UY‹KaHÚ W}4„åW†¬†3§ª]ЬÎkÂèüÃóF‹ÁئGÃï&ð¦ÔAWÛša»­ ùxvÊgu˜—ÿ;†:ßô C¯gñ¨?»VG»nuÎÃÖ ÅÌ[ù· ª-I.ù–0$­=‹6óÖó×m ¼rÖó¤×Ôô6 ÏÈ3†÷ÇÓe<ëöçëµáãò{,A 'bVåûÇ\Ú–1£ÝÑÏ ²&~Ì6iÚ„Z0òÅ.ÓZŒ»ä[–÷Ì«J”ei§sVÿ°b”E—Q~[F×ÏİÑÞi—ãcò|¸EƒµËbÄüºŽ¬H]ëpy¶—:ž7ê¾}m[àÌíû„õÜl©ŠU±Çãóµè”gbF~‡ýÙiùn³ÿé1ž­Y£]°×-wYÏõ„5 T°ÊlJù³ŽOÈ}˜“:sòÞ¢"Àµ"îàÁÆìÿÕ\¤?ÂòÏœ­«tvYÈ öÉš*2nO¤˜  &û.æ±àZ‘ƒ@œacv°üIMm†«ïÌp^`&sMò"íqöÉÖm‰˜Éx^è­dðŒÒ¨uN¤à7Œ}W–7˜ï1úñVmBªÉ‰  (`ù³ü³ ܹ¦<ÒdŒï»£Æ}#°h#eˆYzs°B{ïeñ’ ×±¡:÷N.Òvàó|†¢€åϬÈ<ÝÒÁº¥ž ¼R‹6RN0 2]Ç;êÜ;¾$Ëu¬«Î½slÖ¸V¤f*®pàÄògVÂ~ƒR³¿$„¤®©KÑ4³åOa¿Añ„–oBH깩âï"FXþ„äBK !„’n©ƒûÏ–?I?çt9fé$‹%•œà3ÆgŒ°þ³î“¸Âµ"Êz–ÙÀò'™ãòé½ß.Å)Ý}Ï]רo´¿/=nϘ IsÐòÝ÷?pß8Õýÿ¸›,â׊T@ß+ô°ü™††ì7…!ñ„k ) É}"°mÃâ²ü …!…! ’LZZ( …!…!!IÛ Båy „åO( ) IdÒÒBaH( ) I2 Ûœ73NÂàlIÑzÄò'††ì7…!\cHaHR ׊ÔÛœrÒ®“˜,BaHaÈ~ƒPf®1¤0$$ÓL©²õˆQ+Yþ„®¤¤Y¸ÆÂPR’°Þ좓֘,BaHaHš€k ) …!…!‰-\+Ò`ÿæ¤sªµ’°ü …!×ÖôN:iÎIòܹ=‹‹N*6xm¸„²ÊSR¶×R’”µ"Ó)Ê0³‚åO( ¹Æ0pÖäù*8iÐC*9g©ëbBgš;††-Ã5††„ƒ6Œ,f…!]ICa¹Æ±œÆù»ÔÄõ—"üm\cHaH( ) I=ìTXþÌ C Ã@›ç–*GÞ’4b‡…pCU¬~ó!C¸¯ö†ø¹Æ0]ÂB*&ÙÜ!÷ÂÚ††¤i¸Æ°9ÆtÙÀò'†\c8nÂ-/¢Ð>/hao€='uñ± 0vd’âŒ{¼>)ǺŒ×Q“S¹Wœ´- ¿iM&Fü bBaHR×6Çq'-0Xþ„Âk Û" 1ൃÆôªp\IaD©>†F}™1eס-cò"ßduÔ™Œ¨wínCì5òLUu§¢LŽÔƒK)( !ÆåJ aù Cº’6&ÜúU9R©ý,†µÆß0,A\c˜±Þp–…aaXoâÁ+Òîq—zyÊ]ªb1ÔÇô= º<‹ºWUÅ⩟)¿Ï*¡0$)„k ý9¸ѯžåO( ¹Æ0;`×ñq>&†-C/±¶Vç;×d‚Âí0i2m߯Zw%õûB CB2/ Nªƒn „åO( éJê>ŸÐþËÌUŒ•„k ) ma¶h½7nˆAsVÄëࢪÏtˆ`k‡0$†„dZœ£(`ù3;( ) [z–°?át×îVÝñÌ„SeËa«{raò„a‡Ô#ˆ4¸tš®ÅÃ"Îf á¿fˆ=íÚ¹fÔG[ˆá+ÆwŒ[ ú{±o稼ÖLóªâfº"“kÊß:ÁU hÔsB( IÂáÃúø9Å”,BaHaØJ¿Áçvˆ¢³P#õürÃl CrŠH C’R¸ÆÐ›5Š–?˟°å~Coñ’AÅ=) ×R’AÁLQÀògùSR¶¨ d>–²Aq³{r!…!¡0¤0$$A`­ÀEËŸYAaHaØ2̱ž²úÒʇ\cHaH( ) IláÃjŠªìòÔì`ù C Öúc)ždᇆA1¡’­—k ) IJáà *}.O„åO( £è70¹‚-S\o Š{R¶-NÚtÒEUÞ0Ip!…!!©᥷˜ ,BaHaØ2gÔÁýÙÒH£{r!…!pÒ%†\¶@aHaHH ÙUt`ù C ÃV{åy•½?Ùãk ) ñ|àùž`ÓKaHaHâ×V¸¥¸‰9ËŸPR¶ÒoôÉ ·±:Ä=) ëþ^)»>'â 'Q) IJáà g×—±ü …!…a³ýFN½Ó­GÜãÂÐ3 œ´ã¤m•×Q®1¤0$$õŒHGÑǬ`ù C æ„ÑvÆëR½=¹Æ0{Â&g¤^Ð+…ÂÂ)¬eV°ü …!…¡o†åÙɺ+e½=¹Æ0{ÂpA•=R( ) ) I"¤šQà ïfv°ü …!…aÍ~#¯‚ÝêeTÓS5žÁ9ÕØ6”cà²*ÿsÎ=) M®ÉÄIšàC C’R¸ÆÐ£Se·¨ëò·“YÂò'††®ýj¬tmˆ)Dk,¨òÞn^°[Dž_p®ÞS±_žë0)(îqHaXæ¦Jß$#×R’IºeЃAÚ’â~C,BaHahëá^€ÏÆ’ÁÕéó\Ûb³Ù†¼qÛãk ³' W¤pý:…!…!!)¡¥OHã>Íì`ù C CÕ#ÏÄ`ÚAÄÚ®LÆ ÍZÏàqUv…›ébƒÂÐþ®õ6命Ç!×f3*)꬞`¤ …!…!‰-sÌ‚†’ËYEëËŸPf{áhAâ%öÖTõ6£"› ítíËü‡†·'7µKVU²ÝK¹ÆÂP!'ƒ” ŠøXþ„Â0›k aÍ;¯‚ââ% ÝÖ6ºN0 QhÞkf÷8¤0< 7D n¨dnvÏ5††„‹5~Âò'†qk¥p…®]ËbhÕˆ;hg„¢ÐLÿ…aæ…¡FP³´•PH( !ÆàhÙÀò'††°Â:¬µ¶^ÂpÞIEãV]Ä¢§.Qh®í(ï¾ 2 œÂ°î¤Å’ÄEÅý) ) I„Е´yT`›ÙÀò'††°’ÿa×-ÈàØL¶x›1ˆÔ+ý×Do;E%2·Ç!…¡/°4ëv±†=î.Ç\cHaH( ‰mÌšs*–?¡0ÌŠ0Ä–ˆ°ùˬ2-‹àLíqHaØÇ#œ¸ð ×RB„œ4ŠÇ™,Ba˜a˜—ô«KKhK‹Û‡†† ßI—ø¨PR’ QpR•£Ëq»–?¡0ÌŠ0DpŒõ˜–ŸÞÓÐ-MÄì^MK‹½Ç!…!…!Àö&œx¤0¤0$‘@WÒú6'’DQÀò'†Y†Ø·pϨ÷ÇbV~=ªìžé–â¾™x&ö8¤0ôMŸL ƼH¹ÆÂPf„•Æš2D¶KSÄ0ü–ŸuÒ_8éÓNz¶Ï`vV3D×û-Ÿ|æÝªuíDAi-BaèGt]µª«¬2’ú=) }‹BÜÓDŠ”k ) É,ª<ƒ·Âßw•¿qRIÒ×Tý0îŸ2ÎGú¼ïù¤õ™¿fù ÃDCDI\d Œ¡í“†™†CÒÏLó¡0¤0$$¾ jÜU•Þèqh¾n‰¶?¯ó™oXçÿƒïiæ3,Ba-ØRá¼¢•£Ê–BÑ7°ü …al…!¬XSëåÖ'«Öåm¨rxÿÔÅ‚JᇆÀºuXã“ÌŒk ) £¢(Ï Òš´ÿÖ2&]Ò1gÅR4(DžK€ŽÎé÷üf?Ãò'†Ñ€`(Û (·^°'4¸öciI݇†êú®Ý¥0¤0l LV^—¶”°¶ÃXÁ}?I¨ ’-1Xþ„Â0ƒÂpX­q ×QäÑLÂêš_KKªö8¤0¼^·>Æf—°aΪ²ÅPÉó;)¯aÜ`M º’º ÍÒ,Ba˜=a˜—ú_oÐ¥Õ?m®£µH͇†·Ÿ›´,QàC Ã(Ø•É2¬Ç3ÜmC.ý¡0 m`tC¥x?)Âò'†l©r0ŒzDµÆ0‰®£­’Š=) o»÷¥¤^r!…alH?…­}v¤]D\Œë·‘°< f–?¡0Ì’0„5c/Æ‚+©®£6CM¶I‰ÞãÂpßnB C Öš‡'e’bÑõ‚„ Ü“Ò4³GXþ„°=Rçã芃©ˆ<—×ÑMæA¢÷8¤0Üß3¸‡M-…!…!‰;´Œ¸£×ô3+Xþ„Â0åÂðŒj,Bb»ÖTy6R;‰›ÿ®²·8Ñ{R¡üºSR¹ÆÂ0 0I¯‘My¦ÌD( Û"0‹>Ŭ`ù Ô CóÒáú¥–+Do¼æÒG}ÖIã¤f°žTB÷8¤0Ü tJÄáh ê"×RFÁŠŒË°~ÉJ„´…é<0;‘gv°ü …aŠ„aŸˆ¯BŒÊB»Žâ¹ssmýº*G£ûlBëZ«––DîqHaxL4^ˆIN6¿††¾I‘5ŠDÞ§©²™ú²¢ûËŸP¦CB€!ÂçtŒÊ¡ ºŽÚ¼ËI_sÒrBëZ––ÄíqHaxàÙƒG \¸{“ƒ] C C_lóY º’úG»ŠaqYþ„Â0ÉÂpE:ÙfŸ… ñr%î$jC CO°æpAîE[“àÂIR Ã(QåÉà ˆf"†‘€Nø¤4àÜL“åO( “( ÚûJ ¢"È5†õ\GImqŸˆ=) }K0Ö!^Uñ_GÚŽ5†°ˆÿWi«^àó|x|ÁIïõÙ¾á3ðúk'k¢…Â00Vå¹uK„DŠÞSkQ5´°ü …a”Â0/èX òáûø¦–ëhÚÚÒ’ˆ=) ˆp1Ízà³O«òzb^^çü?QåmAôù§êúùc'}ÅøÌ Bp CB²5˜­=«âÎCXþ$ó³ãë1Ès ¾`YÈX] ÚÒ’ˆ=) ›‡3Þ.Ó†Ÿ¯sþ×­óaiÜkð3Ÿ÷ñ Ãhûõ¼ôeh÷¸¹}ÀЕ´õNyE¥k"Âò§0L§0<&u5ÀuZ}f®4Ù¡#èÌ_ª„îç±ßã°aà^½ãûkÇÿ·DÛÇëœÿ%ëüOªúÖtû3—Ux ÃÀ€ë/&ÏŠ0ÄDÛu•Ü`d†)ÏÇ=ÅÐÓ,BaOaØ#jëøV[¸X·±Y+;"’~U•ÝÌH…‚Šñ‡† ‰üãòœÄ9M;Öb½à_©²«çç|L|ÀâÏœôe)ÛëªþV<ø \P±.ñ3>?Cax6ì= õ¶K‘ر¥¸É&ËŸPÆSBŒ-F˜ÇA¹Žbs{¬úHBëZ˜––ØîqHaè‹IUÙ¼›ûæ–ó@ã9ÖÀù·TÙ¢ÔÛÀgn6ð Ãè¸à!Üw]JI Áfè{Ì–?¡0Œ™0ÄL;‚¼D(©U×Q7ùç*¹Lö´ÄrC ÚåùÜUÜ"•PÜ|g¬÷°Œý%c=]Iƒ³}Ç™ ,Ba#a¨Ýl æ—ß5†A¸Ž’Ɖ݇†žÏ&"ò^’þ#IPÀRFUïpïÚCKo_±ÉZFa7ÐÀc–v„YÁò'†1†°ÖÁ 1p~ùYc8"ÏÄ«W$ÄjC Ã*:äÂ3>¯°¥ 'øˆQFD¿*»[Ÿ•z8©¸m‰ƒ2:Ƭ`ù à Cˆƒí6ç%:è%N”xÒNKKlö8¤0¼MŸ|/,´¢SR’":d„…ÑcÌ–?¡0Œ‘0qÖÎÁ'Özœ•Äí[¼ÅZ;Ez,ö8¤0¼ýLâ;'øPRúfHž›UquK$ èJÚ€€u'gýXþ„Â0^Â0/eXnÖqí:º¤ÂuëÁ~UŸVÜÇÐ/±ØãÂpˆôñ”Ô+®1¤0lgVTåÉø>yí–…a$ Rž‘Žv”ÙÁò'†1†pS[1¿L T»]G±‡áMÅâF(¨ˆ÷8¤0ÜÔÞTéÙkk ) £`\¹R[Sœ¤'ÌX` ¥‹s¡+ËŸPÆIê: k¬ÙíØ- ×Ñë"¹acDºÇ!…á>˜@9¥¸G!…!…a£ÀýzJ•­î+òZ'DaÆÞ•=¬i¤3˜mÝàŒËŸÙAaSa8"c»ÿírµ•=÷1lœÈö8¤0¼=y³%ßËÀL††þ+üŽôo»òÚLˬeÁAWÒÚ`f³ïÃÌ –?¡0Œ±0Ä>NgD¨…ÍqŨ£I%’=) «—~ÚbBë×RF¶^êc¢0Œ Ì@ÀEŠn,BagaˆAþt^…k½ëñùYŨ£I¦í{R 'ã/-“”†k ) £zn0ù©c<à/‚ö²–‘vp“ƒ–?³Â0³¨ßtÒçôqΞšzû‹Å5¶­KK[÷8¤0¬9ÐÅú© "á2ÇÉH C Cw–äYÿ1FC0´=öK¤-ƒEE‹*ËŸPÆ_þ¡“¾î¤ªpÜlTym#ñ#Èâ@[÷8¤0ô=ù²­Ê–V'&) ) mLQèç}ÒøÖn¤¯É E'³ƒåO( c( áÞù'ý¼ ~ÆT»ŽB@˜ߎ±Ê¤‚¶íqHaØà"HÍ ß0ü\cHa^ërÑŽõ³¦Q¶ƒ‚*»Û\§@`ù³ü) c( 3 +a-×ÑUV™Tµq¡ïqHaØX7¥·IŠÛd ×RF‚gÁåzRâ¨ÔÅ ¬e¤Ý`&bKÂËŸYBaã î[…®£áGKKè{R¶öjÃ>mc||( 3. <°eÅMi·‘›n×$2Pù°ŸÝ5i¬ ËŸP¦EbÂpÛ®£$8âji uC Ö—Á0¡0̺0$!CWÒæ€ë|šéRÅò'†i†ƒ2P†E¼ÞZE®1L'¡íqHaØ2ËòlÆ®1¤0Œr’dÊHóªìrM( #!¥1ƒ7ɬ`ù à Cô×”ÿufœI/¡ìqHaØR?³%e'w9®1¤0Œ,sÀ’žóòÁhð[ΰ–‘¸€èaW™ ,Ba˜@a×Q„ÇÇÂý«A[H‚¥%ð=) V{XCàÞ»¡¸G…!…¡’ ’™¸º"ïõ‰P$$60L.ËŸåOa˜4a؈ë( VtÅÀ÷8¤0l½žðœ<§„° ž‹‚¼FtRmE?ËqXpЕ´u¼öU!,’ ®9r$tøðáë\+wäÃ!·û¸ŽÚpaú tÃC‡}.VÏ—“T¼¬ ÚB¸'‚p<æõƒk \ÿï¸#÷‘„fåqU^S(mRž‹œD¡0Œ[Š*Yþ„”‰³{ZP®£\c˜ PGBßã0EÏW³ ÿ€õ#I“Œ\cÈú° ê}=Ñ.Ý”<ÙSô|!1&ìfËŸwÜ2ø¤ëh´$ÍÒú‡㙄kÜyE¯Baècê¿`X•'VºX5Hœ +!ËŸåOâÜqc̲N°x"'‰––P÷8ÌèÀxB7ŸIBaèLÄO³„ ]I[&ì>fËŸ˜uÜy"»ê¹Æ0{„¶ÇaFÆøI^Å5†¬ÿQ€þl‘Õ€Â0î`Ö¯›ÙÀò'$F·vE¨ûŽ€¯Í5†Ù$”=3:0žWɶr!ë Ø ö/Ä:ù-+JÌ–?!1ê¸é:_’ni |ÃŒŒs’—·Tysnz Ãú àÌ’G"$6Ü`°ü ‰AÇ–ë( VX%]кÇaÆÆxNa‰½ª’±M¡0Œ›qóКV•€4¤EèJÚ:7™,B"î¸ÃtµáÃlè‡ïƒgnrp‘»(ÏsœáC ÃvRo… ã$¬Õ½¡ZÛ‚‰P -F,’lÎ:|èJ éСë\çÈþ~ƒ~A¸îv®WâC‚A˜ï=9t!VÏ—“T´.±õÆep1-Ƹü¹Æ°œúÿ‘8Õÿ#GJXnªò²·¤Ý±¹ ‰㤿Wåõ<WÑ.Ê'í® ˜¹»n”ÿÇXþ‰åòЛž\ŠS:rç¡k>î®3Xt ×(%ƒ4YZ|ïq˜»óðõ¸=c*ÞÖ— Þ즀;î9r3Nu÷“Ь\Pñ·¦“Œó˜ÌX@ü³#S`†ê“RþŸWe>BaØ.aØ/‚pKqmE’H›¥Åׇ†M=r¹æÂÂЛE·æPÔ7iž‹0ø[•ì=‰Hã“ÊÿËŸÂ0dah®ëÓ®£SäU^q!©¦î‡†M—Òµ˜Þã†Q A<·ðUý–Œ¿¸]E€p­Hk,;éNúfE怋Ïôe'ý³ƒÂ0DaˆNðªÚu´?¢¼êb¿A\¨¹Ç!…aS ãù˜Þ×RFÖ/I;sN^çåYæ~Ò$ÀÌ ³"³ƒ¡¯±ü) C†˜€øßNú’¢ëh(¦ø·yîqHaØÅí ( ) Mvå¹@ddX õéNÊÛV’ 0{~ƒµÌR`ùS†, ç¥ü¦*»Bt¶Å Ie'Å¿ÍmÃ…aKùy‹ …!…ámM.¤˜Œ¿"ïõ¨r À.Ö´`UŒðÓ*‹Ì‚LÃõV†a C¸"ÀÕÿPå |ãÐñ ±Ï 5°÷8¡0l‰R ï©Cq!…atýÏu™0Á{LÊã·¬°–Ç8ð@IB…aÐÂpPÅoô˜ìâAAUö8ܤ0lŠ«ÆørÌÆ]®!µbKFZlb2 Ÿ[Sîºzäø¶ gSô~™ iHþ£ëÞRß±. CÒ(Ëu2ÖsÕh¤½^y®Nz|vTއeñÁýÃôSª¼&ÂfÄ0„u¤û{òåÁ°ó|=söá, CX³`1DÔógg\jÖ¬ –5‹Ê}³Â°KžS$¬—]p™ÜY3Îé²®yNž¿-Iƒ~…!êþCùýÿŸõ†žÒ“¾ÿ¾ý÷( «&œ×á¬äí yN–صËŒâšBHcLÊàeJÒj“"n©ÁÁAƒßÂðOw—¾ýG»öÿÂõ'c°¨èF6ýò\ÍKÕ{Ù5l¨ž5$¬”¾î/¸B¾Ï0Ä€ƒa¼þÞ×÷ì‹Ä CˆD"þ\ ïmX…oõ¶ÛèC õ‰ Ìçn( W¬I3ÒnŸõ·ŒçêŸ9é—œô×¹£þ,†æÿÝ—ea¨·Âú—1¼·5iÆÛROµÕ.g7ÛCur0 a8&¿Q_Óì?VåxÑH V×’0„W ÜGa5×·Ùõ¨{;ŠñR!$vÂМµ]VŽt]¹[=š†C28èQxÒ,ËFç צ1 0$qôw5 ‹"Ö€vcë—´®Ü]S›†úzyNÎÇúåYçnÙ¸/7aX”çnèÈÑÃ_n¤þ?ãŸw—¾åïϲ0ÌúVXµD[ÊQ—I«f…¡’zÛ/2[ªìd]ú”¢•ºƒ†x «aÿ+¢0<Ȝ՟ëöñ‚âN„9ÇUÅ•tÝ蘇dPi2âò^³ÂÐy£³î1Ú˜á¶Î×ÖE¯ë^¦0$mdQÕŽ¤·¤*®¤ø»j zÜÜJ7†ª²i´¢æ1û»Wý\·‘à3pŸƒ©1£ÛUdy+¬Z¢nBôBYwÑÍ C»3&_ðwÆEDš=“Ö3Ô°04…ám·tðìb]!ÖrîÉÿÙ­„“ñÇ™ „Ø18 ªgðüv¸Í CÝf-ÈÀtÍ SÞRÕáΗ¬ëP6ζ:èVHÂaI¿E—<÷û 5+ ;ebeYž+Ó"xÆå¹ZSÕ¡ã[†°’À…4lQ˜aÇ­°f¬òƒni×K}*ºœ£ÛþYé‡L7ÂQUqAÕט±ž%9¶*¯M¡yBÞŸQ•4öÂ5ãøºõ¬uI„ã°n®çî>òõê#,ä<í®}k¡~ÛWའ%LvªƒZ·DBh€¸p“ÒèÖK´Møx¯Ya8â2Ð `œ¯s߆3ÈêÞÖçªPc2ƶÚm$ ;]ÊÙ\7lNÀ4Ô&ø†ßùcOØÂÈí*b_7ã"X;Bž¬*ÔÁ…:ÏC>Î îC‡n¤„1æz"·¨ÆæÃQU½Æ°KUfùÌ5I9CÜUõZÀAk ¬ƒ_ôªƒ[`¬ï“ÿ'¬Å–ª¬Q¼öô‰ÇûêPúIûÛU<íÅî[6ð"‘®¤¤AÌ(‹ö`sKU,†.}Mê-ÒªU÷‡äs+Æ5 ÆàÉí¹ë2¾{G¾£ Ç6¬{Ûp9Þa={cÆñE?Âk øö»÷Ÿ'Âp¡£0$Q@aÛÛÒNéwÒë¬eáÑ­¸u!ÄŸ0ÔË~sŠÊ=*©) Íd@ícƒV;Õ/âpF¹G)ë—ïžö8ÞmÿœßU C3ÙÑS& m7a\_[ôø˜õ>ïñÙi©¿Ý.ÂÑ~vÜ„aÑEj ÖTÁênGôÕçèãcucÔø|Þ0œ;ø\éà†„ÂÂP€ûÂó ψ³Ê}5 ¦:nT%È…Crì˜k¡£êkbpD’Ë@ú1*LJ}èq»îRÜ&î\ŽS§3a¸Áö´J#ÁgRæJÚaŒ]¼&¨ôq?HuéêÙ]Pƒz Ãv³kŒß¯ÊÄUNÞϳ¦e‹\¯yï”ã«>®µ¬߃ç¸â¬y’©W?ºåø²km5Xpî …!]I‰›fÊÂÄQ†…¡R•­?¦jŒmæ}Ôƒ¢*[J籿[§ ?è …!…a=‰´ß‰úõYÅ} Û6˜«ôZ(Ú¥êïï¤Z8Žßt²‰ûm¢A&áLÔZlÞ]gÖ¨Õú£÷Ïk”ŨY†É†œk¤´Fa˜aØS£É×雊ªù=õ4ÛM<—ù&Ç<„Â0Ž,Šij²) mè5EϬÐAw! kAÑ—õº,¸'[׺º“a`WˆÉÇájø'}RU»`@Èî°ZD¨tˆ3R/0³ºeÍõIÒ{~­¨Æ7S÷s¼ž[ÝOHýù˜u^¯âv0†É†˜@ÛSŒôF( õ–[Vÿb¢ß×}Ó@Âc²uúI¸Ö}ÆåûOªæ£wS{X ðÐZ¡(ÏË%'ÝRþ¼Imy€×šRîáêÆ ¯¹n«[¹[fZØoªÚë ¿ªÊ›eþ¥ ŒLÎ)ú0G…½]N:àœQ®f}EÇ8Bý©7Yòu©?v©?çYŒ†´’,æyÂ-†­þ"lÒÛŒ¸ôM CðNjǤï¹)ƒe“Eå/þ‚Ó††„¸ ÄVÑ”:èJ‡ÿuy7¸ÂÀþdÆWìµ84ÙQ4UG) s.VA’[À¤åêϹ:Ç¿!uçkNú”Ký!†q†ƒÑö³X3“Êý„. Ýú=fqs†7ÔPÀÂpªÎço‰(ÄïúbƒŸ%†„4,ꖸƴËÀ~°FãºÂÀ¾ž+à¿Á=ö#.¢€®UÑ ÃAᇠ¬I]hSý¹P§¼AêÏW]ê-†ñåÊ÷çJ­¦g=£´øo~¾4ö#?ÜòµŽæ*‚|ØVŒ@%©æGŽþrÏØK_þ’ÒÃOé.q­ÚdÛ…³ÛèsV]úŒwú†ãýœæ§Tybñ….}åXÅ…ßwŒc€ÂðîÃÿDµSáÛŸ\ú¡6ü¹»»îø2K…´J«‚Þ)UÙðzBU[tæ¬ô„rÜêÀî3uŽŸôè°O±D* 7¤Ž¤¾˜å¸juÄóÊ=ØK«õÇÞHÝoýT0‘e}ôѾ3gÎ\;}úôO;Ï9é‚ó:iQÒh1ŒýÌ‚2ï{ßûºçi<à}Ñù;ƒÛ¡õ:Yè}»2º°Fx KFÿ ®ÛX÷uãŸñ;vÉ)N%Mæ­>ž+{˜Laî¨èQµ}Þ“†—+!¬?Äî”1CÛP¤?g€;î|沓NDØycR쌢D’Èì€]Öj=‡ïOJ6ÜlZÕ^3O!-QTþ,ˆq{ ± ëñ! O"5êŠAìéÓ§Û½^yTÑPwÈJ€EÏaƳa¡É:1Âv!q}OÖÛ&`í:!ûŒ©jwX“Ry NºÊ"$¬?¤ްÛp£;AtΉ°$|‹° ˜îò° pŠôЕ…Á=Öåú(c’æ¢2f¸> bºŸ6m”$§®/ù™qÎ9î¤Q扨¼¦¥¨âe k¹ðš°þš B„Ûë;Zèè‹X‚ˆrf€Á:¢AK.²´2Á”%ú'U ÖÄ#¨‚kø9÷ôéÓ=ˆ Œg)£uàº1Y`–½½Í&²8¡È–HWQß}ö+WüL®%›V£uYU/¨GT­žˆþÇ,ÚžËqeÝ/ÿæÿ«<âöÿŽÔŸ¤Üo3ÿ››<ñÿàþ¿÷Þ{àÕ¯~õa ,ë¥ê}~Ìð SaÞêÇvUu°¡(ûYßÿc.ögó{>„¤D)ûï ºŸüœÕ÷\VÕðÊë‰S¶hi$ê¨<ãþÛ„4A­ˆ^„°þX0BwÅ4ƒhe‘$$`ÃkÛÛÛ´nÕÞ*ܧ0H ¥\#çËzDö%„4fßÏ2ëqûŠ«Z¡]߉Ù^Ù«kIÖ„áP³k%Šét†² žS¬5„ªì~Cë±Ú°ˆÂ¶†u— Ó²¦dƒ!ù ©¬ŒØÆ–Ç2ò“á:ÊÈ¢éîƒV°¾°•k`„‘L ñÏ6¬„õ‡¸!›ÒGÝ ]ç¸~ÿƒà¸¢¶:˜NÅhØi…#˜èhÕԹƖ“V™£„Ô‹ò/1ëq#n–:D›ƒ«K†¤ðYƒ•üDk¢œëLÁÒžò,Þ–'YsÒÛ÷ Y“ˆNŠ(¥šÌYBjƒ™xnLXHU'W·Yïˆþ¸Da$$Àýëjƒš)Ï2ß9ÖœÔ>hëu=±>r Bj€NgPëуÉ<6ÌŽs ¹G§¹ÂÈ$-8õù¼3áyI“@ìP•í'° ƒS‘†Ä!×âÍcNúŒ“~LqŸÒ8_Qå…ÿ/aýI(„+Û9ì•„û5g~ÙÙ“$#›w_ ºKÈþÝv <ó_vÒ‡œô~U½g!!„DÆœ Šu2#€­&äØ-'•$}ÝI“ ü ö1síÑ  õØ×¥îÜ2&ô1{ƒãË<É1“Ëõ޽îu¯ûÛ7¿ùÍYƒÓË­\³]Ç^õªW}iyyù+?üð•˜Ý§éØÃc‘;aŠã±|>ÿ™0¾ïyÏ{Þÿ@t_q½Žú·›@Ž5yì†5vù¥®™µcs5Ƴ‘{Ñ‹^tí/xÁµ0¿–ÃGy¤7¿=‰Ú¡Ö1’p¾, ë_«ò"nBá¦ÔŸÏ°þ¤ƒ8¯-¬ z©ÓÙ_w:ý%noAH<N:›Ëúÿ”¾çsNz3K7=È>œˆ¨Ûæ÷8ýÄ,–LÐÓ„j®;é Nz;³‚4¬„ŸPå$Á¤©stÄa\a) I‚D[1ˆH¤õžq繘LI–ý²*{ª`üÂ5ÆézN`ýx›úŠSíú.B’\0>¦è£OšãNúÖŸdóÈ#À­f+­¿3ÏØÏ$O‚•›vbJ•-†KÌŠô [Jì´kRO¾ï²“ Ì}BÊÀOŸ“ÖŸŒrúôé ¬=‚•-ÅÂ[\ÃÌ0#˜’ÖÏù CòûÁX_•T€O|žIK„m©'$ip]aýÉ(²§ÓÕ,XÓdfx¿—{X‘ JøÊûÞ÷¾6?ûÓ§OŸ¾˜ðAñ4k!$Pî½÷¾?½'Ÿ¿–öt÷=ù[Nú†™îÜ_ËÂoGrŠúd«uåŽ;Ž~$+ùå'=ñá'ÿþv}‚yq0Ýwÿýg2(Í;ÒÁ,µù ·’ô ÃŽ¨ö …ûxØ–Ê{ïëü³;;ötÇѣ׳ð;ÝÒÑ£w¾§Õz‚‰§mÞŽ¸o˜MÑ\Ò,{°ëÆî_Þ(e1=Üó-™ù­ê`(ù†A˜Õºâ–ºžÐ}ó¡'>éóâ`’ÉsœAñŒ3Ø ‘dX”^sr(+ãŒ;;:¾‘Õþc£ë!¬æç£š 1Å©,9(°u 0¤0¤0¤0¤0Ì„0D§'‹û3¢[‚~¬É``†yBÚ,Ìri¿ C C?–:§ý=‡gR±g_@aHaHaHaHa˜za(ûCí¡ócë_QKáÆDË!ió$ÍI'¦ù7RRúx6ã´Î.Ö\r@aHaAúwÿþ×J?ñº7”¶wþ¨êýÿþGŸ*ýä¿üùýDaHaØJú™õïJ¯š™+íüñ§«ÞGCýúÅÿðŽÌC¬'„Û˜“–Ùò×Z¹u Ù2Ñ Ku\öÚÄ>ŠN:´¥$ÂðC{Ÿßoüì¿ý¿ûí3Ú?ö¿û~ È„!i<£Ø®eÉ% Ãd[ 7ß}z?¹£0¤0 jâ}ÿëÏúô†ñ†ð`qêÙnœÝ÷£Ø_Ô'»Ne+Ja©0Ôîúÿ·Ÿ8Uú•ãÛ·ÅÜõô±Å•ÿ°ïž¡bÝpc0›ÂÂÐ-¡Î îèÿ!ôt玺`vܯù™7í×+L4Àù/]»=˜°ÝC³. aàz‰–ò¯È\ YJƒ¬óÍCŒ/Þò+ïܶ]·÷øÿ¥¯œ¾} ï½üÇgn¿6ûsr‘Â0~ÂЩc«XËs‹!¢öîÁƒ$f·vÊIÃl­( #†hˆ!êÐxꄆW‹;{ fóÐP›}ý>…!…¡[BÝ0ë’®?¨ ¦µÖë·þÚÚïø1ˆ0¯£ë%…á~ç»"Öòlí™A>¡S÷"BbG3Âprzövœ$ˆ?´÷zRÐ<Ô`Œ¢-‹^c ÃxC™|¸š„`_1ÝÂbT¬†°ì­D( Û# a‰±সÓ3xÚòƒÿ1·évÃLaHa¨\a™öª p%5'*0€@4ëž[½Éª0”°Û{tƒ ¥k‘“.Çp™$cra, Vh¬¯ ¢Ž7# 1 m/;Ñ "ÑtÕî¤XÞ¢=•ðyÛC‰Â0Âõ*Ií§óÌŽÇLĮʘÖ-‘4 C¸@x `½Ža _»Ö¢QEã‹Á8Üõô „¬=z=€Ùã<4¸ø psm¢ŽJŠ„×ZÀ „ÿŸ;úÂý¿nëÆ( «:AԷδֱ8 CÔqÔm†PÔ“¨{¨?¨[¶[©®Wz-¢v?EÃy?úŠ©ýz‰×ÚÍçëcøë59<[ÝøÍÒÛ¶N&N:ƒÏ%¶ò¡äí0ÖÇp#dÒÄ s7 [TÀËÀi?.¶ºéx3–?±}ÚhÝ®ã}X Ñ? ?ÐKô²ˆC´ýx­ÇLømü‹_6¹ÿ׌ƒ€×xO÷=8—ÂÁg…aä¬!Ú• ž} ±¦û„cíŒJŠÆ§)RíÿÝîç˜Ö -tͤíæû¶{…áÁüEG鎓º“D 3…‹&^£Þ™h¢’âžP_Ì-&êYu½4'JðÚ®cZã·›ï{Y*|üC¥Ã‡”:Tzèá'Ý®£ >CìAôööv's‚Ô™PØJˆÝßR®í†ºýÆä³í"ªûôv{Œö“~øŒiUÔÂP'7a¨SÒ…¡Å: [¼Œ%uŸñ¦vÝÅj3c¿Â0é.ø²Ñ@LnýÍŒ*G(]pÒ [؈…!SÌ´šìµx¶µGïäûCa¤uÔQ4ÄÍ4(iÞà™—àh×v xuÕïæùèÚ'‹äÆ:$ Ây$ºðf†œ Ò0[_tÖM™O¯«Êþb§žò”§üAGGÇa']wÍE! í€*æ ùº‘à)nÏ^8 «IÜ„aRR;…!uÓ³^[‰×zm¦^«†ÅuÔì8Q/MaˆŽï™.5iÝà>W]XôW~y«tï}÷ûzæÚ- ±Ö QÞ5“­zä‡ F-Mù˜l™sÒ7™©Ç`ø–ô-Dì¸,ÂpV„"’A°à’˜Pèôø.;¤ªK®×ßÙùÀƒ·Å&FŸ\xj bâí)Æ!:Áe_ äOš†v„U¯±$^ûµº;1mZ!2Í1ƒŽç€±‹›ûi«Â6ñ¨H¼7‹ü–Kp ð6Ðþ¸mA…6ˆCQCŒ¶R3Â×0ã ïòr%eTÒDP”I+x0`Íò¢“öTÙ[D! udG̺@Ú)𿽷Z=×C¬IÓ³Fz•ÞwˆM\WÏÁ„sõçL•0DÜ'òÆÍEyb Yˆ%œk k¿é—ßõ»¥ÎÇ=Xº¯óq¥_ÿGc|[l ìP¶øöÚ8tA¦Uu.)æúT=+ˆï×uÇÑèóõ=¡~yíQ7aˆûÔ/nõ¿ÅÜÞÏ~kÐA€ðlÂ5ª÷Û¿Ãuf;„!¬P»³ÿñö>Ä:PæF¬¬ƒS2 º$ƒ«BÏiܼÓRö²?ê¿îÒa CXÔ0B_à¶öýŸX “¥8}bkš†è—ô¸ýš=nÔ1 bˆI`}MÝïé±$¾Co÷¤Å ù™fÇb^Â}TšÝêeÛ¢¨¾ ‰Ü ⬴i$ a˜Å î[†å63…<¾fƒ¯ärwÜ^ðÀƒç÷ ßàÞOP7wj¯:†YVIt|aEÌÅ@ÃɃ!" Ck¤Ež„k[ñd`º“¦}À”&E îÈì{˜ƒÇiD#MÙDǼ_ר0„!&@õ¶^^"Oï¨'ëõ8b)(oîcX[¢ž8õ?µV,“í\ؤRRZë0בUMxÌäi«'é¶Ë‚Ž0Ö”0¼£" ïï|…aŠ…!X¡ë˜¹~ÇôL0fˆí:Vk; vP†#!vHˆŒ¶Ãµk‰¶ ^bÙ¶ƒ€ gU9XL±_([™dÖ8haˆ°pi+—鱋&¨ÑÀ[D·É¶Ë¿ØÂ0xa(Ñr;Np[¾×†-,†d‹5„«Ê;º0I‚0„5ÁFb­IƒÅÐm½#\&õZKü^î Jâû°ùøŽ@\—¨ŸI†È·ú„Û) ÎÛ“¦[v»…¡[P†¡„´Æì$ö‹Á^J¤5KÒ(N:Ãí-ÚÜFñ\"H'T²˜<úè£ýí¶ºôݧê nî–aô«í†zIˆÂº­ CXÉÓp¦N[¾Ù†I¾N™Ì‚§IŸªŽpl&B‹a|…!_{ý¥ž¹aØÈï Å0“ æºJ ¢†vPG~Q¡¡ @i)L(ÇFÜòHSäd’æ¢ ¨H°Ö’˵êo»„¡ð㻿€ûi+[4ÑbèO¢]CÀ%öS¡ÀX—÷±MN³‡Â0¶Âeó=4Úp ZÂÂ0›Âu®EfT·¨„¡”æðáÃ_We7ç‘a½l±S?ÐîÅ>ˆÌ‰À€U®£ÛªÍ?Ã’—ï XKVaõŽZÚÑ;µ§–é>jö†á¯1Ìêd_ˆ—Gßχsª¼Áý”‘ô¦âv†q†Zb@Œ¿¦•¾þ°ê`önvX#¦Ý8°N ï!áu³{úaNa˜naWMÌë:fvð°Bc€5%ºŽé=™t½ÄgÍh¥a¸ãúc/yùþsåT—oŠ0|_@‚a ‘ iYJ7â&|ëGë¹è_¢ðœX Ûn¹€{Y\é$Ö9¬¥l‡0ÔkÊ‘ õhïÑþ£¯ÀZs´ûø_-ƒ ©”:p …aðÂðÔ©S™µXÉò€³!~Üà0 ù½+¯Í´ÎfŸÂ0ƒb Äu²·€ÄÀç¡׳zægZ±è<øø‡ênG@a˜laˆÎݬ+vxrE$Xìô†ÉúµNöQa%|ÏÑ£GsªÌ‡ôå ¥Ng³Â}ð²3ãì”õ £Ýµž9X±"±ØaìGyäzV&rÚéJ a¨ž) õXшvŽ>ÇñbÑüŒ¹…apÂðôéÓCN»u%«.¤z’ËBþ*XéOaWÒ¨Òw}Ï÷Öu¡0L¾+i’’±ajÑ…íÞŽ£úÀÝ7â”î¾#÷¼—pSÏã| ï¿»ãöÔ ƒùÛ*¢ 3ØÛ, Ú7¸Ï†0”u…³î /ÑX¯F0©‡ 4ƒlq( ) 4úâ—ºF£0¤0Œ0l™{î¼ãÚŸÿÂl)N©§ó^ÞK›RGî×ï4ÖÛ\Tm^Sèb=ÈÜ>•2(>kZŒ( ³! á6¶ý:[˜Ybë Œ1JVºÁ܀Çîȑܕԧ\î빃é«iøm‡þ['ý]­sœ¢>ßj]9tèÐg3QW|¦;î8ú‘ÃGŽüóâ`rž­SRR¶¬Ë¼*I4âð¤tçÎ;;¾áö䌱¾–…ßé–r¹;.H„ÚŸ€¶¾"Â=UÞŸuIq!!·SåÈs„¤ C C>¾€…¦#¶Ër!`UÙŸsŠU’düYÈ=úè£a¬¼(bPÉD˜öޏ ¸]!ûàA¸Îl †††™eÍI'"…cNÚÍzA ¢.ÖY²J¦n£ä ‚ñ„ˆµ†äõyã5 $EæŸÞs×cO| ó›?ô„ÿÅêšÎ?íÉ=={ð™ç½`ã´ÇíC÷Þ³ ,ÊcN^ë„I²-ŒqI%´ï02KÑCšõ£ÙFs¡ÏnyÜ…a“éâϽ–ÂØ èØ—U9L{Ô\Žký‰Ëóq_>ÿ·¬²©árÚÎ8õ èÇÈ÷UU^[xU^›‰ûHb7AX Ç™m%/¢§–›&"—­KÆ=®†ŒÏBHÁbÑ8n—ᘼ¿*)ßFaˆïC¤Á“r¯ö@÷¾&i² a‹ç¦×½7* ß>ñ‚Ò¿.½á¹ßWz÷¿äÀq¼÷“?ð=u¯óÁŸyÕþ5^õ½ßÕp‡û+/û¡Ò¿zþìþ=¯~Ùã¿õª)ýÛþ'uïa÷M¯.Íýà³J+/zné5ßÿÝ¥½~ŠÂhިʛ:^Úý(·‰ 0¬“Ž>|…U–ÂÂ00QÍ€?„ø~âìaV´ ÊþÆIïsÒ["±S„O‡ñÞŠªìÃSÙ.³Ìà®9lˆª9ãX·\¯]ÂP‰tû쌪z|¸Ø 0ì’ÀãACˆ±zç@lÕ;çc?ÿ“ûWÇGîpý\ßíºn"WßÇ'ÿõO¹^—Â0³|ÌI_Uå½»ú"¾ C C CÖýv CBHƒÌË r7³¢%ò"Þ´àÂ,Õª¸ì^AwSþÂU¨$ ƒY! —å:ͪJÙ‚E“œñޚ˽M» £†«.ïlPÖį0„»%Dá÷ž´/ Lø;ÿü¥·ß{ÓÈ÷—fŸ3è»CkDâð=ú`54-•úûñ>¬€t¬ð†Ÿpµ2†ÙùÿÌ~oé»ï*­¿t´êýW~ïw•º÷ž}˨ùþß3JÏß}à} ÃÀÁdÊcÒÖÇ! (…!…!…!ë~»„!Æ>çÔAWÒˬš„x³FqX“œ%ú |àyVò톤K"‹Â@lR>‡ÏëX°îý“~OD[—ñ]†ãªT§NC®¹ˆÒåÂ÷0a¸ìòÞ‰(„a-kĘ)°þé·B†^÷kŸ)Táêæ¢ZKBÌâ:íìüï½óhéÐ!UzúC]UïßuÇÎû‡JýO||ÕûwuŸÂ0pUôVB C C C Ã(„!&Ÿ·Uuð™¦Ç„d X¤0¨:–Áß®…߈µew˜eB]’Ù¥UY77-ç÷©ÆBçEüuy×®¤9ëþú axÉhÔàrºn±cªzÍa‡Ëõ¢†‹ÖuX„u#°Cúé0„!Ö ÚâΫgÂ÷·Pó½ÿs¬Ø²( »óÿÀ¿xåþ½Ûk}ŸÂe C CÖw À@̃~VCBšcHêgR4›¢÷Ó+Š ƒoMÄÅy÷TÅÚ§…ß”|¦Á=÷Ë=®HZ3¶‚ÜߤXsý¡fÖøü†õÆäókrL_Ëüì’[‘×~·5É«Š5uÅåÚÚåUÅ™—ÿgåø€qokòÚ^4A}]yìÅ„ÅдÖ}äÓm·b y{~,†ïÝí_K‹B½Þk E^U¼¼&Žp¬Õuáú:µ&µÜŽ÷¨Êfц†„Â0îÂpÍcBšRS"/ˆ•g(†BoP„Û¤!f ¶Eàé0ÅzMÞ;!ļ n†TòïhaHZ†[QÏï{êþ_Ó"§×÷éQ¶5ù¢š×;󓝨¿Î|×·ïÿ}Û±V·Ã…¥¬Ö= ª^gˆ×Çÿñš÷ðcÏìß¿ŽNnu( cO¯´¿Û5&ï¦TõþŸ2!3SÒ¾÷Ôè–\&•†¤Í¡0¤0$†1†“2<%cD3B®’°è räuŠW:8Š^?7¬®‰«•´¨+Ê eʤhkÕ– ~väû!înBoWUÖó­«Š{縪Xú:SV’_[ªþ–†ìp) “K½ÉŸV5+MÞǼËL<…!…!¡0Œ³0—vÌ-‘VøÄ'>Ñ···WdÊfz×»Þ5þš×¼æuÏþóßüŒg<ã===g~øá÷wvvî:é£Wý¦{ï½÷ãò¹]翇k!=ýéOÿÍïüÎïÜzö³ŸýKÅbqåe/{ÙÏNNN¾þMozÓO¼å-oyù‡?üá‘~{!f°h¤\›¿»–Ø…§0¤0lC5;¦ª÷ í6¬y'e¢LïCº¦ª]½s"°VåœÙ6 ÃùÜ®1c>aÏ¿ ÷=Pç>Ü„á L5PF”`X¿×-‚-\¨ýD†k5ö,}áw>mm+…!‰£0D}×ѨÝê;¼S FFaH†[N*11e,qV©L—ªÞBÃN±XÜ–0Ô®§n Óvt¸­Ü…a`ŒZ–3,J3%Â(gL¨l©Ê¾¤‹Ö³Rt±Ä…m1ôºöºªŽL½ZãÜYUäÊüý%U½¶¸¥²¹K+û|bí-Ä!Î¥0$q†nÛ 5³÷-…áÉ<½ÄHÉ÷ï¦0db¢0L;´R†\Ŷ\&E6Ue;˜)upk˜QU àä¶—çJ „a·‹õ²ÛãÜYÕZôêË ’õ\$ƒ2'Iô:`s‹?"2 aøë¯xaé)vî¿~ïÌËKß_¾Öî›^]zðž»JÝ÷å) ) ©ï~,†XçŽk¡þzíDéžúä}kc}ÃöôKoß÷ÀÝ¥'J}7Ÿ…ˆ„!Ú*ô s2i•—É»‹¬š†LL††††­ ·†±S‡! ‹.“¡"p9³çv0™¼Ë¹­ŠÂ†-(nÖ@3ú.þþðwü£È…áC÷ÞS:|èÐþë'wÞwû5‚Láõœã††ÍÔwL|˜õ‚Ïϵ°í§!°\TÃêžä|u÷†gˬïúYðÚB© ±*FäuÉxOq C&& C C C ÀõoÚETuÂp[UÜ” 7,ë é®Ùç!Ô¢p%Ý1¨Y°Î]’ßoþn›Aˆ †9P¶÷õÄÚÁ¨…¡Þ—Ó~­×A6²_'…!…¡™V^ôܦ]Iýã>_ÏGPuß®ïö±„áUÙ^džçë´S„‰‰Â°.“ª²èšXüò†0ìW•¨wó–ØÒ^ô~žø¬Dj^U¶ÞÑײ,xH'Œ×~×Êô׸6èU•ýOa“sGEÌWÕýÜÄ)¬‰·êX·úµ „) ¹ÆÄ­¾ÃÒ‘Ë!RF×®Êd]§! ÑN_7<=…!…!…!…!…aàL)ïÍéIƒe¬§Ò{ƒâ5‚Çh÷Ì×|ÿwWíÙY/ÍÅŸ{íí½FñY· 6†$ŽõV7ìe«ë;ö¬ý÷?úüºjp-Ô{¬-ü§ßV(½ã/Ì¢0Ì‹Ã-†×DޱjR21Q¦G\{Bþî›qJù;ïøï¥]¿ïèG#¬~=bmÃ|ƒ± pÃl6å–¥Ý]M|OW–ë{ƶ«è—¶y´‰ºE( ™˜( ! wË¢¤v ÃNU{ŸÑ\Œò‰ÂÂÐ ¸3ÿ7'ÝPåH’]>Η“¾â¤/;éS ~æï|~†Â0ùÂЭ]$†LL†„Ô!ZkŸÑ®Ýkhe¬©rÛç‘) Á§UÙÝéNúÍ:çÿ‰“nŸÙUÕÁžÜøcžú3}|&•õ=#Â.£×ò6¡0db¢0$„4 CZ Ï7¬ûëœÿUë|äÛ¥?óEŸIe}ψ0<ç¤EÅ@3†LL†$f•w4G0©*£ Ù=°^{àmÊo „°.Y¢í×9ÿ÷¬óÿFÕ·þµè—TB-††¾@ysÍwÔÂð§ú§KOzÒ“J¿û»¿{û½ç<ç9¥W¼âu?‹Ïœ9s&µBãï|§¯|+=ó™Ï,ýÁüAÕ{ï}ï{KÇõ{?øÁî× CBê ¿¥˜Þ—X߆u;Uv[$„°^ì¤ÇœôM'}RUöŸóbXÄ \JMÕ_O‹Ï|Q>óNz‡ w .…a´ÂÁfNÉÄgAqa4Ââ@ýèGKGŽ)½þõ¯¯ù¹·¼å-ûçÙÂ%Ê´»»[ú…_ø…}±»°°pà8DU#BïCúPéýï$¿åÂ… ¥Ç=îqÞö³Ÿ]ú­ßú­P¿ûmo{[éÅ/~1…!‰;è<ôsãÖ`ukµ–åø¤Ë€bLUö©ëk³04¿ûÈ™©ã>§Ueï<³SÔ›¬ï¨ŠÅòXßOaH( ) …!×RV§»ï¾{_àá/„D á×ý×KûØÇöEÖÓŸþôý¤Å„CWW×þy/{ÙËöÅäk_ûÚýsö?«…Ú³žõ¬ÒÚÚZ[„D!¾³Ö9n‚Ñ+MOOï‹Iˆß—¼ä%û¿mlll_0šçá÷?ïyÏ»ý?~ï›ßüæýüÃ5 ¾ŸûÜç–Þóž÷ܶ´â|\ïo|ãíÏÁˆü‚µ¿Å¼¦¾Ÿ;ï¼sÿý=xëC¨Û÷ÿÊW¾òö½BèëߎûxÝë^· å÷´§=mÿþ´Õ߃ï×yª' ðy}ï~÷»oß³9‰ ó uïãºøŒ>ŸÂDQD•^‹a8oXŰù÷¦!¸†Ehi 1©72h“0ï7¯Q4þǽ¿e݇òz͘Im&X …!¡0¤0$†\cHaXmAƒ¸ƒøÃ_ˆ™ÅÅÅý×°XÁjÁñ¢ÏðÃû‚Úº¡ˆ×PZdÂÍÔK@Lýâ/þâþwB¤h—Tüq‘‚k@pâx-Á‡kA„Àš†û4žâ¿ëíoûícŸw¾ç‹Î¹x}åï,}ijªô)Ëú ‹ò߯?q1ež1ïÖÿ#?¿ú«¿º/$ñò¬¿¿ßM®»È{Gœ ‡ÿ¿õ[¿uÿ8Rww÷«-òy®E!„%î â×0χ°Ä½Aâ;Q6ú}ÜÊïá^õo@™!ÿQø î÷‚×ÈkÜîç"o·ú;ï»ï¾Ûu¢çã»p†$@¶ÔAW“u£CA]°­€ "¢ò.‚.'b«ÂPßëˆ*ï§—W•½šDàš¿ ¿c9€ï¥0$r%¾û`ÆcŸÏ;rG>ÂjÂúžÕ=nwWÇ^€ùÖ˜%QCˆˆ=ˆ -Pp ÂLŸ±q€?ŽA$At(±Âza‡ÿë¹;BPà:x áa~)ì : .êýœ£­\æHÓZ ÑÁ†×—œïþ’#|ð÷ Îïø‹| ê³pþêSŸzÛB a…ë»Ý îѼ|.¨jÌø^ír‹ó È °‘o8Ž¿È;} ˆ3Yó{ÞúÖ·Þ¥ZÚ‰„r±­†p›ÅïÇõ‘ßø^Ü——(;ü6}rZÜá³°Dê¼…ØÇïÔ÷ Ѭ×"ê²ÆµµÄ_sý)ê…! “Ê=ÔÞNÖgf ±5íSä…åJŠûU•@0½ò~Qªý»†) !„¤¸’îˆ8´'~I;„!\ õ:6 ö1x‡€8„ÈÃÿZœÀb7F|ïáÎÑçA @œèÑP+h ’H¦uL¿†àðh–AÛ2i Eá–ÂÇœû¾äb´×ÙA„áˆf-hM !,nx h® „øšššÚˆаÊÙ¿׆4…”Û÷à:ú7ÙB ×Õ.¼f>BÌA¨jë-Ê÷ª-”8®-½8ïõߣ-¦È3œkÞ3=ÎÑÖ\¼‡¼Àÿø½ú> µ…‘ÂʺÇz¯Ã:¾d 13šÝºõY\k¹MÂpÎå¾Wût³\æ( !„¤x•×F' a!ÔV"X…`)B@,h‹!,Ix¿ u°èáÄ„V£×Ôia‡ól«—|µ,аDB˜.Š~ÖÚÖ<{=¡)ô®8‚óª#d ¯¾õ­®ë ñý°¸™ký`YµïÖ1¤–¶ÿ¿½³‰íëÒü†® ‚¢©ƒ *°ÁÀ@h „600¨@ha¤100º‚ *¨ „·ƒ .¼ÒÜà70á7¸ðÊàÌ8ƒÓ#´ôÈpÇõ¿Ïê³j¹Ï©Så÷õùÁAë|ìµ÷>g=gï³·ØT‡ŒŠMTÔ‰=D€iÏ ØNÂ!%ÂZm%=ƒ1!%好„"ÈôûA)— HÂÑòtJ|Ú{*½ˆ*úå<–rNÐ#Å*vÕ¾:´Xó¨aHøR"æu8±†3h2# C2$%ˆ;éq«…_Ã/»¡¿Çpç4ð×Nð2¶d¯-ai'y™4"2v¼”3í÷"â¶Ãg^9&ßAÊ·”~i ée\Æñ&Î̓¦]â?Äÿ ¬N„¼š€òf…¡Ÿ}Tzƒ*N¾ôÊ>ú=šˆ¥€ÞEý.PÏ¡ ׋˜P‘éã£Ã¥÷Jœ)ÂBz-}YÚL¤ißJO˜„-‚KŽé°Ç½Dÿ~þ_î…Îÿ—¹»½\ÿÓ XýÎN'БkE Ê_/ÀD4‹à’ã"üþ ß.Ê~ž+ÇEHi+=y*å¯ Õ]XXø#ùëóªÃ}E ‰x!&aËÐPk?»Ü†”‘ÚQÊ[{6¥gPâ±,qIXbw©ZÎ’N+y’sÔbI‡!¬y”kÄæ’?Š*å¢ß)R’g`°êöç© EÄ©WH·Ä=‹øKi› ññ 86;„ %ä-£/dº!>ÓîŽ G ¼¹OÌáeÏ6ò7ÉâþÏ*©¿‡)õ·²×Î}‹õ[¾Ù¯G®•¼¬>²½ÔŸ Ý‘a…aÞ% d(¡wìEøÙÙ9õ¼a×ËËrú›¤ó)â¼f-Í!qÄĈ2¿œ³©Ø0K Ëù6 "Ì“·a¯—´yHš|"4EèJø~W CòB°.ò>©…ìaÎõð:ß=æž²ë^ê처?ô³©úŸ]£Ry™sàê³ìÛÉ,áà ͓ûMf:•Î%yéùó~Û`µyC·a7é5~¥õ-)ˆ°’áK4!O†8}òl;$k…8p;uºFg3âW±?6<ú¹…¡®kÚDü„NÓ!Y[ÔÍ'×ß ÃõÔû^ÿ«Ò›dÜÔÏõ|Û­½})mÔ _fB²¶îÜ C]×W¶•ðpvÏE“6»4Sõù»©ßëC ÊUŸØg>Œö {[!$ßJ¾nÂÃÉäÈG†2ôÒOz¢›_žÛÛØòNDaH!ïqÖöB2´«‚ßê°‰#|nDU9$Ëʨ(Ü5ç/¤¤ç†]#dÅÁ?Œ¼LR·ú{—Œ3¨“Î4ñÿrÄQ^ÉZóæøbH¦ë×56í7Z!™î¿ƒÿkCˆÚc8«rÍ&NEÏ.ÄÛàzòþ© Œckó zQ@»˜ {è^‚¤q,#mr¼œ!ô²Ž?ÓÃ6ò’ÂPG—E×í>o²ø¹ˆEY(^0—ý²(zý^¼É0TY¼^Äœ#ëÕÉb粟ôʵºNÞßüÍßü‡Ø”M¢,‚~ŸÔëö]Ü Ð¿šÿí>Mÿï>¼ÿú²ëàq£0$„2W¸„B!oŽ˜0\¾ß&Rœñ<°n¶#®”c*Wr¬†;ø¿`ÒuãD›:‹V®ã˜ ±E8·U# º·Œs×2„ágœ[„hÓ!«÷Û#¾Vá(#é;6vn!=ë&Ïj/&mØüŽ-Á7ö¾6ù¼Ãù6_å¥Ão›”¶l%Œ-ìoãeé•k·±u`çÒ¿†p[8VBL˜-œc‡ JøgÈkÏØË¾ˆèá…FŒ)\ÓÂß)slénšãÃô¾V`›ì4‹t, ~|6çnGÒ¸`®ï˜v¨vµâ­çÊ¥àl¾Ò‡W¶L½Ö6sf¾3e3Žv·àêh@=û‘! ?¡Ý¶Pºîe†¶ëŽ©k¥'†“ˆ1²7Š0ÙIDAT³i꺻klVquá;„¯Öµ)>2!„ò^°ßÜTCü»œAÂ0¼ÂP¨s™åÐßÛ ç¬go Ç Cu<ÅQœ†£v—C~q³pbDÒ]èŸpg?#_Çœù½dèopâkf»6i²éÛ6âøà}“¶yÖÞ:Dd€ƒzàâ; ɰʻôX*¯Yg£"Ä«u´­sqµo~ï罌´Ùž:éAÑž¶ý 9µŽoe„| šô¥Ù×B~ŠˆVNñ¶ú{½«ç|Ta[~dü‰„a5<ì¡›B¶!Z}¾K9…aÌni“¸:°SñbdÆ ¹,aèÅ_Ù¤»"Þ§žHÚ8ç`£¢‰;VÏŠ†„B¡0Lœçé'†ž8“Ú =‡‰e¹ƒ°‚ëîBÒÓõb¥ê„¡ô \ÁyÕoå®GP"î¾!­Uˆ¹ ãÀ^šx¶OÙ¿㜷!’U J¯ÚO¤W9@>Õ6‡!é-[ýßz­âú‰òµ)÷“ÖVèþg‡sæ†?L¾Šo*§xÛ‰Ô?ÿÛ÷H–r†=#íˆÝF†õuƈ‘=w}ÇRèï ýCIƒ©w1A?çìà‡’†Èoå» km-0Túù›I/vš0<1¢®Œ—ã¦/¹r|Ê¡¤½È½hÜØo#R?ÆÜùÖ†ÅÀe1!„ò›Ò ýCÕ„ýȾ§5«wq:ÅAGê“qÇà\êÌ›=ãØ×œSyƒ¿‹p¤'Œ0;Cºü:†uˆutÆ9¹•œùÚÉd6áá°8§!™ÔCÓë6L~ŽŒ;ß%çïApêú6­«&_'®œ†É—¦O'xi‡þ% Jf¿~'W0⤋sê¡yóÿbH&C±¢P{ÑF¼ú‰o¸N'ñ¼Š"=gÃåÛ‡=“rm7ôCº›Ï™— =w}„ÑD]syÓÙ}[HÛÆ~*ØwC2YJ+"TÚ8¶‰¿S&îsü]IIçÄ¡ÖÛ´“ñÌœvŸÐ:z0š!} Q}i³Š45#n3ôO¸cëðRHÖCíàÿUW^ cÓ†+Ï=ØK'Xò=ü:ñœ¦ä„yוG‰ B!„BòÑ  h # !„B!鵪…_=8ò÷#÷®L[T?¨ ¤ÇRg®åLB!„B>5³£|UB|²’jH_COíPe] 0$„B!„¼äûÉzʶJóB!„B!„B!„B!„ByŸÈôÓ9Ï•iàkÇ«!YÀn2å|Þï‹$ü¼³J˜:¹ÉtxžÙc ¢“—CêOù¥wi@É¢ž£-–ß¡M!„BÈG„ÞMNA%3,^†| Ü[Q(kéz|y…ÀQÎs¿'ܯcøTœ?ÂÑjÆ!RË)"¹Šíwšðåî ó^}yŠ£mQ׬¼³r,™úYH¼Õ,>O!„B^M¶‹ÎèÎ=Ë) cô.âÌŽEDNLSÊA¢­0ÀÑ,†þÅó„a)¤÷Ò_ÈQ_FY5RÒ ÇZÏ$d'BþEÞ•jÈ^®bqæ&ÃàÞ4a8ë„¡öz\a;0 ÃŽ]"MÒ»¹Žcíûí'Žm"½GF ˆ@ºÆuÎñÓ^ÍK„y”!`äú}„!á}6çJ<»F`Ÿ!¯ÏÍ 2xaXB´lÃ&b»[”aÁˆŸ6ì¥/¦Ìµ»°³”ÍÞaØ6ñÜ ~ÚrÛ5åö##ßl”ý'÷Û„%ùÙq/=.ßéývlÊGòÜEü8>i„Ò9•<®štÌ"['›¦ÍªM4Œ=Øëª`Äü Ž]༣W¾÷4ýÆ+¦‹B!äC†Ëp*=y…¡ÆLj+åN»:ÏûpZ½SÞÄÿ“®çü׌¯×mà˜ ÑE8ÍU# »·Œs×2„ágœ+½.2|µcâù’žš8à±Þª[±mlîœØ¥‰¿O( K·…¸%ü±HÜ üµ½ƒ‹0Ǩ²-¤Ä?2²/n  ´¾ÀfˆFí%ZuåÖ̆ dô¹„á:âma[J©ûórIë§Ôçï¦n7ùX „BÈï@1ô/º=hÙ0Ã×ò Cu°Ä™½‚CY0ŽØD”Š˜-8ÔÞ)W‡¶ 't+ô÷H¦ Ã/8×rb„Øsj÷3òunD:ÏgøÿèšÙ®Cz݉ kÞ¤©ê„Kb¹üDÂpË ÍÍ ¬Àa.˜¸Û¡øcmˆzRB“pЭMŽ·uèµÜá¼Ûp²z UœM¢>YQtî„U#ô÷(# ÏÜùš¦yÔïR—~À®¶~ÜBh©¨+§¤c ÂNmîp5%Œo£ß®gÃ9×fJ°WÁ\{èêHÏĽã^&Ì…þžÕç†ã.® ÷Òe7ô[ž¼b!!„B~;TœéV{ahËoppÕ¡Ôa¥G‘Í;å“Sר×Í) cy:0i÷b£7@V]oͱÓH>ÒzÓb“ãhï„ô°øïg xžBNÀ~ „Yq"q'ô÷ôn9—Wêð_iß畆õ±rú{sB†0à €Ô‘®«ïþûÓÇã”4Õ`³×6L¾GêÇ´ui騠ž»ú†±0bÇæ3„á®+ÿ:ê묱ƒ¯×³xé“V·w_H¼ÈhBθzò9’·O†„B!/' Õ‘½ IoÄXÄÙ7N§uÊÃ9›S~ޤSzoÖF†óæ÷*ÂÒôùžIq”Ëöó´Œ0ôß9N…þ^¯ÇC¥ˆp»!ù¶oy¬º­<‚0Ü„X¶×^æ†=WÞc° ûkxá‘ÂpÍ•Ia8ƒº]Hyñ=<.¬õc0Ôz¼8ªC Ã"„¥íßʆm¼<ðu hì°ì®Y0í¶“æK C{/Y3/5Ê!k·q CB!„ÁÂp3Ä×Suò™M8©:”QzzC2+ég8ÔY°’‰: Fì5CÒ{sdœï+8îúíÓuHz䆆ßp­\sfœýuˆgñ¤ Ããôˆéù*:¥wÔ½ë„øl–£î02ÔoÅØ¶“N”[ñTñaÊV‘§;SDz„áì7ƒk÷Ão!ù†p÷ÂPöEK>/r C­ƒ-Øcõ\ËG¿uÂñÔ—RNa¨õøØ½hÉ# lr {."î¼CIµ^Œ;;L¶gêTÃÕ—ÉÿVï9„¡_ÿ±àDi¬Í ±%>!„òѧÉÛñáÛ!»×h:ÅñGí“qúÆB2“¢Î>Y2N^Ç8o2LP‡ ê$(F˜Á¡õëÖá´_ãšiçT\¹½Öä8¯·¶‹%ÞÈ3º[hÇj#´¹—LõhgåïÏOÉkÆý\,™:°80!„vÀeaì­ˆø9Ï!"d¶ÄÞ€ó$üŽ…-\'kºs:éçCä§aÒwô 6;z„àl†·»T…”ùWWnÕWJËkÆ­õ¨÷´ï2ì8þŒqÔ^¹¬ÞÒÆ~ÞoßSî wCÜlùjDl½Í§ng=#>‡¹??GÝ;ÿÍêHÏÔ^àÒF„B^Ø–ëmè_z0”/pNaX8¬7ááâÒ¥ðpóØÃ¿€0‹Õ4ª!}†ÇB'Z…a!Ä\·ñ„Ò—Fi@|ãÌWà é;cãJFšŠC¤£œ‘ k,¥Î‡7¥În9¤÷’TB²ü z]~fÁõL¡-ºfálÜý‰óH>aø ÷¾ wì ÷ÔQ„áyܳk—±{s% ~aw”" ³ÚÖØ÷¤ñaSž åTÆXHŸºšq¬0DÛÏJO,†„B^Uö°}3Žƒ†GÎQ–µÐæs:Ð1ç£ä„¡üÞ¿ß®î·Ëðk͵ÉaØÁyç£gTù}ôU·²†°ÏqΖËß.³+8iNÑΕð¾;Q½nÒwiòèÓ'q,çAzVº5Î\×]Dâ[2ù’x7\ZÛ8®ùšL׈óØ”Û.®½A™”ÃrˆýWHã¢yY aí˜ð'q½Ú쉉®¹DضÎ4Sìu_MøÞŠqò.ö%òÙséûŽcg'­^O /—f[xí|T!Såmr(z!}¤BÇ>¹ö1‹vgG#Ô]8þ~¦m¤{Ç%î1ö:ùÿ êöw´£å”{óœ§Wh“i/nqN÷çKÜ¿µmuÍùç8v‡¿Z¯qìÏeÕݧ¿…þϾšçÄ'ólgÈgsì{Æ=|á^"Žžyö5Ìýæi.¸çÄeŽçÄÒssL>ê.ÇîÞJaH!äU…aè­a¸Ç!íúAÂp aÖñ¿<íPÒ6øú{;$í¬0\Àµìœ¥ÉȃÔ:R3xÈOÇàbFøúp.àÞ͆g!éEkÃÉPçJÂÂï©Ðß;`Ó×1q,9±²hÂlâ}{½øU¤Ü†¤·`ö©™´ž˜|„_‹§Õßcø)$ß/†ä{XÓ°å8ò9oÒqnì{ìá=Ø8ÀQ=7öl‡µ‚pËÆNiNw×8žj§SW¶Íï[#N#<û¦ÕëÃпؼÖÝ4Ôyo©Ü6õCËzñ·ŒV‘§]ü­£Î4ƒ¾‡óôúfˆ÷r¤9—waO¸Ǩ3úòhƽÜéÁæ1a\B¸-ıê„Ð^Ö´÷Ü÷­êS ×ošüO MÓæžáÓX56ëšzjíj_Zø6³Š4kü¶G}.ãEж¥Ð?œ´ƒxG†*¾j‘ëtèêœIÛI¯†QÂ}kÕ°!ý[Eßcxg~O¹{ò9ÚÇî +ا=nóHÓâµí²ˆ6¼áîûjž ëÎ^ŒzÿÍ´áòºn^UÌ˦“?ÍzNØ´pßè"Ÿ?Í= „ûÍ*…!!„礈‡¾nÅÂn1$CJó|c8Œ0Tçòql»ô\ÀÑ«a[Àuáaa×NÁɸ1NQš0l" –]“ö#8yòuú{+ˆg a™|Ôà„lGÒW3¯ GæÜ8*¤Ná€jxóˆoéøáâ;D:4­N, ! kæ·wXb"̦ÊÐbH†¤ÎApj\ŸœÐ*‡U‡÷àL—Ô5Ž:›»º`ëœ:Óc8fûíŒòW§t cVQ1ô÷F¨kÆQßtu{ωÐʺcêò˜©'kæü gË,a8çêqõ°è„Lu€Ík)b×Ùt%$=¸šö%W¿ò²ãDê¼ç5Wwm‹¨s%'ç2ìÕpbºîʬ›3Ý*ÚŠî…‘ ¥ç†¾nž˜rÐ0–!ˆlû•<}É) oÜq›žsg¯CÜ;l\ç&MeS—! Õ&WNt/š6®³²LÎkïvH©ŸDý¼v/Úüs"í¥Ðuèï -™¼•\ÏŒ( !„< 5<ï"N~šÒ!¥kO, ­sÙ…ˆsç|É0Mݦ0ƒ³¢Cw]ÞÒ„a/’Άq|Žœó2HÖSòØCZ}>bý 8rý%~_„äûm†m¸ÆÛNIk}HaX͆=wíU$*fVC2Ìô3œÃ#“Fïü\š¸gàÈë0µÝ”ôÏ¡^]¡\?E„aÌy«g”ÿRH†Äú¼xæCo”:…êÆDÜŠ=¶.×Í>µMl¸_+§0ÜE;¯›­ãœÙQ…a%<œÐÊç×§iaØï,a8‡¼×#yÏ# ?E®Ý Ieah_þÌqñ°¹m»0ê2iíw0< kîÚÓH\ ¦^Þà…×>®o˜ôN»rµq/£íëP×ÕHÚcíݶÍó|é"œZÆsâ(çsϾXêš<ö( !„¼¼Ò!¥ßŸQêð C³ï"ôûRÄo?Á€8–Ç!éÕ(æ†;!ºŒc¶;¢0Ü6¿EÀý„SÑ {&çMþ{'³’žÃ}¤éÌœã‡t`‰o3$CN­@š|aa¸ŽtZ¤7m é¼ ý½C;ÎAÞuΙJ:yÙ1Iÿ™#K9…¡~ßi‡Qfõ^;›®gØt1ds¼—C2tm0섇#òö¶QOªn+=‘0Ü Þ# câ·›SÎ"m>ßc9…ánäÚjÈ7òmó¸ÏvBÒë›% §F†Ç. §¦-jú²íe›Nig†‡‘z¿ˆ:³ˆöe'v9669wωe÷”Io÷˜«HÚË‘{Û2ò³‰2±e9ª0¼t/…fq_YŠäñ›¹wQBy3ÂPÒwîa_ñuÝF|fû—L8§p΋F"ÂðÎ)…‡=†{f“N H¸7桾€ßs# à „YÉÐ(u¦¬Òxf̓~ß·•Ð?Yƒ~Ôt"E')"m!šyqR€cä¿Ì+ 7 îfG†Ä«kbN‡ä} yR›Ì„¤—SëÂ5âÕጷ–Û¼q¦oC|–¿s'¤t‚˜AÂPù!Ês2$Õ¤ ÃuóRàÌ ùàD®f8nÄâbèïÕÐür Ã]´‰¢ o3§0œv/8ìjË|5ô÷ÐÃÃ!z1a¨m±äÎ["a¸jÂ* Î _rqÕÍù=—¶Bèÿî³élb_b-„þá»Z¦cæ…D=‡0ÔWæZ+ U$M£}dÃïHs5" ï`¯ÄÇ…©/væá „Q É(†­”||FùNŽ ]›®£MWÍ1tKï‡ óBéö¨àûáiHfnD^šYqªÃ‰«!ʺ{`ÙÜkï2î§YÂPŸU”¯ \+ ¦Œ†„B^›zÄ9Z¡ÿ²NÊyi×{!UIqVur“œ’3<4¿ñ4mÒRÁ±«L°kܳØÿ)<\Çpê+8‹. 9óÕ1ÊeÄÉ\Ä1MãŠKéq‚K¡U¿gœÓºë¼m4ÏLjïÔ9ß>_YkœUaŸ“”rÛ6NÑvÄ>3.[Ξ:ÌSÜeçl¯ÂVWÆÙª¸cבróå{Hfù[@8å_ÓÒNP¢©hÝØÉ(ÿ%W:|-훦Yˆ½VH&)¹¼·C2JÕÄÓÃõ+‡d'mC“³±MüäÐÿcßèä3-—¶rH&ié cæÚFH&Qj8‘[1av\}X@š´®N¡[§›B!„BÁÞÚ"‹¬„B!„ßé…‘^ZøØk V`í]%†„B!„|¦B2ÉÊøo”¯rˆOŸäeÌØa†Õ¢J¹@3B!„BÞ£à­glc4!„B!„B!„B!„B!„B>vÉJY£Iž…éiYr 4Âu„B!ä:ÜÕð¼ß,Ña|¿”ÜïØâîÏ|owm~ÛÐÉÓ·Õ¼3x~5=kmPB!„ò˜‡3Øñú¥çìÓÌoŠ•œç‰ì¹}²øÎñU"Ó2>@lŠø¸K†Õ”k !ÿò2èX†0Î g ×ÛߥŒ|i³Aù*¹¼”2òV ý=±i°â3¾ž‡ìžÛ´ëlÚ*9íñ˜g‡±û¨uˆB!ä·¡ñÂבף—ó¼ÍŸæÿSÈ×Ã,ëéÞo÷Û^”L½ùdŽKàjJ8—†çpòE¸|ÅïKlví¾uħǗ2„ÉÆ÷ðkif_±ß§¯Š}=¿…­zØÿó~Û0ñÌÝogÆÍœ6“8m/ÜŽËךimì¿­7Îmè9s„´ž#]ÇF yaØ4qž#/qýD|›‘ëZH¬ îMëq†˜VÛÀ.ŸÍ=§áêrÕ½@˜7é¾r÷*ßëìÓïëÐ*o„BÈïÃ&œÙï·=ó°Ÿ“ªß.uá•á\é¹»pxΑ)Áj!üm8%y©!¾âðbk á¶vÁ8_l-œ·kòµ‹ó&ïëC ¼-~Óå{ÎtÏlöø ö†xÏÀÂhÂÆ3ÎQk»î†ü½ êØ·°u!p$+(ÿCW7|µ4ñwÒå{ ÿ—‘Ç-s¼Ç·eêKÞá—Óp~WMùza£ÃöšHË„9¶†ëkƱÿ’ž&m[fiv=NÙ¿ ›eQ„(Ù2mäéÕú&ÂaÊ”ÁyFûð=†?Œ8ýdʳ†pµ¼¦ >&"án@ü)ÓºNLm@˜X²ß+ø½fìsiêÇuHziËH{lxu6Û0uøå½¡R5‚éõE…ág„1ÑÖÃï ~Oû}3mµz´Žº¢õcy)™8k)×›ëæ!N«Fî!meœ»žaº±ûUNaX}ñ{ å·’Cκº©uhŠQB!äý³’7ÝêHà†‡ kvŽÚ¨ÂpÅ9‡êog„wd%ôå Ny…á®·ùn„þoó²„á×» # ÓÂîàå… »ö*îÀžÌ~ŒÙç š d9<ì´oÐ0ÀQ…¡‘Ï3ìk½ˆHôûÈóéU[žÁ>í „aÌÞVüݹûA/å>³G#§0l °ûSÖ!B!„¼#¼¸*EœÞj†È鄇“h˜ã2¬h- !j­°Ë# wsØ#Màu¦ßžJNEÊeç „a9<ì¡« ! ·!Z}¾K9…á^ŠÝžB¶!ö²ÒV@¹‹ G†fÚ¤Aúm^ÚÛStbñì™…ánH†E*‹)ö—ú7í^¨ùî^R,Ž( cy&ô©LC Z›­#î.êUp/ ¶G†«Î¾—[~ŽÔó%óÒ+MF®“á³kC C©ç?]Ýî:ahËz>ô÷žEì®åýÅŹiÒß{Ëç'¢!„B~ B2Œ©’o·ò Ã]8 Eã$n:Ǧä„IÞÉ f#ÂRœ­ ãüLºt# ¿™sD04SœÒXÞý\u¦‹N¤œhÈ# Ç"e°ãÄâ¨ÂP»YS]ÞvH††Cÿwxñ\vyh:‡~×¥{*â”>…0œŠˆÞ1“¶ÊdÒ”áò€igµfŽ|ü€ÝK°é©Iû0ÂP‡™Î#ÝYÂpâjÉ´Õ[#|ýþa^v4MžOM«hG×#CÉûÂ*"/ç/“NP~E¤ùõxùX0y¶ßN+ O‘Î òÖˆØR‡ÁÎÂ>kˆ³bÄsËÜ‡ŽŒÍíuÛÈGeHa¨i݃=fC2ôWÓzi^”|1v/ãØŽ±»ý~³ [WPgNMúU ¯šçÇmÊ}“B!ï98gˆÔ‰>ÔAñ“˨8kà¼Åˆ¨Tñ¨“‚ 3QJ´ V;ƒNd¢“Ç´LÚ¶q]Î˶k &í !™Äe*"†y×ÉgÚ‘´©#®io…þ^–M¶NÂ2ç®U»í†þ0×qÝ‚q6÷#B5‚)W±ß¸+óªI—N:²å»Nº£i´eºfl¢“þÌš¸¦¼²&ý‰ÕÓ}óâAÓ¹î^ttLÚ[!éÅÙuiGøÐ‰„ ”™Ö©F†¸ŽM¸Ñ ñÉ\ÁM1<ÿ÷–zà·X£"Kl~À|Kž«ï<²„ÅØˆ×ʽ~Ûs1ížcî™QËÆ&›)!„ò<ˆ¨ù~­kå‘õ¾îBú,~G8îè½¾ »„uíD¡, p.•æ¼ ¾Ÿ™ôùõ㞊»G8•çïÄ!Õ…äÇ2œÒjx3À>çÌ“eä3m2&è=N¦#/(®°M=a¸Uli“@éDU…WÌûyNaò–ùôˆzÿ÷ÔågL_=$k-Žá9 lçL{eõTÜ«oèH!„Œ, eñä[縕à ^†WxP—††±û*j1ò0.å†åu7Àá+…ìWËað[ø;ã”3â©<±¨¬dÄW|‚|)²Ð÷ŽÖ•”ø¶Âã§Ó¯ Uã!ÞÃZ0ù}Na8…°?¥×Éž)þçœ`Hz easé5ÚPFygú•°Öa“´žžIœ7¨¤•}1dÏt\Ì!ÔU–2ÚÅ 65Lšb6-ŽÐ&숈<õ¾œVaìí˜Ç®i°Š{ß øÆsö‘^9¶ì®“xº8_®“žÅ9ã´œãø%DóçÞ£q[iüûæÜ~_áø÷¬'¨é»€øº5ù¯Ãêô-£Œ¼m4¾’q’v`÷ù’øZ&__Âàžš¼=¹ÕG8E‹°Ã9ÒþÃÔ³ì{Šsn\]­›ü~õõh7Yôž)ÞQíçpÄ¿@øÏ¡^•ÜõŸ!ÏQw6rÔ‡õ!Ò—æÜÏ¡_ œ[¦®÷LÙßà~dÛeÛ´““Œ)çhGz¿9r±iâ97m*ö‚bÏœ{ëÒd©!M_ð÷ÊÙTó­mBþŸ0õïéý‰8oqÞfÊ‹©ØáÒ݇ŽÆeʵG¸èýí/ÔæGæâÅ©ƒöÿ ”Ï9ÄŸ]£QÎ9D~ ­)Ïcë‹ð<Ÿ Óös ¯.!„†›¡8é!œu+ +ø¿dàú âϼq$ ¯BÿR­ˆÃw’aŸEˆ¿FDváÐ)Ö9¬E®kÁ+™t©3¬ªaò-ÐB†0ìì‡I{iWÁ·ãöZuˆ%ÏóƆ7ÆÑÙƒ¿c«Ï!y‹½ðÕ^ÃW4ùjš|]e8SHÇ™)SûÖº‡±‰øó2 »È¾N†À, ‹æ÷±Éce£Ã7áªÃ$±~#;Ò‡?/¢^Ïštï†þ^ö·æú ÃUت…xV2âÞrÇ|Y´\Ø“¸NíÝte™%–ÇцÇM[wíÖ¶ñ%ؽ‘Ï”£¦w܉¢òÐB½ CÞºfêÜ5DÓDCÑ©;#èîÌ ¥ò´•! µj›ÒïíÖaw­' ᬬ¡ýišf\š¼0´uµŠpgŒxZ5mâд¡ì?gDSVay*AufÊ/«Çð[y¾6¶*›òFVÝ‹ / OÍ=¬‰ø¼0\Dݨšò¿ ñ^ÝMÔ³º©wMW'L»é†øw÷£ ÃlÞ2í{ÊŽkâ¶÷Ù´¥ï¦-Õ#÷¶¶¹¯Ñµ!„sªª!{Qù†qÚt8iNIÁ ØÃ`ÅÚ¹q`³„á9G{ú܃ðN~ [Ó*?”T‡Íà{žCþpN¹:bKÆisy­gà 'NM˜;& 82" ;Fà]âÿŽù=~‡p4Ì#†á`ÔÌv [V#iÍ3ü,­,÷BOe×9Emçxu2â(ÇJòöÍÕ­C'€îŒÃ÷Í…u2@е]¼]—fëX.Gêɨ°ìâý=4÷\DÈdõv½ÛCÜ+¤}1¿·aGÛnO\^ ƒ®¦”ÄK[%ô÷{ñtåöUB|)$›Ø4Ý…þõ1{åvîœqvé¹6•õB%+M>o—nß¾ô*RÇ‘ž/¦üæ“§-ß8áWÀ¾™œÂÐ cÏ7óû©„á¦+ï;Ô9+ ?á¾`ËåGHïÉþìÚò¤‰³ˆû™}F¶Ü½ò1ÂpÑÕ¯%#<‹ÈÉ Ù¹áÚ{±­;t!„Ä;³Õ2„¡>ðWáì‡!0GC‡”3”´ Q³ïÒ}’7ÕºíGÒ<‡ë/á8}Ê) cŽ:<ÞiÉ# Óòx»ø¼LG„á<›)\3‡ßâ@œÛüŒ„÷Õäë4r|Áä«úÂp:<üÞmÒ9/³!éé\Ù“24à¨þ@9Ÿ„x±w*®î ÊS#<ü.ji ñɉZO$ œþfÄñ+¡þÖݶ?„0\€¸T{—†¸Wœ»{…n³§>Dêî0Âp;’¶­”°²&™€(¹FÛmG„amaXKyùp–ѦbyÎJ“¿?GêZÏØäq [ax4ä=ªš‘çA°žó÷S ÃzJúm}8Âÿ¾\ê/N<»æÐlDà7žH–CÒ#¸îçbHF'Ø­=„0ÔÑ-õˆ#wÒ× \‡Ç<¬?‡äû ÂÑ™5í÷j6Íspâä¼c„dšÛ8¶É«üŠã!鱪Dœ®NHŸ|Fß’ë³5gÏç¸è·™ËÆ>GÆIX Iï£u*tȬΞj IËc“—¯JÎ|͆d¨¦®9i•IÔ—6þ.…ä[,†:ÑJ'd¯!ÙÉ ŒºÄA;¥Žúò™A>µ÷2òÔ€“ÕÀ …5ç ê„:± `ŠÆ=ó¿–ç¸Ùgm¦e3ïl²ëì©ßéäíð°WvÉØ¼ú{£÷Bÿäë®Ý¥¯/!>ËfÇC2LÕ×û´å V‘Ž®±CÑåC{ÂuRVJxHÇ9êõ¢ÙdDÝ ì>kÒ7íÚ{Ú ƒ}ÓNõeSÁÝ'm›J›˜$–¦^Š}k@Ý̨kÃÝrmbÅ ¤NÄæ§!}ò“– ¯çl½Ÿ"‚b÷ˆ¬ßSV:{iÇÔÁŽêçh¿¶lŽBÿ ¸öþæŸË漓½¤ƒÞ¿tâ™…È {?[t÷ºXÛ·5B2¸ú¿u\7í^¿/;AÙqíw&ò¢§mҧǧLºõ¾R£kC!„’ §|'o…Zx½ÅÚß2GÏÔNÙö !„BÈèòâOÑ„ÂðÃÃiÓöÇibB!„ÍxH¦µŸ 9È+#Ã.—i†,„ôa­£2eÚ~…&&„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„BÈ+óÿ/åOÂ׌­úIEND®B`‚grpc-1.3.2/doc/images/stress_test_framework.png000066400000000000000000001744001310511640000216240ustar00rootroot00000000000000‰PNG  IHDR‰!"˜ ¢€IDATxÚì½\eWyî¿'b‚[ZiåWGË­\%:*v02û; É02C”±ÁHt4¨èEË­\;U0˜C2Äàä@ˆ¥:Zª¤bƒŠTZÇ–¶£åVŒ$¢¢! IHB’¬»Þó†Åž}‡ówŸsžçóYpöŸ³ÏÚÿÖþîw½ï»‡¢(Š¢(Š¢(Š¢(Š¢(Š¢rI%º´èҧ˘.íÖ²z]æ­Òã²VkY+—Eµ¬ÞZÖÃeQ-«´– sYTËvZ˦¸ÌsÙ¼«8\qÙN×ü©—M[Ë pï—ò‘MQÉU™.µÖt@— @±–7!EQ•FÂxaƒz±.£º, »x˜(*qÊžÂMv”‡„¢(ŠÊ@‰¡£ÚšÃÆ.ŠŠu«!EQEe‹¤lQ— >ã(*:‰ÿ†˜ã«x((Š¢¨,Wž.MºÌéRÁÃAQ‘ߪ¤KyÈY÷ãH§jpãæj!¤SE¥íÏ<$µ!ñ˘õ œ4è¢r¼¬)Š¢Ò¢€³äà¡ (ï7©tª 4ŠÏ¹V&±ÿM¼$)Š¢Ò¢Z€b‡ž•ò› Í‡õêÈqHÊõý§(ŠòƒÄíjØI¿ûE¥\Íκÿa%!‰ûOQEQ%’¼‡ö_FHâþSEQQiÈÇÏMŠJ˜ª|~¡'’"ù–Ĺíâ ØŠ¢(*>Éð~sEŠÊ>H²Šl{ÜšŽç†@\&$REå„õž¸<T6©D—ž†D[²í@˜eùnþe%Ø!‘¢(*w@‘Á,TÖHÀ礳î‹HH ‰2ÒÌ’³žö@‚zì<…Cx{t/[ÀöæøfIH¤(Š¢(*% âHÕ7xÄY÷51o‡2¼t#‹õ°hreIdø0>—8´$RE墊ÙNS™.±"Jræ"BbDHŘoŠXët)ÕeU— ³>\`¾õ=B"EQTnJž« Gf¡¨¬‡D鎟Pۥ˥{Y¬‡b]\Ñå(!‘¢(*ç%½NÒÓıž)*‹!q ¿k«oŠ%hŒÌØÒE„DŠ¢¨œ—ø¬·ò0P™$ép6wÃC¢t+‹•P,†â{(>Šb1,ÆX…«ÏÚ6ê4ïƒómêHÑï DOàÜRT6ɤF£(_J†ßk$$qÿ³HåÎÆ(8­. 1¥8¿p6ÆãŽgðIƒ$C6N[ ¥¬çº4Ç8Õh®qB"EQT µœà&!iCr\¥a @Кcûï,  §Fg£ûTRå{@g¯µN›³n=t`0ð·ŒsQ¾$ºAG~oË1¯Û’k¦ó¥›¹óÌï”ãs›k›;1_Jžu=v¡}€×„õK­õª¶€Äj3³M/È­´Ž__˜mJ”gëȾ±êp6¬Ãó¨#-/T¶)‡€ò›¤AŸÍ‚ýð+$Ƀñ$êe†é#$ú Gœ3»~O9Cf ­a¾$D_ÅçY€\À‰¾+;$Šº­íø”é%óÙ¤«2¿SlÕ¯ÜãšÇtêï®k»õb3ÖòÆ- qÁµ½g³…³Ëñî^ï±Ö9jÍŸ·>»öÅ.^ÚT©ÄÙÚ]…¢R®r';†J$D°P9‘-®ÅΆuɆ‚Ž-~¯ØGûŸkØ`ÁWÎßæucQLK¬3ùå˜nµ 2áœF‚Ä#®z–XÓ²¾XÚê±Ìí“8â^Æ2i¾3i©ƒX.+tkÖ5o qÛns ¡,•{c§¡m®c/¿Ñ‚ßi¶ ¶ë™ïUX@+ zº'Ý]õ…¼´©,Ó¢C 9Eù» ³¸Y«,ø›‚ÅDÊ´ò{'±|×.,ëÁCx‘€³Ùg­Ëæð ]ŒÃ:BHŒ ‡=àªÆÙ°&Ú`·ŠõvJÃüF´>‰^ØÝIîÝXcAj®]{ºÐÚ–là²Õ‰CQW³½íu¸öw$Ìq0óg­úJWs£hÓ'‘ÊvZ/uEù€Å–UgÁzp­uƒÎFâqó`¯Æt5¦‹¬‡a‡"êð@´/ž.4Bbl) zÕ‚µYå“ÖùK$vX ä†Ä¢- ÑžWв­¡%NäHïn×ñèØ$<ö¯c‹í¹/€&w´wÐÙðÓ"$R¹ðkça ü$“Bbèáf[“òð`6ÛrTŒyÅø½y‡gÉtýžh‰˜rHw6,gâÞŽÀÔ´³Ñ]Ú—@Hœr6ûá•D¨·$¶[ûb€ËX wZÛjðØÏ²$A¢éªº¾Ûãlö—å;Á+6”7)Š¢Ò£e+E.Bâd˜cI˜‡´ÁX!qÜã÷æ ‰)‡D01ílX¬¤;y ÿÍ9—‚zÈuýÆj”8kDJ¹µ=º¶ ‰&€e- L™“fëEh uÚ•$Hlq6¢¾ ˆ–:8-X9ާœÍùZMZ 6×5>ÅKš¢(*5RY²ñB’X/ú\Vփ׎Ý…ß*Œ{°}û÷V‰)‡DyA2A)#d5¸Ž­œŸaá\çº&L´ïÑ- q«nßX Ñq6|,íú׈5ÀáŒUßÂ$Ab¾õ;ò»³Ö±›²ÀÜÕ,bcΙ‘ÒÍ®cà¥Me¡vòP„DÿAb¬Ux° Ä´¼S¸y¥Œ;]‚±Bb)~¯óGñ%$&^借pÝ”¥€CÓE{Ò°Z‘ÆRçµNP#%œ_Q»U» yœûâõÆü×üJÌw¼£’P÷5ÔsÄÙMÙ‹ïGs™º•{ìŸýýÀïœx&ߣ½N¯¿+Ø;`ÇD•KÝ—<ö¢2]%ÎÖ.+•R-O«Ðy<<‹­Xrsx˜™\sfîC; ¡ÝªS¹kÝ üÎ8ÞKNìcñ)Š¢2[…„DÊojÍ’ýÈ4H’üpG¬i S”#ûOQE)B"EC>lbÅíEÝ¥+3˜CûOQE)fQ!1¤gÝ’+AÕ9¸ÿEQEùXìnÎu)Š¢(ŠJ¤²Åÿ!!Q¢W%àÅ5¤6E¿-¿+NÖŒp¼3ûE½,AI’®ÆËçs'–˱³#n½ö-¤:ÊvK²äº´[…ãÿ<¬áŽ}Iç[ŽA%/T b ŠHHŒK&ÚzÉÙœcï¿ÔŒž#€8‹Ï^ÃÚ ùä8I¾Aç̡ޚ­uZœ¼ˆ&és ¾%+eT´¹ 3A“ǼÏÇõ wì;â8߸? ùˆ¡rô™Lñ‚$$¦Iƒà"€Xœ¢ß— ›£HÞ»«Ø–£BÌËóØNQ˜‡h>¾“ïÇ%Û¨g»xC7Cê9I¶‡°¼ ÷Ã"ê;él¥d‹ßÏ ³¯á޽?nP)Žâ|E¨Oñ6_LÝ· 5^¿c_rLƒØ¿FWÝ㱘ì´~·ÐãX†Ùsmx@b«N%Ž·%±ÄcŸ½ögÎá8¼!‘ÊpÑ'1³$½Õ4¢Y¤Ü‚pZ·³a¥[´¸²þ,–»¾c’š«ž ¯Öš?‰íu„,û!}ÒjJ,Ø^s=ðˬ‡½$zgYoÊÙH½`mÃ} Lhéú^±öÇ•qëÜ{Àež³yäÙÏ ëX˜Nìhùgó1˜Þ…cnF±­~f„–k?'­s8ƒõ=ŽÇ¼«¾rîÆ<^r¦qM¸¾3îqîL}&¬ë£×ºz±^—³ÙŠyÄÚgsÌW­¶ÂÔcÅھݦ˜Ï‹ÎÆPöèHöŠ'­—¤^gÃâNQ„DŠ"$&]-iDû÷ó, p[5KwflÞRÂ2 hÙZgcÌ`£<¤óñ]Æç€X!ú6v„±øØ]ß…XÏ”ò-7ܾM†YÏ p6ÆG®s6ÆvƒpûÓ°Ù…bCŽýb§pŒË&sÖ>˶«ÍVÆ<Ì7CAŽâ{ù€Ÿ)ÔÑÔ¥1 H\ôøp/2} çÜÀêNl£Û‚ØæÛcL»!ñˆ³‘Wtû`FÌÉ´5àóIÔǼ\«qЂVV;¬}vC¢ÂþîĶ‚˜6íNöÓ Ùìr¦¶#¦À¡(BbÌ:•F@´-*6,ḛbÂ+Özµ̇­–%lȲ¨Õ¸ 0ω·o0ä8CÜÍX׉6[E.žq6­”‡D³?%VÝ‚ÎfŸ¶ îÜã›éÔ{eÅ93æ¸ Âš-°‰äÚír6+<î3~òV8®½ qʺOÍþ-º¶)VÆ£¨_AH,±à®Çuÿ‹ª° ì ¼×†y™èðø /Ht\ûóG0=àt,€,aóLQT¦*Ûº›]À’M¥-Í€èࡸ² ±­(æá[ál {èV¡<Ы±Ÿv7hi”8Ø(ñµ&gÃgÑ q ·<'òxÏÑ@b—ë4Z¿gÎNë;ƒÎFðL7w´ø0À<Ï:'f´žHXfñË4DzÕÖk7”Mʼnfÿz­c^‹ý«·À»¿=fÛ^ØáºÿwZ×J©un ëd%¶—'$š{²Î:_•®#B"EQ«lñhv¼#Q³±¤ Ë V¸$š®Ò <üM—æV€1H;‹Œ¶alO¬j']öù0/;e®%@à @ã`Qöaë _·nkß-«—)eQB¢} Úœ Ÿ6£+¨÷$Öë°À¢Ç“z×ïÕX°g }اHÑåSXgÔš7cÔŽãoº»k­/cÝ‹5tû½èl²¬á\´`›æ<š—åx§‰Ïlë¯`ÿäšC½ÛpÞg`I,EG¬ýéÂ:-®*ŠŠFLC“Ši,Ë)øv'½yçŠ,È2ÖŸž0ëVáá9‰uL÷as¦Ÿ½ý ¾3bY™ oƒ–%ÎDX9n• Èõº ¯õ™̵Xºv@ô‚Ävg#еÈUŸJëôZp]„}™˜ôXßiÂüIÔÇKµÍI‡|ëX‰pþZ<À³Ð:£Î†e5Ïšß mâº[—ËšVmÕ½ÛÙ˜Óîl x]OCÖõoç: ZÛ±íA´ Ag#zû–๷cÿ†½Í:ÛûïÞŸk»£|ÄP9üL¦xAR9x,G"<È“%A\aN-/¹¨%À1\vÎL/D%V¥‹^^(ŠÏd*#ÔÊCÀ›{›KštO¤ð7Åri‚vL÷p/¹mAâ*À¥‡#éKí4ÅçEQ¼¹)Š¢¨Dˆ)p(ŠHQEQåo±»™HQEQE°á±¤(Š¢|*¦À¡6<–EQÅçÅ ’Ç’¢(Š¢ø¡2LôIäÍMQEñ9BQonŠ¢(ʧb Š"$REmKfhÁ€³ž½‰%á¥ÎÙ<„$E弨ÝŸŠuù™³> Ècº< ËŒÃaÏ(ŠŠ_2†´Œ-cyˈ9Š%%EÚóa€c/C*—EëWüú i\þ¯.<$EÅ¡]ºŒºÀe íõ$¦m KüEÆ¢ÒeÜYºÒ>î+º êRš¢sÏ8!1ËTІD±$òPƒŠ$khOV‹ÎºU‘JJtiÛ>˜‚öÏdŠ˜…ú ‘ñPPƒj¬—MiKzùÂé •9ëVFîKºÔó™LåŠè“˜k"uŠ¢bi‡ „Œ9©ëÚL²:Ïêì\/Y‹Άe1è¬)*É’­ÒÉüˆ½Î ¯¿úÃPTjÕkÇÑlÚ±óÞöÒ×6¾ëµ{¿íüÝœ›%»%ÝЫÐ':°…)p( ÿ›¾;vÜç0šÎOeÐNQTrÕîlGÔeÛÎýqkçW^Ùóù§^ýÑãj÷•ï{¥“Eí㢊y¼”©lUºº›h8|Ü€ÉKKJÔ¡½{UëW¨¿¼ê*–—–Ë/Wûßð•öÙ¡óqÖYg=}γŸÝËÆ¢’¦Zg½‹y Ÿ3Z@ ¯ôý7ŸsºÜ|ó9¯ùà5_{EïÈS¯ìº-,$:;¥Ù‘»\fb/g*[•ÿ‡ÓÝ+†ÿvûíê‘þÅå—““!hÌ{Ö³Bçç¹ùùâƒÃü¬Š†#ÍÔvÝJþâ?zÍŸ_û£WäS?ÚõŸx¸äúÏ©—~¤Ï¥ z÷ÛßÿW»ßvÕ‹3ÔÊ(EÓõœ(ЧË•ÓØ"7”X¬>ÝÕE0óiùöÐzÁóŸÅsóóÿÑ¡E‘¢©a€ÅHÆï‰†»Wî<û•M--¾fHýþuŸU»tyù§¾¬^ÚTÿ_×mê?|“zÍ[ßÿêÝW]õl½Û§­†¯;ôöº—~áÇ÷½ú¯úGwµ^ó€b¦Y[q.åYšˆA¸Bå,$–îØ±ã)¹¡>síµ„1Ÿ±ðPtÖ÷R•ë“ÉXœÉ;"зûÍïx÷+¯hùè«›Z¾¹SáÎÿµÚõÑ[TÙ §Êþ²W½øêAõ’ö”^þ©W¾í}yÝ›.ÿÓuXÔßÇßý?Ç–Ë>ýý§ÿøÝn>ÿ—î9üÖR³ñ9 ‰ýê¼þ¯«²ÁojHPÏ¿áï4$ªónùªzÅõŸW/¸î³¡y¯|çzw~Û‹/¸¬á%»›ßýÒ›¿vßsOüû3ùC?x¦èúÛ}Ù{?zô•—¿çw2ð˜ÌâÜÖŦÀ¡rR’¡^½a÷n‚W³˜¨g‡NÕŽâ>Ìä(}ÿÍ¿õ’ÿݳPÒ7þôyýßVeßQç LªónýÎzÑŸ7ÍÃth^ð[Ïœ×ÿ­§Ë>ý=õ?¾|·zÎísꥭ׌¾îÐÛê—.– ž[ŠòRÕÝÜ&7¤¸!xe^‘ô8Nb#ø(*e|ת3®ægí>pøÅ{.­¿éµõW\õ‡î»ÿÅÇÿQ•ôVõò[ÿI½ì‹³êe÷cõr „¯ù‹Ô+{nW/ûÛSzÞÔ+}YÏ»Q½ü– õ²a=ï‹ÿWwÛ”*ý«~õ⣷<]þÖ÷¼sÏ¥oº|ÏCÇ*kßx^†‚b9Îí/s*›”*ÿñ¿Q×·µº2°HE4€M¼e(*&9‰³ó3­òLRU[ÿGû¿ìÕõo{ÍÿxÏÇ~ðœkÿ^=·÷«Û.ç^ÿeõœ®/ªç}ô„zÅ[[ï>ðÖ?–íJ¹`ÿe/ ®”㓉¹MZ£x†geo •»8ÐÙIèÊl¿DB"EŦî¡É Þ·%W^™ÞÛ>𑳮ÿª:«J=kðû¡’7ø=uþ§¾¤^ñ™;õçºôWí¸é›ÊéùºÚqý×Ô‹ßÍÔKÞþç/²RßìÈP84šÆ9Ž'È+!‘…HQ9¦FÜC'²`_v¼ªñý;_ø¿®_xÞÇ>¯~ëú/©Ü0ª^Þ÷ªtð[ªø¯¿· $wÜümåÜð >뺯¨½ïÚ>ïò¿øŸY4TŸhç¸He‹Rå“HH$$RT.«ÍÉ¢œ£’¢¦ú-w~ö‹}iæ¿Ô7çîVS?ÿµzÕNªgïTgÿ§u0ìÐpøõJy^ççž*}×_ÝöêÃ|a–¢h(í$!‘ÊI ‰•óm “ÚÜ´IÅμïj}í‡ú§ÿö»?P“‡ÿsN•ÝöµÃüî;Ôï|xð‰’÷^}Ç«/ïŸî9üÁç8™Ý­N½ h'™‡"$²“-]Ù<]J‡¤ü‰Yõ¢ÕÙÙyÖÿ»ç¹µïxÏEMùxÏ_|òÖ±÷ßò7ß=ïC½w¾è½×Ž–¾óý¯yË»®({Ë»Kvj8Ìà79{ީܻ›Y²;tQjÝŒ¢ ÔîW[õÆ7¾ÚL üîì<»sh(ÿƒÇ¾øœ=<öœ’+;óe\çÝ»w?ûõë+2lB"E9 \aÉ2HÔ•¬Ôe€(%Ƕªäûº”ª L[B ’!Âó/mxõE•8ZÒçì9xxâõ>çxK1EHd!$&WuYÐeXǶÆ,Ø”²¤Ë¤bRq*Ç Q¬€U—Ô¿nÏ¥‡ïÐp8¥Ë_ï9pø³¯;xð{ÔßVyàð´Ì{Ãáÿ'ë^pàðQ=ýý=}íOêê^´ç`ýw+÷¿éõ•—êÚ}à@Ñžƒ‡>¢¿ÿ]]F_wÙáÝ»wk<ðæËô¶F/¸ôÐ^äJÌÅsÌÀŠÈBHL"$Ö‰Õ0§âñIÔßÁ6ÚtéÖeX—]ÖÔú Ñn§ÙX4é#IHÌÀºïxí%‡‹5ð}çüºCo¨:pøÅ• õôö\zèÓ¯;pè½{þÝʃo~÷}NÏop|ÝÁ?{AÅÁÃ/;pàÀ¹zzVÏÿ ¼ñÂ=uõÿGä5²½þ‡ô²ÏV<|PäðžËŸŸÁÉ´ ‰TÖ‰>‰,Ùê“8¯ËbœÛËáªk^+À±9Êmcý1L72¬_õ“"$&ZÒ½üÚõ¯«ŸX C–ÂKÞü'{Ñó~ðŠÃ‡ d½ÝW]u‡þSqÏe‡ª%¨%4œßUW=[Cá/õºGv‡€ñЗÅzxÁÁú·êm|}Oí¡ 4t~P–.»¬0ÇÏ1!‘ÊÝ’HHL!$ ˆÍDX.‘Ïeea–çî–uiÑ¥^—j]¦mK"æŠÿ¢yâǸÓù˜®ÄôQl·6Ìï6by+› B¢_,‰{.=üÂ=—úžÀ²@àp†ºëôôÕ•ß^yàÍoÖ뜥—]VyððD奇ÿ|ÏÁú>BéZ.Ý¿ÿ †s<ôÃ׬UåÁ7wi˜üŠ@§ÞFuàÊ+óõò¼þÒ7]žá~‹‰8ÇLCc-ÿ9:ÚF¤2qÛm ¤û¾ÿýˆË½êðùë¯Wÿýµ¯mkŸ~sç„ÄÄâ&ë]˜uzl_Ã0©Â”&k½n;@à)ÓC˜®Ñ唉²ÖÿƒX^¦^íX^å¾v¡[¼ŒÍ !1YÚ½úË4Ì}낃õwêÏÇöÔþÝ7Ô~¹½/…|50¾þ@ý+v>üÛ•×óÿYÖ_÷I<ôÅ êÞtHO÷Vî{KÉݬË4(~åBЃo~‡^vé«ö^ñ\žcŠò2ª»YàëÿàN—çž{®Ê{Ö³6Ík½âŠ„ÁÑGßû^õÎúúˆëÈ~ýöóž·©N2OêÕ~äÈ–¿!ÇDÖÿñw‰­`„uÄ8ßÅ ålã€1€®æE”b¬w땺¾×…é,­`óýftk¯ÁçqË+£Üבxt(D4zÅáÃg‹ïáùo|ãóañÛ!]ÑÒE,óä?ò îå2O@Ræ 8Ê÷_·ÿoI´Y^U{ùïÈr½ÝçˆÅÑÉì$Û„D*ë”Ñ+o=p fÉ‚#Ù¶üÆV(eÏ»ç›ß Á¥,»öˆøý»¾ñ 5>0°¥Å’¸-H¬8c6ì¹,w6ô™™|L7Ù>‹ÖúÆÒ(V¿5|®Ä²EÀä8`Q©0©0°ocèâ û[%踵`*Ø4 ¨´œc¦À¡‰©‚D/±>^ßÖ¦n¿é&õà¿ü˦å2ýå¾¾È}º«k“5ïÛCCêϾºø‚ B·H4eÿÞ²2ü·Ûo•|á êØ‡>úoC¢,“ßuoGêeÏ—zËþÈ~Éþ¹SÖ•í~å–[Ôñ|$ô9Ç ±¹ ‹ã؆éöøà“xÊö)Ôÿç$âÙúžé~®ÃôËÒ(VÃy|îµ»–á¹úä7-?ÉQü—hë—u°'ÿk¶±Ï}Û±bR„D*áç˜+!1(ÀõÂßÿýè½a÷nõüÂBõò—¼ä40 Xí)/Í—å²Lºˆ?síµ¡å²L¦¥û8ˆF‚Ä¿»ñÆÐr5S_Ù®é’~Ë%—lênP•ÏnFùÎeÕÕ§-RWO©·ÔMöSö×¶€þéùç°‹û¸çâØÍÖˆ-^eÒ¤²$®¡KºØ‚È —¥±À †™Ä²qwW1¢²çÃÔiÒµízLOcºÐ¸Š®ëy÷¨3ͬsÒµl4’3Ç´ÒÀ2‚â9&$RþWF§À ‰biû£½(d4V6 ùã—¿<4Ïø7Jl+›€Ø«^úÒ¸»›í {¿e[2- *õ’niežÀßÕïÿ&+¢,‹§L J99yz_ÅbùÒ’’Mõøp”߈·+;!Ñ›€›ZXkí\‡VJðšsùÊô2>›`˜˜6þ„&RºØ†>º,Ùi}¬í¸¶g¬œ…øÎ¦«´s€à“X¿ËOw]@gásY€yE’ºË c8–‹*w‚„DžcB"Eyëâ¾TB¢D8Ëï¹»nÎd¾€“t×Êg N ‰/$À³!Qà5RàŠø2Ú *õK¡À ÔSÖ‹£»{YæßùÙÏž®÷V7Û…ÄN½ýO:Î}ýŽ3¦K0è8Gtc¨ÿŽ;Nig'‰FDs Oº¥;¬e3–¥Ïµô`ºÁ@!tÚ†>ßYvu-›íõZVÈÕ0ÖÇb«ëÛ¤ë)żL/ LÎZÝ䕦+Üêò6ÛÉL6à»-^©…¤s„Añ‡SàP9÷Õ’ß,¥ x \Ù‘ÏÒõ,ó"ºŒeOŠXâ$ÙÆx!Q ÍXM}Å  ð}ÿoÿ64-PÙvå•¡Ïâ»(Ëd?ìý’ý´¯Ì W§X!±[oÿfÇy@âw5¶éÿ]ºœÐeR—y]ÖtYÔå¤.£ ûôÿv]ôçª £oe¯Ú­yW]Aú<¾oº§ð&0ÝŽå§wù¼-p´€±0Ìö•8#È"kÙ,,¥»œbœuY4—,‹j‘kÛŰtš€Ÿ +˜§(\¾JÅsLQéSOòQ=è8?žHŸ@+w1]µR %¸ãÐÞ½!_A0“³0^H”ncY.ÝÎÑB¢ñ9”T>¿¡D XñÚ/Óuž HÔ­žz§†B {݃AË—Í踽¬B—:]ZuéÑ€8¬ÿO$•. ºLë2"Ëe=½­ú[§r0Ç#ûu%áÒÙ ,kÞŒíshùQž€•Ñ@ç  2K0] h¾+/ä’«Ü,[Ào±Ó²hž –{ÔÝmE6VS NÛÑâÉ&ÿE!‘¢2NIôâC0,<–JH4p%hÏø?wCÓm¢™ãD6±ðÙP-$J´µ|·åòËÕù¯|åéù·LãN«#QÒ²®±‚&_/]óŽó=9³·jÐp7#]ÏÛ;Y_,‹°0ŠE²Àx–H  eJõz-žò». U‚d>| KQZ-èË\­YÀ7fù6Y7M°*t%Wáó°GBð* J±Ícm´ÒPï{$ýʤÂï›\‘ó@Î[߯Ã2Ó Þã0ë×ëƒAHŒFLCå$ªb]ÝxN=ú¨“âèf+éª5ݶbÍ“i]&òØÔIºŸ¥[7ÿì³C>‹&HD"‹Í6ÂAâ@`Óˆ+âGhk Àm0MdµX9íõÅâ)Á-&bZÖ•}’ß3*É€D9¡7Y#“tê´¶ oK |ðÉv¥kZ|ÅZ‰.ë |!L—tYÕ¿9B×÷½~.»†bªÈ24Ö½e¦{[á¿Éçh"¥Û,«ã*,ƒ…€³) T›¬¡·%F¶‹u0=oz0=íJd 2epØl%$7ÀYlá¬<‡mhÅ6*Qò ‰”OÏ1W¨œ±$¾y½«Y­:ÎÃ+©†D'“F€Kþ  ÙÑÌ…²Ì,—®fÛú(;Üôas šåvˆ˜³ÓÒlMŽEV÷p}2-Û¶÷Kº§Ý)p ‰ò;ŸÒ'ò¸+÷`k˜_+æ!‘"$RTz'Ò;¹¼þ_”œ8,©–ï=ëA(½áκXè”2™ ÑÌâß?ÇZñ{DPN؈mÙwøQ2bÛÃ2¹År;c… âvºò=º“Ž]£Ø˜Ü”uVPͤõ[5ÆÒ‰®rŒÓ PNfÒpB"!1Žm0wcÜ¥|oáY{Ý7!1³!ñOçj±¼E:ó뾊mðUlÉôûMº×%òZ"°="¶¬ˆí)Ìß±}<Ž¡³°í2>ŒÅÈ¥ÀtºƒMä³;éx¯Õ\ku,Kâ‚•úÇt7YÛšC·ôIt7+•ZÈ'$)*élµ•6" ˜„8n+"!1[ ñÙŽóñõ‹ÆŸ/Ó¬ŠñHöÏŽØFŽÈQ+b{ͱ-ÝòbÁdĶg;Wk`••Vd³ñA4Ùcà´å{Àpˆk®®ìüF*_¶ „DŠJzã™gùö &`“Ið8ÊHHÌHtÖ?új¢¹ĪëÛ¢ÀSgŽúøuZÛ¥æh¸ˆm½lB|'áCɈmïv°ÖÇbDZç£ z]Ì'ÐF–¹,‹V®ÈÁW›AHŒFLC%{ý‰žVDBbA"òvl×Ò+ÚôÜÔf‰uÖW¯ˆíYDk/#zûŒˆm‰öJOj—t·‡Uèn¶Òå˜Ñaò¬6ӤΙH¦ú……HHL“á†Ê•ưß….Pìò$zY ‰Ù‰bÙšˆåê@Rì¥\¶*Æ#;b[º«‘2lĶ1›#¶ÑNZãI/%è:Ý!À_…õYÒSjí¹‚©´5„u–Ÿi g¬éÖ7À8a­ˆ„Ä,‚D±jÅ ´*&Wâßh†F ±­à'i†Fܱ©C#Âÿ° ¹ë}XÅh¢ÚYÏï¸êxä`eIKÖB"å·F¯Ñyf¤€f4€Cð«™±¢ôTúưVDBbA¢œLXª*â¹ZÄ߾д*¦V‚îˆmã´±=ïŽØÆ˜ÜŒØN $ŠÅjÔ“5À‰ ؃ﳤ¦ôâ¸KɲuNd^A’!‘)p¨¨q§5þêœÅ0ëîºi¬q$+"!1Ë ݘ­ñ^5+&xC¢|yçûG&bÛ ¸EÄvhhDFlÇ ‰ÒnÎb¹@‰ È@%Hºý貂ó#VÞ¼$B"EE Š¥°F„EX—L"Úm*A)p"Z ‰ÙgIlè·FˈW¾X¢U1sd†F ±½ihD¯ˆí1@„œÂ2±"1ºÕŸטEœ§B"åP,Þ ‘ âdŒc‘&ÀÿaK+âé›ç؇>DèÊÀÒzÅ› ~…‹‰¼ÖiUÌ>yEl ,=#¶6,‹Ø]˜/ XÀ«Æ×’@¢5”Ê$A"_¨¨±>‡ma,‹ÁüL" q++¢¨]Vl»òJBW–C{÷H<í¼-]òOôuîMº;Sºä E²Ð &b{ Û¡¡½"¶3åú^ÂüÊþV¶'~êvIìt6îûÇm€ú±$A"W¨¨!ÑŒoZëšo`1Ö–8/HU…Ñ\¨‹/¸€Ð•å¥%%Êý “€†$u« BW)foIìÓÊL‹d±;bÛqÞqSĶÑ'Û^Q‹y3 ü]º, m—ñ¬ÅÇñ¤³9بÍñï}%õl<îNŽG½ ´Ð‰¯è*¬‰Å„D*8‚„°ÉŒZŽsÛª# +¢¨hÇŽOåŸ}¶úåä$Á+ƒÊ¿Ý~»Ä%ÇòÄÃ:©£V úV‚$zhU¤"ÉŽØFJŸÞHÛÍ–dDl‡¹V½¢Õ‰ì㋦œÍ9"ó`õ b~†ÄDY•“X‹ó¶YCH¤ÒˆeÈ…¨Ð½Ü­|í²".FaE ICâWv9grWsŸ}>¥‹°="3©¢U‘J„:­¡="¶7 è±½¡õ÷î×ëßâÊêf^kwUîÉ#ÖEóâú#‘ºãκ”f€¥€dÀ쨳ž1cÄ”r ºa¥vÖó:U`Þ$À7’õN¬¨£ø6ëÔ†DI9cŽaU§aÔÛHö·ÑYï žD[Ulí¯Â~$*/kod *¥ Xˆ¼ˆËVíÿÀbÈŠ8´/H÷¸Ê{Ö³ÔøÀ,ʧ»ºB€¨ÿqÇÃÒ"A©SŸyy°§ƒ?•yEl[C#†Ø6C#šˆmýY/_ÓÿÑå{’ àÜ _¶¦C…[E«ëÆÕ›ÏNvxÐXŒß^Æú–åq ؈õ ¸¼°lVºl§Ëd{ÓaêXç¬÷L4â7fœ‘ÃÂu7O¸ê´lâÀ· ˧,Ëi¹³áO¨¶ª#‰HQ[¡¤´)±¢—ݰ˜ÈÈÏ»9BVD}“«í.„Êß~ÞóŠ>/Ÿ¹öZ%îhôŽ„7yxÖ¥ð!^ Ï|пÝeTËDlKIçã±-C#>Šîm¥—?#ÿoÖóÞ ÿ?ÛqÞ‘¨¨Ì™”-'Í,6ˆ59›»8Åê¸æª6g#Pc–4³¼€X `¬h8áƒf&±Mû7#@b9 Ð~9\⣕ÎÈc±Ò juhˆC™QþU* 1mú ³ùžlÌåyXòÜ(À¶êlŽÜ5~ˆæ»6àÉsI¬¤•°î@-À¾íò~¿ Y7Z€ /H4]ÙöËà°³‘]!H,Kò¹$$RIÄbÀ`.Õ   qL%!q±³í8q[½$’tq´;=(üË™]ÿU ÞÙf÷­XÓmɃŸXº kÙšP9 ‰"ñ”îàg£[vÑÙÜõ+`· xtC¢ƒöØtOc;¥Tšeø-c-ÁºC˜Θ Ðw ÛEý*"@¢èêlê4kY·‚Ä“8õI<—„D*% 8®K.í VõÿA•ä|ti°"fãÙËÉ›[|û×?íB÷7­ŠT.C¢Q9`I,|nK>æ;A'^/ïá¾_l-sµ¾ ˶²Ü™Qa®ÓH#®…ù]™_èÚ¿®é*¬çwHd *"$šˆæVX—ð¿ÞµK†‘˜ù(©iÆýRŸL±*Jš.GUxç~ŠHeιäù¤’úÀ”7MºÔÁ±#®Ì«äFncÛ´"Ï’]/û­^’x)IFgAHÔýÄËŸ)'Ô™ŠH)b(âaÍz`Ì«ÔD 6´"ÃK`ìÖÄæïLˆX#Ýá‹A_XãOßó;áFR†Œrß·ò"$R9‰LCmzX Iö.º,à¡!ÃðµøiE$$†•ŒJ\ÚË—ò¹U± Èû‹H¸Bmz@ð€¨ÀgÆ"XOúiE$$F– K6°9¥…ïäG«"î{“<¿÷!‘"$òðRöCbcxXt`¾L§" Ї¥j£‘¸$–õgHã¦ëY¡ËŒ.cƒ)ìÚ¯±ø÷é2­ËŠåb2LŸDBb ™L©,Åaëa1„â—ˆæ|]hE$$F_‹ƒâOÓ© cî. ¤ÀŠƒ.åyë>_Dº«F7〠¯‡á$–êJžßC"SàPg<@ò0ÛX$ˆ¥Û'µk¥‘%$Žö'~lñ¤J‚mRaUD·ò,îï¹$ ±Iå$nÇ’h'©¦ü ‰öA’‡I*ë#¤À Yu)çÙ!$F‰­’Ÿ0ÓêÝ™"«"îï¼®bñÓÎæû¡ X ðS.¸t¼{©*hk;Æõ"èœ9ü¬»Nö=!õ™ÀçÔGà·Ø£>MØsœ¦“p.‰ \ÉaHœA7“8­Oú¤Zá ‘VDBâ¶+\M2 *•û‘*«b˜}=b%×òÚwø1ŸôO€åH´Ÿ+% q°6o±µ€¬,ÌwŒ%O~gѵ¬Í8·‚ø-ù}±þUlQ§v«N% *0(]â&à#€uíí,Zu”ã4”„sIH¤ânü›¬±˜{œŽa(LCµ<0´"c†+ñíëJÀ½Ràšn8 ¦ª+¶ÓeUìLa0Úƒ™pi°àÏ(íÈ4ï;Bb (€îÈ—à& “ïº-Û Îz·q `Ζ´‘ò¦Êý-/“#C™Ã>D['¿Ñ 5VõJÔ'/Ây $R¾‚ÀõyþH‹.X”yc>©1­ˆ„Ę$VÄþ8¬äè†P.ÐD ™1Ü3-)Þ§Ù'±,¤0*ÖÂ"ùeh7VÝQÒ€éÞ‹„DH´»n[0m^ÆŠÍÝÀn tA_5@¬Èúz Å—°1ŒQÂö3”îá5lG`oÖ£NU ±Û[±¾—ïÙÇTüÇ3™'×¶.Œ×š¿Dy¶Z°è§¼ˆ´"c’ø#j˜ZíŒÑêfYÈ- j1ÖÃHÖµdK¬‰°*¶u¦)°íÇ´×-°>®¡MÉçýHHtAâ g#XE®_±â-þ×߇ìËi °ÍÈŒõ¯Þõ;3X6mzÝ#ù¨ã,ê³èlXeý1ëû²¬/BÌw°-[ÃKà ¬S–!Hå$ÊCnÿçð«sYN¤:]ùå\ÎÅ´"ã“D8ßcÒ^øà-ZPhF$k{†­L›Å=]VEëø4›nf»Ûð8“K+•VH´ó$:›s&æ¹ J¦+\ëÈ5p6R娀éyX¿ÀFÅê·+Šz›íxEòn·NEŽw°\¶Sål~i*tâO3GH¤Þ¸Õp,¦QØÐŠHHL$ööǽ/IäѺËJ2¿dr¬)$†UqQ—öÎÔú*.à8ìrÍïÀüI^9‰~Ä\?—‰:ŸL“ƒ€xÚ·]BnXLçPI6$ÒŠ¸ý³«ßÊÕœ.éò$þÿû:pç,$6ô¯;ÆÇr¯”¸Æ4–´º}ó##´ÈH-b9½5EõÂñXpÍ+·t—aÇó%$¦Jr­Mò\&ì|ÒØƒ(Ýɽ »Åt>øpAÒŠÇÒå¿À4³ºtäòÑ<-Åq¿”#HeÑ̾λ(£´ÀW±£3ÉVE±¢ÍhÄtÕÍ܆yE°¾yo)B"åHÇ›~©—å$ÍÕƒó1­ˆqœa}^Õý€Ät)Ìõ#¢¡i~ ‡Æ'N•UÕy«Â|ž°Ö±ÆˆžDW4Gp!$R„Dʧ°ãÂߪ#°øÀJ¢ôD-Њ×1ü,º›?Æc‚Ä9øà³­ŠCIŠ0–|ªäYE»2nr¬J†Ì›GF üqm£ðHH¤| ‰L“Cp˜‡Ñ:•¹æòµò‰åN5ÑŠ÷1kâ2­ˆë :Nsüi&2‹ô¾è2{KýÝy hgvYó%ë’5m§ÊáõJHÜ®äšNÅu#¾ŽåŸ³©‚Ä&*ÀbòÁ•¤¿–ç܈À ¿ZkpÃe@ywgæÔ5Tª’uҤ˵=Z.ƒr=" {†R·=ÊÎ# p”@ 9 ,g8œ!1‚Ž:‘_n¼†èK†ìöçx$.0}„DÊ/ØŒR grã+TåŸZ6/é*ù52­7KrÊZ2AQÃÑò@üùȤ¢ÕiÌ#—RhU¬µ^BOYy& 8v`ºÓ#l¡ ‰1B ¤hIEö í|‰Ú¦_!‘)prKÑÍ3ã“éɼøÑ|zÈÌ 7ŠÏ,‰+“É~8!£.÷t¡.gò½«â‚X'ØÙÕÍ@dó,ŠÂÿk8¿%•x§|‰rŸIÄ{7îm$¡È5mûŸÊËስÌ\“2þ± q7ŽmÊzͰ¾`zœ ´ë7F,¸”ß‹ä¶)Á»½Qk6ÐI=Ú­ïT¸êo_ÏCX>†ß7¿-u¿EçŒA$|‰ \É À¹ü¨Ë?¨Ï_¾ˆß[ͰF•Êc+‰¦û]1ÞKÃ>H·ô“«Pü4%ò;˜Àî:Á ö`º#²Ì#…P±k8¿z¬×ˆy3HZ^ÀÛ"c!±p'Iì« ¤L7[Àµ ¨”gÓ ce€(ÙN êµ¼þž‚´½‚]Ê"l#$Š¥ÐíW¸86pAh»Çv‰TZ±P´œÄ;`AôQM›|ì‹HHÌ‚c+Á†Vâ!¼`eÕ"ɲ*†9~%v73¦×0mFh©4¶óÖH $¶$`ÛCQNKÓ`Ä”5«^nHœ ‰u€Fî× ìÛ¼sf—°Qu„m„ƒÄI@­]ÿU«þò›%›o7§#ÁØã0cƒ\ƶ]ÎÆŠ(Im}ò†`¬ˆ¾õE$$fɱKbÐc-ûU°*ÎëJbZdZ¨ÃçF7"«ÌãYIé=׎yÝ)„Ä“Nd«|´(eѵ¬Â´<Àb#~sØã·"m#$ |¶F¾Ü“‰Ãø>³¨í6Æxk—®›“VT¡ Áç“7„MVÄNÞp~l5 vר©0K«t=£ º6m”I¸}Äšgºôû0]‹ÈèvæRLê=Wy)„Dió§ >é6Kb©5Q@¢ôˆo`µ…³§ÎfdºqzË6–Ãl#$ XŸr6z(Wîò­ 1Ïá9üNŸYT,p‹åxÒoµÖµs[ýìÿÀ.íD7÷{?qŸ"h£&NˆX\aUJ²U1A-’L» ¸b'áÖÿ[1o‘ÓU¼e’rÏpÒŠãÜv´X(•¶_F¤ëÙ~‘;pkÛ ä.c;NÃ= BYÀwÅ:-ÖÂpÁ"á¶ó±M©Ç¾Û½ù ‰•8Öñäp­Ào,$©]e œÅ8„+øþøÄéþ _DB"XI|ïVtOjz­„ЛÆ-Ît¥Êªˆ@—Wp]²C‡æÃ‡ñÚ°|Þ6I¹çL×e0ŽmËKEÑ6¦E»{n8Í9Þù Ýy @[ù€²*gk¿d¯mØ¿íU2|Ç U%Îæt?EÎæ—®xGow»0p…ÊhtõòEÌvH”Æ¢ož“ÎF->°Rà’HúÖe !´rþÙe]¢ Ùvr`UœÅØIËiê*Õlõz(Àa`r¹vϹƒT¤›w Ëêx˜|­Vœ§eÇÛÚßCH¤ì¶!³Þ®=#šý<4W"@FÞÎçÐ07áíoÕa0E*!18cô¦uk’Bqße}— ¢Ã{dh¿` îSD=‡,³èÊoˆ+“™óÀ‡±óòË2×ï©­)HÅÀÇ AÑ·jŽæÃ´sh<á¿ãsX̘ˆæDƒŒ 8n7ŠS¬(Ò½‘fÚ–<wàÔXËÛÙͼmÍྫŽbݼ¶ã~eImiËz´Ÿ#8·£q^#•¼M²M>ÄRk^9ºi¤û¥Ü'5YÅœƒÄŽwלD>ZHlŠzÛYמn‚EAº•aYœŒP§¼¡ÊÛê„ \3[ûcô+´^ÆØêlH"Æõ1Ñe,VÅ#hëZ0½ 9=»™Ñ=]‚héÐ¥W|ZœÑ&ɽ×ËC‘52Ñω°³ «­7fS|E¼¥ÑïJȈeÐ…ÈÍ'¾|¶õI¬¾âk8ƒß’ÆÛ¸ Èg{Ø7÷ôð6Öµ§«P' fÂôê[îx§ŒÉ$VûäØnK^&bED,V¸·Z‘@{óG²iÄ•xA\ß6X“ÎHKÔ.šYæ£zÑ=<;›dÆJ^Ë)•Ùªv6¬Ã‰H[4ÌCšù`X *LKWL=œ»üÓýµ¥1 1›T‘À·Ì”[é z'Žæž«$ÁGqѵbÁç›÷æã\«âd0 ©8à`€>íãNä]ÜÅ3Rî?y9-àáÈX Îá\¶ñpPƉ~ѲÎø3ê2j+b¶§ÀÉIô󢓸1ÀS~l5´T÷Çae‡ÿá4^Ææýg¹÷:SdUô8G8'Óæeɶ×ì±¶EZp!]• ìÉ<ò ìóR§#šW»mÜ¿°µ1Ràdƒä\Ödò±=®Uø%æÇxﵺÜ:æŽ%¼<¼«â¤.S)èÚ´nïÂt­•¬Ãù­ÐE ¤2¼øÉ}$dd”¤ ù—¡D¾ôЇ7Ã!Qœ¶OXÓå–“ö¨Oj¹_DBbn*-ÇV"œo‰±„_¢ÉIÊ!˶‹-°*¶u&Fà«x:¨EÿŸÂt¥µN;uXK\–Vp/N8¼®3ArÝš|—‹Nâ_¾è>“Á€Ø„n®SîÑ‹>qBÞ–/"!‘˜JHìˆÑwÇíë‹{®Á+£<¥‘%þ‰°*N'ÓªÿìZ|–örÁµ|Ð ŽÅÓE9VÕ<$¾•¤-[ƹšs’s3Ûü?Vó¶#š³=å£c+ã÷Çt„èAàŠr ‡Éîº(”*«"ΗÛ¹ ÓUðO\ ×v"8© ¾§µ9r^Å‚hRã˜ñ¼Z}#1ºÌXçG"“pDHÌpP,F—Ê&XôQ 3=¢9Õ #oñC®Äo¦ëáTš%Çö ×÷Oÿ™Cnçþ3£ $ÃÇiD¶ëbU«â­I £®,ÂqÊ `i³~“•Óö=Í«£´7’,Ù‚IÙ%–w^ã©—d“8ê‚C±øIòï2N†Âa©¾Á‹™è‹HH\—l{ÿM‘ß]rbF.…Õl…D‘“ùX»;­1„黕É(-°*vt&é¥éo‚±E,‹0ëÕZ ¸»â¨ /¹””»÷§ ‹RÄÂ4ŽÙ.g=j½‰%!E =Ý8¶ÎF÷¿ ‡²N>[ Ê«ñ:b½OÚ`±Ä'5=ƒ1×Sàȶ½R¨4xÀZ>Þ.wFhÜeyA˜eò+ óÝ]ø^ ö9›!q¨?Æ·qäK\s½°ßÄ.¶VÛ—Œû «âÌ­io¹ÐÆ6º–U˜´:9vj Ð y@ Ë–¥5ÞmÌÃPPK8¤"5^&qï„5v©ÅFb F+b®®„ƒDÉGhé,égÄ©|ÇlÌj8†0Û’ïÙÖ’vÌ3Ëì„Ò“ÎF*…qü†i vf#$êV·¹ý˜ÅzO¶âžœvù&®*6æ1+VÅç´6RÎK“›ÖšÎEÿÓr´CrÏÅ=̶<°¼Íï´ãØJàP:»÷ЕaØ‚‡O!ººÆŒæÁTNÆè‹HH\?vc!³âl$®–7zipÌñ•Ôj‰² c%¬Ç›¿¬W…ïšF§Ë-HœÀºbm,q²Ü’(]Íë@ë=9jÝóôMLœ`UÑåÔ-)|Xéswç³Ùš×gº˜1=d-kÇ‹z ÏæªÊÔ®d$ö {«ÒDXŠÃ'‘Á!+â\^©†DézŸÅ´ µ€FÛ‡ÅX $º»íeý Ìw;"Ûó&Í£¨d=$Š$xåxŒ~…/½‰€©]`ÝŠ¨²ÑG']>‰âB°fý®Á¶¨È¼Z ­eE¨·XÊäAæ‚L´/Ç!±]kÇqO,¬¹Ò¥Œ±ÅJ¬ReUD/I+Ö WŸ5WžÅ6klè|2µãE~ Ë™/“ÊdHd œ †EI{ù¾ü2ºJo úßñ$8.e“#±Óv7³²`qA-;]Û¨¥U‘Èc@åúM+¢XË }ºƒ™2,ßÏaÛ—ÇVÃÆT‚Æ©…obàa‚mCR/öB亜¦hè8«›ù$òbæ™èvu ­œ‹ÓþÉ@A·”<‹™¥Á÷—ֺôÏ–„ù"Îùø¢$$fñ±Õ€Ñ=pfÀÏvîÓø®¹}[ØŠ%_©°*Z/K¶o"懃Ġˆ+¸6:hU$$f€ÄÏ}œçÎ߀X‡ÆhÓ•þ,a¾ˆrAÖdâRY¾ý¥ýØ2Æã¸WíäöÆ7‘þh©};*H,Ö&±].±SŽaú HD7µTb½Ië¡U‘ègµ8é–в!2£«ŒG,ÿ—€jH`D³…Äf¼…*/XôI-˓苸àà7.Bb|’ó)Ö´¶ Ð.³Ž^€¤»y Æs ŸÄEÜ»˜Wƒ.Dú$úH)¶*.ErBïÑŒW=HË€FS© @"åcP,D×Ê ‹>ª¡X“Y?š¹ ‰ñ©ÇÂ'tù© },+ýqäC:” ×ý tV¼Ò/±*Ju}¾—’x_#x¥/‚/b»•Þl—5¿ ó™Ð˜˜Jõ9tñ%æ¹Se XeǨOj*VÄE]rÍ_†ŸîÆñ»F—Ëtù™ßQ$)pú­T&qÞÓù6뀻Ȋô7ó×9ŸÑel0Å/¨ˆ|6)r,?F¹vŽ ‰iX¼éèCHlBC!oœ¥®ùCþÉ«•t+¢Q¡ã¯ür„ÄØU†c'csïõ+ IRíXÓ¥àÅ®yW]©pfq/7ý¥Ný’ž «¢‡aÀ¤Æiõ³è‘B©†gˆHe¾9+ºmip¦ý“<;¥VD1wûi bBbìjñû¿" q¼?Æ4SxÐÛÃóa:)g¼ü­TZáonr'š$Û'Ðþw#Gn5Ï !1E¢ß´ÁÿÅ÷¤o–M,*åXK™Q$– `)%$f¼&œ3ƒT|; ‰X”‚ë£ Äz_K°J¡kž•ƒÑª>WçºU± VŤ K_Å!×}C¸NÖ¼äàÏGw¢<üyýdˆ4 –éë`Z—ÉXÓ"Åp­ Ù× ÑtIÏ!Rz‘£¶,“U¤„çÊ_8äòWª³ß}VÛTZHýÕm q È]éÎ$@ɸ¿ðKÌñ¾Î‡5±ÃißÄÅF8£Ô™"«¢Ç3¡Ó=Öó!î rõðì¨Q<ã(‚¢y;´ý˜0ß'¦ßœh¶Õìxç÷c‰®d i(89c~:¤ÁQ®{ºÇNoBe–l«âñ$ºÀÀ}Át7[–Ô ô@ð¬hŒ‘´7ôIô)$–bø½rkè=Sü2Fs:¬ˆnùÁ7±o[,Û+â6Q~Tzû×ëë}Ý…`´B¶rY‹-°*¶u&顊<¹Åø,Ïa¸ u ¨Eæµcy-Ü’ºÙMH¤²k0ÂJ¡5¯ipÚ|RK?Xå·%|¯*EX×ï›Ü¤”Ÿ„1¾'Ų8`$é1 kbžU`)´¢£•5è_J‰ÑJ\ÚJxnü ˆö ¾Œ·DÞྰ"ŠdIq¬e—•twœâþõ¼Žå©Y‹á×jž–1a YhœTö˜<œ˜?ñà ‰vÖ»™)b!œOÀjhÃbp«ÁàSXS¿ù"Š%Q,Šô RsÁ$¼”0‘vöH¬ŠºL$Ûªˆ‘{­nè>w´¼A¿dÒä`È%Å Bâfõ:ëø,õ)$6áf.Ä=nÝàRÊ}RS¿Xm•ò ¢R!ýà ®û¡&úÞ_AOÂå¬y¡h‚U±£3^˽Ěg,Ž ˜®…Uq§" 7$±3Žï2¨Pö Þ‚›¹€ØŠùsþɰ¯4Œ©ŸG4Ó"C%èr"÷»Üçíx°/»üÈŠY"¡EFj‘[nMÒ‹>ÒàTXÏ ƒ˜Ãz…ÖXÐå<;„D—è»êsH,4y®H;§äUY‡|hE´%]ò’V…–E*)BÚ“ù8îóbÑ“qŸñáµ×MÒ¬Šâ[Kt"šçƒÆ]i'Ö3ù»0½ ßåh-¹ ‰bP¡?¿¡P, ½0ûO¹’fOX“>©±X—2 /¢$·]p¬!¬(*‘’‡ýñó;ÂLážo2ïáÞΣ›½²­Šý ŠQ®!X'Gʤk”–Wîj+uŽf3ÏPNA¢¼8[0HÅ稬µÞZV¿‘^å›dÃ!+b¦8:K÷üœÃ®g*98Úcê%ÜÛ«^@ˆ‡{|[y¤³SAÝÖëëgQ—ž¡µQ⢀gÉ)ËÈ0Še°.®™H˪Xmù¾·ñìä$ŠAjÑáùö=$æ¹SVm(„¿’OºN[3ÉgNÙTR„!Ùzã¸÷Kñ?9îÚᇼbµL´›Ý×P‘¾†Ft™½%A™+Ð}< 6ø"•š‚á!×]­5òO,Œ§,¨¬„[Ä ¸d$ŠÕ¸‚Ç?3@±7b/ü’ ,ŽãsÀ'5Í$+¢—dleñáe‘Š[òPï_Œõ¾¯BwàªË7qž&E¿ÚœP2¬Š×[>^Dòáî° ¢z`X ˆœ±‚©jy–2庪áñÎ0Ü…|V=¸ió¬¹Õ‚ÅiŸÔ8­ˆn‰ÿ…D¤Š‰]ºñøfLŬN}ýè‡úÊñÓEX®&³Pk„ÏØŒ * rGbUÔeX¬Š±Ž ¾k¯Ä¼2‚éfk1륅p‘¹(p(™Äõj”ϽÌÄËñ$æåáÆµa±Ê?Éu3ÞŠhK"G{y%RñJ†` ÆøÅ=_ä1¿í£Mskõuµ ÿ÷Ob¾:D@¯áå„kÜg3jË,Œ-ˆÈgz”̃ÄqÀa€Ç:31¾"‹HUP\´Ò`Ôù¬ÖÙ`EŒ¤Fg=üXËx•RÑJb÷@‚F¬°º'ü•8ŸJµôy¡$l—4KÁ$>ÜñB2ku7Z]Í›º™aY\àË‹¯!Qž_ˆb»н*à ±Ö•ù¾ÒrT?‰··݈YeEô’Xo%Z|œÍÑ^%Îz)¾AS^Xƹ1¶¥(pû&N1P€J•UÑuMÅ58bÍk²|åWð¬",¦%°Õ>þÒ›!nTóxŽ1 %ƒ!ÑD˜•¡ ¢Y¥ÛgÁ*ÙnEô’ýæ%Ý/’˜{yýôlŒ‡ê¬'=Ÿ·J}.v-«ä²-—M™ùÏuœ{ôCü‘Î  ›r}o§×÷Ì2+_¢šsœ'õÛØÃovœß”XCªmw›>]6ï*—±lÊš¿Ó¾Æ®Zj™‡kÃÎh¾ë2ýçI\“¡ ÝŽóÚ‡çé§癿rœûopœ»ai þ»ã\•̺D±lØZV™™Ë~óH”ß à$e 0hTèln3¨,°$.Z–ƒ^ˆôÓè*ž¢Â(ž¤Èèb®£¯µ•¤ÛY@Qº¡‡’x½X†ŠLÙþŠÖu;gÇùM½%‘ÊrPì¶ÌöG­ùÅ€ÇYZ)*c 1ØgÒkøuÀ_ÙD”òåŒÚ$ér–®gtA'-- üä+­næiÛý(ϰI{Ï!‘JÎ Ù€›Ðø&ú$Ý­ˆ$6ôcT‹8Ú€Q×Î'ñ¹…G˜r+…VÅfäJ,sÍ7é›:0]Ž\¿#´Š©Ä߈Ɯ¿¤Öóù¡V´"RTtì’þu§ñXïÿbÜÿ'0¬Ú4æŸðOžTÊo«¢ŒøXLZF ¯îdäòU€ÅF8Ö8î8!‘JÞXì³õÒŠHQÑIÔÇcÅJl0®¡;oÄ ‘FQá„‘fex¿EãÚ\Å€ n•<„D*7.Z ¬j‘VDŠŠN2RÆÀæÈ÷íùþ³„¬ˆט¢¶)ýP^b·å¯Éá96¸9±y<ϱJ åÇt7„D*€X€è¯AX æa¶ïµó$ú ¦´"RTì8Þï»qש\V§ãäÉØâúº\ŠÕg–"$RɇĀ•. §_ÇSâ î£šÒŠHQ1*¨_øúׇ@LFBßD*f%êH©Ä5ð¥€Ä)$Í6ã4K4ã¸OjI+"Eʼn’à8áy ÑfŒa¤¦2i*uê ¼Èˆ¯b3!‘ò(Zþˆ#(ò¹Ö'5¤‘¢âÒ¬ Åé¯%éD0žs/F^±}™˜n„ŠGúEC^ft™”Dð<"„Dʘ‡ÈæE+}@—OjG+"E%@òð‹bíÄ´ ʆ ãè2Ꙋ[뾊mðUdB"•&0¬ßáø<Ì/ñê(5¥‘¢‰2LZÌC“évaØö£ ¶%¹v)0•HѪHH¤ÒˆEˆh¶-s6,ú¤¦´"RTâ ±®??cé]$²K™J‰:õóH_³­â«(ÖÅNI©¤aFL(Dó2Æb-³FQ0‰H}’gŠVDŠJ”d” É—G"Yvâ%³mÅ<,ŒL^L%MbI‹¢X EH¤’‰&#ý2Uf\ËK‹ƒ>©1­ˆ•`ÉÈ+·ÆtxÉœu%Þ_1/<ÂT’_tZà«H«"!‘J0$Â’¸l5ð}þí:¢‘¢-Ã9ž#2.ÚŽVX›Ñ#!ÝÐL]B¥â¦U‘H¥—M7´jYH+"E%^2²….Ãq´ÒV,às».'Ð ½ì¯š¨l—†Ä#È«x´“VEB"JN³r]ÐÈçyÀâ’¢šU­ˆ•H”ˆÑ˜~äH4)oj6ëæUðS©”ŒÐ"#µÈˆ-·Ò/–HÅܰO¢ß¡i×2‹>²q‘VDŠJŽÄúëðgxÁœB{R†nfv5Sé~ùi‚¯bG'­Š„DjÛ {½•ôVʨ‰FDÔ³rœ…¬ˆCÓŸ˜ò…‚ŽS/VE]zhU$$R™}1ÒŠHQ)ÆÃ­‰g­œÜYÊð9À#LùE´*©ð y!Þð}þfO+"E¥»¤ÄѶH~Äi$Ò6Øf¢ž“^ÿþþéy?—[o½u„Wš¯®y»|^üqû&Ý!‘J/$6£ÑnðyMiE¤¨J¬ˆýqøZ]˦tÛRQ0¿ãL¨c®I?d õu?$°¤Å›˜ã€(åÝÈaæã¼Q´"RTª%–ý \팣m@j­ Œo‚âdô•šd×?:S;Q}à†‡‹.<öØ /=¦â.{{V~_¶)Û&$f®§V_ÿ ´*s­·ü1ÿv9ÓŠHQéD8'ÒG /¦¦Ëy%)àh,p\\ÔûøE{{W?··÷ñS5Çÿq¼eïMO|ißM×ìíùõs·EB¢¿E«"!1×!QÞ¶bØ,‹b¯¿`‘VDŠJ#$öJÎÄ8Û™Œá<Ž48v´´=­É¨ûVv¸S­¡nßÞc«³U‚˽ßüøÞý7«s‰™/¸^( 8òˆs¥!÷É@+"E¥dô•8Ú–.0œG@‹üMfÝ#˜R;.ê}â¼½Çû|Ñ”ozWKä·‰™/ér–®gtA×òˆ³ +u郯Pƒ {|RKZ)*Â0fKq´3å€Ã }ó›’, Àö߬~kß6kH\ÑE%©<µ÷Ø£ï=ø õ Îå> ^QGiE¤¨ô )AbNYƒ¤Ú-Ö´¤ÝjHöxðᬳSµï†Õ* pßM" š2»ï¦'^uø‹êY„Äì­Š„ÄlÄ"tÿŒ!±­¤©˜(¶ú¨¦ùº,ЊHQi‡ÄúAØg»#íÌ®œB{³–̤ÚáìâO,ýÁ¾cvÕ{ô)]T’Ë3ûŽ=Ò½ÿæ•ß#$fŸô}Q% ¸õÿaIÈMH¤²ëÑ@WXó à8¶ÒŠHQéWÐqšûCžqµ;sðC¬@û3‚Þ‹‰TBâîõl nuºü,€ˆòȽû­üÿWéß&$fŸd(?ÒO†ö“!þ‰T¶@b›G#>ê“ZŠqQ—]vè@ç¯Î%$f¯rÓªHHÌt(¬B„až5,V¥Цø%¢ÙXËyö(Ê78&ãÚÆÑI÷ò,þ+cG2{/6˜R;jŽ­¾¡æÆ•ÒEE[.é]QoéT}ê[«_=ø´ZYUêö>©®|$´l;ÛÒåÎÚÞ•óì”8„Ä쬊3’>J2)?Cb哸_…ù’î¦V¢UGTH@iE¤(ÿAb»$ÖŽ£*µò°.ãeU¢œóS‰—¤xß±•. jkÑ^W½©ïõñ;VÕýê)õøÚ3ê7=¥îÕåáÇžÖŸŸQ·|ûq½ÎŠÚ,JH¼aåéšc´Õ{èw ‰Ù¯NÇÉÐ/B’B*ÞÀ/B"•LHÜ…Æb8*–E,“®g½åЊHQ~rÃMÇÙ¢»9%þZÀ*OCZ}ͱ‡RsãÃ*RÙ§ËÁO®¨?~Týó]kê±'žQ?Y|R}âŽûÕu_¾OÝñ¯+êÝ·-ªéŸ<¦ž|J©»î}Zu~ù1uéMëßÝjûR‡ý7Þ_iRâ³_ðé«âXvZ ‰™ ‡%æ-Ce¥ž0°ØÏ%>©5­ˆåCÁ×jåx’ÆYN&$î½áá2 hC{o|ø™H·¿÷audèõÕB=úø3jéá§Ô­ß\V{Ծ®/-©Ñ“+ê®{ÔÞkïQ#÷ª_>°¦žÒ°øÃù5õ¾Ï=ÚÆ (u¸ñÂc÷½˜;êÌj«"!1S!q~‡èZÞ…ùu.ËâIŸÔ˜VÄ$)\tÑE•ÕÕÕÍúóéôô”.óáŠ^w'×­ÞÔFZ/Û×Kby ·Xwʺöv¦k]°¿:wï5?=ºïú_?]sãC*\¹¤÷!Õöw¨_-?êNûáŠú³O.h ¼;Tö_wºîŽûÔWþmEUüîÓó÷uߣþæ;ª•Õ§C–Å~iEÕö†ÿPùÄâÓ5ýuõÅûîîíí]C}‡Í¾á^´o¹²n}¤uõòžL[Wß?»ä>ê=çœÿ¨Û³g!ÑuÐÓ­[ßÖD¯{Î9÷®…[÷ /œÕÿ'u9¡?wéÿ úÞ-áS9ý€˜‡ÈÁ |1Ü^¾µN-,‰´"f!Êͨ ¾1OéÏ«ºLë2hß ús±L£ðÈQ‘¤pݺÍ$KâÞ›–ÿdß ~kŸ†³Håà'V¿ã±õðS_¿_]|ÍݪZCàÅßú©_¨/|ÿ!õ†Gé~¾ã_V7ÿ"´\ÊEz÷ýõ¢züÉgÔmß^V—Þ¸¤·ù`ÄßÛwìÁ¿ßwÓÒËhIÌY«b¬Š-ÙfIC„y®ìÝ»w—~ô³§ 8"Ðkp@—*½n¯ŒôcÒO(/X¤1»¤oÄ}#®è2&ot_|q9o@*’èæ~_%Üß÷ßðà5ŸÐEE*ozH]sÇ£ê×®©k¾t¯ª¾z^Õvß­?/©{ZSO?£NK>KËu_^Ò8Z·ñ浂ÄÔ%Ý÷¨½×ýFow9Âo>´ZÓ³üvBbîJ†º«¢.“Aßkâ‡ÄíHz·t9©Ë’1ôóªšWFz@±–E}ôC+b¬Ò7U…~«µÞâvê’Ï#C%ZCŽS(~‰™‰Èþs+@ô‚Ä‹4ø]ªaï݃¿TŸüÚ}jáþ'C€øŒÄ}J}îÎÕŸZP‡{‚ÄË7AâÝzÞÝjo·Åž xãCws[YaUŒß'î#­Fé¦n·]£¨äÁa‘Iè‚EŸ yG+b,‚ ¾M<"T*$#JÜŠì‰=Ëkë½ÈåàMjH|øuq×ÏÔ{4 ..¯©ÏO-«w üB}jü>52ýPèóÍúóÝKOªîQ ”zÝËoþ9 ñ~ ‰b]üY÷vÿZƒâá~÷qB"ºV×­Š“ºLÉç\ƒD·áC?ӆğ‘WFr±Y—5wÚ }ŠO+â6áP¿'ákØÄ®d*Å̋Ǻ%qù©X!ñ}ŸþeÈrøäÚ3êW¬©O~uI}ès‹êžûžTO>õŒZÓåúˆ‰ë%(®),¶ÀªØÖé8Ò¶''ºÙ~¶¡‡Œ–Åb¬…ó“YyÁ¢jJ+bô7L‘Dˆé²@8¤ÒøkÒe8s ñþÙ}7 E.oZÞ‰{?þ3õþ¿þåi?D Jùæ©õɯ-…ÀQôÔÓJÝøÄ»4$ÞcA¢Àá]VP\Ô x¿ëw—@H¤ÜÿDX§3ê˜ü8èŠ^Ô¥‘WHb ±Xˆi;íX‹}RÓ&Z£¿I.¼ðÂnF!SéÔqÇ)Õ¯…ÌÄ®¯¹aùÉí@â c÷ªÿó·‹êä]©G:„O¬=£&´¢úÆïÛŽ?ùÕãêF½þ;‚?Gt³$PüÕiPÜÃòûo|à=„D* Y†XS“'ÝÐ3”i§0£¶ˆyH}³â†AÀ¢ORX(}Ñ«9ZË(”¥\‹™JÓsß…ûzîûNÎ"”ƒ½hH\ Yÿ[ƒŸá‡?ÿ+õÞÁ5úƒÕý+k¡y7mIÃàÓêÎÿZQú…:rËÏÕ—O>¨~¼°Šz¾í[÷©K®ÕPø±Ÿz Š×jP¼þ>]ø‡šëî!‘Š$XeÜô“þõN]2méAÓØ&ÑÐv*j{Xmu/Kwsý6¾[%c¬¦¨¦bEç ûÖT.A){÷î-ãÑ |‰#º4d$¾þKÏÓø¿ößpÿýû5 †+n¼_ýÕí‡,‡bM<þõûTíµêº~ªê®û™zWÿÏUçU‹†Æ?ÿ›_¨ºOüLÕtÝ¥ö^ýSõþO/¨Ÿ,>‚Äï¸Wí¿æ.u‘†BsÍ/û7oÜslá9„D*ªkÙqš`UìèôU1õ#® «Çœ.}t½Š Ë%zÙ \‘®æº-¾“ÿÅ5|7‰°xÚŠàÙ:SȰ¿È7%ʧØÚ2røu³CâË÷÷Ü÷7º<­‹ W÷ݯnøêƒ!Kâ<¥¦òˆjûÌ/4 þTÃàœ†¿Ÿ†>K¹XO¿åؼúÂ÷—Õ+O©_/¯©['îSo¼þ.uñÇæ4 †-Ïì½z¾wïÇú"©!‘ŠV2î3¬Š3þ²*¦gX> 1LCJ|°XjÁâZ¤ÑU‰MV Ka1dEœä:SÆAW,‰<”O!±BT™‰Ž³{@=»æúûë÷õ,ÍF‚ÄKn¸OÕ[Roï_TŸþö}ê÷?J¤ýÕ}H½+xOþ¤¼ñúŸ©O/©{î}BݯñïÿyY9~º´û®<^ú_/tª<»Žõuí;«"ÇnÎ$(lÔe–Ó#°x$Êm,ŽX]Ö †EZÃI†-’ÜP2\åWɃI’j!0Îï(:xÓ#/¸¤g©sÏÒ㺨H咞ߨ7Þ° Þ;øsõå,«% Š ÷=¡†§PÝ_úµúÏ{ Yÿ)ä—øsuÙ'ÄÒø €[–µ‹®¾ë5?þ]¯:RT´‚UQÜ>NÝâ8•„ÄõÑÆhUŒ wm€º«›yq»ùõúƒøÞlÓ¶,ö& ¦´"z_àÝD*SÔ/£ŽS›)ØÙ©Îª½ñþ ö_ï?n‰Rö]ÿkµïÚ»U}Ï]êC'~¡îüñŠzø±§BÝÐÿq÷£êc_ü•:tÃ]ª¦k.8 •‹¯þé7«¯½ç厮 !‘JÐ}X/dºô ¥m¸]@"Ü´ŠÞ`gò"ÃXK¢À]pÛ)ÂwZ\ÛËä’.qÖ”VDI³¾¸G ˆT¦HººtÃÒ)(:0ð«s÷}âÞ#ïÓEmUö}bQíýø¼Ú×õõ–cw©¿üü/T÷—ÕŸû™ºäãü:ÿ;úò±Ÿ+f!n1ÁÝ rdQRº/Æe62¢‘ÈRKîçí n%[mRUUUÌ­†Xü(;…È¡¸DÏÖòt°ë»äËî8²lÙÖç~£TF£K7?cb\p¨tÉí=d•‹¯ÿÅÑl# KÜç|Ъأ^‡4¦h¬õ^â âûѾvÁ–Ç¡ÞËY¶ïÜ [)Ÿ—DZìýFâ tB&܈­ˆ¦P›½ÑÊÊÊj>,~d8§?h>6H„,Û4ögK·Y¿l볯$oìÄ’–Ç×™É* ‰,)€Åå茤^·ãn¡A"YPGq¡Bb%”Ô–Ã<‡¬ä51,³ˆ–WJŸK•®£ä•cåØŠèt#Y…‹!±-Ãü‰VËã+H¼ï²­ÏÊhu@ñ«Kš½ÞþèO*[þøþOú§3$²¤RP}VE¥#ɵ*zQG‘ZÙ.,k¢¨Õ‹4M~ Ël´-s¯tµþ[m€¸Zi?WŠgñ³P ”g{¯‡°ª¶gÏY¶å¹•—m}n,&Plý“¬þêp”8t|ÉíýýÍÏœÏ6²°¸r$ݪÈu½‰ÕF™›”Õ<cX^1ÍßBËž¢ϰJ–¹°ÅlEœûtS€¾“œ¦ÏâwQN¾|&ü‰H YÚ:X¾åÙö˶ŒT*£U€"ê".i ¯Íî¾tãoWw×ÓYÒ)dUì€UÑýÒUއėíL®à1‚E€a» Wư,]_1›–5@ÖÈ)éJë-¶"š‚R7(úÉG‚%„O>ðD°‹»~qÆÒ¶?}ü²­cû/Ûòìtl 8*«n Ч–4ÿþª›ý¨S² C"Kºng\³pC»W ßû¨ÆÝCJW.¨?›º¨ ‘Eq5%œhXì‰a9+ [ 0kèûQÔZtaKÙŠ”%K–T )9ê"òÑ`ÉHDÌÓ*/n[4†º…—í¹¿TxÓe[Ÿé¼lËÓÝÑêÒì^Òôû9ZÕühWõí¿_WÝü»/ûÆðYnl# ‹›—3\Ï䂎Ӫ(ó•>©tTé„Ò!/ï³wK©~bæVë—\À°üUP‘ë|#«¹•¦Ë×e…\ÊåÆçl‚MìÒBëÁûû˶"΃DÎffÉ$ËÄêÎJ½‰ò澬í¹Ë¶ü© jÃÓïˆ^ÿðŽªÆÁ9ŠZˆÕÍ£oþôäénn# K®ÝVÅ謌ò°‘Ê0æõýU؃Ò8™ ‰}¶äè %™LusÂ,#Ëh³×§a‘À²×hçSft˜­PZÁ—# KÆ4ōɿgHämdY¨BõNÛ`UD"šuN Q¤ô;#&¿J5½éj-%ËŠXןubV«'˜Ý|$¤”6ˆ`ßsèjá Bõ‚z‘`X Êàh+DŠ%ÖRù´¿µi>î%´¡4YÛWHËOuÈ Æ¥šÇa­qmÔ‰ùž°ã¸ä‡ø?ÍcVå±-¥urÇ+tOR€xH]ÏÓJ¥Ò_wQ¸q~!D±öѰ&ftl¢#,Ƹ Ì?Bñ‰µF\£U#Ñ…­d+¢!(œ­t‰%$~M/¹9:%\ çpc\°¶'¡l{5˜¬Caío;®§ÞXÇÚßt»x›Î S“µ}õ´ü¾ÿOÒ‰¿½!ö%•*lYú7Óˆo×}?)f˵õDylõr;øV”Š-ÔuüºÒW‰Á×ãsÿûX¯Ž£|Ùgãqjgüê‹-QΗGÓ7ßeQ+>€c£ [ÇVÄÙ'«."g4/8Ùn LûÈb‚kkÐø>ÝIL®@"¹ªúS¸Ý+ã„"Úç¶4w ‰c´=vMÖö•Ñò×¥h?³iÇĬÕ7‹þ7IP»é ûK8F-ù(!¦Û…¥³ÑŠŠŠ‰e|$”hˆ qcÌóc¡ðÝaÛ ƒe‹ƒ5hDÌwÑÕØ ²×6M/m¤7$6й.òiÙÒX´^ˆWŠæ®oRÌ­+¢Á#œÛ½œ¾?l€€VÓ[ï0P•‡ØgIažmù¦;WËFÚs° ÓÕÛ~·»*ë páÝÆ±@âˆ2æÿ2*æÆè­±ý>dÃzÛ6öÍ,mp˜ß„ø‡ó"’÷J¯¹Ãw¡ …6@µCâcýËŸY¢>¶ãXfŠн ‘Žñp$¤ku„ÎÝ>CM l·ñ~·mºAš*Âz¦hÝt¾–Ф´ ŒÊš˜½dÉ’ÁþÛ WµÆÍîlE´ˆ…(àÉGbÁÉ>º)î‰a ˆÃtm5åÕHê'ÿd0Íc@×7債!ãf —ƒÆj²Œ9 ôvZ¡¦¹Jˆ' Dz xÍ%€2 j –Þ¿ZÄiP\NŠþ®ˆöq¯aM†LWKV¬1€"A¢¹Ï6 S m+tíx®r€×aH×F€Ä)Z¿]¶oŒ¶¯ž¶Uƒ­¹}Ú:½Ü8£…Ä1ú}•1Øëí¯Žó¼ÐÛiÂæ¨ˆ-ÄÁ„ÄC¶íÍ ‰Ñ[ˆvqûÕåœCÿA‡Ãã ‡èØ4ÑŒÿ´X¸Ÿ¸ƒÿz1ª¾õÒu*>ûý/)ûŒ0°Ì²n’kV¿ì8ç/#Ëa-ã. Ž+uÒ•“…­ˆ6+âjÉò‘XpÒ'œÝÉN7pmÔ gºñÖÚ,†u,ËJwÛ€³Õ˜¦4 HÜ#æ»ß K¤“XËý 'vqÐfM]MƒP1X™÷™vú¾ßó «¨=&-TF±1ÐäV«¦( Ñ è¶ýíǠƀY;$FjS)q¥ÉaûL¸éµm_‹m[YãÆc€D³„‰†ðí¶ó¢Ýf¹ ÷ T`@€)ÓûSîp ú Q_#“b¾Û‰Ñ[óZñÓ¸U@÷†Ö»q:ïÛèaÆK-3³ ×Ð5æŽÃ´íI÷¾©±¹?ã¼|{(céÍlÌÛêPòÆES/[ ‘;¬,Hé 1Úš1nƒÄÃÊf‡=]¾1XÛÇÕbÖEh‚E}H ‰ÃÆr´+iȶl»XàqŽO".±ÙÙ½ʽZa;冕Ȕ±(!±œŸÁ`ë¶WCØc>}\ ð5·i"Šó#ws¹õ„ølX‰Ã-ÐÀíûªz‰pv¹9<ˆ”ׯdHœ&ðYb»Ím6©©/ĵâE)£{€Ýíˆ ûð^™C×^í¾¨ï‡õ"N£X$¹ôÒK[•6‰L²"NSÇ”¬ç-&0l¤÷STcÍu.m![YXæZY¦„sMÄz­6,„N­$ËØná\¶cm~ «l7ãh!Q»¦¢É¸Õû2ª qð®Y—w¶²Í[m t¡ Î ”œ`§Î€¶ú¼7H,„sƬ¹MÑ”¯I$ö†°’¹‰±œÅ!ŽGp¶†‡‚<uØE–í&;ƒ!1›ö{І½tŽgZ½?€p‹ñ`¨…Ëõe+++Ë+**2§m0AÝ„ŒãdÆ<‰¹ä® ÷Xž îP¶"²°’+fãÚöÛnä¹bn‚…¶¤èÏfQÚV›o­1ðææ!ÚëÚËÚèí1Bb¾˜ëŽZCÇeÔ¶ìíQX*£D ýöšr½Æ$†Ó@ ¨-tC 5 ÷bõy1a;/:"€‹p2 ¬¶ý_ö84$`9@ÛÒñ-Îaé¢QãÁo­àú‚Â8'ŒЄ0½Jë|sÈRˆ ä@’–ÝJ.fI¯.ÙÇVÄ 8ùX’)1[´8R™]ð¸T„ØÖ…’ž‚Óüù†ÕÄŒIÌ7À4 æÇ5åÐ ¸\ÄæÚ*Ú!ÄóŸâŠ0›¹öitÁh»å©€¾Ï¶m£}9Ù´ÝúØeÑ|0ËwZv.}—ç°}º¸uÀá˜9m{(KQ ‚f…Ù¾<ÛöÛ”oÌ«­Ì+mÛ˜o;7#-?ÞóB?˜„{È(1® §c—bÍóÉü=/†c«‹i7zä>Qd<üìIà€ œ#û„s-Ó˜¥²²²±‰~Ä"¥£†µ¯Õ…e–Qr ÜÊ»)inæ€t%cH–³1$$fw3Kš¤Í°(Չ٬ߤ˙¢™$¦•¸•þoXê´•-5‡Eè¢òé–ý"trYªÅìE½G°õ0œd 8(ÒT;x˜ºž´Qe€bMËÓYÌÄA½<éj€®eE\Éç¬#$Ž”——ó“ Kºž¶ ëN‰ðÅ$®tÎϾfIþ ¹WæÓßx»IDATG8»V[Ó¼m:ëÜkÞ¦B-úÿ;´` '1Á1Ò–òÌ¿ße×@Ÿó•NJ#{O½_'Cg’9-³‡1ËÈh^Nëq¡ž’eETO‰’Ÿxœ!qjÁ5gñ’ÀS€ÜSi°NºÅ%p:½ãµ®pXuW ¯RF\]­U“G€ ת®™Ï§qÔ¢K„ÅíQct®«ü‰ºŽá>½LîaI]QJè}O ËÔnæ#£Y¯ÇweEd·RhH”|X¢ ¨vOæÕocaIÚp!œëˆ²Dí1‰ëÞ>xý|±§”}<¢» P«<Ý*¥{)¹0†å5Ðüˆs¢ïVÑw‰öh.g+"C" KHÜßé¯6g,,é”]:;øPÄ,:6ñ« sLw2}ž2â{b\Ü̽F"Ì´.ãÂÖ²1‚dT»–¤Kˆ¦ïÄz±°x]¾K óŠ˜E—ùº-NHÌõ $†½𠣜ñŒå†E²†`ñÅ5&hýc+" KhQ€XÞÉ®3–he#Î Áa±ˆN>J¨­¢ß!1@ ,=QN_HÒºb“tý¤c+" KhÙ©P).1› KD1‹«sù›èÄ,ƒ³p!‘Àoq VÄ݉½¶¢Ù.Á"[c8ñؒ²`EAb— XX$¾ "g Š®ûúbÆB¢Ú«¥í¡Ü¿È@¦„•X’UѼšÞçPòÊÁ¢ UåÙŠ¸`žNXXƒÄv¥ëøH°°D ‰H¾Ð¥pAìzž/£ë³m ;2É-Œ8þ0ÓôÄ‹¸–JÞ´Ù¾Ï&XLð„c+"C" KÔX£t/Þ7«áfv¡±°D‚D€NЍÿWˇgFƒÌ”¼™¢cÕä$z¯N¢‘RNíø®áV£VbQ Ëì32™÷H×[1±‘!‘…%²ïby—ÿÂÚÁ«,,,‘!A’Ž·CìÝâ||p<:ŒãN+E!ŽÿŰ"Ðç~*uÓGI*Òn ŒaÙ5ÔYEgD÷¸‹lEdHda‰,êNPPø‚Ä×Õ«Ä{Îtfa‰ µàó„ ŽÐw¡$„!¦‰<º9^6—űó5$µw›=šÕkžÙ ¬Ã„EêõÉlEdHda‰F‹¨`ñw€D‹@|"–˜!‚6}¨9:nÀâ8}—‰‰aè;–’bnÏyÄhÇx좫=énÎ¥$í.2~[CßåG€ÀÂ(ÖSãB,b [YXbEt]QúdGÐúÁÂÂ;$jÑ×Q¿OwÓoy>ÝÝGÛ¾ocô}~‚Çοc5·&h,¤¶yH>é3O>¹¥›dJÌÎr/[ýuâõôôdwvv.îêêZÓÑÑ1óô¥>·+Ñz×]wÍE«éÛ¢ý­»»»ÔXf/ÿÕoÆo‡2þ·;îxªó¼ó¦;³²Nu~ä#ñ,Ó<§Íïù·¿Í¸õq\ù·™{ÙãÞ˜«î‰å;wîÌñ$Ú¡ er†mP% ´¿·Fã½æšÈ.A·ñ^Asû‘´³GDïVÏlH$è˦×#yeq˜éWÒtk 'që`Ec+bìR^^^ Ngç:ucœTÚ¯´[Ý KŒ%OÝ »A²d¨ Nbg°ö Kª”ƒè®]» {`=Œè{äB¢)…„ûEÐ-+t¬M´<´Á{™¬q XB0ˆ’|­„£!¶°ÛNÛ•ÂcçH4ெ0?Ât¥FfèÞ$[ø–ãÙa¶ºÉÕ+]­¿S˜ÏÈâé ÞøYX<%ÍÍÍYê¾Y¦ªM+wîŸ>ƒDSXˆSƾ0à¨u‚ ²@®ÇÐ&C÷-¶éöÑüCb¶|O¸õÁäÜ:‘xbíÂIJ˜ÜÒtò‹‹kÑVDn­å1ªZ“Ò1u“ÛgÞèXXXXXâx éì\¥î©êµÇ´>ú^@XõVp-ÐÅ«ãžû V˜à“/»ŒDÔND7Ã=ÝGí÷ö&ÙŠ˜ˆ$³-Y·§øFÆÂÂÂ’Ñ75=€§ðþšÎ2.HlEÜz¹î®']%æZíVÅzCkh~¯T• H¬'\C.çlK Xœp)£™­ˆ‰A¢«'QÌøB–ä=ˆû t°0$˜OÝXò ǨÝ^¶1 `±Î…µ±Ñ#H±3äZf·2 K É-HL"82$¦3‹u¨\N;Ü–N°˜àØŠèH$@<MS@5 Ë‚Šß­t I÷a†D>vIÅ|X,uaÉlEô$B:;;k‹|DYXXXÒ'T^¬ŸA‡!ѯ°8Ʊˆ™‰\†………Å{’¤{3ƒN]ƹ›ÃÀ¢ `ÇVÄtC"{B–Eï …¹Õ!1½È-t£D¶"¦©Ô¨Ù…………Å[‚{4\Ï.%³0$2$úÙŠè¢ÄÚ–žLÕ͇ÿ %³t§tDƒõOÐü€µ.îb´•R q(MCbŠ‘­ˆîîîR> ,,,,ÞÊzvÁóèÀÕžÇèÉŒb؈•¬V:FËKT´MÑN›.ãCbŠ q7[YX¼Š‚婸A‹…eHGGG± ±‰ñ€zvøÖ?ôl6+bTв—Û¾Gs†\‚Kü^j[¶©\ÌÞÓb¶ËŠY³7ט7—–›OÓÕ‰ù÷Ä"ã·\lh{jlÛʘơ­Pé([Ý•hÛò!=Cùˆù«©ÂÀ¤ >å³°°°$ Ñ{9’aµGû(£oó!R¡Î(é³¼«tZ̺˜÷Ð6¡×3îgèýéDuSÙ§n.ñœÜ…tÁ­³1"¬ÎЧíׯuì •$NËÙ'h–"¨k«îåãq¶í‹túíËÝ^zm'³¯kH¬‰Ýsm4]cœ8ép®5¶­'ÇŽ%ÊaŽ­ˆi†DÜXbh¹‡`àí"hŽ—¬±é¢E‹ž¤›f‰ €Xh´Â,QZ@Ÿ$°Ln½ÈÂâcQ¸ÅA"¦ ø2¥Æ,ƒˆï3ï-Ä–8 ïÍÄ–Ö8 1ŸÞ¿ÕŠÙll†DA"[Ó ‰Q ¬†{LàÉ¿à|Yþ‰‹å5u—É[nú¬lþ§ëYmzó>#¯¾²Ê:N9çœm‡Æ‰À¢Z@™Ò#qŒ^WʼA¹‰“hébX,ó®·1Ð%Q‡~q|ó›Î;I7™Ž¤]qA ae@„™®Ëè°D!» ¼à>̱!<3YÁ ÑpËÄl÷ S#U è¦e½©ËzeË]›DH¬Ñ·‘Kš 1Âý!‘!‘­ˆ,¡%Ô“f[˜IT!oXUË —=ôÐ.Ëb[|rz°#‰#‹8í’”A]ÀWЂ }kBü^F¿×†€D ˆ“bnQcsÀ ı]e h Â:& x5·)×@u¬[¶ n‹ù®ê1žsãßÌyrC¬Wz¡‚ÄC±ÜGÙŠ¸Ð$Ú¶|NÀyçžsrb´!.E —þ›Ôq¿Bˆ£w ñ›NkJÛïJaâ¹­ç•ÑAÝEŠiÔîêÃr®;‘eáYÇEøðˆÒ–Äp€˜($Â?%BÇ÷æÛ~3v¬w$ —:FÛ>F¿uÛ¬ˆZ›Œã0LÛ…yìno½Ž1›Ì–°¥pîºë®X¼ ‰ ‰lE\€ω‡V †·ÔêEEïy•n6«w Q¨ ±¥K 0P¼ßé’•! $vÖÛ¾ßCß#‹ºFé·þ[Ð2$f;fÄby\%fKi­‹0à®Î…éÃ]ºp §|LØO÷G ¿µô{… …a§}Öc^5ã*Û:ÓrªÝøƒ:::1ÕfHdHd+"CâÌSf}ˆxÜüàŽ‘#ÜÇà–b½»g“¶Ḇ+@\ «"Y”®ëvÙí«Vš­tBé”4¬-FÑîiŠiÌ#X”daÌ!¸&˜¬qXv®œHYü/¸¯Ø#ŠÄÜVg= 4FzX8a6ÜPZ^û’‰X>ÌÌ.%†uÒ‰kBX{ ˜Õë¨Nóê$Ž8((»´¸7F“á^ã§cÇuƒ×c>[=‰c!Á[1=Ž—¡- :uä§2+ëôiºá8^'ˆWTÚ­@q\é!õ~u×ÜA+^H,¦bÚ½¶ïë÷P‰)£Dào½(î¥÷yˆ¯ÈŒ‘aKb šÖ)$MHL$ó]Ö‰¸›&1DH\MÐ7M Ûd³lÚ!±›ŽCŸMGhæ:iþOÝ‚D{Ò΋Ýô縰 Q«€Hm[aÃHŽq2‰¹õ¬–‹9n‚ÿ~Hˆ‡öйýlÍé eeó¡M*$†º€¬›j"2´¥G?ð…/‰¹.,GiVƒ«‚Ãå w+PTv@éʉÕ[D=Å<ÛwÕykésY{és‹‰Ù†Ë:zKÐç5|EfŒà¿“8â‰f7 :ú®ÕEHlác+h› â„D kÉ¢¨Kë,‰=tœBõtO$ÂÕ¬îóûÓ‰ö}Év8Žùt>¬ 1ýJú-Ÿ,‡š Jè\:ÖÚî—5Æúr‰MòÅlæ‡u–ŠøcA$$f´•ÓŸµ–.ÀÝô$„'ÉISïÚV2×Ñç#¾±›¬‹} о”,º'O8œ¯£‚ΨÃxsÀ6à†Ó@„íê6ƱàÐè4õð óL’ÅÉÇ1ÛÅ¥ö}ÐÜ€aàЀ\KË¥1iŠÆÞ¼dB"Ò‰:3½‰ŽQµm\—eÚ`¤3Þó í–ౖĸWNhk8d€ê€H,ÑÅטCP;ÌNÜ=ùµÑ.þ¹igÓ“Æ*ÚÇb¶5”]Ó‰R.HÌc¨¶|êæÑ›*HD­Å[nú¬ÌÎ>sæ¿È9çlYöñ¸V­ßPn‡uVoþÂg¬cSþ‰‹­ce;ˆ8j'¢|Žz2l¤ìèQõ¾ÕŒ†S¤’’_ ÇȲ˜MÓÖê$²>6Ð|¥‚ů’McŒŽ³+u?ÂõnÖÖ¢r1ã^A£¹…JÇ¡å…Ô|`êXúbcš\›¡E/·Âa_´>³Ž¨ÙGºÜ6On²Æ¤ɉ©€Dx×$Ç/T‰£œ Ñü¿:Ĭ73;$Ú½g«KDäøÚŒƒÄ=1õ‰ùnãI"øá\ý=S$n\Útmw_OÑ÷ bº§Ã¶™VF¾±°„5ÄR›Ô-H¬Áåb¶—· K`A^ƒ•O»ôómX+æÆ€6ï¬s=£´OEd sA„× ¸p¨= ‰xÒïµYÄKdÉ'0¶Y;ü~,CxÝÝÝ¥nC"b 1߇þò}rÑ¢EÖqDö2C]rtè÷È ÞòæSt¾¶¸yÞ tJèP ÆI”ÔI´#Ý*Ã:()^q±ÃtÙ¿XKnë"³§4Áç(¹¸K%×Uea‰ÅLHLTt•-ÈDc$‹°Ý¨ßê)HÄŽ­³YÉS3‹ù’pEÊéÕÖÅqá㙩Ìn¼ómòoÏ—gŒ›C&3Ã\re„È¥ï†ËÄQ†TƒqãîDj0V“Ë9bšý…£Fwh#ý® xë߆زÈÂ’ÏE?mðŠøE·CÁª Ú˜ž©““©™¡Ü+\îßÊ2#0Q0Ž5ÌöÅ ‰á!ñ¯>öAëx­¸¼œ!.EŠLh1›õœÜAGÝÀá‚&Wô¹¦ªÁ"~ýÐXHŸgº¸P”Ö (ÝM%uPz‡ï, ‰þƒD-¸~"9Y./ÛÇn­,ƒ‚;¤Jÿ ëlÁZS— ˜Œ8o{ë[äé§/²2p‡½—.EŠCoÓ›B,s•ä8n†Dï@b\÷î2øð„´ XèõM$öÿèÛ¤¼ý- miR£$Žgbñà~F+@´¤Ö€ ;(/EÀØb‡?ŠQ xÆ:ê' ×óJ‡eäP“•²Gr¿w– ”4•ÀaHL!$ê~†-üxJtcû6¿î€Û%pPêó¡•[zËé¼ô\QøfªÁH™ÑHx9€˜—JLQâ4à.%Ë#Zæ„°"êŽ/û6‚½rn¿a¿Cb<‰+køÈÅ,mé€Ä,1[憳ô¼%eô¿ eêQ¬¨‹g£V"[zôÚ•WXÿºÃÿ@XG—GC"ŒŒ{©h7^ëz(EA1ŒûR9ŽVDšöMSAŸó‚{éJ%7#`Y8¸\¤¨JBÊH0q0H,³¥WX¼'£Â¹ýЂ„DtUÁ|Û¶¬e`Ks)œ …øâx *¡ÍE^<Ùt F²,w«m]Þgr%¬Ô„*CCä€íûv³E û8bLà ƒ,™ ‰x BÝe„¸qCŽè¥PÌÖTŽ[âÄ´â¯ñàI¹‡þŸ¯zy#SUGC¢=ŸYãSýÃå$^m:‰Ä­¾ÌIЄÈSº†bÇQƒ±ÃåR_Ô?0Ø`¹œ'uçML×AŸ+—‡rc³°xMb,#Älm`„ºñCQdÑ][pÌv§uÜÛ#ü?xRž§ÿg½O!ÑÕĆDoB¢).*~=®cwzv¨ã:[«ã].Ô€4Zòï*wßé^Ñeô¹›>Ñë”.ÉÃÂ’AP:F÷‘í|8¢¹UYÇ žÅ„’ßâÄZù Áa½&%b¶°¹§3Á£Ó¾º¬Ž1ö÷‰¹Æqñ $jqˆ Ü“H›½d j0’Ë|¦ãÎ* H[ç$jh¶ü+ ¡ÏÙdeœ¢ØÅ<£ãK!ßY2LÔ¨ó!Aìzž/9Áçî™J' ?ÀÆS'±É/ ²Å7ÿ Cbì¸CÝA7—é%H´c®ÑfÏrñvy¸¨ÚÆÅ°*îóu‰ºÏz“ÔÖo˜°…~×®çíÆ<‡è»€OîY°r”‹`ǨzÖ¤iµðÐ9c Sj P„•¬–‡ýÁu¤»°M‰46×0AÄ7Å›€èâæ'ý ‰n—ÀISï»ÓZÆ­_^%ÇGγÀa¹ºH÷½½_³ê2î¸ãËVFo綯Èéc?z}÷ìÞ*oXUk%z þìûó€nä‘ûæ$à`{6ßþEk]ø~êÈOg~Ãg´ Äv_W¿BÞ¿gÛ hbzÔ.t²&âwÌ‹ý@·”õÿx­µÞTCâœsb¾‹·¥ÃÃýÊM÷9âÕûÕ]qz]¨ïó:R%]L¿í¥Ï‹ésžSò‹Ö tŠ6ÆÖÔèYáJÓ ‰‰×ìöû„Ø»…\€>`X¡‡Eš5$þ‡ŠÜ! ½²\Ì7ÿ?Cb¤ó.•ˆyó/8_^¹¢Â-À–eNSþ‰‹g– øBÑn€óâ}4ëÂt…ïy‡5߆۾`A /”»€ˆ÷€J¬u Ë>^2¥ø­ø¢÷Z%€’è[ýàÞírrìÇÖºòÎÏu<&ØÇœsΖ‹?t‘½ØìÇØðCiƒDSì]S|­õjÂK³YȈ6k0"c:ÞxK‚ÀzzŸ« o¿¯1ÝÓ¸À{Mh9ïÜsNâÂù‹2U8WXÝSñ†7œe©: ”x@¬"bu bݨi˜,QÛ Ž4¾ØÞ(¤A"»–½«-yó›Î{®©Ö 3 1nN…xð$^i¢qF®¢$ZVóè¾\MÇ@8bû†éÁ¸"Pë&$j×ÂZÛŸ±ŸKüîXÇt" .xHD™ÄøY°–“ã$Ba)DBFðú½G^XøÎ™ ººòãV‡™iÌê^Lâ)á&S@®Ýd:Ì%+€#+ÚÍ5ÉêHÓBõ‡;ýõÐ]¢½K¸øüõ¶âÉõ<-RÌ’@ œD€UF/ÝdÔšŠà¹˜ ˆì#ë1´ÉÐFã}‹mº}4ÿ˜Í·><ü¶Ñ¸ŸökÞmH4é½Ãv@† ¹ft’OÇÚ47ÓÉ“Ÿàÿ#¼uâIõÄ&JËßùÎc׫Wõt%Õ~HuÉ=JÕvlµ…#ÁžNàÀB¯¹æ¹~ýú¸!ÖH3C/ƒ–÷«Cß•ï ¼ÝZ>Ax0L}L•˜[#ª'¸sxuè5pOwy8^‰¶W×`ì÷r CC,,Á|¾úCuü6MºŒé0”ûVÃ]´@G T÷>ê™qÏý«LÔ4,ðþXí$jÉ%j7c@î½4?wl™+d~Þ'fc<%=ñ¬ŠÒÔÅÿ#Sw"Õ+‹~JÕ(üÔE(÷{îc¯ªWuòIµŸr’Þ÷vÓ´€ÅÚà2>ÞŽ„ÎH°K“m€œšš’ÍÍÍI)¦Œd £È€æ`üô(²¹ã©jVÓ"ÁEAX¯NxQO%µ^Mx¡í­ Œî ÑíAÀ-Çÿ2NÉàóÔŠ{Jѵ”Ô:Š‚Äh¦˜ÎéZ1›H§Æã:ué=õ´¿\ˆOþ‹Íªh&ÝÕÐü…‡‰½É†DS–‹¹ñtfm£&±0k-f‘ù»•ž,Ìã‚oˆ=ˆ=Ìÿ#Õ /ÕÓ’‹¥‚X©žºd…Rµ|¹Ni+ߥ fåh° ‡G%¿ÝJ·øa¾å_ü¥gÈz˜Ë~E‚=”†Át7Üpƒ„$ '§7Wd<SÕÏ…ˆ„uǯ7^:=œ€gdt£ã$îJô¼¶’U)›Äšvkb7CbÈqž¯vGWf:¤$Z'1Qk™Ýœ;FæÞ5ô$““aÇ;—ž(Èš:!æÇ#$jeuø,8lSú²ÒWÉzWE ÔJnpMtì&À"à“€„=´Ìu4_d ‘§“0±*QA¢®É·mÛ¶¤A"êjKI¢ÝHX“S•P²uxi0:¼´y9`@¤Ò?“Žé*”Eî´™/Vÿ(ºGcqòž"Ü/“*@¬¡q°;8®²$MÁM õÏB¥«›™G dUóËȃ%b-YÃí_+Ác–ûÿ\¥ôE‚¼iz…þ/}†›÷0\À~-ä^I®b¸Œ]/«‘¬ÞÍ3V¾ùͤA¢v3ûµt¦*âßÄlÖ³;!Š(áeDé H¼׳ÑózÆ"ÚœºÒ&ðYu;ùœô§^ð–7Ÿ¢ë( XL/Ú^2šp+âB¢]tºz¤Ì#¤Š"«[d Ý RU'¬€¬µ‚탇ÅüÚFf£~‚âU"9ƒ“%1,…°þDéKJ¦&61³ É)X@1–¾Ì¬ÉW*I¤ã]·ü!u ÝèÉœ"Ÿ¯¶ˆö“E´½+ù](à~“×Ô]Æç¤Oèªfܱ¼m äMkL瘹Üͱº.J¨Ú £È8²\N#l}¤ûD|éëûeôÓr£É`2SÙqãLUÛÂ(ÿ ³Óxâù/_ú ky¨‹ÈŠ÷ÔÈxnOÖ¹Û<·'ó$¹yëz<”Žò9TƒqˆÊê´$É…Žæ¨{–³zOQö+Ùc|šJàÄ ˆ‹•öSxÕ‚­ùœÊÄ7%@îYÀ×:²Ìi+Þ¨H]çmÍl§›c¹ÄÓéŽòu[¾0±*i‡DXQ$Ëãlfo*jd×g*àËŠt³Å^²pˆBݺf$à±Ã=×¢unÛ²–ÏGÿ‡m$=œ¸²°S2£É2‚Ièr17-½)„ÚÓ׫e” ï×'óu1íHû•NHDr„ ŒfL¼«F”^«F‹½÷®×;¦Ø]èØþ‰…ì4 Ž×õµê{è„DNLYH¸P…!Ñ%HIJЊOþ—-·X˲waaõ–íÓS÷®½cJ‡‡š©#YB'È2ºª'öDA†D†DB"'¦0$2$úBÜ*ã$Âb¸ãŽ/Ï|®ªø¸µ,®ÿÆ1U±Zë¨cŠe­SŸ×x9áŨÁ¸Wwй Q“‘!‘!1¢x§'¦0$2$úêÄóRâ ‚ïßûîk^hÎ9oÖ`äx«S¯µ®CˆjJx|íC<£Ç^ì1—»‘´—´úîˆCÁq†D†DŸ'¦0$2$2$ƉHNõ½˜Eˆ¤%ys ¾dí×ðåõ„X?QöÖл„¸W½žRú’ÒÛíNÑA'–.F AèXKR¡Ø÷àϾï8Óúôm9uä§Ž÷ˆPóÙócÛB%ºýgØ$8ÌŸÊ®N™‰œ˜ÂÈÈ$âF\þ‰‹g`°°°P^}õÕò–[n±–S^^ÎȘø¢„—ÃJÇÈ5íé6¥ ÿ·¥ ‚ú¼ÒQÂK܈kïÊÖ‡÷X^Íið›îr„9ÔcDÍÒ‚·¿Åú èŠæ:/ýÈdñEïµ^ó/8ßʊ׈p,¯ìã%2ïü\«?8~Ãz±~ó OCVÖésâ–ñŽY~pïvk9X¶mÅåå3`‰i°í˜Ó8Ã%¼ÐÚ7twºg÷Ö™ßPËМË?xß~ŠILS NL‰c¬ötD–‰é,£cÙòóó­ù§§§¥)Éê*½å¦ÏZVûûD X{­Ÿ-!HxQÐØ„„(^v› x j•žPÛö¢zè ZB‹cŸâ[‰@"Ö7œWÑ@â «jgà1Ä›oÿbÄõÜݳiN…xtœ1z¿›ýØûè² Ÿ5$Þ±ñfk}øÀh†Ÿø0~Ã|(¾¯·Óbùú^ƒíÇ~:Y qc~ÝÚ•²³Ï´¦Çv.õu‡ßœ@“WæÀ!'¦0„°d$FÚ/=øLû¥ºYþVöÿèwê úQõýˆºyÊ¿ùëÔ¾÷È’’QYV&enî„ú\qÐÂÍËÏÎΖ‡–NâwHÄ „ÌMH„5F/ÓkX)Ätã>ì§¥dUÓåi¼œðËÃ\(H4Å¢DóÜxῦ?1€ Ó^f²ÚÕWVÍÄ!Ck°&jH4­•èãK!ÞÃ’‡mÒ™PSÕ\,‡zZ¬…ßÃÃØûµ¦¡ÇEÃéuõ+\M¦Ë,HäĆ– DëbP0q…Rµýr-õ’îâ·ªqRæ?¡n¾'­þÓw¾&K>x\Ý0_R7Ý£òæ/<§ÞßgAáM7=,ûÔ½ÿæ›·©Ï¹-Üp±+V¬¡$HÄÀ ÜZ°*À `Zð^[0Þc:ÄEÅs€^¬ËŒ©2U½=f즷¯ ¨¶vÀbaZ ñ ´NÖüŽåb]ömÁ€k÷rú.‘Aî­B| 1t”tÎ(ûPÖÅ 5GšgËÓè„—ýˆgô(ø&‰æ|É‚D]tp…eÀ*§çÃg¸™±,SqîkH´Çj‹Ÿ¹þ`¢ÛÙ󖃇³h¶¿ÙKma»ôñÁ+€ëÇz´Å‘!qΘ‰)îŒÕìn^x˜Šv|á¡ïÍoþÅqõz÷|¥“¸÷âýL¼¬^û‚`h7çý§^!Êå·)hpÝݬçÛ¶m[R 0…#ÌëC¸¬˜¡h{áÖ¯¤;ÄTéx+sP5ßkw¬E,·˜†>ÿ¤— ŒnIˆ,b|Æv"þ*TŒ~Ç2° ¡XÜvf²;7!ѼŒDÝJ–¹u^såFdBÓ~ìÓ /ȘnöN‹«ˆsÇníOñàež¯ˆõ(ê›Ú%¬ç;xœ  —7,y8õ¶a»ìç3¾Óë±-f² îúZÖp÷:®%.3gìáÄ”ôzýý ‰°ý›ÒG܆>¥ûœ Oé€ôõ9ħÓ2s£xÂLjL¢}>·!óíÚq›u³‡F‚DLÁL”ˆ² 8 :@ ¦'HÄ`ƒÀ}s[vÚâã‚ßup>öÁôNÖI§AßÜ hz±0Ȳ“ŠAŽêÂ2×AQ†¨ðµ¯b•(6p /j0¶ßì •ˆ bÀ ï‘ø‡’D!®c<ݾ‡DÓ% íè¦%œÊ´¥OVN@§ßëVƒfì$Xõq1­˜˜S´hn‹dq Œ¦-­Ø–t rû×¢tÐØ!D7¬s=>º7À"Š$ð‚ä—4YIã†D-à0$¢Htå%3CXcPôsÆ5oOçT\?ïÿ3«VñºÑ*öUŠA,, ‰, ‰‘ÝóD×½ŒêIÓ Ûˆ¾q2$2$úYšýSÀ;!HD!øœœ`¸HNNŽ,++“·Ür‹uí±†×ë®»N®X±BfeeÉh½.é¹~àN–¯õ­bwQ,"Ç 2$²0$†?ñ"TâGÕ¹#ÚÞ Ÿ«eHdHÌ8ñpï¸!­³³Ï²þ»+¯¼RŽK–ØeppÐlÇxÚ¦KY“‰È,—où³7ŸÔ­æ¢½á¥_+ ÇOE§è÷í¼!ÑðŽQ\ݲ€]{-“^‚²mÛ6ëXÆÓò2ý%pXÓ ŸÞ)ók¾.?ð©¯ÉÅ¢»C^ø©-ò\†ÄÔœxQ´kBy"ëFæHyä>«w±àX©˜5ïü\Ç~Ï ‰¡Å¼ã‚D^Ç|ùùùrbb‚)/A™œœœ‰Ç޵`½·{7³¤a¬ötÄÄáðòôª­¯¾²õÄ+6Ÿü}EëÉGcÑÊÍ'WµåÄÝÕ[§?¡aCbúžNH1Žš™òþ=Û< ‰põèr<¸a—––r|UŠŒôÂÂÂXdÇ„¿!Ñ”4ðŽ ïØxóŒ›9²k×.yï½÷F5íððpF€âÒ¥K­cŠŒg†D†²¼MVVnžî¯h=1­TÆ£ _®Ür¢kéù>þÒ‰tÅ‘oxÃY'"bº -ò4 âf=::Êæåž{­ºvå§”ðŽ õ7i:!qllÌz Ë¹ùæ›e"ÿC"KÆCâõ]òìªÍ¯·¢uúe¥2­l~zIëë×-û†<‹ÿŸäAb ±*Ûµ¥ 7µPñk‘ qúØ/åÈ#¿•7|®EMW.?ÿùÿR €7Y)UY)ei©”¹¹jšUQÝtË?qqÐ ¶bÓ^2444ЍÇèŽ$±€wBî!-AŒvcã=ܱBÜ7d>lmÇÈȈœšššù~``@:tÈšO ~ÇÖ‹ù¦§§g¾Çgó;íÖëÆz“ýào u*®Ÿ(ŠX¼3Vg®»yÙÖu›^ÿƒ‚¼S›ì%¢­Ó'–l>ñïU­¯_̘THŒå EËõŒd–¶ëäÿü×eÿ~'ûxTÝGäeUˆuj’•å?—×®<ªàí%¹øCÇeà¯Éìì“2+ë”õþ-ö´š®O~ìcOÈë® B"Œ³ÄàhD0xnÄ›®Ž¯ÊÍ}#ghºdQÄñ ¼óm ‰É°êÄYÀ;DbŒ'!É0€&ýþòË/·BËáý÷ßoý†‡:Am=†Éŋˢ¢"Ë#——gÁ" ‡Ê@  ®õ\ùàƒZ`XPP`Íùðt Ø7”ôÁ²®¹æk^½M Y|‰™™¸òéM“¶¤uúþÊMÓS•›^—îèôQµÌµOdÉH´š¼¨\B…Rµ?R=ÑÈ&êëÙ‹ B¼ô˜O¿ªXQíó”ÒyÎ9Èü ~+ÿ²ø'òïØkAâg¯~À‚FÀ# Öé#¿šwcܱcGÂ7]$[¤ÊŠˆí-))±#¼nÞ¼yŽõª)?‹ŽQþõ^ä’(ÑðFŸfõÛs ‹ü‰€C}¬_¿Þ@,ˆØ-¨=xõÕWÏ|†Ëˆy‰˜€‰ÏPœ§wÜqÇÌô·Þz«‹¤(Q%Ÿ“ÉÈÂFª7¿¾¦rÓ«OWnzMº¦­¯ZÒúúÃ˶NÒß(S܉Fæð•+­&à[KÀ§Æ%¹'|rè¼óŽOSþIx}”Vz€¦k§yV)]IË+ .;çïD°Žâ¤pÈ”t£Ôóæ€ïM7ÙñUZ0aiƒÕ¯°R 9FKeeeÒÞTŠn¯ø]-<È¥HšÃðVz‡úî”ú|Ìо€DÓ‚‡uÂò牰"¶ÓhÅï¸Þ4$jôá³é’ÖßáaÍ\y}&ë>áeHä8 ‰i•åí¯¾GÁÜؽî*$õ¥ªMS-Ë6Mþ™ÿ Q.VÚ¬r7ðå+-$@«!àkTÚB ·—€o˜Ú,øÆ øÔAî§éÚø0--¯¨²òw¥ î?¸‚ö}³û, á_{c<ôЮ™æM>HL6œaÀ±[>aé(j+",&€IÄM!V î3 „°~è˜+L‡ùà.3ã°ô ø–åh`„µ ÉÈâwHÔç6°p~ã7}à¡ qưÎëëÉ„Dýà†DÀ!Pˆ¸D½ëuýzkYú!Ïé!‘…!1 r}—<£zó+;ä½ò®ë~UÞóóò7Ož?{ì5ùÿ™’?}ô5ù[õù?}BÞô­WåÒÍáAqIëÔPUëÔJëö¸%1@±|dÄës^=ñ’«²áÝï|Ût47È»{6Í€"XÌ^¸ÁëÌG¯@¢ ‹°"v ÛlÆ=Ù!ÑÔà.ÆvbÓn4  °2BˆPÔ™33µ‘¥‰e!VëNÖ@ÇÈèvD{ÍDÀ P Î{XÎq}@î¾ûn+×”ôu€‡-3þ‚ëá˜_?´™0Šëç2–HÔZ\‡…!1²¬mêÒÊÖ©ßWnzå¤Ré¤+wNÉûNÈ_=ñºì|èEù¥ž£òúÎ#ò‹»Æå×ï{Aö¿&NË/üÛ” µ ¨ÑתZkù–É÷{µÈ,²,Â…ü¤‡!1O˜£8(MÍMEízq$Á¤ 1Ø­º°àÂA¢¶,š±V7Ýt“Šˆ5Ä|_ùÊWdUU•åj>ãŒ3ä—¾ô%ë{u“—«W¯–ûØÇä¹çž+ßúÖ·Ê;ï¼sN€¿›ªýºúû>m»é:ð’V‹¥eBH–ÆÚf1$úSœWjDÿˆzà©ÍH,o>’S½é•ï-ÙøÊñÊÇ¥£n:.;¾.ŸRO{÷NÈOmzF–ßö'ùÉ[ƒº¬åùϽÏ+€|Mþ[ß”¼²ýerYJ—l:þdÕæW?ï±ÛÑd7§=V0Ũ޾aUmL7K$³ ë7M¨.íHD,!¬"¦ fÊ,³aÁvîÝ»w^+<ÖäjVÖé£t^–Dqþbš š·Ïã ÈÈÈÂîï@—m~åª%?¥àíT(¨«mEþÏNÈ{¿,ëî³Àðï¶ŒÉÚ}tæ3@ñû?™”}ƒSrÍ®dEË‹2 tž¨Út|oõÖãæÿÇÓˆ€úéÓO_tªÿGߎ醙¬nê(¤¼‡Ë 1Pf¸¼à* Ú!õÙÞýîwÏ—ü η`1œ·ÜôÙ@fMLoþÂgäÕWVYÇV·k4ô@Xl·M_Áè?•ßLjYÈÈ%pS.Õß«Àmªr#¬Îúù’Ãc'å†=ÏËšÖg >#¿ÐõœÜóÓIyc÷‰£–nú÷còçMÉÆï>//izŽ@Ñy™K6ºªõøõüÿ¸‰IŒUiÅqYü¡‹ääØ3!H$08„›ØŒ„Û‰mAæ¦ND1û"ggŸiA Üìñ4kô:}ìç²ï.yãõWYÇÿÁi§vB½¶„°¶Ú m²H¶š®÷,¯ÝÓ/œ¸Ââ’»¹-# ¤jÓäo—lœ<©T†ÒÜýŠ|ü¹“ò+ß—Ÿï|N~ý¾cò«?8*øÅËrmÏy}dzòÊ­OËÛzÊÿž’Mw•Ÿ¼mT^Òüœ¬Üð‚ã2«6½üjÕ¦—Ö3$º‰I”¥Ã86—/ý„5Pg$Æ[„[ǵ+¯cÃ1¼¥Iqì‹î£sÕn ß­t„^slÖE/¹ 3H2&qeé¦ÉïTmœ<¯ë:.ÿô ¿;.xø%ë= ñŸv‘ÿzðyó¿>'ÛÕw?{tJ®ÿöY~ëS²\â¥!@QâÈÒM/{éX0$†w;áø,­ü+9>rpÁA","±À8kêôþ=ÛdîÏÕƒóþ( ¯Í£.h†D†D†D†DÆ$nya‰¶Ç—l|é”R餟j›”ÿõ¿ÓòàoŽËÿû­#r㞣òöïÏ@âíß?*oùæ¹ÿ—/Ëõ²\µcLAâ“–^bⳊz™“ÓÕ'¿ë± g_@b˜›G²cUJ4(¼ý-òÞÞ¯-HD2‹v1ïÚqÙÇtè÷ÈóßüÆStývD8»møe¥ÛE0¾äóÓyÿaHdH {òr †ÄT˧¿.ßP½iòΪ/¾´dã‹2”nøá+ò‘§¦åwô¢üb÷˜ü‡yZÞöÝ#òšö§åç¶?#{~A>ñìëòÎÿ<&—oxJâgô’Ûž"Pœ°–Uµñ¥ß/ÝôR=ê32$úê 3ŸSëfˆr7è <1ڗшÚm"Ž,oÖÔ)2ê‘`Eçæòç°é‚ÞaƒÆq†D†DÁÙÍ, ‰³rEë‹Qàöp'–lPPè ûµ—d÷ÃSò7|MîÿÕ¤ÜþÀóró¿•Ûî{^þÇÏ'@¾*Ç_œ–?øïåßíOA@lœÕKnU Ø¤@±åØTÕ¦ï\Ú:ðØa`HŒNàÎ[³hÑ¢çÄlYYöñ+N7J¸cêïùuMD¸4#Á0kz瓈¡ÍŽò|n¡yN X’®û—!Yý¸tûI{2~Ã4öïщbè0„yí½ÌñNÃ+’ÆP¨ÛœN÷O‡bYÉ,BÏÈÂh·&þ@ž¾tÓ‹-U^8 ¡Wm{I~mßËòào^‘?{ôùÓ¡WäÏ{Eö ¾,»:&¿ÿ“察’='d]ÛèH ‚⓲¢yì—U›&V¨ëpC¢{'^bU‹õ§vÚAŒ¯‰(jÜù‘ùŒm¶1ˆy_‹/zïët¾­Žò<.Ôa¤Cb~LRe§ZßGÉ îUHDW"”Âõ€îD¨  ™ÿè6„¶”˜­&5Ä¡¾!JIáw¼‡š-+|øMC Úí¡}æÁzð»~XCÏs§GS@$—ÀaaHL¡|jËKï«ÚøâO–lxáõ%ˆ ¡K7“ŸÛyTÞúÝ#²õž#²©÷9yÝŽ§å²Ûÿ(¯Üò”Üu -/É»žQ`82G/¹uäÅKo{²õ²æ‘|.¿ÀjSAÇ®‘Ž¥©}~„ĺº:«+ ¶iä‘ûÂ| hI×q,ƒ)®vËÜT]4B,îĸ/ij.Ä¿x­k€,ˆxÄ쯋"ôhµA'#€½4$"\C÷<Çv¢G³À&‚î@èZ¤ïQ¿Ô´è'ۊȉ+, ‰a¤zóDCՆƖ v0ŒV¶%v=c½Ú»ä¶'þ«ªù—¢¼CbêN<¯[¿A",Øžâ‹ÞËæ:òSyÆY'èZÎõÚ…«a‡ëŽ(}U©Tz×ÝÍ;ú•›V<”…BÇ!³$jjØ$š}˜–Hƒ[°+¢.” Ø\¿~ýÌrPèû75 Q÷Fçìf?H"mùÖxu§>µåøÛ$>°dñ©È xTâÓ GæÁ £Þúøø¥·¬_Ñ<’ëÑÝocH\˜ˆëÁ”wß}·åòÒ‚AIPMD0ÿè_~à—…;¬(8 ( |Aéë‡'•þ0–k$]× ÚVö€€œÇöúƒ,ñ¹Öuw¥Ñ¡ÿä8,)‡D;”Txu¯Øò|éÒ ãWµŒO)•ѨŠ·ýÖCˆ)@|ìùÊ[Ûº´y$àÑݬŸ í²Né”>­ô9¥Jã~šÑ^>!=«âYH„;ËŒ·‚ÕVŒL€ÄÃ÷Ì7ß3$&_(Iå°Òý;£kõg]#ñô/|Ï;¬ýM•¥-“¡'8–•—|4æÿá–›>ˉ+,®@"¤•N¦I¥5^ÜA»^¾áùO+PüNuËø¥-ãG£KšŸ~¸âÖÇ®h|ìÁŠ[‡ï¨¼møCêÚóbɛՇ¶Â»²Lé¸Rõß ãÎÒ'”ö)mWºJéb¥Ù|$“_e¸ÆƒˆE„Eîgíó;$Þù6Ù÷@×¼÷‰(Zº±œL†D†u°vÆV„¾ÑòÖ/¯ŠyÞw§Õõ(++ËE¶(Æ—½ w:þƒœsΖƒ?û~ÌÿÃ5u—éó®Ž!‘ÅJ$ÛÅl•Ä*zÓõüâ›?Õz¤ðŠMÏE­Í#E·áwïòh¢Š|iÄo%Ñ…¯¾úª”°êÓŠ +c¦@¢——™)ˆˆ w+¼+öÐË«o¹%$Wµë1ŠxØ2ë²ÎWdWãº×5Q³³Ï”÷ìÞ×Pþ‰‹õyWÎÈâV¹º•b¶%Ô4Ysøð&E(ÞmÀ!JÞDˆ’êé^¾äl5„ûY“‹ºMé>¥cä¢>¤T=ÈÕduÌIö‰çñXta‰ØÚnlø¡`ŸäÜ7ÎtpH§Ä[ zõ•UrÃm_E,K2nÜ»}æw¼Çwx?ð“ïYï‘„€éè"yÿžmQ¯ë;»ZdéG>`¹¯«_!'Ç~<è°=XÞÃí ‹ ^—¹x˜Çr0ÿÒÊ¿’C¿¸g&kƒhÉ/œ³/fV1@ƒ%¶î·éc?Ÿ±²à8èi± ˜No«ß!ñN!J)9¥cg|÷ðRl3Žm¼ûã«]Ϭ±+®…þ};îãþî´¬¤uã8 !¹dUÔ®Ï1r=äóavEßt|§È²¥»XÆxQJõÊr²:*(•ýnZ}š¸µ•D»lŠŠÞ7SFØZqy¹p€Ùa ßá=@V ¸‡½×‚EÌ @ÝÛû5™Áù `ÞË—~bæ8‡r7—}¼Ä:Θ±Š É Àº±Ýøp Õ_ðö·XÓ:möÛ‚v|ä ×¥Aµ&q<ô´Û¾WÜ—× ±9˜œ²ŽÜˉ„eŸvÚiVðX&œ’Ypá8°FÖ;6Þ<ó•È17Œ,,Ii|awƒ÷Š`FtòØn¸"rÀö´˜F·¾euDrL+YG)îñ0Y×(-duô)$"AË‚“H7[Xž0þÏPŽå5Òá:C9x!óªL€ ‰yççΛ?š~Ñ€Bþ ÀÐV>'HD¬€Ô„ô!%‹\6(`9n;$u„{L­ŽGõ4*Õ‚l"«c¡Ï!1{Ñ¢E¯N¢É°ÀÀU Àð‚*^H´T8H4A,H„0Ôö9A"â­œöQ¯€eZ|c…DÓ k¢¹°HîÚq›e¡Ä‹>Ë~…DuC©U€8Þôú¸%°DZÖØdV÷ƒx¢s.©c4—Àa11tHª²ÝÐÇè‰7À…ŸxBfò1ëNÖÚO¿Í³Ì©Ñ”wĦa«£«ßK)Õ¹)n$TóJ#eZé´Òa9o ‘Edul!XÑVÇ·½í?_4¬Ž¹´\9}Æ?M`»údð˜éÏØ¶¾„XˆZVùé§Ÿö0vâå¼Ü¨o¾€E¸SÓå†ÒènA"ÉL4p^pÝš±~z{ n1ÄNÙ³¶,& ‰æ±‚õx°ÿ° Â­Ž˜G?&® ÞPbw—ºn;“ðàyÚi§ý ÛŽxV0(Îe:ßz“=àqâ K8ë"’.F¬€Èvz døq("7rG„c±8¼T¼ŒG‰ˆc.Bâ!¨^¥“ô]]VDz?ÿóΣÁ¶¯3VÇ‘ûÅò'¿%þáaË¢8¶Ë‰=Ò ‰ ‰°‰OŸy†ïêí¹‰ˆíÓð ,¹‰€ ,K'ˆÀU©c À×¶KÌwåŠ K£…D€‚eéejH„êm Ît]c¿aA„õ°ê7HDƲÃ!@âÎä%âZ±à:™ÇˆÕÕD0<,é¡L ‰¾r7·¥kÝEd!Ûë`=“ôb‘ ³Fi™&ÇøÍŠŠ8¶‚ã~rK«j/ Q²šq-ÁËâ(¦]GÓº ‰õÆwõô]ñ‚òIKŒïóÛ‹Š¶EJ ùbì/¾+>³ý‹âß#«ãp–˜ž¼Nt?þMQßÿ}qÕoWk«#-'—æo¢uÙ!ÛTm›~ M×¼¿a{KC@bÖSBœ(Â:(‘(aIŒá· „DÄçÁÈ‚ Ü€D@ %È΀éläP‰+€l‹ž¯:~2$b]‚úYcûÌíÔˆé‹/zïœåš‰IX§ßJàt©{ÜË©é”ÕªÝÎú¿dõžâ:2BbV§b`dHô$#q%Ñqx(1‚¤Œq:¶ ŒDÀH d-Ad@¤.9&›ÖWNVÁº)b»úÄlI 'Elæ>rÃÇûA<ÀËY;dË,Œ?I‚Äú®ƒ>×z‚ÀïWÒoå4í(½j÷ð‘w½ëzŸ=-²~*­”êìÉ“bÑÉ×Ä™'¯÷!ÃzäMâØ¾gÅGñû«â¬§É’9ÊÝL®ù!únÄxfah‡ «h©$Š…8 Hмºìo‚.wU« >S6¬ß!1Ш’Qö0 Tš B˜>žLZÌã3§ÝÍpy‡Z.\sf¢×! )HLQ€x¨#užš,ºÏY ÈEï)t @ìHÕ€Ï%pݲ•|uUqRD¤È$Xë#ðì1ÖÉ&CmŸ;lÓ0–5Âò)CXCû kh©›ÖP›)¥Û•î#é0O¹‹8DÖ»~#6±Œ¦%8Ì!ÈŽÙ¶qŒ¨þÐP÷ì{ß;e³’¶Ñç" œoO¿ïQ‹}–ßöƒÃï¿{õ„8ýT­šr$¶ÐçUôy•Òô-y´OuàbÚF'H<%ÄÕŽ¼‚Ÿþ¹äýA(Ô&‡øœ@2¯Cb< K^(õš•É“h*JŒÀúW·ÝºèUHìb9õ]nlN}…‰œÓN;í~ízFX'³¤_ñ„²NÆXÕ-¸ú‹Ï 1”È…[OpCÂÇ!²2N‹Ôd‹NÑúúÈUŒÂu´]€‰¤×‡$¸É7>¨å$‰k¨c{Ã@¢Ž…ì'H­ÐîdõÝC:LߌmØn[® ‰ûišBËéb²šÎ€Jî¼$Î}Œ ¥x°ò'â¯_E©žß‰÷[ÖÃÿ+¶V…Øç"Ú¯ý†%±É ±Ï'„x ÖbT"?vÖ™òä»ß¼¿ý-R^Ș˜D·®ßPj&ÂxAa! eõBÖ3ê"ÆR$<]¨žn³ nGqì;ð‰4yŠt W˪ˆ˜ÓDë(²Æ®ÈÈG•.˜­þ„ˆ­í" CbF¬ÅkÐjºÑj]c³Úuµmú cYE‰Y­žÊÏR²Æ ` ¥Ï) ¶Ñ‹ 6ˆê#˜ÉO$Ö‡˜?ßpç6Ù47Ô6Ø Q[F‹Œß÷Ðw%d=•¶˜Ã»»ù¸8õkþŸ/ÿû8<Øo/üòCâWwÃêø%ñõU×°Ì®& ‰2ø€€P±VÊò~òæZ=–ÑéHdM-$RrÊ ‚ÄÞÞé~U®³žµ¢3 P¤u.q޲º§°z£ bhÑ™H̯·›–rt\‡!‘%<Þ]E¨«È<,³%qʈ«+$ ØýV¢:’èn®3Í(¹‡óÉÝÜ«-‡á Q—À1m:hþcñ¹N'ÊÐç2}0Íå9¸›QŽ'çWâCdÞ%þÏß,ÚÅ{‹(˳ïNñù‡ñYåNxÉÂ@"¤èB<)?ô‘î`HdM$*8l ä”•½¢‚Eï¢E‹Ž n£—RU~”B¨ÊÓypâ C"KdÔª%®8IÅçÞÊaam ÁËYÂ&˜Àz'K!$.7¶iÜf™ ‰Ôe–Q­Æþe‘ÅS?édI4–—k$®H#¦ßc[O‰Ó^=*Ξ¹Çð{¸ez¦öˆ+Ÿ:nƒ»â„8ý)!9Oäy€nÆïzÇ[_ÃÓ»,$:“—!1³!±Kˆ<‡û”îðG1ÜïJiÿÖEðî°Æ¯HÄÃbᑸC†D†D–èAñe¥Ÿ´˜$Øâ®É,ó°•’Õm­4²,ÖK[Í+²ìÕËIJªKœ–í0]!e=7j¸ÓÛ@%pìVÎ9%kè» šµÝN ¹Šö¿¬‰õ¡–GÓ×äâ5Ûø­˜–³Š’m`©D—˜ì.qýuw‰ÿó¯Ebè.õ¹¯NÜýòß‹ïMP[Â6¥+ÿ(ÞeÅK¶ñf¯{ΊÀ˜¹¨ °ZÁá¨Ò–fN@`ñ¸0$úG’Ù–%:ä2Àmë,X3åéÄ?±*²@éòkEÏÎÍbݯ‹³ONˆ\ùFñÂoÔ÷»…øÅ6!6lâ}_õ€%¡!13!É) Ûˆiv!.€{5:D­äã¸p –ÄnF‹>íÝìd-mÔ™Þ/Šó®Qo+Uƒºl'ïó8é~muD¼>bS¸™MnC"2SÑ¥“‚Šî-n—v‰‰]B)8Pº§Çüt•£½(àÅÓ Š…………aqB"b„ìQX‹år¥k•öR&;Š‚Ðçµô{²Ê&¹‰(\­cYçjÞùo²²Iu;¿dBb‡«Qû°“ê~²$íê^­t,žÄB–Lt¶åcYÀ°˜IçšME'«ãú®ž¦ÉNpe®@" _ëî ÙÙÙ²´´TÞrË-²¹¹yAë7Þ( g`qÅ—ºÒÆ )9e/,ˆ]Fy(ׯOô˜ßCr|œ].ãÿ±šÅÛ°8O6´N<ŽU±¬ŽÕd]ÜMƒÔYãµ:& ‰èŠ¢qéÒ¥rttT²Ì•{îQÇ('Ç:F×^³ÂuHT`XAÉ)mÍœœ’Ìkf#ô ÆÇ99ÈàÁÈ’Ä›X±Ò½äñ5,R)›€LA‡ÿßY4p­¤¸Æý†Õ±³U™ HD«:ËJ¶bÓ`šÅD;ÉhH!^šÄ¡Œ‘Œ‘ +âØØ˜¼òÊ+eVVÖLœãµ×^+'''g¦9xð eó›èEôÊM?)Ä·ù—Ô«1â€Q÷4‡Gò…ÊYRµfñèÍbÝ)~}h‘8ù<`ñWâCµcT(ºÑÖëy$E¥›¨ t–ÍRWgôa®³mO¾±ž¢pøÿ.¸`Ò¡÷r#z7SQìBúZuámú^oß:½?Tà[wTYKÛ2¯ ¸CíRc«¹aŽw€–ÝDûXlüVMÿGž±}öbáz](0^$¶‹¹™´}1ž* ¹›5¬lÛ¶ÍUºæšk¬øFÀ¢vÕ.^¼XÞpà 3ÓÙ××ç;HD2 ŽÙwvµ¤¥w3KÔwQ

ïæõxwYØÌÌ~?Ò+ØÙ™åeæ}¿ó<ïó<Ž2tƒRkצ~&ðãÏF­wŸOöÕeòš²‰DqíÞ•¦Ké-i¡(u”ñÞºjÛòû%ÙVo¼·&ŸO副}éK·’‚3RQ¥^»! K£nƒ"ÒRÒV¿§Öø[t‹f+Mè(Õ×a”ç[–ã­›•Xx[¾ïªüLi«¥ôÓ®Ô¬^“ãÞ5¶wÉë;r¾Ô>DâC$ÒiwP {1.i,·H|óÍ7K*¤ ¯_¿~Ï{°šnÞ¼iÕÖÖZ/^´677í¶¼¼l»s_yåkww×Þ"QÆ—/_ÎNÓõ«·™Á6p›_½zÕÞvãÆ Ûå]JpÜ@‘ë@)Ë>‚¶Ëº^&È&„"±zD¢}? üÂßA$>øø#7|/ðë}²}Ú¹¿”¬Û!Tï…gä5,mä÷‡à’×ò:.¯“¹.<9Êwÿö•¯ü·!J"¶ÑaUvl_2Ý͈Dý÷uÉßß!–Òš,}Ý £®}AÖqî.Çwë•×ZÔ69¶"!Zѯ³"øj³X¼&amƒP„Xƒt‚óa$DãÚÚšýû777ÛH¸¥! áÚÅ1ð;D¥vO#=ÒôŒ[gÏžµJ "±ö±±±Ñ¶XB¤b¸½)«jôì—å9öEåa ïÀ²|>‰Z¸œÌý’DÀîB4nê7³ˆÄˆS´ˆëïÍÊëZq·ÎVC-¸æëÅš˜Ì÷t"â¬]Ö$î8„U6wxD^´è*F$ÆcÀ·èt¡;ú[Ÿ{Åø\¯ãÜDzÛ)˜¸âd$P¸ Ú•"bíå—_ά߫««³…›cº›µhÔV?X±žÑ˜Špcƒh4j‹G !>ƒ œO[ñB’"±*FÍ Œ…P ³?M$Ò:Eˆ[D¢ilÖC$þlàýO0P®šF ‘ØjZåóÍòÞŒˆ¹¤¹ ÆþZpéõƒÆçws‰Ä•ÚÚ®]±èá“9þžny½(¿íG$ŠÈÍ|gC;„_çZ$j÷눼îÉçn6W&ÅŒs.8ÜÛZ$vˆ{{J^kwó¬ãïÕÖÌFùþú;Œ:„Û’qü5ý> Ûû³ôµ¤òzrŸ"qY P š*R$BBÐ'å'&=Óý¾›E"Dá©S§îK{ƒu†8¶ï%ß~ûmÛ½Œíf3Å ¬’øÜÓO?m F¬QÔÀ… ˆ`X1K™Þ‡"Ñu£eÔ_žb€ E")–åó¶HÔÂ,%ân-‡HÜ6ÖýmkK,‰‰ÁÀÝ,‹Kè󎼅¶QŽ4¢‡u` Ú†l?flOÉy6s‰ÄgŽßÒ–P³½ÿ…/ü—¶.jQkD8kKâŽ>¶Cˆû÷J°IÊø»7ä³Z$¶(:°gÃʒΰ$îŠ4éXƒ¹—Hl1¾KÊè«©^Nt³[E"\ÆpC¤™@àÁ§ƒRò‰Dín†ØÓ .gm-\]]ÍlƒP„;ûc›¨ø‰s"(†"Ñ—#e£TPd_¸¦Àñ \ñ¾Pì×gÄHùRç‰M=<` ±öþAà[Ë:íÏÞÙ 4üžЈã\µrŒ`:‚X‹ºvz{»äÈvት¯ËHgŸ|ýõçÓ)w°­EÞ‹Èþr>œ¿Õ8¿¬› Ë{ òºÏ8Ÿ™§^rÅòÊÓ×éë.ãÜQCpšk³¥ßÑߥWDu¯³‹{ ¸ø4Ç•îfXõ Î`Ƀ«–E—˜ëá>ÆvX "Q¯A„kupŠ•jp=c›Þ¢nmœQÏZ‹»”ɼ)]3BFÁLE"É.j–ö—\ú¾ÚÐwËÐ Qx8€Ëîr3ߣk×$b- J ª`t&ΆÛ¢â*H‹ã@A>g”4ö×)pÌm°TâïÁ6üd _Ž€]"YÊŠD’E$Έ[tŸ¦}»‚˼$™­è8EbYp}àŠß H<ôÑo@vYbÏ…0E"ñÇ@UmUjG+qF®U¡H¤H¤H,rÜÒ)n8–¸W$RxP$ º]bUœ/Õ“9/<ŠDŠDŠÄSA©a¿Ì7‰„"‘T~† g[µÉtJ ^x‰„"ÑãSˆÃY¦¸¡H$‰ÄÓQÇaëÞ`…rMÃFõ–tJ‰ƒ=±çºð¸V…"‘"‘"qŸcR¸—GÙހˊ¼Ëòy[ÖÌ–Q¤ÎØ©V†÷yÌ3ìVmZ,‹}û}zÏ#ùÔB‘H‘H‘XèˆÕ(cÐû‚BîtóFÕ’>£É¢±Ïš™ä¹€c¦¬üu€ŸhQMío­«Ö^‘¸Ãÿ,E¢IÀ¨Àbþ^ H»SêR|‰#âÑ ¥ƒB²:]K¹F^E8.Èëˆl×Hô~íRÁäŠ$’ÖïëÚÉF¥Ð+ò™ŽߦS‚[ nÉ#-þg)s‰D|‡T*UÒcR$zrôëa_x ¸š¹¬È;°,Ÿ·EâŒQrîŠT'©1¶O9\Ña£\\RÊËe,Î2yòÞ‚”®[2JÉËñÜr¦à–\"qll,ÌÿluŠD$»F™>,³þr>‘øÖ[oe’e›µ—‘`Ç»qㆽ?uETzÁ1ñ™rY)Ë:òéºFö…÷ÀÏeEÞ+Þ‰uâb¾kˆ;ÔîsXÍšÂbÔ¥ô ïÛ-ÓÝ,¯WTkKå]/Ï7ÓÁ-;Üâ…G‘˜”ÒC-ç—^zÉoøb.Ÿ»µ˜Q²o||ܮɌ²{¨ç P毾¾Þþ‰j,؆cëúÎ8Êø•ËšH‘X¶QOç@¬c_xu¿¶(‘¸Êž H$•‹ÝbY¼+­>‡HÔîãÓr˜G$.t[Ö?hí³ƒ[f¤ò':ŠÄœ &3¬ˆ¦…b.—HD™>ÔiFy=ͳÏ>k?>#!"5’fÝçÝÍ^åBÌè‘Ø©Ú<{‚"‘”W6Š…oÒñþ´ºh‘¨-°&ÆåùDbPè”!*7÷ùm[epß³rËÄÄĘ@ºù®.‘Ákb¡+}°6B êÖÜÜœ‚x ¡¦Áw§HôìhwLÆæ@ôSSSÇØ ‰¤¼"1$–=¾~Yo—÷0 6È~›òú˜¾]Ù'(ïíd‰ˆˆ®5R,‰“ÆöMÓ=½ÏomVnɺžè7Þ¸¤Ú0ÿÃÕ-ïܹ“Y{˜M$^½zÕjjj²?c¶µµ5ŠDtaq/sñ‘aV.‰„½vÐtG"‘œ"-¡P(³\¼x1ã²>l‘·7EbÑ#\‹,U9Ã[Ø?¨û’Ö`ïˆÄ0E¢÷…bD,JPI“c;ª± ȶZÃ}|Nµf±@Fuµy}NÖ-êà–¸¼7°wÐJa|õ«Ð·ö"t·\ÒÁ-×®]«A®D$¿uÖ+æ¿Rƒ5†p#˜b¿ßºu+oà „`CCƒò /ØŸÙØØ(H$bß“'Of,¥¦µµÕþ®ß™~•"ñ`#[‡D0wòöõp33.E"!{¢.¼;êÄbôYž nQIˆ=䑸ü××m±‚áRä(̬‚VAt3ÒטOŸ×™BH|ÎLgƒ8¦ÄñnÞ¼™y½¾¾nË®OŒTXvZ¬AÞ¦„¸Î˜3©Z?{‚ÆÅ×½Wáp¸&_, Sí8@kÃþ»³qäÉæ’ˆÌ‚¨gX'Ù~Çú“oŸ³Ö~ðç%ëß;·ÿÞzäáÐÿ‰Hô©%ÝŠKvƒÞ¢þfrr²Uåqö„çæéU5OGØÄ•ŒEÑŒI¥YqorbÙ¡£G|WñîÖRÉ„ [ùÚ­ï¾®­“k>ˆ}òÐÇ ¨ @î[õÐÏò’"% Ë`ÏM0J8Z+ ͧÓ¨yäá ãn\¢ó@{¶û7´H¼äÃûWG07òά Ø®âsßz‹¶¶¶æX,¶Îž ‡ù¤R«Úž®4 .Ùk}"Ñ®mU\JWg y°×%"• E˜»Ûú?ü…uô葟Òå/Ã>‡5ªÍÉýÊæ*c7"]ÍÞ#$‰1ö9Ì‹ð\!!ÜpWdµËüõŠëjŽùÕr|行{{æ5Š1·Ä×¾¬­ˆ>ªWl×`†å’kŠ« ¦¼ñìü<Ÿ; !àĉ…”ü‘§ÑEÕòD@ÚyÖd!<‚\80ÝjàZõ?÷9k'y‹‚Ì…ÍH ½R™>ˆ© Â$Ê„xTCSssŠëÉ¡“H$6±öa¯ý®]»V§DâV:Ú9ï„t,Nˣ̱xAÅߢ“N&Ž[wòf.jÈC)ñn ‘îØ+÷b;o¿êall,<111Ğ𶇽@X,6„œ‰…ì«Db£j®e²ÓæŒJŽÅaæXÌPwôè‘Ûè S'Ÿ²RÛß§@sA{ù¿næ[<ãq”û*U†z ¯Á:DÕ˜_RüÓJ<ßF¸}™&+ˆÅ1±f R,Ú49rä=tN˯ýªµú½?£P;¤¶ù/sÖéSQ[>ðÀÿ«~žó@D€Ê‚j‹¼ßªR .«6ÊÞð&p5£±'ˆkP"q9‘Htíç3jZ@j…}L\ ²V‘b1M£Šÿn›|‚G­ßíë*i2h¶ü }}öëÏX¡ÐCZ ~¨~úÀ%kWPÙ+"TªŒëׯ7ä_;N<0ŸcT3qˆŠû‰Õ¶ÇÇÇûö9‰9Åb5?1aQ2\ýXg‹•†_üy;GßÅßÞºzùEëÍñ?b+ACE–óßxήnjÀ!Ýßb=œ ø¢ªŠÕ%÷“&âA$v²­­)åˆë.Ì}‡ÚËSëúÄÄΝdÄâ-‹¬ƒ{h+ÀúË•j[ÒçM>‡A©­žLWE"Õr ª1˜–' æáÕ–ØÄ7` ZÝÐ÷‚'Hˆî ª ²•´a½a·ô±O@Rl{íá"dWHM†fÉ:ÁdÙ>0Ö ÂJ"‘ˆ²7ˆ›/ÔO4ˆ~ÆmáÐ9ÅâSç²ç=Ó"ÖÃ!®?¬>0Öª6{°ñ–¸x<ÞK+"q5mmmê¯4Ò¥ûÔ툴v°x:{)¿='¾°‘:‡y É~Ÿèü‡]ì‹êÁSÕõ Hš­æÞ­D"ÑÊÞ nšYV­¨üZX«¨Ä┊EL‚u‹„Üw_„$¥óVÈ$¡ÆÔy5¦®±7üG,Tóî4{‚¸#obIËê©ÁmNµKpI@,åþXšT«@lúË3é\ˆ¤€0Tm™$h=ô'j¾=VÌR/Bã©f¡”ÇÄÂj$xUmSµL½hY|ݼ÷ºš{ÊýQ,’jˆÝrí³Š†?…`£#»%e)Æô6”DeBÜôTƒ”8+ª ”ãøæ '5¡×UÛUÍ2äääd=^mY‹Å#G~zûñÇÿãÃo~sîÝO·åû\ÑÛZÛf¸íþmX“ª·© ¯‹ÛöÞ¦^ÛÌm¯¾zãEu½O½ü ·^-ôsU°­Ëxñà6Œw½†HD D¢Ú¯³¸ŒÄ+¨9öŒšoÃì âE¡VðŽ{ÒÚk³Ô$bm«6§Z”ÿ5â3ëa“jëb9§h ÄGH‹$\Íì âÕ‹¸=‹]pùD ±Ø§Ú¦j+ªu2ñ@ì• VO!Äg´µµ5cí?~²7©ÜÄÚ)Bq3½vËâ"oâµkË)¦Å‚ØÄþ Ä_D£Ñ:DXÙÄ7ÀíŒ\N™h#â‚Þfâ!•äØWè^&ÄŸ1‹m”k½?!‡†º¨gCÑ;BÑžteѿεæ’¸ð:Å’‰©cÞÁþ Ä¿Qµaöñãô¦P´'a3×"rÌqq˵Ù,®åYÖ^&Ä¿$‰ÕFØÄïú¨Šk¥N¶]¡ ù˜DDÃb³¨Z;ÿ£ä®Å jäÁ¥‡ýA!Ä(‘xÎÛu&í ºWªW¬¥'i¹Š]a °ZR­žýAˆ?õëIµ^üíÈ£¨Z·Ç'ìvÕ$Èeˆ“6)óÃɱrâ ħ`yÖ˜ÒÖÖÖÂ!Õz#„UóIy<;ÈeT&ðÙt„4!%»¾š ëa#ûƒrâĉF%WU›g=fB>Œ5ê¦èÔÇ'ó±ölˆ+º®hRÄõ2‚¦úØ„øv Åb±KȈr{ìBî½AêùŒ'¨D"õÉWô¼Lð#L¡CöyýD%±û #— ñ÷ü§æ½M5ÿÍy3¨“ 5Šr³,øH,†E$îH’î8ÿÓ$ÏõR+õ–“Ì{HHUˆÄ šï¸D‰Bo%{E,.£ü÷ÝÐöä’rëÒΰ2q\#=5Êkƒ_Îo!,­B*8p²G)îéªKðúl]ŸíJœëâÖÙ­zqØ*)«ª1š‘ŸK¡jW$«Ç<"!å¹ÑZÕ –ÄͦZ§¯«Œ”9v}è-ý¬]UâÕ|¦ÅzØËþ Ä? {‡š¯¦$e )\sHH™AŠu³]ÀºEÕR▞Šèíuv ËŒÔŠžN[‰OÅ!–\Kò]Ë„xRÖ •æ5õ¨9hЬ­Œmêý~üdorx¢±InÐa39·IKLüIGË$$ÆïY¶ʾO=ÕõŸ_üâøû>šüø3Ÿ¹}7¾ñ“ãÇŸÙªÄw@mÐ|ûÂýÏ}í}[þÙϾ=öíÛø¿~ö³Ë>ùäs[¥:®Û÷5-(’É€û9Îíqsßt[6Z}™ö óJJoÇõ‘ˆ*)œ• !•²8µÈšÅ©ìÒż‹žý_vJîÌU&['„BH©ܓݪ-Š`e°‹gþwQÕ–E v²?!„R.Ñv» °f´kÅá’$ÄîfB!¤’B¤]‚\Rb­¢`<üÿIć½ªÙ'„B9,a’5oÓ½(u£Yέ2ý”õ¢+‡„B¡`d_׈õ6)–\®9$„Bc÷kQ{†UR!„â7ÁØŸ„!ö\ÊóF„9ûŽB!¾ŒSRëèÆä=Vÿ¸·¯šEîH@JsUB!¤Z„P“jç$a·Ž””HÝ* À€;Þ:#¹ “Òa^'„B©fÁ’Ã’‡¢qN\Ó >Ê—D §Ä-çõ@!„’]<ÕJµ—)Ià×t¯¸b=ji´ÓÖÄÅ•œ”6*ï1} !„BÈ>ÅU£¤}¥m]µ;â–mÄë­c’||ÐáV¿Ä‡„B!¥_¡t [ ^5„ã†j³²Ö±½²iwlAØ".ò)ù.)‰èR­ƒi€!„BG<6I$ðˆˆ³]‰¤Þ(á±>ŠÀ쑵MÙK Úîá°ÑZE|öËúÉY¨»ÒÖD ö§Ýâ„B!ĭ±NÜÕQYçØ'"ñЏ¯—Ä…µ–£Ý5Ö&¥Þ¢¬¼ Çk¡…B!„B!„B!¤ü?~’3o6è?îIEND®B`‚grpc-1.3.2/doc/internationalization.md000066400000000000000000000037321310511640000200000ustar00rootroot00000000000000gRPC Internationalization ========================= As a universal RPC framework, gRPC needs to be fully usable within/across different international environments. This document describes gRPC API and behavior specifics when used in a non-english environment. ## API Concepts While some API elements need to be able to represent non-english content, some are intentionally left as ASCII-only for simplicity & performance reasons. ### Method name (in RPC Invocation) Method names are ASCII-only and may only contain characters allowed by HTTP/2 text header values. That should not be very limiting as most gRPC services will use protobuf which only allows method names from an even more restricted ASCII subset. Also, handling method names is a very hot code path so any additional encoding/decoding step is to be avoided. Recommended representation in language-specific APIs: string type. ### Host name (in RPC Invocation) Host names are punycode encoded, but the user is responsible for providing the punycode-encoded string if she wishes to use an internationalized host name. Recommended representation in language-specific APIs: string/unicode string. NOTE: overriding host name when invoking RPCs is only supported by C-core based gRPC implementations. ### Status detail/message (accompanies RPC status code) Status messages are expected to contain national-alphabet characters. Allowed values are unicode strings (content will be percent-encoded on the wire). Recommended representation in language-specific APIs: unicode string. ### Metadata key Allowed values are defined by HTTP/2 standard (metadata keys are represented as HTTP/2 header/trailer names). Recommended representation in language-specific APIs: string. ### Metadata value (text-valued metadata) Allowed values are defined by HTTP/2 standard (metadata values are represented as HTTP/2 header/trailer text values). Recommended representation in language-specific APIs: string. ### Channel target (in channel creation) TBD grpc-1.3.2/doc/interop-test-descriptions.md000066400000000000000000000721351310511640000206770ustar00rootroot00000000000000Interoperability Test Case Descriptions ======================================= Client and server use [test.proto](../src/proto/grpc/testing/test.proto) and the [gRPC over HTTP/2 v2 protocol](./PROTOCOL-HTTP2.md). Client ------ Clients implement test cases that test certain functionally. Each client is provided the test case it is expected to run as a command-line parameter. Names should be lowercase and without spaces. Clients should accept these arguments: * --server_host=HOSTNAME * The server host to connect to. For example, "localhost" or "127.0.0.1" * --server_host_override=HOSTNAME * The server host to claim to be connecting to, for use in TLS and HTTP/2 :authority header. If unspecified, the value of --server_host will be used * --server_port=PORT * The server port to connect to. For example, "8080" * --test_case=TESTCASE * The name of the test case to execute. For example, "empty_unary" * --use_tls=BOOLEAN * Whether to use a plaintext or encrypted connection * --use_test_ca=BOOLEAN * Whether to replace platform root CAs with [ca.pem](https://github.com/grpc/grpc/blob/master/src/core/tsi/test_creds/ca.pem) as the CA root * --default_service_account=ACCOUNT_EMAIL * Email of the GCE default service account. * --oauth_scope=SCOPE * OAuth scope. For example, "https://www.googleapis.com/auth/xapi.zoo" * --service_account_key_file=PATH * The path to the service account JSON key file generated from GCE developer console. Clients must support TLS with ALPN. Clients must not disable certificate checking. ### empty_unary This test verifies that implementations support zero-size messages. Ideally, client implementations would verify that the request and response were zero bytes serialized, but this is generally prohibitive to perform, so is not required. Server features: * [EmptyCall][] Procedure: 1. Client calls EmptyCall with the default Empty message Client asserts: * call was successful * response is non-null *It may be possible to use UnaryCall instead of EmptyCall, but it is harder to ensure that the proto serialized to zero bytes.* ### cacheable_unary This test verifies that gRPC requests marked as cacheable use GET verb instead of POST, and that server sets appropriate cache control headers for the response to be cached by a proxy. This test requires that the server is behind a caching proxy. Use of current timestamp in the request prevents accidental cache matches left over from previous tests. Server features: * [CacheableUnaryCall][] Procedure: 1. Client calls CacheableUnaryCall with `SimpleRequest` request with payload set to current timestamp. Timestamp format is irrelevant, and resolution is in nanoseconds. Client adds a `x-user-ip` header with value `1.2.3.4` to the request. This is done since some proxys such as GFE will not cache requests from localhost. Client marks the request as cacheable by setting the cacheable flag in the request context. Longer term this should be driven by the method option specified in the proto file itself. 2. Client calls CacheableUnaryCall with `SimpleRequest` request again immediately with the same payload as the previous request. Cacheable flag is also set for this request's context. Client asserts: * Both calls were successful * The payload body of both responses is the same. ### large_unary This test verifies unary calls succeed in sending messages, and touches on flow control (even if compression is enabled on the channel). Server features: * [UnaryCall][] Procedure: 1. Client calls UnaryCall with: ``` { response_size: 314159 payload:{ body: 271828 bytes of zeros } } ``` Client asserts: * call was successful * response payload body is 314159 bytes in size * clients are free to assert that the response payload body contents are zero and comparing the entire response message against a golden response ### client_compressed_unary This test verifies the client can compress unary messages by sending two unary calls, for compressed and uncompressed payloads. It also sends an initial probing request to verify whether the server supports the [CompressedRequest][] feature by checking if the probing call fails with an `INVALID_ARGUMENT` status. Server features: * [UnaryCall][] * [CompressedRequest][] Procedure: 1. Client calls UnaryCall with the feature probe, an *uncompressed* message: ``` { expect_compressed:{ value: true } response_size: 314159 payload:{ body: 271828 bytes of zeros } } ``` 1. Client calls UnaryCall with the *compressed* message: ``` { expect_compressed:{ value: true } response_size: 314159 payload:{ body: 271828 bytes of zeros } } ``` 1. Client calls UnaryCall with the *uncompressed* message: ``` { expect_compressed:{ value: false } response_size: 314159 payload:{ body: 271828 bytes of zeros } } ``` Client asserts: * First call failed with `INVALID_ARGUMENT` status. * Subsequent calls were successful. * Response payload body is 314159 bytes in size. * Clients are free to assert that the response payload body contents are zeros and comparing the entire response message against a golden response. ### server_compressed_unary This test verifies the server can compress unary messages. It sends two unary requests, expecting the server's response to be compressed or not according to the `response_compressed` boolean. Whether compression was actually performed is determined by the compression bit in the response's message flags. *Note that some languages may not have access to the message flags*. Server features: * [UnaryCall][] * [CompressedResponse][] Procedure: 1. Client calls UnaryCall with `SimpleRequest`: ``` { response_compressed:{ value: true } response_size: 314159 payload:{ body: 271828 bytes of zeros } } ``` ``` { response_compressed:{ value: false } response_size: 314159 payload:{ body: 271828 bytes of zeros } } ``` Client asserts: * call was successful * when `response_compressed` is true, the response MUST have the compressed message flag set. * when `response_compressed` is false, the response MUST NOT have the compressed message flag set. * response payload body is 314159 bytes in size in both cases. * clients are free to assert that the response payload body contents are zero and comparing the entire response message against a golden response ### client_streaming This test verifies that client-only streaming succeeds. Server features: * [StreamingInputCall][] Procedure: 1. Client calls StreamingInputCall 2. Client sends: ``` { payload:{ body: 27182 bytes of zeros } } ``` 3. Client then sends: ``` { payload:{ body: 8 bytes of zeros } } ``` 4. Client then sends: ``` { payload:{ body: 1828 bytes of zeros } } ``` 5. Client then sends: ``` { payload:{ body: 45904 bytes of zeros } } ``` 6. Client half-closes Client asserts: * call was successful * response aggregated_payload_size is 74922 ### client_compressed_streaming This test verifies the client can compress requests on per-message basis by performing a two-request streaming call. It also sends an initial probing request to verify whether the server supports the [CompressedRequest][] feature by checking if the probing call fails with an `INVALID_ARGUMENT` status. Procedure: 1. Client calls `StreamingInputCall` and sends the following feature-probing *uncompressed* `StreamingInputCallRequest` message ``` { expect_compressed:{ value: true } payload:{ body: 27182 bytes of zeros } } ``` If the call fails with `INVALID_ARGUMENT`, the test fails. Otherwise, we continue. 1. Client calls `StreamingInputCall` again, sending the *compressed* message ``` { expect_compressed:{ value: true } payload:{ body: 27182 bytes of zeros } } ``` 1. And finally, the *uncompressed* message ``` { expect_compressed:{ value: false } payload:{ body: 45904 bytes of zeros } } ``` 1. Client half-closes Client asserts: * First call fails with `INVALID_ARGUMENT`. * Next calls succeeds. * Response aggregated payload size is 73086. ### server_streaming This test verifies that server-only streaming succeeds. Server features: * [StreamingOutputCall][] Procedure: 1. Client calls StreamingOutputCall with `StreamingOutputCallRequest`: ``` { response_parameters:{ size: 31415 } response_parameters:{ size: 9 } response_parameters:{ size: 2653 } response_parameters:{ size: 58979 } } ``` Client asserts: * call was successful * exactly four responses * response payload bodies are sized (in order): 31415, 9, 2653, 58979 * clients are free to assert that the response payload body contents are zero and comparing the entire response messages against golden responses ### server_compressed_streaming This test verifies that the server can compress streaming messages and disable compression on individual messages. Server features: * [StreamingOutputCall][] * [CompressedResponse][] Procedure: 1. Client calls StreamingOutputCall with `StreamingOutputCallRequest`: ``` { response_parameters:{ compressed: { value: true } size: 31415 } response_parameters:{ compressed: { value: false } size: 92653 } } ``` Client asserts: * call was successful * exactly two responses * when `response_compressed` is false, the response's messages MUST NOT have the compressed message flag set. * when `response_compressed` is true, the response's messages MUST have the compressed message flag set. * response payload bodies are sized (in order): 31415, 92653 * clients are free to assert that the response payload body contents are zero and comparing the entire response messages against golden responses ### ping_pong This test verifies that full duplex bidi is supported. Server features: * [FullDuplexCall][] Procedure: 1. Client calls FullDuplexCall with: ``` { response_parameters:{ size: 31415 } payload:{ body: 27182 bytes of zeros } } ``` 2. After getting a reply, it sends: ``` { response_parameters:{ size: 9 } payload:{ body: 8 bytes of zeros } } ``` 3. After getting a reply, it sends: ``` { response_parameters:{ size: 2653 } payload:{ body: 1828 bytes of zeros } } ``` 4. After getting a reply, it sends: ``` { response_parameters:{ size: 58979 } payload:{ body: 45904 bytes of zeros } } ``` 5. After getting a reply, client half-closes Client asserts: * call was successful * exactly four responses * response payload bodies are sized (in order): 31415, 9, 2653, 58979 * clients are free to assert that the response payload body contents are zero and comparing the entire response messages against golden responses ### empty_stream This test verifies that streams support having zero-messages in both directions. Server features: * [FullDuplexCall][] Procedure: 1. Client calls FullDuplexCall and then half-closes Client asserts: * call was successful * exactly zero responses ### compute_engine_creds This test is only for cloud-to-prod path. This test verifies unary calls succeed in sending messages while using Service Credentials from GCE metadata server. The client instance needs to be created with desired oauth scope. The test uses `--default_service_account` with GCE service account email and `--oauth_scope` with the OAuth scope to use. For testing against grpc-test.sandbox.googleapis.com, "https://www.googleapis.com/auth/xapi.zoo" should be passed in as `--oauth_scope`. Server features: * [UnaryCall][] * [Echo Authenticated Username][] * [Echo OAuth Scope][] Procedure: 1. Client configures channel to use GCECredentials 2. Client calls UnaryCall on the channel with: ``` { response_size: 314159 payload:{ body: 271828 bytes of zeros } fill_username: true fill_oauth_scope: true } ``` Client asserts: * call was successful * received SimpleResponse.username equals the value of `--default_service_account` flag * received SimpleResponse.oauth_scope is in `--oauth_scope` * response payload body is 314159 bytes in size * clients are free to assert that the response payload body contents are zero and comparing the entire response message against a golden response ### jwt_token_creds This test is only for cloud-to-prod path. This test verifies unary calls succeed in sending messages while using JWT token (created by the project's key file) Test caller should set flag `--service_account_key_file` with the path to json key file downloaded from https://console.developers.google.com. Alternately, if using a usable auth implementation, she may specify the file location in the environment variable GOOGLE_APPLICATION_CREDENTIALS. Server features: * [UnaryCall][] * [Echo Authenticated Username][] * [Echo OAuth Scope][] Procedure: 1. Client configures the channel to use JWTTokenCredentials 2. Client calls UnaryCall with: ``` { response_size: 314159 payload:{ body: 271828 bytes of zeros } fill_username: true } ``` Client asserts: * call was successful * received SimpleResponse.username is not empty and is in the json key file used by the auth library. The client can optionally check the username matches the email address in the key file or equals the value of `--default_service_account` flag. * response payload body is 314159 bytes in size * clients are free to assert that the response payload body contents are zero and comparing the entire response message against a golden response ### oauth2_auth_token This test is only for cloud-to-prod path and some implementations may run in GCE only. This test verifies unary calls succeed in sending messages using an OAuth2 token that is obtained out of band. For the purpose of the test, the OAuth2 token is actually obtained from a service account credentials or GCE credentials via the language-specific authorization library. The difference between this test and the other auth tests is that it first uses the authorization library to obtain an authorization token. The test - uses the flag `--service_account_key_file` with the path to a json key file downloaded from https://console.developers.google.com. Alternately, if using a usable auth implementation, it may specify the file location in the environment variable GOOGLE_APPLICATION_CREDENTIALS, *OR* if GCE credentials is used to fetch the token, `--default_service_account` can be used to pass in GCE service account email. - uses the flag `--oauth_scope` for the oauth scope. For testing against grpc-test.sandbox.googleapis.com, "https://www.googleapis.com/auth/xapi.zoo" should be passed as the `--oauth_scope`. Server features: * [UnaryCall][] * [Echo Authenticated Username][] * [Echo OAuth Scope][] Procedure: 1. Client uses the auth library to obtain an authorization token 2. Client configures the channel to use AccessTokenCredentials with the access token obtained in step 1 3. Client calls UnaryCall with the following message ``` { fill_username: true fill_oauth_scope: true } ``` Client asserts: * call was successful * received SimpleResponse.username is valid. Depending on whether a service account key file or GCE credentials was used, client should check against the json key file or GCE default service account email. * received SimpleResponse.oauth_scope is in `--oauth_scope` ### per_rpc_creds Similar to the other auth tests, this test is only for cloud-to-prod path. This test verifies unary calls succeed in sending messages using a JWT or a service account credentials set on the RPC. The test - uses the flag `--service_account_key_file` with the path to a json key file downloaded from https://console.developers.google.com. Alternately, if using a usable auth implementation, it may specify the file location in the environment variable GOOGLE_APPLICATION_CREDENTIALS - optionally uses the flag `--oauth_scope` for the oauth scope if implementator wishes to use service account credential instead of JWT credential. For testing against grpc-test.sandbox.googleapis.com, oauth scope "https://www.googleapis.com/auth/xapi.zoo" should be used. Server features: * [UnaryCall][] * [Echo Authenticated Username][] * [Echo OAuth Scope][] Procedure: 1. Client configures the channel with just SSL credentials 2. Client calls UnaryCall, setting per-call credentials to JWTTokenCredentials. The request is the following message ``` { fill_username: true } ``` Client asserts: * call was successful * received SimpleResponse.username is not empty and is in the json key file used by the auth library. The client can optionally check the username matches the email address in the key file. ### custom_metadata This test verifies that custom metadata in either binary or ascii format can be sent as initial-metadata by the client and as both initial- and trailing-metadata by the server. Server features: * [UnaryCall][] * [FullDuplexCall][] * [Echo Metadata][] Procedure: 1. The client attaches custom metadata with the following keys and values: ``` key: "x-grpc-test-echo-initial", value: "test_initial_metadata_value" key: "x-grpc-test-echo-trailing-bin", value: 0xababab ``` to a UnaryCall with request: ``` { response_size: 314159 payload:{ body: 271828 bytes of zeros } } ``` 2. The client attaches custom metadata with the following keys and values: ``` key: "x-grpc-test-echo-initial", value: "test_initial_metadata_value" key: "x-grpc-test-echo-trailing-bin", value: 0xababab ``` to a FullDuplexCall with request: ``` { response_parameters:{ size: 314159 } payload:{ body: 271828 bytes of zeros } } ``` and then half-closes Client asserts: * call was successful * metadata with key `"x-grpc-test-echo-initial"` and value `"test_initial_metadata_value"`is received in the initial metadata for calls in Procedure steps 1 and 2. * metadata with key `"x-grpc-test-echo-trailing-bin"` and value `0xababab` is received in the trailing metadata for calls in Procedure steps 1 and 2. ### status_code_and_message This test verifies unary calls succeed in sending messages, and propagate back status code and message sent along with the messages. Server features: * [UnaryCall][] * [FullDuplexCall][] * [Echo Status][] Procedure: 1. Client calls UnaryCall with: ``` { response_status:{ code: 2 message: "test status message" } } ``` 2. Client calls FullDuplexCall with: ``` { response_status:{ code: 2 message: "test status message" } } ``` and then half-closes Client asserts: * received status code is the same as the sent code for both Procedure steps 1 and 2 * received status message is the same as the sent message for both Procedure steps 1 and 2 ### unimplemented_method This test verifies that calling an unimplemented RPC method returns the UNIMPLEMENTED status code. Server features: N/A Procedure: * Client calls `grpc.testing.TestService/UnimplementedCall` with an empty request (defined as `grpc.testing.Empty`): ``` { } ``` Client asserts: * received status code is 12 (UNIMPLEMENTED) ### unimplemented_service This test verifies calling an unimplemented server returns the UNIMPLEMENTED status code. Server features: N/A Procedure: * Client calls `grpc.testing.UnimplementedService/UnimplementedCall` with an empty request (defined as `grpc.testing.Empty`) Client asserts: * received status code is 12 (UNIMPLEMENTED) ### cancel_after_begin This test verifies that a request can be cancelled after metadata has been sent but before payloads are sent. Server features: * [StreamingInputCall][] Procedure: 1. Client starts StreamingInputCall 2. Client immediately cancels request Client asserts: * Call completed with status CANCELLED ### cancel_after_first_response This test verifies that a request can be cancelled after receiving a message from the server. Server features: * [FullDuplexCall][] Procedure: 1. Client starts FullDuplexCall with ``` { response_parameters:{ size: 31415 } payload:{ body: 27182 bytes of zeros } } ``` 2. After receiving a response, client cancels request Client asserts: * Call completed with status CANCELLED ### timeout_on_sleeping_server This test verifies that an RPC request whose lifetime exceeds its configured timeout value will end with the DeadlineExceeded status. Server features: * [FullDuplexCall][] Procedure: 1. Client calls FullDuplexCall with the following request and sets its timeout to 1ms ``` { payload:{ body: 27182 bytes of zeros } } ``` 2. Client waits Client asserts: * Call completed with status DEADLINE_EXCEEDED. ### concurrent_large_unary Status: TODO Client performs 1000 large_unary tests in parallel on the same channel. ### Flow control. Pushback at client for large messages (TODO: fix name) Status: TODO This test verifies that a client sending faster than a server can drain sees pushback (i.e., attempts to send succeed only after appropriate delays). ### TODO Tests #### High priority: Propagation of status code and message (yangg) Multiple thousand simultaneous calls on same Channel (ctiller) Metadata: client headers, server headers + trailers, binary+ascii #### Normal priority: Cancel before start (ctiller) Cancel after sent first message (ctiller) Cancel after received headers (ctiller) Timeout but completed before expire (zhaoq) Multiple thousand simultaneous calls timeout on same Channel (ctiller) #### Lower priority: Flow control. Pushback at client for large messages (abhishek) Flow control. Pushback at server for large messages (abhishek) Going over max concurrent streams doesn't fail (client controls itself) (abhishek) RPC method not implemented (yangg) Multiple thousand simultaneous calls on different Channels (ctiller) Failed TLS hostname verification (ejona?) Large amount of headers to cause CONTINUATIONs; 63K of 'X's, all in one header. #### To priorize: Start streaming RPC but don't send any requests, server responds ### Postponed Tests Resilience to buggy servers: These tests would verify that a client application isn't affected negatively by the responses put on the wire by a buggy server (e.g. the client library won't make the application crash). Reconnect after transport failure Reconnect backoff Fuzz testing Server ------ Servers implement various named features for clients to test with. Server features are orthogonal. If a server implements a feature, it is always available for clients. Names are simple descriptions for developer communication and tracking. Servers should accept these arguments: * --port=PORT * The port to listen on. For example, "8080" * --use_tls=BOOLEAN * Whether to use a plaintext or encrypted connection Servers must support TLS with ALPN. They should use [server1.pem](https://github.com/grpc/grpc/blob/master/src/core/tsi/test_creds/server1.pem) for their certificate. ### EmptyCall [EmptyCall]: #emptycall Server implements EmptyCall which immediately returns the empty message. ### UnaryCall [UnaryCall]: #unarycall Server implements UnaryCall which immediately returns a SimpleResponse with a payload body of size `SimpleRequest.response_size` bytes and type as appropriate for the `SimpleRequest.response_type`. If the server does not support the `response_type`, then it should fail the RPC with `INVALID_ARGUMENT`. ### CacheableUnaryCall Server gets the default SimpleRequest proto as the request. The content of the request is ignored. It returns the SimpleResponse proto with the payload set to current timestamp. The timestamp is an integer representing current time with nanosecond resolution. This integer is formated as ASCII decimal in the response. The format is not really important as long as the response payload is different for each request. In addition it adds 1. cache control headers such that the response can be cached by proxies in the response path. Server should be behind a caching proxy for this test to pass. Currently we set the max-age to 60 seconds. ### CompressedResponse [CompressedResponse]: #compressedresponse When the client sets `response_compressed` to true, the server's response is sent back compressed. Note that `response_compressed` is present on both `SimpleRequest` (unary) and `StreamingOutputCallRequest` (streaming). ### CompressedRequest [CompressedRequest]: #compressedrequest When the client sets `expect_compressed` to true, the server expects the client request to be compressed. If it's not, it fails the RPC with `INVALID_ARGUMENT`. Note that `response_compressed` is present on both `SimpleRequest` (unary) and `StreamingOutputCallRequest` (streaming). ### StreamingInputCall [StreamingInputCall]: #streaminginputcall Server implements StreamingInputCall which upon half close immediately returns a StreamingInputCallResponse where aggregated_payload_size is the sum of all request payload bodies received. ### StreamingOutputCall [StreamingOutputCall]: #streamingoutputcall Server implements StreamingOutputCall by replying, in order, with one StreamingOutputCallResponse for each ResponseParameters in StreamingOutputCallRequest. Each StreamingOutputCallResponse should have a payload body of size ResponseParameters.size bytes, as specified by its respective ResponseParameters. After sending all responses, it closes with OK. ### FullDuplexCall [FullDuplexCall]: #fullduplexcall Server implements FullDuplexCall by replying, in order, with one StreamingOutputCallResponse for each ResponseParameters in each StreamingOutputCallRequest. Each StreamingOutputCallResponse should have a payload body of size ResponseParameters.size bytes, as specified by its respective ResponseParameters. After receiving half close and sending all responses, it closes with OK. ### Echo Status [Echo Status]: #echo-status When the client sends a response_status in the request payload, the server closes the stream with the status code and messsage contained within said response_status. The server will not process any further messages on the stream sent by the client. This can be used by clients to verify correct handling of different status codes and associated status messages end-to-end. ### Echo Metadata [Echo Metadata]: #echo-metadata When the client sends metadata with the key `"x-grpc-test-echo-initial"` with its request, the server sends back exactly this key and the corresponding value back to the client as part of initial metadata. When the client sends metadata with the key `"x-grpc-test-echo-trailing-bin"` with its request, the server sends back exactly this key and the corresponding value back to the client as trailing metadata. ### Observe ResponseParameters.interval_us [Observe ResponseParameters.interval_us]: #observe-responseparametersinterval_us In StreamingOutputCall and FullDuplexCall, server delays sending a StreamingOutputCallResponse by the ResponseParameters's `interval_us` for that particular response, relative to the last response sent. That is, `interval_us` acts like a sleep *before* sending the response and accumulates from one response to the next. Interaction with flow control is unspecified. ### Echo Auth Information Status: Pending #### Echo Authenticated Username [Echo Authenticated Username]: #echo-authenticated-username If a SimpleRequest has fill_username=true and that request was successfully authenticated, then the SimpleResponse should have username filled with the canonical form of the authenticated source. The canonical form is dependent on the authentication method, but is likely to be a base 10 integer identifier or an email address. #### Echo OAuth scope [Echo OAuth Scope]: #echo-oauth-scope If a SimpleRequest has `fill_oauth_scope=true` and that request was successfully authenticated via OAuth, then the SimpleResponse should have oauth_scope filled with the scope of the method being invoked. Although a general server-side feature, most test servers won't implement this feature. The TLS server `grpc-test.sandbox.googleapis.com:443` supports this feature. It requires at least the OAuth scope `https://www.googleapis.com/auth/xapi.zoo` for authentication to succeed. Discussion: Ideally, this would be communicated via metadata and not in the request/response, but we want to use this test in code paths that don't yet fully communicate metadata. grpc-1.3.2/doc/load-balancing.md000066400000000000000000000156141310511640000163700ustar00rootroot00000000000000Load Balancing in gRPC ====================== # Scope This document explains the design for load balancing within gRPC. # Background ## Per-Call Load Balancing It is worth noting that load-balancing within gRPC happens on a per-call basis, not a per-connection basis. In other words, even if all requests come from a single client, we still want them to be load-balanced across all servers. ## Approaches to Load Balancing Prior to any gRPC specifics, we explore some usual ways to approach load balancing. ### Proxy Model Using a proxy provides a solid trustable client that can report load to the load balancing system. Proxies typically require more resources to operate since they have temporary copies of the RPC request and response. This model also increases latency to the RPCs. The proxy model was deemed inefficient when considering request heavy services like storage. ### Balancing-aware Client This thicker client places more of the load balancing logic in the client. For example, the client could contain many load balancing policies (Round Robin, Random, etc) used to select servers from a list. In this model, a list of servers would be either statically configured in the client, provided by the name resolution system, an external load balancer, etc. In any case, the client is responsible for choosing the preferred server from the list. One of the drawbacks of this approach is writing and maintaining the load balancing policies in multiple languages and/or versions of the clients. These policies can be fairly complicated. Some of the algorithms also require client to server communication so the client would need to get thicker to support additional RPCs to get health or load information in addition to sending RPCs for user requests. It would also significantly complicate the client's code: the new design hides the load balancing complexity of multiple layers and presents it as a simple list of servers to the client. ### External Load Balancing Service The client load balancing code is kept simple and portable, implementing well-known algorithms (e.g., Round Robin) for server selection. Complex load balancing algorithms are instead provided by the load balancer. The client relies on the load balancer to provide _load balancing configuration_ and _the list of servers_ to which the client should send requests. The balancer updates the server list as needed to balance the load as well as handle server unavailability or health issues. The load balancer will make any necessary complex decisions and inform the client. The load balancer may communicate with the backend servers to collect load and health information. # Requirements ## Simple API and client The gRPC client load balancing code must be simple and portable. The client should only contain simple algorithms (e.g., Round Robin) for server selection. For complex algorithms, the client should rely on a load balancer to provide load balancing configuration and the list of servers to which the client should send requests. The balancer will update the server list as needed to balance the load as well as handle server unavailability or health issues. The load balancer will make any necessary complex decisions and inform the client. The load balancer may communicate with the backend servers to collect load and health information. ## Security The load balancer may be separate from the actual server backends and a compromise of the load balancer should only lead to a compromise of the loadbalancing functionality. In other words, a compromised load balancer should not be able to cause a client to trust a (potentially malicious) backend server any more than in a comparable situation without loadbalancing. # Architecture ## Overview The primary mechanism for load-balancing in gRPC is external load-balancing, where an external load balancer provides simple clients with an up-to-date list of servers. The gRPC client does support an API for built-in load balancing policies. However, there are only a small number of these (one of which is the `grpclb` policy, which implements external load balancing), and users are discouraged from trying to extend gRPC by adding more. Instead, new load balancing policies should be implemented in external load balancers. ## Workflow Load-balancing policies fit into the gRPC client workflow in between name resolution and the connection to the server. Here's how it all works: ![image](images/load-balancing.png) 1. On startup, the gRPC client issues a [name resolution](naming.md) request for the server name. The name will resolve to one or more IP addresses, each of which will indicate whether it is a server address or a load balancer address, and a [service config](service_config.md) that indicates which client-side load-balancing policy to use (e.g., `round_robin` or `grpclb`). 2. The client instantiates the load balancing policy. - Note: If all addresses returned by the resolver are balancer addresses, then the client will use the `grpclb` policy, regardless of what load-balancing policy was requested by the service config. Otherwise, the client will use the load-balancing policy requested by the service config. If no load-balancing policy is requested by the service config, then the client will default to a policy that picks the first available server address. 3. The load balancing policy creates a subchannel to each server address. - For all policies *except* `grpclb`, this means one subchannel for each address returned by the resolver. Note that these policies ignore any balancer addresses returned by the resolver. - In the case of the `grpclb` policy, the workflow is as follows: 1. The policy opens a stream to one of the balancer addresses returned by the resolver. It asks the balancer for the server addresses to use for the server name originally requested by the client (i.e., the same one originally passed to the name resolver). - Note: The `grpclb` policy currently ignores any non-balancer addresses returned by the resolver. However, in the future, it may be changed to use these addresses as a fallback in case no balancers can be contacted. 2. The gRPC servers to which the load balancer is directing the client may report load to the load balancers, if that information is needed by the load balancer's configuration. 3. The load balancer returns a server list to the gRPC client's `grpclb` policy. The `grpclb` policy will then create a subchannel to each of server in the list. 4. For each RPC sent, the load balancing policy decides which subchannel (i.e., which server) the RPC should be sent to. - In the case of the `grpclb` policy, the client will send requests to the servers in the order in which they were returned by the load balancer. If the server list is empty, the call will block until a non-empty one is received. grpc-1.3.2/doc/naming.md000066400000000000000000000043721310511640000150050ustar00rootroot00000000000000# gRPC Name Resolution ## Overview gRPC supports DNS as the default name-system. A number of alternative name-systems are used in various deployments. We support an API that is general enough to support a range of name-systems and the corresponding syntax for names. The gRPC client library in various languages will provide a plugin mechanism so resolvers for different name-systems can be plugged in. ## Detailed Design ### Name Syntax A fully qualified, self contained name used for gRPC channel construction uses the syntax: ``` scheme://authority/endpoint_name ``` Here, `scheme` indicates the name-system to be used. Currently, we support the following schemes: - `dns` - `ipv4` (IPv4 address) - `ipv6` (IPv6 address) - `unix` (path to unix domain socket -- unix systems only) In the future, additional schemes such as `etcd` could be added. The `authority` indicates some scheme-specific bootstrap information, e.g., for DNS, the authority may include the IP[:port] of the DNS server to use. Often, a DNS name may be used as the authority, since the ability to resolve DNS names is already built into all gRPC client libraries. Finally, the `endpoint_name` indicates a concrete name to be looked up in a given name-system identified by the scheme and the authority. The syntax of the endpoint name is dictated by the scheme in use. ### Resolver Plugins The gRPC client library will use the specified scheme to pick the right resolver plugin and pass it the fully qualified name string. Resolvers should be able to contact the authority and get a resolution that they return back to the gRPC client library. The returned contents include: - A list of resolved addresses, each of which has three attributes: - The address itself, including both IP address and port. - A boolean indicating whether the address is a backend address (i.e., the address to use to contact the server directly) or a balancer address (for cases where [external load balancing](load-balancing.md) is in use). - The name of the balancer, if the address is a balancer address. This will be used to perform peer authorization. - A [service config](service_config.md). The plugin API allows the resolvers to continuously watch an endpoint and return updated resolutions as needed. grpc-1.3.2/doc/server-reflection.md000066400000000000000000000170541310511640000171730ustar00rootroot00000000000000GRPC Server Reflection Protocol =============================== This document describes server reflection as an optional extension for servers to assist clients in runtime construction of requests without having stub information precompiled into the client. The primary usecase for server reflection is to write (typically) command line debugging tools for talking to a grpc server. In particular, such a tool will take in a method and a payload (in human readable text format) send it to the server (typically in binary proto wire format), and then take the response and decode it to text to present to the user. This broadly involves two problems: determining what formats (which protobuf messages) a server’s method uses, and determining how to convert messages between human readable format and the (likely binary) wire format. ## Method reflection We want to be able to answer the following queries: 1. What methods does a server export? 2. For a particular method, how do we call it? Specifically, what are the names of the methods, are those methods unary or streaming, and what are the types of the argument and result? ``` #TODO(dklempner): link to an actual .proto later. package grpc.reflection.v1alpha; message ListApisRequest { } message ListApisResponse { repeated google.protobuf.Api apis = 1; } message GetMethodRequest { string method = 1; } message GetMethodResponse { google.protobuf.Method method = 1; } service ServerReflection { rpc ListApis (ListApisRequest) returns (ListApisResponse); rpc GetMethod (GetMethodRequest) returns (GetMethodResponse); } ``` Note that a server is under no obligation to return a complete list of all methods it supports. For example, a reverse proxy may support server reflection for methods implemented directly on the proxy but not enumerate all methods supported by its backends. ### Open questions on method reflection * Consider how to extend this protocol to support non-protobuf methods. ## Argument reflection The second half of the problem is converting between the human readable input/output of a debugging tool and the binary format understood by the method. This is obviously dependent on protocol type. At one extreme, if both the server and the debugging tool accept JSON, there may be no need for such a conversion in the first place. At the opposite extreme, a server using a custom binary format has no hope of being supported by a generic system. The intermediate interesting common case is a server which speaks binary-proto and a debugging client which speaks either ascii-proto or json-proto. One approach would be to require servers directly support human readable input. In the future method reflection may be extended to document such support, should it become widespread or standardized. ## Protobuf descriptors A second would be for the server to export its google::protobuf::DescriptorDatabase over the wire. This is very easy to implement in C++, and Google implementations of a similar protocol already exist in C++, Go, and Java. This protocol mostly returns FileDescriptorProtos, which are a proto encoding of a parsed .proto file. It supports four queries: 1. The FileDescriptorProto for a given file name 2. The FileDescriptorProto for the file with a given symbol 3. The FileDescriptorProto for the file with a given extension 4. The list of known extension tag numbers of a given type These directly correspond to the methods of google::protobuf::DescriptorDatabase. Note that this protocol includes support for extensions, which have been removed from proto3 but are still in widespread use in Google’s codebase. Because most usecases will require also requesting the transitive dependencies of requested files, the queries will also return all transitive dependencies of the returned file. Should interesting usecases for non-transitive queries turn up later, we can easily extend the protocol to support them. ### Reverse proxy traversal One potential issue with naive reverse proxies is that, while any individual server will have a consistent and valid picture of the proto DB which is sufficient to handle incoming requests, incompatibilities will arise if the backend servers have a mix of builds. For example, if a given message is moved from foo.proto to bar.proto, and the client requests foo.proto from an old server and bar.proto from a new server, the resulting database will have a double definition. To solve this problem, the protocol is structured as a bidirectional stream, ensuring all related requests go to a single server. This has the additional benefit that overlapping recursive requests don’t require sending a lot of redundant information, because there is a single stream to maintain context between queries. ``` package grpc.reflection.v1alpha; message DescriptorDatabaseRequest { string host = 1; oneof message_request { string files_for_file_name = 3; string files_for_symbol_name = 4; FileContainingExtensionRequest file_containing_extension = 5; string list_all_extensions_of_type = 6; } } message FileContainingExtensionRequest { string base_message = 1; int64 extension_id = 2; } message DescriptorDatabaseResponse { string valid_host = 1; DescriptorDatabaseRequest original_request = 2; oneof message_response { // These are proto2 type google.protobuf.FileDescriptorProto, but // we avoid taking a dependency on descriptor.proto, which uses // proto2 only features, by making them opaque // bytes instead repeated bytes fd_proto = 4; ListAllExtensionsResponse extensions_response = 5; // Notably includes error code 5, NOT FOUND int32 error_code = 6; } } message ListAllExtensionsResponse { string base_type_name; repeated int64 extension_number; } service ProtoDescriptorDatabase { rpc DescriptorDatabaseInfo(stream DescriptorDatabaseRequest) returns (stream DescriptorDatabaseResponse); } ``` Any given request must either result in an error code or an answer, usually in the form of a series of FileDescriptorProtos with the requested file itself and all previously unsent transitive imports of that file. Servers may track which FileDescriptorProtos have been sent on a given stream, for a given value of valid_host, and avoid sending them repeatedly for overlapping requests. | message_request message | Result | | files_for_file_name | transitive closure of file name | | files_for_symbol_name | transitive closure file containing symbol | | file_containing_extension | transitive closure of file containing a given extension number of a given symbol | | list_all_extensions_of_type | ListAllExtensionsResponse containing all known extension numbers of a given type | At some point it would make sense to additionally also support any.proto’s format. Note that known any.proto messages can be queried by symbol using this protocol even without any such support, by parsing the url and extracting the symbol name from it. ## Language specific implementation thoughts All of the information needed to implement Proto reflection is available to the code generator, but I’m not certain we actually generate this in every language. If the proto implementation in the language doesn’t have something like google::protobuf::DescriptorPool the grpc implementation for that language will need to index those FileDescriptorProtos by file and symbol and imports. One issue is that some grpc implementations are very loosely coupled with protobufs; in such implementations it probably makes sense to split apart these reflection APIs so as not to take an additional proto dependency. grpc-1.3.2/doc/server_reflection_tutorial.md000066400000000000000000000131131310511640000211700ustar00rootroot00000000000000# gRPC Server Reflection Tutorial gRPC Server Reflection provides information about publicly-accessible gRPC services on a server, and assists clients at runtime to construct RPC requests and responses without precompiled service information. It is used by gRPC CLI, which can be used to introspect server protos and send/receive test RPCs. ## Enable Server Reflection ### Enable server reflection in C++ servers C++ Server Reflection is an add-on library, `libgrpc++_reflction`. To enable C++ server reflection, you can link this library to your server binary. Some platforms (e.g. Ubuntu 11.10 onwards) only link in libraries that directly contain symbols used by the application. On these platforms, LD flag `--no-as-needed` is needed for for dynamic linking and `--whole-archive` is needed for for static linking. This [Makefile](../examples/cpp/helloworld/Makefile#L37#L45) demonstrates enabling c++ server reflection on Linux and MacOS. ## Test services using Server Reflection After enabling Server Reflection in a server application, you can use gRPC CLI to test its services. Instructions on how to use gRPC CLI can be found at [command_line_tool.md](command_line_tool.md), or using `grpc_cli help` command. Here we use `examples/cpp/helloworld` as an example to show the use of gRPC Server Reflection and gRPC CLI. First, we need to build gRPC CLI and setup an example server with Server Reflection enabled. - Setup an example server Server Reflection has already been enabled in the [Makefile](../examples/cpp/helloworld/Makefile) of the helloworld example. We can simply make it and run the greeter_server. ```sh $ make -C examples/cpp/helloworld $ examples/cpp/helloworld/greeter_server & ``` - Build gRPC CLI ```sh make grpc_cli cd bins/opt ``` gRPC CLI binary `grpc_cli` can be found at `bins/opt/` folder. This tool is still new and does not have a `make install` target yet. ### List services `grpc_cli ls` command lists services and methods exposed at a given port - List all the services exposed at a given port ```sh $ grpc_cli ls localhost:50051 ``` output: ```sh helloworld.Greeter grpc.reflection.v1alpha.ServerReflection ``` - List one service with details `grpc_cli ls` command inspects a service given its full name (in the format of \.\). It can print information with a long listing format when `-l` flag is set. This flag can be used to get more details about a service. ```sh $ grpc_cli ls localhost:50051 helloworld.Greeter -l ``` output: ```sh filename: helloworld.proto package: helloworld; service Greeter { rpc SayHello(helloworld.HelloRequest) returns (helloworld.HelloReply) {} } ``` ### List methods - List one method with details `grpc_cli ls` command also inspects a method given its full name (in the format of \.\.\). ```sh $ grpc_cli ls localhost:50051 helloworld.Greeter.SayHello -l ``` output: ```sh rpc SayHello(helloworld.HelloRequest) returns (helloworld.HelloReply) {} ``` ### Inspect message types We can use`grpc_cli type` command to inspect request/response types given the full name of the type (in the format of \.\). - Get information about the request type ```sh $ grpc_cli type localhost:50051 helloworld.HelloRequest ``` output: ```sh message HelloRequest { optional string name = 1; } ``` ### Call a remote method We can send RPCs to a server and get responses using `grpc_cli call` command. - Call a unary method ```sh $ grpc_cli call localhost:50051 SayHello "name: 'gRPC CLI'" ``` output: ```sh message: "Hello gRPC CLI" ``` ## Use Server Reflection in a C++ client Server Reflection can be used by clients to get information about gRPC services at runtime. We've provided a descriptor database called [grpc::ProtoReflectionDescriptorDatabase](../test/cpp/util/proto_reflection_descriptor_database.h) which implements the [google::protobuf::DescriptorDatabase](https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.descriptor_database#DescriptorDatabase) interface. It manages the communication between clients and reflection services and the storage of received information. Clients can use it as using a local descriptor database. - To use Server Reflection with grpc::ProtoReflectionDescriptorDatabase, first initialize an instance with a grpc::Channel. ```c++ std::shared_ptr channel = grpc::CreateChannel(server_address, server_cred); grpc::ProtoReflectionDescriptorDatabase reflection_db(channel); ``` - Then use this instance to feed a [google::protobuf::DescriptorPool](https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.descriptor#DescriptorPool). ```c++ google::protobuf::DescriptorPool desc_pool(&reflection_db); ``` - Example usage of this descriptor pool * Get Service/method descriptors. ```c++ const google::protobuf::ServiceDescriptor* service_desc = desc_pool->FindServiceByName("helloworld.Greeter"); const google::protobuf::MethodDescriptor* method_desc = desc_pool->FindMethodByName("helloworld.Greeter.SayHello"); ``` * Get message type descriptors. ```c++ const google::protobuf::Descriptor* request_desc = desc_pool->FindMessageTypeByName("helloworld.HelloRequest"); ``` * Feed [google::protobuf::DynamicMessageFactory](https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.dynamic_message#DynamicMessageFactory). ```c++ google::protobuf::DynamicMessageFactory(&desc_pool); ``` grpc-1.3.2/doc/server_side_auth.md000066400000000000000000000070021310511640000170600ustar00rootroot00000000000000Server-side API for Authenticating Clients ========================================== NOTE: This document describes how server-side authentication works in C-core based gRPC implementations only. In gRPC Java and Go, server side authentication is handled differently. ## AuthContext To perform server-side authentication, gRPC exposes the *authentication context* for each call. The context exposes important authentication-related information about the RPC such as the type of security/authentication type being used and the peer identity. The authentication context is structured as a multi-map of key-value pairs - the *auth properties*. In addition to that, for authenticated RPCs, the set of properties corresponding to a selected key will represent the verified identity of the caller - the *peer identity*. The contents of the *auth properties* are populated by an *auth interceptor*. The interceptor also chooses which property key will act as the peer identity (e.g. for client certificate authentication this property will be `"x509_common_name"` or `"x509_subject_alternative_name"`). WARNING: AuthContext is the only reliable source of truth when it comes to authenticating RPCs. Using any other call/context properties for authentication purposes is wrong and inherently unsafe. ####Example AuthContext contents For secure channel using mutual TLS authentication with both client and server certificates (test certificates from this repository are used). Populated auth properties: ``` "transport_security_type": "ssl" # connection is secured using TLS/SSL "x509_common_name": "*.test.google.com" # from client's certificate "x509_pem_cert": "-----BEGIN CERTIFICATE-----\n..." # client's PEM encoded certificate "x509_subject_alternative_name": "*.test.google.fr" "x509_subject_alternative_name": "waterzooi.test.google.be" "x509_subject_alternative_name": "*.test.youtube.com" "x509_subject_alternative_name": "192.168.1.3" ``` The peer identity is set of all properties named `"x509_subject_alternative_name"`: ``` peer_identity_property_name = "x509_subject_alternative_name" ``` ## AuthProperty Auth properties are elements of the AuthContext. They have a name (a key of type string) and a value which can be a string or binary data. ## Auth Interceptors Auth interceptors are gRPC components that populate contents of the auth context based on gRPC's internal state and/or call metadata. gRPC comes with some basic "interceptors" already built-in. WARNING: While there is a public API that allows anyone to write their own custom interceptor, please think twice before using it. There are legitimate uses for custom interceptors but you should keep in mind that as auth interceptors essentially decide which RPCs are authenticated and which are not, their code is very sensitive from the security perspective and getting things wrong might have serious consequences. If unsure, we strongly recommend to rely on official & proven interceptors that come with gRPC. ####Available auth interceptors - TLS/SSL certificate authentication (built into gRPC's security layer, automatically used whenever you use a secure connection) - (coming soon) JWT auth token authentication - more will be added over time ## Status (by language) C-core exposes low level API to access auth context contents and to implement an auth interceptor. In C++, the auth interceptor API is exposed as `AuthMetadataProcessor`. A high level API to access AuthContext contents is available in these languages: - C++ - C# (implementation in-progress) - other languages coming soon grpc-1.3.2/doc/service_config.md000066400000000000000000000135611310511640000165210ustar00rootroot00000000000000Service Config in gRPC ====================== # Objective The service config is a mechanism that allows service owners to publish parameters to be automatically used by all clients of their service. # Format The service config is a JSON string of the following form: ``` { // Load balancing policy name. // Supported values are 'round_robin' and 'grpclb'. // Optional; if unset, the default behavior is pick the first available // backend. // Note that if the resolver returns only balancer addresses and no // backend addresses, gRPC will always use the 'grpclb' policy, // regardless of what this field is set to. 'loadBalancingPolicy': string, // Per-method configuration. Optional. 'methodConfig': [ { // The names of the methods to which this method config applies. There // must be at least one name. Each name entry must be unique across the // entire service config. If the 'method' field is empty, then this // method config specifies the defaults for all methods for the specified // service. // // For example, let's say that the service config contains the following // method config entries: // // 'methodConfig': [ // { 'name': [ { 'service': 'MyService' } ] ... }, // { 'name': [ { 'service': 'MyService', 'method': 'Foo' } ] ... } // ] // // For a request for MyService/Foo, we will use the second entry, because // it exactly matches the service and method name. // For a request for MyService/Bar, we will use the first entry, because // it provides the default for all methods of MyService. 'name': [ { // RPC service name. Required. // If using gRPC with protobuf as the IDL, then this will be of // the form "pkg.service_name", where "pkg" is the package name // defined in the proto file. 'service': string, // RPC method name. Optional (see above). 'method': string, } ], // Whether RPCs sent to this method should wait until the connection is // ready by default. If false, the RPC will abort immediately if there // is a transient failure connecting to the server. Otherwise, gRPC will // attempt to connect until the deadline is exceeded. // // The value specified via the gRPC client API will override the value // set here. However, note that setting the value in the client API will // also affect transient errors encountered during name resolution, // which cannot be caught by the value here, since the service config // is obtained by the gRPC client via name resolution. 'waitForReady': bool, // The default timeout in seconds for RPCs sent to this method. This can // be overridden in code. If no reply is received in the specified amount // of time, the request is aborted and a deadline-exceeded error status // is returned to the caller. // // The actual deadline used will be the minimum of the value specified // here and the value set by the application via the gRPC client API. // If either one is not set, then the other will be used. // If neither is set, then the request has no deadline. // // The format of the value is that of the 'Duration' type defined here: // https://developers.google.com/protocol-buffers/docs/proto3#json 'timeout': string, // The maximum allowed payload size for an individual request or object // in a stream (client->server) in bytes. The size which is measured is // the serialized, uncompressed payload in bytes. This applies both // to streaming and non-streaming requests. // // The actual value used is the minimum of the value specified here and // the value set by the application via the gRPC client API. // If either one is not set, then the other will be used. // If neither is set, then the built-in default is used. // // If a client attempts to send an object larger than this value, it // will not be sent and the client will see an error. // Note that 0 is a valid value, meaning that the request message must // be empty. 'maxRequestMessageBytes': number, // The maximum allowed payload size for an individual response or object // in a stream (server->client) in bytes. The size which is measured is // the serialized, uncompressed payload in bytes. This applies both // to streaming and non-streaming requests. // // The actual value used is the minimum of the value specified here and // the value set by the application via the gRPC client API. // If either one is not set, then the other will be used. // If neither is set, then the built-in default is used. // // If a server attempts to send an object larger than this value, it // will not be sent, and the client will see an error. // Note that 0 is a valid value, meaning that the response message must // be empty. 'maxResponseMessageBytes': number } ] } ``` Note that new per-method parameters may be added in the future as new functionality is introduced. # Architecture A service config is associated with a server name. The [name resolver](naming.md) plugin, when asked to resolve a particular server name, will return both the resolved addresses and the service config. TODO(roth): Design how the service config will be encoded in DNS. # APIs The service config is used in the following APIs: - In the resolver API, used by resolver plugins to return the service config to the gRPC client. - In the gRPC client API, where users can query the channel to obtain the service config associated with the channel (for debugging purposes). - In the gRPC client API, where users can set the service config explicitly. This is intended for use in unit tests. grpc-1.3.2/doc/status_ordering.md000066400000000000000000000016371310511640000167510ustar00rootroot00000000000000Ordering Status and Reads in the gRPC API ----------------------------------------- Rules for implementors: 1. Reads and Writes Must not succeed after Status has been delivered. 2. OK Status is only delivered after all buffered messages are read. 3. Reads May continue to succeed after a failing write. However, once a write fails, all subsequent writes Must fail, and similarly, once a read fails, all subsequent reads Must fail. 4. When an error status is known to the library, if the user asks for status, the library Should discard messages received in the library but not delivered to the user and then deliver the status. If the user does not ask for status but continues reading, the library Should deliver buffered messages before delivering status. The library MAY choose to implement the stricter version where errors cause all buffered messages to be dropped, but this is not a requirement. grpc-1.3.2/doc/statuscodes.md000066400000000000000000000061251310511640000160730ustar00rootroot00000000000000# Status codes and their use in gRPC gRPC uses a set of well defined status codes as part of the RPC API. All RPCs started at a client return a `status` object composed of an integer `code` and a string `message`. The server-side can choose the status it returns for a given RPC. The gRPC client and server-side implementations may also generate and return `status` on their own when errors happen. Only a subset of the pre-defined status codes are generated by the gRPC libraries. This allows applications to be sure that any other code it sees was actually returned by the application (although it is also possible for the server-side to return one of the codes generated by the gRPC libraries). The following table lists the codes that may be returned by the gRPC libraries (on either the client-side or server-side) and summarizes the situations in which they are generated. | Case | Code | Generated at Client or Server | | ------------- |:-------------| :-----:| | Client Application cancelled the request | CANCELLED | Both | | Deadline expires before server returns status | DEADLINE_EXCEEDED | Both | | Method not found at server | UNIMPLEMENTED | Server| | Server shutting down | UNAVAILABLE | Server| | Server side application throws an exception (or does something other than returning a Status code to terminate an RPC) | UNKNOWN | Server| | No response received before Deadline expires. This may occur either when the client is unable to send the request to the server or when the server fails to respond in time. | DEADLINE_EXCEEDED | Both| | Some data transmitted (e.g., request metadata written to TCP connection) before connection breaks | UNAVAILABLE | Client | | Could not decompress, but compression algorithm supported (Client -> Server) | INTERNAL | Server | | Could not decompress, but compression algorithm supported (Server -> Client) | INTERNAL | Client | | Compression mechanism used by client not supported at server | UNIMPLEMENTED | Server | | Server temporarily out of resources (e.g., Flow-control resource limits reached) | RESOURCE_EXHAUSTED | Server| | Client does not have enough memory to hold the server response | RESOURCE_EXHAUSTED | Client | | Flow-control protocol violation | INTERNAL | Both | | Error parsing returned status | UNKNOWN | Client | | Incorrect Auth metadata ( Credentials failed to get metadata, Incompatible credentials set on channel and call, Invalid host set in `:authority` metadata, etc.) | UNAUTHENTICATED | Both | | Request cardinality violation (method requires exactly one request but client sent some other number of requests) | UNIMPLEMENTED | Server| | Response cardinality violation (method requires exactly one response but server sent some other number of responses) | UNIMPLEMENTED | Client| | Error parsing response proto | INTERNAL | Client| | Error parsing request proto | INTERNAL | Server| | Sent or received message was larger than configured limit | RESOURCE_EXHAUSTED | Both | The following status codes are never generated by the library: - INVALID_ARGUMENT - NOT_FOUND - ALREADY_EXISTS - FAILED_PRECONDITION - ABORTED - OUT_OF_RANGE - DATA_LOSS grpc-1.3.2/doc/stress_test_framework.md000066400000000000000000000117001310511640000201640ustar00rootroot00000000000000# Stress Test framework for gRPC (Sree Kuchibhotla - sreek@) > Status: This is implemented. More details at [README.md](https://github.com/grpc/grpc/blob/master/tools/run_tests/stress_test/README.md) **I. GOALS** 1) Build a stress test suite for gRPC: * Build a stress test suite that can Identify bugs by testing the system (gRPC server/client) under extreme conditions: * High load * High concurrency * Limited resources * Intermittent failures * Should be integrated with Jenkins CI 2) Make it generic enough (i.e build a generic test framework) that can be used for: * Executing M instances of a client against N instances of a server with an arbitrarily defined connection matrix * Execute heterogenous test configurations - for example: Java stress test clients against C++ servers or Node clients against Python servers or TSAN C++ clients vs ASAN C++ Servers etc. * Easy and Flexible enough that Devs can use it to recreate complex test scenarios The implementation effort is divided into two parts: * Building a "Stress Test Framework" to run the stress test suites- More details in **Section II** (The idea is that the Stress Test framework is generic enough that it would be easier to modify it to run other suites like interop-tests or custom test scenarios) * Building a 'Stress test suite' - More details in **section III** **Terminology:** GCE - Google compute engine GKE - Google Container engine Kubernetes - Google's open source service scheduler / orchestrator. **Note:** The terms GKE and Kubernetes are used interchangeably in this document # II. STRESS TEST FRAMEWORK (The details of each step are explained below)) ![image](images/stress_test_framework.png) **Figure 1** ### Step 1 Read the test config, generate base docker images **_Test Config:_** The test configuration contains the following information: * _GKE info:_ GKE project and cluster info * _Docker images:_ Instructions to build docker images * _Client templates:_ One or more client templates each containing the following information: * Which docker image to use * Path to the client program to launch (within the docker image) * Parameters to the client program * _Server templates:_ Similar to Client templates - except that these are for servers * Test matrix containing the following: * _Server groups:_ One or more groups of servers containing the following info for each group * Which server template to use * How many instances to launch * _Client groups:_ One or more groups of clients containing the following (for each group): * Which client template to use * How many instances to launch * Which server group to talk to (all clients in this group will talk to all servers in the server group) The first step is to read the test config and build the docker images **_Stress server docker image:_** The following are the main files in the server docker images * _Interop_server:_ The server program * `run_server.py`: This is a python script which is the entry point of the docker image (i.e this is the script that is called when the docker image is run in GKE). This script launches the interop server and also updates the status in BigQuery. If the interop_server fails for whatever reason, the script launch_server.py logs that status in BigQuery **_Stress client docker image:_** * Stress client: The stress test client. In addition to talking to the interop_server, the stress client also exports metrics (which can be queried by the metrics_client described below) * Metrics client: Metrics client connects to the stress_client to get the current qps metrics. * `run_client.py`: This is a python script which is the entry point of the docker image (i.e this is the script that is called when the docker image is run in GKE). This script launches the stress client and also updates the status in BigQuery. The script then periodically launches metrics client to query the qps from the stress client and then uploads the qps to BigQuery. ### Step 2) Upload the docker images to GKE The docker images are uploaded to the GKE registry ### Step 3) Launch the tests in GKE The test driver reads the test matrix (described in step 1) and creates the necessary server and client pods in GKE. ### Step 4) Tests are run in GKE GKE starts running the tests by calling the entry points in *each* docker image (i.e `run_server.py` or `run_client.py` depending on whcih docker image it is) ### Step 5) Upload the status to GKE and Monitor the status in GKE * 5.1 The tests periodically update their status in BigQuery * 5.2 The test driver periodically checks the status in Bigquery to see if any tests failed. If any tests failed, the driver immediately stops the tests. If not, the driver continues to run the tests for a configurable amount of time. ### Step 6) Create a summary report The test driver creates a final summary report containing details about any test failures and information about how to connect the failed pods in GKE for debugging. grpc-1.3.2/doc/wait-for-ready.md000066400000000000000000000014551310511640000163650ustar00rootroot00000000000000gRPC Wait for Ready Semantics ============================= If an RPC is issued but the channel is in `TRANSIENT_FAILURE` or `SHUTDOWN` states, the RPC is unable to be transmited promptly. By default, gRPC implementations SHOULD fail such RPCs immediately. This is known as "fail fast," but usage of the term is historical. RPCs SHOULD NOT fail as a result of the channel being in other states (`CONNECTING`, `READY`, or `IDLE`). gRPC implementations MAY provide a per-RPC option to not fail RPCs as a result of the channel being in `TRANSIENT_FAILURE` state. Instead, the implementation queues the RPCs until the channel is `READY`. This is known as "wait for ready." The RPCs SHOULD still fail before `READY` if there are unrelated reasons, such as the channel is `SHUTDOWN` or the RPC's deadline is reached. grpc-1.3.2/etc/000077500000000000000000000000001310511640000132125ustar00rootroot00000000000000grpc-1.3.2/etc/README.md000066400000000000000000000003071310511640000144710ustar00rootroot00000000000000The roots.pem file is periodically generated from: https://hg.mozilla.org/mozilla-central/raw-file/tip/security/nss/lib/ckfw/builtins/certdata.txt using https://github.com/agl/extract-nss-root-certs grpc-1.3.2/etc/roots.pem000066400000000000000000011704131310511640000150720ustar00rootroot00000000000000# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # Issuer: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA # Subject: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA # Label: "GlobalSign Root CA" # Serial: 4835703278459707669005204 # MD5 Fingerprint: 3e:45:52:15:09:51:92:e1:b7:5d:37:9f:b1:87:29:8a # SHA1 Fingerprint: b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c # SHA256 Fingerprint: eb:d4:10:40:e4:bb:3e:c7:42:c9:e3:81:d3:1e:f2:a4:1a:48:b6:68:5c:96:e7:ce:f3:c1:df:6c:d4:33:1c:99 -----BEGIN CERTIFICATE----- MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp 1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE 38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== -----END CERTIFICATE----- # Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 # Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 # Label: "GlobalSign Root CA - R2" # Serial: 4835703278459682885658125 # MD5 Fingerprint: 94:14:77:7e:3e:5e:fd:8f:30:bd:41:b0:cf:e7:d0:30 # SHA1 Fingerprint: 75:e0:ab:b6:13:85:12:27:1c:04:f8:5f:dd:de:38:e4:b7:24:2e:fe # SHA256 Fingerprint: ca:42:dd:41:74:5f:d0:b8:1e:b9:02:36:2c:f9:d8:bf:71:9d:a1:bd:1b:1e:fc:94:6f:5b:4c:99:f4:2c:1b:9e -----BEGIN CERTIFICATE----- MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG 3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO 291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== -----END CERTIFICATE----- # Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only # Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only # Label: "Verisign Class 3 Public Primary Certification Authority - G3" # Serial: 206684696279472310254277870180966723415 # MD5 Fingerprint: cd:68:b6:a7:c7:c4:ce:75:e0:1d:4f:57:44:61:92:09 # SHA1 Fingerprint: 13:2d:0d:45:53:4b:69:97:cd:b2:d5:c3:39:e2:55:76:60:9b:5c:c6 # SHA256 Fingerprint: eb:04:cf:5e:b1:f3:9a:fa:76:2f:2b:b1:20:f2:96:cb:a5:20:c1:b9:7d:b1:58:95:65:b8:1c:b9:a1:7b:72:44 -----BEGIN CERTIFICATE----- MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te 2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC /Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== -----END CERTIFICATE----- # Issuer: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited # Subject: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited # Label: "Entrust.net Premium 2048 Secure Server CA" # Serial: 946069240 # MD5 Fingerprint: ee:29:31:bc:32:7e:9a:e6:e8:b5:f7:51:b4:34:71:90 # SHA1 Fingerprint: 50:30:06:09:1d:97:d4:f5:ae:39:f7:cb:e7:92:7d:7d:65:2d:34:31 # SHA256 Fingerprint: 6d:c4:71:72:e0:1c:bc:b0:bf:62:58:0d:89:5f:e2:b8:ac:9a:d4:f8:73:80:1e:0c:10:b9:c8:37:d2:1e:b1:77 -----BEGIN CERTIFICATE----- MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3 MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH 4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+ bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er fF6adulZkMV8gzURZVE= -----END CERTIFICATE----- # Issuer: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust # Subject: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust # Label: "Baltimore CyberTrust Root" # Serial: 33554617 # MD5 Fingerprint: ac:b6:94:a5:9c:17:e0:d7:91:52:9b:b1:97:06:a6:e4 # SHA1 Fingerprint: d4:de:20:d0:5e:66:fc:53:fe:1a:50:88:2c:78:db:28:52:ca:e4:74 # SHA256 Fingerprint: 16:af:57:a9:f6:76:b0:ab:12:60:95:aa:5e:ba:de:f2:2a:b3:11:19:d6:44:ac:95:cd:4b:93:db:f3:f2:6a:eb -----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp -----END CERTIFICATE----- # Issuer: CN=AddTrust Class 1 CA Root O=AddTrust AB OU=AddTrust TTP Network # Subject: CN=AddTrust Class 1 CA Root O=AddTrust AB OU=AddTrust TTP Network # Label: "AddTrust Low-Value Services Root" # Serial: 1 # MD5 Fingerprint: 1e:42:95:02:33:92:6b:b9:5f:c0:7f:da:d6:b2:4b:fc # SHA1 Fingerprint: cc:ab:0e:a0:4c:23:01:d6:69:7b:dd:37:9f:cd:12:eb:24:e3:94:9d # SHA256 Fingerprint: 8c:72:09:27:9a:c0:4e:27:5e:16:d0:7f:d3:b7:75:e8:01:54:b5:96:80:46:e3:1f:52:dd:25:76:63:24:e9:a7 -----BEGIN CERTIFICATE----- MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEU MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMw MTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYD VQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUA A4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ul CDtbKRY654eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6n tGO0/7Gcrjyvd7ZWxbWroulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyl dI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJch PXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC +Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0O BBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E BTADAQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBl MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk ZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENB IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0MkhHma6X 7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0PhiVYrqW9yTkkz 43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJl pz/+0WatC7xrmYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOA WiFeIc9TVPC6b4nbqKqVz4vjccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= -----END CERTIFICATE----- # Issuer: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network # Subject: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network # Label: "AddTrust External Root" # Serial: 1 # MD5 Fingerprint: 1d:35:54:04:85:78:b0:3f:42:42:4d:bf:20:73:0a:3f # SHA1 Fingerprint: 02:fa:f3:e2:91:43:54:68:60:78:57:69:4d:f5:e4:5b:68:85:18:68 # SHA256 Fingerprint: 68:7f:a4:51:38:22:78:ff:f0:c8:b1:1f:8d:43:d5:76:67:1c:6e:b2:bc:ea:b4:13:fb:83:d9:65:d0:6d:2f:f2 -----BEGIN CERTIFICATE----- MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= -----END CERTIFICATE----- # Issuer: CN=AddTrust Public CA Root O=AddTrust AB OU=AddTrust TTP Network # Subject: CN=AddTrust Public CA Root O=AddTrust AB OU=AddTrust TTP Network # Label: "AddTrust Public Services Root" # Serial: 1 # MD5 Fingerprint: c1:62:3e:23:c5:82:73:9c:03:59:4b:2b:e9:77:49:7f # SHA1 Fingerprint: 2a:b6:28:48:5e:78:fb:f3:ad:9e:79:10:dd:6b:df:99:72:2c:96:e5 # SHA256 Fingerprint: 07:91:ca:07:49:b2:07:82:aa:d3:c7:d7:bd:0c:df:c9:48:58:35:84:3e:b2:d7:99:60:09:ce:43:ab:6c:69:27 -----BEGIN CERTIFICATE----- MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEU MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 b3JrMSAwHgYDVQQDExdBZGRUcnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAx MDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtB ZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIDAeBgNV BAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV 6tsfSlbunyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nX GCwwfQ56HmIexkvA/X1id9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnP dzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSGAa2Il+tmzV7R/9x98oTaunet3IAIx6eH 1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAwHM+A+WD+eeSI8t0A65RF 62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0GA1UdDgQW BBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUw AwEB/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDEL MAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRU cnVzdCBUVFAgTmV0d29yazEgMB4GA1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJv b3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4JNojVhaTdt02KLmuG7jD8WS6 IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL+YPoRNWyQSW/ iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh 4SINhwBk/ox9Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQm XiLsks3/QppEIW1cxeMiHV9HEufOX1362KqxMy3ZdvJOOjMMK7MtkAY= -----END CERTIFICATE----- # Issuer: CN=AddTrust Qualified CA Root O=AddTrust AB OU=AddTrust TTP Network # Subject: CN=AddTrust Qualified CA Root O=AddTrust AB OU=AddTrust TTP Network # Label: "AddTrust Qualified Certificates Root" # Serial: 1 # MD5 Fingerprint: 27:ec:39:47:cd:da:5a:af:e2:9a:01:65:21:a9:4c:bb # SHA1 Fingerprint: 4d:23:78:ec:91:95:39:b5:00:7f:75:8f:03:3b:21:1e:c5:4d:8b:cf # SHA256 Fingerprint: 80:95:21:08:05:db:4b:bc:35:5e:44:28:d8:fd:6e:c2:cd:e3:ab:5f:b9:7a:99:42:98:8e:b8:f4:dc:d0:60:16 -----BEGIN CERTIFICATE----- MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEU MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 b3JrMSMwIQYDVQQDExpBZGRUcnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1 MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcxCzAJBgNVBAYTAlNFMRQwEgYDVQQK EwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIzAh BgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG9w0B AQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwq xBb/4Oxx64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G 87B4pfYOQnrjfxvM0PC3KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i 2O+tCBGaKZnhqkRFmhJePp1tUvznoD1oL/BLcHwTOK28FSXx1s6rosAx1i+f4P8U WfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GRwVY18BTcZTYJbqukB8c1 0cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HUMIHRMB0G A1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0T AQH/BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6Fr pGkwZzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQL ExRBZGRUcnVzdCBUVFAgTmV0d29yazEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlm aWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBABmrder4i2VhlRO6aQTv hsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxGGuoYQ992zPlm hpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3 P6CxB9bpT9zeRXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9Y iQBCYz95OdBEsIJuQRno3eDBiFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5no xqE= -----END CERTIFICATE----- # Issuer: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. # Subject: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. # Label: "Entrust Root Certification Authority" # Serial: 1164660820 # MD5 Fingerprint: d6:a5:c3:ed:5d:dd:3e:00:c1:3d:87:92:1f:1d:3f:e4 # SHA1 Fingerprint: b3:1e:b1:b7:40:e3:6c:84:02:da:dc:37:d4:4d:f5:d4:67:49:52:f9 # SHA256 Fingerprint: 73:c1:76:43:4f:1b:c6:d5:ad:f4:5b:0e:76:e7:27:28:7c:8d:e5:76:16:c1:e6:e6:14:1a:2b:2c:bc:7d:8e:4c -----BEGIN CERTIFICATE----- MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi 94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP 9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m 0vdXcDazv/wor3ElhVsT/h5/WrQ8 -----END CERTIFICATE----- # Issuer: CN=GeoTrust Global CA O=GeoTrust Inc. # Subject: CN=GeoTrust Global CA O=GeoTrust Inc. # Label: "GeoTrust Global CA" # Serial: 144470 # MD5 Fingerprint: f7:75:ab:29:fb:51:4e:b7:77:5e:ff:05:3c:99:8e:f5 # SHA1 Fingerprint: de:28:f4:a4:ff:e5:b9:2f:a3:c5:03:d1:a3:49:a7:f9:96:2a:82:12 # SHA256 Fingerprint: ff:85:6a:2d:25:1d:cd:88:d3:66:56:f4:50:12:67:98:cf:ab:aa:de:40:79:9c:72:2d:e4:d2:b5:db:36:a7:3a -----BEGIN CERTIFICATE----- MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU 1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV 5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== -----END CERTIFICATE----- # Issuer: CN=GeoTrust Global CA 2 O=GeoTrust Inc. # Subject: CN=GeoTrust Global CA 2 O=GeoTrust Inc. # Label: "GeoTrust Global CA 2" # Serial: 1 # MD5 Fingerprint: 0e:40:a7:6c:de:03:5d:8f:d1:0f:e4:d1:8d:f9:6c:a9 # SHA1 Fingerprint: a9:e9:78:08:14:37:58:88:f2:05:19:b0:6d:2b:0d:2b:60:16:90:7d # SHA256 Fingerprint: ca:2d:82:a0:86:77:07:2f:8a:b6:76:4f:f0:35:67:6c:fe:3e:5e:32:5e:01:21:72:df:3f:92:09:6d:b7:9b:85 -----BEGIN CERTIFICATE----- MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEW MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFs IENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQG EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg R2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvPE1A PRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/NTL8 Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hL TytCOb1kLUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL 5mkWRxHCJ1kDs6ZgwiFAVvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7 S4wMcoKK+xfNAGw6EzywhIdLFnopsk/bHdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe 2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE FHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNHK266ZUap EBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6td EPx7srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv /NgdRN3ggX+d6YvhZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywN A0ZF66D0f0hExghAzN4bcLUprbqLOzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0 abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkCx1YAzUm5s2x7UwQa4qjJqhIF I8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqFH4z1Ir+rzoPz 4iIprn2DQKi6bA== -----END CERTIFICATE----- # Issuer: CN=GeoTrust Universal CA O=GeoTrust Inc. # Subject: CN=GeoTrust Universal CA O=GeoTrust Inc. # Label: "GeoTrust Universal CA" # Serial: 1 # MD5 Fingerprint: 92:65:58:8b:a2:1a:31:72:73:68:5c:b4:a5:7a:07:48 # SHA1 Fingerprint: e6:21:f3:35:43:79:05:9a:4b:68:30:9d:8a:2f:74:22:15:87:ec:79 # SHA256 Fingerprint: a0:45:9b:9f:63:b2:25:59:f5:fa:5d:4c:6d:b3:f9:f7:2f:f1:93:42:03:35:78:f0:73:bf:1d:1b:46:cb:b9:12 -----BEGIN CERTIFICATE----- MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0 IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8 cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+ nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB /wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG 9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9 ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw= -----END CERTIFICATE----- # Issuer: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. # Subject: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. # Label: "GeoTrust Universal CA 2" # Serial: 1 # MD5 Fingerprint: 34:fc:b8:d0:36:db:9e:14:b3:c2:f2:db:8f:e4:94:c7 # SHA1 Fingerprint: 37:9a:19:7b:41:85:45:35:0c:a6:03:69:f3:3c:2e:af:47:4f:20:79 # SHA256 Fingerprint: a0:23:4f:3b:c8:52:7c:a5:62:8e:ec:81:ad:5d:69:89:5d:a5:68:0d:c9:1d:1c:b8:47:7f:33:f8:78:b9:5b:0b -----BEGIN CERTIFICATE----- MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1 c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81 WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73 y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4 Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m 1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH 6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS -----END CERTIFICATE----- # Issuer: CN=Visa eCommerce Root O=VISA OU=Visa International Service Association # Subject: CN=Visa eCommerce Root O=VISA OU=Visa International Service Association # Label: "Visa eCommerce Root" # Serial: 25952180776285836048024890241505565794 # MD5 Fingerprint: fc:11:b8:d8:08:93:30:00:6d:23:f9:7e:eb:52:1e:02 # SHA1 Fingerprint: 70:17:9b:86:8c:00:a4:fa:60:91:52:22:3f:9f:3e:32:bd:e0:05:62 # SHA256 Fingerprint: 69:fa:c9:bd:55:fb:0a:c7:8d:53:bb:ee:5c:f1:d5:97:98:9f:d0:aa:ab:20:a2:51:51:bd:f1:73:3e:e7:d1:22 -----BEGIN CERTIFICATE----- MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h 2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq 299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3 LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd 7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw ++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt 398znM/jra6O1I7mT1GvFpLgXPYHDw== -----END CERTIFICATE----- # Issuer: CN=Certum CA O=Unizeto Sp. z o.o. # Subject: CN=Certum CA O=Unizeto Sp. z o.o. # Label: "Certum Root CA" # Serial: 65568 # MD5 Fingerprint: 2c:8f:9f:66:1d:18:90:b1:47:26:9d:8e:86:82:8c:a9 # SHA1 Fingerprint: 62:52:dc:40:f7:11:43:a2:2f:de:9e:f7:34:8e:06:42:51:b1:81:18 # SHA256 Fingerprint: d8:e0:fe:bc:1d:b2:e3:8d:00:94:0f:37:d2:7d:41:34:4d:99:3e:73:4b:99:d5:65:6d:97:78:d4:d8:14:36:24 -----BEGIN CERTIFICATE----- MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBM MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD QTAeFw0wMjA2MTExMDQ2MzlaFw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBM MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6xwS7TT3zNJc4YPk/E jG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdLkKWo ePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GI ULdtlkIJ89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapu Ob7kky/ZR6By6/qmW6/KUz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUg AKpoC6EahQGcxEZjgoi2IrHu/qpGWX7PNSzVttpd90gzFFS269lvzs2I1qsb2pY7 HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEA uI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+GXYkHAQa TOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTg xSvgGrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1q CjqTE5s7FCMTY5w/0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5x O/fIR/RpbxXyEV6DHpx8Uq79AtoSqFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs 6GAqm4VKQPNriiTsBhYscw== -----END CERTIFICATE----- # Issuer: CN=AAA Certificate Services O=Comodo CA Limited # Subject: CN=AAA Certificate Services O=Comodo CA Limited # Label: "Comodo AAA Services root" # Serial: 1 # MD5 Fingerprint: 49:79:04:b0:eb:87:19:ac:47:b0:bc:11:51:9b:74:d0 # SHA1 Fingerprint: d1:eb:23:a4:6d:17:d6:8f:d9:25:64:c2:f1:f1:60:17:64:d8:e3:49 # SHA256 Fingerprint: d7:a7:a0:fb:5d:7e:27:31:d7:71:e9:48:4e:bc:de:f7:1d:5f:0c:3e:0a:29:48:78:2b:c8:3e:e0:ea:69:9e:f4 -----BEGIN CERTIFICATE----- MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe 3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== -----END CERTIFICATE----- # Issuer: CN=Secure Certificate Services O=Comodo CA Limited # Subject: CN=Secure Certificate Services O=Comodo CA Limited # Label: "Comodo Secure Services root" # Serial: 1 # MD5 Fingerprint: d3:d9:bd:ae:9f:ac:67:24:b3:c8:1b:52:e1:b9:a9:bd # SHA1 Fingerprint: 4a:65:d5:f4:1d:ef:39:b8:b8:90:4a:4a:d3:64:81:33:cf:c7:a1:d1 # SHA256 Fingerprint: bd:81:ce:3b:4f:65:91:d1:1a:67:b5:fc:7a:47:fd:ef:25:52:1b:f9:aa:4e:18:b9:e3:df:2e:34:a7:80:3b:e8 -----BEGIN CERTIFICATE----- MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEb MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRp ZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVow fjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAiBgNV BAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEB BQADggEPADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPM cm3ye5drswfxdySRXyWP9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3S HpR7LZQdqnXXs5jLrLxkU0C8j6ysNstcrbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996 CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rCoznl2yY4rYsK7hljxxwk 3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3Vp6ea5EQz 6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNV HQ4EFgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud EwEB/wQFMAMBAf8wgYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2Rv Y2EuY29tL1NlY3VyZUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRw Oi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmww DQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm4J4oqF7Tt/Q0 5qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtI gKvcnDe4IRRLDXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJ aD61JlfutuC23bkpgHl9j6PwpCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDl izeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1HRR3B7Hzs/Sk= -----END CERTIFICATE----- # Issuer: CN=Trusted Certificate Services O=Comodo CA Limited # Subject: CN=Trusted Certificate Services O=Comodo CA Limited # Label: "Comodo Trusted Services root" # Serial: 1 # MD5 Fingerprint: 91:1b:3f:6e:cd:9e:ab:ee:07:fe:1f:71:d2:b3:61:27 # SHA1 Fingerprint: e1:9f:e3:0e:8b:84:60:9e:80:9b:17:0d:72:a8:c5:ba:6e:14:09:bd # SHA256 Fingerprint: 3f:06:e5:56:81:d4:96:f5:be:16:9e:b5:38:9f:9f:2b:8f:f6:1e:17:08:df:68:81:72:48:49:cd:5d:27:cb:69 -----BEGIN CERTIFICATE----- MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEb MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0 aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTla MH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO BgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUwIwYD VQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0B AQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWW fnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt TGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7IL fhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW 1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7 kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0G A1UdDgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYD VR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21v ZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRo dHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu Y3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/ HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxIS jBc/lDb+XbDABHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+ xqFx7D+gIIxmOom0jtTYsU0lR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/Atyjcn dBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O9y5Xt5hwXsjEeLBi -----END CERTIFICATE----- # Issuer: CN=QuoVadis Root Certification Authority O=QuoVadis Limited OU=Root Certification Authority # Subject: CN=QuoVadis Root Certification Authority O=QuoVadis Limited OU=Root Certification Authority # Label: "QuoVadis Root CA" # Serial: 985026699 # MD5 Fingerprint: 27:de:36:fe:72:b7:00:03:00:9d:f4:f0:1e:6c:04:24 # SHA1 Fingerprint: de:3f:40:bd:50:93:d3:9b:6c:60:f6:da:bc:07:62:01:00:89:76:c9 # SHA256 Fingerprint: a4:5e:de:3b:bb:f0:9c:8a:e1:5c:72:ef:c0:72:68:d6:93:a2:1c:99:6f:d5:1e:67:ca:07:94:60:fd:6d:88:73 -----BEGIN CERTIFICATE----- MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0 aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0 aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG 9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8 7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK SnQ2+Q== -----END CERTIFICATE----- # Issuer: CN=QuoVadis Root CA 2 O=QuoVadis Limited # Subject: CN=QuoVadis Root CA 2 O=QuoVadis Limited # Label: "QuoVadis Root CA 2" # Serial: 1289 # MD5 Fingerprint: 5e:39:7b:dd:f8:ba:ec:82:e9:ac:62:ba:0c:54:00:2b # SHA1 Fingerprint: ca:3a:fb:cf:12:40:36:4b:44:b2:16:20:88:80:48:39:19:93:7c:f7 # SHA256 Fingerprint: 85:a0:dd:7d:d7:20:ad:b7:ff:05:f8:3d:54:2b:20:9d:c7:ff:45:28:f7:d6:77:b1:83:89:fe:a5:e5:c4:9e:86 -----BEGIN CERTIFICATE----- MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp +ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1 ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og /zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2 A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y 4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza 8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u -----END CERTIFICATE----- # Issuer: CN=QuoVadis Root CA 3 O=QuoVadis Limited # Subject: CN=QuoVadis Root CA 3 O=QuoVadis Limited # Label: "QuoVadis Root CA 3" # Serial: 1478 # MD5 Fingerprint: 31:85:3c:62:94:97:63:b9:aa:fd:89:4e:af:6f:e0:cf # SHA1 Fingerprint: 1f:49:14:f7:d8:74:95:1d:dd:ae:02:c0:be:fd:3a:2d:82:75:51:85 # SHA256 Fingerprint: 18:f1:fc:7f:20:5d:f8:ad:dd:eb:7f:e0:07:dd:57:e3:af:37:5a:9c:4d:8d:73:54:6b:f4:f1:fe:d1:e1:8d:35 -----BEGIN CERTIFICATE----- MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB 4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd 8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A 4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd +LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B 4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK 4SVhM7JZG+Ju1zdXtg2pEto= -----END CERTIFICATE----- # Issuer: O=SECOM Trust.net OU=Security Communication RootCA1 # Subject: O=SECOM Trust.net OU=Security Communication RootCA1 # Label: "Security Communication Root CA" # Serial: 0 # MD5 Fingerprint: f1:bc:63:6a:54:e0:b5:27:f5:cd:e7:1a:e3:4d:6e:4a # SHA1 Fingerprint: 36:b1:2b:49:f9:81:9e:d7:4c:9e:bc:38:0f:c6:56:8f:5d:ac:b2:f7 # SHA256 Fingerprint: e7:5e:72:ed:9f:56:0e:ec:6e:b4:80:00:73:a4:3f:c3:ad:19:19:5a:39:22:82:01:78:95:97:4a:99:02:6b:6c -----BEGIN CERTIFICATE----- MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== -----END CERTIFICATE----- # Issuer: CN=Sonera Class2 CA O=Sonera # Subject: CN=Sonera Class2 CA O=Sonera # Label: "Sonera Class 2 Root CA" # Serial: 29 # MD5 Fingerprint: a3:ec:75:0f:2e:88:df:fa:48:01:4e:0b:5c:48:6f:fb # SHA1 Fingerprint: 37:f7:6d:e6:07:7c:90:c5:b1:3e:93:1a:b7:41:10:b4:f2:e4:9a:27 # SHA256 Fingerprint: 79:08:b4:03:14:c1:38:10:0b:51:8d:07:35:80:7f:fb:fc:f8:51:8a:00:95:33:71:05:ba:38:6b:15:3d:d9:27 -----BEGIN CERTIFICATE----- MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt 5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s 3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu 8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ 3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M -----END CERTIFICATE----- # Issuer: CN=UTN-USERFirst-Hardware O=The USERTRUST Network OU=http://www.usertrust.com # Subject: CN=UTN-USERFirst-Hardware O=The USERTRUST Network OU=http://www.usertrust.com # Label: "UTN USERFirst Hardware Root CA" # Serial: 91374294542884704022267039221184531197 # MD5 Fingerprint: 4c:56:41:e5:0d:bb:2b:e8:ca:a3:ed:18:08:ad:43:39 # SHA1 Fingerprint: 04:83:ed:33:99:ac:36:08:05:87:22:ed:bc:5e:46:00:e3:be:f9:d7 # SHA256 Fingerprint: 6e:a5:47:41:d0:04:66:7e:ed:1b:48:16:63:4a:a3:a7:9e:6e:4b:96:95:0f:82:79:da:fc:8d:9b:d8:81:21:37 -----BEGIN CERTIFICATE----- MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn 0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0 dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM //bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t 3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== -----END CERTIFICATE----- # Issuer: CN=Chambers of Commerce Root O=AC Camerfirma SA CIF A82743287 OU=http://www.chambersign.org # Subject: CN=Chambers of Commerce Root O=AC Camerfirma SA CIF A82743287 OU=http://www.chambersign.org # Label: "Camerfirma Chambers of Commerce Root" # Serial: 0 # MD5 Fingerprint: b0:01:ee:14:d9:af:29:18:94:76:8e:f1:69:33:2a:84 # SHA1 Fingerprint: 6e:3a:55:a4:19:0c:19:5c:93:84:3c:c0:db:72:2e:31:30:61:f0:b1 # SHA256 Fingerprint: 0c:25:8a:12:a5:67:4a:ef:25:f2:8b:a7:dc:fa:ec:ee:a3:48:e5:41:e6:f5:cc:4e:e6:3b:71:b3:61:60:6a:c3 -----BEGIN CERTIFICATE----- MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEn MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMg b2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAxNjEzNDNaFw0zNzA5MzAxNjEzNDRa MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBB ODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIw IAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0B AQEFAAOCAQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtb unXF/KGIJPov7coISjlUxFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0d BmpAPrMMhe5cG3nCYsS4No41XQEMIwRHNaqbYE6gZj3LJgqcQKH0XZi/caulAGgq 7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jWDA+wWFjbw2Y3npuRVDM3 0pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFVd9oKDMyX roDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIG A1UdEwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5j aGFtYmVyc2lnbi5vcmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p 26EpW1eLTXYGduHRooowDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIA BzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24ub3JnMCcGA1Ud EgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYDVR0gBFEwTzBN BgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEB AAxBl8IahsAifJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZd p0AJPaxJRUXcLo0waLIJuvvDL8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi 1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wNUPf6s+xCX6ndbcj0dc97wXImsQEc XCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/nADydb47kMgkdTXg0 eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1erfu tGWaIZDgqtCYvDi1czyL+Nw= -----END CERTIFICATE----- # Issuer: CN=Global Chambersign Root O=AC Camerfirma SA CIF A82743287 OU=http://www.chambersign.org # Subject: CN=Global Chambersign Root O=AC Camerfirma SA CIF A82743287 OU=http://www.chambersign.org # Label: "Camerfirma Global Chambersign Root" # Serial: 0 # MD5 Fingerprint: c5:e6:7b:bf:06:d0:4f:43:ed:c4:7a:65:8a:fb:6b:19 # SHA1 Fingerprint: 33:9b:6b:14:50:24:9b:55:7a:01:87:72:84:d9:e0:2f:c3:d2:d8:e9 # SHA256 Fingerprint: ef:3c:b4:17:fc:8e:bf:6f:97:87:6c:9e:4e:ce:39:de:1e:a5:fe:64:91:41:d1:02:8b:7d:11:c0:b2:29:8c:ed -----BEGIN CERTIFICATE----- MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEn MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENo YW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYxNDE4WhcNMzcwOTMwMTYxNDE4WjB9 MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgy NzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4G A1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUA A4IBDQAwggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0 Mi+ITaFgCPS3CU6gSS9J1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/s QJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8Oby4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpV eAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl6DJWk0aJqCWKZQbua795 B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c8lCrEqWh z0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0T AQH/BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1i ZXJzaWduLm9yZy9jaGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4w TcbOX60Qq+UDpfqpFDAOBgNVHQ8BAf8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAH MCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBjaGFtYmVyc2lnbi5vcmcwKgYD VR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9yZzBbBgNVHSAE VDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0B AQUFAAOCAQEAPDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUM bKGKfKX0j//U2K0X1S0E0T9YgOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXi ryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJPJ7oKXqJ1/6v/2j1pReQvayZzKWG VwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4IBHNfTIzSJRUTN3c ecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREest2d/ AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== -----END CERTIFICATE----- # Issuer: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com # Subject: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com # Label: "XRamp Global CA Root" # Serial: 107108908803651509692980124233745014957 # MD5 Fingerprint: a1:0b:44:b3:ca:10:d8:00:6e:9d:0f:d8:0f:92:0a:d1 # SHA1 Fingerprint: b8:01:86:d1:eb:9c:86:a5:41:04:cf:30:54:f3:4c:52:b7:e5:58:c6 # SHA256 Fingerprint: ce:cd:dc:90:50:99:d8:da:df:c5:b1:d2:09:b7:37:cb:e2:c1:8c:fb:2c:10:c0:ff:0b:cf:0d:32:86:fc:1a:a2 -----BEGIN CERTIFICATE----- MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ O+7ETPTsJ3xCwnR8gooJybQDJbw= -----END CERTIFICATE----- # Issuer: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority # Subject: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority # Label: "Go Daddy Class 2 CA" # Serial: 0 # MD5 Fingerprint: 91:de:06:25:ab:da:fd:32:17:0c:bb:25:17:2a:84:67 # SHA1 Fingerprint: 27:96:ba:e6:3f:18:01:e2:77:26:1b:a0:d7:77:70:02:8f:20:ee:e4 # SHA256 Fingerprint: c3:84:6b:f2:4b:9e:93:ca:64:27:4c:0e:c6:7c:1e:cc:5e:02:4f:fc:ac:d2:d7:40:19:35:0e:81:fe:54:6a:e4 -----BEGIN CERTIFICATE----- MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h /t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf ReYNnyicsbkqWletNw+vHX/bvZ8= -----END CERTIFICATE----- # Issuer: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority # Subject: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority # Label: "Starfield Class 2 CA" # Serial: 0 # MD5 Fingerprint: 32:4a:4b:bb:c8:63:69:9b:be:74:9a:c6:dd:1d:46:24 # SHA1 Fingerprint: ad:7e:1c:28:b0:64:ef:8f:60:03:40:20:14:c3:d0:e3:37:0e:b5:8a # SHA256 Fingerprint: 14:65:fa:20:53:97:b8:76:fa:a6:f0:a9:95:8e:55:90:e4:0f:cc:7f:aa:4f:b7:c2:c8:67:75:21:fb:5f:b6:58 -----BEGIN CERTIFICATE----- MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf 8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN +lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA 1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= -----END CERTIFICATE----- # Issuer: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing # Subject: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing # Label: "StartCom Certification Authority" # Serial: 1 # MD5 Fingerprint: 22:4d:8f:8a:fc:f7:35:c2:bb:57:34:90:7b:8b:22:16 # SHA1 Fingerprint: 3e:2b:f7:f2:03:1b:96:f3:8c:e6:c4:d8:a8:5d:3e:2d:58:47:6a:0f # SHA256 Fingerprint: c7:66:a9:be:f2:d4:07:1c:86:3a:31:aa:49:20:e8:13:b2:d1:98:60:8c:b7:b7:cf:e2:11:43:b8:36:df:09:ea -----BEGIN CERTIFICATE----- MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9 MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w +2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B 26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0 Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ 9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8 jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1 ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14= -----END CERTIFICATE----- # Issuer: O=Government Root Certification Authority # Subject: O=Government Root Certification Authority # Label: "Taiwan GRCA" # Serial: 42023070807708724159991140556527066870 # MD5 Fingerprint: 37:85:44:53:32:45:1f:20:f0:f3:95:e1:25:c4:43:4e # SHA1 Fingerprint: f4:8b:11:bf:de:ab:be:94:54:20:71:e6:41:de:6b:be:88:2b:40:b9 # SHA256 Fingerprint: 76:00:29:5e:ef:e8:5b:9e:1f:d6:24:db:76:06:2a:aa:ae:59:81:8a:54:d2:77:4c:d4:c0:b2:c0:11:31:e1:b3 -----BEGIN CERTIFICATE----- MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/ MQswCQYDVQQGEwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmlj YXRpb24gQXV0aG9yaXR5MB4XDTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1ow PzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dvdmVybm1lbnQgUm9vdCBDZXJ0aWZp Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB AJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qNw8XR IePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1q gQdW8or5BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKy yhwOeYHWtXBiCAEuTk8O1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAts F/tnyMKtsc2AtJfcdgEWFelq16TheEfOhtX7MfP6Mb40qij7cEwdScevLJ1tZqa2 jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wovJ5pGfaENda1UhhXcSTvx ls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7Q3hub/FC VGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHK YS1tB6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoH EgKXTiCQ8P8NHuJBO9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThN Xo+EHWbNxWCWtFJaBYmOlXqYwZE8lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1Ud DgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNVHRMEBTADAQH/MDkGBGcqBwAE MTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg209yewDL7MTqK UWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyf qzvS/3WXy6TjZwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaK ZEk9GhiHkASfQlK3T8v+R0F2Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFE JPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlUD7gsL0u8qV1bYH+Mh6XgUmMqvtg7 hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6QzDxARvBMB1uUO07+1 EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+HbkZ6Mm nD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WX udpVBrkk7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44Vbnz ssQwmSNOXfJIoRIM3BKQCZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDe LMDDav7v3Aun+kbfYNucpllQdSNpc5Oy+fwC00fmcc4QAu4njIT/rEUNE1yDMuAl pYYsfPQS -----END CERTIFICATE----- # Issuer: CN=Swisscom Root CA 1 O=Swisscom OU=Digital Certificate Services # Subject: CN=Swisscom Root CA 1 O=Swisscom OU=Digital Certificate Services # Label: "Swisscom Root CA 1" # Serial: 122348795730808398873664200247279986742 # MD5 Fingerprint: f8:38:7c:77:88:df:2c:16:68:2e:c2:e2:52:4b:b8:f9 # SHA1 Fingerprint: 5f:3a:fc:0a:8b:64:f6:86:67:34:74:df:7e:a9:a2:fe:f9:fa:7a:51 # SHA256 Fingerprint: 21:db:20:12:36:60:bb:2e:d4:18:20:5d:a1:1e:e7:a8:5a:65:e2:bc:6e:55:b5:af:7e:78:99:c8:a2:66:d9:2e -----BEGIN CERTIFICATE----- MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBk MQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0 YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3Qg Q0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4MTgyMjA2MjBaMGQxCzAJBgNVBAYT AmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZp Y2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIICIjAN BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9 m2BtRsiMMW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdih FvkcxC7mlSpnzNApbjyFNDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/ TilftKaNXXsLmREDA/7n29uj/x2lzZAeAR81sH8A25Bvxn570e56eqeqDFdvpG3F EzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkCb6dJtDZd0KTeByy2dbco kdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn7uHbHaBu HYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNF vJbNcA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo 19AOeCMgkckkKmUpWyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjC L3UcPX7ape8eYIVpQtPM+GP+HkM5haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJW bjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNYMUJDLXT5xp6mig/p/r+D5kNX JLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0hBBYw FDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzc K6FptWfUjNP9MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzf ky9NfEBWMXrrpA9gzXrzvsMnjgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7Ik Vh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQMbFamIp1TpBcahQq4FJHgmDmHtqB sfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4HVtA4oJVwIHaM190e 3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtlvrsR ls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ip mXeascClOS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HH b6D0jqTsNFFbjCYDcKF31QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksf rK/7DZBaZmBwXarNeNQk7shBoJMBkpxqnvy5JMWzFYJ+vq6VK+uxwNrjAWALXmms hFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCyx/yP2FS1k2Kdzs9Z+z0Y zirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMWNY6E0F/6 MBr1mmz0DlP5OlvRHA== -----END CERTIFICATE----- # Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com # Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com # Label: "DigiCert Assured ID Root CA" # Serial: 17154717934120587862167794914071425081 # MD5 Fingerprint: 87:ce:0b:7b:2a:0e:49:00:e1:58:71:9b:37:a8:93:72 # SHA1 Fingerprint: 05:63:b8:63:0d:62:d7:5a:bb:c8:ab:1e:4b:df:b5:a8:99:b2:4d:43 # SHA256 Fingerprint: 3e:90:99:b5:01:5e:8f:48:6c:00:bc:ea:9d:11:1e:e7:21:fa:ba:35:5a:89:bc:f1:df:69:56:1e:3d:c6:32:5c -----BEGIN CERTIFICATE----- MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== -----END CERTIFICATE----- # Issuer: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com # Subject: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com # Label: "DigiCert Global Root CA" # Serial: 10944719598952040374951832963794454346 # MD5 Fingerprint: 79:e4:a9:84:0d:7d:3a:96:d7:c0:4f:e2:43:4c:89:2e # SHA1 Fingerprint: a8:98:5d:3a:65:e5:e5:c4:b2:d7:d6:6d:40:c6:dd:2f:b1:9c:54:36 # SHA256 Fingerprint: 43:48:a0:e9:44:4c:78:cb:26:5e:05:8d:5e:89:44:b4:d8:4f:96:62:bd:26:db:25:7f:89:34:a4:43:c7:01:61 -----BEGIN CERTIFICATE----- MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt 43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg 06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= -----END CERTIFICATE----- # Issuer: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com # Subject: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com # Label: "DigiCert High Assurance EV Root CA" # Serial: 3553400076410547919724730734378100087 # MD5 Fingerprint: d4:74:de:57:5c:39:b2:d3:9c:85:83:c5:c0:65:49:8a # SHA1 Fingerprint: 5f:b7:ee:06:33:e2:59:db:ad:0c:4c:9a:e6:d3:8f:1a:61:c7:dc:25 # SHA256 Fingerprint: 74:31:e5:f4:c3:c1:ce:46:90:77:4f:0b:61:e0:54:40:88:3b:a9:a0:1e:d0:0b:a6:ab:d7:80:6e:d3:b1:18:cf -----BEGIN CERTIFICATE----- MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm +9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep +OkuE6N36B9K -----END CERTIFICATE----- # Issuer: CN=Class 2 Primary CA O=Certplus # Subject: CN=Class 2 Primary CA O=Certplus # Label: "Certplus Class 2 Primary CA" # Serial: 177770208045934040241468760488327595043 # MD5 Fingerprint: 88:2c:8c:52:b8:a2:3c:f3:f7:bb:03:ea:ae:ac:42:0b # SHA1 Fingerprint: 74:20:74:41:72:9c:dd:92:ec:79:31:d8:23:10:8d:c2:81:92:e2:bb # SHA256 Fingerprint: 0f:99:3c:8a:ef:97:ba:af:56:87:14:0e:d5:9a:d1:82:1b:b4:af:ac:f0:aa:9a:58:b5:d5:7a:33:8a:3a:fb:cb -----BEGIN CERTIFICATE----- MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAw PTELMAkGA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFz cyAyIFByaW1hcnkgQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9 MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNz IDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANxQ ltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR5aiR VhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyL kcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCd EgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas H7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0 HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1Ud DwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4 QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMu Y29tL0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/ AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8 yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMR FcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW2ikbhiMA ybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 l7+ijrRU -----END CERTIFICATE----- # Issuer: CN=DST Root CA X3 O=Digital Signature Trust Co. # Subject: CN=DST Root CA X3 O=Digital Signature Trust Co. # Label: "DST Root CA X3" # Serial: 91299735575339953335919266965803778155 # MD5 Fingerprint: 41:03:52:dc:0f:f7:50:1b:16:f0:02:8e:ba:6f:45:c5 # SHA1 Fingerprint: da:c9:02:4f:54:d8:f6:df:94:93:5f:b1:73:26:38:ca:6a:d7:7c:13 # SHA256 Fingerprint: 06:87:26:03:31:a7:24:03:d9:09:f1:05:e6:9b:cf:0d:32:e1:bd:24:93:ff:c6:d9:20:6d:11:bc:d6:77:07:39 -----BEGIN CERTIFICATE----- MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw 7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ -----END CERTIFICATE----- # Issuer: CN=DST ACES CA X6 O=Digital Signature Trust OU=DST ACES # Subject: CN=DST ACES CA X6 O=Digital Signature Trust OU=DST ACES # Label: "DST ACES CA X6" # Serial: 17771143917277623872238992636097467865 # MD5 Fingerprint: 21:d8:4c:82:2b:99:09:33:a2:eb:14:24:8d:8e:5f:e8 # SHA1 Fingerprint: 40:54:da:6f:1c:3f:40:74:ac:ed:0f:ec:cd:db:79:d1:53:fb:90:1d # SHA256 Fingerprint: 76:7c:95:5a:76:41:2c:89:af:68:8e:90:a1:c7:0f:55:6c:fd:6b:60:25:db:ea:10:41:6d:7e:b6:83:1f:8c:40 -----BEGIN CERTIFICATE----- MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBb MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3Qx ETAPBgNVBAsTCERTVCBBQ0VTMRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0w MzExMjAyMTE5NThaFw0xNzExMjAyMTE5NThaMFsxCzAJBgNVBAYTAlVTMSAwHgYD VQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UECxMIRFNUIEFDRVMx FzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPu ktKe1jzIDZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7 gLFViYsx+tC3dr5BPTCapCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZH fAjIgrrep4c9oW24MFbCswKBXy314powGCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4a ahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPyMjwmR/onJALJfh1biEIT ajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1UdEwEB/wQF MAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rk c3QuY29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjto dHRwOi8vd3d3LnRydXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMt aW5kZXguaHRtbDAdBgNVHQ4EFgQUCXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZI hvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V25FYrnJmQ6AgwbN99Pe7lv7Uk QIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6tFr8hlxCBPeP/ h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpR rscL9yuwNwXsvFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf2 9w4LTJxoeHtxMcfrHuBnQfO3oKfN5XozNmr6mis= -----END CERTIFICATE----- # Issuer: CN=SwissSign Gold CA - G2 O=SwissSign AG # Subject: CN=SwissSign Gold CA - G2 O=SwissSign AG # Label: "SwissSign Gold CA - G2" # Serial: 13492815561806991280 # MD5 Fingerprint: 24:77:d9:a8:91:d1:3b:fa:88:2d:c2:ff:f8:cd:33:93 # SHA1 Fingerprint: d8:c5:38:8a:b7:30:1b:1b:6e:d4:7a:e6:45:25:3a:6f:9f:1a:27:61 # SHA256 Fingerprint: 62:dd:0b:e9:b9:f5:0a:16:3e:a0:f8:e7:5c:05:3b:1e:ca:57:ea:55:c8:68:8f:64:7c:68:81:f2:c8:35:7b:95 -----BEGIN CERTIFICATE----- MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8 76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+ bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c 6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7 lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn 8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6 45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5 O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a 77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3 92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ -----END CERTIFICATE----- # Issuer: CN=SwissSign Silver CA - G2 O=SwissSign AG # Subject: CN=SwissSign Silver CA - G2 O=SwissSign AG # Label: "SwissSign Silver CA - G2" # Serial: 5700383053117599563 # MD5 Fingerprint: e0:06:a1:c9:7d:cf:c9:fc:0d:c0:56:75:96:d8:62:13 # SHA1 Fingerprint: 9b:aa:e5:9f:56:ee:21:cb:43:5a:be:25:93:df:a7:f0:40:d1:1d:cb # SHA256 Fingerprint: be:6c:4d:a2:bb:b9:ba:59:b6:f3:93:97:68:37:42:46:c3:c0:05:99:3f:a9:8f:02:0d:1d:ed:be:d4:8a:81:d5 -----BEGIN CERTIFICATE----- MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWdu IFNpbHZlciBDQSAtIEcyMB4XDTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0Nlow RzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMY U3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A MIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644N0Mv Fz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7br YT7QbNHm+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieF nbAVlDLaYQ1HTWBCrpJH6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH 6ATK72oxh9TAtvmUcXtnZLi2kUpCe2UuMGoM9ZDulebyzYLs2aFK7PayS+VFheZt eJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5hqAaEuSh6XzjZG6k4sIN/ c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5FZGkECwJ MoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRH HTBsROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTf jNFusB3hB48IHpmccelM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb6 5i/4z3GcRm25xBWNOHkDRUjvxF3XCO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOB rDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU F6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRBtjpbO8tFnb0c wpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIB AHPGgeAn0i0P4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShp WJHckRE1qTodvBqlYJ7YH39FkWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9 xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L3XWgwF15kIwb4FDm3jH+mHtwX6WQ 2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx/uNncqCxv1yL5PqZ IseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFaDGi8 aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2X em1ZqSqPe97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQR dAtq/gsD/KNVV4n+SsuuWxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/ OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+ hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u -----END CERTIFICATE----- # Issuer: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc. # Subject: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc. # Label: "GeoTrust Primary Certification Authority" # Serial: 32798226551256963324313806436981982369 # MD5 Fingerprint: 02:26:c3:01:5e:08:30:37:43:a9:d0:7d:cf:37:e6:bf # SHA1 Fingerprint: 32:3c:11:8e:1b:f7:b8:b6:52:54:e2:e2:10:0d:d6:02:90:37:f0:96 # SHA256 Fingerprint: 37:d5:10:06:c5:12:ea:ab:62:64:21:f1:ec:8c:92:01:3f:c5:f8:2a:e9:8e:e5:33:eb:46:19:b8:de:b4:d0:6c -----BEGIN CERTIFICATE----- MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9 AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0 7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1 6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl 4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= -----END CERTIFICATE----- # Issuer: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only # Subject: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only # Label: "thawte Primary Root CA" # Serial: 69529181992039203566298953787712940909 # MD5 Fingerprint: 8c:ca:dc:0b:22:ce:f5:be:72:ac:41:1a:11:a8:d8:12 # SHA1 Fingerprint: 91:c6:d6:ee:3e:8a:c8:63:84:e5:48:c2:99:29:5c:75:6c:81:7b:81 # SHA256 Fingerprint: 8d:72:2f:81:a9:c1:13:c0:79:1d:f1:36:a2:96:6d:b2:6c:95:0a:97:1d:b4:6b:41:99:f4:ea:54:b7:8b:fb:9f -----BEGIN CERTIFICATE----- MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta 3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk 6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 /qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 jVaMaA== -----END CERTIFICATE----- # Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only # Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only # Label: "VeriSign Class 3 Public Primary Certification Authority - G5" # Serial: 33037644167568058970164719475676101450 # MD5 Fingerprint: cb:17:e4:31:67:3e:e2:09:fe:45:57:93:f3:0a:fa:1c # SHA1 Fingerprint: 4e:b6:d5:78:49:9b:1c:cf:5f:58:1e:ad:56:be:3d:9b:67:44:a5:e5 # SHA256 Fingerprint: 9a:cf:ab:7e:43:c8:d8:80:d0:6b:26:2a:94:de:ee:e4:b4:65:99:89:c3:d0:ca:f1:9b:af:64:05:e4:1a:b7:df -----BEGIN CERTIFICATE----- MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y 5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ 4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq -----END CERTIFICATE----- # Issuer: CN=SecureTrust CA O=SecureTrust Corporation # Subject: CN=SecureTrust CA O=SecureTrust Corporation # Label: "SecureTrust CA" # Serial: 17199774589125277788362757014266862032 # MD5 Fingerprint: dc:32:c3:a7:6d:25:57:c7:68:09:9d:ea:2d:a9:a2:d1 # SHA1 Fingerprint: 87:82:c6:c3:04:35:3b:cf:d2:96:92:d2:59:3e:7d:44:d9:34:ff:11 # SHA256 Fingerprint: f1:c1:b5:0a:e5:a2:0d:d8:03:0e:c9:f6:bc:24:82:3d:d3:67:b5:25:57:59:b4:e7:1b:61:fc:e9:f7:37:5d:73 -----BEGIN CERTIFICATE----- MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO 0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj 7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS 8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB /zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ 3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR 3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= -----END CERTIFICATE----- # Issuer: CN=Secure Global CA O=SecureTrust Corporation # Subject: CN=Secure Global CA O=SecureTrust Corporation # Label: "Secure Global CA" # Serial: 9751836167731051554232119481456978597 # MD5 Fingerprint: cf:f4:27:0d:d4:ed:dc:65:16:49:6d:3d:da:bf:6e:de # SHA1 Fingerprint: 3a:44:73:5a:e5:81:90:1f:24:86:61:46:1e:3b:9c:c4:5f:f5:3a:1b # SHA256 Fingerprint: 42:00:f5:04:3a:c8:59:0e:bb:52:7d:20:9e:d1:50:30:29:fb:cb:d4:1c:a1:b5:06:ec:27:f1:5a:de:7d:ac:69 -----BEGIN CERTIFICATE----- MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa /FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW -----END CERTIFICATE----- # Issuer: CN=COMODO Certification Authority O=COMODO CA Limited # Subject: CN=COMODO Certification Authority O=COMODO CA Limited # Label: "COMODO Certification Authority" # Serial: 104350513648249232941998508985834464573 # MD5 Fingerprint: 5c:48:dc:f7:42:72:ec:56:94:6d:1c:cc:71:35:80:75 # SHA1 Fingerprint: 66:31:bf:9e:f7:4f:9e:b6:c9:d5:a6:0c:ba:6a:be:d1:f7:bd:ef:7b # SHA256 Fingerprint: 0c:2c:d6:3d:f7:80:6f:a3:99:ed:e8:09:11:6b:57:5b:f8:79:89:f0:65:18:f9:80:8c:86:05:03:17:8b:af:66 -----BEGIN CERTIFICATE----- MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI 2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp +2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW /zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB ZQ== -----END CERTIFICATE----- # Issuer: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C. # Subject: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C. # Label: "Network Solutions Certificate Authority" # Serial: 116697915152937497490437556386812487904 # MD5 Fingerprint: d3:f3:a6:16:c0:fa:6b:1d:59:b1:2d:96:4d:0e:11:2e # SHA1 Fingerprint: 74:f8:a3:c3:ef:e7:b3:90:06:4b:83:90:3c:21:64:60:20:e5:df:ce # SHA256 Fingerprint: 15:f0:ba:00:a3:ac:7a:f3:ac:88:4c:07:2b:10:11:a0:77:bd:77:c0:97:f4:01:64:b2:f8:59:8a:bd:83:86:0c -----BEGIN CERTIFICATE----- MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4 qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8 6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/ h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH /nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey -----END CERTIFICATE----- # Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited # Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited # Label: "COMODO ECC Certification Authority" # Serial: 41578283867086692638256921589707938090 # MD5 Fingerprint: 7c:62:ff:74:9d:31:53:5e:68:4a:d5:78:aa:1e:bf:23 # SHA1 Fingerprint: 9f:74:4e:9f:2b:4d:ba:ec:0f:31:2c:50:b6:56:3b:8e:2d:93:c3:11 # SHA256 Fingerprint: 17:93:92:7a:06:14:54:97:89:ad:ce:2f:8f:34:f7:f0:b6:6d:0f:3a:e3:a3:b8:4d:21:ec:15:db:ba:4f:ad:c7 -----BEGIN CERTIFICATE----- MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= -----END CERTIFICATE----- # Issuer: O=SECOM Trust Systems CO.,LTD. OU=Security Communication EV RootCA1 # Subject: O=SECOM Trust Systems CO.,LTD. OU=Security Communication EV RootCA1 # Label: "Security Communication EV RootCA1" # Serial: 0 # MD5 Fingerprint: 22:2d:a6:01:ea:7c:0a:f7:f0:6c:56:43:3f:77:76:d3 # SHA1 Fingerprint: fe:b8:c4:32:dc:f9:76:9a:ce:ae:3d:d8:90:8f:fd:28:86:65:64:7d # SHA256 Fingerprint: a2:2d:ba:68:1e:97:37:6e:2d:39:7d:72:8a:ae:3a:9b:62:96:b9:fd:ba:60:bc:2e:11:f6:47:f2:c6:75:fb:37 -----BEGIN CERTIFICATE----- MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDEl MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMh U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIz MloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09N IFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNlY3VyaXR5IENvbW11 bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSE RMqm4miO/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gO zXppFodEtZDkBp2uoQSXWHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5 bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4zZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDF MxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4bepJz11sS6/vmsJWXMY1 VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK9U2vP9eC OKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0G CSqGSIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HW tWS3irO4G8za+6xmiEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZ q51ihPZRwSzJIxXYKLerJRO1RuGGAv8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDb EJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnWmHyojf6GPgcWkuF75x3sM3Z+ Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEWT1MKZPlO9L9O VL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490 -----END CERTIFICATE----- # Issuer: CN=OISTE WISeKey Global Root GA CA O=WISeKey OU=Copyright (c) 2005/OISTE Foundation Endorsed # Subject: CN=OISTE WISeKey Global Root GA CA O=WISeKey OU=Copyright (c) 2005/OISTE Foundation Endorsed # Label: "OISTE WISeKey Global Root GA CA" # Serial: 86718877871133159090080555911823548314 # MD5 Fingerprint: bc:6c:51:33:a7:e9:d3:66:63:54:15:72:1b:21:92:93 # SHA1 Fingerprint: 59:22:a1:e1:5a:ea:16:35:21:f8:98:39:6a:46:46:b0:44:1b:0f:a9 # SHA256 Fingerprint: 41:c9:23:86:6a:b4:ca:d6:b7:ad:57:80:81:58:2e:02:07:97:a6:cb:df:4f:ff:78:ce:83:96:b3:89:37:d7:f5 -----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCB ijELMAkGA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHly aWdodCAoYykgMjAwNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0w NTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYDVQQGEwJDSDEQMA4G A1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYD VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBX SVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR VVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2 w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsF mQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg 4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t9 4B3RLoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQw EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOx SPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VFvbBsUfk2 ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8 vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZi Fj4A4xylNoEYokxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ /L7fCg0= -----END CERTIFICATE----- # Issuer: CN=Certigna O=Dhimyotis # Subject: CN=Certigna O=Dhimyotis # Label: "Certigna" # Serial: 18364802974209362175 # MD5 Fingerprint: ab:57:a6:5b:7d:42:82:19:b5:d8:58:26:28:5e:fd:ff # SHA1 Fingerprint: b1:2e:13:63:45:86:a4:6f:1a:b2:60:68:37:58:2d:c4:ac:fd:94:97 # SHA256 Fingerprint: e3:b6:a2:db:2e:d7:ce:48:84:2f:7a:c5:32:41:c7:b7:1d:54:14:4b:fb:40:c1:1f:3f:1d:0b:42:f5:ee:a1:2d -----BEGIN CERTIFICATE----- MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4 QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q 130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2 JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG 9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== -----END CERTIFICATE----- # Issuer: CN=Deutsche Telekom Root CA 2 O=Deutsche Telekom AG OU=T-TeleSec Trust Center # Subject: CN=Deutsche Telekom Root CA 2 O=Deutsche Telekom AG OU=T-TeleSec Trust Center # Label: "Deutsche Telekom Root CA 2" # Serial: 38 # MD5 Fingerprint: 74:01:4a:91:b1:08:c4:58:ce:47:cd:f0:dd:11:53:08 # SHA1 Fingerprint: 85:a4:08:c0:9c:19:3e:5d:51:58:7d:cd:d6:13:30:fd:8c:de:37:bf # SHA256 Fingerprint: b6:19:1a:50:d0:c3:97:7f:7d:a9:9b:cd:aa:c8:6a:22:7d:ae:b9:67:9e:c7:0b:a3:b0:c9:d9:22:71:c1:70:d3 -----BEGIN CERTIFICATE----- MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290 IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc QqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl 6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+ xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU Cm26OWMohpLzGITY+9HPBVZkVw== -----END CERTIFICATE----- # Issuer: CN=Cybertrust Global Root O=Cybertrust, Inc # Subject: CN=Cybertrust Global Root O=Cybertrust, Inc # Label: "Cybertrust Global Root" # Serial: 4835703278459682877484360 # MD5 Fingerprint: 72:e4:4a:87:e3:69:40:80:77:ea:bc:e3:f4:ff:f0:e1 # SHA1 Fingerprint: 5f:43:e5:b1:bf:f8:78:8c:ac:1c:c7:ca:4a:9a:c6:22:2b:cc:34:c6 # SHA256 Fingerprint: 96:0a:df:00:63:e9:63:56:75:0c:29:65:dd:0a:08:67:da:0b:9c:bd:6e:77:71:4a:ea:fb:23:49:ab:39:3d:a3 -----BEGIN CERTIFICATE----- MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5 7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/ MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW WL1WMRJOEcgh4LMRkWXbtKaIOM5V -----END CERTIFICATE----- # Issuer: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority # Subject: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority # Label: "ePKI Root Certification Authority" # Serial: 28956088682735189655030529057352760477 # MD5 Fingerprint: 1b:2e:00:ca:26:06:90:3d:ad:fe:6f:15:68:d3:6b:b3 # SHA1 Fingerprint: 67:65:0d:f1:7e:8e:7e:5b:82:40:a4:f4:56:4b:cf:e2:3d:69:c6:f0 # SHA256 Fingerprint: c0:a6:f4:dc:63:a2:4b:fd:cf:54:ef:2a:6a:08:2a:0a:72:de:35:80:3e:2f:f5:ff:52:7a:e5:d8:72:06:df:d5 -----BEGIN CERTIFICATE----- MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1 TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/ gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2 j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6 5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS /jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D hNQ+IIX3Sj0rnP0qCglN6oH4EZw= -----END CERTIFICATE----- # Issuer: CN=TÜBİTAK UEKAE Kök Sertifika Hizmet SaÄŸlayıcısı - Sürüm 3 O=Türkiye Bilimsel ve Teknolojik AraÅŸtırma Kurumu - TÜBİTAK OU=Ulusal Elektronik ve Kriptoloji AraÅŸtırma Enstitüsü - UEKAE/Kamu Sertifikasyon Merkezi # Subject: CN=TÜBİTAK UEKAE Kök Sertifika Hizmet SaÄŸlayıcısı - Sürüm 3 O=Türkiye Bilimsel ve Teknolojik AraÅŸtırma Kurumu - TÜBİTAK OU=Ulusal Elektronik ve Kriptoloji AraÅŸtırma Enstitüsü - UEKAE/Kamu Sertifikasyon Merkezi # Label: "T\xc3\x9c\x42\xC4\xB0TAK UEKAE K\xC3\xB6k Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 - S\xC3\xBCr\xC3\xBCm 3" # Serial: 17 # MD5 Fingerprint: ed:41:f5:8c:50:c5:2b:9c:73:e6:ee:6c:eb:c2:a8:26 # SHA1 Fingerprint: 1b:4b:39:61:26:27:6b:64:91:a2:68:6d:d7:02:43:21:2d:1f:1d:96 # SHA256 Fingerprint: e4:c7:34:30:d7:a5:b5:09:25:df:43:37:0a:0d:21:6e:9a:79:b9:d6:db:83:73:a0:c6:9e:b1:cc:31:c7:c5:2a -----BEGIN CERTIFICATE----- MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRS MRgwFgYDVQQHDA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJp bGltc2VsIHZlIFRla25vbG9qaWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSw VEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ryb25payB2ZSBLcmlwdG9sb2ppIEFy YcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNVBAsMGkthbXUgU2Vy dGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUgS8O2 ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAe Fw0wNzA4MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIx GDAWBgNVBAcMD0dlYnplIC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmls aW1zZWwgdmUgVGVrbm9sb2ppayBBcmHFn3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBU QUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZlIEtyaXB0b2xvamkgQXJh xZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2FtdSBTZXJ0 aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7Zr IFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIB IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4h gb46ezzb8R1Sf1n68yJMlaCQvEhOEav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yK O7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1xnnRFDDtG1hba+818qEhTsXO fJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR6Oqeyjh1jmKw lZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQID AQABo0IwQDAdBgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/ BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmP NOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4N5EY3ATIZJkrGG2AA1nJrvhY0D7t wyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLTy9LQQfMmNkqblWwM 7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYhLBOh gLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5n oN+J1q2MdqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUs yZyQ2uypQjyttgI= -----END CERTIFICATE----- # Issuer: O=certSIGN OU=certSIGN ROOT CA # Subject: O=certSIGN OU=certSIGN ROOT CA # Label: "certSIGN ROOT CA" # Serial: 35210227249154 # MD5 Fingerprint: 18:98:c0:d6:e9:3a:fc:f9:b0:f5:0c:f7:4b:01:44:17 # SHA1 Fingerprint: fa:b7:ee:36:97:26:62:fb:2d:b0:2a:f6:bf:03:fd:e8:7c:4b:2f:9b # SHA256 Fingerprint: ea:a9:62:c4:fa:4a:6b:af:eb:e4:15:19:6d:35:1c:cd:88:8d:4f:53:f3:fa:8a:e6:d7:c4:66:a9:4e:60:42:bb -----BEGIN CERTIFICATE----- MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do 0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ 44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN 9u6wWk5JRFRYX0KD -----END CERTIFICATE----- # Issuer: CN=CNNIC ROOT O=CNNIC # Subject: CN=CNNIC ROOT O=CNNIC # Label: "CNNIC ROOT" # Serial: 1228079105 # MD5 Fingerprint: 21:bc:82:ab:49:c4:13:3b:4b:b2:2b:5c:6b:90:9c:19 # SHA1 Fingerprint: 8b:af:4c:9b:1d:f0:2a:92:f7:da:12:8e:b9:1b:ac:f4:98:60:4b:6f # SHA256 Fingerprint: e2:83:93:77:3d:a8:45:a6:79:f2:08:0c:c7:fb:44:a3:b7:a1:c3:79:2c:b7:eb:77:29:fd:cb:6a:8d:99:ae:a7 -----BEGIN CERTIFICATE----- MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJD TjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2 MDcwOTE0WhcNMjcwNDE2MDcwOTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMF Q05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwggEiMA0GCSqGSIb3DQEBAQUAA4IB DwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzDo+/hn7E7SIX1mlwh IhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tizVHa6 dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZO V/kbZKKTVrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrC GHn2emU1z5DrvTOTn1OrczvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gN v7Sg2Ca+I19zN38m5pIEo3/PIKe38zrKy5nLAgMBAAGjczBxMBEGCWCGSAGG+EIB AQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscCwQ7vptU7ETAPBgNVHRMB Af8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991SlgrHAsEO 76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnK OOK5Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvH ugDnuL8BV8F3RTIMO/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7Hgvi yJA/qIYM/PmLXoXLT1tLYhFHxUV8BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fL buXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2G8kS1sHNzYDzAgE8yGnLRUhj 2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5mmxE= -----END CERTIFICATE----- # Issuer: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only # Subject: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only # Label: "GeoTrust Primary Certification Authority - G3" # Serial: 28809105769928564313984085209975885599 # MD5 Fingerprint: b5:e8:34:36:c9:10:44:58:48:70:6d:2e:83:d4:b8:05 # SHA1 Fingerprint: 03:9e:ed:b8:0b:e7:a0:3c:69:53:89:3b:20:d2:d9:32:3a:4c:2a:fd # SHA256 Fingerprint: b4:78:b8:12:25:0d:f8:78:63:5c:2a:a7:ec:7d:15:5e:aa:62:5e:e8:29:16:e2:cd:29:43:61:88:6c:d1:fb:d4 -----BEGIN CERTIFICATE----- MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0 BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz +uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn 5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G spki4cErx5z481+oghLrGREt -----END CERTIFICATE----- # Issuer: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only # Subject: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only # Label: "thawte Primary Root CA - G2" # Serial: 71758320672825410020661621085256472406 # MD5 Fingerprint: 74:9d:ea:60:24:c4:fd:22:53:3e:cc:3a:72:d9:29:4f # SHA1 Fingerprint: aa:db:bc:22:23:8f:c4:01:a1:27:bb:38:dd:f4:1d:db:08:9e:f0:12 # SHA256 Fingerprint: a4:31:0d:50:af:18:a6:44:71:90:37:2a:86:af:af:8b:95:1f:fb:43:1d:83:7f:1e:56:88:b4:59:71:ed:15:57 -----BEGIN CERTIFICATE----- MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/ BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6 papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3 KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== -----END CERTIFICATE----- # Issuer: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only # Subject: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only # Label: "thawte Primary Root CA - G3" # Serial: 127614157056681299805556476275995414779 # MD5 Fingerprint: fb:1b:5d:43:8a:94:cd:44:c6:76:f2:43:4b:47:e7:31 # SHA1 Fingerprint: f1:8b:53:8d:1b:e9:03:b6:a6:f0:56:43:5b:17:15:89:ca:f3:6b:f2 # SHA256 Fingerprint: 4b:03:f4:58:07:ad:70:f2:1b:fc:2c:ae:71:c9:fd:e4:60:4c:06:4c:f5:ff:b6:86:ba:e5:db:aa:d7:fd:d3:4c -----BEGIN CERTIFICATE----- MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8 YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9 9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA 2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu MdRAGmI0Nj81Aa6sY6A= -----END CERTIFICATE----- # Issuer: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only # Subject: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only # Label: "GeoTrust Primary Certification Authority - G2" # Serial: 80682863203381065782177908751794619243 # MD5 Fingerprint: 01:5e:d8:6b:bd:6f:3d:8e:a1:31:f8:12:e0:98:73:6a # SHA1 Fingerprint: 8d:17:84:d5:37:f3:03:7d:ec:70:fe:57:8b:51:9a:99:e6:10:d7:b0 # SHA256 Fingerprint: 5e:db:7a:c4:3b:82:a0:6a:87:61:e8:d7:be:49:79:eb:f2:61:1f:7d:d7:9b:f9:1c:1c:6b:56:6a:21:9e:d7:66 -----BEGIN CERTIFICATE----- MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2 MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz rD6ogRLQy7rQkgu2npaqBA+K -----END CERTIFICATE----- # Issuer: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only # Subject: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only # Label: "VeriSign Universal Root Certification Authority" # Serial: 85209574734084581917763752644031726877 # MD5 Fingerprint: 8e:ad:b5:01:aa:4d:81:e4:8c:1d:d1:e1:14:00:95:19 # SHA1 Fingerprint: 36:79:ca:35:66:87:72:30:4d:30:a5:fb:87:3b:0f:a7:7b:b7:0d:54 # SHA256 Fingerprint: 23:99:56:11:27:a5:71:25:de:8c:ef:ea:61:0d:df:2f:a0:78:b5:c8:06:7f:4e:82:82:90:bf:b8:60:e8:4b:3c -----BEGIN CERTIFICATE----- MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0 IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF 9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN /BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4 sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+ seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz 4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+ BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3 7M2CYfE45k+XmCpajQ== -----END CERTIFICATE----- # Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only # Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only # Label: "VeriSign Class 3 Public Primary Certification Authority - G4" # Serial: 63143484348153506665311985501458640051 # MD5 Fingerprint: 3a:52:e1:e7:fd:6f:3a:e3:6f:f3:6f:99:1b:f9:22:41 # SHA1 Fingerprint: 22:d5:d8:df:8f:02:31:d1:8d:f7:9d:b7:cf:8a:2d:64:c9:3f:6c:3a # SHA256 Fingerprint: 69:dd:d7:ea:90:bb:57:c9:3e:13:5d:c8:5e:a6:fc:d5:48:0b:60:32:39:bd:c4:54:fc:75:8b:2a:26:cf:7f:79 -----BEGIN CERTIFICATE----- MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC 4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== -----END CERTIFICATE----- # Issuer: CN=NetLock Arany (Class Gold) FÅ‘tanúsítvány O=NetLock Kft. OU=Tanúsítványkiadók (Certification Services) # Subject: CN=NetLock Arany (Class Gold) FÅ‘tanúsítvány O=NetLock Kft. OU=Tanúsítványkiadók (Certification Services) # Label: "NetLock Arany (Class Gold) FÅ‘tanúsítvány" # Serial: 80544274841616 # MD5 Fingerprint: c5:a1:b7:ff:73:dd:d6:d7:34:32:18:df:fc:3c:ad:88 # SHA1 Fingerprint: 06:08:3f:59:3f:15:a1:04:a0:69:a4:6b:a9:03:d0:06:b7:97:09:91 # SHA256 Fingerprint: 6c:61:da:c3:a2:de:f0:31:50:6b:e0:36:d2:a6:fe:40:19:94:fb:d1:3d:f9:c8:d4:66:59:92:74:c4:46:ec:98 -----BEGIN CERTIFICATE----- MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5 VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2 BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C +C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= -----END CERTIFICATE----- # Issuer: CN=Staat der Nederlanden Root CA - G2 O=Staat der Nederlanden # Subject: CN=Staat der Nederlanden Root CA - G2 O=Staat der Nederlanden # Label: "Staat der Nederlanden Root CA - G2" # Serial: 10000012 # MD5 Fingerprint: 7c:a5:0f:f8:5b:9a:7d:6d:30:ae:54:5a:e3:42:a2:8a # SHA1 Fingerprint: 59:af:82:79:91:86:c7:b4:75:07:cb:cf:03:57:46:eb:04:dd:b7:16 # SHA256 Fingerprint: 66:8c:83:94:7d:a6:3b:72:4b:ec:e1:74:3c:31:a0:e6:ae:d0:db:8e:c5:b3:1b:e3:77:bb:78:4f:91:b6:71:6f -----BEGIN CERTIFICATE----- MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oX DTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv b3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ5291 qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8Sp uOUfiUtnvWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPU Z5uW6M7XxgpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvE pMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiile7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp 5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCROME4HYYEhLoaJXhena/M UGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpICT0ugpTN GmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy 5V6548r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv 6q012iDTiIJh8BIitrzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEK eN5KzlW/HdXZt1bv8Hb/C3m1r737qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6 B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMBAAGjgZcwgZQwDwYDVR0TAQH/ BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcCARYxaHR0cDov L3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqG SIb3DQEBCwUAA4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLyS CZa59sCrI2AGeYwRTlHSeYAz+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen 5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwjf/ST7ZwaUb7dRUG/kSS0H4zpX897 IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaNkqbG9AclVMwWVxJK gnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfkCpYL +63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxL vJxxcypFURmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkm bEgeqmiSBeGCc1qb3AdbCG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvk N1trSt8sV4pAWja63XVECDdCcAz+3F4hoKOKwJCcaNpQ5kUQR3i2TtJlycM33+FC Y7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoVIPVVYpbtbZNQvOSqeK3Z ywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm66+KAQ== -----END CERTIFICATE----- # Issuer: CN=Hongkong Post Root CA 1 O=Hongkong Post # Subject: CN=Hongkong Post Root CA 1 O=Hongkong Post # Label: "Hongkong Post Root CA 1" # Serial: 1000 # MD5 Fingerprint: a8:0d:6f:39:78:b9:43:6d:77:42:6d:98:5a:cc:23:ca # SHA1 Fingerprint: d6:da:a8:20:8d:09:d2:15:4d:24:b5:2f:cb:34:6e:b2:58:b2:8a:58 # SHA256 Fingerprint: f9:e6:7d:33:6c:51:00:2a:c0:54:c6:32:02:2d:66:dd:a2:e7:e3:ff:f1:0a:d0:61:ed:31:d8:bb:b4:10:cf:b2 -----BEGIN CERTIFICATE----- MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9 nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3 7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi AmvZWg== -----END CERTIFICATE----- # Issuer: CN=SecureSign RootCA11 O=Japan Certification Services, Inc. # Subject: CN=SecureSign RootCA11 O=Japan Certification Services, Inc. # Label: "SecureSign RootCA11" # Serial: 1 # MD5 Fingerprint: b7:52:74:e2:92:b4:80:93:f2:75:e4:cc:d7:f2:ea:26 # SHA1 Fingerprint: 3b:c4:9f:48:f8:f3:73:a0:9c:1e:bd:f8:5b:b1:c3:65:c7:d8:11:b3 # SHA256 Fingerprint: bf:0f:ee:fb:9e:3a:58:1a:d5:f9:e9:db:75:89:98:57:43:d2:61:08:5c:4d:31:4f:6f:5d:72:59:aa:42:16:12 -----BEGIN CERTIFICATE----- MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDEr MCkGA1UEChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoG A1UEAxMTU2VjdXJlU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0 MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZp Y2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RD QTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvLTJsz i1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8 h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOV MdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9 UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni 8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsC h8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYD VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB AKChOBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xm KbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQ X5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWr QbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR7SXf+Of5 pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN QSdJQO7e5iNEOdyhIta6A/I= -----END CERTIFICATE----- # Issuer: CN=ACEDICOM Root O=EDICOM OU=PKI # Subject: CN=ACEDICOM Root O=EDICOM OU=PKI # Label: "ACEDICOM Root" # Serial: 7029493972724711941 # MD5 Fingerprint: 42:81:a0:e2:1c:e3:55:10:de:55:89:42:65:96:22:e6 # SHA1 Fingerprint: e0:b4:32:2e:b2:f6:a5:68:b6:54:53:84:48:18:4a:50:36:87:43:84 # SHA256 Fingerprint: 03:95:0f:b4:9a:53:1f:3e:19:91:94:23:98:df:a9:e0:ea:32:d7:ba:1c:dd:9b:c8:5d:b5:7e:d9:40:0b:43:4a -----BEGIN CERTIFICATE----- MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UE AwwNQUNFRElDT00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00x CzAJBgNVBAYTAkVTMB4XDTA4MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEW MBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZF RElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC AgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHkWLn7 09gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7 XBZXehuDYAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5P Grjm6gSSrj0RuVFCPYewMYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAK t0SdE3QrwqXrIhWYENiLxQSfHY9g5QYbm8+5eaA9oiM/Qj9r+hwDezCNzmzAv+Yb X79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbkHQl/Sog4P75n/TSW9R28 MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTTxKJxqvQU fecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI 2Sf23EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyH K9caUPgn6C9D4zq92Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEae ZAwUswdbxcJzbPEHXEUkFDWug/FqTYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAP BgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz4SsrSbbXc6GqlPUB53NlTKxQ MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU9QHnc2VMrFAw RAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWIm fQwng4/F9tqgaHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3 gvoFNTPhNahXwOf9jU8/kzJPeGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKe I6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1PwkzQSulgUV1qzOMPPKC8W64iLgpq0i 5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1ThCojz2GuHURwCRi ipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oIKiMn MCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZ o5NjEFIqnxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6 zqylfDJKZ0DcMDQj3dcEI2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacN GHk0vFQYXlPKNFHtRQrmjseCNj6nOGOpMCwXEGCSn1WHElkQwg9naRHMTh5+Spqt r0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3otkYNbn5XOmeUwssfnHdK Z05phkOTOPu220+DkdRgfks+KzgHVZhepA== -----END CERTIFICATE----- # Issuer: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. # Subject: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. # Label: "Microsec e-Szigno Root CA 2009" # Serial: 14014712776195784473 # MD5 Fingerprint: f8:49:f4:03:bc:44:2d:83:be:48:69:7d:29:64:fc:b1 # SHA1 Fingerprint: 89:df:74:fe:5c:f4:0f:4a:80:f9:e3:37:7d:54:da:91:e1:01:31:8e # SHA256 Fingerprint: 3c:5f:81:fe:a5:fa:b8:2c:64:bf:a2:ea:ec:af:cd:e8:e0:77:fc:86:20:a7:ca:e5:37:16:3d:f3:6e:db:f3:78 -----BEGIN CERTIFICATE----- MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7 N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1 +rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c 2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW -----END CERTIFICATE----- # Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 # Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 # Label: "GlobalSign Root CA - R3" # Serial: 4835703278459759426209954 # MD5 Fingerprint: c5:df:b8:49:ca:05:13:55:ee:2d:ba:1a:c3:3e:b0:28 # SHA1 Fingerprint: d6:9b:56:11:48:f0:1c:77:c5:45:78:c1:09:26:df:5b:85:69:76:ad # SHA256 Fingerprint: cb:b5:22:d7:b7:f1:27:ad:6a:01:13:86:5b:df:1c:d4:10:2e:7d:07:59:af:63:5a:7c:f4:72:0d:c9:63:c5:3b -----BEGIN CERTIFICATE----- MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK 6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH WD9f -----END CERTIFICATE----- # Issuer: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 # Subject: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 # Label: "Autoridad de Certificacion Firmaprofesional CIF A62634068" # Serial: 6047274297262753887 # MD5 Fingerprint: 73:3a:74:7a:ec:bb:a3:96:a6:c2:e4:e2:c8:9b:c0:c3 # SHA1 Fingerprint: ae:c5:fb:3f:c8:e1:bf:c4:e5:4f:03:07:5a:9a:e8:00:b7:f7:b6:fa # SHA256 Fingerprint: 04:04:80:28:bf:1f:28:64:d4:8f:9a:d4:d8:32:94:36:6a:82:88:56:55:3f:3b:14:30:3f:90:14:7f:5d:40:ef -----BEGIN CERTIFICATE----- MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEy MzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9 thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF 6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNHDhpkLzCBpgYD VR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBv ACAAZABlACAAbABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBl AGwAbwBuAGEAIAAwADgAMAAxADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF 661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx51tkljYyGOylMnfX40S2wBEqgLk9 am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qkR71kMrv2JYSiJ0L1 ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaPT481 PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS 3a/DTg4fJl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5k SeTy36LssUzAKh3ntLFlosS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF 3dvd6qJ2gHN99ZwExEWN57kci57q13XRcrHedUTnQn3iV2t93Jm8PYMo6oCTjcVM ZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoRsaS8I8nkvof/uZS2+F0g StRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTDKCOM/icz Q0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQB jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V -----END CERTIFICATE----- # Issuer: CN=Izenpe.com O=IZENPE S.A. # Subject: CN=Izenpe.com O=IZENPE S.A. # Label: "Izenpe.com" # Serial: 917563065490389241595536686991402621 # MD5 Fingerprint: a6:b0:cd:85:80:da:5c:50:34:a3:39:90:2f:55:67:73 # SHA1 Fingerprint: 2f:78:3d:25:52:18:a7:4a:65:39:71:b5:2c:a2:9c:45:15:6f:e9:19 # SHA256 Fingerprint: 25:30:cc:8e:98:32:15:02:ba:d9:6f:9b:1f:ba:1b:09:9e:2d:29:9e:0f:45:48:bb:91:4f:36:3b:c0:d4:53:1f -----BEGIN CERTIFICATE----- MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4 MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6 ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+ JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+ HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56 awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/ QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+ naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== -----END CERTIFICATE----- # Issuer: CN=Chambers of Commerce Root - 2008 O=AC Camerfirma S.A. # Subject: CN=Chambers of Commerce Root - 2008 O=AC Camerfirma S.A. # Label: "Chambers of Commerce Root - 2008" # Serial: 11806822484801597146 # MD5 Fingerprint: 5e:80:9e:84:5a:0e:65:0b:17:02:f3:55:18:2a:3e:d7 # SHA1 Fingerprint: 78:6a:74:ac:76:ab:14:7f:9c:6a:30:50:ba:9e:a8:7e:fe:9a:ce:3c # SHA256 Fingerprint: 06:3e:4a:fa:c4:91:df:d3:32:f3:08:9b:85:42:e9:46:17:d8:93:d7:fe:94:4e:10:a7:93:7e:e2:9d:96:93:c0 -----BEGIN CERTIFICATE----- MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJz IG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEyMjk1MFoXDTM4MDcz MTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBj dXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIw EAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEp MCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0G CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW9 28sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKAXuFixrYp4YFs8r/lfTJq VKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorjh40G072Q DuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR 5gN/ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfL ZEFHcpOrUMPrCXZkNNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05a Sd+pZgvMPMZ4fKecHePOjlO+Bd5gD2vlGts/4+EhySnB8esHnFIbAURRPHsl18Tl UlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331lubKgdaX8ZSD6e2wsWsSaR6s +12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ0wlf2eOKNcx5 Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAx hduub+84Mxh2EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNV HQ4EFgQU+SSsD7K1+HnA+mCIG8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1 +HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpN YWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29t L2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVy ZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAt IDIwMDiCCQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRV HSAAMCowKAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20w DQYJKoZIhvcNAQEFBQADggIBAJASryI1wqM58C7e6bXpeHxIvj99RZJe6dqxGfwW PJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH3qLPaYRgM+gQDROpI9CF 5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbURWpGqOt1 glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaH FoI6M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2 pSB7+R5KBWIBpih1YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MD xvbxrN8y8NmBGuScvfaAFPDRLLmF9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QG tjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcKzBIKinmwPQN/aUv0NCB9szTq jktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvGnrDQWzilm1De fhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZ d0jQ -----END CERTIFICATE----- # Issuer: CN=Global Chambersign Root - 2008 O=AC Camerfirma S.A. # Subject: CN=Global Chambersign Root - 2008 O=AC Camerfirma S.A. # Label: "Global Chambersign Root - 2008" # Serial: 14541511773111788494 # MD5 Fingerprint: 9e:80:ff:78:01:0c:2e:c1:36:bd:fe:96:90:6e:08:f3 # SHA1 Fingerprint: 4a:bd:ee:ec:95:0d:35:9c:89:ae:c7:52:a1:2c:5b:29:f6:d6:aa:0c # SHA256 Fingerprint: 13:63:35:43:93:34:a7:69:80:16:a0:d3:24:de:72:28:4e:07:9d:7b:52:20:bb:8f:bd:74:78:16:ee:be:ba:ca -----BEGIN CERTIFICATE----- MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD aGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMxNDBaFw0zODA3MzEx MjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI hvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xed KYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7 G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2 zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4 ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyG HoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2 Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3V yJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al/3K1dh3e beksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r 6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsog zCtLkykPAgMBAAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQW BBS5CcqcHtvTbDprru1U8VuTBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDpr ru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJp ZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJmaXJtYS5jb20vYWRk cmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJt YSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiC CQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow KAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI hvcNAQEFBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZ UohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXoz X1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/x fxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVz a2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yyd Yhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMd SqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9O AP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso M0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4ge v8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z 09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B -----END CERTIFICATE----- # Issuer: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. # Subject: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. # Label: "Go Daddy Root Certificate Authority - G2" # Serial: 0 # MD5 Fingerprint: 80:3a:bc:22:c1:e6:fb:8d:9b:3b:27:4a:32:1b:9a:01 # SHA1 Fingerprint: 47:be:ab:c9:22:ea:e8:0e:78:78:34:62:a7:9f:45:c2:54:fd:e6:8b # SHA256 Fingerprint: 45:14:0b:32:47:eb:9c:c8:c5:b4:f0:d7:b5:30:91:f7:32:92:08:9e:6e:5a:63:e2:74:9d:d3:ac:a9:19:8e:da -----BEGIN CERTIFICATE----- MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH /PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu 9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo 2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI 4uJEvlz36hz1 -----END CERTIFICATE----- # Issuer: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. # Subject: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. # Label: "Starfield Root Certificate Authority - G2" # Serial: 0 # MD5 Fingerprint: d6:39:81:c6:52:7e:96:69:fc:fc:ca:66:ed:05:f2:96 # SHA1 Fingerprint: b5:1c:06:7c:ee:2b:0c:3d:f8:55:ab:2d:92:f4:fe:39:d4:e7:0f:0e # SHA256 Fingerprint: 2c:e1:cb:0b:f9:d2:f9:e1:02:99:3f:be:21:51:52:c3:b2:dd:0c:ab:de:1c:68:e5:31:9b:83:91:54:db:b7:f5 -----BEGIN CERTIFICATE----- MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg 8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 -----END CERTIFICATE----- # Issuer: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. # Subject: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. # Label: "Starfield Services Root Certificate Authority - G2" # Serial: 0 # MD5 Fingerprint: 17:35:74:af:7b:61:1c:eb:f4:f9:3c:e2:ee:40:f9:a2 # SHA1 Fingerprint: 92:5a:8f:8d:2c:6d:04:e0:66:5f:59:6a:ff:22:d8:63:e8:25:6f:3f # SHA256 Fingerprint: 56:8d:69:05:a2:c8:87:08:a4:b3:02:51:90:ed:cf:ed:b1:97:4a:60:6a:13:c6:e5:29:0f:cb:2a:e6:3e:da:b5 -----BEGIN CERTIFICATE----- MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk 6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn 0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN sSi6 -----END CERTIFICATE----- # Issuer: CN=AffirmTrust Commercial O=AffirmTrust # Subject: CN=AffirmTrust Commercial O=AffirmTrust # Label: "AffirmTrust Commercial" # Serial: 8608355977964138876 # MD5 Fingerprint: 82:92:ba:5b:ef:cd:8a:6f:a6:3d:55:f9:84:f6:d6:b7 # SHA1 Fingerprint: f9:b5:b6:32:45:5f:9c:be:ec:57:5f:80:dc:e9:6e:2c:c7:b2:78:b7 # SHA256 Fingerprint: 03:76:ab:1d:54:c5:f9:80:3c:e4:b2:e2:01:a0:ee:7e:ef:7b:57:b6:36:e8:a9:3c:9b:8d:48:60:c9:6f:5f:a7 -----BEGIN CERTIFICATE----- MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= -----END CERTIFICATE----- # Issuer: CN=AffirmTrust Networking O=AffirmTrust # Subject: CN=AffirmTrust Networking O=AffirmTrust # Label: "AffirmTrust Networking" # Serial: 8957382827206547757 # MD5 Fingerprint: 42:65:ca:be:01:9a:9a:4c:a9:8c:41:49:cd:c0:d5:7f # SHA1 Fingerprint: 29:36:21:02:8b:20:ed:02:f5:66:c5:32:d1:d6:ed:90:9f:45:00:2f # SHA256 Fingerprint: 0a:81:ec:5a:92:97:77:f1:45:90:4a:f3:8d:5d:50:9f:66:b5:e2:c5:8f:cd:b5:31:05:8b:0e:17:f3:f0:b4:1b -----BEGIN CERTIFICATE----- MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp 6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= -----END CERTIFICATE----- # Issuer: CN=AffirmTrust Premium O=AffirmTrust # Subject: CN=AffirmTrust Premium O=AffirmTrust # Label: "AffirmTrust Premium" # Serial: 7893706540734352110 # MD5 Fingerprint: c4:5d:0e:48:b6:ac:28:30:4e:0a:bc:f9:38:16:87:57 # SHA1 Fingerprint: d8:a6:33:2c:e0:03:6f:b1:85:f6:63:4f:7d:6a:06:65:26:32:28:27 # SHA256 Fingerprint: 70:a7:3f:7f:37:6b:60:07:42:48:90:45:34:b1:14:82:d5:bf:0e:69:8e:cc:49:8d:f5:25:77:eb:f2:e9:3b:9a -----BEGIN CERTIFICATE----- MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ +jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S 5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B 8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc 0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e KeC2uAloGRwYQw== -----END CERTIFICATE----- # Issuer: CN=AffirmTrust Premium ECC O=AffirmTrust # Subject: CN=AffirmTrust Premium ECC O=AffirmTrust # Label: "AffirmTrust Premium ECC" # Serial: 8401224907861490260 # MD5 Fingerprint: 64:b0:09:55:cf:b1:d5:99:e2:be:13:ab:a6:5d:ea:4d # SHA1 Fingerprint: b8:23:6b:00:2f:1d:16:86:53:01:55:6c:11:a4:37:ca:eb:ff:c3:bb # SHA256 Fingerprint: bd:71:fd:f6:da:97:e4:cf:62:d1:64:7a:dd:25:81:b0:7d:79:ad:f8:39:7e:b4:ec:ba:9c:5e:84:88:82:14:23 -----BEGIN CERTIFICATE----- MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D 0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== -----END CERTIFICATE----- # Issuer: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority # Subject: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority # Label: "Certum Trusted Network CA" # Serial: 279744 # MD5 Fingerprint: d5:e9:81:40:c5:18:69:fc:46:2c:89:75:62:0f:aa:78 # SHA1 Fingerprint: 07:e0:32:e0:20:b7:2c:3f:19:2f:06:28:a2:59:3a:19:a7:0f:06:9e # SHA256 Fingerprint: 5c:58:46:8d:55:f5:8e:49:7e:74:39:82:d2:b5:00:10:b6:d1:65:37:4a:cf:83:a7:d4:a3:2d:b7:68:c4:40:8e -----BEGIN CERTIFICATE----- MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3 WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8 J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI 03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= -----END CERTIFICATE----- # Issuer: CN=Certinomis - Autorité Racine O=Certinomis OU=0002 433998903 # Subject: CN=Certinomis - Autorité Racine O=Certinomis OU=0002 433998903 # Label: "Certinomis - Autorité Racine" # Serial: 1 # MD5 Fingerprint: 7f:30:78:8c:03:e3:ca:c9:0a:e2:c9:ea:1e:aa:55:1a # SHA1 Fingerprint: 2e:14:da:ec:28:f0:fa:1e:8e:38:9a:4e:ab:eb:26:c0:0a:d3:83:c3 # SHA256 Fingerprint: fc:bf:e2:88:62:06:f7:2b:27:59:3c:8b:07:02:97:e1:2d:76:9e:d1:0e:d7:93:07:05:a8:09:8e:ff:c1:4d:17 -----BEGIN CERTIFICATE----- MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjET MBEGA1UEChMKQ2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAk BgNVBAMMHUNlcnRpbm9taXMgLSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4 Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkGA1UEBhMCRlIxEzARBgNVBAoTCkNl cnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYwJAYDVQQDDB1DZXJ0 aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQADggIP ADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jY F1AMnmHawE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N 8y4oH3DfVS9O7cdxbwlyLu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWe rP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K /OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92NjMD2AR5vpTESOH2VwnHu 7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9qc1pkIuVC 28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6 lSTClrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1E nn1So2+WLhl+HPNbxxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB 0iSVL1N6aaLwD4ZFjliCK0wi1F6g530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql09 5gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna4NH4+ej9Uji29YnfAgMBAAGj WzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBQN jLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9s ov3/4gbIOZ/xWqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZM OH8oMDX/nyNTt7buFHAAQCvaR6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q 619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40nJ+U8/aGH88bc62UeYdocMMzpXDn 2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1BCxMjidPJC+iKunqj o3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjvJL1v nxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG 5ERQL1TEqkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWq pdEdnV1j6CTmNhTih60bWfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZb dsLLO7XSAPCjDuGtbkD326C00EauFddEwk01+dIL8hf2rGbVJLJP0RyZwG71fet0 BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/vgt2Fl43N+bYdJeimUV5 -----END CERTIFICATE----- # Issuer: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA # Subject: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA # Label: "TWCA Root Certification Authority" # Serial: 1 # MD5 Fingerprint: aa:08:8f:f6:f9:7b:b7:f2:b1:a7:1e:9b:ea:ea:bd:79 # SHA1 Fingerprint: cf:9e:87:6d:d3:eb:fc:42:26:97:a3:b5:a3:7a:a0:76:a9:06:23:48 # SHA256 Fingerprint: bf:d8:8f:e1:10:1c:41:ae:3e:80:1b:f8:be:56:35:0e:e9:ba:d1:a6:b9:bd:51:5e:dc:5c:6d:5b:87:11:ac:44 -----BEGIN CERTIFICATE----- MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx 3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== -----END CERTIFICATE----- # Issuer: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2 # Subject: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2 # Label: "Security Communication RootCA2" # Serial: 0 # MD5 Fingerprint: 6c:39:7d:a4:0e:55:59:b2:3f:d6:41:b1:12:50:de:43 # SHA1 Fingerprint: 5f:3b:8c:f2:f8:10:b3:7d:78:b4:ce:ec:19:19:c3:73:34:b9:c7:74 # SHA256 Fingerprint: 51:3b:2c:ec:b8:10:d4:cd:e5:dd:85:39:1a:df:c6:c2:dd:60:d8:7b:b7:36:d2:b5:21:48:4a:a4:7a:0e:be:f6 -----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8 t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy 1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/ SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 -----END CERTIFICATE----- # Issuer: CN=EC-ACC O=Agencia Catalana de Certificacio (NIF Q-0801176-I) OU=Serveis Publics de Certificacio/Vegeu https://www.catcert.net/verarrel (c)03/Jerarquia Entitats de Certificacio Catalanes # Subject: CN=EC-ACC O=Agencia Catalana de Certificacio (NIF Q-0801176-I) OU=Serveis Publics de Certificacio/Vegeu https://www.catcert.net/verarrel (c)03/Jerarquia Entitats de Certificacio Catalanes # Label: "EC-ACC" # Serial: -23701579247955709139626555126524820479 # MD5 Fingerprint: eb:f5:9d:29:0d:61:f9:42:1f:7c:c2:ba:6d:e3:15:09 # SHA1 Fingerprint: 28:90:3a:63:5b:52:80:fa:e6:77:4c:0b:6d:a7:d6:ba:a6:4a:f2:e8 # SHA256 Fingerprint: 88:49:7f:01:60:2f:31:54:24:6a:e2:8c:4d:5a:ef:10:f1:d8:7e:bb:76:62:6f:4a:e0:b7:f9:5b:a7:96:87:99 -----BEGIN CERTIFICATE----- MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB 8zELMAkGA1UEBhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2Vy dGlmaWNhY2lvIChOSUYgUS0wODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1 YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYDVQQLEyxWZWdldSBodHRwczovL3d3 dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UECxMsSmVyYXJxdWlh IEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMTBkVD LUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQG EwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8g KE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBD ZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQu bmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMg ZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUNDMIIBIjAN BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R 85iKw5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm 4CgPukLjbo73FCeTae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaV HMf5NLWUhdWZXqBIoH7nF2W4onW4HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNd QlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0aE9jD2z3Il3rucO2n5nzbcc8t lGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw0JDnJwIDAQAB o4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4 opvpXY0wfwYDVR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBo dHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidW ZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAwDQYJKoZIhvcN AQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJlF7W2u++AVtd0x7Y /X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNaAl6k SBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhy Rp/7SNVel+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOS Agu+TGbrIP65y7WZf+a2E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xl nJ2lYJU6Un/10asIbvPuW/mIPX64b24D5EI= -----END CERTIFICATE----- # Issuer: CN=Hellenic Academic and Research Institutions RootCA 2011 O=Hellenic Academic and Research Institutions Cert. Authority # Subject: CN=Hellenic Academic and Research Institutions RootCA 2011 O=Hellenic Academic and Research Institutions Cert. Authority # Label: "Hellenic Academic and Research Institutions RootCA 2011" # Serial: 0 # MD5 Fingerprint: 73:9f:4c:4b:73:5b:79:e9:fa:ba:1c:ef:6e:cb:d5:c9 # SHA1 Fingerprint: fe:45:65:9b:79:03:5b:98:a1:61:b5:51:2e:ac:da:58:09:48:22:4d # SHA256 Fingerprint: bc:10:4f:15:a4:8b:e7:09:dc:a5:42:a7:e1:d4:b9:df:6f:05:45:27:e8:02:ea:a9:2d:59:54:44:25:8a:fe:71 -----BEGIN CERTIFICATE----- MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1Ix RDBCBgNVBAoTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1p YyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIFJvb3RDQSAyMDExMB4XDTExMTIw NjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYTAkdSMUQwQgYDVQQK EztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENl cnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl c2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEB BQADggEPADCCAQoCggEBAKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPz dYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJ fel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa71HFK9+WXesyHgLacEns bgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u8yBRQlqD 75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSP FEDH3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNV HRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp 5dgTBCPuQSUwRwYDVR0eBEAwPqA8MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQu b3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQub3JnMA0GCSqGSIb3DQEBBQUA A4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVtXdMiKahsog2p 6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7 dIsXRSZMFpGD/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8Acys Nnq/onN694/BtZqhFLKPM58N7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXI l7WdmplNsDz4SgCbZN2fOUvRJ9e4 -----END CERTIFICATE----- # Issuer: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967 # Subject: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967 # Label: "Actalis Authentication Root CA" # Serial: 6271844772424770508 # MD5 Fingerprint: 69:c1:0d:4f:07:a3:1b:c3:fe:56:3d:04:bc:11:f6:a6 # SHA1 Fingerprint: f3:73:b3:87:06:5a:28:84:8a:f2:f3:4a:ce:19:2b:dd:c7:8e:9c:ac # SHA256 Fingerprint: 55:92:60:84:ec:96:3a:64:b9:6e:2a:be:01:ce:0b:a8:6a:64:fb:fe:bc:c7:aa:b5:af:c1:55:b3:7f:d7:60:66 -----BEGIN CERTIFICATE----- MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1 ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX 4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9 KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/ gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ 51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7 jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70 jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== -----END CERTIFICATE----- # Issuer: O=Trustis Limited OU=Trustis FPS Root CA # Subject: O=Trustis Limited OU=Trustis FPS Root CA # Label: "Trustis FPS Root CA" # Serial: 36053640375399034304724988975563710553 # MD5 Fingerprint: 30:c9:e7:1e:6b:e6:14:eb:65:b2:16:69:20:31:67:4d # SHA1 Fingerprint: 3b:c0:38:0b:33:c3:f6:a6:0c:86:15:22:93:d9:df:f5:4b:81:c0:04 # SHA256 Fingerprint: c1:b4:82:99:ab:a5:20:8f:e9:63:0a:ce:55:ca:68:a0:3e:da:5a:51:9c:88:02:a0:d3:a6:73:be:8f:8e:55:7d -----BEGIN CERTIFICATE----- MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBF MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQL ExNUcnVzdGlzIEZQUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTEx MzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEc MBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD ggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQRUN+ AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihH iTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjj vSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA 0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlB OrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/ BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4E FgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01 GX2cGE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmW zaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP4 1BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZE f1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/rGXuhg8F jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN ZetX2fNXlrtIzYE= -----END CERTIFICATE----- # Issuer: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing # Subject: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing # Label: "StartCom Certification Authority" # Serial: 45 # MD5 Fingerprint: c9:3b:0d:84:41:fc:a4:76:79:23:08:57:de:10:19:16 # SHA1 Fingerprint: a3:f1:33:3f:e2:42:bf:cf:c5:d1:4e:8f:39:42:98:40:68:10:d1:a0 # SHA256 Fingerprint: e1:78:90:ee:09:a3:fb:f4:f4:8b:9c:41:4a:17:d6:37:b7:a5:06:47:e9:bc:75:23:22:72:7f:cc:17:42:a9:11 -----BEGIN CERTIFICATE----- MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9 MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w +2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B 26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID AQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFul F2mHMMo0aEPQQa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCC ATgwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w ZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2ludGVybWVk aWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENvbW1lcmNpYWwgKFN0 YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0aGUg c2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0 aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93 d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgG CWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1 dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTF wWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvS Ta0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst 0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNc pRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKl CcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVF P0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK 1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLm KhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ 8dCAWZvLMdibD4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnm fyWl8kgAwKQB2j8= -----END CERTIFICATE----- # Issuer: CN=StartCom Certification Authority G2 O=StartCom Ltd. # Subject: CN=StartCom Certification Authority G2 O=StartCom Ltd. # Label: "StartCom Certification Authority G2" # Serial: 59 # MD5 Fingerprint: 78:4b:fb:9e:64:82:0a:d3:b8:4c:62:f3:64:f2:90:64 # SHA1 Fingerprint: 31:f1:fd:68:22:63:20:ee:c6:3b:3f:9d:ea:4a:3e:53:7c:7c:39:17 # SHA256 Fingerprint: c7:ba:65:67:de:93:a7:98:ae:1f:aa:79:1e:71:2d:37:8f:ae:1f:93:c4:39:7f:ea:44:1b:b7:cb:e6:fd:59:95 -----BEGIN CERTIFICATE----- MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEW MBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlm aWNhdGlvbiBBdXRob3JpdHkgRzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1 OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoG A1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRzIwggIiMA0G CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8Oo1XJ JZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsD vfOpL9HG4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnoo D/Uefyf3lLE3PbfHkffiAez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/ Q0kGi4xDuFby2X8hQxfqp0iVAXV16iulQ5XqFYSdCI0mblWbq9zSOdIxHWDirMxW RST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbsO+wmETRIjfaAKxojAuuK HDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8HvKTlXcxN nw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM 0D4LnMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/i UUjXuG+v+E5+M5iSFGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9 Ha90OrInwMEePnWjFqmveiJdnxMaz6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHg TuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE AwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJKoZIhvcNAQEL BQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K 2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfX UfEpY9Z1zRbkJ4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl 6/2o1PXWT6RbdejF0mCy2wl+JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK 9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG/+gyRr61M3Z3qAFdlsHB1b6uJcDJ HgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTcnIhT76IxW1hPkWLI wpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/XldblhY XzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5l IxKVCCIcl85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoo hdVddLHRDiBYmxOlsGOm7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulr so8uBtjRkcfGEvRM/TAXw8HaOFvjqermobp573PYtlNXLfbQ4ddI -----END CERTIFICATE----- # Issuer: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 # Subject: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 # Label: "Buypass Class 2 Root CA" # Serial: 2 # MD5 Fingerprint: 46:a7:d2:fe:45:fb:64:5a:a8:59:90:9b:78:44:9b:29 # SHA1 Fingerprint: 49:0a:75:74:de:87:0a:47:fe:58:ee:f6:c7:6b:eb:c6:0b:12:40:99 # SHA256 Fingerprint: 9a:11:40:25:19:7c:5b:b9:5d:94:e6:3d:55:cd:43:79:08:47:b6:46:b2:3c:df:11:ad:a4:a0:0e:ff:15:fb:48 -----BEGIN CERTIFICATE----- MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr 6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91 1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN 9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h 9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo +fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7 KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2 DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7 5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h 3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA= -----END CERTIFICATE----- # Issuer: CN=Buypass Class 3 Root CA O=Buypass AS-983163327 # Subject: CN=Buypass Class 3 Root CA O=Buypass AS-983163327 # Label: "Buypass Class 3 Root CA" # Serial: 2 # MD5 Fingerprint: 3d:3b:18:9e:2c:64:5a:e8:d5:88:ce:0e:f9:37:c2:ec # SHA1 Fingerprint: da:fa:f7:fa:66:84:ec:06:8f:14:50:bd:c7:c2:81:a5:bc:a9:64:57 # SHA256 Fingerprint: ed:f7:eb:bc:a2:7a:2a:38:4d:38:7b:7d:40:10:c6:66:e2:ed:b4:84:3e:4c:29:b4:ae:1d:5b:93:32:e6:b2:4d -----BEGIN CERTIFICATE----- MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9 tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX 0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c /3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D 34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3 AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2 HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv 033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41 3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq 4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc= -----END CERTIFICATE----- # Issuer: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center # Subject: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center # Label: "T-TeleSec GlobalRoot Class 3" # Serial: 1 # MD5 Fingerprint: ca:fb:40:a8:4e:39:92:8a:1d:fe:8e:2f:c4:27:ea:ef # SHA1 Fingerprint: 55:a6:72:3e:cb:f2:ec:cd:c3:23:74:70:19:9d:2a:be:11:e3:81:d1 # SHA256 Fingerprint: fd:73:da:d3:1c:64:4f:f1:b4:3b:ef:0c:cd:da:96:71:0b:9c:d9:87:5e:ca:7e:31:70:7a:f3:e9:6d:52:2b:bd -----BEGIN CERTIFICATE----- MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1 OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN 8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/ RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4 hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5 ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1 A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ 1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30 6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT 91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p TpPDpFQUWw== -----END CERTIFICATE----- # Issuer: CN=EE Certification Centre Root CA O=AS Sertifitseerimiskeskus # Subject: CN=EE Certification Centre Root CA O=AS Sertifitseerimiskeskus # Label: "EE Certification Centre Root CA" # Serial: 112324828676200291871926431888494945866 # MD5 Fingerprint: 43:5e:88:d4:7d:1a:4a:7e:fd:84:2e:52:eb:01:d4:6f # SHA1 Fingerprint: c9:a8:b9:e7:55:80:5e:58:e3:53:77:a7:25:eb:af:c3:7b:27:cc:d7 # SHA256 Fingerprint: 3e:84:ba:43:42:90:85:16:e7:75:73:c0:99:2f:09:79:ca:08:4e:46:85:68:1f:f1:95:cc:ba:8a:22:9b:8a:76 -----BEGIN CERTIFICATE----- MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1 MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1 czEoMCYGA1UEAwwfRUUgQ2VydGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYG CSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIwMTAxMDMwMTAxMDMwWhgPMjAzMDEy MTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNl ZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBS b290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEB AQUAA4IBDwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUy euuOF0+W2Ap7kaJjbMeMTC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvO bntl8jixwKIy72KyaOBhU8E2lf/slLo2rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIw WFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw93X2PaRka9ZP585ArQ/d MtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtNP2MbRMNE 1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYD VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/ zQas8fElyalL1BSZMEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYB BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEF BQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQiZrxTFGGV v9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqMlIpPnTX/dqQG E5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIW iAYLtqZLICjU3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/v GVCJYMzpJJUPwssd8m92kMfMdcGWxZ0= -----END CERTIFICATE----- # Issuer: CN=TÜRKTRUST Elektronik Sertifika Hizmet SaÄŸlayıcısı O=TÜRKTRUST Bilgi İletiÅŸim ve BiliÅŸim GüvenliÄŸi Hizmetleri A.Åž. (c) Aralık 2007 # Subject: CN=TÜRKTRUST Elektronik Sertifika Hizmet SaÄŸlayıcısı O=TÜRKTRUST Bilgi İletiÅŸim ve BiliÅŸim GüvenliÄŸi Hizmetleri A.Åž. (c) Aralık 2007 # Label: "TURKTRUST Certificate Services Provider Root 2007" # Serial: 1 # MD5 Fingerprint: 2b:70:20:56:86:82:a0:18:c8:07:53:12:28:70:21:72 # SHA1 Fingerprint: f1:7f:6f:b6:31:dc:99:e3:a3:c8:7f:fe:1c:f1:81:10:88:d9:60:33 # SHA256 Fingerprint: 97:8c:d9:66:f2:fa:a0:7b:a7:aa:95:00:d9:c0:2e:9d:77:f2:cd:ad:a6:ad:6b:a7:4a:f4:b9:1c:66:59:3c:50 -----BEGIN CERTIFICATE----- MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOc UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx c8SxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xS S1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kg SGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4XDTA3MTIyNTE4Mzcx OVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxla3Ry b25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMC VFIxDzANBgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDE sGxldGnFn2ltIHZlIEJpbGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7F ni4gKGMpIEFyYWzEsWsgMjAwNzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9NYvDdE3ePYakqtdTyuTFY KTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQvKUmi8wUG +7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveG HtyaKhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6P IzdezKKqdfcYbwnTrqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M 733WB2+Y8a+xwXrXgTW4qhe04MsCAwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHk Yb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0G CSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/sPx+EnWVUXKgW AkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5 mxRZNTZPz/OOXl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsa XRik7r4EW5nVcV9VZWRi1aKbBFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZ qxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAKpoRq0Tl9 -----END CERTIFICATE----- # Issuer: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH # Subject: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH # Label: "D-TRUST Root Class 3 CA 2 2009" # Serial: 623603 # MD5 Fingerprint: cd:e0:25:69:8d:47:ac:9c:89:35:90:f7:fd:51:3d:2f # SHA1 Fingerprint: 58:e8:ab:b0:36:15:33:fb:80:f7:9b:1b:6d:29:d3:ff:8d:5f:00:f0 # SHA256 Fingerprint: 49:e7:a4:42:ac:f0:ea:62:87:05:00:54:b5:25:64:b6:50:e4:f4:9e:42:e3:48:d6:aa:38:e0:39:e9:57:b1:c1 -----BEGIN CERTIFICATE----- MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03 UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42 tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp /hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8 PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y Johw1+qRzT65ysCQblrGXnRl11z+o+I= -----END CERTIFICATE----- # Issuer: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH # Subject: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH # Label: "D-TRUST Root Class 3 CA 2 EV 2009" # Serial: 623604 # MD5 Fingerprint: aa:c6:43:2c:5e:2d:cd:c4:34:c0:50:4f:11:02:4f:b6 # SHA1 Fingerprint: 96:c9:1b:0b:95:b4:10:98:42:fa:d0:d8:22:79:fe:60:fa:b9:16:83 # SHA256 Fingerprint: ee:c5:49:6b:98:8c:e9:86:25:b9:34:09:2e:ec:29:08:be:d0:b0:f3:16:c2:d4:73:0c:84:ea:f1:f3:d3:48:81 -----BEGIN CERTIFICATE----- MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0 3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8 HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp 3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1 -----END CERTIFICATE----- # Issuer: CN=Autoridad de Certificacion Raiz del Estado Venezolano O=Sistema Nacional de Certificacion Electronica OU=Superintendencia de Servicios de Certificacion Electronica # Subject: CN=PSCProcert O=Sistema Nacional de Certificacion Electronica OU=Proveedor de Certificados PROCERT # Label: "PSCProcert" # Serial: 11 # MD5 Fingerprint: e6:24:e9:12:01:ae:0c:de:8e:85:c4:ce:a3:12:dd:ec # SHA1 Fingerprint: 70:c1:8d:74:b4:28:81:0a:e4:fd:a5:75:d7:01:9f:99:b0:3d:50:74 # SHA256 Fingerprint: 3c:fc:3c:14:d1:f6:84:ff:17:e3:8c:43:ca:44:0c:00:b9:67:ec:93:3e:8b:fe:06:4c:a1:d7:2c:90:f2:ad:b0 -----BEGIN CERTIFICATE----- MIIJhjCCB26gAwIBAgIBCzANBgkqhkiG9w0BAQsFADCCAR4xPjA8BgNVBAMTNUF1 dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIFJhaXogZGVsIEVzdGFkbyBWZW5lem9s YW5vMQswCQYDVQQGEwJWRTEQMA4GA1UEBxMHQ2FyYWNhczEZMBcGA1UECBMQRGlz dHJpdG8gQ2FwaXRhbDE2MDQGA1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0 aWZpY2FjaW9uIEVsZWN0cm9uaWNhMUMwQQYDVQQLEzpTdXBlcmludGVuZGVuY2lh IGRlIFNlcnZpY2lvcyBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMSUwIwYJ KoZIhvcNAQkBFhZhY3JhaXpAc3VzY2VydGUuZ29iLnZlMB4XDTEwMTIyODE2NTEw MFoXDTIwMTIyNTIzNTk1OVowgdExJjAkBgkqhkiG9w0BCQEWF2NvbnRhY3RvQHBy b2NlcnQubmV0LnZlMQ8wDQYDVQQHEwZDaGFjYW8xEDAOBgNVBAgTB01pcmFuZGEx KjAoBgNVBAsTIVByb3ZlZWRvciBkZSBDZXJ0aWZpY2Fkb3MgUFJPQ0VSVDE2MDQG A1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9u aWNhMQswCQYDVQQGEwJWRTETMBEGA1UEAxMKUFNDUHJvY2VydDCCAiIwDQYJKoZI hvcNAQEBBQADggIPADCCAgoCggIBANW39KOUM6FGqVVhSQ2oh3NekS1wwQYalNo9 7BVCwfWMrmoX8Yqt/ICV6oNEolt6Vc5Pp6XVurgfoCfAUFM+jbnADrgV3NZs+J74 BCXfgI8Qhd19L3uA3VcAZCP4bsm+lU/hdezgfl6VzbHvvnpC2Mks0+saGiKLt38G ieU89RLAu9MLmV+QfI4tL3czkkohRqipCKzx9hEC2ZUWno0vluYC3XXCFCpa1sl9 JcLB/KpnheLsvtF8PPqv1W7/U0HU9TI4seJfxPmOEO8GqQKJ/+MMbpfg353bIdD0 PghpbNjU5Db4g7ayNo+c7zo3Fn2/omnXO1ty0K+qP1xmk6wKImG20qCZyFSTXai2 0b1dCl53lKItwIKOvMoDKjSuc/HUtQy9vmebVOvh+qBa7Dh+PsHMosdEMXXqP+UH 0quhJZb25uSgXTcYOWEAM11G1ADEtMo88aKjPvM6/2kwLkDd9p+cJsmWN63nOaK/ 6mnbVSKVUyqUtd+tFjiBdWbjxywbk5yqjKPK2Ww8F22c3HxT4CAnQzb5EuE8XL1m v6JpIzi4mWCZDlZTOpx+FIywBm/xhnaQr/2v/pDGj59/i5IjnOcVdo/Vi5QTcmn7 K2FjiO/mpF7moxdqWEfLcU8UC17IAggmosvpr2uKGcfLFFb14dq12fy/czja+eev bqQ34gcnAgMBAAGjggMXMIIDEzASBgNVHRMBAf8ECDAGAQH/AgEBMDcGA1UdEgQw MC6CD3N1c2NlcnRlLmdvYi52ZaAbBgVghl4CAqASDBBSSUYtRy0yMDAwNDAzNi0w MB0GA1UdDgQWBBRBDxk4qpl/Qguk1yeYVKIXTC1RVDCCAVAGA1UdIwSCAUcwggFD gBStuyIdxuDSAaj9dlBSk+2YwU2u06GCASakggEiMIIBHjE+MDwGA1UEAxM1QXV0 b3JpZGFkIGRlIENlcnRpZmljYWNpb24gUmFpeiBkZWwgRXN0YWRvIFZlbmV6b2xh bm8xCzAJBgNVBAYTAlZFMRAwDgYDVQQHEwdDYXJhY2FzMRkwFwYDVQQIExBEaXN0 cml0byBDYXBpdGFsMTYwNAYDVQQKEy1TaXN0ZW1hIE5hY2lvbmFsIGRlIENlcnRp ZmljYWNpb24gRWxlY3Ryb25pY2ExQzBBBgNVBAsTOlN1cGVyaW50ZW5kZW5jaWEg ZGUgU2VydmljaW9zIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExJTAjBgkq hkiG9w0BCQEWFmFjcmFpekBzdXNjZXJ0ZS5nb2IudmWCAQowDgYDVR0PAQH/BAQD AgEGME0GA1UdEQRGMESCDnByb2NlcnQubmV0LnZloBUGBWCGXgIBoAwMClBTQy0w MDAwMDKgGwYFYIZeAgKgEgwQUklGLUotMzE2MzUzNzMtNzB2BgNVHR8EbzBtMEag RKBChkBodHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52ZS9sY3IvQ0VSVElGSUNBRE8t UkFJWi1TSEEzODRDUkxERVIuY3JsMCOgIaAfhh1sZGFwOi8vYWNyYWl6LnN1c2Nl cnRlLmdvYi52ZTA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9v Y3NwLnN1c2NlcnRlLmdvYi52ZTBBBgNVHSAEOjA4MDYGBmCGXgMBAjAsMCoGCCsG AQUFBwIBFh5odHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52ZS9kcGMwDQYJKoZIhvcN AQELBQADggIBACtZ6yKZu4SqT96QxtGGcSOeSwORR3C7wJJg7ODU523G0+1ng3dS 1fLld6c2suNUvtm7CpsR72H0xpkzmfWvADmNg7+mvTV+LFwxNG9s2/NkAZiqlCxB 3RWGymspThbASfzXg0gTB1GEMVKIu4YXx2sviiCtxQuPcD4quxtxj7mkoP3Yldmv Wb8lK5jpY5MvYB7Eqvh39YtsL+1+LrVPQA3uvFd359m21D+VJzog1eWuq2w1n8Gh HVnchIHuTQfiSLaeS5UtQbHh6N5+LwUeaO6/u5BlOsju6rEYNxxik6SgMexxbJHm pHmJWhSnFFAFTKQAVzAswbVhltw+HoSvOULP5dAssSS830DD7X9jSr3hTxJkhpXz sOfIt+FTvZLm8wyWuevo5pLtp4EJFAv8lXrPj9Y0TzYS3F7RNHXGRoAvlQSMx4bE qCaJqD8Zm4G7UaRKhqsLEQ+xrmNTbSjq3TNWOByyrYDT13K9mmyZY+gAu0F2Bbdb mRiKw7gSXFbPVgx96OLP7bx0R/vu0xdOIk9W/1DzLuY5poLWccret9W6aAjtmcz9 opLLabid+Qqkpj5PkygqYWwHJgD/ll9ohri4zspV4KuxPX+Y1zMOWj3YeMLEYC/H YvBhkdI4sPaeVdtAgAUSM84dkpvRabP/v/GSCmE1P93+hvS84Bpxs2Km -----END CERTIFICATE----- # Issuer: CN=China Internet Network Information Center EV Certificates Root O=China Internet Network Information Center # Subject: CN=China Internet Network Information Center EV Certificates Root O=China Internet Network Information Center # Label: "China Internet Network Information Center EV Certificates Root" # Serial: 1218379777 # MD5 Fingerprint: 55:5d:63:00:97:bd:6a:97:f5:67:ab:4b:fb:6e:63:15 # SHA1 Fingerprint: 4f:99:aa:93:fb:2b:d1:37:26:a1:99:4a:ce:7f:f0:05:f2:93:5d:1e # SHA256 Fingerprint: 1c:01:c6:f4:db:b2:fe:fc:22:55:8b:2b:ca:32:56:3f:49:84:4a:cf:c3:2b:7b:e4:b0:ff:59:9f:9e:8c:7a:f7 -----BEGIN CERTIFICATE----- MIID9zCCAt+gAwIBAgIESJ8AATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMC Q04xMjAwBgNVBAoMKUNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24g Q2VudGVyMUcwRQYDVQQDDD5DaGluYSBJbnRlcm5ldCBOZXR3b3JrIEluZm9ybWF0 aW9uIENlbnRlciBFViBDZXJ0aWZpY2F0ZXMgUm9vdDAeFw0xMDA4MzEwNzExMjVa Fw0zMDA4MzEwNzExMjVaMIGKMQswCQYDVQQGEwJDTjEyMDAGA1UECgwpQ2hpbmEg SW50ZXJuZXQgTmV0d29yayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMMPkNo aW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRp ZmljYXRlcyBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm35z 7r07eKpkQ0H1UN+U8i6yjUqORlTSIRLIOTJCBumD1Z9S7eVnAztUwYyZmczpwA// DdmEEbK40ctb3B75aDFk4Zv6dOtouSCV98YPjUesWgbdYavi7NifFy2cyjw1l1Vx zUOFsUcW9SxTgHbP0wBkvUCZ3czY28Sf1hNfQYOL+Q2HklY0bBoQCxfVWhyXWIQ8 hBouXJE0bhlffxdpxWXvayHG1VA6v2G5BY3vbzQ6sm8UY78WO5upKv23KzhmBsUs 4qpnHkWnjQRmQvaPK++IIGmPMowUc9orhpFjIpryp9vOiYurXccUwVswah+xt54u gQEC7c+WXmPbqOY4twIDAQABo2MwYTAfBgNVHSMEGDAWgBR8cks5x8DbYqVPm6oY NJKiyoOCWTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E FgQUfHJLOcfA22KlT5uqGDSSosqDglkwDQYJKoZIhvcNAQEFBQADggEBACrDx0M3 j92tpLIM7twUbY8opJhJywyA6vPtI2Z1fcXTIWd50XPFtQO3WKwMVC/GVhMPMdoG 52U7HW8228gd+f2ABsqjPWYWqJ1MFn3AlUa1UeTiH9fqBk1jjZaM7+czV0I664zB echNdn3e9rG3geCg+aF4RhcaVpjwTj2rHO3sOdwHSPdj/gauwqRcalsyiMXHM4Ws ZkJHwlgkmeHlPuV1LI5D1l08eB6olYIpUNHRFrrvwb562bTYzB5MRuF3sTGrvSrI zo9uoV1/A3U05K2JRVRevq4opbs/eHnrc7MKDf2+yfdWrPa37S+bISnHOLaVxATy wy39FCqQmbkHzJ8= -----END CERTIFICATE----- # Issuer: CN=Swisscom Root CA 2 O=Swisscom OU=Digital Certificate Services # Subject: CN=Swisscom Root CA 2 O=Swisscom OU=Digital Certificate Services # Label: "Swisscom Root CA 2" # Serial: 40698052477090394928831521023204026294 # MD5 Fingerprint: 5b:04:69:ec:a5:83:94:63:18:a7:86:d0:e4:f2:6e:19 # SHA1 Fingerprint: 77:47:4f:c6:30:e4:0f:4c:47:64:3f:84:ba:b8:c6:95:4a:8a:41:ec # SHA256 Fingerprint: f0:9b:12:2c:71:14:f4:a0:9b:d4:ea:4f:4a:99:d5:58:b4:6e:4c:25:cd:81:14:0d:29:c0:56:13:91:4c:38:41 -----BEGIN CERTIFICATE----- MIIF2TCCA8GgAwIBAgIQHp4o6Ejy5e/DfEoeWhhntjANBgkqhkiG9w0BAQsFADBk MQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0 YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3Qg Q0EgMjAeFw0xMTA2MjQwODM4MTRaFw0zMTA2MjUwNzM4MTRaMGQxCzAJBgNVBAYT AmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZp Y2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAyMIICIjAN BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlUJOhJ1R5tMJ6HJaI2nbeHCOFvEr jw0DzpPMLgAIe6szjPTpQOYXTKueuEcUMncy3SgM3hhLX3af+Dk7/E6J2HzFZ++r 0rk0X2s682Q2zsKwzxNoysjL67XiPS4h3+os1OD5cJZM/2pYmLcX5BtS5X4HAB1f 2uY+lQS3aYg5oUFgJWFLlTloYhyxCwWJwDaCFCE/rtuh/bxvHGCGtlOUSbkrRsVP ACu/obvLP+DHVxxX6NZp+MEkUp2IVd3Chy50I9AU/SpHWrumnf2U5NGKpV+GY3aF y6//SSj8gO1MedK75MDvAe5QQQg1I3ArqRa0jG6F6bYRzzHdUyYb3y1aSgJA/MTA tukxGggo5WDDH8SQjhBiYEQN7Aq+VRhxLKX0srwVYv8c474d2h5Xszx+zYIdkeNL 6yxSNLCK/RJOlrDrcH+eOfdmQrGrrFLadkBXeyq96G4DsguAhYidDMfCd7Camlf0 uPoTXGiTOmekl9AbmbeGMktg2M7v0Ax/lZ9vh0+Hio5fCHyqW/xavqGRn1V9TrAL acywlKinh/LTSlDcX3KwFnUey7QYYpqwpzmqm59m2I2mbJYV4+by+PGDYmy7Velh k6M99bFXi08jsJvllGov34zflVEpYKELKeRcVVi3qPyZ7iVNTA6z00yPhOgpD/0Q VAKFyPnlw4vP5w8CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0hBBYw FDASBgdghXQBUwIBBgdghXQBUwIBMBIGA1UdEwEB/wQIMAYBAf8CAQcwHQYDVR0O BBYEFE0mICKJS9PVpAqhb97iEoHF8TwuMB8GA1UdIwQYMBaAFE0mICKJS9PVpAqh b97iEoHF8TwuMA0GCSqGSIb3DQEBCwUAA4ICAQAyCrKkG8t9voJXiblqf/P0wS4R fbgZPnm3qKhyN2abGu2sEzsOv2LwnN+ee6FTSA5BesogpxcbtnjsQJHzQq0Qw1zv /2BZf82Fo4s9SBwlAjxnffUy6S8w5X2lejjQ82YqZh6NM4OKb3xuqFp1mrjX2lhI REeoTPpMSQpKwhI3qEAMw8jh0FcNlzKVxzqfl9NX+Ave5XLzo9v/tdhZsnPdTSpx srpJ9csc1fV5yJmz/MFMdOO0vSk3FQQoHt5FRnDsr7p4DooqzgB53MBfGWcsa0vv aGgLQ+OswWIJ76bdZWGgr4RVSJFSHMYlkSrQwSIjYVmvRRGFHQEkNI/Ps/8XciAT woCqISxxOQ7Qj1zB09GOInJGTB2Wrk9xseEFKZZZ9LuedT3PDTcNYtsmjGOpI99n Bjx8Oto0QuFmtEYE3saWmA9LSHokMnWRn6z3aOkquVVlzl1h0ydw2Df+n7mvoC5W t6NlUe07qxS/TFED6F+KBZvuim6c779o+sjaC+NCydAXFJy3SuCvkychVSa1ZC+N 8f+mQAWFBVzKBxlcCxMoTFh/wqXvRdpg065lYZ1Tg3TCrvJcwhbtkj6EPnNgiLx2 9CzP0H1907he0ZESEOnN3col49XtmS++dYFLJPlFRpTJKSFTnCZFqhMX5OfNeOI5 wSsSnqaeG8XmDtkx2Q== -----END CERTIFICATE----- # Issuer: CN=Swisscom Root EV CA 2 O=Swisscom OU=Digital Certificate Services # Subject: CN=Swisscom Root EV CA 2 O=Swisscom OU=Digital Certificate Services # Label: "Swisscom Root EV CA 2" # Serial: 322973295377129385374608406479535262296 # MD5 Fingerprint: 7b:30:34:9f:dd:0a:4b:6b:35:ca:31:51:28:5d:ae:ec # SHA1 Fingerprint: e7:a1:90:29:d3:d5:52:dc:0d:0f:c6:92:d3:ea:88:0d:15:2e:1a:6b # SHA256 Fingerprint: d9:5f:ea:3c:a4:ee:dc:e7:4c:d7:6e:75:fc:6d:1f:f6:2c:44:1f:0f:a8:bc:77:f0:34:b1:9e:5d:b2:58:01:5d -----BEGIN CERTIFICATE----- MIIF4DCCA8igAwIBAgIRAPL6ZOJ0Y9ON/RAdBB92ylgwDQYJKoZIhvcNAQELBQAw ZzELMAkGA1UEBhMCY2gxETAPBgNVBAoTCFN3aXNzY29tMSUwIwYDVQQLExxEaWdp dGFsIENlcnRpZmljYXRlIFNlcnZpY2VzMR4wHAYDVQQDExVTd2lzc2NvbSBSb290 IEVWIENBIDIwHhcNMTEwNjI0MDk0NTA4WhcNMzEwNjI1MDg0NTA4WjBnMQswCQYD VQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2Vy dGlmaWNhdGUgU2VydmljZXMxHjAcBgNVBAMTFVN3aXNzY29tIFJvb3QgRVYgQ0Eg MjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMT3HS9X6lds93BdY7Bx UglgRCgzo3pOCvrY6myLURYaVa5UJsTMRQdBTxB5f3HSek4/OE6zAMaVylvNwSqD 1ycfMQ4jFrclyxy0uYAyXhqdk/HoPGAsp15XGVhRXrwsVgu42O+LgrQ8uMIkqBPH oCE2G3pXKSinLr9xJZDzRINpUKTk4RtiGZQJo/PDvO/0vezbE53PnUgJUmfANykR HvvSEaeFGHR55E+FFOtSN+KxRdjMDUN/rhPSays/p8LiqG12W0OfvrSdsyaGOx9/ 5fLoZigWJdBLlzin5M8J0TbDC77aO0RYjb7xnglrPvMyxyuHxuxenPaHZa0zKcQv idm5y8kDnftslFGXEBuGCxobP/YCfnvUxVFkKJ3106yDgYjTdLRZncHrYTNaRdHL OdAGalNgHa/2+2m8atwBz735j9m9W8E6X47aD0upm50qKGsaCnw8qyIL5XctcfaC NYGu+HuB5ur+rPQam3Rc6I8k9l2dRsQs0h4rIWqDJ2dVSqTjyDKXZpBy2uPUZC5f 46Fq9mDU5zXNysRojddxyNMkM3OxbPlq4SjbX8Y96L5V5jcb7STZDxmPX2MYWFCB UWVv8p9+agTnNCRxunZLWB4ZvRVgRaoMEkABnRDixzgHcgplwLa7JSnaFp6LNYth 7eVxV4O1PHGf40+/fh6Bn0GXAgMBAAGjgYYwgYMwDgYDVR0PAQH/BAQDAgGGMB0G A1UdIQQWMBQwEgYHYIV0AVMCAgYHYIV0AVMCAjASBgNVHRMBAf8ECDAGAQH/AgED MB0GA1UdDgQWBBRF2aWBbj2ITY1x0kbBbkUe88SAnTAfBgNVHSMEGDAWgBRF2aWB bj2ITY1x0kbBbkUe88SAnTANBgkqhkiG9w0BAQsFAAOCAgEAlDpzBp9SSzBc1P6x XCX5145v9Ydkn+0UjrgEjihLj6p7jjm02Vj2e6E1CqGdivdj5eu9OYLU43otb98T PLr+flaYC/NUn81ETm484T4VvwYmneTwkLbUwp4wLh/vx3rEUMfqe9pQy3omywC0 Wqu1kx+AiYQElY2NfwmTv9SoqORjbdlk5LgpWgi/UOGED1V7XwgiG/W9mR4U9s70 WBCCswo9GcG/W6uqmdjyMb3lOGbcWAXH7WMaLgqXfIeTK7KK4/HsGOV1timH59yL Gn602MnTihdsfSlEvoqq9X46Lmgxk7lq2prg2+kupYTNHAq4Sgj5nPFhJpiTt3tm 7JFe3VE/23MPrQRYCd0EApUKPtN236YQHoA96M2kZNEzx5LH4k5E4wnJTsJdhw4S nr8PyQUQ3nqjsTzyP6WqJ3mtMX0f/fwZacXduT98zca0wjAefm6S139hdlqP65VN vBFuIXxZN5nQBrz5Bm0yFqXZaajh3DyAHmBR3NdUIR7KYndP+tiPsys6DXhyyWhB WkdKwqPrGtcKqzwyVcgKEZzfdNbwQBUdyLmPtTbFr/giuMod89a2GQ+fYWVq6nTI fI/DT11lgh/ZDYnadXL77/FHZxOzyNEZiCcmmpl5fx7kLD977vHeTYuWl8PVP3wb I+2ksx0WckNLIOFZfsLorSa/ovc= -----END CERTIFICATE----- # Issuer: CN=CA Disig Root R1 O=Disig a.s. # Subject: CN=CA Disig Root R1 O=Disig a.s. # Label: "CA Disig Root R1" # Serial: 14052245610670616104 # MD5 Fingerprint: be:ec:11:93:9a:f5:69:21:bc:d7:c1:c0:67:89:cc:2a # SHA1 Fingerprint: 8e:1c:74:f8:a6:20:b9:e5:8a:f4:61:fa:ec:2b:47:56:51:1a:52:c6 # SHA256 Fingerprint: f9:6f:23:f4:c3:e7:9c:07:7a:46:98:8d:5a:f5:90:06:76:a0:f0:39:cb:64:5d:d1:75:49:b2:16:c8:24:40:ce -----BEGIN CERTIFICATE----- MIIFaTCCA1GgAwIBAgIJAMMDmu5QkG4oMA0GCSqGSIb3DQEBBQUAMFIxCzAJBgNV BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIxMB4XDTEyMDcxOTA5MDY1NloXDTQy MDcxOTA5MDY1NlowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjEw ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqw3j33Jijp1pedxiy3QRk D2P9m5YJgNXoqqXinCaUOuiZc4yd39ffg/N4T0Dhf9Kn0uXKE5Pn7cZ3Xza1lK/o OI7bm+V8u8yN63Vz4STN5qctGS7Y1oprFOsIYgrY3LMATcMjfF9DCCMyEtztDK3A fQ+lekLZWnDZv6fXARz2m6uOt0qGeKAeVjGu74IKgEH3G8muqzIm1Cxr7X1r5OJe IgpFy4QxTaz+29FHuvlglzmxZcfe+5nkCiKxLU3lSCZpq+Kq8/v8kiky6bM+TR8n oc2OuRf7JT7JbvN32g0S9l3HuzYQ1VTW8+DiR0jm3hTaYVKvJrT1cU/J19IG32PK /yHoWQbgCNWEFVP3Q+V8xaCJmGtzxmjOZd69fwX3se72V6FglcXM6pM6vpmumwKj rckWtc7dXpl4fho5frLABaTAgqWjR56M6ly2vGfb5ipN0gTco65F97yLnByn1tUD 3AjLLhbKXEAz6GfDLuemROoRRRw1ZS0eRWEkG4IupZ0zXWX4Qfkuy5Q/H6MMMSRE 7cderVC6xkGbrPAXZcD4XW9boAo0PO7X6oifmPmvTiT6l7Jkdtqr9O3jw2Dv1fkC yC2fg69naQanMVXVz0tv/wQFx1isXxYb5dKj6zHbHzMVTdDypVP1y+E9Tmgt2BLd qvLmTZtJ5cUoobqwWsagtQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud DwEB/wQEAwIBBjAdBgNVHQ4EFgQUiQq0OJMa5qvum5EY+fU8PjXQ04IwDQYJKoZI hvcNAQEFBQADggIBADKL9p1Kyb4U5YysOMo6CdQbzoaz3evUuii+Eq5FLAR0rBNR xVgYZk2C2tXck8An4b58n1KeElb21Zyp9HWc+jcSjxyT7Ff+Bw+r1RL3D65hXlaA SfX8MPWbTx9BLxyE04nH4toCdu0Jz2zBuByDHBb6lM19oMgY0sidbvW9adRtPTXo HqJPYNcHKfyyo6SdbhWSVhlMCrDpfNIZTUJG7L399ldb3Zh+pE3McgODWF3vkzpB emOqfDqo9ayk0d2iLbYq/J8BjuIQscTK5GfbVSUZP/3oNn6z4eGBrxEWi1CXYBmC AMBrTXO40RMHPuq2MU/wQppt4hF05ZSsjYSVPCGvxdpHyN85YmLLW1AL14FABZyb 7bq2ix4Eb5YgOe2kfSnbSM6C3NQCjR0EMVrHS/BsYVLXtFHCgWzN4funodKSds+x DzdYpPJScWc/DIh4gInByLUfkmO+p3qKViwaqKactV2zY9ATIKHrkWzQjX2v3wvk F7mGnjixlAxYjOBVqjtjbZqJYLhkKpLGN/R+Q0O3c+gB53+XD9fyexn9GtePyfqF a3qdnom2piiZk4hA9z7NUaPK6u95RyG1/jLix8NRb76AdPCkwzryT+lf3xkK8jsT Q6wxpLPn6/wY1gGp8yqPNg7rtLG8t0zJa7+h89n07eLw4+1knj0vllJPgFOL -----END CERTIFICATE----- # Issuer: CN=CA Disig Root R2 O=Disig a.s. # Subject: CN=CA Disig Root R2 O=Disig a.s. # Label: "CA Disig Root R2" # Serial: 10572350602393338211 # MD5 Fingerprint: 26:01:fb:d8:27:a7:17:9a:45:54:38:1a:43:01:3b:03 # SHA1 Fingerprint: b5:61:eb:ea:a4:de:e4:25:4b:69:1a:98:a5:57:47:c2:34:c7:d9:71 # SHA256 Fingerprint: e2:3d:4a:03:6d:7b:70:e9:f5:95:b1:42:20:79:d2:b9:1e:df:bb:1f:b6:51:a0:63:3e:aa:8a:9d:c5:f8:07:03 -----BEGIN CERTIFICATE----- MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912 H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1 rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka +elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3 gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL -----END CERTIFICATE----- # Issuer: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV # Subject: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV # Label: "ACCVRAIZ1" # Serial: 6828503384748696800 # MD5 Fingerprint: d0:a0:5a:ee:05:b6:09:94:21:a1:7d:f1:b2:29:82:02 # SHA1 Fingerprint: 93:05:7a:88:15:c6:4f:ce:88:2f:fa:91:16:52:28:78:bc:53:64:17 # SHA256 Fingerprint: 9a:6e:c0:12:e1:a7:da:9d:be:34:19:4d:47:8a:d7:c0:db:18:22:fb:07:1d:f1:29:81:49:6e:d1:04:38:41:13 -----BEGIN CERTIFICATE----- MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/ 0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47 4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA 7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH 7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7 -----END CERTIFICATE----- # Issuer: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA # Subject: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA # Label: "TWCA Global Root CA" # Serial: 3262 # MD5 Fingerprint: f9:03:7e:cf:e6:9e:3c:73:7a:2a:90:07:69:ff:2b:96 # SHA1 Fingerprint: 9c:bb:48:53:f6:a4:f6:d3:52:a4:e8:32:52:55:60:13:f5:ad:af:65 # SHA256 Fingerprint: 59:76:90:07:f7:68:5d:0f:cd:50:87:2f:9f:95:d5:75:5a:5b:2b:45:7d:81:f3:69:2b:61:0a:98:67:2f:0e:1b -----BEGIN CERTIFICATE----- MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5 NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF 10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz 0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc 46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2 yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm 4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB /zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL 1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+ nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh 15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW 6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy KwbQBM0= -----END CERTIFICATE----- # Issuer: CN=TeliaSonera Root CA v1 O=TeliaSonera # Subject: CN=TeliaSonera Root CA v1 O=TeliaSonera # Label: "TeliaSonera Root CA v1" # Serial: 199041966741090107964904287217786801558 # MD5 Fingerprint: 37:41:49:1b:18:56:9a:26:f5:ad:c2:66:fb:40:a5:4c # SHA1 Fingerprint: 43:13:bb:96:f1:d5:86:9b:c1:4e:6a:92:f6:cf:f6:34:69:87:82:37 # SHA256 Fingerprint: dd:69:36:fe:21:f8:f0:77:c1:23:a1:a5:21:c1:22:24:f7:22:55:b7:3e:03:a7:26:06:93:e8:a2:4b:0f:a3:89 -----BEGIN CERTIFICATE----- MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2 MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1 7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+ /jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs 81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4 pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG 9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx 0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7 Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7 vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= -----END CERTIFICATE----- # Issuer: CN=E-Tugra Certification Authority O=E-TuÄŸra EBG BiliÅŸim Teknolojileri ve Hizmetleri A.Åž. OU=E-Tugra Sertifikasyon Merkezi # Subject: CN=E-Tugra Certification Authority O=E-TuÄŸra EBG BiliÅŸim Teknolojileri ve Hizmetleri A.Åž. OU=E-Tugra Sertifikasyon Merkezi # Label: "E-Tugra Certification Authority" # Serial: 7667447206703254355 # MD5 Fingerprint: b8:a1:03:63:b0:bd:21:71:70:8a:6f:13:3a:bb:79:49 # SHA1 Fingerprint: 51:c6:e7:08:49:06:6e:f3:92:d4:5c:a0:0d:6d:a3:62:8f:c3:52:39 # SHA256 Fingerprint: b0:bf:d5:2b:b0:d7:d9:bd:92:bf:5d:4d:c1:3d:a2:55:c0:2c:54:2f:37:83:65:ea:89:39:11:f5:5e:55:f2:3c -----BEGIN CERTIFICATE----- MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNV BAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBC aWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNV BAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQDDB9FLVR1 Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMwNTEyMDk0OFoXDTIz MDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+ BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhp em1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4vU/kwVRHoViVF56C/UY B4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vdhQd2h8y/L5VMzH2nPbxH D5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5KCKpbknSF Q9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEo q1+gElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3D k14opz8n8Y4e0ypQBaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcH fC425lAcP9tDJMW/hkd5s3kc91r0E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsut dEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gzrt48Ue7LE3wBf4QOXVGUnhMM ti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAqjqFGOjGY5RH8 zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUX U8u3Zg5mTPj5dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6 Jyr+zE7S6E5UMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5 XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAF Nzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAKkEh47U6YA5n+KGCR HTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jOXKqY GwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c 77NCR807VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3 +GbHeJAAFS6LrVE1Uweoa2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WK vJUawSg5TB9D0pH0clmKuVb8P7Sd2nCcdlqMQ1DujjByTd//SffGqWfZbawCEeI6 FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEVKV0jq9BgoRJP3vQXzTLl yb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gTDx4JnW2P AJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpD y4Q08ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8d NL/+I5c30jn6PQ0GC7TbO6Orb1wdtn7os4I07QZcJA== -----END CERTIFICATE----- # Issuer: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center # Subject: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center # Label: "T-TeleSec GlobalRoot Class 2" # Serial: 1 # MD5 Fingerprint: 2b:9b:9e:e4:7b:6c:1f:00:72:1a:cc:c1:77:79:df:6a # SHA1 Fingerprint: 59:0d:2d:7d:88:4f:40:2e:61:7e:a5:62:32:17:65:cf:17:d8:94:e9 # SHA256 Fingerprint: 91:e2:f5:78:8d:58:10:eb:a7:ba:58:73:7d:e1:54:8a:8e:ca:cd:01:45:98:bc:0b:14:3e:04:1b:17:05:25:52 -----BEGIN CERTIFICATE----- MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1 OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi 1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/ WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6 g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN 9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP BSeOE6Fuwg== -----END CERTIFICATE----- # Issuer: CN=Atos TrustedRoot 2011 O=Atos # Subject: CN=Atos TrustedRoot 2011 O=Atos # Label: "Atos TrustedRoot 2011" # Serial: 6643877497813316402 # MD5 Fingerprint: ae:b9:c4:32:4b:ac:7f:5d:66:cc:77:94:bb:2a:77:56 # SHA1 Fingerprint: 2b:b1:f5:3e:55:0c:1d:c5:f1:d4:e6:b7:6a:46:4b:55:06:02:ac:21 # SHA256 Fingerprint: f3:56:be:a2:44:b7:a9:1e:b3:5d:53:ca:9a:d7:86:4a:ce:01:8e:2d:35:d5:f8:f9:6d:df:68:a6:f4:1a:a4:74 -----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ 4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed -----END CERTIFICATE----- # Issuer: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited # Subject: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited # Label: "QuoVadis Root CA 1 G3" # Serial: 687049649626669250736271037606554624078720034195 # MD5 Fingerprint: a4:bc:5b:3f:fe:37:9a:fa:64:f0:e2:fa:05:3d:0b:ab # SHA1 Fingerprint: 1b:8e:ea:57:96:29:1a:c9:39:ea:b8:0a:81:1a:73:73:c0:93:79:67 # SHA256 Fingerprint: 8a:86:6f:d1:b2:76:b5:7e:57:8e:92:1c:65:82:8a:2b:ed:58:e9:f2:f2:88:05:41:34:b7:f1:f4:bf:c9:cc:74 -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00 MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341 68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh 4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc 3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2 cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5 YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2 8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD -----END CERTIFICATE----- # Issuer: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited # Subject: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited # Label: "QuoVadis Root CA 2 G3" # Serial: 390156079458959257446133169266079962026824725800 # MD5 Fingerprint: af:0c:86:6e:bf:40:2d:7f:0b:3e:12:50:ba:12:3d:06 # SHA1 Fingerprint: 09:3c:61:f3:8b:8b:dc:7d:55:df:75:38:02:05:00:e1:25:f5:c8:36 # SHA256 Fingerprint: 8f:e4:fb:0a:f9:3a:4d:0d:67:db:0b:eb:b2:3e:37:c7:1b:f3:25:dc:bc:dd:24:0e:a0:4d:af:58:b4:7e:18:40 -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00 MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+ O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1 o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz 8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l 7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE +V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4 WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M -----END CERTIFICATE----- # Issuer: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited # Subject: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited # Label: "QuoVadis Root CA 3 G3" # Serial: 268090761170461462463995952157327242137089239581 # MD5 Fingerprint: df:7d:b9:ad:54:6f:68:a1:df:89:57:03:97:43:b0:d7 # SHA1 Fingerprint: 48:12:bd:92:3c:a8:c4:39:06:e7:30:6d:27:96:e6:a4:cf:22:2e:7d # SHA256 Fingerprint: 88:ef:81:de:20:2e:b0:18:45:2e:43:f8:64:72:5c:ea:5f:bd:1f:c2:d9:d2:05:73:07:09:c5:d8:b8:69:0f:46 -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00 MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR /xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP 0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf 3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl 8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+ DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0 -----END CERTIFICATE----- # Issuer: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com # Subject: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com # Label: "DigiCert Assured ID Root G2" # Serial: 15385348160840213938643033620894905419 # MD5 Fingerprint: 92:38:b9:f8:63:24:82:65:2c:57:33:e6:fe:81:8f:9d # SHA1 Fingerprint: a1:4b:48:d9:43:ee:0a:0e:40:90:4f:3c:e0:a4:c0:91:93:51:5d:3f # SHA256 Fingerprint: 7d:05:eb:b6:82:33:9f:8c:94:51:ee:09:4e:eb:fe:fa:79:53:a1:14:ed:b2:f4:49:49:45:2f:ab:7d:2f:c1:85 -----BEGIN CERTIFICATE----- MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I 0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9 B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo IhNzbM8m9Yop5w== -----END CERTIFICATE----- # Issuer: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com # Subject: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com # Label: "DigiCert Assured ID Root G3" # Serial: 15459312981008553731928384953135426796 # MD5 Fingerprint: 7c:7f:65:31:0c:81:df:8d:ba:3e:99:e2:5c:ad:6e:fb # SHA1 Fingerprint: f5:17:a2:4f:9a:48:c6:c9:f8:a2:00:26:9f:dc:0f:48:2c:ab:30:89 # SHA256 Fingerprint: 7e:37:cb:8b:4c:47:09:0c:ab:36:55:1b:a6:f4:5d:b8:40:68:0f:ba:16:6a:95:2d:b1:00:71:7f:43:05:3f:c2 -----BEGIN CERTIFICATE----- MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv 6pZjamVFkpUBtA== -----END CERTIFICATE----- # Issuer: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com # Subject: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com # Label: "DigiCert Global Root G2" # Serial: 4293743540046975378534879503202253541 # MD5 Fingerprint: e4:a6:8a:c8:54:ac:52:42:46:0a:fd:72:48:1b:2a:44 # SHA1 Fingerprint: df:3c:24:f9:bf:d6:66:76:1b:26:80:73:fe:06:d1:cc:8d:4f:82:a4 # SHA256 Fingerprint: cb:3c:cb:b7:60:31:e5:e0:13:8f:8d:d3:9a:23:f9:de:47:ff:c3:5e:43:c1:14:4c:ea:27:d4:6a:5a:b1:cb:5f -----BEGIN CERTIFICATE----- MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG 9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI 2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx 1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV 5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY 1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4 NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl MrY= -----END CERTIFICATE----- # Issuer: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com # Subject: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com # Label: "DigiCert Global Root G3" # Serial: 7089244469030293291760083333884364146 # MD5 Fingerprint: f5:5d:a4:50:a5:fb:28:7e:1e:0f:0d:cc:96:57:56:ca # SHA1 Fingerprint: 7e:04:de:89:6a:3e:66:6d:00:e6:87:d3:3f:fa:d9:3b:e8:3d:34:9e # SHA256 Fingerprint: 31:ad:66:48:f8:10:41:38:c7:38:f3:9e:a4:32:01:33:39:3e:3a:18:cc:02:29:6e:f9:7c:2a:c9:ef:67:31:d0 -----BEGIN CERTIFICATE----- MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/ oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8 sycX -----END CERTIFICATE----- # Issuer: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com # Subject: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com # Label: "DigiCert Trusted Root G4" # Serial: 7451500558977370777930084869016614236 # MD5 Fingerprint: 78:f2:fc:aa:60:1f:2f:b4:eb:c9:37:ba:53:2e:75:49 # SHA1 Fingerprint: dd:fb:16:cd:49:31:c9:73:a2:03:7d:3f:c8:3a:4d:7d:77:5d:05:e4 # SHA256 Fingerprint: 55:2f:7b:dc:f1:a7:af:9e:6c:e6:72:01:7f:4f:12:ab:f7:72:40:c7:8e:76:1a:c2:03:d1:d9:d2:0a:c8:99:88 -----BEGIN CERTIFICATE----- MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/ CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t 9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2 SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd +SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N 0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie 4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1 /YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+ -----END CERTIFICATE----- # Issuer: CN=Certification Authority of WoSign O=WoSign CA Limited # Subject: CN=Certification Authority of WoSign O=WoSign CA Limited # Label: "WoSign" # Serial: 125491772294754854453622855443212256657 # MD5 Fingerprint: a1:f2:f9:b5:d2:c8:7a:74:b8:f3:05:f1:d7:e1:84:8d # SHA1 Fingerprint: b9:42:94:bf:91:ea:8f:b6:4b:e6:10:97:c7:fb:00:13:59:b6:76:cb # SHA256 Fingerprint: 4b:22:d5:a6:ae:c9:9f:3c:db:79:aa:5e:c0:68:38:47:9c:d5:ec:ba:71:64:f7:f2:2d:c1:d6:5f:63:d8:57:08 -----BEGIN CERTIFICATE----- MIIFdjCCA16gAwIBAgIQXmjWEXGUY1BWAGjzPsnFkTANBgkqhkiG9w0BAQUFADBV MQswCQYDVQQGEwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxKjAoBgNV BAMTIUNlcnRpZmljYXRpb24gQXV0aG9yaXR5IG9mIFdvU2lnbjAeFw0wOTA4MDgw MTAwMDFaFw0zOTA4MDgwMTAwMDFaMFUxCzAJBgNVBAYTAkNOMRowGAYDVQQKExFX b1NpZ24gQ0EgTGltaXRlZDEqMCgGA1UEAxMhQ2VydGlmaWNhdGlvbiBBdXRob3Jp dHkgb2YgV29TaWduMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvcqN rLiRFVaXe2tcesLea9mhsMMQI/qnobLMMfo+2aYpbxY94Gv4uEBf2zmoAHqLoE1U fcIiePyOCbiohdfMlZdLdNiefvAA5A6JrkkoRBoQmTIPJYhTpA2zDxIIFgsDcScc f+Hb0v1naMQFXQoOXXDX2JegvFNBmpGN9J42Znp+VsGQX+axaCA2pIwkLCxHC1l2 ZjC1vt7tj/id07sBMOby8w7gLJKA84X5KIq0VC6a7fd2/BVoFutKbOsuEo/Uz/4M x1wdC34FMr5esAkqQtXJTpCzWQ27en7N1QhatH/YHGkR+ScPewavVIMYe+HdVHpR aG53/Ma/UkpmRqGyZxq7o093oL5d//xWC0Nyd5DKnvnyOfUNqfTq1+ezEC8wQjch zDBwyYaYD8xYTYO7feUapTeNtqwylwA6Y3EkHp43xP901DfA4v6IRmAR3Qg/UDar uHqklWJqbrDKaiFaafPz+x1wOZXzp26mgYmhiMU7ccqjUu6Du/2gd/Tkb+dC221K mYo0SLwX3OSACCK28jHAPwQ+658geda4BmRkAjHXqc1S+4RFaQkAKtxVi8QGRkvA Sh0JWzko/amrzgD5LkhLJuYwTKVYyrREgk/nkR4zw7CT/xH8gdLKH3Ep3XZPkiWv HYG3Dy+MwwbMLyejSuQOmbp8HkUff6oZRZb9/D0CAwEAAaNCMEAwDgYDVR0PAQH/ BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFOFmzw7R8bNLtwYgFP6H EtX2/vs+MA0GCSqGSIb3DQEBBQUAA4ICAQCoy3JAsnbBfnv8rWTjMnvMPLZdRtP1 LOJwXcgu2AZ9mNELIaCJWSQBnfmvCX0KI4I01fx8cpm5o9dU9OpScA7F9dY74ToJ MuYhOZO9sxXqT2r09Ys/L3yNWC7F4TmgPsc9SnOeQHrAK2GpZ8nzJLmzbVUsWh2e JXLOC62qx1ViC777Y7NhRCOjy+EaDveaBk3e1CNOIZZbOVtXHS9dCF4Jef98l7VN g64N1uajeeAz0JmWAjCnPv/So0M/BVoG6kQC2nz4SNAzqfkHx5Xh9T71XXG68pWp dIhhWeO/yloTunK0jF02h+mmxTwTv97QRCbut+wucPrXnbes5cVAWubXbHssw1ab R80LzvobtCHXt2a49CUwi1wNuepnsvRtrtWhnk/Yn+knArAdBtaP4/tIEp9/EaEQ PkxROpaw0RPxx9gmrjrKkcRpnd8BKWRRb2jaFOwIQZeQjdCygPLPwj2/kWjFgGce xGATVdVhmVd8upUPYUk6ynW8yQqTP2cOEvIo4jEbwFcW3wh8GcF+Dx+FHgo2fFt+ J7x6v+Db9NpSvd4MVHAxkUOVyLzwPt0JfjBkUO1/AaQzZ01oT74V77D2AhGiGxMl OtzCWfHjXEa7ZywCRuoeSKbmW9m1vFGikpbbqsY3Iqb+zCB0oy2pLmvLwIIRIbWT ee5Ehr7XHuQe+w== -----END CERTIFICATE----- # Issuer: CN=CA 沃通根è¯ä¹¦ O=WoSign CA Limited # Subject: CN=CA 沃通根è¯ä¹¦ O=WoSign CA Limited # Label: "WoSign China" # Serial: 106921963437422998931660691310149453965 # MD5 Fingerprint: 78:83:5b:52:16:76:c4:24:3b:83:78:e8:ac:da:9a:93 # SHA1 Fingerprint: 16:32:47:8d:89:f9:21:3a:92:00:85:63:f5:a4:a7:d3:12:40:8a:d6 # SHA256 Fingerprint: d6:f0:34:bd:94:aa:23:3f:02:97:ec:a4:24:5b:28:39:73:e4:47:aa:59:0f:31:0c:77:f4:8f:df:83:11:22:54 -----BEGIN CERTIFICATE----- MIIFWDCCA0CgAwIBAgIQUHBrzdgT/BtOOzNy0hFIjTANBgkqhkiG9w0BAQsFADBG MQswCQYDVQQGEwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNV BAMMEkNBIOayg+mAmuagueivgeS5pjAeFw0wOTA4MDgwMTAwMDFaFw0zOTA4MDgw MTAwMDFaMEYxCzAJBgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRl ZDEbMBkGA1UEAwwSQ0Eg5rKD6YCa5qC56K+B5LmmMIICIjANBgkqhkiG9w0BAQEF AAOCAg8AMIICCgKCAgEA0EkhHiX8h8EqwqzbdoYGTufQdDTc7WU1/FDWiD+k8H/r D195L4mx/bxjWDeTmzj4t1up+thxx7S8gJeNbEvxUNUqKaqoGXqW5pWOdO2XCld1 9AXbbQs5uQF/qvbW2mzmBeCkTVL829B0txGMe41P/4eDrv8FAxNXUDf+jJZSEExf v5RxadmWPgxDT74wwJ85dE8GRV2j1lY5aAfMh09Qd5Nx2UQIsYo06Yms25tO4dnk UkWMLhQfkWsZHWgpLFbE4h4TV2TwYeO5Ed+w4VegG63XX9Gv2ystP9Bojg/qnw+L NVgbExz03jWhCl3W6t8Sb8D7aQdGctyB9gQjF+BNdeFyb7Ao65vh4YOhn0pdr8yb +gIgthhid5E7o9Vlrdx8kHccREGkSovrlXLp9glk3Kgtn3R46MGiCWOc76DbT52V qyBPt7D3h1ymoOQ3OMdc4zUPLK2jgKLsLl3Az+2LBcLmc272idX10kaO6m1jGx6K yX2m+Jzr5dVjhU1zZmkR/sgO9MHHZklTfuQZa/HpelmjbX7FF+Ynxu8b22/8DU0G AbQOXDBGVWCvOGU6yke6rCzMRh+yRpY/8+0mBe53oWprfi1tWFxK1I5nuPHa1UaK J/kR8slC/k7e3x9cxKSGhxYzoacXGKUN5AXlK8IrC6KVkLn9YDxOiT7nnO4fuwEC AwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O BBYEFOBNv9ybQV0T6GTwp+kVpOGBwboxMA0GCSqGSIb3DQEBCwUAA4ICAQBqinA4 WbbaixjIvirTthnVZil6Xc1bL3McJk6jfW+rtylNpumlEYOnOXOvEESS5iVdT2H6 yAa+Tkvv/vMx/sZ8cApBWNromUuWyXi8mHwCKe0JgOYKOoICKuLJL8hWGSbueBwj /feTZU7n85iYr83d2Z5AiDEoOqsuC7CsDCT6eiaY8xJhEPRdF/d+4niXVOKM6Cm6 jBAyvd0zaziGfjk9DgNyp115j0WKWa5bIW4xRtVZjc8VX90xJc/bYNaBRHIpAlf2 ltTW/+op2znFuCyKGo3Oy+dCMYYFaA6eFN0AkLppRQjbbpCBhqcqBT/mhDn4t/lX X0ykeVoQDF7Va/81XwVRHmyjdanPUIPTfPRm94KNPQx96N97qA4bLJyuQHCH2u2n FoJavjVsIE4iYdm8UXrNemHcSxH5/mc0zy4EZmFcV5cjjPOGG0jfKq+nwf/Yjj4D u9gqsPoUJbJRa4ZDhS4HIxaAjUz7tGM7zMN07RujHv41D198HRaG9Q7DlfEvr10l O1Hm13ZBONFLAzkopR6RctR9q5czxNM+4Gm2KHmgCY0c0f9BckgG/Jou5yD5m6Le ie2uPAmvylezkolwQOQvT8Jwg0DXJCxr5wkf09XHwQj02w47HAcLQxGEIYbpgNR1 2KvxAmLBsX5VYc8T1yaw15zLKYs4SgsOkI26oQ== -----END CERTIFICATE----- # Issuer: CN=COMODO RSA Certification Authority O=COMODO CA Limited # Subject: CN=COMODO RSA Certification Authority O=COMODO CA Limited # Label: "COMODO RSA Certification Authority" # Serial: 101909084537582093308941363524873193117 # MD5 Fingerprint: 1b:31:b0:71:40:36:cc:14:36:91:ad:c4:3e:fd:ec:18 # SHA1 Fingerprint: af:e5:d2:44:a8:d1:19:42:30:ff:47:9f:e2:f8:97:bb:cd:7a:8c:b4 # SHA256 Fingerprint: 52:f0:e1:c4:e5:8e:c6:29:29:1b:60:31:7f:07:46:71:b8:5d:7e:a8:0d:5b:07:27:34:63:53:4b:32:b4:02:34 -----BEGIN CERTIFICATE----- MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5 MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR 6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC 9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV /erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z +pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB /wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM 4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV 2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl 0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB NVOFBkpdn627G190 -----END CERTIFICATE----- # Issuer: CN=USERTrust RSA Certification Authority O=The USERTRUST Network # Subject: CN=USERTrust RSA Certification Authority O=The USERTRUST Network # Label: "USERTrust RSA Certification Authority" # Serial: 2645093764781058787591871645665788717 # MD5 Fingerprint: 1b:fe:69:d1:91:b7:19:33:a3:72:a8:0f:e1:55:e5:b5 # SHA1 Fingerprint: 2b:8f:1b:57:33:0d:bb:a2:d0:7a:6c:51:f7:0e:e9:0d:da:b9:ad:8e # SHA256 Fingerprint: e7:93:c9:b0:2f:d8:aa:13:e2:1c:31:22:8a:cc:b0:81:19:64:3b:74:9c:89:89:64:b1:74:6d:46:c3:d4:cb:d2 -----BEGIN CERTIFICATE----- MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B 3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/ Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2 VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT 79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6 c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3 ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs 8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/ qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG jjxDah2nGN59PRbxYvnKkKj9 -----END CERTIFICATE----- # Issuer: CN=USERTrust ECC Certification Authority O=The USERTRUST Network # Subject: CN=USERTrust ECC Certification Authority O=The USERTRUST Network # Label: "USERTrust ECC Certification Authority" # Serial: 123013823720199481456569720443997572134 # MD5 Fingerprint: fa:68:bc:d9:b5:7f:ad:fd:c9:1d:06:83:28:cc:24:c1 # SHA1 Fingerprint: d1:cb:ca:5d:b2:d5:2a:7f:69:3b:67:4d:e5:f0:5a:1d:0c:95:7d:f0 # SHA256 Fingerprint: 4f:f4:60:d5:4b:9c:86:da:bf:bc:fc:57:12:e0:40:0d:2b:ed:3f:bc:4d:4f:bd:aa:86:e0:6a:dc:d2:a9:ad:7a -----BEGIN CERTIFICATE----- MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= -----END CERTIFICATE----- # Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4 # Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4 # Label: "GlobalSign ECC Root CA - R4" # Serial: 14367148294922964480859022125800977897474 # MD5 Fingerprint: 20:f0:27:68:d1:7e:a0:9d:0e:e6:2a:ca:df:5c:89:8e # SHA1 Fingerprint: 69:69:56:2e:40:80:f4:24:a1:e7:19:9f:14:ba:f3:ee:58:ab:6a:bb # SHA256 Fingerprint: be:c9:49:11:c2:95:56:76:db:6c:0a:55:09:86:d7:6e:3b:a0:05:66:7c:44:2c:97:62:b4:fb:b7:73:de:22:8c -----BEGIN CERTIFICATE----- MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs ewv4n4Q= -----END CERTIFICATE----- # Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5 # Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5 # Label: "GlobalSign ECC Root CA - R5" # Serial: 32785792099990507226680698011560947931244 # MD5 Fingerprint: 9f:ad:3b:1c:02:1e:8a:ba:17:74:38:81:0c:a2:bc:08 # SHA1 Fingerprint: 1f:24:c6:30:cd:a4:18:ef:20:69:ff:ad:4f:dd:5f:46:3a:1b:69:aa # SHA256 Fingerprint: 17:9f:bc:14:8a:3d:d0:0f:d2:4e:a1:34:58:cc:43:bf:a7:f5:9c:81:82:d7:83:a5:13:f6:eb:ec:10:0c:89:24 -----BEGIN CERTIFICATE----- MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc 8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg 515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO xwy8p2Fp8fc74SrL+SvzZpA3 -----END CERTIFICATE----- # Issuer: CN=Staat der Nederlanden Root CA - G3 O=Staat der Nederlanden # Subject: CN=Staat der Nederlanden Root CA - G3 O=Staat der Nederlanden # Label: "Staat der Nederlanden Root CA - G3" # Serial: 10003001 # MD5 Fingerprint: 0b:46:67:07:db:10:2f:19:8c:35:50:60:d1:0b:f4:37 # SHA1 Fingerprint: d8:eb:6b:41:51:92:59:e0:f3:e7:85:00:c0:3d:b6:88:97:c9:ee:fc # SHA256 Fingerprint: 3c:4f:b0:b9:5a:b8:b3:00:32:f4:32:b8:6f:53:5f:e1:72:c1:85:d0:fd:39:86:58:37:cf:36:18:7f:a6:f4:28 -----BEGIN CERTIFICATE----- MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloX DTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv b3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4yolQP cPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WW IkYFsO2tx1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqX xz8ecAgwoNzFs21v0IJyEavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFy KJLZWyNtZrVtB0LrpjPOktvA9mxjeM3KTj215VKb8b475lRgsGYeCasH/lSJEULR 9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUurmkVLoR9BvUhTFXFkC4az 5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU51nus6+N8 6U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7 Ngzp07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHP bMk7ccHViLVlvMDoFxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXt BznaqB16nzaeErAMZRKQFWDZJkBE41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTt XUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMBAAGjQjBAMA8GA1UdEwEB/wQF MAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleuyjWcLhL75Lpd INyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwp LiniyMMB8jPqKqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8 Ipf3YF3qKS9Ysr1YvY2WTxB1v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixp gZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA8KCWAg8zxXHzniN9lLf9OtMJgwYh /WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b8KKaa8MFSu1BYBQw 0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0rmj1A fsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq 4BZ+Extq1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR 1VmiiXTTn74eS9fGbbeIJG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/ QFH1T/U67cjF68IeHRaVesd+QnGTbksVtzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM 94B7IWcnMFk= -----END CERTIFICATE----- # Issuer: CN=Staat der Nederlanden EV Root CA O=Staat der Nederlanden # Subject: CN=Staat der Nederlanden EV Root CA O=Staat der Nederlanden # Label: "Staat der Nederlanden EV Root CA" # Serial: 10000013 # MD5 Fingerprint: fc:06:af:7b:e8:1a:f1:9a:b4:e8:d2:70:1f:c0:f5:ba # SHA1 Fingerprint: 76:e2:7e:c1:4f:db:82:c1:c0:a6:75:b5:05:be:3d:29:b4:ed:db:bb # SHA256 Fingerprint: 4d:24:91:41:4c:fe:95:67:46:ec:4c:ef:a6:cf:6f:72:e2:8a:13:29:43:2f:9d:8a:90:7a:c4:cb:5d:ad:c1:5a -----BEGIN CERTIFICATE----- MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJO TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFh dCBkZXIgTmVkZXJsYW5kZW4gRVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0y MjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIg TmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBS b290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkkSzrS M4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nC UiY4iKTWO0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3d Z//BYY1jTw+bbRcwJu+r0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46p rfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13l pJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gVXJrm0w912fxBmJc+qiXb j5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr08C+eKxC KFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS /ZbV0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0X cgOPvZuM5l5Tnrmd74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH 1vI4gnPah1vlPNOePqc7nvQDs/nxfRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrP px9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB /zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwaivsnuL8wbqg7 MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u 2dfOWBfoqSmuc0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHS v4ilf0X8rLiltTMMgsT7B/Zq5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTC wPTxGfARKbalGAKb12NMcIxHowNDXLldRqANb/9Zjr7dn3LDWyvfjFvO5QxGbJKy CqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tNf1zuacpzEPuKqf2e vTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi5Dp6 Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIa Gl6I6lD4WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeL eG9QgkRQP2YGiqtDhFZKDyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8 FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGyeUN51q1veieQA6TqJIc/2b3Z6fJfUEkc 7uzXLg== -----END CERTIFICATE----- # Issuer: CN=IdenTrust Commercial Root CA 1 O=IdenTrust # Subject: CN=IdenTrust Commercial Root CA 1 O=IdenTrust # Label: "IdenTrust Commercial Root CA 1" # Serial: 13298821034946342390520003877796839426 # MD5 Fingerprint: b3:3e:77:73:75:ee:a0:d3:e3:7e:49:63:49:59:bb:c7 # SHA1 Fingerprint: df:71:7e:aa:4a:d9:4e:c9:55:84:99:60:2d:48:de:5f:bc:f0:3a:25 # SHA256 Fingerprint: 5d:56:49:9b:e4:d2:e0:8b:cf:ca:d0:8a:3e:38:72:3d:50:50:3b:de:70:69:48:e4:2f:55:60:30:19:e5:28:ae -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT 3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU +ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1 bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB /zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH 6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93 nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3 +wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG 4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A 7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H -----END CERTIFICATE----- # Issuer: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust # Subject: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust # Label: "IdenTrust Public Sector Root CA 1" # Serial: 13298821034946342390521976156843933698 # MD5 Fingerprint: 37:06:a5:b0:fc:89:9d:ba:f4:6b:8c:1a:64:cd:d5:ba # SHA1 Fingerprint: ba:29:41:60:77:98:3f:f4:f3:ef:f2:31:05:3b:2e:ea:6d:4d:45:fd # SHA256 Fingerprint: 30:d0:89:5a:9a:44:8a:26:20:91:63:55:22:d1:f5:20:10:b5:86:7a:ca:e1:2c:78:ef:95:8f:d4:f4:38:9f:2f -----BEGIN CERTIFICATE----- MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0 MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7 ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF /YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R 3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy 9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ 2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9 TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5 +bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv 8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c -----END CERTIFICATE----- # Issuer: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only # Subject: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only # Label: "Entrust Root Certification Authority - G2" # Serial: 1246989352 # MD5 Fingerprint: 4b:e2:c9:91:96:65:0c:f4:0e:5a:93:92:a0:0a:fe:b2 # SHA1 Fingerprint: 8c:f4:27:fd:79:0c:3a:d1:66:06:8d:e8:1e:57:ef:bb:93:22:72:d4 # SHA256 Fingerprint: 43:df:57:74:b0:3e:7f:ef:5f:e4:0d:93:1a:7b:ed:f1:bb:2e:6b:42:73:8c:4e:6d:38:41:10:3d:3a:a7:f3:39 -----BEGIN CERTIFICATE----- MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50 cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0 aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1 U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0 jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/ jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v 1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g== -----END CERTIFICATE----- # Issuer: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only # Subject: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only # Label: "Entrust Root Certification Authority - EC1" # Serial: 51543124481930649114116133369 # MD5 Fingerprint: b6:7e:1d:f0:58:c5:49:6c:24:3b:3d:ed:98:18:ed:bc # SHA1 Fingerprint: 20:d8:06:40:df:9b:25:f5:12:25:3a:11:ea:f7:59:8a:eb:14:b5:47 # SHA256 Fingerprint: 02:ed:0e:b2:8c:14:da:45:16:5c:56:67:91:70:0d:64:51:d7:fb:56:f0:b2:ab:1d:3b:8e:b0:70:e5:6e:df:f5 -----BEGIN CERTIFICATE----- MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3 d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G -----END CERTIFICATE----- # Issuer: CN=CFCA EV ROOT O=China Financial Certification Authority # Subject: CN=CFCA EV ROOT O=China Financial Certification Authority # Label: "CFCA EV ROOT" # Serial: 407555286 # MD5 Fingerprint: 74:e1:b6:ed:26:7a:7a:44:30:33:94:ab:7b:27:81:30 # SHA1 Fingerprint: e2:b8:29:4b:55:84:ab:6b:58:c2:90:46:6c:ac:3f:b8:39:8f:84:83 # SHA256 Fingerprint: 5c:c3:d7:8e:4e:1d:5e:45:54:7a:04:e6:87:3e:64:f9:0c:f9:53:6d:1c:cc:2e:f8:00:f3:55:c4:c5:fd:70:fd -----BEGIN CERTIFICATE----- MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03 sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5 /ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp 7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19 xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN 5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe /v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ 5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su -----END CERTIFICATE----- # Issuer: CN=TÜRKTRUST Elektronik Sertifika Hizmet SaÄŸlayıcısı H5 O=TÜRKTRUST Bilgi İletiÅŸim ve BiliÅŸim GüvenliÄŸi Hizmetleri A.Åž. # Subject: CN=TÜRKTRUST Elektronik Sertifika Hizmet SaÄŸlayıcısı H5 O=TÜRKTRUST Bilgi İletiÅŸim ve BiliÅŸim GüvenliÄŸi Hizmetleri A.Åž. # Label: "TÜRKTRUST Elektronik Sertifika Hizmet SaÄŸlayıcısı H5" # Serial: 156233699172481 # MD5 Fingerprint: da:70:8e:f0:22:df:93:26:f6:5f:9f:d3:15:06:52:4e # SHA1 Fingerprint: c4:18:f6:4d:46:d1:df:00:3d:27:30:13:72:43:a9:12:11:c6:75:fb # SHA256 Fingerprint: 49:35:1b:90:34:44:c1:85:cc:dc:5c:69:3d:24:d8:55:5c:b2:08:d6:a8:14:13:07:69:9f:4a:f0:63:19:9d:78 -----BEGIN CERTIFICATE----- MIIEJzCCAw+gAwIBAgIHAI4X/iQggTANBgkqhkiG9w0BAQsFADCBsTELMAkGA1UE BhMCVFIxDzANBgNVBAcMBkFua2FyYTFNMEsGA1UECgxEVMOcUktUUlVTVCBCaWxn aSDEsGxldGnFn2ltIHZlIEJpbGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkg QS7Fni4xQjBABgNVBAMMOVTDnFJLVFJVU1QgRWxla3Ryb25payBTZXJ0aWZpa2Eg SGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSBINTAeFw0xMzA0MzAwODA3MDFaFw0yMzA0 MjgwODA3MDFaMIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0wSwYD VQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8 dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBF bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1MIIB IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApCUZ4WWe60ghUEoI5RHwWrom /4NZzkQqL/7hzmAD/I0Dpe3/a6i6zDQGn1k19uwsu537jVJp45wnEFPzpALFp/kR Gml1bsMdi9GYjZOHp3GXDSHHmflS0yxjXVW86B8BSLlg/kJK9siArs1mep5Fimh3 4khon6La8eHBEJ/rPCmBp+EyCNSgBbGM+42WAA4+Jd9ThiI7/PS98wl+d+yG6w8z 5UNP9FR1bSmZLmZaQ9/LXMrI5Tjxfjs1nQ/0xVqhzPMggCTTV+wVunUlm+hkS7M0 hO8EuPbJbKoCPrZV4jI3X/xml1/N1p7HIL9Nxqw/dV8c7TKcfGkAaZHjIxhT6QID AQABo0IwQDAdBgNVHQ4EFgQUVpkHHtOsDGlktAxQR95DLL4gwPswDgYDVR0PAQH/ BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ5FdnsX SDLyOIspve6WSk6BGLFRRyDN0GSxDsnZAdkJzsiZ3GglE9Rc8qPoBP5yCccLqh0l VX6Wmle3usURehnmp349hQ71+S4pL+f5bFgWV1Al9j4uPqrtd3GqqpmWRgqujuwq URawXs3qZwQcWDD1YIq9pr1N5Za0/EKJAWv2cMhQOQwt1WbZyNKzMrcbGW3LM/nf peYVhDfwwvJllpKQd/Ct9JDpEXjXk4nAPQu6KfTomZ1yju2dL+6SfaHx/126M2CF Yv4HAqGEVka+lgqaE9chTLd8B59OTj+RdPsnnRHM3eaxynFNExc5JsUpISuTKWqW +qtB4Uu2NQvAmxU= -----END CERTIFICATE----- # Issuer: CN=Certinomis - Root CA O=Certinomis OU=0002 433998903 # Subject: CN=Certinomis - Root CA O=Certinomis OU=0002 433998903 # Label: "Certinomis - Root CA" # Serial: 1 # MD5 Fingerprint: 14:0a:fd:8d:a8:28:b5:38:69:db:56:7e:61:22:03:3f # SHA1 Fingerprint: 9d:70:bb:01:a5:a4:a0:18:11:2e:f7:1c:01:b9:32:c5:34:e7:88:a8 # SHA256 Fingerprint: 2a:99:f5:bc:11:74:b7:3c:bb:1d:62:08:84:e0:1c:34:e5:1c:cb:39:78:da:12:5f:0e:33:26:88:83:bf:41:58 -----BEGIN CERTIFICATE----- MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjET MBEGA1UEChMKQ2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAb BgNVBAMTFENlcnRpbm9taXMgLSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMz MTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMx FzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRDZXJ0aW5vbWlzIC0g Um9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQosP5L2 fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJfl LieY6pOod5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQV WZUKxkd8aRi5pwP5ynapz8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDF TKWrteoB4owuZH9kb/2jJZOLyKIOSY008B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb 5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09xRLWtwHkziOC/7aOgFLSc CbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE6OXWk6Ri wsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJ wx3tFvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SG m/lg0h9tkQPTYKbVPZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4 F2iw4lNVYC2vPsKD2NkJK/DAZNuHi5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZng WVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIB BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I6tNxIqSSaHh0 2TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/ 0KGRHCwPT5iVWVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWw F6YSjNRieOpWauwK0kDDPAUwPk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZS g081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAXlCOotQqSD7J6wWAsOMwaplv/8gzj qh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJy29SWwNyhlCVCNSN h4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9Iff/ ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8V btaw5BngDwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwj Y/M50n92Uaf0yKHxDHYiI0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ 8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nMcyrDflOR1m749fPH0FFNjkulW+YZFzvW gQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVrhkIGuUE= -----END CERTIFICATE----- # Issuer: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed # Subject: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed # Label: "OISTE WISeKey Global Root GB CA" # Serial: 157768595616588414422159278966750757568 # MD5 Fingerprint: a4:eb:b9:61:28:2e:b7:2f:98:b0:35:26:90:99:51:1d # SHA1 Fingerprint: 0f:f9:40:76:18:d3:d7:6a:4b:98:f0:a8:35:9e:0c:fd:27:ac:cc:ed # SHA256 Fingerprint: 6b:9c:08:e8:6e:b0:f7:67:cf:ad:65:cd:98:b6:21:49:e5:49:4a:67:f5:84:5e:7b:d1:ed:01:9f:27:b8:6b:d6 -----BEGIN CERTIFICATE----- MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i YWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAwMzJaFw0zOTEyMDExNTEwMzFaMG0x CzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBG b3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh bCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3 HEokKtaXscriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGx WuR51jIjK+FTzJlFXHtPrby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX 1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNk u7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4oQnc/nSMbsrY9gBQHTC5P 99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvgGUpuuy9r M2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw AwEB/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUB BAMCAQAwDQYJKoZIhvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrgh cViXfa43FK8+5/ea4n32cZiZBKpDdHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5 gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0VQreUGdNZtGn//3ZwLWoo4rO ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= -----END CERTIFICATE----- # Issuer: CN=Certification Authority of WoSign G2 O=WoSign CA Limited # Subject: CN=Certification Authority of WoSign G2 O=WoSign CA Limited # Label: "Certification Authority of WoSign G2" # Serial: 142423943073812161787490648904721057092 # MD5 Fingerprint: c8:1c:7d:19:aa:cb:71:93:f2:50:f8:52:a8:1e:ba:60 # SHA1 Fingerprint: fb:ed:dc:90:65:b7:27:20:37:bc:55:0c:9c:56:de:bb:f2:78:94:e1 # SHA256 Fingerprint: d4:87:a5:6f:83:b0:74:82:e8:5e:96:33:94:c1:ec:c2:c9:e5:1d:09:03:ee:94:6b:02:c3:01:58:1e:d9:9e:16 -----BEGIN CERTIFICATE----- MIIDfDCCAmSgAwIBAgIQayXaioidfLwPBbOxemFFRDANBgkqhkiG9w0BAQsFADBY MQswCQYDVQQGEwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxLTArBgNV BAMTJENlcnRpZmljYXRpb24gQXV0aG9yaXR5IG9mIFdvU2lnbiBHMjAeFw0xNDEx MDgwMDU4NThaFw00NDExMDgwMDU4NThaMFgxCzAJBgNVBAYTAkNOMRowGAYDVQQK ExFXb1NpZ24gQ0EgTGltaXRlZDEtMCsGA1UEAxMkQ2VydGlmaWNhdGlvbiBBdXRo b3JpdHkgb2YgV29TaWduIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEAvsXEoCKASU+/2YcRxlPhuw+9YH+v9oIOH9ywjj2X4FA8jzrvZjtFB5sg+OPX JYY1kBaiXW8wGQiHC38Gsp1ij96vkqVg1CuAmlI/9ZqD6TRay9nVYlzmDuDfBpgO gHzKtB0TiGsOqCR3A9DuW/PKaZE1OVbFbeP3PU9ekzgkyhjpJMuSA93MHD0JcOQg 5PGurLtzaaNjOg9FD6FKmsLRY6zLEPg95k4ot+vElbGs/V6r+kHLXZ1L3PR8du9n fwB6jdKgGlxNIuG12t12s9R23164i5jIFFTMaxeSt+BKv0mUYQs4kI9dJGwlezt5 2eJ+na2fmKEG/HgUYFf47oB3sQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU+mCp62XF3RYUCE4MD42b4Pdkr2cwDQYJ KoZIhvcNAQELBQADggEBAFfDejaCnI2Y4qtAqkePx6db7XznPWZaOzG73/MWM5H8 fHulwqZm46qwtyeYP0nXYGdnPzZPSsvxFPpahygc7Y9BMsaV+X3avXtbwrAh449G 3CE4Q3RM+zD4F3LBMvzIkRfEzFg3TgvMWvchNSiDbGAtROtSjFA9tWwS1/oJu2yy SrHFieT801LYYRf+epSEj3m2M1m6D8QL4nCgS3gu+sif/a+RZQp4OBXllxcU3fng LDT4ONCEIgDAFFEYKwLcMFrw6AF8NTojrwjkr6qOKEJJLvD1mTS+7Q9LGOHSJDy7 XUe3IfKN0QqZjuNuPq1w4I+5ysxugTH2e5x6eeRncRg= -----END CERTIFICATE----- # Issuer: CN=CA WoSign ECC Root O=WoSign CA Limited # Subject: CN=CA WoSign ECC Root O=WoSign CA Limited # Label: "CA WoSign ECC Root" # Serial: 138625735294506723296996289575837012112 # MD5 Fingerprint: 80:c6:53:ee:61:82:28:72:f0:ff:21:b9:17:ca:b2:20 # SHA1 Fingerprint: d2:7a:d2:be:ed:94:c0:a1:3c:c7:25:21:ea:5d:71:be:81:19:f3:2b # SHA256 Fingerprint: 8b:45:da:1c:06:f7:91:eb:0c:ab:f2:6b:e5:88:f5:fb:23:16:5c:2e:61:4b:f8:85:56:2d:0d:ce:50:b2:9b:02 -----BEGIN CERTIFICATE----- MIICCTCCAY+gAwIBAgIQaEpYcIBr8I8C+vbe6LCQkDAKBggqhkjOPQQDAzBGMQsw CQYDVQQGEwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNVBAMT EkNBIFdvU2lnbiBFQ0MgUm9vdDAeFw0xNDExMDgwMDU4NThaFw00NDExMDgwMDU4 NThaMEYxCzAJBgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRlZDEb MBkGA1UEAxMSQ0EgV29TaWduIEVDQyBSb290MHYwEAYHKoZIzj0CAQYFK4EEACID YgAE4f2OuEMkq5Z7hcK6C62N4DrjJLnSsb6IOsq/Srj57ywvr1FQPEd1bPiUt5v8 KB7FVMxjnRZLU8HnIKvNrCXSf4/CwVqCXjCLelTOA7WRf6qU0NGKSMyCBSah1VES 1ns2o0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E FgQUqv3VWqP2h4syhf3RMluARZPzA7gwCgYIKoZIzj0EAwMDaAAwZQIxAOSkhLCB 1T2wdKyUpOgOPQB0TKGXa/kNUTyh2Tv0Daupn75OcsqF1NnstTJFGG+rrQIwfcf3 aWMvoeGY7xMQ0Xk/0f7qO3/eVvSQsRUR2LIiFdAvwyYua/GRspBl9JrmkO5K -----END CERTIFICATE----- # Issuer: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A. # Subject: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A. # Label: "SZAFIR ROOT CA2" # Serial: 357043034767186914217277344587386743377558296292 # MD5 Fingerprint: 11:64:c1:89:b0:24:b1:8c:b1:07:7e:89:9e:51:9e:99 # SHA1 Fingerprint: e2:52:fa:95:3f:ed:db:24:60:bd:6e:28:f3:9c:cc:cf:5e:b3:3f:de # SHA256 Fingerprint: a1:33:9d:33:28:1a:0b:56:e5:57:d3:d3:2b:1c:e7:f9:36:7e:b0:94:bd:5f:a7:2a:7e:50:04:c8:de:d7:ca:fe -----BEGIN CERTIFICATE----- MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQEL BQAwUTELMAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6 ZW5pb3dhIFMuQS4xGDAWBgNVBAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkw NzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9L cmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYDVQQDDA9TWkFGSVIg Uk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5QqEvN QLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT 3PSQ1hNKDJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw 3gAeqDRHu5rr/gsUvTaE2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr6 3fE9biCloBK0TXC5ztdyO4mTp4CEHCdJckm1/zuVnsHMyAHs6A6KCpbns6aH5db5 BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwiieDhZNRnvDF5YTy7ykHN XGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD AgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsF AAOCAQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw 8PRBEew/R40/cof5O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOG nXkZ7/e7DDWQw4rtTw/1zBLZpD67oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCP oky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul4+vJhaAlIDf7js4MNIThPIGy d05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6+/NNIxuZMzSg LvWpCz/UXeHPhJ/iGcJfitYgHuNztw== -----END CERTIFICATE----- # Issuer: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority # Subject: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority # Label: "Certum Trusted Network CA 2" # Serial: 44979900017204383099463764357512596969 # MD5 Fingerprint: 6d:46:9e:d9:25:6d:08:23:5b:5e:74:7d:1e:27:db:f2 # SHA1 Fingerprint: d3:dd:48:3e:2b:bf:4c:05:e8:af:10:f5:fa:76:26:cf:d3:dc:30:92 # SHA256 Fingerprint: b6:76:f2:ed:da:e8:77:5c:d3:6c:b0:f6:3c:d1:d4:60:39:61:f4:9e:62:65:ba:01:3a:2f:03:07:b6:d0:b8:04 -----BEGIN CERTIFICATE----- MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCB gDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMu QS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIG A1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMCIYDzIwMTExMDA2MDgz OTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZ VW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRp ZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3 b3JrIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWA DGSdhhuWZGc/IjoedQF97/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn 0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+oCgCXhVqqndwpyeI1B+twTUrWwbNWuKFB OJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40bRr5HMNUuctHFY9rnY3lE fktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2puTRZCr+E Sv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1m o130GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02i sx7QBlrd9pPPV3WZ9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOW OZV7bIBaTxNyxtd9KXpEulKkKtVBRgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgez Tv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pyehizKV/Ma5ciSixqClnrDvFAS adgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vMBhBgu4M1t15n 3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMC AQYwDQYJKoZIhvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQ F/xlhMcQSZDe28cmk4gmb3DWAl45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTf CVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuAL55MYIR4PSFk1vtBHxgP58l1cb29 XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMoclm2q8KMZiYcdywm djWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tMpkT/ WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jb AoJnwTnbw3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksq P/ujmv5zMnHCnsZy4YpoJ/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Ko b7a6bINDd82Kkhehnlt4Fj1F4jNy3eFmypnTycUm/Q1oBEauttmbjL4ZvrHG8hnj XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P 5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7zAYspsbi DrW5viSP -----END CERTIFICATE----- # Issuer: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority # Subject: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority # Label: "Hellenic Academic and Research Institutions RootCA 2015" # Serial: 0 # MD5 Fingerprint: ca:ff:e2:db:03:d9:cb:4b:e9:0f:ad:84:fd:7b:18:ce # SHA1 Fingerprint: 01:0c:06:95:a6:98:19:14:ff:bf:5f:c6:b0:b6:95:ea:29:e9:12:a6 # SHA256 Fingerprint: a0:40:92:9a:02:ce:53:b4:ac:f4:f2:ff:c6:98:1c:e4:49:6f:75:5e:6d:45:fe:0b:2a:69:2b:cd:52:52:3f:36 -----BEGIN CERTIFICATE----- MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT N0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9v dENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAxMTIxWjCBpjELMAkG A1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNh ZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkx QDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 dGlvbnMgUm9vdENBIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC AQDC+Kk/G4n8PDwEXT2QNrCROnk8ZlrvbTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA 4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+ehiGsxr/CL0BgzuNtFajT0 AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+6PAQZe10 4S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06C ojXdFPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV 9Cz82XBST3i4vTwri5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrD gfgXy5I2XdGj2HUb4Ysn6npIQf1FGQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6 Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2fu/Z8VFRfS0myGlZYeCsargq NhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9muiNX6hME6wGko LfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNV HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVd ctA4GGqd83EkVAswDQYJKoZIhvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0I XtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+D1hYc2Ryx+hFjtyp8iY/xnmMsVMI M4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrMd/K4kPFox/la/vot 9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+yd+2V Z5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/ea j8GsGsVn82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnh X9izjFk0WaSrT2y7HxjbdavYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQ l033DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6A7na+RZukYT1HCjI/CbM1xyQVqdf bzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVtJ94Cj8rDtSvK6evIIVM4 pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0 vm9qp/UsQu0yrbYhnr68 -----END CERTIFICATE----- # Issuer: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority # Subject: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority # Label: "Hellenic Academic and Research Institutions ECC RootCA 2015" # Serial: 0 # MD5 Fingerprint: 81:e5:b4:17:eb:c2:f5:e1:4b:0d:41:7b:49:92:fe:ef # SHA1 Fingerprint: 9f:f1:71:8d:92:d5:9a:f3:7d:74:97:b4:bc:6f:84:68:0b:ba:b6:66 # SHA256 Fingerprint: 44:b5:45:aa:8a:25:e6:5a:73:ca:15:dc:27:fc:36:d2:4c:1c:b9:95:3a:06:65:39:b1:15:82:dc:48:7b:48:33 -----BEGIN CERTIFICATE----- MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl bGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgRUNDIFJv b3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEwMzcxMlowgaoxCzAJ BgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmljIEFj YWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5 MUQwQgYDVQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0 dXRpb25zIEVDQyBSb290Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKg QehLgoRc4vgxEZmGZE4JJS+dQS8KrjVPdJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJa jq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoKVlp8aQuqgAkkbH7BRqNC MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLQi C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR -----END CERTIFICATE----- # Issuer: CN=Certplus Root CA G1 O=Certplus # Subject: CN=Certplus Root CA G1 O=Certplus # Label: "Certplus Root CA G1" # Serial: 1491911565779898356709731176965615564637713 # MD5 Fingerprint: 7f:09:9c:f7:d9:b9:5c:69:69:56:d5:37:3e:14:0d:42 # SHA1 Fingerprint: 22:fd:d0:b7:fd:a2:4e:0d:ac:49:2c:a0:ac:a6:7b:6a:1f:e3:f7:66 # SHA256 Fingerprint: 15:2a:40:2b:fc:df:2c:d5:48:05:4d:22:75:b3:9c:7f:ca:3e:c0:97:80:78:b0:f0:ea:76:e5:61:a6:c7:43:3e -----BEGIN CERTIFICATE----- MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUA MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy dHBsdXMgUm9vdCBDQSBHMTAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBa MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy dHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB ANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHNr49a iZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt 6kuJPKNxQv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP 0FG7Yn2ksYyy/yARujVjBYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f 6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTvLRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDE EW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2z4QTd28n6v+WZxcIbekN 1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc4nBvCGrc h2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCT mehd4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV 4EJQeIQEQWGw9CEjjy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPO WftwenMGE9nTdDckQQoRb5fc5+R+ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1Ud DwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSowcCbkahDFXxd Bie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHYlwuBsTANBgkq hkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh 66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7 /SMNkPX0XtPGYX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BS S7CTKtQ+FjPlnsZlFT5kOwQ/2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j 2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F6ALEUz65noe8zDUa3qHpimOHZR4R Kttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilXCNQ314cnrUlZp5Gr RHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWetUNy 6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEV V/xuZDDCVRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5 g4VCXA9DO2pJNdWY9BW/+mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl ++O/QmueD6i9a5jc2NvLi6Td11n0bt3+qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo= -----END CERTIFICATE----- # Issuer: CN=Certplus Root CA G2 O=Certplus # Subject: CN=Certplus Root CA G2 O=Certplus # Label: "Certplus Root CA G2" # Serial: 1492087096131536844209563509228951875861589 # MD5 Fingerprint: a7:ee:c4:78:2d:1b:ee:2d:b9:29:ce:d6:a7:96:32:31 # SHA1 Fingerprint: 4f:65:8e:1f:e9:06:d8:28:02:e9:54:47:41:c9:54:25:5d:69:cc:1a # SHA256 Fingerprint: 6c:c0:50:41:e6:44:5e:74:69:6c:4c:fb:c9:f8:0f:54:3b:7e:ab:bb:44:b4:ce:6f:78:7c:6a:99:71:c4:2f:17 -----BEGIN CERTIFICATE----- MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4x CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs dXMgUm9vdCBDQSBHMjAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4x CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs dXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABM0PW1aC3/BFGtat 93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uNAm8x Ik0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0P AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwj FNiPwyCrKGBZMB8GA1UdIwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqG SM49BAMDA2gAMGUCMHD+sAvZ94OX7PNVHdTcswYO/jOYnYs5kGuUIe22113WTNch p+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjlvPl5adytRSv3tjFzzAal U5ORGpOucGpnutee5WEaXw== -----END CERTIFICATE----- # Issuer: CN=OpenTrust Root CA G1 O=OpenTrust # Subject: CN=OpenTrust Root CA G1 O=OpenTrust # Label: "OpenTrust Root CA G1" # Serial: 1492036577811947013770400127034825178844775 # MD5 Fingerprint: 76:00:cc:81:29:cd:55:5e:88:6a:7a:2e:f7:4d:39:da # SHA1 Fingerprint: 79:91:e8:34:f7:e2:ee:dd:08:95:01:52:e9:55:2d:14:e9:58:d5:7e # SHA256 Fingerprint: 56:c7:71:28:d9:8c:18:d9:1b:4c:fd:ff:bc:25:ee:91:03:d4:75:8e:a2:ab:ad:82:6a:90:f3:45:7d:46:0e:b4 -----BEGIN CERTIFICATE----- MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUA MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w ZW5UcnVzdCBSb290IENBIEcxMB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAw MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU T3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK AoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7faYp6b wiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX /uMftk87ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR0 77F9jAHiOH3BX2pfJLKOYheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGP uY4zbGneWK2gDqdkVBFpRGZPTBKnjix9xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLx p2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO9z0M+Yo0FMT7MzUj8czx Kselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq3ywgsNw2 TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+W G+Oin6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPw vFEVVJSmdz7QdFG9URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYY EQRVzXR7z2FwefR7LFxckvzluFqrTJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAO BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUl0YhVyE1 2jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/PxN3DlCPaTKbYw DQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kf gLMtMrpkZ2CvuVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbS FXJfLkur1J1juONI5f6ELlgKn0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0 V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLhX4SPgPL0DTatdrOjteFkdjpY3H1P XlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80nR14SohWZ25g/4/I i+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcmGS3t TAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L91 09S5zvE/bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/Ky Pu1svf0OnWZzsD2097+o4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJ AwSQiumPv+i2tCqjI40cHLI5kqiPAlxAOXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj 1oxx -----END CERTIFICATE----- # Issuer: CN=OpenTrust Root CA G2 O=OpenTrust # Subject: CN=OpenTrust Root CA G2 O=OpenTrust # Label: "OpenTrust Root CA G2" # Serial: 1492012448042702096986875987676935573415441 # MD5 Fingerprint: 57:24:b6:59:24:6b:ae:c8:fe:1c:0c:20:f2:c0:4e:eb # SHA1 Fingerprint: 79:5f:88:60:c5:ab:7c:3d:92:e6:cb:f4:8d:e1:45:cd:11:ef:60:0b # SHA256 Fingerprint: 27:99:58:29:fe:6a:75:15:c1:bf:e8:48:f9:c4:76:1d:b1:6c:22:59:29:25:7b:f4:0d:08:94:f2:9e:a8:ba:f2 -----BEGIN CERTIFICATE----- MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUA MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w ZW5UcnVzdCBSb290IENBIEcyMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAw MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU T3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK AoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+Ntmh /LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78e CbY2albz4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/6 1UWY0jUJ9gNDlP7ZvyCVeYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fE FY8ElggGQgT4hNYdvJGmQr5J1WqIP7wtUdGejeBSzFfdNTVY27SPJIjki9/ca1TS gSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz3GIZ38i1MH/1PCZ1Eb3X G7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj3CzMpSZy YhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaH vGOz9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4 t/bQWVyJ98LVtZR00dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/ gh7PU3+06yzbXfZqfUAkBXKJOAGTy3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAO BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUajn6QiL3 5okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59M4PLuG53hq8w DQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0 nXGEL8pZ0keImUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qT RmTFAHneIWv2V6CG1wZy7HBGS4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpT wm+bREx50B1ws9efAvSyB7DH5fitIw6mVskpEndI2S9G/Tvw/HRwkqWOOAgfZDC2 t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ6e18CL13zSdkzJTa TkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97krgCf2 o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU 3jg9CcCoSmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eA iN1nE28daCSLT7d0geX0YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14f WKGVyasvc0rQLW6aWQ9VGHgtPFGml4vmu7JwqkwR3v98KzfUetF3NI/n+UL3PIEM S1IK -----END CERTIFICATE----- # Issuer: CN=OpenTrust Root CA G3 O=OpenTrust # Subject: CN=OpenTrust Root CA G3 O=OpenTrust # Label: "OpenTrust Root CA G3" # Serial: 1492104908271485653071219941864171170455615 # MD5 Fingerprint: 21:37:b4:17:16:92:7b:67:46:70:a9:96:d7:a8:13:24 # SHA1 Fingerprint: 6e:26:64:f3:56:bf:34:55:bf:d1:93:3f:7c:01:de:d8:13:da:8a:a6 # SHA256 Fingerprint: b7:c3:62:31:70:6e:81:07:8c:36:7c:b8:96:19:8f:1e:32:08:dd:92:69:49:dd:8f:57:09:a4:10:f7:5b:62:92 -----BEGIN CERTIFICATE----- MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAx CzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5U cnVzdCBSb290IENBIEczMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFow QDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwUT3Bl blRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARK7liuTcpm 3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5Bta1d oYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4G A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5 DMlv4VBN0BBY3JWIbTAfBgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAK BggqhkjOPQQDAwNpADBmAjEAj6jcnboMBBf6Fek9LykBl7+BFjNAk2z8+e2AcG+q j9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta3U1fJAuwACEl74+nBCZx 4nxp5V2a+EEfOzmTk51V6s2N8fvB -----END CERTIFICATE----- # Issuer: CN=ISRG Root X1 O=Internet Security Research Group # Subject: CN=ISRG Root X1 O=Internet Security Research Group # Label: "ISRG Root X1" # Serial: 172886928669790476064670243504169061120 # MD5 Fingerprint: 0c:d2:f9:e0:da:17:73:e9:ed:86:4d:a5:e3:70:e7:4e # SHA1 Fingerprint: ca:bd:2a:79:a1:07:6a:31:f2:1d:25:36:35:cb:03:9d:43:29:a5:e8 # SHA256 Fingerprint: 96:bc:ec:06:26:49:76:f3:74:60:77:9a:cf:28:c5:a7:cf:e8:a3:c0:aa:e1:1a:8f:fc:ee:05:c0:bd:df:08:c6 -----BEGIN CERTIFICATE----- MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ 0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ 3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq 4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= -----END CERTIFICATE----- # Issuer: O=FNMT-RCM OU=AC RAIZ FNMT-RCM # Subject: O=FNMT-RCM OU=AC RAIZ FNMT-RCM # Label: "AC RAIZ FNMT-RCM" # Serial: 485876308206448804701554682760554759 # MD5 Fingerprint: e2:09:04:b4:d3:bd:d1:a0:14:fd:1a:d2:47:c4:57:1d # SHA1 Fingerprint: ec:50:35:07:b2:15:c4:95:62:19:e2:a8:9a:5b:42:99:2c:4c:2c:20 # SHA256 Fingerprint: eb:c5:57:0c:29:01:8c:4d:67:b1:aa:12:7b:af:12:f7:03:b4:61:1e:bc:17:b7:da:b5:57:38:94:17:9b:93:fa -----BEGIN CERTIFICATE----- MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/ yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z 374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7 wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2 ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3 LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1 RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf 77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp 6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp 1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B 9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv uu8wd+RU4riEmViAqhOLUTpPSPaLtrM= -----END CERTIFICATE----- # Issuer: CN=Amazon Root CA 1 O=Amazon # Subject: CN=Amazon Root CA 1 O=Amazon # Label: "Amazon Root CA 1" # Serial: 143266978916655856878034712317230054538369994 # MD5 Fingerprint: 43:c6:bf:ae:ec:fe:ad:2f:18:c6:88:68:30:fc:c8:e6 # SHA1 Fingerprint: 8d:a7:f9:65:ec:5e:fc:37:91:0f:1c:6e:59:fd:c1:cc:6a:6e:de:16 # SHA256 Fingerprint: 8e:cd:e6:88:4f:3d:87:b1:12:5b:a3:1a:c3:fc:b1:3d:70:16:de:7f:57:cc:90:4f:e1:cb:97:c6:ae:98:19:6e -----BEGIN CERTIFICATE----- MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM 9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L 93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU 5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy rqXRfboQnoZsG4q5WTP468SQvvG5 -----END CERTIFICATE----- # Issuer: CN=Amazon Root CA 2 O=Amazon # Subject: CN=Amazon Root CA 2 O=Amazon # Label: "Amazon Root CA 2" # Serial: 143266982885963551818349160658925006970653239 # MD5 Fingerprint: c8:e5:8d:ce:a8:42:e2:7a:c0:2a:5c:7c:9e:26:bf:66 # SHA1 Fingerprint: 5a:8c:ef:45:d7:a6:98:59:76:7a:8c:8b:44:96:b5:78:cf:47:4b:1a # SHA256 Fingerprint: 1b:a5:b2:aa:8c:65:40:1a:82:96:01:18:f8:0b:ec:4f:62:30:4d:83:ce:c4:71:3a:19:c3:9c:01:1e:a4:6d:b4 -----BEGIN CERTIFICATE----- MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg 1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K 8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r 2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR 8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz 7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6 +XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI 0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2 LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY +gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl 7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+ fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63 n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE 76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H 9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT 4PsJYGw= -----END CERTIFICATE----- # Issuer: CN=Amazon Root CA 3 O=Amazon # Subject: CN=Amazon Root CA 3 O=Amazon # Label: "Amazon Root CA 3" # Serial: 143266986699090766294700635381230934788665930 # MD5 Fingerprint: a0:d4:ef:0b:f7:b5:d8:49:95:2a:ec:f5:c4:fc:81:87 # SHA1 Fingerprint: 0d:44:dd:8c:3c:8c:1a:1a:58:75:64:81:e9:0f:2e:2a:ff:b3:d2:6e # SHA256 Fingerprint: 18:ce:6c:fe:7b:f1:4e:60:b2:e3:47:b8:df:e8:68:cb:31:d0:2e:bb:3a:da:27:15:69:f5:03:43:b4:6d:b3:a4 -----BEGIN CERTIFICATE----- MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5 MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM YyRIHN8wfdVoOw== -----END CERTIFICATE----- # Issuer: CN=Amazon Root CA 4 O=Amazon # Subject: CN=Amazon Root CA 4 O=Amazon # Label: "Amazon Root CA 4" # Serial: 143266989758080763974105200630763877849284878 # MD5 Fingerprint: 89:bc:27:d5:eb:17:8d:06:6a:69:d5:fd:89:47:b4:cd # SHA1 Fingerprint: f6:10:84:07:d6:f8:bb:67:98:0c:c2:e2:44:c2:eb:ae:1c:ef:63:be # SHA256 Fingerprint: e3:5d:28:41:9e:d0:20:25:cf:a6:90:38:cd:62:39:62:45:8d:a5:c6:95:fb:de:a3:c2:2b:0b:fb:25:89:70:92 -----BEGIN CERTIFICATE----- MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5 MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi 9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB /zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW 1KyLa2tJElMzrdfkviT8tQp21KW8EA== -----END CERTIFICATE----- # Issuer: CN=LuxTrust Global Root 2 O=LuxTrust S.A. # Subject: CN=LuxTrust Global Root 2 O=LuxTrust S.A. # Label: "LuxTrust Global Root 2" # Serial: 59914338225734147123941058376788110305822489521 # MD5 Fingerprint: b2:e1:09:00:61:af:f7:f1:91:6f:c4:ad:8d:5e:3b:7c # SHA1 Fingerprint: 1e:0e:56:19:0a:d1:8b:25:98:b2:04:44:ff:66:8a:04:17:99:5f:3f # SHA256 Fingerprint: 54:45:5f:71:29:c2:0b:14:47:c4:18:f9:97:16:8f:24:c5:8f:c5:02:3b:f5:da:5b:e2:eb:6e:1d:d8:90:2e:d5 -----BEGIN CERTIFICATE----- MIIFwzCCA6ugAwIBAgIUCn6m30tEntpqJIWe5rgV0xZ/u7EwDQYJKoZIhvcNAQEL BQAwRjELMAkGA1UEBhMCTFUxFjAUBgNVBAoMDUx1eFRydXN0IFMuQS4xHzAdBgNV BAMMFkx1eFRydXN0IEdsb2JhbCBSb290IDIwHhcNMTUwMzA1MTMyMTU3WhcNMzUw MzA1MTMyMTU3WjBGMQswCQYDVQQGEwJMVTEWMBQGA1UECgwNTHV4VHJ1c3QgUy5B LjEfMB0GA1UEAwwWTHV4VHJ1c3QgR2xvYmFsIFJvb3QgMjCCAiIwDQYJKoZIhvcN AQEBBQADggIPADCCAgoCggIBANeFl78RmOnwYoNMPIf5U2o3C/IPPIfOb9wmKb3F ibrJgz337spbxm1Jc7TJRqMbNBM/wYlFV/TZsfs2ZUv7COJIcRHIbjuend+JZTem hfY7RBi2xjcwYkSSl2l9QjAk5A0MiWtj3sXh306pFGxT4GHO9hcvHTy95iJMHZP1 EMShduxq3sVs35a0VkBCwGKSMKEtFZSg0iAGCW5qbeXrt77U8PEVfIvmTroTzEsn Xpk8F12PgX8zPU/TPxvsXD/wPEx1bvKm1Z3aLQdjAsZy6ZS8TEmVT4hSyNvoaYL4 zDRbIvCGp4m9SAptZoFtyMhk+wHh9OHe2Z7d21vUKpkmFRseTJIpgp7VkoGSQXAZ 96Tlk0u8d2cx3Rz9MXANF5kM+Qw5GSoXtTBxVdUPrljhPS80m8+f9niFwpN6cj5m j5wWEWCPnolvZ77gR1o7DJpni89Gxq44o/KnvObWhWszJHAiS8sIm7vI+AIpHb4g DEa/a4ebsypmQjVGbKq6rfmYe+lQVRQxv7HaLe2ArWgk+2mr2HETMOZns4dA/Yl+ 8kPREd8vZS9kzl8UubG/Mb2HeFpZZYiq/FkySIbWTLkpS5XTdvN3JW1CHDiDTf2j X5t/Lax5Gw5CMZdjpPuKadUiDTSQMC6otOBttpSsvItO13D8xTiOZCXhTTmQzsmH hFhxAgMBAAGjgagwgaUwDwYDVR0TAQH/BAUwAwEB/zBCBgNVHSAEOzA5MDcGByuB KwEBAQowLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9yZXBvc2l0b3J5Lmx1eHRydXN0 Lmx1MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT/GCh2+UgFLKGu8SsbK7JT +Et8szAdBgNVHQ4EFgQU/xgodvlIBSyhrvErGyuyU/hLfLMwDQYJKoZIhvcNAQEL BQADggIBAGoZFO1uecEsh9QNcH7X9njJCwROxLHOk3D+sFTAMs2ZMGQXvw/l4jP9 BzZAcg4atmpZ1gDlaCDdLnINH2pkMSCEfUmmWjfrRcmF9dTHF5kH5ptV5AzoqbTO jFu1EVzPig4N1qx3gf4ynCSecs5U89BvolbW7MM3LGVYvlcAGvI1+ut7MV3CwRI9 loGIlonBWVx65n9wNOeD4rHh4bhY79SV5GCc8JaXcozrhAIuZY+kt9J/Z93I055c qqmkoCUUBpvsT34tC38ddfEz2O3OuHVtPlu5mB0xDVbYQw8wkbIEa91WvpWAVWe+ 2M2D2RjuLg+GLZKecBPs3lHJQ3gCpU3I+V/EkVhGFndadKpAvAefMLmx9xIX3eP/ JEAdemrRTxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKre zrnK+T+Tb/mjuuqlPpmt/f97mfVl7vBZKGfXkJWkE4SphMHozs51k2MavDzq1WQf LSoSOcbDWjLtR5EWDrw4wVDej8oqkDQc7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+ x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31IiyBMz2TWuJdGsE7RKlY6 oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr -----END CERTIFICATE----- # Issuer: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM # Subject: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM # Label: "TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1" # Serial: 1 # MD5 Fingerprint: dc:00:81:dc:69:2f:3e:2f:b0:3b:f6:3d:5a:91:8e:49 # SHA1 Fingerprint: 31:43:64:9b:ec:ce:27:ec:ed:3a:3f:0b:8f:0d:e4:e8:91:dd:ee:ca # SHA256 Fingerprint: 46:ed:c3:68:90:46:d5:3a:45:3f:b3:10:4a:b8:0d:ca:ec:65:8b:26:60:ea:16:29:dd:7e:86:79:90:64:87:16 -----BEGIN CERTIFICATE----- MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0 BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7 a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/ iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4 lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c 8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= -----END CERTIFICATE----- grpc-1.3.2/examples/000077500000000000000000000000001310511640000142555ustar00rootroot00000000000000grpc-1.3.2/examples/README.md000066400000000000000000000020041310511640000155300ustar00rootroot00000000000000# Examples This directory contains code examples for all the C-based gRPC implementations: C++, Node.js, Python, Ruby, Objective-C, PHP, and C#. You can find examples and instructions specific to your favourite language in the relevant subdirectory. Examples for Go and Java gRPC live in their own repositories: * [Java](https://github.com/grpc/grpc-java/tree/master/examples) * [Android Java](https://github.com/grpc/grpc-java/tree/master/examples/android) * [Go](https://github.com/grpc/grpc-go/tree/master/examples) For more comprehensive documentation, including an [overview](http://www.grpc.io/docs/) and tutorials that use this example code, visit [grpc.io](http://www.grpc.io/docs/). ## Quick start Each example directory has quick start instructions for the appropriate language, including installation instructions and how to run our simplest Hello World example: * [C++](cpp) * [Ruby](ruby) * [Node.js](node) * [Python](python/helloworld) * [C#](csharp) * [Objective-C](objective-c/helloworld) * [PHP](php) grpc-1.3.2/examples/cpp/000077500000000000000000000000001310511640000150375ustar00rootroot00000000000000grpc-1.3.2/examples/cpp/README.md000066400000000000000000000020171310511640000163160ustar00rootroot00000000000000#gRPC in 3 minutes (C++) ## Installation To install gRPC on your system, follow the instructions to build from source [here](../../INSTALL.md). This also installs the protocol buffer compiler `protoc` (if you don't have it already), and the C++ gRPC plugin for `protoc`. ## Hello C++ gRPC! Here's how to build and run the C++ implementation of the [Hello World](../protos/helloworld.proto) example used in [Getting started](..). ### Client and server implementations The client implementation is at [greeter_client.cc](helloworld/greeter_client.cc). The server implementation is at [greeter_server.cc](helloworld/greeter_server.cc). ### Try it! Build client and server: ```sh $ make ``` Run the server, which will listen on port 50051: ```sh $ ./greeter_server ``` Run the client (in a different terminal): ```sh $ ./greeter_client ``` If things go smoothly, you will see the "Greeter received: Hello world" in the client side output. ## Tutorial You can find a more detailed tutorial in [gRPC Basics: C++](cpptutorial.md) grpc-1.3.2/examples/cpp/cpptutorial.md000066400000000000000000000462731310511640000177430ustar00rootroot00000000000000#gRPC Basics: C++ This tutorial provides a basic C++ programmer's introduction to working with gRPC. By walking through this example you'll learn how to: - Define a service in a `.proto` file. - Generate server and client code using the protocol buffer compiler. - Use the C++ gRPC API to write a simple client and server for your service. It assumes that you are familiar with [protocol buffers](https://developers.google.com/protocol-buffers/docs/overview). Note that the example in this tutorial uses the proto3 version of the protocol buffers language, which is currently in alpha release: you can find out more in the [proto3 language guide](https://developers.google.com/protocol-buffers/docs/proto3) and see the [release notes](https://github.com/google/protobuf/releases) for the new version in the protocol buffers Github repository. ## Why use gRPC? Our example is a simple route mapping application that lets clients get information about features on their route, create a summary of their route, and exchange route information such as traffic updates with the server and other clients. With gRPC we can define our service once in a `.proto` file and implement clients and servers in any of gRPC's supported languages, which in turn can be run in environments ranging from servers inside Google to your own tablet - all the complexity of communication between different languages and environments is handled for you by gRPC. We also get all the advantages of working with protocol buffers, including efficient serialization, a simple IDL, and easy interface updating. ## Example code and setup The example code for our tutorial is in [examples/cpp/route_guide](route_guide). You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [INSTALL.md](../../INSTALL.md). ## Defining the service Our first step is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers](https://developers.google.com/protocol-buffers/docs/overview). You can see the complete `.proto` file in [`examples/protos/route_guide.proto`](../protos/route_guide.proto). To define a service, you specify a named `service` in your `.proto` file: ```protobuf service RouteGuide { ... } ``` Then you define `rpc` methods inside your service definition, specifying their request and response types. gRPC lets you define four kinds of service method, all of which are used in the `RouteGuide` service: - A *simple RPC* where the client sends a request to the server using the stub and waits for a response to come back, just like a normal function call. ```protobuf // Obtains the feature at a given position. rpc GetFeature(Point) returns (Feature) {} ``` - A *server-side streaming RPC* where the client sends a request to the server and gets a stream to read a sequence of messages back. The client reads from the returned stream until there are no more messages. As you can see in our example, you specify a server-side streaming method by placing the `stream` keyword before the *response* type. ```protobuf // Obtains the Features available within the given Rectangle. Results are // streamed rather than returned at once (e.g. in a response message with a // repeated field), as the rectangle may cover a large area and contain a // huge number of features. rpc ListFeatures(Rectangle) returns (stream Feature) {} ``` - A *client-side streaming RPC* where the client writes a sequence of messages and sends them to the server, again using a provided stream. Once the client has finished writing the messages, it waits for the server to read them all and return its response. You specify a client-side streaming method by placing the `stream` keyword before the *request* type. ```protobuf // Accepts a stream of Points on a route being traversed, returning a // RouteSummary when traversal is completed. rpc RecordRoute(stream Point) returns (RouteSummary) {} ``` - A *bidirectional streaming RPC* where both sides send a sequence of messages using a read-write stream. The two streams operate independently, so clients and servers can read and write in whatever order they like: for example, the server could wait to receive all the client messages before writing its responses, or it could alternately read a message then write a message, or some other combination of reads and writes. The order of messages in each stream is preserved. You specify this type of method by placing the `stream` keyword before both the request and the response. ```protobuf // Accepts a stream of RouteNotes sent while a route is being traversed, // while receiving other RouteNotes (e.g. from other users). rpc RouteChat(stream RouteNote) returns (stream RouteNote) {} ``` Our `.proto` file also contains protocol buffer message type definitions for all the request and response types used in our service methods - for example, here's the `Point` message type: ```protobuf // Points are represented as latitude-longitude pairs in the E7 representation // (degrees multiplied by 10**7 and rounded to the nearest integer). // Latitudes should be in the range +/- 90 degrees and longitude should be in // the range +/- 180 degrees (inclusive). message Point { int32 latitude = 1; int32 longitude = 2; } ``` ## Generating client and server code Next we need to generate the gRPC client and server interfaces from our `.proto` service definition. We do this using the protocol buffer compiler `protoc` with a special gRPC C++ plugin. For simplicity, we've provided a [Makefile](route_guide/Makefile) that runs `protoc` for you with the appropriate plugin, input, and output (if you want to run this yourself, make sure you've installed protoc and followed the gRPC code [installation instructions](../../INSTALL.md) first): ```shell $ make route_guide.grpc.pb.cc route_guide.pb.cc ``` which actually runs: ```shell $ protoc -I ../../protos --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` ../../protos/route_guide.proto $ protoc -I ../../protos --cpp_out=. ../../protos/route_guide.proto ``` Running this command generates the following files in your current directory: - `route_guide.pb.h`, the header which declares your generated message classes - `route_guide.pb.cc`, which contains the implementation of your message classes - `route_guide.grpc.pb.h`, the header which declares your generated service classes - `route_guide.grpc.pb.cc`, which contains the implementation of your service classes These contain: - All the protocol buffer code to populate, serialize, and retrieve our request and response message types - A class called `RouteGuide` that contains - a remote interface type (or *stub*) for clients to call with the methods defined in the `RouteGuide` service. - two abstract interfaces for servers to implement, also with the methods defined in the `RouteGuide` service. ## Creating the server First let's look at how we create a `RouteGuide` server. If you're only interested in creating gRPC clients, you can skip this section and go straight to [Creating the client](#client) (though you might find it interesting anyway!). There are two parts to making our `RouteGuide` service do its job: - Implementing the service interface generated from our service definition: doing the actual "work" of our service. - Running a gRPC server to listen for requests from clients and return the service responses. You can find our example `RouteGuide` server in [route_guide/route_guide_server.cc](route_guide/route_guide_server.cc). Let's take a closer look at how it works. ### Implementing RouteGuide As you can see, our server has a `RouteGuideImpl` class that implements the generated `RouteGuide::Service` interface: ```cpp class RouteGuideImpl final : public RouteGuide::Service { ... } ``` In this case we're implementing the *synchronous* version of `RouteGuide`, which provides our default gRPC server behaviour. It's also possible to implement an asynchronous interface, `RouteGuide::AsyncService`, which allows you to further customize your server's threading behaviour, though we won't look at this in this tutorial. `RouteGuideImpl` implements all our service methods. Let's look at the simplest type first, `GetFeature`, which just gets a `Point` from the client and returns the corresponding feature information from its database in a `Feature`. ```cpp Status GetFeature(ServerContext* context, const Point* point, Feature* feature) override { feature->set_name(GetFeatureName(*point, feature_list_)); feature->mutable_location()->CopyFrom(*point); return Status::OK; } ``` The method is passed a context object for the RPC, the client's `Point` protocol buffer request, and a `Feature` protocol buffer to fill in with the response information. In the method we populate the `Feature` with the appropriate information, and then `return` with an `OK` status to tell gRPC that we've finished dealing with the RPC and that the `Feature` can be returned to the client. Now let's look at something a bit more complicated - a streaming RPC. `ListFeatures` is a server-side streaming RPC, so we need to send back multiple `Feature`s to our client. ```cpp Status ListFeatures(ServerContext* context, const Rectangle* rectangle, ServerWriter* writer) override { auto lo = rectangle->lo(); auto hi = rectangle->hi(); long left = std::min(lo.longitude(), hi.longitude()); long right = std::max(lo.longitude(), hi.longitude()); long top = std::max(lo.latitude(), hi.latitude()); long bottom = std::min(lo.latitude(), hi.latitude()); for (const Feature& f : feature_list_) { if (f.location().longitude() >= left && f.location().longitude() <= right && f.location().latitude() >= bottom && f.location().latitude() <= top) { writer->Write(f); } } return Status::OK; } ``` As you can see, instead of getting simple request and response objects in our method parameters, this time we get a request object (the `Rectangle` in which our client wants to find `Feature`s) and a special `ServerWriter` object. In the method, we populate as many `Feature` objects as we need to return, writing them to the `ServerWriter` using its `Write()` method. Finally, as in our simple RPC, we `return Status::OK` to tell gRPC that we've finished writing responses. If you look at the client-side streaming method `RecordRoute` you'll see it's quite similar, except this time we get a `ServerReader` instead of a request object and a single response. We use the `ServerReader`s `Read()` method to repeatedly read in our client's requests to a request object (in this case a `Point`) until there are no more messages: the server needs to check the return value of `Read()` after each call. If `true`, the stream is still good and it can continue reading; if `false` the message stream has ended. ```cpp while (stream->Read(&point)) { ...//process client input } ``` Finally, let's look at our bidirectional streaming RPC `RouteChat()`. ```cpp Status RouteChat(ServerContext* context, ServerReaderWriter* stream) override { std::vector received_notes; RouteNote note; while (stream->Read(¬e)) { for (const RouteNote& n : received_notes) { if (n.location().latitude() == note.location().latitude() && n.location().longitude() == note.location().longitude()) { stream->Write(n); } } received_notes.push_back(note); } return Status::OK; } ``` This time we get a `ServerReaderWriter` that can be used to read *and* write messages. The syntax for reading and writing here is exactly the same as for our client-streaming and server-streaming methods. Although each side will always get the other's messages in the order they were written, both the client and server can read and write in any order — the streams operate completely independently. ### Starting the server Once we've implemented all our methods, we also need to start up a gRPC server so that clients can actually use our service. The following snippet shows how we do this for our `RouteGuide` service: ```cpp void RunServer(const std::string& db_path) { std::string server_address("0.0.0.0:50051"); RouteGuideImpl service(db_path); ServerBuilder builder; builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); builder.RegisterService(&service); std::unique_ptr server(builder.BuildAndStart()); std::cout << "Server listening on " << server_address << std::endl; server->Wait(); } ``` As you can see, we build and start our server using a `ServerBuilder`. To do this, we: 1. Create an instance of our service implementation class `RouteGuideImpl`. 1. Create an instance of the factory `ServerBuilder` class. 1. Specify the address and port we want to use to listen for client requests using the builder's `AddListeningPort()` method. 1. Register our service implementation with the builder. 1. Call `BuildAndStart()` on the builder to create and start an RPC server for our service. 1. Call `Wait()` on the server to do a blocking wait until process is killed or `Shutdown()` is called. ## Creating the client In this section, we'll look at creating a C++ client for our `RouteGuide` service. You can see our complete example client code in [route_guide/route_guide_client.cc](route_guide/route_guide_client.cc). ### Creating a stub To call service methods, we first need to create a *stub*. First we need to create a gRPC *channel* for our stub, specifying the server address and port we want to connect to without SSL: ```cpp grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials()); ``` Now we can use the channel to create our stub using the `NewStub` method provided in the `RouteGuide` class we generated from our `.proto`. ```cpp public: RouteGuideClient(std::shared_ptr channel, const std::string& db) : stub_(RouteGuide::NewStub(channel)) { ... } ``` ### Calling service methods Now let's look at how we call our service methods. Note that in this tutorial we're calling the *blocking/synchronous* versions of each method: this means that the RPC call waits for the server to respond, and will either return a response or raise an exception. #### Simple RPC Calling the simple RPC `GetFeature` is nearly as straightforward as calling a local method. ```cpp Point point; Feature feature; point = MakePoint(409146138, -746188906); GetOneFeature(point, &feature); ... bool GetOneFeature(const Point& point, Feature* feature) { ClientContext context; Status status = stub_->GetFeature(&context, point, feature); ... } ``` As you can see, we create and populate a request protocol buffer object (in our case `Point`), and create a response protocol buffer object for the server to fill in. We also create a `ClientContext` object for our call - you can optionally set RPC configuration values on this object, such as deadlines, though for now we'll use the default settings. Note that you cannot reuse this object between calls. Finally, we call the method on the stub, passing it the context, request, and response. If the method returns `OK`, then we can read the response information from the server from our response object. ```cpp std::cout << "Found feature called " << feature->name() << " at " << feature->location().latitude()/kCoordFactor_ << ", " << feature->location().longitude()/kCoordFactor_ << std::endl; ``` #### Streaming RPCs Now let's look at our streaming methods. If you've already read [Creating the server](#server) some of this may look very familiar - streaming RPCs are implemented in a similar way on both sides. Here's where we call the server-side streaming method `ListFeatures`, which returns a stream of geographical `Feature`s: ```cpp std::unique_ptr > reader( stub_->ListFeatures(&context, rect)); while (reader->Read(&feature)) { std::cout << "Found feature called " << feature.name() << " at " << feature.location().latitude()/kCoordFactor_ << ", " << feature.location().longitude()/kCoordFactor_ << std::endl; } Status status = reader->Finish(); ``` Instead of passing the method a context, request, and response, we pass it a context and request and get a `ClientReader` object back. The client can use the `ClientReader` to read the server's responses. We use the `ClientReader`s `Read()` method to repeatedly read in the server's responses to a response protocol buffer object (in this case a `Feature`) until there are no more messages: the client needs to check the return value of `Read()` after each call. If `true`, the stream is still good and it can continue reading; if `false` the message stream has ended. Finally, we call `Finish()` on the stream to complete the call and get our RPC status. The client-side streaming method `RecordRoute` is similar, except there we pass the method a context and response object and get back a `ClientWriter`. ```cpp std::unique_ptr > writer( stub_->RecordRoute(&context, &stats)); for (int i = 0; i < kPoints; i++) { const Feature& f = feature_list_[feature_distribution(generator)]; std::cout << "Visiting point " << f.location().latitude()/kCoordFactor_ << ", " << f.location().longitude()/kCoordFactor_ << std::endl; if (!writer->Write(f.location())) { // Broken stream. break; } std::this_thread::sleep_for(std::chrono::milliseconds( delay_distribution(generator))); } writer->WritesDone(); Status status = writer->Finish(); if (status.IsOk()) { std::cout << "Finished trip with " << stats.point_count() << " points\n" << "Passed " << stats.feature_count() << " features\n" << "Travelled " << stats.distance() << " meters\n" << "It took " << stats.elapsed_time() << " seconds" << std::endl; } else { std::cout << "RecordRoute rpc failed." << std::endl; } ``` Once we've finished writing our client's requests to the stream using `Write()`, we need to call `WritesDone()` on the stream to let gRPC know that we've finished writing, then `Finish()` to complete the call and get our RPC status. If the status is `OK`, our response object that we initially passed to `RecordRoute()` will be populated with the server's response. Finally, let's look at our bidirectional streaming RPC `RouteChat()`. In this case, we just pass a context to the method and get back a `ClientReaderWriter`, which we can use to both write and read messages. ```cpp std::shared_ptr > stream( stub_->RouteChat(&context)); ``` The syntax for reading and writing here is exactly the same as for our client-streaming and server-streaming methods. Although each side will always get the other's messages in the order they were written, both the client and server can read and write in any order — the streams operate completely independently. ## Try it out! Build client and server: ```shell $ make ``` Run the server, which will listen on port 50051: ```shell $ ./route_guide_server ``` Run the client (in a different terminal): ```shell $ ./route_guide_client ``` grpc-1.3.2/examples/cpp/helloworld/000077500000000000000000000000001310511640000172125ustar00rootroot00000000000000grpc-1.3.2/examples/cpp/helloworld/BUILD000066400000000000000000000034521310511640000200000ustar00rootroot00000000000000# Copyright 2017, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cc_binary( name = "greeter_client", srcs = ["greeter_client.cc"], deps = ["//examples/protos:helloworld"], defines = ["BAZEL_BUILD"], ) cc_binary( name = "greeter_server", srcs = ["greeter_server.cc"], deps = ["//examples/protos:helloworld"], defines = ["BAZEL_BUILD"], ) grpc-1.3.2/examples/cpp/helloworld/CMakeLists.txt000066400000000000000000000030261310511640000217530ustar00rootroot00000000000000# Minimum CMake required cmake_minimum_required(VERSION 2.8) # Project project(HelloWorld CXX) # Protobuf set(protobuf_MODULE_COMPATIBLE TRUE) find_package(protobuf CONFIG REQUIRED) message(STATUS "Using protobuf ${protobuf_VERSION}") # gRPC find_package(gRPC CONFIG REQUIRED) message(STATUS "Using gRPC ${gRPC_VERSION}") # gRPC C++ plugin get_target_property(gRPC_CPP_PLUGIN_EXECUTABLE gRPC::grpc_cpp_plugin IMPORTED_LOCATION_RELEASE) # Proto file get_filename_component(hw_proto "../../protos/helloworld.proto" ABSOLUTE) get_filename_component(hw_proto_path "${hw_proto}" PATH) # Generated sources protobuf_generate_cpp(hw_proto_srcs hw_proto_hdrs "${hw_proto}") set(hw_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.grpc.pb.cc") set(hw_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.grpc.pb.h") add_custom_command( OUTPUT "${hw_grpc_srcs}" "${hw_grpc_hdrs}" COMMAND protobuf::protoc ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" -I "${hw_proto_path}" --plugin=protoc-gen-grpc="${gRPC_CPP_PLUGIN_EXECUTABLE}" "${hw_proto}" DEPENDS "${hw_proto}") # Generated include directory include_directories("${CMAKE_CURRENT_BINARY_DIR}") # Targets greeter_[async_](client|server) foreach(_target greeter_client greeter_server greeter_async_client greeter_async_server) add_executable(${_target} "${_target}.cc" ${hw_proto_srcs} ${hw_grpc_srcs}) target_link_libraries(${_target} protobuf::libprotobuf gRPC::grpc++_unsecure) endforeach() grpc-1.3.2/examples/cpp/helloworld/Makefile000066400000000000000000000111511310511640000206510ustar00rootroot00000000000000# # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # HOST_SYSTEM = $(shell uname | cut -f 1 -d_) SYSTEM ?= $(HOST_SYSTEM) CXX = g++ CPPFLAGS += -I/usr/local/include -pthread CXXFLAGS += -std=c++11 ifeq ($(SYSTEM),Darwin) LDFLAGS += -L/usr/local/lib `pkg-config --libs grpc++ grpc` \ -lgrpc++_reflection \ -lprotobuf -lpthread -ldl else LDFLAGS += -L/usr/local/lib `pkg-config --libs grpc++ grpc` \ -Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed \ -lprotobuf -lpthread -ldl endif PROTOC = protoc GRPC_CPP_PLUGIN = grpc_cpp_plugin GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)` PROTOS_PATH = ../../protos vpath %.proto $(PROTOS_PATH) all: system-check greeter_client greeter_server greeter_async_client greeter_async_client2 greeter_async_server greeter_client: helloworld.pb.o helloworld.grpc.pb.o greeter_client.o $(CXX) $^ $(LDFLAGS) -o $@ greeter_server: helloworld.pb.o helloworld.grpc.pb.o greeter_server.o $(CXX) $^ $(LDFLAGS) -o $@ greeter_async_client: helloworld.pb.o helloworld.grpc.pb.o greeter_async_client.o $(CXX) $^ $(LDFLAGS) -o $@ greeter_async_client2: helloworld.pb.o helloworld.grpc.pb.o greeter_async_client2.o $(CXX) $^ $(LDFLAGS) -o $@ greeter_async_server: helloworld.pb.o helloworld.grpc.pb.o greeter_async_server.o $(CXX) $^ $(LDFLAGS) -o $@ .PRECIOUS: %.grpc.pb.cc %.grpc.pb.cc: %.proto $(PROTOC) -I $(PROTOS_PATH) --grpc_out=. --plugin=protoc-gen-grpc=$(GRPC_CPP_PLUGIN_PATH) $< .PRECIOUS: %.pb.cc %.pb.cc: %.proto $(PROTOC) -I $(PROTOS_PATH) --cpp_out=. $< clean: rm -f *.o *.pb.cc *.pb.h greeter_client greeter_server greeter_async_client greeter_async_client2 greeter_async_server # The following is to test your system and ensure a smoother experience. # They are by no means necessary to actually compile a grpc-enabled software. PROTOC_CMD = which $(PROTOC) PROTOC_CHECK_CMD = $(PROTOC) --version | grep -q libprotoc.3 PLUGIN_CHECK_CMD = which $(GRPC_CPP_PLUGIN) HAS_PROTOC = $(shell $(PROTOC_CMD) > /dev/null && echo true || echo false) ifeq ($(HAS_PROTOC),true) HAS_VALID_PROTOC = $(shell $(PROTOC_CHECK_CMD) 2> /dev/null && echo true || echo false) endif HAS_PLUGIN = $(shell $(PLUGIN_CHECK_CMD) > /dev/null && echo true || echo false) SYSTEM_OK = false ifeq ($(HAS_VALID_PROTOC),true) ifeq ($(HAS_PLUGIN),true) SYSTEM_OK = true endif endif system-check: ifneq ($(HAS_VALID_PROTOC),true) @echo " DEPENDENCY ERROR" @echo @echo "You don't have protoc 3.0.0 installed in your path." @echo "Please install Google protocol buffers 3.0.0 and its compiler." @echo "You can find it here:" @echo @echo " https://github.com/google/protobuf/releases/tag/v3.0.0" @echo @echo "Here is what I get when trying to evaluate your version of protoc:" @echo -$(PROTOC) --version @echo @echo endif ifneq ($(HAS_PLUGIN),true) @echo " DEPENDENCY ERROR" @echo @echo "You don't have the grpc c++ protobuf plugin installed in your path." @echo "Please install grpc. You can find it here:" @echo @echo " https://github.com/grpc/grpc" @echo @echo "Here is what I get when trying to detect if you have the plugin:" @echo -which $(GRPC_CPP_PLUGIN) @echo @echo endif ifneq ($(SYSTEM_OK),true) @false endif grpc-1.3.2/examples/cpp/helloworld/README.md000066400000000000000000000165271310511640000205040ustar00rootroot00000000000000# gRPC C++ Hello World Tutorial ### Install gRPC Make sure you have installed gRPC on your system. Follow the instructions here: [https://github.com/grpc/grpc/blob/master/INSTALL](../../../INSTALL.md). ### Get the tutorial source code The example code for this and our other examples lives in the `examples` directory. Clone this repository to your local machine by running the following command: ```sh $ git clone -b $(curl -L http://grpc.io/release) https://github.com/grpc/grpc ``` Change your current directory to examples/cpp/helloworld ```sh $ cd examples/cpp/helloworld/ ``` ### Defining a service The first step in creating our example is to define a *service*: an RPC service specifies the methods that can be called remotely with their parameters and return types. As you saw in the [overview](#protocolbuffers) above, gRPC does this using [protocol buffers](https://developers.google.com/protocol-buffers/docs/overview). We use the protocol buffers interface definition language (IDL) to define our service methods, and define the parameters and return types as protocol buffer message types. Both the client and the server use interface code generated from the service definition. Here's our example service definition, defined using protocol buffers IDL in [helloworld.proto](../../protos/helloworld.proto). The `Greeting` service has one method, `hello`, that lets the server receive a single `HelloRequest` message from the remote client containing the user's name, then send back a greeting in a single `HelloReply`. This is the simplest type of RPC you can specify in gRPC - we'll look at some other types later in this document. ```protobuf syntax = "proto3"; option java_package = "ex.grpc"; package helloworld; // The greeting service definition. service Greeter { // Sends a greeting rpc SayHello (HelloRequest) returns (HelloReply) {} } // The request message containing the user's name. message HelloRequest { string name = 1; } // The response message containing the greetings message HelloReply { string message = 1; } ``` ### Generating gRPC code Once we've defined our service, we use the protocol buffer compiler `protoc` to generate the special client and server code we need to create our application. The generated code contains both stub code for clients to use and an abstract interface for servers to implement, both with the method defined in our `Greeting` service. To generate the client and server side interfaces: ```sh $ make helloworld.grpc.pb.cc helloworld.pb.cc ``` Which internally invokes the proto-compiler as: ```sh $ protoc -I ../../protos/ --grpc_out=. --plugin=protoc-gen-grpc=grpc_cpp_plugin ../../protos/helloworld.proto $ protoc -I ../../protos/ --cpp_out=. ../../protos/helloworld.proto ``` ### Writing a client - Create a channel. A channel is a logical connection to an endpoint. A gRPC channel can be created with the target address, credentials to use and arguments as follows ```cpp auto channel = CreateChannel("localhost:50051", InsecureChannelCredentials()); ``` - Create a stub. A stub implements the rpc methods of a service and in the generated code, a method is provided to created a stub with a channel: ```cpp auto stub = helloworld::Greeter::NewStub(channel); ``` - Make a unary rpc, with `ClientContext` and request/response proto messages. ```cpp ClientContext context; HelloRequest request; request.set_name("hello"); HelloReply reply; Status status = stub->SayHello(&context, request, &reply); ``` - Check returned status and response. ```cpp if (status.ok()) { // check reply.message() } else { // rpc failed. } ``` For a working example, refer to [greeter_client.cc](greeter_client.cc). ### Writing a server - Implement the service interface ```cpp class GreeterServiceImpl final : public Greeter::Service { Status SayHello(ServerContext* context, const HelloRequest* request, HelloReply* reply) override { std::string prefix("Hello "); reply->set_message(prefix + request->name()); return Status::OK; } }; ``` - Build a server exporting the service ```cpp GreeterServiceImpl service; ServerBuilder builder; builder.AddListeningPort("0.0.0.0:50051", grpc::InsecureServerCredentials()); builder.RegisterService(&service); std::unique_ptr server(builder.BuildAndStart()); ``` For a working example, refer to [greeter_server.cc](greeter_server.cc). ### Writing asynchronous client and server gRPC uses `CompletionQueue` API for asynchronous operations. The basic work flow is - bind a `CompletionQueue` to a rpc call - do something like a read or write, present with a unique `void*` tag - call `CompletionQueue::Next` to wait for operations to complete. If a tag appears, it indicates that the corresponding operation is complete. #### Async client The channel and stub creation code is the same as the sync client. - Initiate the rpc and create a handle for the rpc. Bind the rpc to a `CompletionQueue`. ```cpp CompletionQueue cq; auto rpc = stub->AsyncSayHello(&context, request, &cq); ``` - Ask for reply and final status, with a unique tag ```cpp Status status; rpc->Finish(&reply, &status, (void*)1); ``` - Wait for the completion queue to return the next tag. The reply and status are ready once the tag passed into the corresponding `Finish()` call is returned. ```cpp void* got_tag; bool ok = false; cq.Next(&got_tag, &ok); if (ok && got_tag == (void*)1) { // check reply and status } ``` For a working example, refer to [greeter_async_client.cc](greeter_async_client.cc). #### Async server The server implementation requests a rpc call with a tag and then wait for the completion queue to return the tag. The basic flow is - Build a server exporting the async service ```cpp helloworld::Greeter::AsyncService service; ServerBuilder builder; builder.AddListeningPort("0.0.0.0:50051", InsecureServerCredentials()); builder.RegisterService(&service); auto cq = builder.AddCompletionQueue(); auto server = builder.BuildAndStart(); ``` - Request one rpc ```cpp ServerContext context; HelloRequest request; ServerAsyncResponseWriter responder; service.RequestSayHello(&context, &request, &responder, &cq, &cq, (void*)1); ``` - Wait for the completion queue to return the tag. The context, request and responder are ready once the tag is retrieved. ```cpp HelloReply reply; Status status; void* got_tag; bool ok = false; cq.Next(&got_tag, &ok); if (ok && got_tag == (void*)1) { // set reply and status responder.Finish(reply, status, (void*)2); } ``` - Wait for the completion queue to return the tag. The rpc is finished when the tag is back. ```cpp void* got_tag; bool ok = false; cq.Next(&got_tag, &ok); if (ok && got_tag == (void*)2) { // clean up } ``` To handle multiple rpcs, the async server creates an object `CallData` to maintain the state of each rpc and use the address of it as the unique tag. For simplicity the server only uses one completion queue for all events, and runs a main loop in `HandleRpcs` to query the queue. For a working example, refer to [greeter_async_server.cc](greeter_async_server.cc). grpc-1.3.2/examples/cpp/helloworld/greeter_async_client.cc000066400000000000000000000114741310511640000237200ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include "helloworld.grpc.pb.h" using grpc::Channel; using grpc::ClientAsyncResponseReader; using grpc::ClientContext; using grpc::CompletionQueue; using grpc::Status; using helloworld::HelloRequest; using helloworld::HelloReply; using helloworld::Greeter; class GreeterClient { public: explicit GreeterClient(std::shared_ptr channel) : stub_(Greeter::NewStub(channel)) {} // Assembles the client's payload, sends it and presents the response back // from the server. std::string SayHello(const std::string& user) { // Data we are sending to the server. HelloRequest request; request.set_name(user); // Container for the data we expect from the server. HelloReply reply; // Context for the client. It could be used to convey extra information to // the server and/or tweak certain RPC behaviors. ClientContext context; // The producer-consumer queue we use to communicate asynchronously with the // gRPC runtime. CompletionQueue cq; // Storage for the status of the RPC upon completion. Status status; // stub_->AsyncSayHello() performs the RPC call, returning an instance we // store in "rpc". Because we are using the asynchronous API, we need to // hold on to the "rpc" instance in order to get updates on the ongoing RPC. std::unique_ptr > rpc( stub_->AsyncSayHello(&context, request, &cq)); // Request that, upon completion of the RPC, "reply" be updated with the // server's response; "status" with the indication of whether the operation // was successful. Tag the request with the integer 1. rpc->Finish(&reply, &status, (void*)1); void* got_tag; bool ok = false; // Block until the next result is available in the completion queue "cq". // The return value of Next should always be checked. This return value // tells us whether there is any kind of event or the cq_ is shutting down. GPR_ASSERT(cq.Next(&got_tag, &ok)); // Verify that the result from "cq" corresponds, by its tag, our previous // request. GPR_ASSERT(got_tag == (void*)1); // ... and that the request was completed successfully. Note that "ok" // corresponds solely to the request for updates introduced by Finish(). GPR_ASSERT(ok); // Act upon the status of the actual RPC. if (status.ok()) { return reply.message(); } else { return "RPC failed"; } } private: // Out of the passed in Channel comes the stub, stored here, our view of the // server's exposed services. std::unique_ptr stub_; }; int main(int argc, char** argv) { // Instantiate the client. It requires a channel, out of which the actual RPCs // are created. This channel models a connection to an endpoint (in this case, // localhost at port 50051). We indicate that the channel isn't authenticated // (use of InsecureChannelCredentials()). GreeterClient greeter(grpc::CreateChannel( "localhost:50051", grpc::InsecureChannelCredentials())); std::string user("world"); std::string reply = greeter.SayHello(user); // The actual RPC call! std::cout << "Greeter received: " << reply << std::endl; return 0; } grpc-1.3.2/examples/cpp/helloworld/greeter_async_client2.cc000066400000000000000000000131571310511640000240020ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include "helloworld.grpc.pb.h" using grpc::Channel; using grpc::ClientAsyncResponseReader; using grpc::ClientContext; using grpc::CompletionQueue; using grpc::Status; using helloworld::HelloRequest; using helloworld::HelloReply; using helloworld::Greeter; class GreeterClient { public: explicit GreeterClient(std::shared_ptr channel) : stub_(Greeter::NewStub(channel)) {} // Assembles the client's payload and sends it to the server. void SayHello(const std::string& user) { // Data we are sending to the server. HelloRequest request; request.set_name(user); // Call object to store rpc data AsyncClientCall* call = new AsyncClientCall; // stub_->AsyncSayHello() performs the RPC call, returning an instance to // store in "call". Because we are using the asynchronous API, we need to // hold on to the "call" instance in order to get updates on the ongoing RPC. call->response_reader = stub_->AsyncSayHello(&call->context, request, &cq_); // Request that, upon completion of the RPC, "reply" be updated with the // server's response; "status" with the indication of whether the operation // was successful. Tag the request with the memory address of the call object. call->response_reader->Finish(&call->reply, &call->status, (void*)call); } // Loop while listening for completed responses. // Prints out the response from the server. void AsyncCompleteRpc() { void* got_tag; bool ok = false; // Block until the next result is available in the completion queue "cq". while (cq_.Next(&got_tag, &ok)) { // The tag in this example is the memory location of the call object AsyncClientCall* call = static_cast(got_tag); // Verify that the request was completed successfully. Note that "ok" // corresponds solely to the request for updates introduced by Finish(). GPR_ASSERT(ok); if (call->status.ok()) std::cout << "Greeter received: " << call->reply.message() << std::endl; else std::cout << "RPC failed" << std::endl; // Once we're complete, deallocate the call object. delete call; } } private: // struct for keeping state and data information struct AsyncClientCall { // Container for the data we expect from the server. HelloReply reply; // Context for the client. It could be used to convey extra information to // the server and/or tweak certain RPC behaviors. ClientContext context; // Storage for the status of the RPC upon completion. Status status; std::unique_ptr> response_reader; }; // Out of the passed in Channel comes the stub, stored here, our view of the // server's exposed services. std::unique_ptr stub_; // The producer-consumer queue we use to communicate asynchronously with the // gRPC runtime. CompletionQueue cq_; }; int main(int argc, char** argv) { // Instantiate the client. It requires a channel, out of which the actual RPCs // are created. This channel models a connection to an endpoint (in this case, // localhost at port 50051). We indicate that the channel isn't authenticated // (use of InsecureChannelCredentials()). GreeterClient greeter(grpc::CreateChannel( "localhost:50051", grpc::InsecureChannelCredentials())); // Spawn reader thread that loops indefinitely std::thread thread_ = std::thread(&GreeterClient::AsyncCompleteRpc, &greeter); for (int i = 0; i < 100; i++) { std::string user("world " + std::to_string(i)); greeter.SayHello(user); // The actual RPC call! } std::cout << "Press control-c to quit" << std::endl << std::endl; thread_.join(); //blocks forever return 0; } grpc-1.3.2/examples/cpp/helloworld/greeter_async_server.cc000066400000000000000000000151561310511640000237510ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include "helloworld.grpc.pb.h" using grpc::Server; using grpc::ServerAsyncResponseWriter; using grpc::ServerBuilder; using grpc::ServerContext; using grpc::ServerCompletionQueue; using grpc::Status; using helloworld::HelloRequest; using helloworld::HelloReply; using helloworld::Greeter; class ServerImpl final { public: ~ServerImpl() { server_->Shutdown(); // Always shutdown the completion queue after the server. cq_->Shutdown(); } // There is no shutdown handling in this code. void Run() { std::string server_address("0.0.0.0:50051"); ServerBuilder builder; // Listen on the given address without any authentication mechanism. builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); // Register "service_" as the instance through which we'll communicate with // clients. In this case it corresponds to an *asynchronous* service. builder.RegisterService(&service_); // Get hold of the completion queue used for the asynchronous communication // with the gRPC runtime. cq_ = builder.AddCompletionQueue(); // Finally assemble the server. server_ = builder.BuildAndStart(); std::cout << "Server listening on " << server_address << std::endl; // Proceed to the server's main loop. HandleRpcs(); } private: // Class encompasing the state and logic needed to serve a request. class CallData { public: // Take in the "service" instance (in this case representing an asynchronous // server) and the completion queue "cq" used for asynchronous communication // with the gRPC runtime. CallData(Greeter::AsyncService* service, ServerCompletionQueue* cq) : service_(service), cq_(cq), responder_(&ctx_), status_(CREATE) { // Invoke the serving logic right away. Proceed(); } void Proceed() { if (status_ == CREATE) { // Make this instance progress to the PROCESS state. status_ = PROCESS; // As part of the initial CREATE state, we *request* that the system // start processing SayHello requests. In this request, "this" acts are // the tag uniquely identifying the request (so that different CallData // instances can serve different requests concurrently), in this case // the memory address of this CallData instance. service_->RequestSayHello(&ctx_, &request_, &responder_, cq_, cq_, this); } else if (status_ == PROCESS) { // Spawn a new CallData instance to serve new clients while we process // the one for this CallData. The instance will deallocate itself as // part of its FINISH state. new CallData(service_, cq_); // The actual processing. std::string prefix("Hello "); reply_.set_message(prefix + request_.name()); // And we are done! Let the gRPC runtime know we've finished, using the // memory address of this instance as the uniquely identifying tag for // the event. status_ = FINISH; responder_.Finish(reply_, Status::OK, this); } else { GPR_ASSERT(status_ == FINISH); // Once in the FINISH state, deallocate ourselves (CallData). delete this; } } private: // The means of communication with the gRPC runtime for an asynchronous // server. Greeter::AsyncService* service_; // The producer-consumer queue where for asynchronous server notifications. ServerCompletionQueue* cq_; // Context for the rpc, allowing to tweak aspects of it such as the use // of compression, authentication, as well as to send metadata back to the // client. ServerContext ctx_; // What we get from the client. HelloRequest request_; // What we send back to the client. HelloReply reply_; // The means to get back to the client. ServerAsyncResponseWriter responder_; // Let's implement a tiny state machine with the following states. enum CallStatus { CREATE, PROCESS, FINISH }; CallStatus status_; // The current serving state. }; // This can be run in multiple threads if needed. void HandleRpcs() { // Spawn a new CallData instance to serve new clients. new CallData(&service_, cq_.get()); void* tag; // uniquely identifies a request. bool ok; while (true) { // Block waiting to read the next event from the completion queue. The // event is uniquely identified by its tag, which in this case is the // memory address of a CallData instance. // The return value of Next should always be checked. This return value // tells us whether there is any kind of event or cq_ is shutting down. GPR_ASSERT(cq_->Next(&tag, &ok)); GPR_ASSERT(ok); static_cast(tag)->Proceed(); } } std::unique_ptr cq_; Greeter::AsyncService service_; std::unique_ptr server_; }; int main(int argc, char** argv) { ServerImpl server; server.Run(); return 0; } grpc-1.3.2/examples/cpp/helloworld/greeter_client.cc000066400000000000000000000066451310511640000225270ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #ifdef BAZEL_BUILD #include "examples/protos/helloworld.grpc.pb.h" #else #include "helloworld.grpc.pb.h" #endif using grpc::Channel; using grpc::ClientContext; using grpc::Status; using helloworld::HelloRequest; using helloworld::HelloReply; using helloworld::Greeter; class GreeterClient { public: GreeterClient(std::shared_ptr channel) : stub_(Greeter::NewStub(channel)) {} // Assembles the client's payload, sends it and presents the response back // from the server. std::string SayHello(const std::string& user) { // Data we are sending to the server. HelloRequest request; request.set_name(user); // Container for the data we expect from the server. HelloReply reply; // Context for the client. It could be used to convey extra information to // the server and/or tweak certain RPC behaviors. ClientContext context; // The actual RPC. Status status = stub_->SayHello(&context, request, &reply); // Act upon its status. if (status.ok()) { return reply.message(); } else { std::cout << status.error_code() << ": " << status.error_message() << std::endl; return "RPC failed"; } } private: std::unique_ptr stub_; }; int main(int argc, char** argv) { // Instantiate the client. It requires a channel, out of which the actual RPCs // are created. This channel models a connection to an endpoint (in this case, // localhost at port 50051). We indicate that the channel isn't authenticated // (use of InsecureChannelCredentials()). GreeterClient greeter(grpc::CreateChannel( "localhost:50051", grpc::InsecureChannelCredentials())); std::string user("world"); std::string reply = greeter.SayHello(user); std::cout << "Greeter received: " << reply << std::endl; return 0; } grpc-1.3.2/examples/cpp/helloworld/greeter_server.cc000066400000000000000000000061151310511640000225470ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #ifdef BAZEL_BUILD #include "examples/protos/helloworld.grpc.pb.h" #else #include "helloworld.grpc.pb.h" #endif using grpc::Server; using grpc::ServerBuilder; using grpc::ServerContext; using grpc::Status; using helloworld::HelloRequest; using helloworld::HelloReply; using helloworld::Greeter; // Logic and data behind the server's behavior. class GreeterServiceImpl final : public Greeter::Service { Status SayHello(ServerContext* context, const HelloRequest* request, HelloReply* reply) override { std::string prefix("Hello "); reply->set_message(prefix + request->name()); return Status::OK; } }; void RunServer() { std::string server_address("0.0.0.0:50051"); GreeterServiceImpl service; ServerBuilder builder; // Listen on the given address without any authentication mechanism. builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); // Register "service" as the instance through which we'll communicate with // clients. In this case it corresponds to an *synchronous* service. builder.RegisterService(&service); // Finally assemble the server. std::unique_ptr server(builder.BuildAndStart()); std::cout << "Server listening on " << server_address << std::endl; // Wait for the server to shutdown. Note that some other thread must be // responsible for shutting down the server for this call to ever return. server->Wait(); } int main(int argc, char** argv) { RunServer(); return 0; } grpc-1.3.2/examples/cpp/route_guide/000077500000000000000000000000001310511640000173525ustar00rootroot00000000000000grpc-1.3.2/examples/cpp/route_guide/Makefile000066400000000000000000000102451310511640000210140ustar00rootroot00000000000000# # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # HOST_SYSTEM = $(shell uname | cut -f 1 -d_) SYSTEM ?= $(HOST_SYSTEM) CXX = g++ CPPFLAGS += -I/usr/local/include -pthread CXXFLAGS += -std=c++11 ifeq ($(SYSTEM),Darwin) LDFLAGS += -L/usr/local/lib `pkg-config --libs grpc++` \ -lgrpc++_reflection \ -lprotobuf -lpthread -ldl else LDFLAGS += -L/usr/local/lib `pkg-config --libs grpc++` \ -Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed \ -lprotobuf -lpthread -ldl endif PROTOC = protoc GRPC_CPP_PLUGIN = grpc_cpp_plugin GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)` PROTOS_PATH = ../../protos vpath %.proto $(PROTOS_PATH) all: system-check route_guide_client route_guide_server route_guide_client: route_guide.pb.o route_guide.grpc.pb.o route_guide_client.o helper.o $(CXX) $^ $(LDFLAGS) -o $@ route_guide_server: route_guide.pb.o route_guide.grpc.pb.o route_guide_server.o helper.o $(CXX) $^ $(LDFLAGS) -o $@ %.grpc.pb.cc: %.proto $(PROTOC) -I $(PROTOS_PATH) --grpc_out=. --plugin=protoc-gen-grpc=$(GRPC_CPP_PLUGIN_PATH) $< %.pb.cc: %.proto $(PROTOC) -I $(PROTOS_PATH) --cpp_out=. $< clean: rm -f *.o *.pb.cc *.pb.h route_guide_client route_guide_server # The following is to test your system and ensure a smoother experience. # They are by no means necessary to actually compile a grpc-enabled software. PROTOC_CMD = which $(PROTOC) PROTOC_CHECK_CMD = $(PROTOC) --version | grep -q libprotoc.3 PLUGIN_CHECK_CMD = which $(GRPC_CPP_PLUGIN) HAS_PROTOC = $(shell $(PROTOC_CMD) > /dev/null && echo true || echo false) ifeq ($(HAS_PROTOC),true) HAS_VALID_PROTOC = $(shell $(PROTOC_CHECK_CMD) 2> /dev/null && echo true || echo false) endif HAS_PLUGIN = $(shell $(PLUGIN_CHECK_CMD) > /dev/null && echo true || echo false) SYSTEM_OK = false ifeq ($(HAS_VALID_PROTOC),true) ifeq ($(HAS_PLUGIN),true) SYSTEM_OK = true endif endif system-check: ifneq ($(HAS_VALID_PROTOC),true) @echo " DEPENDENCY ERROR" @echo @echo "You don't have protoc 3.0.0 installed in your path." @echo "Please install Google protocol buffers 3.0.0 and its compiler." @echo "You can find it here:" @echo @echo " https://github.com/google/protobuf/releases/tag/v3.0.0" @echo @echo "Here is what I get when trying to evaluate your version of protoc:" @echo -$(PROTOC) --version @echo @echo endif ifneq ($(HAS_PLUGIN),true) @echo " DEPENDENCY ERROR" @echo @echo "You don't have the grpc c++ protobuf plugin installed in your path." @echo "Please install grpc. You can find it here:" @echo @echo " https://github.com/grpc/grpc" @echo @echo "Here is what I get when trying to detect if you have the plugin:" @echo -which $(GRPC_CPP_PLUGIN) @echo @echo endif ifneq ($(SYSTEM_OK),true) @false endif grpc-1.3.2/examples/cpp/route_guide/helper.cc000066400000000000000000000125701310511640000211450ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include "route_guide.grpc.pb.h" namespace routeguide { std::string GetDbFileContent(int argc, char** argv) { std::string db_path; std::string arg_str("--db_path"); if (argc > 1) { std::string argv_1 = argv[1]; size_t start_position = argv_1.find(arg_str); if (start_position != std::string::npos) { start_position += arg_str.size(); if (argv_1[start_position] == ' ' || argv_1[start_position] == '=') { db_path = argv_1.substr(start_position + 1); } } } else { db_path = "route_guide_db.json"; } std::ifstream db_file(db_path); if (!db_file.is_open()) { std::cout << "Failed to open " << db_path << std::endl; return ""; } std::stringstream db; db << db_file.rdbuf(); return db.str(); } // A simple parser for the json db file. It requires the db file to have the // exact form of [{"location": { "latitude": 123, "longitude": 456}, "name": // "the name can be empty" }, { ... } ... The spaces will be stripped. class Parser { public: explicit Parser(const std::string& db) : db_(db) { // Remove all spaces. db_.erase( std::remove_if(db_.begin(), db_.end(), isspace), db_.end()); if (!Match("[")) { SetFailedAndReturnFalse(); } } bool Finished() { return current_ >= db_.size(); } bool TryParseOne(Feature* feature) { if (failed_ || Finished() || !Match("{")) { return SetFailedAndReturnFalse(); } if (!Match(location_) || !Match("{") || !Match(latitude_)) { return SetFailedAndReturnFalse(); } long temp = 0; ReadLong(&temp); feature->mutable_location()->set_latitude(temp); if (!Match(",") || !Match(longitude_)) { return SetFailedAndReturnFalse(); } ReadLong(&temp); feature->mutable_location()->set_longitude(temp); if (!Match("},") || !Match(name_) || !Match("\"")) { return SetFailedAndReturnFalse(); } size_t name_start = current_; while (current_ != db_.size() && db_[current_++] != '"') { } if (current_ == db_.size()) { return SetFailedAndReturnFalse(); } feature->set_name(db_.substr(name_start, current_-name_start-1)); if (!Match("},")) { if (db_[current_ - 1] == ']' && current_ == db_.size()) { return true; } return SetFailedAndReturnFalse(); } return true; } private: bool SetFailedAndReturnFalse() { failed_ = true; return false; } bool Match(const std::string& prefix) { bool eq = db_.substr(current_, prefix.size()) == prefix; current_ += prefix.size(); return eq; } void ReadLong(long* l) { size_t start = current_; while (current_ != db_.size() && db_[current_] != ',' && db_[current_] != '}') { current_++; } // It will throw an exception if fails. *l = std::stol(db_.substr(start, current_ - start)); } bool failed_ = false; std::string db_; size_t current_ = 0; const std::string location_ = "\"location\":"; const std::string latitude_ = "\"latitude\":"; const std::string longitude_ = "\"longitude\":"; const std::string name_ = "\"name\":"; }; void ParseDb(const std::string& db, std::vector* feature_list) { feature_list->clear(); std::string db_content(db); db_content.erase( std::remove_if(db_content.begin(), db_content.end(), isspace), db_content.end()); Parser parser(db_content); Feature feature; while (!parser.Finished()) { feature_list->push_back(Feature()); if (!parser.TryParseOne(&feature_list->back())) { std::cout << "Error parsing the db file"; feature_list->clear(); break; } } std::cout << "DB parsed, loaded " << feature_list->size() << " features." << std::endl; } } // namespace routeguide grpc-1.3.2/examples/cpp/route_guide/helper.h000066400000000000000000000036311310511640000210050ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_COMMON_CPP_ROUTE_GUIDE_HELPER_H_ #define GRPC_COMMON_CPP_ROUTE_GUIDE_HELPER_H_ #include #include namespace routeguide { class Feature; std::string GetDbFileContent(int argc, char** argv); void ParseDb(const std::string& db, std::vector* feature_list); } // namespace routeguide #endif // GRPC_COMMON_CPP_ROUTE_GUIDE_HELPER_H_ grpc-1.3.2/examples/cpp/route_guide/route_guide_client.cc000066400000000000000000000205611310511640000235360ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include #include #include "helper.h" #include "route_guide.grpc.pb.h" using grpc::Channel; using grpc::ClientContext; using grpc::ClientReader; using grpc::ClientReaderWriter; using grpc::ClientWriter; using grpc::Status; using routeguide::Point; using routeguide::Feature; using routeguide::Rectangle; using routeguide::RouteSummary; using routeguide::RouteNote; using routeguide::RouteGuide; Point MakePoint(long latitude, long longitude) { Point p; p.set_latitude(latitude); p.set_longitude(longitude); return p; } Feature MakeFeature(const std::string& name, long latitude, long longitude) { Feature f; f.set_name(name); f.mutable_location()->CopyFrom(MakePoint(latitude, longitude)); return f; } RouteNote MakeRouteNote(const std::string& message, long latitude, long longitude) { RouteNote n; n.set_message(message); n.mutable_location()->CopyFrom(MakePoint(latitude, longitude)); return n; } class RouteGuideClient { public: RouteGuideClient(std::shared_ptr channel, const std::string& db) : stub_(RouteGuide::NewStub(channel)) { routeguide::ParseDb(db, &feature_list_); } void GetFeature() { Point point; Feature feature; point = MakePoint(409146138, -746188906); GetOneFeature(point, &feature); point = MakePoint(0, 0); GetOneFeature(point, &feature); } void ListFeatures() { routeguide::Rectangle rect; Feature feature; ClientContext context; rect.mutable_lo()->set_latitude(400000000); rect.mutable_lo()->set_longitude(-750000000); rect.mutable_hi()->set_latitude(420000000); rect.mutable_hi()->set_longitude(-730000000); std::cout << "Looking for features between 40, -75 and 42, -73" << std::endl; std::unique_ptr > reader( stub_->ListFeatures(&context, rect)); while (reader->Read(&feature)) { std::cout << "Found feature called " << feature.name() << " at " << feature.location().latitude()/kCoordFactor_ << ", " << feature.location().longitude()/kCoordFactor_ << std::endl; } Status status = reader->Finish(); if (status.ok()) { std::cout << "ListFeatures rpc succeeded." << std::endl; } else { std::cout << "ListFeatures rpc failed." << std::endl; } } void RecordRoute() { Point point; RouteSummary stats; ClientContext context; const int kPoints = 10; unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); std::default_random_engine generator(seed); std::uniform_int_distribution feature_distribution( 0, feature_list_.size() - 1); std::uniform_int_distribution delay_distribution( 500, 1500); std::unique_ptr > writer( stub_->RecordRoute(&context, &stats)); for (int i = 0; i < kPoints; i++) { const Feature& f = feature_list_[feature_distribution(generator)]; std::cout << "Visiting point " << f.location().latitude()/kCoordFactor_ << ", " << f.location().longitude()/kCoordFactor_ << std::endl; if (!writer->Write(f.location())) { // Broken stream. break; } std::this_thread::sleep_for(std::chrono::milliseconds( delay_distribution(generator))); } writer->WritesDone(); Status status = writer->Finish(); if (status.ok()) { std::cout << "Finished trip with " << stats.point_count() << " points\n" << "Passed " << stats.feature_count() << " features\n" << "Travelled " << stats.distance() << " meters\n" << "It took " << stats.elapsed_time() << " seconds" << std::endl; } else { std::cout << "RecordRoute rpc failed." << std::endl; } } void RouteChat() { ClientContext context; std::shared_ptr > stream( stub_->RouteChat(&context)); std::thread writer([stream]() { std::vector notes{ MakeRouteNote("First message", 0, 0), MakeRouteNote("Second message", 0, 1), MakeRouteNote("Third message", 1, 0), MakeRouteNote("Fourth message", 0, 0)}; for (const RouteNote& note : notes) { std::cout << "Sending message " << note.message() << " at " << note.location().latitude() << ", " << note.location().longitude() << std::endl; stream->Write(note); } stream->WritesDone(); }); RouteNote server_note; while (stream->Read(&server_note)) { std::cout << "Got message " << server_note.message() << " at " << server_note.location().latitude() << ", " << server_note.location().longitude() << std::endl; } writer.join(); Status status = stream->Finish(); if (!status.ok()) { std::cout << "RouteChat rpc failed." << std::endl; } } private: bool GetOneFeature(const Point& point, Feature* feature) { ClientContext context; Status status = stub_->GetFeature(&context, point, feature); if (!status.ok()) { std::cout << "GetFeature rpc failed." << std::endl; return false; } if (!feature->has_location()) { std::cout << "Server returns incomplete feature." << std::endl; return false; } if (feature->name().empty()) { std::cout << "Found no feature at " << feature->location().latitude()/kCoordFactor_ << ", " << feature->location().longitude()/kCoordFactor_ << std::endl; } else { std::cout << "Found feature called " << feature->name() << " at " << feature->location().latitude()/kCoordFactor_ << ", " << feature->location().longitude()/kCoordFactor_ << std::endl; } return true; } const float kCoordFactor_ = 10000000.0; std::unique_ptr stub_; std::vector feature_list_; }; int main(int argc, char** argv) { // Expect only arg: --db_path=path/to/route_guide_db.json. std::string db = routeguide::GetDbFileContent(argc, argv); RouteGuideClient guide( grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials()), db); std::cout << "-------------- GetFeature --------------" << std::endl; guide.GetFeature(); std::cout << "-------------- ListFeatures --------------" << std::endl; guide.ListFeatures(); std::cout << "-------------- RecordRoute --------------" << std::endl; guide.RecordRoute(); std::cout << "-------------- RouteChat --------------" << std::endl; guide.RouteChat(); return 0; } grpc-1.3.2/examples/cpp/route_guide/route_guide_db.json000066400000000000000000000327101310511640000232300ustar00rootroot00000000000000[{ "location": { "latitude": 407838351, "longitude": -746143763 }, "name": "Patriots Path, Mendham, NJ 07945, USA" }, { "location": { "latitude": 408122808, "longitude": -743999179 }, "name": "101 New Jersey 10, Whippany, NJ 07981, USA" }, { "location": { "latitude": 413628156, "longitude": -749015468 }, "name": "U.S. 6, Shohola, PA 18458, USA" }, { "location": { "latitude": 419999544, "longitude": -740371136 }, "name": "5 Conners Road, Kingston, NY 12401, USA" }, { "location": { "latitude": 414008389, "longitude": -743951297 }, "name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA" }, { "location": { "latitude": 419611318, "longitude": -746524769 }, "name": "287 Flugertown Road, Livingston Manor, NY 12758, USA" }, { "location": { "latitude": 406109563, "longitude": -742186778 }, "name": "4001 Tremley Point Road, Linden, NJ 07036, USA" }, { "location": { "latitude": 416802456, "longitude": -742370183 }, "name": "352 South Mountain Road, Wallkill, NY 12589, USA" }, { "location": { "latitude": 412950425, "longitude": -741077389 }, "name": "Bailey Turn Road, Harriman, NY 10926, USA" }, { "location": { "latitude": 412144655, "longitude": -743949739 }, "name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA" }, { "location": { "latitude": 415736605, "longitude": -742847522 }, "name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA" }, { "location": { "latitude": 413843930, "longitude": -740501726 }, "name": "162 Merrill Road, Highland Mills, NY 10930, USA" }, { "location": { "latitude": 410873075, "longitude": -744459023 }, "name": "Clinton Road, West Milford, NJ 07480, USA" }, { "location": { "latitude": 412346009, "longitude": -744026814 }, "name": "16 Old Brook Lane, Warwick, NY 10990, USA" }, { "location": { "latitude": 402948455, "longitude": -747903913 }, "name": "3 Drake Lane, Pennington, NJ 08534, USA" }, { "location": { "latitude": 406337092, "longitude": -740122226 }, "name": "6324 8th Avenue, Brooklyn, NY 11220, USA" }, { "location": { "latitude": 406421967, "longitude": -747727624 }, "name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA" }, { "location": { "latitude": 416318082, "longitude": -749677716 }, "name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA" }, { "location": { "latitude": 415301720, "longitude": -748416257 }, "name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA" }, { "location": { "latitude": 402647019, "longitude": -747071791 }, "name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA" }, { "location": { "latitude": 412567807, "longitude": -741058078 }, "name": "New York State Reference Route 987E, Southfields, NY 10975, USA" }, { "location": { "latitude": 416855156, "longitude": -744420597 }, "name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA" }, { "location": { "latitude": 404663628, "longitude": -744820157 }, "name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA" }, { "location": { "latitude": 407113723, "longitude": -749746483 }, "name": "" }, { "location": { "latitude": 402133926, "longitude": -743613249 }, "name": "" }, { "location": { "latitude": 400273442, "longitude": -741220915 }, "name": "" }, { "location": { "latitude": 411236786, "longitude": -744070769 }, "name": "" }, { "location": { "latitude": 411633782, "longitude": -746784970 }, "name": "211-225 Plains Road, Augusta, NJ 07822, USA" }, { "location": { "latitude": 415830701, "longitude": -742952812 }, "name": "" }, { "location": { "latitude": 413447164, "longitude": -748712898 }, "name": "165 Pedersen Ridge Road, Milford, PA 18337, USA" }, { "location": { "latitude": 405047245, "longitude": -749800722 }, "name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA" }, { "location": { "latitude": 418858923, "longitude": -746156790 }, "name": "" }, { "location": { "latitude": 417951888, "longitude": -748484944 }, "name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA" }, { "location": { "latitude": 407033786, "longitude": -743977337 }, "name": "26 East 3rd Street, New Providence, NJ 07974, USA" }, { "location": { "latitude": 417548014, "longitude": -740075041 }, "name": "" }, { "location": { "latitude": 410395868, "longitude": -744972325 }, "name": "" }, { "location": { "latitude": 404615353, "longitude": -745129803 }, "name": "" }, { "location": { "latitude": 406589790, "longitude": -743560121 }, "name": "611 Lawrence Avenue, Westfield, NJ 07090, USA" }, { "location": { "latitude": 414653148, "longitude": -740477477 }, "name": "18 Lannis Avenue, New Windsor, NY 12553, USA" }, { "location": { "latitude": 405957808, "longitude": -743255336 }, "name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA" }, { "location": { "latitude": 411733589, "longitude": -741648093 }, "name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA" }, { "location": { "latitude": 412676291, "longitude": -742606606 }, "name": "1270 Lakes Road, Monroe, NY 10950, USA" }, { "location": { "latitude": 409224445, "longitude": -748286738 }, "name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA" }, { "location": { "latitude": 406523420, "longitude": -742135517 }, "name": "652 Garden Street, Elizabeth, NJ 07202, USA" }, { "location": { "latitude": 401827388, "longitude": -740294537 }, "name": "349 Sea Spray Court, Neptune City, NJ 07753, USA" }, { "location": { "latitude": 410564152, "longitude": -743685054 }, "name": "13-17 Stanley Street, West Milford, NJ 07480, USA" }, { "location": { "latitude": 408472324, "longitude": -740726046 }, "name": "47 Industrial Avenue, Teterboro, NJ 07608, USA" }, { "location": { "latitude": 412452168, "longitude": -740214052 }, "name": "5 White Oak Lane, Stony Point, NY 10980, USA" }, { "location": { "latitude": 409146138, "longitude": -746188906 }, "name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA" }, { "location": { "latitude": 404701380, "longitude": -744781745 }, "name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA" }, { "location": { "latitude": 409642566, "longitude": -746017679 }, "name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA" }, { "location": { "latitude": 408031728, "longitude": -748645385 }, "name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA" }, { "location": { "latitude": 413700272, "longitude": -742135189 }, "name": "367 Prospect Road, Chester, NY 10918, USA" }, { "location": { "latitude": 404310607, "longitude": -740282632 }, "name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA" }, { "location": { "latitude": 409319800, "longitude": -746201391 }, "name": "11 Ward Street, Mount Arlington, NJ 07856, USA" }, { "location": { "latitude": 406685311, "longitude": -742108603 }, "name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA" }, { "location": { "latitude": 419018117, "longitude": -749142781 }, "name": "43 Dreher Road, Roscoe, NY 12776, USA" }, { "location": { "latitude": 412856162, "longitude": -745148837 }, "name": "Swan Street, Pine Island, NY 10969, USA" }, { "location": { "latitude": 416560744, "longitude": -746721964 }, "name": "66 Pleasantview Avenue, Monticello, NY 12701, USA" }, { "location": { "latitude": 405314270, "longitude": -749836354 }, "name": "" }, { "location": { "latitude": 414219548, "longitude": -743327440 }, "name": "" }, { "location": { "latitude": 415534177, "longitude": -742900616 }, "name": "565 Winding Hills Road, Montgomery, NY 12549, USA" }, { "location": { "latitude": 406898530, "longitude": -749127080 }, "name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA" }, { "location": { "latitude": 407586880, "longitude": -741670168 }, "name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA" }, { "location": { "latitude": 400106455, "longitude": -742870190 }, "name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA" }, { "location": { "latitude": 400066188, "longitude": -746793294 }, "name": "" }, { "location": { "latitude": 418803880, "longitude": -744102673 }, "name": "40 Mountain Road, Napanoch, NY 12458, USA" }, { "location": { "latitude": 414204288, "longitude": -747895140 }, "name": "" }, { "location": { "latitude": 414777405, "longitude": -740615601 }, "name": "" }, { "location": { "latitude": 415464475, "longitude": -747175374 }, "name": "48 North Road, Forestburgh, NY 12777, USA" }, { "location": { "latitude": 404062378, "longitude": -746376177 }, "name": "" }, { "location": { "latitude": 405688272, "longitude": -749285130 }, "name": "" }, { "location": { "latitude": 400342070, "longitude": -748788996 }, "name": "" }, { "location": { "latitude": 401809022, "longitude": -744157964 }, "name": "" }, { "location": { "latitude": 404226644, "longitude": -740517141 }, "name": "9 Thompson Avenue, Leonardo, NJ 07737, USA" }, { "location": { "latitude": 410322033, "longitude": -747871659 }, "name": "" }, { "location": { "latitude": 407100674, "longitude": -747742727 }, "name": "" }, { "location": { "latitude": 418811433, "longitude": -741718005 }, "name": "213 Bush Road, Stone Ridge, NY 12484, USA" }, { "location": { "latitude": 415034302, "longitude": -743850945 }, "name": "" }, { "location": { "latitude": 411349992, "longitude": -743694161 }, "name": "" }, { "location": { "latitude": 404839914, "longitude": -744759616 }, "name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA" }, { "location": { "latitude": 414638017, "longitude": -745957854 }, "name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA" }, { "location": { "latitude": 412127800, "longitude": -740173578 }, "name": "" }, { "location": { "latitude": 401263460, "longitude": -747964303 }, "name": "" }, { "location": { "latitude": 412843391, "longitude": -749086026 }, "name": "" }, { "location": { "latitude": 418512773, "longitude": -743067823 }, "name": "" }, { "location": { "latitude": 404318328, "longitude": -740835638 }, "name": "42-102 Main Street, Belford, NJ 07718, USA" }, { "location": { "latitude": 419020746, "longitude": -741172328 }, "name": "" }, { "location": { "latitude": 404080723, "longitude": -746119569 }, "name": "" }, { "location": { "latitude": 401012643, "longitude": -744035134 }, "name": "" }, { "location": { "latitude": 404306372, "longitude": -741079661 }, "name": "" }, { "location": { "latitude": 403966326, "longitude": -748519297 }, "name": "" }, { "location": { "latitude": 405002031, "longitude": -748407866 }, "name": "" }, { "location": { "latitude": 409532885, "longitude": -742200683 }, "name": "" }, { "location": { "latitude": 416851321, "longitude": -742674555 }, "name": "" }, { "location": { "latitude": 406411633, "longitude": -741722051 }, "name": "3387 Richmond Terrace, Staten Island, NY 10303, USA" }, { "location": { "latitude": 413069058, "longitude": -744597778 }, "name": "261 Van Sickle Road, Goshen, NY 10924, USA" }, { "location": { "latitude": 418465462, "longitude": -746859398 }, "name": "" }, { "location": { "latitude": 411733222, "longitude": -744228360 }, "name": "" }, { "location": { "latitude": 410248224, "longitude": -747127767 }, "name": "3 Hasta Way, Newton, NJ 07860, USA" }] grpc-1.3.2/examples/cpp/route_guide/route_guide_server.cc000066400000000000000000000150771310511640000235740ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include #include #include "helper.h" #include "route_guide.grpc.pb.h" using grpc::Server; using grpc::ServerBuilder; using grpc::ServerContext; using grpc::ServerReader; using grpc::ServerReaderWriter; using grpc::ServerWriter; using grpc::Status; using routeguide::Point; using routeguide::Feature; using routeguide::Rectangle; using routeguide::RouteSummary; using routeguide::RouteNote; using routeguide::RouteGuide; using std::chrono::system_clock; float ConvertToRadians(float num) { return num * 3.1415926 /180; } float GetDistance(const Point& start, const Point& end) { const float kCoordFactor = 10000000.0; float lat_1 = start.latitude() / kCoordFactor; float lat_2 = end.latitude() / kCoordFactor; float lon_1 = start.longitude() / kCoordFactor; float lon_2 = end.longitude() / kCoordFactor; float lat_rad_1 = ConvertToRadians(lat_1); float lat_rad_2 = ConvertToRadians(lat_2); float delta_lat_rad = ConvertToRadians(lat_2-lat_1); float delta_lon_rad = ConvertToRadians(lon_2-lon_1); float a = pow(sin(delta_lat_rad/2), 2) + cos(lat_rad_1) * cos(lat_rad_2) * pow(sin(delta_lon_rad/2), 2); float c = 2 * atan2(sqrt(a), sqrt(1-a)); int R = 6371000; // metres return R * c; } std::string GetFeatureName(const Point& point, const std::vector& feature_list) { for (const Feature& f : feature_list) { if (f.location().latitude() == point.latitude() && f.location().longitude() == point.longitude()) { return f.name(); } } return ""; } class RouteGuideImpl final : public RouteGuide::Service { public: explicit RouteGuideImpl(const std::string& db) { routeguide::ParseDb(db, &feature_list_); } Status GetFeature(ServerContext* context, const Point* point, Feature* feature) override { feature->set_name(GetFeatureName(*point, feature_list_)); feature->mutable_location()->CopyFrom(*point); return Status::OK; } Status ListFeatures(ServerContext* context, const routeguide::Rectangle* rectangle, ServerWriter* writer) override { auto lo = rectangle->lo(); auto hi = rectangle->hi(); long left = (std::min)(lo.longitude(), hi.longitude()); long right = (std::max)(lo.longitude(), hi.longitude()); long top = (std::max)(lo.latitude(), hi.latitude()); long bottom = (std::min)(lo.latitude(), hi.latitude()); for (const Feature& f : feature_list_) { if (f.location().longitude() >= left && f.location().longitude() <= right && f.location().latitude() >= bottom && f.location().latitude() <= top) { writer->Write(f); } } return Status::OK; } Status RecordRoute(ServerContext* context, ServerReader* reader, RouteSummary* summary) override { Point point; int point_count = 0; int feature_count = 0; float distance = 0.0; Point previous; system_clock::time_point start_time = system_clock::now(); while (reader->Read(&point)) { point_count++; if (!GetFeatureName(point, feature_list_).empty()) { feature_count++; } if (point_count != 1) { distance += GetDistance(previous, point); } previous = point; } system_clock::time_point end_time = system_clock::now(); summary->set_point_count(point_count); summary->set_feature_count(feature_count); summary->set_distance(static_cast(distance)); auto secs = std::chrono::duration_cast( end_time - start_time); summary->set_elapsed_time(secs.count()); return Status::OK; } Status RouteChat(ServerContext* context, ServerReaderWriter* stream) override { std::vector received_notes; RouteNote note; while (stream->Read(¬e)) { for (const RouteNote& n : received_notes) { if (n.location().latitude() == note.location().latitude() && n.location().longitude() == note.location().longitude()) { stream->Write(n); } } received_notes.push_back(note); } return Status::OK; } private: std::vector feature_list_; }; void RunServer(const std::string& db_path) { std::string server_address("0.0.0.0:50051"); RouteGuideImpl service(db_path); ServerBuilder builder; builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); builder.RegisterService(&service); std::unique_ptr server(builder.BuildAndStart()); std::cout << "Server listening on " << server_address << std::endl; server->Wait(); } int main(int argc, char** argv) { // Expect only arg: --db_path=path/to/route_guide_db.json. std::string db = routeguide::GetDbFileContent(argc, argv); RunServer(db); return 0; } grpc-1.3.2/examples/csharp/000077500000000000000000000000001310511640000155355ustar00rootroot00000000000000grpc-1.3.2/examples/csharp/.gitignore000066400000000000000000000000461310511640000175250ustar00rootroot00000000000000bin/ obj/ packages/ *.suo *.userprefs grpc-1.3.2/examples/csharp/helloworld-from-cli/000077500000000000000000000000001310511640000214165ustar00rootroot00000000000000grpc-1.3.2/examples/csharp/helloworld-from-cli/Greeter/000077500000000000000000000000001310511640000230135ustar00rootroot00000000000000grpc-1.3.2/examples/csharp/helloworld-from-cli/Greeter/Helloworld.cs000066400000000000000000000163311310511640000254610ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: helloworld.proto #pragma warning disable 1591, 0612, 3021 #region Designer generated code using pb = global::Google.Protobuf; using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; namespace Helloworld { ///

Holder for reflection information generated from helloworld.proto [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public static partial class HelloworldReflection { #region Descriptor /// File descriptor for helloworld.proto public static pbr::FileDescriptor Descriptor { get { return descriptor; } } private static pbr::FileDescriptor descriptor; static HelloworldReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "ChBoZWxsb3dvcmxkLnByb3RvEgpoZWxsb3dvcmxkIhwKDEhlbGxvUmVxdWVz", "dBIMCgRuYW1lGAEgASgJIh0KCkhlbGxvUmVwbHkSDwoHbWVzc2FnZRgBIAEo", "CTJJCgdHcmVldGVyEj4KCFNheUhlbGxvEhguaGVsbG93b3JsZC5IZWxsb1Jl", "cXVlc3QaFi5oZWxsb3dvcmxkLkhlbGxvUmVwbHkiAEI2Chtpby5ncnBjLmV4", "YW1wbGVzLmhlbGxvd29ybGRCD0hlbGxvV29ybGRQcm90b1ABogIDSExXYgZw", "cm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Helloworld.HelloRequest), global::Helloworld.HelloRequest.Parser, new[]{ "Name" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Helloworld.HelloReply), global::Helloworld.HelloReply.Parser, new[]{ "Message" }, null, null, null) })); } #endregion } #region Messages /// /// The request message containing the user's name. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public sealed partial class HelloRequest : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new HelloRequest()); public static pb::MessageParser Parser { get { return _parser; } } public static pbr::MessageDescriptor Descriptor { get { return global::Helloworld.HelloworldReflection.Descriptor.MessageTypes[0]; } } pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } public HelloRequest() { OnConstruction(); } partial void OnConstruction(); public HelloRequest(HelloRequest other) : this() { name_ = other.name_; } public HelloRequest Clone() { return new HelloRequest(this); } /// Field number for the "name" field. public const int NameFieldNumber = 1; private string name_ = ""; public string Name { get { return name_; } set { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } public override bool Equals(object other) { return Equals(other as HelloRequest); } public bool Equals(HelloRequest other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Name != other.Name) return false; return true; } public override int GetHashCode() { int hash = 1; if (Name.Length != 0) hash ^= Name.GetHashCode(); return hash; } public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); } } public int CalculateSize() { int size = 0; if (Name.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } return size; } public void MergeFrom(HelloRequest other) { if (other == null) { return; } if (other.Name.Length != 0) { Name = other.Name; } } public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { Name = input.ReadString(); break; } } } } } /// /// The response message containing the greetings /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public sealed partial class HelloReply : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new HelloReply()); public static pb::MessageParser Parser { get { return _parser; } } public static pbr::MessageDescriptor Descriptor { get { return global::Helloworld.HelloworldReflection.Descriptor.MessageTypes[1]; } } pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } public HelloReply() { OnConstruction(); } partial void OnConstruction(); public HelloReply(HelloReply other) : this() { message_ = other.message_; } public HelloReply Clone() { return new HelloReply(this); } /// Field number for the "message" field. public const int MessageFieldNumber = 1; private string message_ = ""; public string Message { get { return message_; } set { message_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } public override bool Equals(object other) { return Equals(other as HelloReply); } public bool Equals(HelloReply other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Message != other.Message) return false; return true; } public override int GetHashCode() { int hash = 1; if (Message.Length != 0) hash ^= Message.GetHashCode(); return hash; } public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { if (Message.Length != 0) { output.WriteRawTag(10); output.WriteString(Message); } } public int CalculateSize() { int size = 0; if (Message.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Message); } return size; } public void MergeFrom(HelloReply other) { if (other == null) { return; } if (other.Message.Length != 0) { Message = other.Message; } } public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { Message = input.ReadString(); break; } } } } } #endregion } #endregion Designer generated code grpc-1.3.2/examples/csharp/helloworld-from-cli/Greeter/HelloworldGrpc.cs000066400000000000000000000144001310511640000262700ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: helloworld.proto // Original file comments: // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #region Designer generated code using System; using System.Threading; using System.Threading.Tasks; using Grpc.Core; namespace Helloworld { /// /// The greeting service definition. /// public static class Greeter { static readonly string __ServiceName = "helloworld.Greeter"; static readonly Marshaller __Marshaller_HelloRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloRequest.Parser.ParseFrom); static readonly Marshaller __Marshaller_HelloReply = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloReply.Parser.ParseFrom); static readonly Method __Method_SayHello = new Method( MethodType.Unary, __ServiceName, "SayHello", __Marshaller_HelloRequest, __Marshaller_HelloReply); /// Service descriptor public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor { get { return global::Helloworld.HelloworldReflection.Descriptor.Services[0]; } } /// Base class for server-side implementations of Greeter public abstract class GreeterBase { /// /// Sends a greeting /// public virtual global::System.Threading.Tasks.Task SayHello(global::Helloworld.HelloRequest request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } } /// Client for Greeter public class GreeterClient : ClientBase { /// Creates a new client for Greeter /// The channel to use to make remote calls. public GreeterClient(Channel channel) : base(channel) { } /// Creates a new client for Greeter that uses a custom CallInvoker. /// The callInvoker to use to make remote calls. public GreeterClient(CallInvoker callInvoker) : base(callInvoker) { } /// Protected parameterless constructor to allow creation of test doubles. protected GreeterClient() : base() { } /// Protected constructor to allow creation of configured clients. /// The client configuration. protected GreeterClient(ClientBaseConfiguration configuration) : base(configuration) { } /// /// Sends a greeting /// public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return SayHello(request, new CallOptions(headers, deadline, cancellationToken)); } /// /// Sends a greeting /// public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, CallOptions options) { return CallInvoker.BlockingUnaryCall(__Method_SayHello, null, options, request); } /// /// Sends a greeting /// public virtual AsyncUnaryCall SayHelloAsync(global::Helloworld.HelloRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return SayHelloAsync(request, new CallOptions(headers, deadline, cancellationToken)); } /// /// Sends a greeting /// public virtual AsyncUnaryCall SayHelloAsync(global::Helloworld.HelloRequest request, CallOptions options) { return CallInvoker.AsyncUnaryCall(__Method_SayHello, null, options, request); } protected override GreeterClient NewInstance(ClientBaseConfiguration configuration) { return new GreeterClient(configuration); } } /// Creates service definition that can be registered with a server public static ServerServiceDefinition BindService(GreeterBase serviceImpl) { return ServerServiceDefinition.CreateBuilder() .AddMethod(__Method_SayHello, serviceImpl.SayHello).Build(); } } } #endregion grpc-1.3.2/examples/csharp/helloworld-from-cli/Greeter/project.json000066400000000000000000000011141310511640000253510ustar00rootroot00000000000000{ "title": "Greeter", "version": "1.0.0-*", "buildOptions": { "debugType": "portable", }, "dependencies": { "Google.Protobuf": "3.0.0", "Grpc": "1.0.1", }, "frameworks": { "net45": { "frameworkAssemblies": { "System.Runtime": "", "System.IO": "" }, "dependencies": { "Microsoft.NETCore.Platforms": "1.0.1" } }, "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", "version": "1.0.1" } }, "imports": "dnxcore50" } } } grpc-1.3.2/examples/csharp/helloworld-from-cli/GreeterClient/000077500000000000000000000000001310511640000241525ustar00rootroot00000000000000grpc-1.3.2/examples/csharp/helloworld-from-cli/GreeterClient/Program.cs000066400000000000000000000042161310511640000261130ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using System; using Grpc.Core; using Helloworld; namespace GreeterClient { class Program { public static void Main(string[] args) { Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure); var client = new Greeter.GreeterClient(channel); String user = "you"; var reply = client.SayHello(new HelloRequest { Name = user }); Console.WriteLine("Greeting: " + reply.Message); channel.ShutdownAsync().Wait(); Console.WriteLine("Press any key to exit..."); Console.ReadKey(); } } } grpc-1.3.2/examples/csharp/helloworld-from-cli/GreeterClient/project.json000066400000000000000000000012401310511640000265100ustar00rootroot00000000000000{ "title": "GreeterClient", "version": "1.0.0-*", "buildOptions": { "debugType": "portable", "emitEntryPoint": "true" }, "dependencies": { "Google.Protobuf": "3.0.0", "Grpc": "1.0.1", "Greeter": { "target": "project" } }, "frameworks": { "net45": { "frameworkAssemblies": { "System.Runtime": "", "System.IO": "" }, "dependencies": { "Microsoft.NETCore.Platforms": "1.0.1" } }, "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", "version": "1.0.1" } }, "imports": "dnxcore50" } } } grpc-1.3.2/examples/csharp/helloworld-from-cli/GreeterServer/000077500000000000000000000000001310511640000242025ustar00rootroot00000000000000grpc-1.3.2/examples/csharp/helloworld-from-cli/GreeterServer/Program.cs000066400000000000000000000050361310511640000261440ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using System; using System.Threading.Tasks; using Grpc.Core; using Helloworld; namespace GreeterServer { class GreeterImpl : Greeter.GreeterBase { // Server side handler of the SayHello RPC public override Task SayHello(HelloRequest request, ServerCallContext context) { return Task.FromResult(new HelloReply { Message = "Hello " + request.Name }); } } class Program { const int Port = 50051; public static void Main(string[] args) { Server server = new Server { Services = { Greeter.BindService(new GreeterImpl()) }, Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) } }; server.Start(); Console.WriteLine("Greeter server listening on port " + Port); Console.WriteLine("Press any key to stop the server..."); Console.ReadKey(); server.ShutdownAsync().Wait(); } } } grpc-1.3.2/examples/csharp/helloworld-from-cli/GreeterServer/project.json000066400000000000000000000012401310511640000265400ustar00rootroot00000000000000{ "title": "GreeterServer", "version": "1.0.0-*", "buildOptions": { "debugType": "portable", "emitEntryPoint": "true" }, "dependencies": { "Google.Protobuf": "3.0.0", "Grpc": "1.0.1", "Greeter": { "target": "project" } }, "frameworks": { "net45": { "frameworkAssemblies": { "System.Runtime": "", "System.IO": "" }, "dependencies": { "Microsoft.NETCore.Platforms": "1.0.1" } }, "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", "version": "1.0.1" } }, "imports": "dnxcore50" } } } grpc-1.3.2/examples/csharp/helloworld-from-cli/README.md000066400000000000000000000024431310511640000227000ustar00rootroot00000000000000gRPC in 3 minutes (C#) ======================== BACKGROUND ------------- This is a different version of the helloworld example, using the dotnet sdk tools to build and run. For this sample, we've already generated the server and client stubs from [helloworld.proto][]. Example projects in this directory depend on the [Grpc](https://www.nuget.org/packages/Grpc/) and [Google.Protobuf](https://www.nuget.org/packages/Google.Protobuf/) NuGet packages which have been already added to the project for you. The examples in this directory target .NET 4.5 framework, as .NET Core support is currently experimental. PREREQUISITES ------------- - The DotNetCore SDK cli. - The .NET 4.5 framework. Both are available to download at https://www.microsoft.com/net/download BUILD ------- From the `examples/csharp/helloworld-from-cli` directory: - `dotnet restore` - `dotnet build **/project.json` (this will automatically download NuGet dependencies) Try it! ------- - Run the server ``` > cd GreeterServer > dotnet run ``` - Run the client ``` > cd GreeterClient > dotnet run ``` Tutorial -------- You can find a more detailed tutorial about Grpc in [gRPC Basics: C#][] [helloworld.proto]:../../protos/helloworld.proto [gRPC Basics: C#]:http://www.grpc.io/docs/tutorials/basic/csharp.html grpc-1.3.2/examples/csharp/helloworld-from-cli/global.json000066400000000000000000000001011310511640000235410ustar00rootroot00000000000000{ "sdk": { "version": "1.0.0-preview2-003131" } }grpc-1.3.2/examples/csharp/helloworld/000077500000000000000000000000001310511640000177105ustar00rootroot00000000000000grpc-1.3.2/examples/csharp/helloworld/Greeter.sln000066400000000000000000000040031310511640000220200ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 VisualStudioVersion = 12.0.31101.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Greeter", "Greeter\Greeter.csproj", "{724DFC8C-4B57-4C3F-811C-0463BE2A2829}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreeterServer", "GreeterServer\GreeterServer.csproj", "{A7706C84-92D2-4B7A-B779-76B64D2950EC}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreeterClient", "GreeterClient\GreeterClient.csproj", "{ACCF4597-3748-4117-8633-1CB767F8CCC3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {724DFC8C-4B57-4C3F-811C-0463BE2A2829}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {724DFC8C-4B57-4C3F-811C-0463BE2A2829}.Debug|Any CPU.Build.0 = Debug|Any CPU {724DFC8C-4B57-4C3F-811C-0463BE2A2829}.Release|Any CPU.ActiveCfg = Release|Any CPU {724DFC8C-4B57-4C3F-811C-0463BE2A2829}.Release|Any CPU.Build.0 = Release|Any CPU {A7706C84-92D2-4B7A-B779-76B64D2950EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A7706C84-92D2-4B7A-B779-76B64D2950EC}.Debug|Any CPU.Build.0 = Debug|Any CPU {A7706C84-92D2-4B7A-B779-76B64D2950EC}.Release|Any CPU.ActiveCfg = Release|Any CPU {A7706C84-92D2-4B7A-B779-76B64D2950EC}.Release|Any CPU.Build.0 = Release|Any CPU {ACCF4597-3748-4117-8633-1CB767F8CCC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {ACCF4597-3748-4117-8633-1CB767F8CCC3}.Debug|Any CPU.Build.0 = Debug|Any CPU {ACCF4597-3748-4117-8633-1CB767F8CCC3}.Release|Any CPU.ActiveCfg = Release|Any CPU {ACCF4597-3748-4117-8633-1CB767F8CCC3}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution StartupItem = Greeter\Greeter.csproj EndGlobalSection EndGlobal grpc-1.3.2/examples/csharp/helloworld/Greeter/000077500000000000000000000000001310511640000213055ustar00rootroot00000000000000grpc-1.3.2/examples/csharp/helloworld/Greeter/.gitignore000066400000000000000000000000101310511640000232640ustar00rootroot00000000000000bin obj grpc-1.3.2/examples/csharp/helloworld/Greeter/Greeter.csproj000066400000000000000000000071401310511640000241260ustar00rootroot00000000000000 Debug AnyCPU 10.0.0 2.0 {724DFC8C-4B57-4C3F-811C-0463BE2A2829} Library Greeter Greeter v4.5 2669b4f2 true full false bin\Debug DEBUG; prompt 4 false full true bin\Release prompt 4 false False ..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll False ..\packages\Grpc.Core.1.0.1\lib\net45\Grpc.Core.dll False ..\packages\System.Interactive.Async.3.0.0\lib\net45\System.Interactive.Async.dll protos\helloworld.proto generate_protos.bat 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}. grpc-1.3.2/examples/csharp/helloworld/Greeter/Helloworld.cs000066400000000000000000000163311310511640000237530ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: helloworld.proto #pragma warning disable 1591, 0612, 3021 #region Designer generated code using pb = global::Google.Protobuf; using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; namespace Helloworld { /// Holder for reflection information generated from helloworld.proto [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public static partial class HelloworldReflection { #region Descriptor /// File descriptor for helloworld.proto public static pbr::FileDescriptor Descriptor { get { return descriptor; } } private static pbr::FileDescriptor descriptor; static HelloworldReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "ChBoZWxsb3dvcmxkLnByb3RvEgpoZWxsb3dvcmxkIhwKDEhlbGxvUmVxdWVz", "dBIMCgRuYW1lGAEgASgJIh0KCkhlbGxvUmVwbHkSDwoHbWVzc2FnZRgBIAEo", "CTJJCgdHcmVldGVyEj4KCFNheUhlbGxvEhguaGVsbG93b3JsZC5IZWxsb1Jl", "cXVlc3QaFi5oZWxsb3dvcmxkLkhlbGxvUmVwbHkiAEI2Chtpby5ncnBjLmV4", "YW1wbGVzLmhlbGxvd29ybGRCD0hlbGxvV29ybGRQcm90b1ABogIDSExXYgZw", "cm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Helloworld.HelloRequest), global::Helloworld.HelloRequest.Parser, new[]{ "Name" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Helloworld.HelloReply), global::Helloworld.HelloReply.Parser, new[]{ "Message" }, null, null, null) })); } #endregion } #region Messages /// /// The request message containing the user's name. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public sealed partial class HelloRequest : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new HelloRequest()); public static pb::MessageParser Parser { get { return _parser; } } public static pbr::MessageDescriptor Descriptor { get { return global::Helloworld.HelloworldReflection.Descriptor.MessageTypes[0]; } } pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } public HelloRequest() { OnConstruction(); } partial void OnConstruction(); public HelloRequest(HelloRequest other) : this() { name_ = other.name_; } public HelloRequest Clone() { return new HelloRequest(this); } /// Field number for the "name" field. public const int NameFieldNumber = 1; private string name_ = ""; public string Name { get { return name_; } set { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } public override bool Equals(object other) { return Equals(other as HelloRequest); } public bool Equals(HelloRequest other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Name != other.Name) return false; return true; } public override int GetHashCode() { int hash = 1; if (Name.Length != 0) hash ^= Name.GetHashCode(); return hash; } public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); } } public int CalculateSize() { int size = 0; if (Name.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } return size; } public void MergeFrom(HelloRequest other) { if (other == null) { return; } if (other.Name.Length != 0) { Name = other.Name; } } public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { Name = input.ReadString(); break; } } } } } /// /// The response message containing the greetings /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public sealed partial class HelloReply : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new HelloReply()); public static pb::MessageParser Parser { get { return _parser; } } public static pbr::MessageDescriptor Descriptor { get { return global::Helloworld.HelloworldReflection.Descriptor.MessageTypes[1]; } } pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } public HelloReply() { OnConstruction(); } partial void OnConstruction(); public HelloReply(HelloReply other) : this() { message_ = other.message_; } public HelloReply Clone() { return new HelloReply(this); } /// Field number for the "message" field. public const int MessageFieldNumber = 1; private string message_ = ""; public string Message { get { return message_; } set { message_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } public override bool Equals(object other) { return Equals(other as HelloReply); } public bool Equals(HelloReply other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Message != other.Message) return false; return true; } public override int GetHashCode() { int hash = 1; if (Message.Length != 0) hash ^= Message.GetHashCode(); return hash; } public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { if (Message.Length != 0) { output.WriteRawTag(10); output.WriteString(Message); } } public int CalculateSize() { int size = 0; if (Message.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Message); } return size; } public void MergeFrom(HelloReply other) { if (other == null) { return; } if (other.Message.Length != 0) { Message = other.Message; } } public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { Message = input.ReadString(); break; } } } } } #endregion } #endregion Designer generated code grpc-1.3.2/examples/csharp/helloworld/Greeter/HelloworldGrpc.cs000066400000000000000000000144001310511640000245620ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: helloworld.proto // Original file comments: // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #region Designer generated code using System; using System.Threading; using System.Threading.Tasks; using Grpc.Core; namespace Helloworld { /// /// The greeting service definition. /// public static class Greeter { static readonly string __ServiceName = "helloworld.Greeter"; static readonly Marshaller __Marshaller_HelloRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloRequest.Parser.ParseFrom); static readonly Marshaller __Marshaller_HelloReply = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloReply.Parser.ParseFrom); static readonly Method __Method_SayHello = new Method( MethodType.Unary, __ServiceName, "SayHello", __Marshaller_HelloRequest, __Marshaller_HelloReply); /// Service descriptor public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor { get { return global::Helloworld.HelloworldReflection.Descriptor.Services[0]; } } /// Base class for server-side implementations of Greeter public abstract class GreeterBase { /// /// Sends a greeting /// public virtual global::System.Threading.Tasks.Task SayHello(global::Helloworld.HelloRequest request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } } /// Client for Greeter public class GreeterClient : ClientBase { /// Creates a new client for Greeter /// The channel to use to make remote calls. public GreeterClient(Channel channel) : base(channel) { } /// Creates a new client for Greeter that uses a custom CallInvoker. /// The callInvoker to use to make remote calls. public GreeterClient(CallInvoker callInvoker) : base(callInvoker) { } /// Protected parameterless constructor to allow creation of test doubles. protected GreeterClient() : base() { } /// Protected constructor to allow creation of configured clients. /// The client configuration. protected GreeterClient(ClientBaseConfiguration configuration) : base(configuration) { } /// /// Sends a greeting /// public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return SayHello(request, new CallOptions(headers, deadline, cancellationToken)); } /// /// Sends a greeting /// public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, CallOptions options) { return CallInvoker.BlockingUnaryCall(__Method_SayHello, null, options, request); } /// /// Sends a greeting /// public virtual AsyncUnaryCall SayHelloAsync(global::Helloworld.HelloRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return SayHelloAsync(request, new CallOptions(headers, deadline, cancellationToken)); } /// /// Sends a greeting /// public virtual AsyncUnaryCall SayHelloAsync(global::Helloworld.HelloRequest request, CallOptions options) { return CallInvoker.AsyncUnaryCall(__Method_SayHello, null, options, request); } protected override GreeterClient NewInstance(ClientBaseConfiguration configuration) { return new GreeterClient(configuration); } } /// Creates service definition that can be registered with a server public static ServerServiceDefinition BindService(GreeterBase serviceImpl) { return ServerServiceDefinition.CreateBuilder() .AddMethod(__Method_SayHello, serviceImpl.SayHello).Build(); } } } #endregion grpc-1.3.2/examples/csharp/helloworld/Greeter/Properties/000077500000000000000000000000001310511640000234415ustar00rootroot00000000000000grpc-1.3.2/examples/csharp/helloworld/Greeter/Properties/AssemblyInfo.cs000066400000000000000000000050331310511640000263640ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; // Information about this assembly is defined by the following attributes. // Change them to the values specific to your project. [assembly: AssemblyTitle("Greeter")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("jtattermusch")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". // The form "{Major}.{Minor}.*" will automatically update the build and revision, // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("1.0.*")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. //[assembly: AssemblyDelaySign(false)] //[assembly: AssemblyKeyFile("")] grpc-1.3.2/examples/csharp/helloworld/Greeter/packages.config000066400000000000000000000006531310511640000242560ustar00rootroot00000000000000 grpc-1.3.2/examples/csharp/helloworld/GreeterClient/000077500000000000000000000000001310511640000224445ustar00rootroot00000000000000grpc-1.3.2/examples/csharp/helloworld/GreeterClient/.gitignore000066400000000000000000000000101310511640000244230ustar00rootroot00000000000000bin obj grpc-1.3.2/examples/csharp/helloworld/GreeterClient/GreeterClient.csproj000066400000000000000000000070621310511640000264270ustar00rootroot00000000000000 Debug AnyCPU 10.0.0 2.0 {ACCF4597-3748-4117-8633-1CB767F8CCC3} Exe GreeterClient GreeterClient v4.5 5e942a7d true full false bin\Debug DEBUG; prompt 4 true full true bin\Release prompt 4 true False ..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll False ..\packages\Grpc.Core.1.0.1\lib\net45\Grpc.Core.dll False ..\packages\System.Interactive.Async.3.0.0\lib\net45\System.Interactive.Async.dll {724DFC8C-4B57-4C3F-811C-0463BE2A2829} Greeter 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}. grpc-1.3.2/examples/csharp/helloworld/GreeterClient/Program.cs000066400000000000000000000042161310511640000244050ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using System; using Grpc.Core; using Helloworld; namespace GreeterClient { class Program { public static void Main(string[] args) { Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure); var client = new Greeter.GreeterClient(channel); String user = "you"; var reply = client.SayHello(new HelloRequest { Name = user }); Console.WriteLine("Greeting: " + reply.Message); channel.ShutdownAsync().Wait(); Console.WriteLine("Press any key to exit..."); Console.ReadKey(); } } } grpc-1.3.2/examples/csharp/helloworld/GreeterClient/Properties/000077500000000000000000000000001310511640000246005ustar00rootroot00000000000000grpc-1.3.2/examples/csharp/helloworld/GreeterClient/Properties/AssemblyInfo.cs000066400000000000000000000050411310511640000275220ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; // Information about this assembly is defined by the following attributes. // Change them to the values specific to your project. [assembly: AssemblyTitle("GreeterClient")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("jtattermusch")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". // The form "{Major}.{Minor}.*" will automatically update the build and revision, // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("1.0.*")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. //[assembly: AssemblyDelaySign(false)] //[assembly: AssemblyKeyFile("")] grpc-1.3.2/examples/csharp/helloworld/GreeterClient/packages.config000066400000000000000000000005451310511640000254150ustar00rootroot00000000000000 grpc-1.3.2/examples/csharp/helloworld/GreeterServer/000077500000000000000000000000001310511640000224745ustar00rootroot00000000000000grpc-1.3.2/examples/csharp/helloworld/GreeterServer/.gitignore000066400000000000000000000000101310511640000244530ustar00rootroot00000000000000bin obj grpc-1.3.2/examples/csharp/helloworld/GreeterServer/GreeterServer.csproj000066400000000000000000000070621310511640000265070ustar00rootroot00000000000000 Debug AnyCPU 10.0.0 2.0 {A7706C84-92D2-4B7A-B779-76B64D2950EC} Exe GreeterServer GreeterServer v4.5 9c7b2963 true full false bin\Debug DEBUG; prompt 4 true full true bin\Release prompt 4 true False ..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll False ..\packages\Grpc.Core.1.0.1\lib\net45\Grpc.Core.dll False ..\packages\System.Interactive.Async.3.0.0\lib\net45\System.Interactive.Async.dll {724DFC8C-4B57-4C3F-811C-0463BE2A2829} Greeter 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}. grpc-1.3.2/examples/csharp/helloworld/GreeterServer/Program.cs000066400000000000000000000050361310511640000244360ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using System; using System.Threading.Tasks; using Grpc.Core; using Helloworld; namespace GreeterServer { class GreeterImpl : Greeter.GreeterBase { // Server side handler of the SayHello RPC public override Task SayHello(HelloRequest request, ServerCallContext context) { return Task.FromResult(new HelloReply { Message = "Hello " + request.Name }); } } class Program { const int Port = 50051; public static void Main(string[] args) { Server server = new Server { Services = { Greeter.BindService(new GreeterImpl()) }, Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) } }; server.Start(); Console.WriteLine("Greeter server listening on port " + Port); Console.WriteLine("Press any key to stop the server..."); Console.ReadKey(); server.ShutdownAsync().Wait(); } } } grpc-1.3.2/examples/csharp/helloworld/GreeterServer/Properties/000077500000000000000000000000001310511640000246305ustar00rootroot00000000000000grpc-1.3.2/examples/csharp/helloworld/GreeterServer/Properties/AssemblyInfo.cs000066400000000000000000000050411310511640000275520ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; // Information about this assembly is defined by the following attributes. // Change them to the values specific to your project. [assembly: AssemblyTitle("GreeterServer")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("jtattermusch")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". // The form "{Major}.{Minor}.*" will automatically update the build and revision, // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("1.0.*")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. //[assembly: AssemblyDelaySign(false)] //[assembly: AssemblyKeyFile("")] grpc-1.3.2/examples/csharp/helloworld/GreeterServer/packages.config000066400000000000000000000005451310511640000254450ustar00rootroot00000000000000 grpc-1.3.2/examples/csharp/helloworld/README.md000066400000000000000000000037121310511640000211720ustar00rootroot00000000000000gRPC in 3 minutes (C#) ======================== BACKGROUND ------------- For this sample, we've already generated the server and client stubs from [helloworld.proto][]. Example projects depend on the [Grpc](https://www.nuget.org/packages/Grpc/), [Grpc.Tools](https://www.nuget.org/packages/Grpc.Tools/) and [Google.Protobuf](https://www.nuget.org/packages/Google.Protobuf/) NuGet packages which have been already added to the project for you. PREREQUISITES ------------- - Windows: .NET Framework 4.5+, Visual Studio 2013 or 2015 - Linux: Mono 4+, MonoDevelop 5.9+ - Mac OS X: Xamarin Studio 5.9+ BUILD ------- - Open solution `Greeter.sln` with Visual Studio, Monodevelop (on Linux) or Xamarin Studio (on Mac OS X) # Using Visual Studio * Build the solution (this will automatically download NuGet dependencies) # Using Monodevelop or Xamarin Studio The nuget add-in available for Xamarin Studio and Monodevelop IDEs is too old to download all of the nuget dependencies of gRPC. One alternative to is to use the dotnet command line tools instead (see [helloworld-from-cli]). Using these IDEs, a workaround is as follows: * Obtain a nuget executable for your platform and update it with `nuget update -self`. * Navigate to this directory and run `nuget restore`. * Now that packages have been restored into their proper package folder, build the solution from your IDE. Try it! ------- - Run the server ``` > cd GreeterServer/bin/Debug > GreeterServer.exe ``` - Run the client ``` > cd GreeterClient/bin/Debug > GreeterClient.exe ``` You can also run the server and client directly from the IDE. On Linux or Mac, use `mono GreeterServer.exe` and `mono GreeterClient.exe` to run the server and client. Tutorial -------- You can find a more detailed tutorial in [gRPC Basics: C#][] [helloworld-from-cli]:../helloworld-from-cli/README.md [helloworld.proto]:../../protos/helloworld.proto [gRPC Basics: C#]:http://www.grpc.io/docs/tutorials/basic/csharp.html grpc-1.3.2/examples/csharp/helloworld/generate_protos.bat000066400000000000000000000036331310511640000236050ustar00rootroot00000000000000@rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or without @rem modification, are permitted provided that the following conditions are @rem met: @rem @rem * Redistributions of source code must retain the above copyright @rem notice, this list of conditions and the following disclaimer. @rem * Redistributions in binary form must reproduce the above @rem copyright notice, this list of conditions and the following disclaimer @rem in the documentation and/or other materials provided with the @rem distribution. @rem * Neither the name of Google Inc. nor the names of its @rem contributors may be used to endorse or promote products derived from @rem this software without specific prior written permission. @rem @rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS @rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @rem A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT @rem OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, @rem SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT @rem LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, @rem DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY @rem THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT @rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE @rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @rem Generate the C# code for .proto files setlocal @rem enter this directory cd /d %~dp0 set TOOLS_PATH=packages\Grpc.Tools.1.0.1\tools\windows_x86 %TOOLS_PATH%\protoc.exe -I../../protos --csharp_out Greeter ../../protos/helloworld.proto --grpc_out Greeter --plugin=protoc-gen-grpc=%TOOLS_PATH%\grpc_csharp_plugin.exe endlocal grpc-1.3.2/examples/csharp/route_guide/000077500000000000000000000000001310511640000200505ustar00rootroot00000000000000grpc-1.3.2/examples/csharp/route_guide/.gitignore000066400000000000000000000000461310511640000220400ustar00rootroot00000000000000bin/ obj/ packages/ *.suo *.userprefs grpc-1.3.2/examples/csharp/route_guide/README.md000066400000000000000000000003251310511640000213270ustar00rootroot00000000000000#gRPC Basics: C# sample code The files in this folder are the samples used in [gRPC Basics: C#][], a detailed tutorial for using gRPC in C#. [gRPC Basics: C#]:http://www.grpc.io/docs/tutorials/basic/csharp.html grpc-1.3.2/examples/csharp/route_guide/RouteGuide.sln000066400000000000000000000036611310511640000226500ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 VisualStudioVersion = 12.0.31101.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RouteGuide", "RouteGuide\RouteGuide.csproj", "{49954D9C-5F17-4662-96B2-73BE833DD81A}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RouteGuideClient", "RouteGuideClient\RouteGuideClient.csproj", "{D47BE663-4DE3-4206-B7A8-EA3FA066DADC}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RouteGuideServer", "RouteGuideServer\RouteGuideServer.csproj", "{4B7C7794-BE24-4477-ACE7-18259EB73D27}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {49954D9C-5F17-4662-96B2-73BE833DD81A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {49954D9C-5F17-4662-96B2-73BE833DD81A}.Debug|Any CPU.Build.0 = Debug|Any CPU {49954D9C-5F17-4662-96B2-73BE833DD81A}.Release|Any CPU.ActiveCfg = Release|Any CPU {49954D9C-5F17-4662-96B2-73BE833DD81A}.Release|Any CPU.Build.0 = Release|Any CPU {D47BE663-4DE3-4206-B7A8-EA3FA066DADC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D47BE663-4DE3-4206-B7A8-EA3FA066DADC}.Debug|Any CPU.Build.0 = Debug|Any CPU {D47BE663-4DE3-4206-B7A8-EA3FA066DADC}.Release|Any CPU.ActiveCfg = Release|Any CPU {D47BE663-4DE3-4206-B7A8-EA3FA066DADC}.Release|Any CPU.Build.0 = Release|Any CPU {4B7C7794-BE24-4477-ACE7-18259EB73D27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4B7C7794-BE24-4477-ACE7-18259EB73D27}.Debug|Any CPU.Build.0 = Debug|Any CPU {4B7C7794-BE24-4477-ACE7-18259EB73D27}.Release|Any CPU.ActiveCfg = Release|Any CPU {4B7C7794-BE24-4477-ACE7-18259EB73D27}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal grpc-1.3.2/examples/csharp/route_guide/RouteGuide/000077500000000000000000000000001310511640000221245ustar00rootroot00000000000000grpc-1.3.2/examples/csharp/route_guide/RouteGuide/Properties/000077500000000000000000000000001310511640000242605ustar00rootroot00000000000000grpc-1.3.2/examples/csharp/route_guide/RouteGuide/Properties/AssemblyInfo.cs000066400000000000000000000056731310511640000272150ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("RouteGuide")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("RouteGuide")] [assembly: AssemblyCopyright("Copyright © 2015")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("ef6b85bc-ac27-46de-8714-a658236cc6fb")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] grpc-1.3.2/examples/csharp/route_guide/RouteGuide/RouteGuide.cs000066400000000000000000000711761310511640000245430ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: route_guide.proto #pragma warning disable 1591, 0612, 3021 #region Designer generated code using pb = global::Google.Protobuf; using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; namespace Routeguide { /// Holder for reflection information generated from route_guide.proto public static partial class RouteGuideReflection { #region Descriptor /// File descriptor for route_guide.proto public static pbr::FileDescriptor Descriptor { get { return descriptor; } } private static pbr::FileDescriptor descriptor; static RouteGuideReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "ChFyb3V0ZV9ndWlkZS5wcm90bxIKcm91dGVndWlkZSIsCgVQb2ludBIQCghs", "YXRpdHVkZRgBIAEoBRIRCglsb25naXR1ZGUYAiABKAUiSQoJUmVjdGFuZ2xl", "Eh0KAmxvGAEgASgLMhEucm91dGVndWlkZS5Qb2ludBIdCgJoaRgCIAEoCzIR", "LnJvdXRlZ3VpZGUuUG9pbnQiPAoHRmVhdHVyZRIMCgRuYW1lGAEgASgJEiMK", "CGxvY2F0aW9uGAIgASgLMhEucm91dGVndWlkZS5Qb2ludCJBCglSb3V0ZU5v", "dGUSIwoIbG9jYXRpb24YASABKAsyES5yb3V0ZWd1aWRlLlBvaW50Eg8KB21l", "c3NhZ2UYAiABKAkiYgoMUm91dGVTdW1tYXJ5EhMKC3BvaW50X2NvdW50GAEg", "ASgFEhUKDWZlYXR1cmVfY291bnQYAiABKAUSEAoIZGlzdGFuY2UYAyABKAUS", "FAoMZWxhcHNlZF90aW1lGAQgASgFMoUCCgpSb3V0ZUd1aWRlEjYKCkdldEZl", "YXR1cmUSES5yb3V0ZWd1aWRlLlBvaW50GhMucm91dGVndWlkZS5GZWF0dXJl", "IgASPgoMTGlzdEZlYXR1cmVzEhUucm91dGVndWlkZS5SZWN0YW5nbGUaEy5y", "b3V0ZWd1aWRlLkZlYXR1cmUiADABEj4KC1JlY29yZFJvdXRlEhEucm91dGVn", "dWlkZS5Qb2ludBoYLnJvdXRlZ3VpZGUuUm91dGVTdW1tYXJ5IgAoARI/CglS", "b3V0ZUNoYXQSFS5yb3V0ZWd1aWRlLlJvdXRlTm90ZRoVLnJvdXRlZ3VpZGUu", "Um91dGVOb3RlIgAoATABQjYKG2lvLmdycGMuZXhhbXBsZXMucm91dGVndWlk", "ZUIPUm91dGVHdWlkZVByb3RvUAGiAgNSVEdiBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Routeguide.Point), global::Routeguide.Point.Parser, new[]{ "Latitude", "Longitude" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Routeguide.Rectangle), global::Routeguide.Rectangle.Parser, new[]{ "Lo", "Hi" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Routeguide.Feature), global::Routeguide.Feature.Parser, new[]{ "Name", "Location" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Routeguide.RouteNote), global::Routeguide.RouteNote.Parser, new[]{ "Location", "Message" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Routeguide.RouteSummary), global::Routeguide.RouteSummary.Parser, new[]{ "PointCount", "FeatureCount", "Distance", "ElapsedTime" }, null, null, null) })); } #endregion } #region Messages /// /// Points are represented as latitude-longitude pairs in the E7 representation /// (degrees multiplied by 10**7 and rounded to the nearest integer). /// Latitudes should be in the range +/- 90 degrees and longitude should be in /// the range +/- 180 degrees (inclusive). /// public sealed partial class Point : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Point()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Routeguide.RouteGuideReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Point() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Point(Point other) : this() { latitude_ = other.latitude_; longitude_ = other.longitude_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Point Clone() { return new Point(this); } /// Field number for the "latitude" field. public const int LatitudeFieldNumber = 1; private int latitude_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int Latitude { get { return latitude_; } set { latitude_ = value; } } /// Field number for the "longitude" field. public const int LongitudeFieldNumber = 2; private int longitude_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int Longitude { get { return longitude_; } set { longitude_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as Point); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(Point other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Latitude != other.Latitude) return false; if (Longitude != other.Longitude) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Latitude != 0) hash ^= Latitude.GetHashCode(); if (Longitude != 0) hash ^= Longitude.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Latitude != 0) { output.WriteRawTag(8); output.WriteInt32(Latitude); } if (Longitude != 0) { output.WriteRawTag(16); output.WriteInt32(Longitude); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Latitude != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(Latitude); } if (Longitude != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(Longitude); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(Point other) { if (other == null) { return; } if (other.Latitude != 0) { Latitude = other.Latitude; } if (other.Longitude != 0) { Longitude = other.Longitude; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { Latitude = input.ReadInt32(); break; } case 16: { Longitude = input.ReadInt32(); break; } } } } } /// /// A latitude-longitude rectangle, represented as two diagonally opposite /// points "lo" and "hi". /// public sealed partial class Rectangle : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Rectangle()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Routeguide.RouteGuideReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Rectangle() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Rectangle(Rectangle other) : this() { Lo = other.lo_ != null ? other.Lo.Clone() : null; Hi = other.hi_ != null ? other.Hi.Clone() : null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Rectangle Clone() { return new Rectangle(this); } /// Field number for the "lo" field. public const int LoFieldNumber = 1; private global::Routeguide.Point lo_; /// /// One corner of the rectangle. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Routeguide.Point Lo { get { return lo_; } set { lo_ = value; } } /// Field number for the "hi" field. public const int HiFieldNumber = 2; private global::Routeguide.Point hi_; /// /// The other corner of the rectangle. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Routeguide.Point Hi { get { return hi_; } set { hi_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as Rectangle); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(Rectangle other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (!object.Equals(Lo, other.Lo)) return false; if (!object.Equals(Hi, other.Hi)) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (lo_ != null) hash ^= Lo.GetHashCode(); if (hi_ != null) hash ^= Hi.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (lo_ != null) { output.WriteRawTag(10); output.WriteMessage(Lo); } if (hi_ != null) { output.WriteRawTag(18); output.WriteMessage(Hi); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (lo_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Lo); } if (hi_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Hi); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(Rectangle other) { if (other == null) { return; } if (other.lo_ != null) { if (lo_ == null) { lo_ = new global::Routeguide.Point(); } Lo.MergeFrom(other.Lo); } if (other.hi_ != null) { if (hi_ == null) { hi_ = new global::Routeguide.Point(); } Hi.MergeFrom(other.Hi); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { if (lo_ == null) { lo_ = new global::Routeguide.Point(); } input.ReadMessage(lo_); break; } case 18: { if (hi_ == null) { hi_ = new global::Routeguide.Point(); } input.ReadMessage(hi_); break; } } } } } /// /// A feature names something at a given point. /// /// If a feature could not be named, the name is empty. /// public sealed partial class Feature : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Feature()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Routeguide.RouteGuideReflection.Descriptor.MessageTypes[2]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Feature() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Feature(Feature other) : this() { name_ = other.name_; Location = other.location_ != null ? other.Location.Clone() : null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Feature Clone() { return new Feature(this); } /// Field number for the "name" field. public const int NameFieldNumber = 1; private string name_ = ""; /// /// The name of the feature. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Name { get { return name_; } set { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Field number for the "location" field. public const int LocationFieldNumber = 2; private global::Routeguide.Point location_; /// /// The point where the feature is detected. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Routeguide.Point Location { get { return location_; } set { location_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as Feature); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(Feature other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Name != other.Name) return false; if (!object.Equals(Location, other.Location)) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Name.Length != 0) hash ^= Name.GetHashCode(); if (location_ != null) hash ^= Location.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); } if (location_ != null) { output.WriteRawTag(18); output.WriteMessage(Location); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Name.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } if (location_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Location); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(Feature other) { if (other == null) { return; } if (other.Name.Length != 0) { Name = other.Name; } if (other.location_ != null) { if (location_ == null) { location_ = new global::Routeguide.Point(); } Location.MergeFrom(other.Location); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { Name = input.ReadString(); break; } case 18: { if (location_ == null) { location_ = new global::Routeguide.Point(); } input.ReadMessage(location_); break; } } } } } /// /// A RouteNote is a message sent while at a given point. /// public sealed partial class RouteNote : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new RouteNote()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Routeguide.RouteGuideReflection.Descriptor.MessageTypes[3]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public RouteNote() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public RouteNote(RouteNote other) : this() { Location = other.location_ != null ? other.Location.Clone() : null; message_ = other.message_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public RouteNote Clone() { return new RouteNote(this); } /// Field number for the "location" field. public const int LocationFieldNumber = 1; private global::Routeguide.Point location_; /// /// The location from which the message is sent. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Routeguide.Point Location { get { return location_; } set { location_ = value; } } /// Field number for the "message" field. public const int MessageFieldNumber = 2; private string message_ = ""; /// /// The message to be sent. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Message { get { return message_; } set { message_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as RouteNote); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(RouteNote other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (!object.Equals(Location, other.Location)) return false; if (Message != other.Message) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (location_ != null) hash ^= Location.GetHashCode(); if (Message.Length != 0) hash ^= Message.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (location_ != null) { output.WriteRawTag(10); output.WriteMessage(Location); } if (Message.Length != 0) { output.WriteRawTag(18); output.WriteString(Message); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (location_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Location); } if (Message.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Message); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(RouteNote other) { if (other == null) { return; } if (other.location_ != null) { if (location_ == null) { location_ = new global::Routeguide.Point(); } Location.MergeFrom(other.Location); } if (other.Message.Length != 0) { Message = other.Message; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { if (location_ == null) { location_ = new global::Routeguide.Point(); } input.ReadMessage(location_); break; } case 18: { Message = input.ReadString(); break; } } } } } /// /// A RouteSummary is received in response to a RecordRoute rpc. /// /// It contains the number of individual points received, the number of /// detected features, and the total distance covered as the cumulative sum of /// the distance between each point. /// public sealed partial class RouteSummary : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new RouteSummary()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Routeguide.RouteGuideReflection.Descriptor.MessageTypes[4]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public RouteSummary() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public RouteSummary(RouteSummary other) : this() { pointCount_ = other.pointCount_; featureCount_ = other.featureCount_; distance_ = other.distance_; elapsedTime_ = other.elapsedTime_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public RouteSummary Clone() { return new RouteSummary(this); } /// Field number for the "point_count" field. public const int PointCountFieldNumber = 1; private int pointCount_; /// /// The number of points received. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int PointCount { get { return pointCount_; } set { pointCount_ = value; } } /// Field number for the "feature_count" field. public const int FeatureCountFieldNumber = 2; private int featureCount_; /// /// The number of known features passed while traversing the route. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int FeatureCount { get { return featureCount_; } set { featureCount_ = value; } } /// Field number for the "distance" field. public const int DistanceFieldNumber = 3; private int distance_; /// /// The distance covered in metres. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int Distance { get { return distance_; } set { distance_ = value; } } /// Field number for the "elapsed_time" field. public const int ElapsedTimeFieldNumber = 4; private int elapsedTime_; /// /// The duration of the traversal in seconds. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int ElapsedTime { get { return elapsedTime_; } set { elapsedTime_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as RouteSummary); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(RouteSummary other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (PointCount != other.PointCount) return false; if (FeatureCount != other.FeatureCount) return false; if (Distance != other.Distance) return false; if (ElapsedTime != other.ElapsedTime) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (PointCount != 0) hash ^= PointCount.GetHashCode(); if (FeatureCount != 0) hash ^= FeatureCount.GetHashCode(); if (Distance != 0) hash ^= Distance.GetHashCode(); if (ElapsedTime != 0) hash ^= ElapsedTime.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (PointCount != 0) { output.WriteRawTag(8); output.WriteInt32(PointCount); } if (FeatureCount != 0) { output.WriteRawTag(16); output.WriteInt32(FeatureCount); } if (Distance != 0) { output.WriteRawTag(24); output.WriteInt32(Distance); } if (ElapsedTime != 0) { output.WriteRawTag(32); output.WriteInt32(ElapsedTime); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (PointCount != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(PointCount); } if (FeatureCount != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(FeatureCount); } if (Distance != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(Distance); } if (ElapsedTime != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(ElapsedTime); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(RouteSummary other) { if (other == null) { return; } if (other.PointCount != 0) { PointCount = other.PointCount; } if (other.FeatureCount != 0) { FeatureCount = other.FeatureCount; } if (other.Distance != 0) { Distance = other.Distance; } if (other.ElapsedTime != 0) { ElapsedTime = other.ElapsedTime; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { PointCount = input.ReadInt32(); break; } case 16: { FeatureCount = input.ReadInt32(); break; } case 24: { Distance = input.ReadInt32(); break; } case 32: { ElapsedTime = input.ReadInt32(); break; } } } } } #endregion } #endregion Designer generated code grpc-1.3.2/examples/csharp/route_guide/RouteGuide/RouteGuide.csproj000066400000000000000000000113461310511640000254270ustar00rootroot00000000000000 Debug AnyCPU {49954D9C-5F17-4662-96B2-73BE833DD81A} Library Properties RouteGuide RouteGuide v4.5 512 de2137f9 true full false bin\Debug\ DEBUG;TRACE prompt 4 pdbonly true bin\Release\ TRACE prompt 4 False ..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll False ..\packages\Grpc.Core.1.0.1\lib\net45\Grpc.Core.dll False ..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll False ..\packages\System.Interactive.Async.3.0.0\lib\net45\System.Interactive.Async.dll protos\route_guide.proto generate_protos.bat PreserveNewest 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}. grpc-1.3.2/examples/csharp/route_guide/RouteGuide/RouteGuideGrpc.cs000066400000000000000000000337451310511640000253570ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: route_guide.proto // Original file comments: // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #region Designer generated code using System; using System.Threading; using System.Threading.Tasks; using Grpc.Core; namespace Routeguide { /// /// Interface exported by the server. /// public static class RouteGuide { static readonly string __ServiceName = "routeguide.RouteGuide"; static readonly Marshaller __Marshaller_Point = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Routeguide.Point.Parser.ParseFrom); static readonly Marshaller __Marshaller_Feature = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Routeguide.Feature.Parser.ParseFrom); static readonly Marshaller __Marshaller_Rectangle = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Routeguide.Rectangle.Parser.ParseFrom); static readonly Marshaller __Marshaller_RouteSummary = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Routeguide.RouteSummary.Parser.ParseFrom); static readonly Marshaller __Marshaller_RouteNote = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Routeguide.RouteNote.Parser.ParseFrom); static readonly Method __Method_GetFeature = new Method( MethodType.Unary, __ServiceName, "GetFeature", __Marshaller_Point, __Marshaller_Feature); static readonly Method __Method_ListFeatures = new Method( MethodType.ServerStreaming, __ServiceName, "ListFeatures", __Marshaller_Rectangle, __Marshaller_Feature); static readonly Method __Method_RecordRoute = new Method( MethodType.ClientStreaming, __ServiceName, "RecordRoute", __Marshaller_Point, __Marshaller_RouteSummary); static readonly Method __Method_RouteChat = new Method( MethodType.DuplexStreaming, __ServiceName, "RouteChat", __Marshaller_RouteNote, __Marshaller_RouteNote); /// Service descriptor public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor { get { return global::Routeguide.RouteGuideReflection.Descriptor.Services[0]; } } /// Base class for server-side implementations of RouteGuide public abstract class RouteGuideBase { /// /// A simple RPC. /// /// Obtains the feature at a given position. /// /// A feature with an empty name is returned if there's no feature at the given /// position. /// public virtual global::System.Threading.Tasks.Task GetFeature(global::Routeguide.Point request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } /// /// A server-to-client streaming RPC. /// /// Obtains the Features available within the given Rectangle. Results are /// streamed rather than returned at once (e.g. in a response message with a /// repeated field), as the rectangle may cover a large area and contain a /// huge number of features. /// public virtual global::System.Threading.Tasks.Task ListFeatures(global::Routeguide.Rectangle request, IServerStreamWriter responseStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } /// /// A client-to-server streaming RPC. /// /// Accepts a stream of Points on a route being traversed, returning a /// RouteSummary when traversal is completed. /// public virtual global::System.Threading.Tasks.Task RecordRoute(IAsyncStreamReader requestStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } /// /// A Bidirectional streaming RPC. /// /// Accepts a stream of RouteNotes sent while a route is being traversed, /// while receiving other RouteNotes (e.g. from other users). /// public virtual global::System.Threading.Tasks.Task RouteChat(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } } /// Client for RouteGuide public class RouteGuideClient : ClientBase { /// Creates a new client for RouteGuide /// The channel to use to make remote calls. public RouteGuideClient(Channel channel) : base(channel) { } /// Creates a new client for RouteGuide that uses a custom CallInvoker. /// The callInvoker to use to make remote calls. public RouteGuideClient(CallInvoker callInvoker) : base(callInvoker) { } /// Protected parameterless constructor to allow creation of test doubles. protected RouteGuideClient() : base() { } /// Protected constructor to allow creation of configured clients. /// The client configuration. protected RouteGuideClient(ClientBaseConfiguration configuration) : base(configuration) { } /// /// A simple RPC. /// /// Obtains the feature at a given position. /// /// A feature with an empty name is returned if there's no feature at the given /// position. /// public virtual global::Routeguide.Feature GetFeature(global::Routeguide.Point request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return GetFeature(request, new CallOptions(headers, deadline, cancellationToken)); } /// /// A simple RPC. /// /// Obtains the feature at a given position. /// /// A feature with an empty name is returned if there's no feature at the given /// position. /// public virtual global::Routeguide.Feature GetFeature(global::Routeguide.Point request, CallOptions options) { return CallInvoker.BlockingUnaryCall(__Method_GetFeature, null, options, request); } /// /// A simple RPC. /// /// Obtains the feature at a given position. /// /// A feature with an empty name is returned if there's no feature at the given /// position. /// public virtual AsyncUnaryCall GetFeatureAsync(global::Routeguide.Point request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return GetFeatureAsync(request, new CallOptions(headers, deadline, cancellationToken)); } /// /// A simple RPC. /// /// Obtains the feature at a given position. /// /// A feature with an empty name is returned if there's no feature at the given /// position. /// public virtual AsyncUnaryCall GetFeatureAsync(global::Routeguide.Point request, CallOptions options) { return CallInvoker.AsyncUnaryCall(__Method_GetFeature, null, options, request); } /// /// A server-to-client streaming RPC. /// /// Obtains the Features available within the given Rectangle. Results are /// streamed rather than returned at once (e.g. in a response message with a /// repeated field), as the rectangle may cover a large area and contain a /// huge number of features. /// public virtual AsyncServerStreamingCall ListFeatures(global::Routeguide.Rectangle request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return ListFeatures(request, new CallOptions(headers, deadline, cancellationToken)); } /// /// A server-to-client streaming RPC. /// /// Obtains the Features available within the given Rectangle. Results are /// streamed rather than returned at once (e.g. in a response message with a /// repeated field), as the rectangle may cover a large area and contain a /// huge number of features. /// public virtual AsyncServerStreamingCall ListFeatures(global::Routeguide.Rectangle request, CallOptions options) { return CallInvoker.AsyncServerStreamingCall(__Method_ListFeatures, null, options, request); } /// /// A client-to-server streaming RPC. /// /// Accepts a stream of Points on a route being traversed, returning a /// RouteSummary when traversal is completed. /// public virtual AsyncClientStreamingCall RecordRoute(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return RecordRoute(new CallOptions(headers, deadline, cancellationToken)); } /// /// A client-to-server streaming RPC. /// /// Accepts a stream of Points on a route being traversed, returning a /// RouteSummary when traversal is completed. /// public virtual AsyncClientStreamingCall RecordRoute(CallOptions options) { return CallInvoker.AsyncClientStreamingCall(__Method_RecordRoute, null, options); } /// /// A Bidirectional streaming RPC. /// /// Accepts a stream of RouteNotes sent while a route is being traversed, /// while receiving other RouteNotes (e.g. from other users). /// public virtual AsyncDuplexStreamingCall RouteChat(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return RouteChat(new CallOptions(headers, deadline, cancellationToken)); } /// /// A Bidirectional streaming RPC. /// /// Accepts a stream of RouteNotes sent while a route is being traversed, /// while receiving other RouteNotes (e.g. from other users). /// public virtual AsyncDuplexStreamingCall RouteChat(CallOptions options) { return CallInvoker.AsyncDuplexStreamingCall(__Method_RouteChat, null, options); } protected override RouteGuideClient NewInstance(ClientBaseConfiguration configuration) { return new RouteGuideClient(configuration); } } /// Creates service definition that can be registered with a server public static ServerServiceDefinition BindService(RouteGuideBase serviceImpl) { return ServerServiceDefinition.CreateBuilder() .AddMethod(__Method_GetFeature, serviceImpl.GetFeature) .AddMethod(__Method_ListFeatures, serviceImpl.ListFeatures) .AddMethod(__Method_RecordRoute, serviceImpl.RecordRoute) .AddMethod(__Method_RouteChat, serviceImpl.RouteChat).Build(); } } } #endregion grpc-1.3.2/examples/csharp/route_guide/RouteGuide/RouteGuideUtil.cs000066400000000000000000000125351310511640000253730ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Routeguide { /// /// Utility methods for the route guide example. /// public static class RouteGuideUtil { public const string DefaultFeaturesFile = "route_guide_db.json"; private const double CoordFactor = 1e7; /// /// Indicates whether the given feature exists (i.e. has a valid name). /// public static bool Exists(this Feature feature) { return feature != null && (feature.Name.Length != 0); } public static double GetLatitude(this Point point) { return point.Latitude / CoordFactor; } public static double GetLongitude(this Point point) { return point.Longitude / CoordFactor; } /// /// Calculate the distance between two points using the "haversine" formula. /// This code was taken from http://www.movable-type.co.uk/scripts/latlong.html. /// /// the starting point /// the end point /// the distance between the points in meters public static double GetDistance(this Point start, Point end) { double lat1 = start.GetLatitude(); double lat2 = end.GetLatitude(); double lon1 = start.GetLongitude(); double lon2 = end.GetLongitude(); int r = 6371000; // metres double phi1 = ToRadians(lat1); double phi2 = ToRadians(lat2); double deltaPhi = ToRadians(lat2 - lat1); double deltaLambda = ToRadians(lon2 - lon1); double a = Math.Sin(deltaPhi / 2) * Math.Sin(deltaPhi / 2) + Math.Cos(phi1) * Math.Cos(phi2) * Math.Sin(deltaLambda / 2) * Math.Sin(deltaLambda / 2); double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a)); return r * c; } /// /// Returns true if rectangular area contains given point. /// public static bool Contains(this Rectangle rectangle, Point point) { int left = Math.Min(rectangle.Lo.Longitude, rectangle.Hi.Longitude); int right = Math.Max(rectangle.Lo.Longitude, rectangle.Hi.Longitude); int top = Math.Max(rectangle.Lo.Latitude, rectangle.Hi.Latitude); int bottom = Math.Min(rectangle.Lo.Latitude, rectangle.Hi.Latitude); return (point.Longitude >= left && point.Longitude <= right && point.Latitude >= bottom && point.Latitude <= top); } private static double ToRadians(double val) { return (Math.PI / 180) * val; } /// /// Parses features from a JSON file. /// public static List ParseFeatures(string filename) { var features = new List(); var jsonFeatures = JsonConvert.DeserializeObject>(File.ReadAllText(filename)); foreach(var jsonFeature in jsonFeatures) { features.Add(new Feature { Name = jsonFeature.name, Location = new Point { Longitude = jsonFeature.location.longitude, Latitude = jsonFeature.location.latitude} }); } return features; } private class JsonFeature { public string name; public JsonLocation location; } private class JsonLocation { public int longitude; public int latitude; } } } grpc-1.3.2/examples/csharp/route_guide/RouteGuide/packages.config000066400000000000000000000006601310511640000250730ustar00rootroot00000000000000 grpc-1.3.2/examples/csharp/route_guide/RouteGuide/route_guide_db.json000066400000000000000000000327121310511640000260040ustar00rootroot00000000000000[{ "location": { "latitude": 407838351, "longitude": -746143763 }, "name": "Patriots Path, Mendham, NJ 07945, USA" }, { "location": { "latitude": 408122808, "longitude": -743999179 }, "name": "101 New Jersey 10, Whippany, NJ 07981, USA" }, { "location": { "latitude": 413628156, "longitude": -749015468 }, "name": "U.S. 6, Shohola, PA 18458, USA" }, { "location": { "latitude": 419999544, "longitude": -740371136 }, "name": "5 Conners Road, Kingston, NY 12401, USA" }, { "location": { "latitude": 414008389, "longitude": -743951297 }, "name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA" }, { "location": { "latitude": 419611318, "longitude": -746524769 }, "name": "287 Flugertown Road, Livingston Manor, NY 12758, USA" }, { "location": { "latitude": 406109563, "longitude": -742186778 }, "name": "4001 Tremley Point Road, Linden, NJ 07036, USA" }, { "location": { "latitude": 416802456, "longitude": -742370183 }, "name": "352 South Mountain Road, Wallkill, NY 12589, USA" }, { "location": { "latitude": 412950425, "longitude": -741077389 }, "name": "Bailey Turn Road, Harriman, NY 10926, USA" }, { "location": { "latitude": 412144655, "longitude": -743949739 }, "name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA" }, { "location": { "latitude": 415736605, "longitude": -742847522 }, "name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA" }, { "location": { "latitude": 413843930, "longitude": -740501726 }, "name": "162 Merrill Road, Highland Mills, NY 10930, USA" }, { "location": { "latitude": 410873075, "longitude": -744459023 }, "name": "Clinton Road, West Milford, NJ 07480, USA" }, { "location": { "latitude": 412346009, "longitude": -744026814 }, "name": "16 Old Brook Lane, Warwick, NY 10990, USA" }, { "location": { "latitude": 402948455, "longitude": -747903913 }, "name": "3 Drake Lane, Pennington, NJ 08534, USA" }, { "location": { "latitude": 406337092, "longitude": -740122226 }, "name": "6324 8th Avenue, Brooklyn, NY 11220, USA" }, { "location": { "latitude": 406421967, "longitude": -747727624 }, "name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA" }, { "location": { "latitude": 416318082, "longitude": -749677716 }, "name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA" }, { "location": { "latitude": 415301720, "longitude": -748416257 }, "name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA" }, { "location": { "latitude": 402647019, "longitude": -747071791 }, "name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA" }, { "location": { "latitude": 412567807, "longitude": -741058078 }, "name": "New York State Reference Route 987E, Southfields, NY 10975, USA" }, { "location": { "latitude": 416855156, "longitude": -744420597 }, "name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA" }, { "location": { "latitude": 404663628, "longitude": -744820157 }, "name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA" }, { "location": { "latitude": 407113723, "longitude": -749746483 }, "name": "" }, { "location": { "latitude": 402133926, "longitude": -743613249 }, "name": "" }, { "location": { "latitude": 400273442, "longitude": -741220915 }, "name": "" }, { "location": { "latitude": 411236786, "longitude": -744070769 }, "name": "" }, { "location": { "latitude": 411633782, "longitude": -746784970 }, "name": "211-225 Plains Road, Augusta, NJ 07822, USA" }, { "location": { "latitude": 415830701, "longitude": -742952812 }, "name": "" }, { "location": { "latitude": 413447164, "longitude": -748712898 }, "name": "165 Pedersen Ridge Road, Milford, PA 18337, USA" }, { "location": { "latitude": 405047245, "longitude": -749800722 }, "name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA" }, { "location": { "latitude": 418858923, "longitude": -746156790 }, "name": "" }, { "location": { "latitude": 417951888, "longitude": -748484944 }, "name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA" }, { "location": { "latitude": 407033786, "longitude": -743977337 }, "name": "26 East 3rd Street, New Providence, NJ 07974, USA" }, { "location": { "latitude": 417548014, "longitude": -740075041 }, "name": "" }, { "location": { "latitude": 410395868, "longitude": -744972325 }, "name": "" }, { "location": { "latitude": 404615353, "longitude": -745129803 }, "name": "" }, { "location": { "latitude": 406589790, "longitude": -743560121 }, "name": "611 Lawrence Avenue, Westfield, NJ 07090, USA" }, { "location": { "latitude": 414653148, "longitude": -740477477 }, "name": "18 Lannis Avenue, New Windsor, NY 12553, USA" }, { "location": { "latitude": 405957808, "longitude": -743255336 }, "name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA" }, { "location": { "latitude": 411733589, "longitude": -741648093 }, "name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA" }, { "location": { "latitude": 412676291, "longitude": -742606606 }, "name": "1270 Lakes Road, Monroe, NY 10950, USA" }, { "location": { "latitude": 409224445, "longitude": -748286738 }, "name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA" }, { "location": { "latitude": 406523420, "longitude": -742135517 }, "name": "652 Garden Street, Elizabeth, NJ 07202, USA" }, { "location": { "latitude": 401827388, "longitude": -740294537 }, "name": "349 Sea Spray Court, Neptune City, NJ 07753, USA" }, { "location": { "latitude": 410564152, "longitude": -743685054 }, "name": "13-17 Stanley Street, West Milford, NJ 07480, USA" }, { "location": { "latitude": 408472324, "longitude": -740726046 }, "name": "47 Industrial Avenue, Teterboro, NJ 07608, USA" }, { "location": { "latitude": 412452168, "longitude": -740214052 }, "name": "5 White Oak Lane, Stony Point, NY 10980, USA" }, { "location": { "latitude": 409146138, "longitude": -746188906 }, "name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA" }, { "location": { "latitude": 404701380, "longitude": -744781745 }, "name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA" }, { "location": { "latitude": 409642566, "longitude": -746017679 }, "name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA" }, { "location": { "latitude": 408031728, "longitude": -748645385 }, "name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA" }, { "location": { "latitude": 413700272, "longitude": -742135189 }, "name": "367 Prospect Road, Chester, NY 10918, USA" }, { "location": { "latitude": 404310607, "longitude": -740282632 }, "name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA" }, { "location": { "latitude": 409319800, "longitude": -746201391 }, "name": "11 Ward Street, Mount Arlington, NJ 07856, USA" }, { "location": { "latitude": 406685311, "longitude": -742108603 }, "name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA" }, { "location": { "latitude": 419018117, "longitude": -749142781 }, "name": "43 Dreher Road, Roscoe, NY 12776, USA" }, { "location": { "latitude": 412856162, "longitude": -745148837 }, "name": "Swan Street, Pine Island, NY 10969, USA" }, { "location": { "latitude": 416560744, "longitude": -746721964 }, "name": "66 Pleasantview Avenue, Monticello, NY 12701, USA" }, { "location": { "latitude": 405314270, "longitude": -749836354 }, "name": "" }, { "location": { "latitude": 414219548, "longitude": -743327440 }, "name": "" }, { "location": { "latitude": 415534177, "longitude": -742900616 }, "name": "565 Winding Hills Road, Montgomery, NY 12549, USA" }, { "location": { "latitude": 406898530, "longitude": -749127080 }, "name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA" }, { "location": { "latitude": 407586880, "longitude": -741670168 }, "name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA" }, { "location": { "latitude": 400106455, "longitude": -742870190 }, "name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA" }, { "location": { "latitude": 400066188, "longitude": -746793294 }, "name": "" }, { "location": { "latitude": 418803880, "longitude": -744102673 }, "name": "40 Mountain Road, Napanoch, NY 12458, USA" }, { "location": { "latitude": 414204288, "longitude": -747895140 }, "name": "" }, { "location": { "latitude": 414777405, "longitude": -740615601 }, "name": "" }, { "location": { "latitude": 415464475, "longitude": -747175374 }, "name": "48 North Road, Forestburgh, NY 12777, USA" }, { "location": { "latitude": 404062378, "longitude": -746376177 }, "name": "" }, { "location": { "latitude": 405688272, "longitude": -749285130 }, "name": "" }, { "location": { "latitude": 400342070, "longitude": -748788996 }, "name": "" }, { "location": { "latitude": 401809022, "longitude": -744157964 }, "name": "" }, { "location": { "latitude": 404226644, "longitude": -740517141 }, "name": "9 Thompson Avenue, Leonardo, NJ 07737, USA" }, { "location": { "latitude": 410322033, "longitude": -747871659 }, "name": "" }, { "location": { "latitude": 407100674, "longitude": -747742727 }, "name": "" }, { "location": { "latitude": 418811433, "longitude": -741718005 }, "name": "213 Bush Road, Stone Ridge, NY 12484, USA" }, { "location": { "latitude": 415034302, "longitude": -743850945 }, "name": "" }, { "location": { "latitude": 411349992, "longitude": -743694161 }, "name": "" }, { "location": { "latitude": 404839914, "longitude": -744759616 }, "name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA" }, { "location": { "latitude": 414638017, "longitude": -745957854 }, "name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA" }, { "location": { "latitude": 412127800, "longitude": -740173578 }, "name": "" }, { "location": { "latitude": 401263460, "longitude": -747964303 }, "name": "" }, { "location": { "latitude": 412843391, "longitude": -749086026 }, "name": "" }, { "location": { "latitude": 418512773, "longitude": -743067823 }, "name": "" }, { "location": { "latitude": 404318328, "longitude": -740835638 }, "name": "42-102 Main Street, Belford, NJ 07718, USA" }, { "location": { "latitude": 419020746, "longitude": -741172328 }, "name": "" }, { "location": { "latitude": 404080723, "longitude": -746119569 }, "name": "" }, { "location": { "latitude": 401012643, "longitude": -744035134 }, "name": "" }, { "location": { "latitude": 404306372, "longitude": -741079661 }, "name": "" }, { "location": { "latitude": 403966326, "longitude": -748519297 }, "name": "" }, { "location": { "latitude": 405002031, "longitude": -748407866 }, "name": "" }, { "location": { "latitude": 409532885, "longitude": -742200683 }, "name": "" }, { "location": { "latitude": 416851321, "longitude": -742674555 }, "name": "" }, { "location": { "latitude": 406411633, "longitude": -741722051 }, "name": "3387 Richmond Terrace, Staten Island, NY 10303, USA" }, { "location": { "latitude": 413069058, "longitude": -744597778 }, "name": "261 Van Sickle Road, Goshen, NY 10924, USA" }, { "location": { "latitude": 418465462, "longitude": -746859398 }, "name": "" }, { "location": { "latitude": 411733222, "longitude": -744228360 }, "name": "" }, { "location": { "latitude": 410248224, "longitude": -747127767 }, "name": "3 Hasta Way, Newton, NJ 07860, USA" }]grpc-1.3.2/examples/csharp/route_guide/RouteGuideClient/000077500000000000000000000000001310511640000232635ustar00rootroot00000000000000grpc-1.3.2/examples/csharp/route_guide/RouteGuideClient/Program.cs000066400000000000000000000237631310511640000252340ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using Grpc.Core; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Routeguide { class Program { /// /// Sample client code that makes gRPC calls to the server. /// public class RouteGuideClient { readonly RouteGuide.RouteGuideClient client; public RouteGuideClient(RouteGuide.RouteGuideClient client) { this.client = client; } /// /// Blocking unary call example. Calls GetFeature and prints the response. /// public void GetFeature(int lat, int lon) { try { Log("*** GetFeature: lat={0} lon={1}", lat, lon); Point request = new Point { Latitude = lat, Longitude = lon }; Feature feature = client.GetFeature(request); if (feature.Exists()) { Log("Found feature called \"{0}\" at {1}, {2}", feature.Name, feature.Location.GetLatitude(), feature.Location.GetLongitude()); } else { Log("Found no feature at {0}, {1}", feature.Location.GetLatitude(), feature.Location.GetLongitude()); } } catch (RpcException e) { Log("RPC failed " + e); throw; } } /// /// Server-streaming example. Calls listFeatures with a rectangle of interest. Prints each response feature as it arrives. /// public async Task ListFeatures(int lowLat, int lowLon, int hiLat, int hiLon) { try { Log("*** ListFeatures: lowLat={0} lowLon={1} hiLat={2} hiLon={3}", lowLat, lowLon, hiLat, hiLon); Rectangle request = new Rectangle { Lo = new Point { Latitude = lowLat, Longitude = lowLon }, Hi = new Point { Latitude = hiLat, Longitude = hiLon } }; using (var call = client.ListFeatures(request)) { var responseStream = call.ResponseStream; StringBuilder responseLog = new StringBuilder("Result: "); while (await responseStream.MoveNext()) { Feature feature = responseStream.Current; responseLog.Append(feature.ToString()); } Log(responseLog.ToString()); } } catch (RpcException e) { Log("RPC failed " + e); throw; } } /// /// Client-streaming example. Sends numPoints randomly chosen points from features /// with a variable delay in between. Prints the statistics when they are sent from the server. /// public async Task RecordRoute(List features, int numPoints) { try { Log("*** RecordRoute"); using (var call = client.RecordRoute()) { // Send numPoints points randomly selected from the features list. StringBuilder numMsg = new StringBuilder(); Random rand = new Random(); for (int i = 0; i < numPoints; ++i) { int index = rand.Next(features.Count); Point point = features[index].Location; Log("Visiting point {0}, {1}", point.GetLatitude(), point.GetLongitude()); await call.RequestStream.WriteAsync(point); // A bit of delay before sending the next one. await Task.Delay(rand.Next(1000) + 500); } await call.RequestStream.CompleteAsync(); RouteSummary summary = await call.ResponseAsync; Log("Finished trip with {0} points. Passed {1} features. " + "Travelled {2} meters. It took {3} seconds.", summary.PointCount, summary.FeatureCount, summary.Distance, summary.ElapsedTime); Log("Finished RecordRoute"); } } catch (RpcException e) { Log("RPC failed", e); throw; } } /// /// Bi-directional streaming example. Send some chat messages, and print any /// chat messages that are sent from the server. /// public async Task RouteChat() { try { Log("*** RouteChat"); var requests = new List { NewNote("First message", 0, 0), NewNote("Second message", 0, 1), NewNote("Third message", 1, 0), NewNote("Fourth message", 0, 0) }; using (var call = client.RouteChat()) { var responseReaderTask = Task.Run(async () => { while (await call.ResponseStream.MoveNext()) { var note = call.ResponseStream.Current; Log("Got message \"{0}\" at {1}, {2}", note.Message, note.Location.Latitude, note.Location.Longitude); } }); foreach (RouteNote request in requests) { Log("Sending message \"{0}\" at {1}, {2}", request.Message, request.Location.Latitude, request.Location.Longitude); await call.RequestStream.WriteAsync(request); } await call.RequestStream.CompleteAsync(); await responseReaderTask; Log("Finished RouteChat"); } } catch (RpcException e) { Log("RPC failed", e); throw; } } private void Log(string s, params object[] args) { Console.WriteLine(string.Format(s, args)); } private void Log(string s) { Console.WriteLine(s); } private RouteNote NewNote(string message, int lat, int lon) { return new RouteNote { Message = message, Location = new Point { Latitude = lat, Longitude = lon } }; } } static void Main(string[] args) { var channel = new Channel("127.0.0.1:50052", ChannelCredentials.Insecure); var client = new RouteGuideClient(new RouteGuide.RouteGuideClient(channel)); // Looking for a valid feature client.GetFeature(409146138, -746188906); // Feature missing. client.GetFeature(0, 0); // Looking for features between 40, -75 and 42, -73. client.ListFeatures(400000000, -750000000, 420000000, -730000000).Wait(); // Record a few randomly selected points from the features file. client.RecordRoute(RouteGuideUtil.ParseFeatures(RouteGuideUtil.DefaultFeaturesFile), 10).Wait(); // Send and receive some notes. client.RouteChat().Wait(); channel.ShutdownAsync().Wait(); Console.WriteLine("Press any key to exit..."); Console.ReadKey(); } } } grpc-1.3.2/examples/csharp/route_guide/RouteGuideClient/Properties/000077500000000000000000000000001310511640000254175ustar00rootroot00000000000000grpc-1.3.2/examples/csharp/route_guide/RouteGuideClient/Properties/AssemblyInfo.cs000066400000000000000000000057071310511640000303520ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("RouteGuideClient")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("RouteGuideClient")] [assembly: AssemblyCopyright("Copyright © 2015")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("914644eb-47cd-4a37-9fba-5e62dd432333")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] grpc-1.3.2/examples/csharp/route_guide/RouteGuideClient/RouteGuideClient.csproj000066400000000000000000000111701310511640000277200ustar00rootroot00000000000000 Debug AnyCPU {D47BE663-4DE3-4206-B7A8-EA3FA066DADC} Exe Properties RouteGuideClient RouteGuideClient v4.5 512 b880049a AnyCPU true full false bin\Debug\ DEBUG;TRACE prompt 4 AnyCPU pdbonly true bin\Release\ TRACE prompt 4 False ..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll False ..\packages\Grpc.Core.1.0.1\lib\net45\Grpc.Core.dll False ..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll False ..\packages\System.Interactive.Async.3.0.0\lib\net45\System.Interactive.Async.dll {49954d9c-5f17-4662-96b2-73be833dd81a} RouteGuide 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}. grpc-1.3.2/examples/csharp/route_guide/RouteGuideClient/packages.config000066400000000000000000000006601310511640000262320ustar00rootroot00000000000000 grpc-1.3.2/examples/csharp/route_guide/RouteGuideServer/000077500000000000000000000000001310511640000233135ustar00rootroot00000000000000grpc-1.3.2/examples/csharp/route_guide/RouteGuideServer/Program.cs000066400000000000000000000046031310511640000252540ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using Grpc.Core; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Routeguide { class Program { static void Main(string[] args) { const int Port = 50052; var features = RouteGuideUtil.ParseFeatures(RouteGuideUtil.DefaultFeaturesFile); Server server = new Server { Services = { RouteGuide.BindService(new RouteGuideImpl(features)) }, Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) } }; server.Start(); Console.WriteLine("RouteGuide server listening on port " + Port); Console.WriteLine("Press any key to stop the server..."); Console.ReadKey(); server.ShutdownAsync().Wait(); } } } grpc-1.3.2/examples/csharp/route_guide/RouteGuideServer/Properties/000077500000000000000000000000001310511640000254475ustar00rootroot00000000000000grpc-1.3.2/examples/csharp/route_guide/RouteGuideServer/Properties/AssemblyInfo.cs000066400000000000000000000057071310511640000304020ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("RouteGuideServer")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("RouteGuideServer")] [assembly: AssemblyCopyright("Copyright © 2015")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("908bdeef-05cc-42bf-9498-c4c573df8925")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] grpc-1.3.2/examples/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs000066400000000000000000000150131310511640000265400ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Utils; namespace Routeguide { /// /// Example implementation of RouteGuide server. /// public class RouteGuideImpl : RouteGuide.RouteGuideBase { readonly List features; readonly object myLock = new object(); readonly Dictionary> routeNotes = new Dictionary>(); public RouteGuideImpl(List features) { this.features = features; } /// /// Gets the feature at the requested point. If no feature at that location /// exists, an unnammed feature is returned at the provided location. /// public override Task GetFeature(Point request, ServerCallContext context) { return Task.FromResult(CheckFeature(request)); } /// /// Gets all features contained within the given bounding rectangle. /// public override async Task ListFeatures(Rectangle request, IServerStreamWriter responseStream, ServerCallContext context) { var responses = features.FindAll( (feature) => feature.Exists() && request.Contains(feature.Location) ); foreach (var response in responses) { await responseStream.WriteAsync(response); } } /// /// Gets a stream of points, and responds with statistics about the "trip": number of points, /// number of known features visited, total distance traveled, and total time spent. /// public override async Task RecordRoute(IAsyncStreamReader requestStream, ServerCallContext context) { int pointCount = 0; int featureCount = 0; int distance = 0; Point previous = null; var stopwatch = new Stopwatch(); stopwatch.Start(); while (await requestStream.MoveNext()) { var point = requestStream.Current; pointCount++; if (CheckFeature(point).Exists()) { featureCount++; } if (previous != null) { distance += (int) previous.GetDistance(point); } previous = point; } stopwatch.Stop(); return new RouteSummary { PointCount = pointCount, FeatureCount = featureCount, Distance = distance, ElapsedTime = (int)(stopwatch.ElapsedMilliseconds / 1000) }; } /// /// Receives a stream of message/location pairs, and responds with a stream of all previous /// messages at each of those locations. /// public override async Task RouteChat(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) { while (await requestStream.MoveNext()) { var note = requestStream.Current; List prevNotes = AddNoteForLocation(note.Location, note); foreach (var prevNote in prevNotes) { await responseStream.WriteAsync(prevNote); } } } /// /// Adds a note for location and returns a list of pre-existing notes for that location (not containing the newly added note). /// private List AddNoteForLocation(Point location, RouteNote note) { lock (myLock) { List notes; if (!routeNotes.TryGetValue(location, out notes)) { notes = new List(); routeNotes.Add(location, notes); } var preexistingNotes = new List(notes); notes.Add(note); return preexistingNotes; } } /// /// Gets the feature at the given point. /// /// the location to check /// The feature object at the point Note that an empty name indicates no feature. private Feature CheckFeature(Point location) { var result = features.FirstOrDefault((feature) => feature.Location.Equals(location)); if (result == null) { // No feature was found, return an unnamed feature. return new Feature { Name = "", Location = location }; } return result; } } } grpc-1.3.2/examples/csharp/route_guide/RouteGuideServer/RouteGuideServer.csproj000066400000000000000000000112441310511640000300020ustar00rootroot00000000000000 Debug AnyCPU {4B7C7794-BE24-4477-ACE7-18259EB73D27} Exe Properties RouteGuideServer RouteGuideServer v4.5 512 946ecc79 AnyCPU true full false bin\Debug\ DEBUG;TRACE prompt 4 AnyCPU pdbonly true bin\Release\ TRACE prompt 4 False ..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll False ..\packages\Grpc.Core.1.0.1\lib\net45\Grpc.Core.dll False ..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll False ..\packages\System.Interactive.Async.3.0.0\lib\net45\System.Interactive.Async.dll {49954d9c-5f17-4662-96b2-73be833dd81a} RouteGuide 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}. grpc-1.3.2/examples/csharp/route_guide/RouteGuideServer/packages.config000066400000000000000000000007661310511640000262710ustar00rootroot00000000000000 grpc-1.3.2/examples/csharp/route_guide/generate_protos.bat000066400000000000000000000036421310511640000237450ustar00rootroot00000000000000@rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or without @rem modification, are permitted provided that the following conditions are @rem met: @rem @rem * Redistributions of source code must retain the above copyright @rem notice, this list of conditions and the following disclaimer. @rem * Redistributions in binary form must reproduce the above @rem copyright notice, this list of conditions and the following disclaimer @rem in the documentation and/or other materials provided with the @rem distribution. @rem * Neither the name of Google Inc. nor the names of its @rem contributors may be used to endorse or promote products derived from @rem this software without specific prior written permission. @rem @rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS @rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @rem A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT @rem OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, @rem SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT @rem LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, @rem DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY @rem THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT @rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE @rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @rem Generate the C# code for .proto files setlocal @rem enter this directory cd /d %~dp0 set TOOLS_PATH=packages\Grpc.Tools.1.0.0\tools\windows_x86 %TOOLS_PATH%\protoc.exe -I../../protos --csharp_out RouteGuide ../../protos/route_guide.proto --grpc_out RouteGuide --plugin=protoc-gen-grpc=%TOOLS_PATH%\grpc_csharp_plugin.exe endlocal grpc-1.3.2/examples/node/000077500000000000000000000000001310511640000152025ustar00rootroot00000000000000grpc-1.3.2/examples/node/.gitignore000066400000000000000000000000351310511640000171700ustar00rootroot00000000000000*~ node_modules npm-debug.loggrpc-1.3.2/examples/node/README.md000066400000000000000000000025021310511640000164600ustar00rootroot00000000000000gRPC in 3 minutes (Node.js) =========================== PREREQUISITES ------------- - `node`: This requires Node 0.12.x or greater. INSTALL ------- ```sh $ # Get the gRPC repository $ export REPO_ROOT=grpc # REPO root can be any directory of your choice $ git clone -b $(curl -L http://grpc.io/release) https://github.com/grpc/grpc $REPO_ROOT $ cd $REPO_ROOT $ cd examples/node $ npm install ``` TRY IT! ------- There are two ways to generate the code needed to work with protocol buffers in Node.js - one approach uses [Protobuf.js](https://github.com/dcodeIO/ProtoBuf.js/) to dynamically generate the code at runtime, the other uses code statically generated using the protocol buffer compiler `protoc`. The examples behave identically, and either server can be used with either client. - Run the server ```sh $ # from this directory $ node ./dynamic_codegen/greeter_server.js & $ # OR $ node ./static_codegen/greeter_server.js & ``` - Run the client ```sh $ # from this directory $ node ./dynamic_codegen/greeter_client.js $ # OR $ node ./static_codegen/greeter_client.js ``` TUTORIAL -------- You can find a more detailed tutorial in [gRPC Basics: Node.js][] [Install gRPC Node]:../../src/node [gRPC Basics: Node.js]:http://www.grpc.io/docs/tutorials/basic/node.html grpc-1.3.2/examples/node/dynamic_codegen/000077500000000000000000000000001310511640000203125ustar00rootroot00000000000000grpc-1.3.2/examples/node/dynamic_codegen/README.md000066400000000000000000000002041310511640000215650ustar00rootroot00000000000000This is the dynamic code generation variant of the Node examples. Code in these examples is generated at runtime using Protobuf.js. grpc-1.3.2/examples/node/dynamic_codegen/greeter_client.js000066400000000000000000000040621310511640000236450ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ var PROTO_PATH = __dirname + '/../../protos/helloworld.proto'; var grpc = require('grpc'); var hello_proto = grpc.load(PROTO_PATH).helloworld; function main() { var client = new hello_proto.Greeter('localhost:50051', grpc.credentials.createInsecure()); var user; if (process.argv.length >= 3) { user = process.argv[2]; } else { user = 'world'; } client.sayHello({name: user}, function(err, response) { console.log('Greeting:', response.message); }); } main(); grpc-1.3.2/examples/node/dynamic_codegen/greeter_server.js000066400000000000000000000042271310511640000237000ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ var PROTO_PATH = __dirname + '/../../protos/helloworld.proto'; var grpc = require('grpc'); var hello_proto = grpc.load(PROTO_PATH).helloworld; /** * Implements the SayHello RPC method. */ function sayHello(call, callback) { callback(null, {message: 'Hello ' + call.request.name}); } /** * Starts an RPC server that receives requests for the Greeter service at the * sample server port */ function main() { var server = new grpc.Server(); server.addProtoService(hello_proto.Greeter.service, {sayHello: sayHello}); server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure()); server.start(); } main(); grpc-1.3.2/examples/node/dynamic_codegen/route_guide/000077500000000000000000000000001310511640000226255ustar00rootroot00000000000000grpc-1.3.2/examples/node/dynamic_codegen/route_guide/README.md000066400000000000000000000003471310511640000241100ustar00rootroot00000000000000#gRPC Basics: Node.js sample code The files in this folder are the samples used in [gRPC Basics: Node.js][], a detailed tutorial for using gRPC in Node.js. [gRPC Basics: Node.js]:http://www.grpc.io/docs/tutorials/basic/node.html grpc-1.3.2/examples/node/dynamic_codegen/route_guide/route_guide_client.js000066400000000000000000000163331310511640000270420ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ var PROTO_PATH = __dirname + '/../../../protos/route_guide.proto'; var async = require('async'); var fs = require('fs'); var parseArgs = require('minimist'); var path = require('path'); var _ = require('lodash'); var grpc = require('grpc'); var routeguide = grpc.load(PROTO_PATH).routeguide; var client = new routeguide.RouteGuide('localhost:50051', grpc.credentials.createInsecure()); var COORD_FACTOR = 1e7; /** * Run the getFeature demo. Calls getFeature with a point known to have a * feature and a point known not to have a feature. * @param {function} callback Called when this demo is complete */ function runGetFeature(callback) { var next = _.after(2, callback); function featureCallback(error, feature) { if (error) { callback(error); return; } if (feature.name === '') { console.log('Found no feature at ' + feature.location.latitude/COORD_FACTOR + ', ' + feature.location.longitude/COORD_FACTOR); } else { console.log('Found feature called "' + feature.name + '" at ' + feature.location.latitude/COORD_FACTOR + ', ' + feature.location.longitude/COORD_FACTOR); } next(); } var point1 = { latitude: 409146138, longitude: -746188906 }; var point2 = { latitude: 0, longitude: 0 }; client.getFeature(point1, featureCallback); client.getFeature(point2, featureCallback); } /** * Run the listFeatures demo. Calls listFeatures with a rectangle containing all * of the features in the pre-generated database. Prints each response as it * comes in. * @param {function} callback Called when this demo is complete */ function runListFeatures(callback) { var rectangle = { lo: { latitude: 400000000, longitude: -750000000 }, hi: { latitude: 420000000, longitude: -730000000 } }; console.log('Looking for features between 40, -75 and 42, -73'); var call = client.listFeatures(rectangle); call.on('data', function(feature) { console.log('Found feature called "' + feature.name + '" at ' + feature.location.latitude/COORD_FACTOR + ', ' + feature.location.longitude/COORD_FACTOR); }); call.on('end', callback); } /** * Run the recordRoute demo. Sends several randomly chosen points from the * pre-generated feature database with a variable delay in between. Prints the * statistics when they are sent from the server. * @param {function} callback Called when this demo is complete */ function runRecordRoute(callback) { var argv = parseArgs(process.argv, { string: 'db_path' }); fs.readFile(path.resolve(argv.db_path), function(err, data) { if (err) { callback(err); return; } var feature_list = JSON.parse(data); var num_points = 10; var call = client.recordRoute(function(error, stats) { if (error) { callback(error); return; } console.log('Finished trip with', stats.point_count, 'points'); console.log('Passed', stats.feature_count, 'features'); console.log('Travelled', stats.distance, 'meters'); console.log('It took', stats.elapsed_time, 'seconds'); callback(); }); /** * Constructs a function that asynchronously sends the given point and then * delays sending its callback * @param {number} lat The latitude to send * @param {number} lng The longitude to send * @return {function(function)} The function that sends the point */ function pointSender(lat, lng) { /** * Sends the point, then calls the callback after a delay * @param {function} callback Called when complete */ return function(callback) { console.log('Visiting point ' + lat/COORD_FACTOR + ', ' + lng/COORD_FACTOR); call.write({ latitude: lat, longitude: lng }); _.delay(callback, _.random(500, 1500)); }; } var point_senders = []; for (var i = 0; i < num_points; i++) { var rand_point = feature_list[_.random(0, feature_list.length - 1)]; point_senders[i] = pointSender(rand_point.location.latitude, rand_point.location.longitude); } async.series(point_senders, function() { call.end(); }); }); } /** * Run the routeChat demo. Send some chat messages, and print any chat messages * that are sent from the server. * @param {function} callback Called when the demo is complete */ function runRouteChat(callback) { var call = client.routeChat(); call.on('data', function(note) { console.log('Got message "' + note.message + '" at ' + note.location.latitude + ', ' + note.location.longitude); }); call.on('end', callback); var notes = [{ location: { latitude: 0, longitude: 0 }, message: 'First message' }, { location: { latitude: 0, longitude: 1 }, message: 'Second message' }, { location: { latitude: 1, longitude: 0 }, message: 'Third message' }, { location: { latitude: 0, longitude: 0 }, message: 'Fourth message' }]; for (var i = 0; i < notes.length; i++) { var note = notes[i]; console.log('Sending message "' + note.message + '" at ' + note.location.latitude + ', ' + note.location.longitude); call.write(note); } call.end(); } /** * Run all of the demos in order */ function main() { async.series([ runGetFeature, runListFeatures, runRecordRoute, runRouteChat ]); } if (require.main === module) { main(); } exports.runGetFeature = runGetFeature; exports.runListFeatures = runListFeatures; exports.runRecordRoute = runRecordRoute; exports.runRouteChat = runRouteChat; grpc-1.3.2/examples/node/dynamic_codegen/route_guide/route_guide_db.json000066400000000000000000000327101310511640000265030ustar00rootroot00000000000000[{ "location": { "latitude": 407838351, "longitude": -746143763 }, "name": "Patriots Path, Mendham, NJ 07945, USA" }, { "location": { "latitude": 408122808, "longitude": -743999179 }, "name": "101 New Jersey 10, Whippany, NJ 07981, USA" }, { "location": { "latitude": 413628156, "longitude": -749015468 }, "name": "U.S. 6, Shohola, PA 18458, USA" }, { "location": { "latitude": 419999544, "longitude": -740371136 }, "name": "5 Conners Road, Kingston, NY 12401, USA" }, { "location": { "latitude": 414008389, "longitude": -743951297 }, "name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA" }, { "location": { "latitude": 419611318, "longitude": -746524769 }, "name": "287 Flugertown Road, Livingston Manor, NY 12758, USA" }, { "location": { "latitude": 406109563, "longitude": -742186778 }, "name": "4001 Tremley Point Road, Linden, NJ 07036, USA" }, { "location": { "latitude": 416802456, "longitude": -742370183 }, "name": "352 South Mountain Road, Wallkill, NY 12589, USA" }, { "location": { "latitude": 412950425, "longitude": -741077389 }, "name": "Bailey Turn Road, Harriman, NY 10926, USA" }, { "location": { "latitude": 412144655, "longitude": -743949739 }, "name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA" }, { "location": { "latitude": 415736605, "longitude": -742847522 }, "name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA" }, { "location": { "latitude": 413843930, "longitude": -740501726 }, "name": "162 Merrill Road, Highland Mills, NY 10930, USA" }, { "location": { "latitude": 410873075, "longitude": -744459023 }, "name": "Clinton Road, West Milford, NJ 07480, USA" }, { "location": { "latitude": 412346009, "longitude": -744026814 }, "name": "16 Old Brook Lane, Warwick, NY 10990, USA" }, { "location": { "latitude": 402948455, "longitude": -747903913 }, "name": "3 Drake Lane, Pennington, NJ 08534, USA" }, { "location": { "latitude": 406337092, "longitude": -740122226 }, "name": "6324 8th Avenue, Brooklyn, NY 11220, USA" }, { "location": { "latitude": 406421967, "longitude": -747727624 }, "name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA" }, { "location": { "latitude": 416318082, "longitude": -749677716 }, "name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA" }, { "location": { "latitude": 415301720, "longitude": -748416257 }, "name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA" }, { "location": { "latitude": 402647019, "longitude": -747071791 }, "name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA" }, { "location": { "latitude": 412567807, "longitude": -741058078 }, "name": "New York State Reference Route 987E, Southfields, NY 10975, USA" }, { "location": { "latitude": 416855156, "longitude": -744420597 }, "name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA" }, { "location": { "latitude": 404663628, "longitude": -744820157 }, "name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA" }, { "location": { "latitude": 407113723, "longitude": -749746483 }, "name": "" }, { "location": { "latitude": 402133926, "longitude": -743613249 }, "name": "" }, { "location": { "latitude": 400273442, "longitude": -741220915 }, "name": "" }, { "location": { "latitude": 411236786, "longitude": -744070769 }, "name": "" }, { "location": { "latitude": 411633782, "longitude": -746784970 }, "name": "211-225 Plains Road, Augusta, NJ 07822, USA" }, { "location": { "latitude": 415830701, "longitude": -742952812 }, "name": "" }, { "location": { "latitude": 413447164, "longitude": -748712898 }, "name": "165 Pedersen Ridge Road, Milford, PA 18337, USA" }, { "location": { "latitude": 405047245, "longitude": -749800722 }, "name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA" }, { "location": { "latitude": 418858923, "longitude": -746156790 }, "name": "" }, { "location": { "latitude": 417951888, "longitude": -748484944 }, "name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA" }, { "location": { "latitude": 407033786, "longitude": -743977337 }, "name": "26 East 3rd Street, New Providence, NJ 07974, USA" }, { "location": { "latitude": 417548014, "longitude": -740075041 }, "name": "" }, { "location": { "latitude": 410395868, "longitude": -744972325 }, "name": "" }, { "location": { "latitude": 404615353, "longitude": -745129803 }, "name": "" }, { "location": { "latitude": 406589790, "longitude": -743560121 }, "name": "611 Lawrence Avenue, Westfield, NJ 07090, USA" }, { "location": { "latitude": 414653148, "longitude": -740477477 }, "name": "18 Lannis Avenue, New Windsor, NY 12553, USA" }, { "location": { "latitude": 405957808, "longitude": -743255336 }, "name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA" }, { "location": { "latitude": 411733589, "longitude": -741648093 }, "name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA" }, { "location": { "latitude": 412676291, "longitude": -742606606 }, "name": "1270 Lakes Road, Monroe, NY 10950, USA" }, { "location": { "latitude": 409224445, "longitude": -748286738 }, "name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA" }, { "location": { "latitude": 406523420, "longitude": -742135517 }, "name": "652 Garden Street, Elizabeth, NJ 07202, USA" }, { "location": { "latitude": 401827388, "longitude": -740294537 }, "name": "349 Sea Spray Court, Neptune City, NJ 07753, USA" }, { "location": { "latitude": 410564152, "longitude": -743685054 }, "name": "13-17 Stanley Street, West Milford, NJ 07480, USA" }, { "location": { "latitude": 408472324, "longitude": -740726046 }, "name": "47 Industrial Avenue, Teterboro, NJ 07608, USA" }, { "location": { "latitude": 412452168, "longitude": -740214052 }, "name": "5 White Oak Lane, Stony Point, NY 10980, USA" }, { "location": { "latitude": 409146138, "longitude": -746188906 }, "name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA" }, { "location": { "latitude": 404701380, "longitude": -744781745 }, "name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA" }, { "location": { "latitude": 409642566, "longitude": -746017679 }, "name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA" }, { "location": { "latitude": 408031728, "longitude": -748645385 }, "name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA" }, { "location": { "latitude": 413700272, "longitude": -742135189 }, "name": "367 Prospect Road, Chester, NY 10918, USA" }, { "location": { "latitude": 404310607, "longitude": -740282632 }, "name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA" }, { "location": { "latitude": 409319800, "longitude": -746201391 }, "name": "11 Ward Street, Mount Arlington, NJ 07856, USA" }, { "location": { "latitude": 406685311, "longitude": -742108603 }, "name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA" }, { "location": { "latitude": 419018117, "longitude": -749142781 }, "name": "43 Dreher Road, Roscoe, NY 12776, USA" }, { "location": { "latitude": 412856162, "longitude": -745148837 }, "name": "Swan Street, Pine Island, NY 10969, USA" }, { "location": { "latitude": 416560744, "longitude": -746721964 }, "name": "66 Pleasantview Avenue, Monticello, NY 12701, USA" }, { "location": { "latitude": 405314270, "longitude": -749836354 }, "name": "" }, { "location": { "latitude": 414219548, "longitude": -743327440 }, "name": "" }, { "location": { "latitude": 415534177, "longitude": -742900616 }, "name": "565 Winding Hills Road, Montgomery, NY 12549, USA" }, { "location": { "latitude": 406898530, "longitude": -749127080 }, "name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA" }, { "location": { "latitude": 407586880, "longitude": -741670168 }, "name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA" }, { "location": { "latitude": 400106455, "longitude": -742870190 }, "name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA" }, { "location": { "latitude": 400066188, "longitude": -746793294 }, "name": "" }, { "location": { "latitude": 418803880, "longitude": -744102673 }, "name": "40 Mountain Road, Napanoch, NY 12458, USA" }, { "location": { "latitude": 414204288, "longitude": -747895140 }, "name": "" }, { "location": { "latitude": 414777405, "longitude": -740615601 }, "name": "" }, { "location": { "latitude": 415464475, "longitude": -747175374 }, "name": "48 North Road, Forestburgh, NY 12777, USA" }, { "location": { "latitude": 404062378, "longitude": -746376177 }, "name": "" }, { "location": { "latitude": 405688272, "longitude": -749285130 }, "name": "" }, { "location": { "latitude": 400342070, "longitude": -748788996 }, "name": "" }, { "location": { "latitude": 401809022, "longitude": -744157964 }, "name": "" }, { "location": { "latitude": 404226644, "longitude": -740517141 }, "name": "9 Thompson Avenue, Leonardo, NJ 07737, USA" }, { "location": { "latitude": 410322033, "longitude": -747871659 }, "name": "" }, { "location": { "latitude": 407100674, "longitude": -747742727 }, "name": "" }, { "location": { "latitude": 418811433, "longitude": -741718005 }, "name": "213 Bush Road, Stone Ridge, NY 12484, USA" }, { "location": { "latitude": 415034302, "longitude": -743850945 }, "name": "" }, { "location": { "latitude": 411349992, "longitude": -743694161 }, "name": "" }, { "location": { "latitude": 404839914, "longitude": -744759616 }, "name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA" }, { "location": { "latitude": 414638017, "longitude": -745957854 }, "name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA" }, { "location": { "latitude": 412127800, "longitude": -740173578 }, "name": "" }, { "location": { "latitude": 401263460, "longitude": -747964303 }, "name": "" }, { "location": { "latitude": 412843391, "longitude": -749086026 }, "name": "" }, { "location": { "latitude": 418512773, "longitude": -743067823 }, "name": "" }, { "location": { "latitude": 404318328, "longitude": -740835638 }, "name": "42-102 Main Street, Belford, NJ 07718, USA" }, { "location": { "latitude": 419020746, "longitude": -741172328 }, "name": "" }, { "location": { "latitude": 404080723, "longitude": -746119569 }, "name": "" }, { "location": { "latitude": 401012643, "longitude": -744035134 }, "name": "" }, { "location": { "latitude": 404306372, "longitude": -741079661 }, "name": "" }, { "location": { "latitude": 403966326, "longitude": -748519297 }, "name": "" }, { "location": { "latitude": 405002031, "longitude": -748407866 }, "name": "" }, { "location": { "latitude": 409532885, "longitude": -742200683 }, "name": "" }, { "location": { "latitude": 416851321, "longitude": -742674555 }, "name": "" }, { "location": { "latitude": 406411633, "longitude": -741722051 }, "name": "3387 Richmond Terrace, Staten Island, NY 10303, USA" }, { "location": { "latitude": 413069058, "longitude": -744597778 }, "name": "261 Van Sickle Road, Goshen, NY 10924, USA" }, { "location": { "latitude": 418465462, "longitude": -746859398 }, "name": "" }, { "location": { "latitude": 411733222, "longitude": -744228360 }, "name": "" }, { "location": { "latitude": 410248224, "longitude": -747127767 }, "name": "3 Hasta Way, Newton, NJ 07860, USA" }] grpc-1.3.2/examples/node/dynamic_codegen/route_guide/route_guide_server.js000066400000000000000000000200271310511640000270650ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ var PROTO_PATH = __dirname + '/../../../protos/route_guide.proto'; var fs = require('fs'); var parseArgs = require('minimist'); var path = require('path'); var _ = require('lodash'); var grpc = require('grpc'); var routeguide = grpc.load(PROTO_PATH).routeguide; var COORD_FACTOR = 1e7; /** * For simplicity, a point is a record type that looks like * {latitude: number, longitude: number}, and a feature is a record type that * looks like {name: string, location: point}. feature objects with name==='' * are points with no feature. */ /** * List of feature objects at points that have been requested so far. */ var feature_list = []; /** * Get a feature object at the given point, or creates one if it does not exist. * @param {point} point The point to check * @return {feature} The feature object at the point. Note that an empty name * indicates no feature */ function checkFeature(point) { var feature; // Check if there is already a feature object for the given point for (var i = 0; i < feature_list.length; i++) { feature = feature_list[i]; if (feature.location.latitude === point.latitude && feature.location.longitude === point.longitude) { return feature; } } var name = ''; feature = { name: name, location: point }; return feature; } /** * getFeature request handler. Gets a request with a point, and responds with a * feature object indicating whether there is a feature at that point. * @param {EventEmitter} call Call object for the handler to process * @param {function(Error, feature)} callback Response callback */ function getFeature(call, callback) { callback(null, checkFeature(call.request)); } /** * listFeatures request handler. Gets a request with two points, and responds * with a stream of all features in the bounding box defined by those points. * @param {Writable} call Writable stream for responses with an additional * request property for the request value. */ function listFeatures(call) { var lo = call.request.lo; var hi = call.request.hi; var left = _.min([lo.longitude, hi.longitude]); var right = _.max([lo.longitude, hi.longitude]); var top = _.max([lo.latitude, hi.latitude]); var bottom = _.min([lo.latitude, hi.latitude]); // For each feature, check if it is in the given bounding box _.each(feature_list, function(feature) { if (feature.name === '') { return; } if (feature.location.longitude >= left && feature.location.longitude <= right && feature.location.latitude >= bottom && feature.location.latitude <= top) { call.write(feature); } }); call.end(); } /** * Calculate the distance between two points using the "haversine" formula. * This code was taken from http://www.movable-type.co.uk/scripts/latlong.html. * @param start The starting point * @param end The end point * @return The distance between the points in meters */ function getDistance(start, end) { function toRadians(num) { return num * Math.PI / 180; } var lat1 = start.latitude / COORD_FACTOR; var lat2 = end.latitude / COORD_FACTOR; var lon1 = start.longitude / COORD_FACTOR; var lon2 = end.longitude / COORD_FACTOR; var R = 6371000; // metres var φ1 = toRadians(lat1); var φ2 = toRadians(lat2); var Δφ = toRadians(lat2-lat1); var Δλ = toRadians(lon2-lon1); var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) + Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ/2) * Math.sin(Δλ/2); var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); return R * c; } /** * recordRoute handler. Gets a stream of points, and responds with statistics * about the "trip": number of points, number of known features visited, total * distance traveled, and total time spent. * @param {Readable} call The request point stream. * @param {function(Error, routeSummary)} callback The callback to pass the * response to */ function recordRoute(call, callback) { var point_count = 0; var feature_count = 0; var distance = 0; var previous = null; // Start a timer var start_time = process.hrtime(); call.on('data', function(point) { point_count += 1; if (checkFeature(point).name !== '') { feature_count += 1; } /* For each point after the first, add the incremental distance from the * previous point to the total distance value */ if (previous != null) { distance += getDistance(previous, point); } previous = point; }); call.on('end', function() { callback(null, { point_count: point_count, feature_count: feature_count, // Cast the distance to an integer distance: distance|0, // End the timer elapsed_time: process.hrtime(start_time)[0] }); }); } var route_notes = {}; /** * Turn the point into a dictionary key. * @param {point} point The point to use * @return {string} The key for an object */ function pointKey(point) { return point.latitude + ' ' + point.longitude; } /** * routeChat handler. Receives a stream of message/location pairs, and responds * with a stream of all previous messages at each of those locations. * @param {Duplex} call The stream for incoming and outgoing messages */ function routeChat(call) { call.on('data', function(note) { var key = pointKey(note.location); /* For each note sent, respond with all previous notes that correspond to * the same point */ if (route_notes.hasOwnProperty(key)) { _.each(route_notes[key], function(note) { call.write(note); }); } else { route_notes[key] = []; } // Then add the new note to the list route_notes[key].push(JSON.parse(JSON.stringify(note))); }); call.on('end', function() { call.end(); }); } /** * Get a new server with the handler functions in this file bound to the methods * it serves. * @return {Server} The new server object */ function getServer() { var server = new grpc.Server(); server.addProtoService(routeguide.RouteGuide.service, { getFeature: getFeature, listFeatures: listFeatures, recordRoute: recordRoute, routeChat: routeChat }); return server; } if (require.main === module) { // If this is run as a script, start a server on an unused port var routeServer = getServer(); routeServer.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure()); var argv = parseArgs(process.argv, { string: 'db_path' }); fs.readFile(path.resolve(argv.db_path), function(err, data) { if (err) throw err; feature_list = JSON.parse(data); routeServer.start(); }); } exports.getServer = getServer; grpc-1.3.2/examples/node/package.json000066400000000000000000000003141310511640000174660ustar00rootroot00000000000000{ "name": "grpc-examples", "version": "0.1.0", "dependencies": { "async": "^1.5.2", "google-protobuf": "^3.0.0", "grpc": "^1.0.0", "lodash": "^4.6.1", "minimist": "^1.2.0" } } grpc-1.3.2/examples/node/static_codegen/000077500000000000000000000000001310511640000201555ustar00rootroot00000000000000grpc-1.3.2/examples/node/static_codegen/README.md000066400000000000000000000015661310511640000214440ustar00rootroot00000000000000This is the static code generation variant of the Node examples. Code in these examples is pre-generated using protoc and the Node gRPC protoc plugin, and the generated code can be found in various `*_pb.js` files. The command line sequence for generating those files is as follows (assuming that `protoc` and `grpc_node_plugin` are present, and starting in the directory which contains this README.md file): ```sh cd ../../protos npm install -g grpc-tools grpc_tools_node_protoc --js_out=import_style=commonjs,binary:../node/static_codegen/ --grpc_out=../node/static_codegen --plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin` helloworld.proto grpc_tools_node_protoc --js_out=import_style=commonjs,binary:../node/static_codegen/route_guide/ --grpc_out=../node/static_codegen/route_guide/ --plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin` route_guide.proto ``` grpc-1.3.2/examples/node/static_codegen/greeter_client.js000066400000000000000000000041461310511640000235130ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ var messages = require('./helloworld_pb'); var services = require('./helloworld_grpc_pb'); var grpc = require('grpc'); function main() { var client = new services.GreeterClient('localhost:50051', grpc.credentials.createInsecure()); var request = new messages.HelloRequest(); var user; if (process.argv.length >= 3) { user = process.argv[2]; } else { user = 'world'; } request.setName(user); client.sayHello(request, function(err, response) { console.log('Greeting:', response.getMessage()); }); } main(); grpc-1.3.2/examples/node/static_codegen/greeter_server.js000066400000000000000000000042641310511640000235440ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ var messages = require('./helloworld_pb'); var services = require('./helloworld_grpc_pb'); var grpc = require('grpc'); /** * Implements the SayHello RPC method. */ function sayHello(call, callback) { var reply = new messages.HelloReply(); reply.setMessage('Hello ' + call.request.getName()); callback(null, reply); } /** * Starts an RPC server that receives requests for the Greeter service at the * sample server port */ function main() { var server = new grpc.Server(); server.addService(services.GreeterService, {sayHello: sayHello}); server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure()); server.start(); } main(); grpc-1.3.2/examples/node/static_codegen/helloworld_grpc_pb.js000066400000000000000000000056261310511640000243730ustar00rootroot00000000000000// GENERATED CODE -- DO NOT EDIT! // Original file comments: // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // 'use strict'; var grpc = require('grpc'); var helloworld_pb = require('./helloworld_pb.js'); function serialize_HelloReply(arg) { if (!(arg instanceof helloworld_pb.HelloReply)) { throw new Error('Expected argument of type HelloReply'); } return new Buffer(arg.serializeBinary()); } function deserialize_HelloReply(buffer_arg) { return helloworld_pb.HelloReply.deserializeBinary(new Uint8Array(buffer_arg)); } function serialize_HelloRequest(arg) { if (!(arg instanceof helloworld_pb.HelloRequest)) { throw new Error('Expected argument of type HelloRequest'); } return new Buffer(arg.serializeBinary()); } function deserialize_HelloRequest(buffer_arg) { return helloworld_pb.HelloRequest.deserializeBinary(new Uint8Array(buffer_arg)); } // The greeting service definition. var GreeterService = exports.GreeterService = { // Sends a greeting sayHello: { path: '/helloworld.Greeter/SayHello', requestStream: false, responseStream: false, requestType: helloworld_pb.HelloRequest, responseType: helloworld_pb.HelloReply, requestSerialize: serialize_HelloRequest, requestDeserialize: deserialize_HelloRequest, responseSerialize: serialize_HelloReply, responseDeserialize: deserialize_HelloReply, }, }; exports.GreeterClient = grpc.makeGenericClientConstructor(GreeterService); grpc-1.3.2/examples/node/static_codegen/helloworld_pb.js000066400000000000000000000231601310511640000233510ustar00rootroot00000000000000/** * @fileoverview * @enhanceable * @public */ // GENERATED CODE -- DO NOT EDIT! var jspb = require('google-protobuf'); var goog = jspb; var global = Function('return this')(); goog.exportSymbol('proto.helloworld.HelloReply', null, global); goog.exportSymbol('proto.helloworld.HelloRequest', null, global); /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a * server response, or constructed directly in Javascript. The array is used * in place and becomes part of the constructed object. It is not cloned. * If no data is provided, the constructed object will be empty, but still * valid. * @extends {jspb.Message} * @constructor */ proto.helloworld.HelloRequest = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; goog.inherits(proto.helloworld.HelloRequest, jspb.Message); if (goog.DEBUG && !COMPILED) { proto.helloworld.HelloRequest.displayName = 'proto.helloworld.HelloRequest'; } if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto suitable for use in Soy templates. * Field names that are reserved in JavaScript and will be renamed to pb_name. * To access a reserved field use, foo.pb_, eg, foo.pb_default. * For the list of reserved names please see: * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration * @return {!Object} */ proto.helloworld.HelloRequest.prototype.toObject = function(opt_includeInstance) { return proto.helloworld.HelloRequest.toObject(opt_includeInstance, this); }; /** * Static version of the {@see toObject} method. * @param {boolean|undefined} includeInstance Whether to include the JSPB * instance for transitional soy proto support: * http://goto/soy-param-migration * @param {!proto.helloworld.HelloRequest} msg The msg instance to transform. * @return {!Object} */ proto.helloworld.HelloRequest.toObject = function(includeInstance, msg) { var f, obj = { name: msg.getName() }; if (includeInstance) { obj.$jspbMessageInstance = msg; } return obj; }; } /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. * @return {!proto.helloworld.HelloRequest} */ proto.helloworld.HelloRequest.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); var msg = new proto.helloworld.HelloRequest; return proto.helloworld.HelloRequest.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. * @param {!proto.helloworld.HelloRequest} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. * @return {!proto.helloworld.HelloRequest} */ proto.helloworld.HelloRequest.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); switch (field) { case 1: var value = /** @type {string} */ (reader.readString()); msg.setName(value); break; default: reader.skipField(); break; } } return msg; }; /** * Class method variant: serializes the given message to binary data * (in protobuf wire format), writing to the given BinaryWriter. * @param {!proto.helloworld.HelloRequest} message * @param {!jspb.BinaryWriter} writer */ proto.helloworld.HelloRequest.serializeBinaryToWriter = function(message, writer) { message.serializeBinaryToWriter(writer); }; /** * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ proto.helloworld.HelloRequest.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); this.serializeBinaryToWriter(writer); return writer.getResultBuffer(); }; /** * Serializes the message to binary data (in protobuf wire format), * writing to the given BinaryWriter. * @param {!jspb.BinaryWriter} writer */ proto.helloworld.HelloRequest.prototype.serializeBinaryToWriter = function (writer) { var f = undefined; f = this.getName(); if (f.length > 0) { writer.writeString( 1, f ); } }; /** * Creates a deep clone of this proto. No data is shared with the original. * @return {!proto.helloworld.HelloRequest} The clone. */ proto.helloworld.HelloRequest.prototype.cloneMessage = function() { return /** @type {!proto.helloworld.HelloRequest} */ (jspb.Message.cloneMessage(this)); }; /** * optional string name = 1; * @return {string} */ proto.helloworld.HelloRequest.prototype.getName = function() { return /** @type {string} */ (jspb.Message.getFieldProto3(this, 1, "")); }; /** @param {string} value */ proto.helloworld.HelloRequest.prototype.setName = function(value) { jspb.Message.setField(this, 1, value); }; /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a * server response, or constructed directly in Javascript. The array is used * in place and becomes part of the constructed object. It is not cloned. * If no data is provided, the constructed object will be empty, but still * valid. * @extends {jspb.Message} * @constructor */ proto.helloworld.HelloReply = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; goog.inherits(proto.helloworld.HelloReply, jspb.Message); if (goog.DEBUG && !COMPILED) { proto.helloworld.HelloReply.displayName = 'proto.helloworld.HelloReply'; } if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto suitable for use in Soy templates. * Field names that are reserved in JavaScript and will be renamed to pb_name. * To access a reserved field use, foo.pb_, eg, foo.pb_default. * For the list of reserved names please see: * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration * @return {!Object} */ proto.helloworld.HelloReply.prototype.toObject = function(opt_includeInstance) { return proto.helloworld.HelloReply.toObject(opt_includeInstance, this); }; /** * Static version of the {@see toObject} method. * @param {boolean|undefined} includeInstance Whether to include the JSPB * instance for transitional soy proto support: * http://goto/soy-param-migration * @param {!proto.helloworld.HelloReply} msg The msg instance to transform. * @return {!Object} */ proto.helloworld.HelloReply.toObject = function(includeInstance, msg) { var f, obj = { message: msg.getMessage() }; if (includeInstance) { obj.$jspbMessageInstance = msg; } return obj; }; } /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. * @return {!proto.helloworld.HelloReply} */ proto.helloworld.HelloReply.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); var msg = new proto.helloworld.HelloReply; return proto.helloworld.HelloReply.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. * @param {!proto.helloworld.HelloReply} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. * @return {!proto.helloworld.HelloReply} */ proto.helloworld.HelloReply.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); switch (field) { case 1: var value = /** @type {string} */ (reader.readString()); msg.setMessage(value); break; default: reader.skipField(); break; } } return msg; }; /** * Class method variant: serializes the given message to binary data * (in protobuf wire format), writing to the given BinaryWriter. * @param {!proto.helloworld.HelloReply} message * @param {!jspb.BinaryWriter} writer */ proto.helloworld.HelloReply.serializeBinaryToWriter = function(message, writer) { message.serializeBinaryToWriter(writer); }; /** * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ proto.helloworld.HelloReply.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); this.serializeBinaryToWriter(writer); return writer.getResultBuffer(); }; /** * Serializes the message to binary data (in protobuf wire format), * writing to the given BinaryWriter. * @param {!jspb.BinaryWriter} writer */ proto.helloworld.HelloReply.prototype.serializeBinaryToWriter = function (writer) { var f = undefined; f = this.getMessage(); if (f.length > 0) { writer.writeString( 1, f ); } }; /** * Creates a deep clone of this proto. No data is shared with the original. * @return {!proto.helloworld.HelloReply} The clone. */ proto.helloworld.HelloReply.prototype.cloneMessage = function() { return /** @type {!proto.helloworld.HelloReply} */ (jspb.Message.cloneMessage(this)); }; /** * optional string message = 1; * @return {string} */ proto.helloworld.HelloReply.prototype.getMessage = function() { return /** @type {string} */ (jspb.Message.getFieldProto3(this, 1, "")); }; /** @param {string} value */ proto.helloworld.HelloReply.prototype.setMessage = function(value) { jspb.Message.setField(this, 1, value); }; goog.object.extend(exports, proto.helloworld); grpc-1.3.2/examples/node/static_codegen/route_guide/000077500000000000000000000000001310511640000224705ustar00rootroot00000000000000grpc-1.3.2/examples/node/static_codegen/route_guide/README.md000066400000000000000000000003471310511640000237530ustar00rootroot00000000000000#gRPC Basics: Node.js sample code The files in this folder are the samples used in [gRPC Basics: Node.js][], a detailed tutorial for using gRPC in Node.js. [gRPC Basics: Node.js]:http://www.grpc.io/docs/tutorials/basic/node.html grpc-1.3.2/examples/node/static_codegen/route_guide/route_guide_client.js000066400000000000000000000177251310511640000267130ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ var messages = require('./route_guide_pb'); var services = require('./route_guide_grpc_pb'); var async = require('async'); var fs = require('fs'); var parseArgs = require('minimist'); var path = require('path'); var _ = require('lodash'); var grpc = require('grpc'); var client = new services.RouteGuideClient('localhost:50051', grpc.credentials.createInsecure()); var COORD_FACTOR = 1e7; /** * Run the getFeature demo. Calls getFeature with a point known to have a * feature and a point known not to have a feature. * @param {function} callback Called when this demo is complete */ function runGetFeature(callback) { var next = _.after(2, callback); function featureCallback(error, feature) { if (error) { callback(error); return; } var latitude = feature.getLocation().getLatitude(); var longitude = feature.getLocation().getLongitude(); if (feature.getName() === '') { console.log('Found no feature at ' + latitude/COORD_FACTOR + ', ' + longitude/COORD_FACTOR); } else { console.log('Found feature called "' + feature.getName() + '" at ' + latitude/COORD_FACTOR + ', ' + longitude/COORD_FACTOR); } next(); } var point1 = new messages.Point(); point1.setLatitude(409146138); point1.setLongitude(-746188906); var point2 = new messages.Point(); point2.setLatitude(0); point2.setLongitude(0); client.getFeature(point1, featureCallback); client.getFeature(point2, featureCallback); } /** * Run the listFeatures demo. Calls listFeatures with a rectangle containing all * of the features in the pre-generated database. Prints each response as it * comes in. * @param {function} callback Called when this demo is complete */ function runListFeatures(callback) { var rect = new messages.Rectangle(); var lo = new messages.Point(); lo.setLatitude(400000000); lo.setLongitude(-750000000); rect.setLo(lo); var hi = new messages.Point(); hi.setLatitude(420000000); hi.setLongitude(-730000000); rect.setHi(hi); console.log('Looking for features between 40, -75 and 42, -73'); var call = client.listFeatures(rect); call.on('data', function(feature) { console.log('Found feature called "' + feature.getName() + '" at ' + feature.getLocation().getLatitude()/COORD_FACTOR + ', ' + feature.getLocation().getLongitude()/COORD_FACTOR); }); call.on('end', callback); } /** * Run the recordRoute demo. Sends several randomly chosen points from the * pre-generated feature database with a variable delay in between. Prints the * statistics when they are sent from the server. * @param {function} callback Called when this demo is complete */ function runRecordRoute(callback) { var argv = parseArgs(process.argv, { string: 'db_path' }); fs.readFile(path.resolve(argv.db_path), function(err, data) { if (err) { callback(err); return; } // Transform the loaded features to Feature objects var feature_list = _.map(JSON.parse(data), function(value) { var feature = new messages.Feature(); feature.setName(value.name); var location = new messages.Point(); location.setLatitude(value.location.latitude); location.setLongitude(value.location.longitude); feature.setLocation(location); return feature; }); var num_points = 10; var call = client.recordRoute(function(error, stats) { if (error) { callback(error); return; } console.log('Finished trip with', stats.getPointCount(), 'points'); console.log('Passed', stats.getFeatureCount(), 'features'); console.log('Travelled', stats.getDistance(), 'meters'); console.log('It took', stats.getElapsedTime(), 'seconds'); callback(); }); /** * Constructs a function that asynchronously sends the given point and then * delays sending its callback * @param {messages.Point} location The point to send * @return {function(function)} The function that sends the point */ function pointSender(location) { /** * Sends the point, then calls the callback after a delay * @param {function} callback Called when complete */ return function(callback) { console.log('Visiting point ' + location.getLatitude()/COORD_FACTOR + ', ' + location.getLongitude()/COORD_FACTOR); call.write(location); _.delay(callback, _.random(500, 1500)); }; } var point_senders = []; for (var i = 0; i < num_points; i++) { var rand_point = feature_list[_.random(0, feature_list.length - 1)]; point_senders[i] = pointSender(rand_point.getLocation()); } async.series(point_senders, function() { call.end(); }); }); } /** * Run the routeChat demo. Send some chat messages, and print any chat messages * that are sent from the server. * @param {function} callback Called when the demo is complete */ function runRouteChat(callback) { var call = client.routeChat(); call.on('data', function(note) { console.log('Got message "' + note.getMessage() + '" at ' + note.getLocation().getLatitude() + ', ' + note.getLocation().getLongitude()); }); call.on('end', callback); var notes = [{ location: { latitude: 0, longitude: 0 }, message: 'First message' }, { location: { latitude: 0, longitude: 1 }, message: 'Second message' }, { location: { latitude: 1, longitude: 0 }, message: 'Third message' }, { location: { latitude: 0, longitude: 0 }, message: 'Fourth message' }]; for (var i = 0; i < notes.length; i++) { var note = notes[i]; console.log('Sending message "' + note.message + '" at ' + note.location.latitude + ', ' + note.location.longitude); var noteMsg = new messages.RouteNote(); noteMsg.setMessage(note.message); var location = new messages.Point(); location.setLatitude(note.location.latitude); location.setLongitude(note.location.longitude); noteMsg.setLocation(location); call.write(noteMsg); } call.end(); } /** * Run all of the demos in order */ function main() { async.series([ runGetFeature, runListFeatures, runRecordRoute, runRouteChat ]); } if (require.main === module) { main(); } exports.runGetFeature = runGetFeature; exports.runListFeatures = runListFeatures; exports.runRecordRoute = runRecordRoute; exports.runRouteChat = runRouteChat; grpc-1.3.2/examples/node/static_codegen/route_guide/route_guide_db.json000066400000000000000000000327101310511640000263460ustar00rootroot00000000000000[{ "location": { "latitude": 407838351, "longitude": -746143763 }, "name": "Patriots Path, Mendham, NJ 07945, USA" }, { "location": { "latitude": 408122808, "longitude": -743999179 }, "name": "101 New Jersey 10, Whippany, NJ 07981, USA" }, { "location": { "latitude": 413628156, "longitude": -749015468 }, "name": "U.S. 6, Shohola, PA 18458, USA" }, { "location": { "latitude": 419999544, "longitude": -740371136 }, "name": "5 Conners Road, Kingston, NY 12401, USA" }, { "location": { "latitude": 414008389, "longitude": -743951297 }, "name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA" }, { "location": { "latitude": 419611318, "longitude": -746524769 }, "name": "287 Flugertown Road, Livingston Manor, NY 12758, USA" }, { "location": { "latitude": 406109563, "longitude": -742186778 }, "name": "4001 Tremley Point Road, Linden, NJ 07036, USA" }, { "location": { "latitude": 416802456, "longitude": -742370183 }, "name": "352 South Mountain Road, Wallkill, NY 12589, USA" }, { "location": { "latitude": 412950425, "longitude": -741077389 }, "name": "Bailey Turn Road, Harriman, NY 10926, USA" }, { "location": { "latitude": 412144655, "longitude": -743949739 }, "name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA" }, { "location": { "latitude": 415736605, "longitude": -742847522 }, "name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA" }, { "location": { "latitude": 413843930, "longitude": -740501726 }, "name": "162 Merrill Road, Highland Mills, NY 10930, USA" }, { "location": { "latitude": 410873075, "longitude": -744459023 }, "name": "Clinton Road, West Milford, NJ 07480, USA" }, { "location": { "latitude": 412346009, "longitude": -744026814 }, "name": "16 Old Brook Lane, Warwick, NY 10990, USA" }, { "location": { "latitude": 402948455, "longitude": -747903913 }, "name": "3 Drake Lane, Pennington, NJ 08534, USA" }, { "location": { "latitude": 406337092, "longitude": -740122226 }, "name": "6324 8th Avenue, Brooklyn, NY 11220, USA" }, { "location": { "latitude": 406421967, "longitude": -747727624 }, "name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA" }, { "location": { "latitude": 416318082, "longitude": -749677716 }, "name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA" }, { "location": { "latitude": 415301720, "longitude": -748416257 }, "name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA" }, { "location": { "latitude": 402647019, "longitude": -747071791 }, "name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA" }, { "location": { "latitude": 412567807, "longitude": -741058078 }, "name": "New York State Reference Route 987E, Southfields, NY 10975, USA" }, { "location": { "latitude": 416855156, "longitude": -744420597 }, "name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA" }, { "location": { "latitude": 404663628, "longitude": -744820157 }, "name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA" }, { "location": { "latitude": 407113723, "longitude": -749746483 }, "name": "" }, { "location": { "latitude": 402133926, "longitude": -743613249 }, "name": "" }, { "location": { "latitude": 400273442, "longitude": -741220915 }, "name": "" }, { "location": { "latitude": 411236786, "longitude": -744070769 }, "name": "" }, { "location": { "latitude": 411633782, "longitude": -746784970 }, "name": "211-225 Plains Road, Augusta, NJ 07822, USA" }, { "location": { "latitude": 415830701, "longitude": -742952812 }, "name": "" }, { "location": { "latitude": 413447164, "longitude": -748712898 }, "name": "165 Pedersen Ridge Road, Milford, PA 18337, USA" }, { "location": { "latitude": 405047245, "longitude": -749800722 }, "name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA" }, { "location": { "latitude": 418858923, "longitude": -746156790 }, "name": "" }, { "location": { "latitude": 417951888, "longitude": -748484944 }, "name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA" }, { "location": { "latitude": 407033786, "longitude": -743977337 }, "name": "26 East 3rd Street, New Providence, NJ 07974, USA" }, { "location": { "latitude": 417548014, "longitude": -740075041 }, "name": "" }, { "location": { "latitude": 410395868, "longitude": -744972325 }, "name": "" }, { "location": { "latitude": 404615353, "longitude": -745129803 }, "name": "" }, { "location": { "latitude": 406589790, "longitude": -743560121 }, "name": "611 Lawrence Avenue, Westfield, NJ 07090, USA" }, { "location": { "latitude": 414653148, "longitude": -740477477 }, "name": "18 Lannis Avenue, New Windsor, NY 12553, USA" }, { "location": { "latitude": 405957808, "longitude": -743255336 }, "name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA" }, { "location": { "latitude": 411733589, "longitude": -741648093 }, "name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA" }, { "location": { "latitude": 412676291, "longitude": -742606606 }, "name": "1270 Lakes Road, Monroe, NY 10950, USA" }, { "location": { "latitude": 409224445, "longitude": -748286738 }, "name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA" }, { "location": { "latitude": 406523420, "longitude": -742135517 }, "name": "652 Garden Street, Elizabeth, NJ 07202, USA" }, { "location": { "latitude": 401827388, "longitude": -740294537 }, "name": "349 Sea Spray Court, Neptune City, NJ 07753, USA" }, { "location": { "latitude": 410564152, "longitude": -743685054 }, "name": "13-17 Stanley Street, West Milford, NJ 07480, USA" }, { "location": { "latitude": 408472324, "longitude": -740726046 }, "name": "47 Industrial Avenue, Teterboro, NJ 07608, USA" }, { "location": { "latitude": 412452168, "longitude": -740214052 }, "name": "5 White Oak Lane, Stony Point, NY 10980, USA" }, { "location": { "latitude": 409146138, "longitude": -746188906 }, "name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA" }, { "location": { "latitude": 404701380, "longitude": -744781745 }, "name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA" }, { "location": { "latitude": 409642566, "longitude": -746017679 }, "name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA" }, { "location": { "latitude": 408031728, "longitude": -748645385 }, "name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA" }, { "location": { "latitude": 413700272, "longitude": -742135189 }, "name": "367 Prospect Road, Chester, NY 10918, USA" }, { "location": { "latitude": 404310607, "longitude": -740282632 }, "name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA" }, { "location": { "latitude": 409319800, "longitude": -746201391 }, "name": "11 Ward Street, Mount Arlington, NJ 07856, USA" }, { "location": { "latitude": 406685311, "longitude": -742108603 }, "name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA" }, { "location": { "latitude": 419018117, "longitude": -749142781 }, "name": "43 Dreher Road, Roscoe, NY 12776, USA" }, { "location": { "latitude": 412856162, "longitude": -745148837 }, "name": "Swan Street, Pine Island, NY 10969, USA" }, { "location": { "latitude": 416560744, "longitude": -746721964 }, "name": "66 Pleasantview Avenue, Monticello, NY 12701, USA" }, { "location": { "latitude": 405314270, "longitude": -749836354 }, "name": "" }, { "location": { "latitude": 414219548, "longitude": -743327440 }, "name": "" }, { "location": { "latitude": 415534177, "longitude": -742900616 }, "name": "565 Winding Hills Road, Montgomery, NY 12549, USA" }, { "location": { "latitude": 406898530, "longitude": -749127080 }, "name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA" }, { "location": { "latitude": 407586880, "longitude": -741670168 }, "name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA" }, { "location": { "latitude": 400106455, "longitude": -742870190 }, "name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA" }, { "location": { "latitude": 400066188, "longitude": -746793294 }, "name": "" }, { "location": { "latitude": 418803880, "longitude": -744102673 }, "name": "40 Mountain Road, Napanoch, NY 12458, USA" }, { "location": { "latitude": 414204288, "longitude": -747895140 }, "name": "" }, { "location": { "latitude": 414777405, "longitude": -740615601 }, "name": "" }, { "location": { "latitude": 415464475, "longitude": -747175374 }, "name": "48 North Road, Forestburgh, NY 12777, USA" }, { "location": { "latitude": 404062378, "longitude": -746376177 }, "name": "" }, { "location": { "latitude": 405688272, "longitude": -749285130 }, "name": "" }, { "location": { "latitude": 400342070, "longitude": -748788996 }, "name": "" }, { "location": { "latitude": 401809022, "longitude": -744157964 }, "name": "" }, { "location": { "latitude": 404226644, "longitude": -740517141 }, "name": "9 Thompson Avenue, Leonardo, NJ 07737, USA" }, { "location": { "latitude": 410322033, "longitude": -747871659 }, "name": "" }, { "location": { "latitude": 407100674, "longitude": -747742727 }, "name": "" }, { "location": { "latitude": 418811433, "longitude": -741718005 }, "name": "213 Bush Road, Stone Ridge, NY 12484, USA" }, { "location": { "latitude": 415034302, "longitude": -743850945 }, "name": "" }, { "location": { "latitude": 411349992, "longitude": -743694161 }, "name": "" }, { "location": { "latitude": 404839914, "longitude": -744759616 }, "name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA" }, { "location": { "latitude": 414638017, "longitude": -745957854 }, "name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA" }, { "location": { "latitude": 412127800, "longitude": -740173578 }, "name": "" }, { "location": { "latitude": 401263460, "longitude": -747964303 }, "name": "" }, { "location": { "latitude": 412843391, "longitude": -749086026 }, "name": "" }, { "location": { "latitude": 418512773, "longitude": -743067823 }, "name": "" }, { "location": { "latitude": 404318328, "longitude": -740835638 }, "name": "42-102 Main Street, Belford, NJ 07718, USA" }, { "location": { "latitude": 419020746, "longitude": -741172328 }, "name": "" }, { "location": { "latitude": 404080723, "longitude": -746119569 }, "name": "" }, { "location": { "latitude": 401012643, "longitude": -744035134 }, "name": "" }, { "location": { "latitude": 404306372, "longitude": -741079661 }, "name": "" }, { "location": { "latitude": 403966326, "longitude": -748519297 }, "name": "" }, { "location": { "latitude": 405002031, "longitude": -748407866 }, "name": "" }, { "location": { "latitude": 409532885, "longitude": -742200683 }, "name": "" }, { "location": { "latitude": 416851321, "longitude": -742674555 }, "name": "" }, { "location": { "latitude": 406411633, "longitude": -741722051 }, "name": "3387 Richmond Terrace, Staten Island, NY 10303, USA" }, { "location": { "latitude": 413069058, "longitude": -744597778 }, "name": "261 Van Sickle Road, Goshen, NY 10924, USA" }, { "location": { "latitude": 418465462, "longitude": -746859398 }, "name": "" }, { "location": { "latitude": 411733222, "longitude": -744228360 }, "name": "" }, { "location": { "latitude": 410248224, "longitude": -747127767 }, "name": "3 Hasta Way, Newton, NJ 07860, USA" }] grpc-1.3.2/examples/node/static_codegen/route_guide/route_guide_grpc_pb.js000066400000000000000000000133561310511640000270450ustar00rootroot00000000000000// GENERATED CODE -- DO NOT EDIT! // Original file comments: // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // 'use strict'; var grpc = require('grpc'); var route_guide_pb = require('./route_guide_pb.js'); function serialize_Feature(arg) { if (!(arg instanceof route_guide_pb.Feature)) { throw new Error('Expected argument of type Feature'); } return new Buffer(arg.serializeBinary()); } function deserialize_Feature(buffer_arg) { return route_guide_pb.Feature.deserializeBinary(new Uint8Array(buffer_arg)); } function serialize_Point(arg) { if (!(arg instanceof route_guide_pb.Point)) { throw new Error('Expected argument of type Point'); } return new Buffer(arg.serializeBinary()); } function deserialize_Point(buffer_arg) { return route_guide_pb.Point.deserializeBinary(new Uint8Array(buffer_arg)); } function serialize_Rectangle(arg) { if (!(arg instanceof route_guide_pb.Rectangle)) { throw new Error('Expected argument of type Rectangle'); } return new Buffer(arg.serializeBinary()); } function deserialize_Rectangle(buffer_arg) { return route_guide_pb.Rectangle.deserializeBinary(new Uint8Array(buffer_arg)); } function serialize_RouteNote(arg) { if (!(arg instanceof route_guide_pb.RouteNote)) { throw new Error('Expected argument of type RouteNote'); } return new Buffer(arg.serializeBinary()); } function deserialize_RouteNote(buffer_arg) { return route_guide_pb.RouteNote.deserializeBinary(new Uint8Array(buffer_arg)); } function serialize_RouteSummary(arg) { if (!(arg instanceof route_guide_pb.RouteSummary)) { throw new Error('Expected argument of type RouteSummary'); } return new Buffer(arg.serializeBinary()); } function deserialize_RouteSummary(buffer_arg) { return route_guide_pb.RouteSummary.deserializeBinary(new Uint8Array(buffer_arg)); } // Interface exported by the server. var RouteGuideService = exports.RouteGuideService = { // A simple RPC. // // Obtains the feature at a given position. // // A feature with an empty name is returned if there's no feature at the given // position. getFeature: { path: '/routeguide.RouteGuide/GetFeature', requestStream: false, responseStream: false, requestType: route_guide_pb.Point, responseType: route_guide_pb.Feature, requestSerialize: serialize_Point, requestDeserialize: deserialize_Point, responseSerialize: serialize_Feature, responseDeserialize: deserialize_Feature, }, // A server-to-client streaming RPC. // // Obtains the Features available within the given Rectangle. Results are // streamed rather than returned at once (e.g. in a response message with a // repeated field), as the rectangle may cover a large area and contain a // huge number of features. listFeatures: { path: '/routeguide.RouteGuide/ListFeatures', requestStream: false, responseStream: true, requestType: route_guide_pb.Rectangle, responseType: route_guide_pb.Feature, requestSerialize: serialize_Rectangle, requestDeserialize: deserialize_Rectangle, responseSerialize: serialize_Feature, responseDeserialize: deserialize_Feature, }, // A client-to-server streaming RPC. // // Accepts a stream of Points on a route being traversed, returning a // RouteSummary when traversal is completed. recordRoute: { path: '/routeguide.RouteGuide/RecordRoute', requestStream: true, responseStream: false, requestType: route_guide_pb.Point, responseType: route_guide_pb.RouteSummary, requestSerialize: serialize_Point, requestDeserialize: deserialize_Point, responseSerialize: serialize_RouteSummary, responseDeserialize: deserialize_RouteSummary, }, // A Bidirectional streaming RPC. // // Accepts a stream of RouteNotes sent while a route is being traversed, // while receiving other RouteNotes (e.g. from other users). routeChat: { path: '/routeguide.RouteGuide/RouteChat', requestStream: true, responseStream: true, requestType: route_guide_pb.RouteNote, responseType: route_guide_pb.RouteNote, requestSerialize: serialize_RouteNote, requestDeserialize: deserialize_RouteNote, responseSerialize: serialize_RouteNote, responseDeserialize: deserialize_RouteNote, }, }; exports.RouteGuideClient = grpc.makeGenericClientConstructor(RouteGuideService); grpc-1.3.2/examples/node/static_codegen/route_guide/route_guide_pb.js000066400000000000000000000716231310511640000260330ustar00rootroot00000000000000/** * @fileoverview * @enhanceable * @public */ // GENERATED CODE -- DO NOT EDIT! var jspb = require('google-protobuf'); var goog = jspb; var global = Function('return this')(); goog.exportSymbol('proto.routeguide.Feature', null, global); goog.exportSymbol('proto.routeguide.Point', null, global); goog.exportSymbol('proto.routeguide.Rectangle', null, global); goog.exportSymbol('proto.routeguide.RouteNote', null, global); goog.exportSymbol('proto.routeguide.RouteSummary', null, global); /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a * server response, or constructed directly in Javascript. The array is used * in place and becomes part of the constructed object. It is not cloned. * If no data is provided, the constructed object will be empty, but still * valid. * @extends {jspb.Message} * @constructor */ proto.routeguide.Point = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; goog.inherits(proto.routeguide.Point, jspb.Message); if (goog.DEBUG && !COMPILED) { proto.routeguide.Point.displayName = 'proto.routeguide.Point'; } if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto suitable for use in Soy templates. * Field names that are reserved in JavaScript and will be renamed to pb_name. * To access a reserved field use, foo.pb_, eg, foo.pb_default. * For the list of reserved names please see: * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration * @return {!Object} */ proto.routeguide.Point.prototype.toObject = function(opt_includeInstance) { return proto.routeguide.Point.toObject(opt_includeInstance, this); }; /** * Static version of the {@see toObject} method. * @param {boolean|undefined} includeInstance Whether to include the JSPB * instance for transitional soy proto support: * http://goto/soy-param-migration * @param {!proto.routeguide.Point} msg The msg instance to transform. * @return {!Object} */ proto.routeguide.Point.toObject = function(includeInstance, msg) { var f, obj = { latitude: msg.getLatitude(), longitude: msg.getLongitude() }; if (includeInstance) { obj.$jspbMessageInstance = msg; } return obj; }; } /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. * @return {!proto.routeguide.Point} */ proto.routeguide.Point.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); var msg = new proto.routeguide.Point; return proto.routeguide.Point.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. * @param {!proto.routeguide.Point} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. * @return {!proto.routeguide.Point} */ proto.routeguide.Point.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); switch (field) { case 1: var value = /** @type {number} */ (reader.readInt32()); msg.setLatitude(value); break; case 2: var value = /** @type {number} */ (reader.readInt32()); msg.setLongitude(value); break; default: reader.skipField(); break; } } return msg; }; /** * Class method variant: serializes the given message to binary data * (in protobuf wire format), writing to the given BinaryWriter. * @param {!proto.routeguide.Point} message * @param {!jspb.BinaryWriter} writer */ proto.routeguide.Point.serializeBinaryToWriter = function(message, writer) { message.serializeBinaryToWriter(writer); }; /** * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ proto.routeguide.Point.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); this.serializeBinaryToWriter(writer); return writer.getResultBuffer(); }; /** * Serializes the message to binary data (in protobuf wire format), * writing to the given BinaryWriter. * @param {!jspb.BinaryWriter} writer */ proto.routeguide.Point.prototype.serializeBinaryToWriter = function (writer) { var f = undefined; f = this.getLatitude(); if (f !== 0) { writer.writeInt32( 1, f ); } f = this.getLongitude(); if (f !== 0) { writer.writeInt32( 2, f ); } }; /** * Creates a deep clone of this proto. No data is shared with the original. * @return {!proto.routeguide.Point} The clone. */ proto.routeguide.Point.prototype.cloneMessage = function() { return /** @type {!proto.routeguide.Point} */ (jspb.Message.cloneMessage(this)); }; /** * optional int32 latitude = 1; * @return {number} */ proto.routeguide.Point.prototype.getLatitude = function() { return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0)); }; /** @param {number} value */ proto.routeguide.Point.prototype.setLatitude = function(value) { jspb.Message.setField(this, 1, value); }; /** * optional int32 longitude = 2; * @return {number} */ proto.routeguide.Point.prototype.getLongitude = function() { return /** @type {number} */ (jspb.Message.getFieldProto3(this, 2, 0)); }; /** @param {number} value */ proto.routeguide.Point.prototype.setLongitude = function(value) { jspb.Message.setField(this, 2, value); }; /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a * server response, or constructed directly in Javascript. The array is used * in place and becomes part of the constructed object. It is not cloned. * If no data is provided, the constructed object will be empty, but still * valid. * @extends {jspb.Message} * @constructor */ proto.routeguide.Rectangle = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; goog.inherits(proto.routeguide.Rectangle, jspb.Message); if (goog.DEBUG && !COMPILED) { proto.routeguide.Rectangle.displayName = 'proto.routeguide.Rectangle'; } if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto suitable for use in Soy templates. * Field names that are reserved in JavaScript and will be renamed to pb_name. * To access a reserved field use, foo.pb_, eg, foo.pb_default. * For the list of reserved names please see: * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration * @return {!Object} */ proto.routeguide.Rectangle.prototype.toObject = function(opt_includeInstance) { return proto.routeguide.Rectangle.toObject(opt_includeInstance, this); }; /** * Static version of the {@see toObject} method. * @param {boolean|undefined} includeInstance Whether to include the JSPB * instance for transitional soy proto support: * http://goto/soy-param-migration * @param {!proto.routeguide.Rectangle} msg The msg instance to transform. * @return {!Object} */ proto.routeguide.Rectangle.toObject = function(includeInstance, msg) { var f, obj = { lo: (f = msg.getLo()) && proto.routeguide.Point.toObject(includeInstance, f), hi: (f = msg.getHi()) && proto.routeguide.Point.toObject(includeInstance, f) }; if (includeInstance) { obj.$jspbMessageInstance = msg; } return obj; }; } /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. * @return {!proto.routeguide.Rectangle} */ proto.routeguide.Rectangle.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); var msg = new proto.routeguide.Rectangle; return proto.routeguide.Rectangle.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. * @param {!proto.routeguide.Rectangle} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. * @return {!proto.routeguide.Rectangle} */ proto.routeguide.Rectangle.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); switch (field) { case 1: var value = new proto.routeguide.Point; reader.readMessage(value,proto.routeguide.Point.deserializeBinaryFromReader); msg.setLo(value); break; case 2: var value = new proto.routeguide.Point; reader.readMessage(value,proto.routeguide.Point.deserializeBinaryFromReader); msg.setHi(value); break; default: reader.skipField(); break; } } return msg; }; /** * Class method variant: serializes the given message to binary data * (in protobuf wire format), writing to the given BinaryWriter. * @param {!proto.routeguide.Rectangle} message * @param {!jspb.BinaryWriter} writer */ proto.routeguide.Rectangle.serializeBinaryToWriter = function(message, writer) { message.serializeBinaryToWriter(writer); }; /** * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ proto.routeguide.Rectangle.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); this.serializeBinaryToWriter(writer); return writer.getResultBuffer(); }; /** * Serializes the message to binary data (in protobuf wire format), * writing to the given BinaryWriter. * @param {!jspb.BinaryWriter} writer */ proto.routeguide.Rectangle.prototype.serializeBinaryToWriter = function (writer) { var f = undefined; f = this.getLo(); if (f != null) { writer.writeMessage( 1, f, proto.routeguide.Point.serializeBinaryToWriter ); } f = this.getHi(); if (f != null) { writer.writeMessage( 2, f, proto.routeguide.Point.serializeBinaryToWriter ); } }; /** * Creates a deep clone of this proto. No data is shared with the original. * @return {!proto.routeguide.Rectangle} The clone. */ proto.routeguide.Rectangle.prototype.cloneMessage = function() { return /** @type {!proto.routeguide.Rectangle} */ (jspb.Message.cloneMessage(this)); }; /** * optional Point lo = 1; * @return {proto.routeguide.Point} */ proto.routeguide.Rectangle.prototype.getLo = function() { return /** @type{proto.routeguide.Point} */ ( jspb.Message.getWrapperField(this, proto.routeguide.Point, 1)); }; /** @param {proto.routeguide.Point|undefined} value */ proto.routeguide.Rectangle.prototype.setLo = function(value) { jspb.Message.setWrapperField(this, 1, value); }; proto.routeguide.Rectangle.prototype.clearLo = function() { this.setLo(undefined); }; /** * optional Point hi = 2; * @return {proto.routeguide.Point} */ proto.routeguide.Rectangle.prototype.getHi = function() { return /** @type{proto.routeguide.Point} */ ( jspb.Message.getWrapperField(this, proto.routeguide.Point, 2)); }; /** @param {proto.routeguide.Point|undefined} value */ proto.routeguide.Rectangle.prototype.setHi = function(value) { jspb.Message.setWrapperField(this, 2, value); }; proto.routeguide.Rectangle.prototype.clearHi = function() { this.setHi(undefined); }; /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a * server response, or constructed directly in Javascript. The array is used * in place and becomes part of the constructed object. It is not cloned. * If no data is provided, the constructed object will be empty, but still * valid. * @extends {jspb.Message} * @constructor */ proto.routeguide.Feature = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; goog.inherits(proto.routeguide.Feature, jspb.Message); if (goog.DEBUG && !COMPILED) { proto.routeguide.Feature.displayName = 'proto.routeguide.Feature'; } if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto suitable for use in Soy templates. * Field names that are reserved in JavaScript and will be renamed to pb_name. * To access a reserved field use, foo.pb_, eg, foo.pb_default. * For the list of reserved names please see: * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration * @return {!Object} */ proto.routeguide.Feature.prototype.toObject = function(opt_includeInstance) { return proto.routeguide.Feature.toObject(opt_includeInstance, this); }; /** * Static version of the {@see toObject} method. * @param {boolean|undefined} includeInstance Whether to include the JSPB * instance for transitional soy proto support: * http://goto/soy-param-migration * @param {!proto.routeguide.Feature} msg The msg instance to transform. * @return {!Object} */ proto.routeguide.Feature.toObject = function(includeInstance, msg) { var f, obj = { name: msg.getName(), location: (f = msg.getLocation()) && proto.routeguide.Point.toObject(includeInstance, f) }; if (includeInstance) { obj.$jspbMessageInstance = msg; } return obj; }; } /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. * @return {!proto.routeguide.Feature} */ proto.routeguide.Feature.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); var msg = new proto.routeguide.Feature; return proto.routeguide.Feature.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. * @param {!proto.routeguide.Feature} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. * @return {!proto.routeguide.Feature} */ proto.routeguide.Feature.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); switch (field) { case 1: var value = /** @type {string} */ (reader.readString()); msg.setName(value); break; case 2: var value = new proto.routeguide.Point; reader.readMessage(value,proto.routeguide.Point.deserializeBinaryFromReader); msg.setLocation(value); break; default: reader.skipField(); break; } } return msg; }; /** * Class method variant: serializes the given message to binary data * (in protobuf wire format), writing to the given BinaryWriter. * @param {!proto.routeguide.Feature} message * @param {!jspb.BinaryWriter} writer */ proto.routeguide.Feature.serializeBinaryToWriter = function(message, writer) { message.serializeBinaryToWriter(writer); }; /** * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ proto.routeguide.Feature.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); this.serializeBinaryToWriter(writer); return writer.getResultBuffer(); }; /** * Serializes the message to binary data (in protobuf wire format), * writing to the given BinaryWriter. * @param {!jspb.BinaryWriter} writer */ proto.routeguide.Feature.prototype.serializeBinaryToWriter = function (writer) { var f = undefined; f = this.getName(); if (f.length > 0) { writer.writeString( 1, f ); } f = this.getLocation(); if (f != null) { writer.writeMessage( 2, f, proto.routeguide.Point.serializeBinaryToWriter ); } }; /** * Creates a deep clone of this proto. No data is shared with the original. * @return {!proto.routeguide.Feature} The clone. */ proto.routeguide.Feature.prototype.cloneMessage = function() { return /** @type {!proto.routeguide.Feature} */ (jspb.Message.cloneMessage(this)); }; /** * optional string name = 1; * @return {string} */ proto.routeguide.Feature.prototype.getName = function() { return /** @type {string} */ (jspb.Message.getFieldProto3(this, 1, "")); }; /** @param {string} value */ proto.routeguide.Feature.prototype.setName = function(value) { jspb.Message.setField(this, 1, value); }; /** * optional Point location = 2; * @return {proto.routeguide.Point} */ proto.routeguide.Feature.prototype.getLocation = function() { return /** @type{proto.routeguide.Point} */ ( jspb.Message.getWrapperField(this, proto.routeguide.Point, 2)); }; /** @param {proto.routeguide.Point|undefined} value */ proto.routeguide.Feature.prototype.setLocation = function(value) { jspb.Message.setWrapperField(this, 2, value); }; proto.routeguide.Feature.prototype.clearLocation = function() { this.setLocation(undefined); }; /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a * server response, or constructed directly in Javascript. The array is used * in place and becomes part of the constructed object. It is not cloned. * If no data is provided, the constructed object will be empty, but still * valid. * @extends {jspb.Message} * @constructor */ proto.routeguide.RouteNote = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; goog.inherits(proto.routeguide.RouteNote, jspb.Message); if (goog.DEBUG && !COMPILED) { proto.routeguide.RouteNote.displayName = 'proto.routeguide.RouteNote'; } if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto suitable for use in Soy templates. * Field names that are reserved in JavaScript and will be renamed to pb_name. * To access a reserved field use, foo.pb_, eg, foo.pb_default. * For the list of reserved names please see: * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration * @return {!Object} */ proto.routeguide.RouteNote.prototype.toObject = function(opt_includeInstance) { return proto.routeguide.RouteNote.toObject(opt_includeInstance, this); }; /** * Static version of the {@see toObject} method. * @param {boolean|undefined} includeInstance Whether to include the JSPB * instance for transitional soy proto support: * http://goto/soy-param-migration * @param {!proto.routeguide.RouteNote} msg The msg instance to transform. * @return {!Object} */ proto.routeguide.RouteNote.toObject = function(includeInstance, msg) { var f, obj = { location: (f = msg.getLocation()) && proto.routeguide.Point.toObject(includeInstance, f), message: msg.getMessage() }; if (includeInstance) { obj.$jspbMessageInstance = msg; } return obj; }; } /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. * @return {!proto.routeguide.RouteNote} */ proto.routeguide.RouteNote.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); var msg = new proto.routeguide.RouteNote; return proto.routeguide.RouteNote.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. * @param {!proto.routeguide.RouteNote} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. * @return {!proto.routeguide.RouteNote} */ proto.routeguide.RouteNote.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); switch (field) { case 1: var value = new proto.routeguide.Point; reader.readMessage(value,proto.routeguide.Point.deserializeBinaryFromReader); msg.setLocation(value); break; case 2: var value = /** @type {string} */ (reader.readString()); msg.setMessage(value); break; default: reader.skipField(); break; } } return msg; }; /** * Class method variant: serializes the given message to binary data * (in protobuf wire format), writing to the given BinaryWriter. * @param {!proto.routeguide.RouteNote} message * @param {!jspb.BinaryWriter} writer */ proto.routeguide.RouteNote.serializeBinaryToWriter = function(message, writer) { message.serializeBinaryToWriter(writer); }; /** * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ proto.routeguide.RouteNote.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); this.serializeBinaryToWriter(writer); return writer.getResultBuffer(); }; /** * Serializes the message to binary data (in protobuf wire format), * writing to the given BinaryWriter. * @param {!jspb.BinaryWriter} writer */ proto.routeguide.RouteNote.prototype.serializeBinaryToWriter = function (writer) { var f = undefined; f = this.getLocation(); if (f != null) { writer.writeMessage( 1, f, proto.routeguide.Point.serializeBinaryToWriter ); } f = this.getMessage(); if (f.length > 0) { writer.writeString( 2, f ); } }; /** * Creates a deep clone of this proto. No data is shared with the original. * @return {!proto.routeguide.RouteNote} The clone. */ proto.routeguide.RouteNote.prototype.cloneMessage = function() { return /** @type {!proto.routeguide.RouteNote} */ (jspb.Message.cloneMessage(this)); }; /** * optional Point location = 1; * @return {proto.routeguide.Point} */ proto.routeguide.RouteNote.prototype.getLocation = function() { return /** @type{proto.routeguide.Point} */ ( jspb.Message.getWrapperField(this, proto.routeguide.Point, 1)); }; /** @param {proto.routeguide.Point|undefined} value */ proto.routeguide.RouteNote.prototype.setLocation = function(value) { jspb.Message.setWrapperField(this, 1, value); }; proto.routeguide.RouteNote.prototype.clearLocation = function() { this.setLocation(undefined); }; /** * optional string message = 2; * @return {string} */ proto.routeguide.RouteNote.prototype.getMessage = function() { return /** @type {string} */ (jspb.Message.getFieldProto3(this, 2, "")); }; /** @param {string} value */ proto.routeguide.RouteNote.prototype.setMessage = function(value) { jspb.Message.setField(this, 2, value); }; /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a * server response, or constructed directly in Javascript. The array is used * in place and becomes part of the constructed object. It is not cloned. * If no data is provided, the constructed object will be empty, but still * valid. * @extends {jspb.Message} * @constructor */ proto.routeguide.RouteSummary = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; goog.inherits(proto.routeguide.RouteSummary, jspb.Message); if (goog.DEBUG && !COMPILED) { proto.routeguide.RouteSummary.displayName = 'proto.routeguide.RouteSummary'; } if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto suitable for use in Soy templates. * Field names that are reserved in JavaScript and will be renamed to pb_name. * To access a reserved field use, foo.pb_, eg, foo.pb_default. * For the list of reserved names please see: * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration * @return {!Object} */ proto.routeguide.RouteSummary.prototype.toObject = function(opt_includeInstance) { return proto.routeguide.RouteSummary.toObject(opt_includeInstance, this); }; /** * Static version of the {@see toObject} method. * @param {boolean|undefined} includeInstance Whether to include the JSPB * instance for transitional soy proto support: * http://goto/soy-param-migration * @param {!proto.routeguide.RouteSummary} msg The msg instance to transform. * @return {!Object} */ proto.routeguide.RouteSummary.toObject = function(includeInstance, msg) { var f, obj = { pointCount: msg.getPointCount(), featureCount: msg.getFeatureCount(), distance: msg.getDistance(), elapsedTime: msg.getElapsedTime() }; if (includeInstance) { obj.$jspbMessageInstance = msg; } return obj; }; } /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. * @return {!proto.routeguide.RouteSummary} */ proto.routeguide.RouteSummary.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); var msg = new proto.routeguide.RouteSummary; return proto.routeguide.RouteSummary.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. * @param {!proto.routeguide.RouteSummary} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. * @return {!proto.routeguide.RouteSummary} */ proto.routeguide.RouteSummary.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); switch (field) { case 1: var value = /** @type {number} */ (reader.readInt32()); msg.setPointCount(value); break; case 2: var value = /** @type {number} */ (reader.readInt32()); msg.setFeatureCount(value); break; case 3: var value = /** @type {number} */ (reader.readInt32()); msg.setDistance(value); break; case 4: var value = /** @type {number} */ (reader.readInt32()); msg.setElapsedTime(value); break; default: reader.skipField(); break; } } return msg; }; /** * Class method variant: serializes the given message to binary data * (in protobuf wire format), writing to the given BinaryWriter. * @param {!proto.routeguide.RouteSummary} message * @param {!jspb.BinaryWriter} writer */ proto.routeguide.RouteSummary.serializeBinaryToWriter = function(message, writer) { message.serializeBinaryToWriter(writer); }; /** * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ proto.routeguide.RouteSummary.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); this.serializeBinaryToWriter(writer); return writer.getResultBuffer(); }; /** * Serializes the message to binary data (in protobuf wire format), * writing to the given BinaryWriter. * @param {!jspb.BinaryWriter} writer */ proto.routeguide.RouteSummary.prototype.serializeBinaryToWriter = function (writer) { var f = undefined; f = this.getPointCount(); if (f !== 0) { writer.writeInt32( 1, f ); } f = this.getFeatureCount(); if (f !== 0) { writer.writeInt32( 2, f ); } f = this.getDistance(); if (f !== 0) { writer.writeInt32( 3, f ); } f = this.getElapsedTime(); if (f !== 0) { writer.writeInt32( 4, f ); } }; /** * Creates a deep clone of this proto. No data is shared with the original. * @return {!proto.routeguide.RouteSummary} The clone. */ proto.routeguide.RouteSummary.prototype.cloneMessage = function() { return /** @type {!proto.routeguide.RouteSummary} */ (jspb.Message.cloneMessage(this)); }; /** * optional int32 point_count = 1; * @return {number} */ proto.routeguide.RouteSummary.prototype.getPointCount = function() { return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0)); }; /** @param {number} value */ proto.routeguide.RouteSummary.prototype.setPointCount = function(value) { jspb.Message.setField(this, 1, value); }; /** * optional int32 feature_count = 2; * @return {number} */ proto.routeguide.RouteSummary.prototype.getFeatureCount = function() { return /** @type {number} */ (jspb.Message.getFieldProto3(this, 2, 0)); }; /** @param {number} value */ proto.routeguide.RouteSummary.prototype.setFeatureCount = function(value) { jspb.Message.setField(this, 2, value); }; /** * optional int32 distance = 3; * @return {number} */ proto.routeguide.RouteSummary.prototype.getDistance = function() { return /** @type {number} */ (jspb.Message.getFieldProto3(this, 3, 0)); }; /** @param {number} value */ proto.routeguide.RouteSummary.prototype.setDistance = function(value) { jspb.Message.setField(this, 3, value); }; /** * optional int32 elapsed_time = 4; * @return {number} */ proto.routeguide.RouteSummary.prototype.getElapsedTime = function() { return /** @type {number} */ (jspb.Message.getFieldProto3(this, 4, 0)); }; /** @param {number} value */ proto.routeguide.RouteSummary.prototype.setElapsedTime = function(value) { jspb.Message.setField(this, 4, value); }; goog.object.extend(exports, proto.routeguide); grpc-1.3.2/examples/node/static_codegen/route_guide/route_guide_server.js000066400000000000000000000211441310511640000267310ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ var messages = require('./route_guide_pb'); var services = require('./route_guide_grpc_pb'); var fs = require('fs'); var parseArgs = require('minimist'); var path = require('path'); var _ = require('lodash'); var grpc = require('grpc'); var COORD_FACTOR = 1e7; /** * For simplicity, a point is a record type that looks like * {latitude: number, longitude: number}, and a feature is a record type that * looks like {name: string, location: point}. feature objects with name==='' * are points with no feature. */ /** * List of feature objects at points that have been requested so far. */ var feature_list = []; /** * Get a feature object at the given point, or creates one if it does not exist. * @param {point} point The point to check * @return {feature} The feature object at the point. Note that an empty name * indicates no feature */ function checkFeature(point) { var feature; // Check if there is already a feature object for the given point for (var i = 0; i < feature_list.length; i++) { feature = feature_list[i]; if (feature.getLocation().getLatitude() === point.getLatitude() && feature.getLocation().getLongitude() === point.getLongitude()) { return feature; } } var name = ''; feature = new messages.Feature(); feature.setName(name); feature.setLocation(point); return feature; } /** * getFeature request handler. Gets a request with a point, and responds with a * feature object indicating whether there is a feature at that point. * @param {EventEmitter} call Call object for the handler to process * @param {function(Error, feature)} callback Response callback */ function getFeature(call, callback) { callback(null, checkFeature(call.request)); } /** * listFeatures request handler. Gets a request with two points, and responds * with a stream of all features in the bounding box defined by those points. * @param {Writable} call Writable stream for responses with an additional * request property for the request value. */ function listFeatures(call) { var lo = call.request.getLo(); var hi = call.request.getHi(); var left = _.min([lo.getLongitude(), hi.getLongitude()]); var right = _.max([lo.getLongitude(), hi.getLongitude()]); var top = _.max([lo.getLatitude(), hi.getLatitude()]); var bottom = _.min([lo.getLatitude(), hi.getLatitude()]); // For each feature, check if it is in the given bounding box _.each(feature_list, function(feature) { if (feature.getName() === '') { return; } if (feature.getLocation().getLongitude() >= left && feature.getLocation().getLongitude() <= right && feature.getLocation().getLatitude() >= bottom && feature.getLocation().getLatitude() <= top) { call.write(feature); } }); call.end(); } /** * Calculate the distance between two points using the "haversine" formula. * This code was taken from http://www.movable-type.co.uk/scripts/latlong.html. * @param start The starting point * @param end The end point * @return The distance between the points in meters */ function getDistance(start, end) { function toRadians(num) { return num * Math.PI / 180; } var lat1 = start.getLatitude() / COORD_FACTOR; var lat2 = end.getLatitude() / COORD_FACTOR; var lon1 = start.getLongitude() / COORD_FACTOR; var lon2 = end.getLongitude() / COORD_FACTOR; var R = 6371000; // metres var φ1 = toRadians(lat1); var φ2 = toRadians(lat2); var Δφ = toRadians(lat2-lat1); var Δλ = toRadians(lon2-lon1); var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) + Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ/2) * Math.sin(Δλ/2); var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); return R * c; } /** * recordRoute handler. Gets a stream of points, and responds with statistics * about the "trip": number of points, number of known features visited, total * distance traveled, and total time spent. * @param {Readable} call The request point stream. * @param {function(Error, routeSummary)} callback The callback to pass the * response to */ function recordRoute(call, callback) { var point_count = 0; var feature_count = 0; var distance = 0; var previous = null; // Start a timer var start_time = process.hrtime(); call.on('data', function(point) { point_count += 1; if (checkFeature(point).name !== '') { feature_count += 1; } /* For each point after the first, add the incremental distance from the * previous point to the total distance value */ if (previous != null) { distance += getDistance(previous, point); } previous = point; }); call.on('end', function() { var summary = new messages.RouteSummary(); summary.setPointCount(point_count); summary.setFeatureCount(feature_count); // Cast the distance to an integer summary.setDistance(distance|0); // End the timer summary.setElapsedTime(process.hrtime(start_time)[0]); callback(null, summary); }); } var route_notes = {}; /** * Turn the point into a dictionary key. * @param {point} point The point to use * @return {string} The key for an object */ function pointKey(point) { return point.getLatitude() + ' ' + point.getLongitude(); } /** * routeChat handler. Receives a stream of message/location pairs, and responds * with a stream of all previous messages at each of those locations. * @param {Duplex} call The stream for incoming and outgoing messages */ function routeChat(call) { call.on('data', function(note) { var key = pointKey(note.getLocation()); /* For each note sent, respond with all previous notes that correspond to * the same point */ if (route_notes.hasOwnProperty(key)) { _.each(route_notes[key], function(note) { call.write(note); }); } else { route_notes[key] = []; } // Then add the new note to the list route_notes[key].push(note); }); call.on('end', function() { call.end(); }); } /** * Get a new server with the handler functions in this file bound to the methods * it serves. * @return {Server} The new server object */ function getServer() { var server = new grpc.Server(); server.addService(services.RouteGuideService, { getFeature: getFeature, listFeatures: listFeatures, recordRoute: recordRoute, routeChat: routeChat }); return server; } if (require.main === module) { // If this is run as a script, start a server on an unused port var routeServer = getServer(); routeServer.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure()); var argv = parseArgs(process.argv, { string: 'db_path' }); fs.readFile(path.resolve(argv.db_path), function(err, data) { if (err) throw err; // Transform the loaded features to Feature objects feature_list = _.map(JSON.parse(data), function(value) { var feature = new messages.Feature(); feature.setName(value.name); var location = new messages.Point(); location.setLatitude(value.location.latitude); location.setLongitude(value.location.longitude); feature.setLocation(location); return feature; }); routeServer.start(); }); } exports.getServer = getServer; grpc-1.3.2/examples/objective-c/000077500000000000000000000000001310511640000164475ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/auth_sample/000077500000000000000000000000001310511640000207515ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/auth_sample/AuthSample.xcodeproj/000077500000000000000000000000001310511640000250105ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/auth_sample/AuthSample.xcodeproj/project.pbxproj000066400000000000000000000365521310511640000300770ustar00rootroot00000000000000// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 63E1E9821B28CB2100EF0978 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 63E1E9811B28CB2100EF0978 /* main.m */; }; 63E1E9851B28CB2100EF0978 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 63E1E9841B28CB2100EF0978 /* AppDelegate.m */; }; 63E1E9881B28CB2100EF0978 /* SelectUserViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 63E1E9871B28CB2100EF0978 /* SelectUserViewController.m */; }; 63E1E98B1B28CB2100EF0978 /* MakeRPCViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 63E1E98A1B28CB2100EF0978 /* MakeRPCViewController.m */; }; 63E1E98E1B28CB2100EF0978 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 63E1E98C1B28CB2100EF0978 /* Main.storyboard */; }; 63E1E9901B28CB2100EF0978 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 63E1E98F1B28CB2100EF0978 /* Images.xcassets */; }; 63F5DE481B28F5C100CDD07E /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 63F5DE471B28F5C100CDD07E /* GoogleService-Info.plist */; }; 832213142AB24DB816D02635 /* libPods-AuthSample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F217A6ECA7F5BD1D5FB5071B /* libPods-AuthSample.a */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 63E1E97C1B28CB2100EF0978 /* AuthSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AuthSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 63E1E9801B28CB2100EF0978 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 63E1E9811B28CB2100EF0978 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 63E1E9831B28CB2100EF0978 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 63E1E9841B28CB2100EF0978 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 63E1E9861B28CB2100EF0978 /* SelectUserViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SelectUserViewController.h; sourceTree = ""; }; 63E1E9871B28CB2100EF0978 /* SelectUserViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SelectUserViewController.m; sourceTree = ""; }; 63E1E9891B28CB2100EF0978 /* MakeRPCViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MakeRPCViewController.h; sourceTree = ""; }; 63E1E98A1B28CB2100EF0978 /* MakeRPCViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MakeRPCViewController.m; sourceTree = ""; }; 63E1E98D1B28CB2100EF0978 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 63E1E98F1B28CB2100EF0978 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 63F5DE471B28F5C100CDD07E /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; A387D6CECBCF2EAF2983033A /* Pods-AuthSample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AuthSample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AuthSample/Pods-AuthSample.debug.xcconfig"; sourceTree = ""; }; B444176735DA81FBE4B8B80C /* Pods-AuthSample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AuthSample.release.xcconfig"; path = "Pods/Target Support Files/Pods-AuthSample/Pods-AuthSample.release.xcconfig"; sourceTree = ""; }; F217A6ECA7F5BD1D5FB5071B /* libPods-AuthSample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AuthSample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 63E1E9791B28CB2000EF0978 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 832213142AB24DB816D02635 /* libPods-AuthSample.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 021FA0E0B3F5D3D477DDAC10 /* Pods */ = { isa = PBXGroup; children = ( A387D6CECBCF2EAF2983033A /* Pods-AuthSample.debug.xcconfig */, B444176735DA81FBE4B8B80C /* Pods-AuthSample.release.xcconfig */, ); name = Pods; sourceTree = ""; }; 4F443572636F3D60F26E870D /* Frameworks */ = { isa = PBXGroup; children = ( F217A6ECA7F5BD1D5FB5071B /* libPods-AuthSample.a */, ); name = Frameworks; sourceTree = ""; }; 63E1E9731B28CB2000EF0978 = { isa = PBXGroup; children = ( 63E1E97E1B28CB2100EF0978 /* AuthSample */, 63E1E97D1B28CB2100EF0978 /* Products */, 021FA0E0B3F5D3D477DDAC10 /* Pods */, 4F443572636F3D60F26E870D /* Frameworks */, ); sourceTree = ""; }; 63E1E97D1B28CB2100EF0978 /* Products */ = { isa = PBXGroup; children = ( 63E1E97C1B28CB2100EF0978 /* AuthSample.app */, ); name = Products; sourceTree = ""; }; 63E1E97E1B28CB2100EF0978 /* AuthSample */ = { isa = PBXGroup; children = ( 63E1E9861B28CB2100EF0978 /* SelectUserViewController.h */, 63E1E9871B28CB2100EF0978 /* SelectUserViewController.m */, 63E1E9891B28CB2100EF0978 /* MakeRPCViewController.h */, 63E1E98A1B28CB2100EF0978 /* MakeRPCViewController.m */, 63E1E97F1B28CB2100EF0978 /* Supporting Files */, ); name = AuthSample; sourceTree = SOURCE_ROOT; }; 63E1E97F1B28CB2100EF0978 /* Supporting Files */ = { isa = PBXGroup; children = ( 63E1E98C1B28CB2100EF0978 /* Main.storyboard */, 63F5DE471B28F5C100CDD07E /* GoogleService-Info.plist */, 63E1E98F1B28CB2100EF0978 /* Images.xcassets */, 63E1E9801B28CB2100EF0978 /* Info.plist */, 63E1E9831B28CB2100EF0978 /* AppDelegate.h */, 63E1E9841B28CB2100EF0978 /* AppDelegate.m */, 63E1E9811B28CB2100EF0978 /* main.m */, ); name = "Supporting Files"; path = Misc; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 63E1E97B1B28CB2000EF0978 /* AuthSample */ = { isa = PBXNativeTarget; buildConfigurationList = 63E1E9A21B28CB2100EF0978 /* Build configuration list for PBXNativeTarget "AuthSample" */; buildPhases = ( DAABBA7B5788A39108D7CA83 /* [CP] Check Pods Manifest.lock */, 63E1E9781B28CB2000EF0978 /* Sources */, 63E1E9791B28CB2000EF0978 /* Frameworks */, 63E1E97A1B28CB2000EF0978 /* Resources */, AEFCCC69DD59CE8F6EB769D7 /* [CP] Copy Pods Resources */, D24F6598302C412D4B863D6F /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); dependencies = ( ); name = AuthSample; productName = AuthSample; productReference = 63E1E97C1B28CB2100EF0978 /* AuthSample.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 63E1E9741B28CB2000EF0978 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0630; ORGANIZATIONNAME = gRPC; TargetAttributes = { 63E1E97B1B28CB2000EF0978 = { CreatedOnToolsVersion = 6.3.1; }; }; }; buildConfigurationList = 63E1E9771B28CB2000EF0978 /* Build configuration list for PBXProject "AuthSample" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 63E1E9731B28CB2000EF0978; productRefGroup = 63E1E97D1B28CB2100EF0978 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 63E1E97B1B28CB2000EF0978 /* AuthSample */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 63E1E97A1B28CB2000EF0978 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 63E1E98E1B28CB2100EF0978 /* Main.storyboard in Resources */, 63E1E9901B28CB2100EF0978 /* Images.xcassets in Resources */, 63F5DE481B28F5C100CDD07E /* GoogleService-Info.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ AEFCCC69DD59CE8F6EB769D7 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AuthSample/Pods-AuthSample-resources.sh\"\n"; showEnvVarsInLog = 0; }; D24F6598302C412D4B863D6F /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AuthSample/Pods-AuthSample-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; DAABBA7B5788A39108D7CA83 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 63E1E9781B28CB2000EF0978 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 63E1E98B1B28CB2100EF0978 /* MakeRPCViewController.m in Sources */, 63E1E9851B28CB2100EF0978 /* AppDelegate.m in Sources */, 63E1E9881B28CB2100EF0978 /* SelectUserViewController.m in Sources */, 63E1E9821B28CB2100EF0978 /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 63E1E98C1B28CB2100EF0978 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 63E1E98D1B28CB2100EF0978 /* Base */, ); name = Main.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 63E1E9A01B28CB2100EF0978 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.3; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 63E1E9A11B28CB2100EF0978 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.3; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; 63E1E9A31B28CB2100EF0978 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = A387D6CECBCF2EAF2983033A /* Pods-AuthSample.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Misc/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 63E1E9A41B28CB2100EF0978 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = B444176735DA81FBE4B8B80C /* Pods-AuthSample.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Misc/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 63E1E9771B28CB2000EF0978 /* Build configuration list for PBXProject "AuthSample" */ = { isa = XCConfigurationList; buildConfigurations = ( 63E1E9A01B28CB2100EF0978 /* Debug */, 63E1E9A11B28CB2100EF0978 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 63E1E9A21B28CB2100EF0978 /* Build configuration list for PBXNativeTarget "AuthSample" */ = { isa = XCConfigurationList; buildConfigurations = ( 63E1E9A31B28CB2100EF0978 /* Debug */, 63E1E9A41B28CB2100EF0978 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 63E1E9741B28CB2000EF0978 /* Project object */; } grpc-1.3.2/examples/objective-c/auth_sample/AuthSample.xcodeproj/project.xcworkspace/000077500000000000000000000000001310511640000310065ustar00rootroot00000000000000contents.xcworkspacedata000066400000000000000000000002331310511640000356670ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/auth_sample/AuthSample.xcodeproj/project.xcworkspace grpc-1.3.2/examples/objective-c/auth_sample/AuthSample.xcodeproj/xcshareddata/000077500000000000000000000000001310511640000274435ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/auth_sample/AuthSample.xcodeproj/xcshareddata/xcschemes/000077500000000000000000000000001310511640000314255ustar00rootroot00000000000000AuthSample.xcscheme000066400000000000000000000064131310511640000351360ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/auth_sample/AuthSample.xcodeproj/xcshareddata/xcschemes grpc-1.3.2/examples/objective-c/auth_sample/AuthTestService.podspec000066400000000000000000000043361310511640000254200ustar00rootroot00000000000000Pod::Spec.new do |s| s.name = "AuthTestService" s.version = "0.0.1" s.license = "New BSD" s.authors = { 'gRPC contributors' => 'grpc-io@googlegroups.com' } s.homepage = "http://www.grpc.io/" s.summary = "AuthTestService example" s.source = { :git => 'https://github.com/grpc/grpc.git' } s.ios.deployment_target = "7.1" s.osx.deployment_target = "10.9" # Base directory where the .proto files are. src = "../../protos" # Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients. s.dependency "!ProtoCompiler-gRPCPlugin", "~> 1.0" # Pods directory corresponding to this app's Podfile, relative to the location of this podspec. pods_root = 'Pods' # Path where Cocoapods downloads protoc and the gRPC plugin. protoc_dir = "#{pods_root}/!ProtoCompiler" protoc = "#{protoc_dir}/protoc" plugin = "#{pods_root}/!ProtoCompiler-gRPCPlugin/grpc_objective_c_plugin" # Directory where the generated files will be placed. dir = "#{pods_root}/#{s.name}" s.prepare_command = <<-CMD mkdir -p #{dir} #{protoc} \ --plugin=protoc-gen-grpc=#{plugin} \ --objc_out=#{dir} \ --grpc_out=#{dir} \ -I #{src} \ -I #{protoc_dir} \ #{src}/auth_sample.proto CMD # Files generated by protoc s.subspec "Messages" do |ms| ms.source_files = "#{dir}/*.pbobjc.{h,m}", "#{dir}/**/*.pbobjc.{h,m}" ms.header_mappings_dir = dir ms.requires_arc = false # The generated files depend on the protobuf runtime. ms.dependency "Protobuf" end # Files generated by the gRPC plugin s.subspec "Services" do |ss| ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}" ss.header_mappings_dir = dir ss.requires_arc = true # The generated files depend on the gRPC runtime, and on the files generated by protoc. ss.dependency "gRPC-ProtoRPC" ss.dependency "#{s.name}/Messages" end s.pod_target_xcconfig = { # This is needed by all pods that depend on Protobuf: 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1', # This is needed by all pods that depend on gRPC-RxLibrary: 'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES', } end grpc-1.3.2/examples/objective-c/auth_sample/MakeRPCViewController.h000066400000000000000000000033211310511640000252420ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import extern NSString * const kTestScope; @interface MakeRPCViewController : UIViewController @property(weak, nonatomic) IBOutlet UILabel *mainLabel; @end grpc-1.3.2/examples/objective-c/auth_sample/MakeRPCViewController.m000066400000000000000000000075421310511640000252600ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "MakeRPCViewController.h" #import #import #import NSString * const kTestScope = @"https://www.googleapis.com/auth/xapi.zoo"; static NSString * const kTestHostAddress = @"grpc-test.sandbox.googleapis.com"; // Category for RPC errors to create the descriptions as we want them to appear on our view. @interface NSError (AuthSample) - (NSString *)UIDescription; @end @implementation NSError (AuthSample) - (NSString *)UIDescription { if (self.code == GRPCErrorCodeUnauthenticated) { // Authentication error. OAuth2 specifies we'll receive a challenge header. // |userInfo[kGRPCHeadersKey]| is the dictionary of response headers. NSString *challengeHeader = self.userInfo[kGRPCHeadersKey][@"www-authenticate"] ?: @""; return [@"Invalid credentials. Server challenge:\n" stringByAppendingString:challengeHeader]; } else { // Any other error. return [NSString stringWithFormat:@"Unexpected RPC error %li: %@", (long)self.code, self.localizedDescription]; } } @end @implementation MakeRPCViewController - (void)viewWillAppear:(BOOL)animated { // Create a service client and a proto request as usual. AUTHTestService *client = [[AUTHTestService alloc] initWithHost:kTestHostAddress]; AUTHRequest *request = [AUTHRequest message]; request.fillUsername = YES; request.fillOauthScope = YES; // Create a not-yet-started RPC. We want to set the request headers on this object before starting // it. ProtoRPC *call = [client RPCToUnaryCallWithRequest:request handler:^(AUTHResponse *response, NSError *error) { if (response) { // This test server responds with the email and scope of the access token it receives. self.mainLabel.text = [NSString stringWithFormat:@"Used scope: %@ on behalf of user %@", response.oauthScope, response.username]; } else { self.mainLabel.text = error.UIDescription; } }]; // Set the access token to be used. NSString *accessToken = GIDSignIn.sharedInstance.currentUser.authentication.accessToken; call.requestHeaders[@"Authorization"] = [@"Bearer " stringByAppendingString:accessToken]; // Start the RPC. [call start]; self.mainLabel.text = @"Waiting for RPC to complete..."; } @end grpc-1.3.2/examples/objective-c/auth_sample/Misc/000077500000000000000000000000001310511640000216445ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/auth_sample/Misc/AppDelegate.h000066400000000000000000000032551310511640000241750ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @end grpc-1.3.2/examples/objective-c/auth_sample/Misc/AppDelegate.m000066400000000000000000000050261310511640000242000ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "AppDelegate.h" #import @implementation AppDelegate // As instructed in https://developers.google.com/identity/sign-in/ios/sign-in - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSError* configureError; [GGLContext.sharedInstance configureWithError: &configureError]; NSAssert(!configureError, @"Error configuring Google services: %@", configureError); return YES; } // As instructed in https://developers.google.com/identity/sign-in/ios/sign-in - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { // This will properly handle the URL that the application receives at the end of the // authentication process. return [GIDSignIn.sharedInstance handleURL:url sourceApplication:sourceApplication annotation:annotation]; } @end grpc-1.3.2/examples/objective-c/auth_sample/Misc/Base.lproj/000077500000000000000000000000001310511640000236435ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/auth_sample/Misc/Base.lproj/Main.storyboard000066400000000000000000000312321310511640000266420ustar00rootroot00000000000000 grpc-1.3.2/examples/objective-c/auth_sample/Misc/GoogleService-Info.plist000066400000000000000000000023461310511640000263540ustar00rootroot00000000000000 AD_UNIT_ID_FOR_BANNER_TEST redacted AD_UNIT_ID_FOR_INTERSTITIAL_TEST redacted CLIENT_ID 15087385131-lh9bpkiai9nls53uadju0if6k7un3uih.apps.googleusercontent.com REVERSED_CLIENT_ID com.googleusercontent.apps.15087385131-lh9bpkiai9nls53uadju0if6k7un3uih API_KEY redacted GCM_SENDER_ID redacted PLIST_VERSION 1 BUNDLE_ID io.grpc.AuthSample PROJECT_ID grpc-authsample STORAGE_BUCKET grpc-authsample.appspot.com IS_ADS_ENABLED IS_ANALYTICS_ENABLED IS_APPINVITE_ENABLED IS_GCM_ENABLED IS_SIGNIN_ENABLED GOOGLE_APP_ID 1:15087385131:ios:d547168abe3c362f DATABASE_URL https://grpc-authsample.firebaseio.com grpc-1.3.2/examples/objective-c/auth_sample/Misc/Images.xcassets/000077500000000000000000000000001310511640000247055ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/auth_sample/Misc/Images.xcassets/AppIcon.appiconset/000077500000000000000000000000001310511640000304025ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/auth_sample/Misc/Images.xcassets/AppIcon.appiconset/Contents.json000066400000000000000000000020651310511640000330750ustar00rootroot00000000000000{ "images" : [ { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } }grpc-1.3.2/examples/objective-c/auth_sample/Misc/Images.xcassets/first.imageset/000077500000000000000000000000001310511640000276315ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/auth_sample/Misc/Images.xcassets/first.imageset/Contents.json000066400000000000000000000002321310511640000323160ustar00rootroot00000000000000{ "images" : [ { "idiom" : "universal", "filename" : "first.pdf" } ], "info" : { "version" : 1, "author" : "xcode" } }grpc-1.3.2/examples/objective-c/auth_sample/Misc/Images.xcassets/first.imageset/first.pdf000066400000000000000000000046411310511640000314600ustar00rootroot00000000000000%PDF-1.3 %Äåòåë§ó ÐÄÆ 4 0 obj << /Length 5 0 R /Filter /FlateDecode >> stream x+TT(TÐw.6TH.V0Ãâd#SCS…\md gbaja‚ÄK¥’,õL M ÍŒ€ ¹”‚$+˜"äá ÁR ­psú‚mæJVÈPHÓR3ßÅ endstream endobj 5 0 obj 95 endobj 2 0 obj << /Type /Page /Parent 3 0 R /Resources 6 0 R /Contents 4 0 R >> endobj 6 0 obj << /ProcSet [ /PDF ] /ColorSpace << /Cs1 7 0 R >> >> endobj 8 0 obj << /Length 9 0 R /N 3 /Alternate /DeviceRGB /Filter /FlateDecode >> stream x…UßoÛT>‰oR¤? XG‡ŠÅ¯US[¹­ÆI“¥íJ¥éØ*$ä:7‰©Û鶪O{7ü@ÙH§kk?ì<Ê»øÎí¾kktüqóÝ‹mÇ6°nÆ¶ÂøØ¯±-ümR;`zŠ–¡Êðv x#=\Ó% ëoàYÐÚRÚ±£¥êùÐ#&Á?È>ÌÒ¹áЪþ¢þ©n¨_¨Ôß;j„;¦$}*}+ý(}'}/ýLŠtYº"ý$]•¾‘.9»ï½Ÿ%Ø{¯_aÝŠ]hÕkŸ5'SNÊ{äå”ü¼ü²<°¹_“§ä½ðì öÍ ý½t ³jMµ{-ñ4%ׯTÅ„«tYÛŸ“¦R6ÈÆØô#§v\œå–Šx:žŠ'H‰ï‹OÄÇâ3·ž¼ø^ø&°¦õþ“0::àm,L%È3â:qVEô t›ÐÍ]~ߢI«vÖ6ÊWÙ¯ª¯) |ʸ2]ÕG‡Í4Ïå(6w¸½Â‹£$¾ƒ"ŽèAÞû¾EvÝ mî[D‡ÿÂ;ëVh[¨}íõ¿Ú†ðN|æ3¢‹õº½âç£Hä‘S:°ßûéKâÝt·Ñx€÷UÏ'D;7ÿ®7;_"ÿÑeó?Yqx endstream endobj 9 0 obj 1047 endobj 7 0 obj [ /ICCBased 8 0 R ] endobj 3 0 obj << /Type /Pages /MediaBox [0 0 30 30] /Count 1 /Kids [ 2 0 R ] >> endobj 10 0 obj << /Type /Catalog /Pages 3 0 R >> endobj 11 0 obj (New Image) endobj 12 0 obj (Mac OS X 10.10 Quartz PDFContext) endobj 13 0 obj (Alex Raftis) endobj 14 0 obj (Opacity) endobj 15 0 obj (D:20140731232851Z00'00') endobj 1 0 obj << /Title 11 0 R /Author 13 0 R /Producer 12 0 R /Creator 14 0 R /CreationDate 15 0 R /ModDate 15 0 R >> endobj xref 0 16 0000000000 65535 f 0000001868 00000 n 0000000209 00000 n 0000001560 00000 n 0000000022 00000 n 0000000191 00000 n 0000000289 00000 n 0000001525 00000 n 0000000357 00000 n 0000001505 00000 n 0000001641 00000 n 0000001691 00000 n 0000001719 00000 n 0000001770 00000 n 0000001800 00000 n 0000001826 00000 n trailer << /Size 16 /Root 10 0 R /Info 1 0 R /ID [ ] >> startxref 1988 %%EOF grpc-1.3.2/examples/objective-c/auth_sample/Misc/Images.xcassets/second.imageset/000077500000000000000000000000001310511640000277555ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/auth_sample/Misc/Images.xcassets/second.imageset/Contents.json000066400000000000000000000002331310511640000324430ustar00rootroot00000000000000{ "images" : [ { "idiom" : "universal", "filename" : "second.pdf" } ], "info" : { "version" : 1, "author" : "xcode" } }grpc-1.3.2/examples/objective-c/auth_sample/Misc/Images.xcassets/second.imageset/second.pdf000066400000000000000000000045671310511640000317370ustar00rootroot00000000000000%PDF-1.3 %Äåòåë§ó ÐÄÆ 4 0 obj << /Length 5 0 R /Filter /FlateDecode >> stream x+TT(TÐw.6TH.V0Ãâd#3…\D9@6”2rÀr9  iZ Û>8 endstream endobj 5 0 obj 53 endobj 2 0 obj << /Type /Page /Parent 3 0 R /Resources 6 0 R /Contents 4 0 R >> endobj 6 0 obj << /ProcSet [ /PDF ] /ColorSpace << /Cs1 7 0 R >> >> endobj 8 0 obj << /Length 9 0 R /N 3 /Alternate /DeviceRGB /Filter /FlateDecode >> stream x…UßoÛT>‰oR¤? XG‡ŠÅ¯US[¹­ÆI“¥íJ¥éØ*$ä:7‰©Û鶪O{7ü@ÙH§kk?ì<Ê»øÎí¾kktüqóÝ‹mÇ6°nÆ¶ÂøØ¯±-ümR;`zŠ–¡Êðv x#=\Ó% ëoàYÐÚRÚ±£¥êùÐ#&Á?È>ÌÒ¹áЪþ¢þ©n¨_¨Ôß;j„;¦$}*}+ý(}'}/ýLŠtYº"ý$]•¾‘.9»ï½Ÿ%Ø{¯_aÝŠ]hÕkŸ5'SNÊ{äå”ü¼ü²<°¹_“§ä½ðì öÍ ý½t ³jMµ{-ñ4%ׯTÅ„«tYÛŸ“¦R6ÈÆØô#§v\œå–Šx:žŠ'H‰ï‹OÄÇâ3·ž¼ø^ø&°¦õþ“0::àm,L%È3â:qVEô t›ÐÍ]~ߢI«vÖ6ÊWÙ¯ª¯) |ʸ2]ÕG‡Í4Ïå(6w¸½Â‹£$¾ƒ"ŽèAÞû¾EvÝ mî[D‡ÿÂ;ëVh[¨}íõ¿Ú†ðN|æ3¢‹õº½âç£Hä‘S:°ßûéKâÝt·Ñx€÷UÏ'D;7ÿ®7;_"ÿÑeó?Yqx endstream endobj 9 0 obj 1047 endobj 7 0 obj [ /ICCBased 8 0 R ] endobj 3 0 obj << /Type /Pages /MediaBox [0 0 30 30] /Count 1 /Kids [ 2 0 R ] >> endobj 10 0 obj << /Type /Catalog /Pages 3 0 R >> endobj 11 0 obj (New Image) endobj 12 0 obj (Mac OS X 10.10 Quartz PDFContext) endobj 13 0 obj (Alex Raftis) endobj 14 0 obj (Opacity) endobj 15 0 obj (D:20140731232851Z00'00') endobj 1 0 obj << /Title 11 0 R /Author 13 0 R /Producer 12 0 R /Creator 14 0 R /CreationDate 15 0 R /ModDate 15 0 R >> endobj xref 0 16 0000000000 65535 f 0000001826 00000 n 0000000167 00000 n 0000001518 00000 n 0000000022 00000 n 0000000149 00000 n 0000000247 00000 n 0000001483 00000 n 0000000315 00000 n 0000001463 00000 n 0000001599 00000 n 0000001649 00000 n 0000001677 00000 n 0000001728 00000 n 0000001758 00000 n 0000001784 00000 n trailer << /Size 16 /Root 10 0 R /Info 1 0 R /ID [ ] >> startxref 1946 %%EOF grpc-1.3.2/examples/objective-c/auth_sample/Misc/Info.plist000066400000000000000000000043431310511640000236200ustar00rootroot00000000000000 CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier io.grpc.$(PRODUCT_NAME:rfc1034identifier) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleURLTypes CFBundleTypeRole Editor CFBundleURLName REVERSED_CLIENT_ID CFBundleURLSchemes com.googleusercontent.apps.15087385131-lh9bpkiai9nls53uadju0if6k7un3uih CFBundleTypeRole Editor CFBundleURLName BUNDLE_ID CFBundleURLSchemes io.grpc.AuthSample CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName Main UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UIStatusBarTintParameters UINavigationBar Style UIBarStyleDefault Translucent UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight grpc-1.3.2/examples/objective-c/auth_sample/Misc/main.m000066400000000000000000000033531310511640000227520ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import "AppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } grpc-1.3.2/examples/objective-c/auth_sample/Podfile000066400000000000000000000004561310511640000222630ustar00rootroot00000000000000source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' install! 'cocoapods', :deterministic_uuids => false target 'AuthSample' do # Depend on the generated AuthTestService library. pod 'AuthTestService', :path => '.' # Depend on Google's OAuth2 library pod 'Google/SignIn' end grpc-1.3.2/examples/objective-c/auth_sample/README.md000066400000000000000000000002541310511640000222310ustar00rootroot00000000000000#OAuth2 on gRPC: Objective-C This is the supporting code for the tutorial "[OAuth2 on gRPC: Objective-C](http://www.grpc.io/docs/tutorials/auth/oauth2-objective-c.html)." grpc-1.3.2/examples/objective-c/auth_sample/SelectUserViewController.h000066400000000000000000000036511310511640000261040ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import @interface SelectUserViewController : UIViewController @property(weak, nonatomic) IBOutlet GIDSignInButton *signInButton; @property(weak, nonatomic) IBOutlet UIButton *signOutButton; @property(weak, nonatomic) IBOutlet UILabel *mainLabel; @property(weak, nonatomic) IBOutlet UILabel *subLabel; @end grpc-1.3.2/examples/objective-c/auth_sample/SelectUserViewController.m000066400000000000000000000056761310511640000261220ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "SelectUserViewController.h" #import "MakeRPCViewController.h" @implementation SelectUserViewController - (void)viewDidLoad { [super viewDidLoad]; self.signOutButton.layer.cornerRadius = 5; self.signOutButton.hidden = YES; // As instructed in https://developers.google.com/identity/sign-in/ios/sign-in GIDSignIn *signIn = GIDSignIn.sharedInstance; signIn.delegate = self; signIn.uiDelegate = self; // As instructed in https://developers.google.com/identity/sign-in/ios/additional-scopes if (![signIn.scopes containsObject:kTestScope]) { signIn.scopes = [signIn.scopes arrayByAddingObject:kTestScope]; } [signIn signInSilently]; } - (void)signIn:(GIDSignIn *)signIn didSignInForUser:(GIDGoogleUser *)user withError:(NSError *)error { if (error) { // The user probably cancelled the sign-in flow. return; } self.mainLabel.text = [NSString stringWithFormat:@"User: %@", user.profile.email]; NSString *scopes = [user.accessibleScopes componentsJoinedByString:@", "]; scopes = scopes.length ? scopes : @"(none)"; self.subLabel.text = [NSString stringWithFormat:@"Scopes: %@", scopes]; self.signInButton.hidden = YES; self.signOutButton.hidden = NO; } - (IBAction)didTapSignOut { [GIDSignIn.sharedInstance signOut]; self.mainLabel.text = @"Please sign in."; self.subLabel.text = @""; self.signInButton.hidden = NO; self.signOutButton.hidden = YES; } @end grpc-1.3.2/examples/objective-c/helloworld/000077500000000000000000000000001310511640000206225ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/helloworld/HelloWorld.podspec000066400000000000000000000043231310511640000242560ustar00rootroot00000000000000Pod::Spec.new do |s| s.name = "HelloWorld" s.version = "0.0.1" s.license = "New BSD" s.authors = { 'gRPC contributors' => 'grpc-io@googlegroups.com' } s.homepage = "http://www.grpc.io/" s.summary = "HelloWorld example" s.source = { :git => 'https://github.com/grpc/grpc.git' } s.ios.deployment_target = "7.1" s.osx.deployment_target = "10.9" # Base directory where the .proto files are. src = "../../protos" # Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients. s.dependency "!ProtoCompiler-gRPCPlugin", "~> 1.0" # Pods directory corresponding to this app's Podfile, relative to the location of this podspec. pods_root = 'Pods' # Path where Cocoapods downloads protoc and the gRPC plugin. protoc_dir = "#{pods_root}/!ProtoCompiler" protoc = "#{protoc_dir}/protoc" plugin = "#{pods_root}/!ProtoCompiler-gRPCPlugin/grpc_objective_c_plugin" # Directory where the generated files will be placed. dir = "#{pods_root}/#{s.name}" s.prepare_command = <<-CMD mkdir -p #{dir} #{protoc} \ --plugin=protoc-gen-grpc=#{plugin} \ --objc_out=#{dir} \ --grpc_out=#{dir} \ -I #{src} \ -I #{protoc_dir} \ #{src}/helloworld.proto CMD # Files generated by protoc s.subspec "Messages" do |ms| ms.source_files = "#{dir}/*.pbobjc.{h,m}", "#{dir}/**/*.pbobjc.{h,m}" ms.header_mappings_dir = dir ms.requires_arc = false # The generated files depend on the protobuf runtime. ms.dependency "Protobuf" end # Files generated by the gRPC plugin s.subspec "Services" do |ss| ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}" ss.header_mappings_dir = dir ss.requires_arc = true # The generated files depend on the gRPC runtime, and on the files generated by protoc. ss.dependency "gRPC-ProtoRPC" ss.dependency "#{s.name}/Messages" end s.pod_target_xcconfig = { # This is needed by all pods that depend on Protobuf: 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1', # This is needed by all pods that depend on gRPC-RxLibrary: 'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES', } end grpc-1.3.2/examples/objective-c/helloworld/HelloWorld.xcodeproj/000077500000000000000000000000001310511640000246715ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/helloworld/HelloWorld.xcodeproj/project.pbxproj000066400000000000000000000333201310511640000277460ustar00rootroot00000000000000// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 5E3690661B2A23800040F884 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E3690651B2A23800040F884 /* main.m */; }; 5E3690691B2A23800040F884 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E3690681B2A23800040F884 /* AppDelegate.m */; }; 5E36906C1B2A23800040F884 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E36906B1B2A23800040F884 /* ViewController.m */; }; 5E36906F1B2A23800040F884 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5E36906D1B2A23800040F884 /* Main.storyboard */; }; 5E3690711B2A23800040F884 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5E3690701B2A23800040F884 /* Images.xcassets */; }; EF61CF6AE2536A31D47F0E63 /* libPods-HelloWorld.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6B4E1F55F8A2EC95A0E7EE88 /* libPods-HelloWorld.a */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 0C432EF610DB15C0F47A66BB /* Pods-HelloWorld.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloWorld.release.xcconfig"; path = "Pods/Target Support Files/Pods-HelloWorld/Pods-HelloWorld.release.xcconfig"; sourceTree = ""; }; 5E3690601B2A23800040F884 /* HelloWorld.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HelloWorld.app; sourceTree = BUILT_PRODUCTS_DIR; }; 5E3690641B2A23800040F884 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 5E3690651B2A23800040F884 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 5E3690671B2A23800040F884 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 5E3690681B2A23800040F884 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 5E36906B1B2A23800040F884 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 5E36906E1B2A23800040F884 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 5E3690701B2A23800040F884 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 6B4E1F55F8A2EC95A0E7EE88 /* libPods-HelloWorld.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-HelloWorld.a"; sourceTree = BUILT_PRODUCTS_DIR; }; DBDE3E48389499064CD664B8 /* Pods-HelloWorld.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloWorld.debug.xcconfig"; path = "Pods/Target Support Files/Pods-HelloWorld/Pods-HelloWorld.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 5E36905D1B2A23800040F884 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( EF61CF6AE2536A31D47F0E63 /* libPods-HelloWorld.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 5E3690571B2A23800040F884 = { isa = PBXGroup; children = ( 5E3690651B2A23800040F884 /* main.m */, 5E3690621B2A23800040F884 /* HelloWorld */, 5E3690611B2A23800040F884 /* Products */, BD9CE6458E7C4FF49A1DF69F /* Pods */, 66CEC7120220DDD2221DD075 /* Frameworks */, ); sourceTree = ""; }; 5E3690611B2A23800040F884 /* Products */ = { isa = PBXGroup; children = ( 5E3690601B2A23800040F884 /* HelloWorld.app */, ); name = Products; sourceTree = ""; }; 5E3690621B2A23800040F884 /* HelloWorld */ = { isa = PBXGroup; children = ( 5E3690631B2A23800040F884 /* Supporting Files */, ); path = HelloWorld; sourceTree = ""; }; 5E3690631B2A23800040F884 /* Supporting Files */ = { isa = PBXGroup; children = ( 5E3690701B2A23800040F884 /* Images.xcassets */, 5E36906D1B2A23800040F884 /* Main.storyboard */, 5E36906B1B2A23800040F884 /* ViewController.m */, 5E3690681B2A23800040F884 /* AppDelegate.m */, 5E3690671B2A23800040F884 /* AppDelegate.h */, 5E3690641B2A23800040F884 /* Info.plist */, ); name = "Supporting Files"; sourceTree = ""; }; 66CEC7120220DDD2221DD075 /* Frameworks */ = { isa = PBXGroup; children = ( 6B4E1F55F8A2EC95A0E7EE88 /* libPods-HelloWorld.a */, ); name = Frameworks; sourceTree = ""; }; BD9CE6458E7C4FF49A1DF69F /* Pods */ = { isa = PBXGroup; children = ( DBDE3E48389499064CD664B8 /* Pods-HelloWorld.debug.xcconfig */, 0C432EF610DB15C0F47A66BB /* Pods-HelloWorld.release.xcconfig */, ); name = Pods; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 5E36905F1B2A23800040F884 /* HelloWorld */ = { isa = PBXNativeTarget; buildConfigurationList = 5E3690831B2A23810040F884 /* Build configuration list for PBXNativeTarget "HelloWorld" */; buildPhases = ( ACF9162361FB8F24C70657DE /* [CP] Check Pods Manifest.lock */, 5E36905C1B2A23800040F884 /* Sources */, 5E36905D1B2A23800040F884 /* Frameworks */, 5E36905E1B2A23800040F884 /* Resources */, 4C7D815378D98AB3BFC1A7D5 /* [CP] Copy Pods Resources */, BB76529986A8BFAF19A385B1 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); dependencies = ( ); name = HelloWorld; productName = HelloWorld; productReference = 5E3690601B2A23800040F884 /* HelloWorld.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 5E3690581B2A23800040F884 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0620; ORGANIZATIONNAME = Google; TargetAttributes = { 5E36905F1B2A23800040F884 = { CreatedOnToolsVersion = 6.2; }; }; }; buildConfigurationList = 5E36905B1B2A23800040F884 /* Build configuration list for PBXProject "HelloWorld" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 5E3690571B2A23800040F884; productRefGroup = 5E3690611B2A23800040F884 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 5E36905F1B2A23800040F884 /* HelloWorld */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 5E36905E1B2A23800040F884 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 5E36906F1B2A23800040F884 /* Main.storyboard in Resources */, 5E3690711B2A23800040F884 /* Images.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 4C7D815378D98AB3BFC1A7D5 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-HelloWorld/Pods-HelloWorld-resources.sh\"\n"; showEnvVarsInLog = 0; }; ACF9162361FB8F24C70657DE /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; BB76529986A8BFAF19A385B1 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-HelloWorld/Pods-HelloWorld-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 5E36905C1B2A23800040F884 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 5E36906C1B2A23800040F884 /* ViewController.m in Sources */, 5E3690691B2A23800040F884 /* AppDelegate.m in Sources */, 5E3690661B2A23800040F884 /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 5E36906D1B2A23800040F884 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 5E36906E1B2A23800040F884 /* Base */, ); name = Main.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 5E3690811B2A23810040F884 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.2; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 5E3690821B2A23810040F884 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.2; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; 5E3690841B2A23810040F884 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = DBDE3E48389499064CD664B8 /* Pods-HelloWorld.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = HelloWorld/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 5E3690851B2A23810040F884 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 0C432EF610DB15C0F47A66BB /* Pods-HelloWorld.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = HelloWorld/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 5E36905B1B2A23800040F884 /* Build configuration list for PBXProject "HelloWorld" */ = { isa = XCConfigurationList; buildConfigurations = ( 5E3690811B2A23810040F884 /* Debug */, 5E3690821B2A23810040F884 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 5E3690831B2A23810040F884 /* Build configuration list for PBXNativeTarget "HelloWorld" */ = { isa = XCConfigurationList; buildConfigurations = ( 5E3690841B2A23810040F884 /* Debug */, 5E3690851B2A23810040F884 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 5E3690581B2A23800040F884 /* Project object */; } grpc-1.3.2/examples/objective-c/helloworld/HelloWorld.xcodeproj/project.xcworkspace/000077500000000000000000000000001310511640000306675ustar00rootroot00000000000000contents.xcworkspacedata000066400000000000000000000002331310511640000355500ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/helloworld/HelloWorld.xcodeproj/project.xcworkspace grpc-1.3.2/examples/objective-c/helloworld/HelloWorld.xcodeproj/xcshareddata/000077500000000000000000000000001310511640000273245ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/helloworld/HelloWorld.xcodeproj/xcshareddata/xcschemes/000077500000000000000000000000001310511640000313065ustar00rootroot00000000000000HelloWorld.xcscheme000066400000000000000000000064131310511640000350270ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/helloworld/HelloWorld.xcodeproj/xcshareddata/xcschemes grpc-1.3.2/examples/objective-c/helloworld/HelloWorld/000077500000000000000000000000001310511640000226755ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/helloworld/HelloWorld/AppDelegate.h000066400000000000000000000032551310511640000252260ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @end grpc-1.3.2/examples/objective-c/helloworld/HelloWorld/AppDelegate.m000066400000000000000000000031341310511640000252270ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "AppDelegate.h" @implementation AppDelegate @end grpc-1.3.2/examples/objective-c/helloworld/HelloWorld/Base.lproj/000077500000000000000000000000001310511640000246745ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/helloworld/HelloWorld/Base.lproj/Main.storyboard000066400000000000000000000030471310511640000276760ustar00rootroot00000000000000 grpc-1.3.2/examples/objective-c/helloworld/HelloWorld/Images.xcassets/000077500000000000000000000000001310511640000257365ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/helloworld/HelloWorld/Images.xcassets/AppIcon.appiconset/000077500000000000000000000000001310511640000314335ustar00rootroot00000000000000Contents.json000066400000000000000000000020651310511640000340470ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/helloworld/HelloWorld/Images.xcassets/AppIcon.appiconset{ "images" : [ { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } }grpc-1.3.2/examples/objective-c/helloworld/HelloWorld/Info.plist000066400000000000000000000027331310511640000246520ustar00rootroot00000000000000 CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier Google.$(PRODUCT_NAME:rfc1034identifier) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName Main UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight grpc-1.3.2/examples/objective-c/helloworld/HelloWorld/ViewController.m000066400000000000000000000032221310511640000260300ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import @interface ViewController : UIViewController @end @implementation ViewController @end grpc-1.3.2/examples/objective-c/helloworld/Podfile000066400000000000000000000003471310511640000221330ustar00rootroot00000000000000source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' install! 'cocoapods', :deterministic_uuids => false target 'HelloWorld' do # Depend on the generated HelloWorld library. pod 'HelloWorld', :path => '.' end grpc-1.3.2/examples/objective-c/helloworld/README.md000066400000000000000000000036451310511640000221110ustar00rootroot00000000000000#gRPC in 3 minutes (Objective-C) ## Installation To run this example you should have [Cocoapods](https://cocoapods.org/#install) installed, as well as the relevant tools to generate the client library code (and a server in another language, for testing). You can obtain the latter by following [these setup instructions](https://github.com/grpc/homebrew-grpc). ## Hello Objective-C gRPC! Here's how to build and run the Objective-C implementation of the [Hello World](../../protos/helloworld.proto) example used in [Getting started](https://github.com/grpc/grpc/tree/master/examples). The example code for this and our other examples lives in the `examples` directory. Clone this repository to your local machine by running the following commands: ```sh $ git clone -b $(curl -L http://grpc.io/release) https://github.com/grpc/grpc $ cd grpc $ git submodule update --init ``` Change your current directory to `examples/objective-c/helloworld` ```sh $ cd examples/objective-c/helloworld ``` ### Try it! To try the sample app, we need a gRPC server running locally. Let's compile and run, for example, the C++ server in this repository: ```shell $ pushd ../../cpp/helloworld $ make $ ./greeter_server & $ popd ``` Now have Cocoapods generate and install the client library for our .proto files: ```shell $ pod install ``` (This might have to compile OpenSSL, which takes around 15 minutes if Cocoapods doesn't have it yet on your computer's cache.) Finally, open the XCode workspace created by Cocoapods, and run the app. You can check the calling code in `main.m` and see the results in XCode's log console. The code sends a `HLWHelloRequest` containing the string "Objective-C" to a local server. The server responds with a `HLWHelloResponse`, which contains a string that is then output to the log. ## Tutorial You can find a more detailed tutorial in [gRPC Basics: Objective-C](http://www.grpc.io/docs/tutorials/basic/objective-c.html). grpc-1.3.2/examples/objective-c/helloworld/main.m000066400000000000000000000045351310511640000217330ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import "AppDelegate.h" #import #import #import static NSString * const kHostAddress = @"localhost:50051"; int main(int argc, char * argv[]) { @autoreleasepool { [GRPCCall useInsecureConnectionsForHost:kHostAddress]; [GRPCCall setUserAgentPrefix:@"HelloWorld/1.0" forHost:kHostAddress]; HLWGreeter *client = [[HLWGreeter alloc] initWithHost:kHostAddress]; HLWHelloRequest *request = [HLWHelloRequest message]; request.name = @"Objective-C"; [client sayHelloWithRequest:request handler:^(HLWHelloReply *response, NSError *error) { NSLog(@"%@", response.message); }]; return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } grpc-1.3.2/examples/objective-c/route_guide/000077500000000000000000000000001310511640000207625ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/route_guide/Misc/000077500000000000000000000000001310511640000216555ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/route_guide/Misc/AppDelegate.h000066400000000000000000000032551310511640000242060ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @end grpc-1.3.2/examples/objective-c/route_guide/Misc/AppDelegate.m000066400000000000000000000031341310511640000242070ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "AppDelegate.h" @implementation AppDelegate @end grpc-1.3.2/examples/objective-c/route_guide/Misc/Base.lproj/000077500000000000000000000000001310511640000236545ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/route_guide/Misc/Base.lproj/Main.storyboard000066400000000000000000000406141310511640000266570ustar00rootroot00000000000000 grpc-1.3.2/examples/objective-c/route_guide/Misc/Images.xcassets/000077500000000000000000000000001310511640000247165ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/route_guide/Misc/Images.xcassets/AppIcon.appiconset/000077500000000000000000000000001310511640000304135ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/route_guide/Misc/Images.xcassets/AppIcon.appiconset/Contents.json000066400000000000000000000020651310511640000331060ustar00rootroot00000000000000{ "images" : [ { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } }grpc-1.3.2/examples/objective-c/route_guide/Misc/Images.xcassets/first.imageset/000077500000000000000000000000001310511640000276425ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/route_guide/Misc/Images.xcassets/first.imageset/Contents.json000066400000000000000000000002321310511640000323270ustar00rootroot00000000000000{ "images" : [ { "idiom" : "universal", "filename" : "first.pdf" } ], "info" : { "version" : 1, "author" : "xcode" } }grpc-1.3.2/examples/objective-c/route_guide/Misc/Images.xcassets/first.imageset/first.pdf000066400000000000000000000046411310511640000314710ustar00rootroot00000000000000%PDF-1.3 %Äåòåë§ó ÐÄÆ 4 0 obj << /Length 5 0 R /Filter /FlateDecode >> stream x+TT(TÐw.6TH.V0Ãâd#SCS…\md gbaja‚ÄK¥’,õL M ÍŒ€ ¹”‚$+˜"äá ÁR ­psú‚mæJVÈPHÓR3ßÅ endstream endobj 5 0 obj 95 endobj 2 0 obj << /Type /Page /Parent 3 0 R /Resources 6 0 R /Contents 4 0 R >> endobj 6 0 obj << /ProcSet [ /PDF ] /ColorSpace << /Cs1 7 0 R >> >> endobj 8 0 obj << /Length 9 0 R /N 3 /Alternate /DeviceRGB /Filter /FlateDecode >> stream x…UßoÛT>‰oR¤? XG‡ŠÅ¯US[¹­ÆI“¥íJ¥éØ*$ä:7‰©Û鶪O{7ü@ÙH§kk?ì<Ê»øÎí¾kktüqóÝ‹mÇ6°nÆ¶ÂøØ¯±-ümR;`zŠ–¡Êðv x#=\Ó% ëoàYÐÚRÚ±£¥êùÐ#&Á?È>ÌÒ¹áЪþ¢þ©n¨_¨Ôß;j„;¦$}*}+ý(}'}/ýLŠtYº"ý$]•¾‘.9»ï½Ÿ%Ø{¯_aÝŠ]hÕkŸ5'SNÊ{äå”ü¼ü²<°¹_“§ä½ðì öÍ ý½t ³jMµ{-ñ4%ׯTÅ„«tYÛŸ“¦R6ÈÆØô#§v\œå–Šx:žŠ'H‰ï‹OÄÇâ3·ž¼ø^ø&°¦õþ“0::àm,L%È3â:qVEô t›ÐÍ]~ߢI«vÖ6ÊWÙ¯ª¯) |ʸ2]ÕG‡Í4Ïå(6w¸½Â‹£$¾ƒ"ŽèAÞû¾EvÝ mî[D‡ÿÂ;ëVh[¨}íõ¿Ú†ðN|æ3¢‹õº½âç£Hä‘S:°ßûéKâÝt·Ñx€÷UÏ'D;7ÿ®7;_"ÿÑeó?Yqx endstream endobj 9 0 obj 1047 endobj 7 0 obj [ /ICCBased 8 0 R ] endobj 3 0 obj << /Type /Pages /MediaBox [0 0 30 30] /Count 1 /Kids [ 2 0 R ] >> endobj 10 0 obj << /Type /Catalog /Pages 3 0 R >> endobj 11 0 obj (New Image) endobj 12 0 obj (Mac OS X 10.10 Quartz PDFContext) endobj 13 0 obj (Alex Raftis) endobj 14 0 obj (Opacity) endobj 15 0 obj (D:20140731232851Z00'00') endobj 1 0 obj << /Title 11 0 R /Author 13 0 R /Producer 12 0 R /Creator 14 0 R /CreationDate 15 0 R /ModDate 15 0 R >> endobj xref 0 16 0000000000 65535 f 0000001868 00000 n 0000000209 00000 n 0000001560 00000 n 0000000022 00000 n 0000000191 00000 n 0000000289 00000 n 0000001525 00000 n 0000000357 00000 n 0000001505 00000 n 0000001641 00000 n 0000001691 00000 n 0000001719 00000 n 0000001770 00000 n 0000001800 00000 n 0000001826 00000 n trailer << /Size 16 /Root 10 0 R /Info 1 0 R /ID [ ] >> startxref 1988 %%EOF grpc-1.3.2/examples/objective-c/route_guide/Misc/Images.xcassets/second.imageset/000077500000000000000000000000001310511640000277665ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/route_guide/Misc/Images.xcassets/second.imageset/Contents.json000066400000000000000000000002331310511640000324540ustar00rootroot00000000000000{ "images" : [ { "idiom" : "universal", "filename" : "second.pdf" } ], "info" : { "version" : 1, "author" : "xcode" } }grpc-1.3.2/examples/objective-c/route_guide/Misc/Images.xcassets/second.imageset/second.pdf000066400000000000000000000045671310511640000317500ustar00rootroot00000000000000%PDF-1.3 %Äåòåë§ó ÐÄÆ 4 0 obj << /Length 5 0 R /Filter /FlateDecode >> stream x+TT(TÐw.6TH.V0Ãâd#3…\D9@6”2rÀr9  iZ Û>8 endstream endobj 5 0 obj 53 endobj 2 0 obj << /Type /Page /Parent 3 0 R /Resources 6 0 R /Contents 4 0 R >> endobj 6 0 obj << /ProcSet [ /PDF ] /ColorSpace << /Cs1 7 0 R >> >> endobj 8 0 obj << /Length 9 0 R /N 3 /Alternate /DeviceRGB /Filter /FlateDecode >> stream x…UßoÛT>‰oR¤? XG‡ŠÅ¯US[¹­ÆI“¥íJ¥éØ*$ä:7‰©Û鶪O{7ü@ÙH§kk?ì<Ê»øÎí¾kktüqóÝ‹mÇ6°nÆ¶ÂøØ¯±-ümR;`zŠ–¡Êðv x#=\Ó% ëoàYÐÚRÚ±£¥êùÐ#&Á?È>ÌÒ¹áЪþ¢þ©n¨_¨Ôß;j„;¦$}*}+ý(}'}/ýLŠtYº"ý$]•¾‘.9»ï½Ÿ%Ø{¯_aÝŠ]hÕkŸ5'SNÊ{äå”ü¼ü²<°¹_“§ä½ðì öÍ ý½t ³jMµ{-ñ4%ׯTÅ„«tYÛŸ“¦R6ÈÆØô#§v\œå–Šx:žŠ'H‰ï‹OÄÇâ3·ž¼ø^ø&°¦õþ“0::àm,L%È3â:qVEô t›ÐÍ]~ߢI«vÖ6ÊWÙ¯ª¯) |ʸ2]ÕG‡Í4Ïå(6w¸½Â‹£$¾ƒ"ŽèAÞû¾EvÝ mî[D‡ÿÂ;ëVh[¨}íõ¿Ú†ðN|æ3¢‹õº½âç£Hä‘S:°ßûéKâÝt·Ñx€÷UÏ'D;7ÿ®7;_"ÿÑeó?Yqx endstream endobj 9 0 obj 1047 endobj 7 0 obj [ /ICCBased 8 0 R ] endobj 3 0 obj << /Type /Pages /MediaBox [0 0 30 30] /Count 1 /Kids [ 2 0 R ] >> endobj 10 0 obj << /Type /Catalog /Pages 3 0 R >> endobj 11 0 obj (New Image) endobj 12 0 obj (Mac OS X 10.10 Quartz PDFContext) endobj 13 0 obj (Alex Raftis) endobj 14 0 obj (Opacity) endobj 15 0 obj (D:20140731232851Z00'00') endobj 1 0 obj << /Title 11 0 R /Author 13 0 R /Producer 12 0 R /Creator 14 0 R /CreationDate 15 0 R /ModDate 15 0 R >> endobj xref 0 16 0000000000 65535 f 0000001826 00000 n 0000000167 00000 n 0000001518 00000 n 0000000022 00000 n 0000000149 00000 n 0000000247 00000 n 0000001483 00000 n 0000000315 00000 n 0000001463 00000 n 0000001599 00000 n 0000001649 00000 n 0000001677 00000 n 0000001728 00000 n 0000001758 00000 n 0000001784 00000 n trailer << /Size 16 /Root 10 0 R /Info 1 0 R /ID [ ] >> startxref 1946 %%EOF grpc-1.3.2/examples/objective-c/route_guide/Misc/Info.plist000066400000000000000000000032401310511640000236240ustar00rootroot00000000000000 CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier gRPC.$(PRODUCT_NAME:rfc1034identifier) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName Main UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UIStatusBarTintParameters UINavigationBar Style UIBarStyleDefault Translucent UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight grpc-1.3.2/examples/objective-c/route_guide/Misc/main.m000066400000000000000000000033511310511640000227610ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import "AppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } grpc-1.3.2/examples/objective-c/route_guide/Podfile000066400000000000000000000003551310511640000222720ustar00rootroot00000000000000source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' install! 'cocoapods', :deterministic_uuids => false target 'RouteGuideClient' do # Depend on the generated RouteGuide library. pod 'RouteGuide', :path => '.' end grpc-1.3.2/examples/objective-c/route_guide/README.md000066400000000000000000000002411310511640000222360ustar00rootroot00000000000000#gRPC Basics: Objective-C This is the supporting code for the tutorial "[gRPC Basics: Objective-C](http://www.grpc.io/docs/tutorials/basic/objective-c.html)." grpc-1.3.2/examples/objective-c/route_guide/RouteGuide.podspec000066400000000000000000000043241310511640000244200ustar00rootroot00000000000000Pod::Spec.new do |s| s.name = "RouteGuide" s.version = "0.0.1" s.license = "New BSD" s.authors = { 'gRPC contributors' => 'grpc-io@googlegroups.com' } s.homepage = "http://www.grpc.io/" s.summary = "RouteGuide example" s.source = { :git => 'https://github.com/grpc/grpc.git' } s.ios.deployment_target = "7.1" s.osx.deployment_target = "10.9" # Base directory where the .proto files are. src = "../../protos" # Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients. s.dependency "!ProtoCompiler-gRPCPlugin", "~> 1.0" # Pods directory corresponding to this app's Podfile, relative to the location of this podspec. pods_root = 'Pods' # Path where Cocoapods downloads protoc and the gRPC plugin. protoc_dir = "#{pods_root}/!ProtoCompiler" protoc = "#{protoc_dir}/protoc" plugin = "#{pods_root}/!ProtoCompiler-gRPCPlugin/grpc_objective_c_plugin" # Directory where the generated files will be placed. dir = "#{pods_root}/#{s.name}" s.prepare_command = <<-CMD mkdir -p #{dir} #{protoc} \ --plugin=protoc-gen-grpc=#{plugin} \ --objc_out=#{dir} \ --grpc_out=#{dir} \ -I #{src} \ -I #{protoc_dir} \ #{src}/route_guide.proto CMD # Files generated by protoc s.subspec "Messages" do |ms| ms.source_files = "#{dir}/*.pbobjc.{h,m}", "#{dir}/**/*.pbobjc.{h,m}" ms.header_mappings_dir = dir ms.requires_arc = false # The generated files depend on the protobuf runtime. ms.dependency "Protobuf" end # Files generated by the gRPC plugin s.subspec "Services" do |ss| ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}" ss.header_mappings_dir = dir ss.requires_arc = true # The generated files depend on the gRPC runtime, and on the files generated by protoc. ss.dependency "gRPC-ProtoRPC" ss.dependency "#{s.name}/Messages" end s.pod_target_xcconfig = { # This is needed by all pods that depend on Protobuf: 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1', # This is needed by all pods that depend on gRPC-RxLibrary: 'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES', } end grpc-1.3.2/examples/objective-c/route_guide/RouteGuideClient.xcodeproj/000077500000000000000000000000001310511640000261715ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/route_guide/RouteGuideClient.xcodeproj/project.pbxproj000066400000000000000000000353531310511640000312560ustar00rootroot00000000000000// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 124E20A2FC8EAE54460D4ED2 /* libPods-RouteGuideClient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 71CEE03D66D40FC37264D6E4 /* libPods-RouteGuideClient.a */; }; 632527831B1D0396003073D9 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 632527821B1D0396003073D9 /* main.m */; }; 632527861B1D0396003073D9 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 632527851B1D0396003073D9 /* AppDelegate.m */; }; 6325278F1B1D0396003073D9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6325278D1B1D0396003073D9 /* Main.storyboard */; }; 632527911B1D0396003073D9 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 632527901B1D0396003073D9 /* Images.xcassets */; }; 6367B55B1B223AFA008861F5 /* route_guide_db.json in Resources */ = {isa = PBXBuildFile; fileRef = 6367B55A1B223AFA008861F5 /* route_guide_db.json */; }; 63A6015C1B1DAB5000FA5B86 /* ViewControllers.m in Sources */ = {isa = PBXBuildFile; fileRef = 63A6015B1B1DAB5000FA5B86 /* ViewControllers.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 6325277D1B1D0396003073D9 /* RouteGuideClient.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RouteGuideClient.app; sourceTree = BUILT_PRODUCTS_DIR; }; 632527811B1D0396003073D9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 632527821B1D0396003073D9 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 632527841B1D0396003073D9 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 632527851B1D0396003073D9 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 6325278E1B1D0396003073D9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 632527901B1D0396003073D9 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 6367B55A1B223AFA008861F5 /* route_guide_db.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = route_guide_db.json; sourceTree = ""; }; 63A6015B1B1DAB5000FA5B86 /* ViewControllers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewControllers.m; sourceTree = ""; }; 71CEE03D66D40FC37264D6E4 /* libPods-RouteGuideClient.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RouteGuideClient.a"; sourceTree = BUILT_PRODUCTS_DIR; }; ADA4C647BAE906F79AD9A45E /* Pods-RouteGuideClient.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RouteGuideClient.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RouteGuideClient/Pods-RouteGuideClient.debug.xcconfig"; sourceTree = ""; }; C83C5A54D1A4EA07569F1AED /* Pods-RouteGuideClient.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RouteGuideClient.release.xcconfig"; path = "Pods/Target Support Files/Pods-RouteGuideClient/Pods-RouteGuideClient.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 6325277A1B1D0395003073D9 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 124E20A2FC8EAE54460D4ED2 /* libPods-RouteGuideClient.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 56849C29DC376BF4B902CD77 /* Pods */ = { isa = PBXGroup; children = ( ADA4C647BAE906F79AD9A45E /* Pods-RouteGuideClient.debug.xcconfig */, C83C5A54D1A4EA07569F1AED /* Pods-RouteGuideClient.release.xcconfig */, ); name = Pods; sourceTree = ""; }; 631C63891B1DBC41001295D5 /* Misc */ = { isa = PBXGroup; children = ( 632527841B1D0396003073D9 /* AppDelegate.h */, 632527851B1D0396003073D9 /* AppDelegate.m */, 632527901B1D0396003073D9 /* Images.xcassets */, 632527801B1D0396003073D9 /* Supporting Files */, ); path = Misc; sourceTree = ""; }; 632527741B1D0395003073D9 = { isa = PBXGroup; children = ( 6325277F1B1D0396003073D9 /* RouteGuideClient */, 6325277E1B1D0396003073D9 /* Products */, 56849C29DC376BF4B902CD77 /* Pods */, 7482B8A18481F7B13ADE4530 /* Frameworks */, ); sourceTree = ""; }; 6325277E1B1D0396003073D9 /* Products */ = { isa = PBXGroup; children = ( 6325277D1B1D0396003073D9 /* RouteGuideClient.app */, ); name = Products; sourceTree = ""; }; 6325277F1B1D0396003073D9 /* RouteGuideClient */ = { isa = PBXGroup; children = ( 63A6015B1B1DAB5000FA5B86 /* ViewControllers.m */, 6367B55A1B223AFA008861F5 /* route_guide_db.json */, 6325278D1B1D0396003073D9 /* Main.storyboard */, 631C63891B1DBC41001295D5 /* Misc */, ); name = RouteGuideClient; sourceTree = SOURCE_ROOT; }; 632527801B1D0396003073D9 /* Supporting Files */ = { isa = PBXGroup; children = ( 632527811B1D0396003073D9 /* Info.plist */, 632527821B1D0396003073D9 /* main.m */, ); name = "Supporting Files"; sourceTree = ""; }; 7482B8A18481F7B13ADE4530 /* Frameworks */ = { isa = PBXGroup; children = ( 71CEE03D66D40FC37264D6E4 /* libPods-RouteGuideClient.a */, ); name = Frameworks; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 6325277C1B1D0395003073D9 /* RouteGuideClient */ = { isa = PBXNativeTarget; buildConfigurationList = 632527A31B1D0396003073D9 /* Build configuration list for PBXNativeTarget "RouteGuideClient" */; buildPhases = ( C6FC30AD2376EC04317237C5 /* [CP] Check Pods Manifest.lock */, 632527791B1D0395003073D9 /* Sources */, 6325277A1B1D0395003073D9 /* Frameworks */, 6325277B1B1D0395003073D9 /* Resources */, FFE0BCF30339E7A50A989EAB /* [CP] Copy Pods Resources */, B5388EC5A25E89021740B916 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); dependencies = ( ); name = RouteGuideClient; productName = RouteGuideClient; productReference = 6325277D1B1D0396003073D9 /* RouteGuideClient.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 632527751B1D0395003073D9 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0630; ORGANIZATIONNAME = gRPC; TargetAttributes = { 6325277C1B1D0395003073D9 = { CreatedOnToolsVersion = 6.3.1; }; }; }; buildConfigurationList = 632527781B1D0395003073D9 /* Build configuration list for PBXProject "RouteGuideClient" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 632527741B1D0395003073D9; productRefGroup = 6325277E1B1D0396003073D9 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 6325277C1B1D0395003073D9 /* RouteGuideClient */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 6325277B1B1D0395003073D9 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 6325278F1B1D0396003073D9 /* Main.storyboard in Resources */, 632527911B1D0396003073D9 /* Images.xcassets in Resources */, 6367B55B1B223AFA008861F5 /* route_guide_db.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ B5388EC5A25E89021740B916 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RouteGuideClient/Pods-RouteGuideClient-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; C6FC30AD2376EC04317237C5 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; FFE0BCF30339E7A50A989EAB /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RouteGuideClient/Pods-RouteGuideClient-resources.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 632527791B1D0395003073D9 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 632527861B1D0396003073D9 /* AppDelegate.m in Sources */, 632527831B1D0396003073D9 /* main.m in Sources */, 63A6015C1B1DAB5000FA5B86 /* ViewControllers.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 6325278D1B1D0396003073D9 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 6325278E1B1D0396003073D9 /* Base */, ); name = Main.storyboard; path = Misc; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 632527A11B1D0396003073D9 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.3; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 632527A21B1D0396003073D9 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.3; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; 632527A41B1D0396003073D9 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = ADA4C647BAE906F79AD9A45E /* Pods-RouteGuideClient.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Misc/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 632527A51B1D0396003073D9 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = C83C5A54D1A4EA07569F1AED /* Pods-RouteGuideClient.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Misc/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 632527781B1D0395003073D9 /* Build configuration list for PBXProject "RouteGuideClient" */ = { isa = XCConfigurationList; buildConfigurations = ( 632527A11B1D0396003073D9 /* Debug */, 632527A21B1D0396003073D9 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 632527A31B1D0396003073D9 /* Build configuration list for PBXNativeTarget "RouteGuideClient" */ = { isa = XCConfigurationList; buildConfigurations = ( 632527A41B1D0396003073D9 /* Debug */, 632527A51B1D0396003073D9 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 632527751B1D0395003073D9 /* Project object */; } grpc-1.3.2/examples/objective-c/route_guide/RouteGuideClient.xcodeproj/project.xcworkspace/000077500000000000000000000000001310511640000321675ustar00rootroot00000000000000contents.xcworkspacedata000066400000000000000000000002411310511640000370470ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/route_guide/RouteGuideClient.xcodeproj/project.xcworkspace grpc-1.3.2/examples/objective-c/route_guide/RouteGuideClient.xcodeproj/xcshareddata/000077500000000000000000000000001310511640000306245ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/route_guide/RouteGuideClient.xcodeproj/xcshareddata/xcschemes/000077500000000000000000000000001310511640000326065ustar00rootroot00000000000000RouteGuideClient.xcscheme000066400000000000000000000065231310511640000374710ustar00rootroot00000000000000grpc-1.3.2/examples/objective-c/route_guide/RouteGuideClient.xcodeproj/xcshareddata/xcschemes grpc-1.3.2/examples/objective-c/route_guide/ViewControllers.m000066400000000000000000000260531310511640000243070ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import #import #import #import static NSString * const kHostAddress = @"localhost:50051"; /** Category to override RTGPoint's description. */ @interface RTGPoint (Description) - (NSString *)description; @end @implementation RTGPoint (Description) - (NSString *)description { NSString *verticalDirection = self.latitude >= 0 ? @"N" : @"S"; NSString *horizontalDirection = self.longitude >= 0 ? @"E" : @"W"; return [NSString stringWithFormat:@"%.02f%@ %.02f%@", abs(self.latitude) / 1E7f, verticalDirection, abs(self.longitude) / 1E7f, horizontalDirection]; } @end /** Category to give RTGRouteNote a convenience constructor. */ @interface RTGRouteNote (Constructors) + (instancetype)noteWithMessage:(NSString *)message latitude:(float)latitude longitude:(float)longitude; @end @implementation RTGRouteNote (Constructors) + (instancetype)noteWithMessage:(NSString *)message latitude:(float)latitude longitude:(float)longitude { RTGRouteNote *note = [self message]; note.message = message; note.location.latitude = (int32_t) latitude * 1E7; note.location.longitude = (int32_t) longitude * 1E7; return note; } @end #pragma mark Demo: Get Feature /** * Run the getFeature demo. Calls getFeature with a point known to have a feature and a point known * not to have a feature. */ @interface GetFeatureViewController : UIViewController @property (weak, nonatomic) IBOutlet UILabel *outputLabel; @end @implementation GetFeatureViewController { RTGRouteGuide *_service; } - (void)execRequest { void (^handler)(RTGFeature *response, NSError *error) = ^(RTGFeature *response, NSError *error) { // TODO(makdharma): Remove boilerplate by consolidating into one log function. if (response.name.length) { NSString *str =[NSString stringWithFormat:@"%@\nFound feature called %@ at %@.", self.outputLabel.text, response.location, response.name]; self.outputLabel.text = str; NSLog(@"Found feature called %@ at %@.", response.name, response.location); } else if (response) { NSString *str =[NSString stringWithFormat:@"%@\nFound no features at %@", self.outputLabel.text,response.location]; self.outputLabel.text = str; NSLog(@"Found no features at %@", response.location); } else { NSString *str =[NSString stringWithFormat:@"%@\nRPC error: %@", self.outputLabel.text, error]; self.outputLabel.text = str; NSLog(@"RPC error: %@", error); } }; RTGPoint *point = [RTGPoint message]; point.latitude = 409146138; point.longitude = -746188906; [_service getFeatureWithRequest:point handler:handler]; [_service getFeatureWithRequest:[RTGPoint message] handler:handler]; } - (void)viewDidLoad { [super viewDidLoad]; // This only needs to be done once per host, before creating service objects for that host. [GRPCCall useInsecureConnectionsForHost:kHostAddress]; _service = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; } - (void)viewDidAppear:(BOOL)animated { self.outputLabel.text = @"RPC log:"; self.outputLabel.numberOfLines = 0; self.outputLabel.font = [UIFont fontWithName:@"Helvetica Neue" size:8.0]; [self execRequest]; } @end #pragma mark Demo: List Features /** * Run the listFeatures demo. Calls listFeatures with a rectangle containing all of the features in * the pre-generated database. Prints each response as it comes in. */ @interface ListFeaturesViewController : UIViewController @property (weak, nonatomic) IBOutlet UILabel *outputLabel; @end @implementation ListFeaturesViewController { RTGRouteGuide *_service; } - (void)execRequest { RTGRectangle *rectangle = [RTGRectangle message]; rectangle.lo.latitude = 405E6; rectangle.lo.longitude = -750E6; rectangle.hi.latitude = 410E6; rectangle.hi.longitude = -745E6; NSLog(@"Looking for features between %@ and %@", rectangle.lo, rectangle.hi); [_service listFeaturesWithRequest:rectangle eventHandler:^(BOOL done, RTGFeature *response, NSError *error) { if (response) { NSString *str =[NSString stringWithFormat:@"%@\nFound feature at %@ called %@.", self.outputLabel.text, response.location, response.name]; self.outputLabel.text = str; NSLog(@"Found feature at %@ called %@.", response.location, response.name); } else if (error) { NSString *str =[NSString stringWithFormat:@"%@\nRPC error: %@", self.outputLabel.text, error]; self.outputLabel.text = str; NSLog(@"RPC error: %@", error); } }]; } - (void)viewDidLoad { [super viewDidLoad]; _service = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; } - (void)viewDidAppear:(BOOL)animated { self.outputLabel.text = @"RPC log:"; self.outputLabel.numberOfLines = 0; self.outputLabel.font = [UIFont fontWithName:@"Helvetica Neue" size:8.0]; [self execRequest]; } @end #pragma mark Demo: Record Route /** * Run the recordRoute demo. Sends several randomly chosen points from the pre-generated feature * database with a variable delay in between. Prints the statistics when they are sent from the * server. */ @interface RecordRouteViewController : UIViewController @property (weak, nonatomic) IBOutlet UILabel *outputLabel; @end @implementation RecordRouteViewController { RTGRouteGuide *_service; } - (void)execRequest { NSString *dataBasePath = [NSBundle.mainBundle pathForResource:@"route_guide_db" ofType:@"json"]; NSData *dataBaseContent = [NSData dataWithContentsOfFile:dataBasePath]; NSArray *features = [NSJSONSerialization JSONObjectWithData:dataBaseContent options:0 error:NULL]; GRXWriter *locations = [[GRXWriter writerWithContainer:features] map:^id(id feature) { RTGPoint *location = [RTGPoint message]; location.longitude = [((NSNumber *) feature[@"location"][@"longitude"]) intValue]; location.latitude = [((NSNumber *) feature[@"location"][@"latitude"]) intValue]; NSString *str =[NSString stringWithFormat:@"%@\nVisiting point %@", self.outputLabel.text, location]; self.outputLabel.text = str; NSLog(@"Visiting point %@", location); return location; }]; [_service recordRouteWithRequestsWriter:locations handler:^(RTGRouteSummary *response, NSError *error) { if (response) { NSString *str =[NSString stringWithFormat: @"%@\nFinished trip with %i points\nPassed %i features\n" "Travelled %i meters\nIt took %i seconds", self.outputLabel.text, response.pointCount, response.featureCount, response.distance, response.elapsedTime]; self.outputLabel.text = str; NSLog(@"Finished trip with %i points", response.pointCount); NSLog(@"Passed %i features", response.featureCount); NSLog(@"Travelled %i meters", response.distance); NSLog(@"It took %i seconds", response.elapsedTime); } else { NSString *str =[NSString stringWithFormat:@"%@\nRPC error: %@", self.outputLabel.text, error]; self.outputLabel.text = str; NSLog(@"RPC error: %@", error); } }]; } - (void)viewDidLoad { [super viewDidLoad]; _service = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; } - (void)viewDidAppear:(BOOL)animated { self.outputLabel.text = @"RPC log:"; self.outputLabel.numberOfLines = 0; self.outputLabel.font = [UIFont fontWithName:@"Helvetica Neue" size:8.0]; [self execRequest]; } @end #pragma mark Demo: Route Chat /** * Run the routeChat demo. Send some chat messages, and print any chat messages that are sent from * the server. */ @interface RouteChatViewController : UIViewController @property (weak, nonatomic) IBOutlet UILabel *outputLabel; @end @implementation RouteChatViewController { RTGRouteGuide *_service; } - (void)execRequest { NSArray *notes = @[[RTGRouteNote noteWithMessage:@"First message" latitude:0 longitude:0], [RTGRouteNote noteWithMessage:@"Second message" latitude:0 longitude:1], [RTGRouteNote noteWithMessage:@"Third message" latitude:1 longitude:0], [RTGRouteNote noteWithMessage:@"Fourth message" latitude:0 longitude:0]]; GRXWriter *notesWriter = [[GRXWriter writerWithContainer:notes] map:^id(RTGRouteNote *note) { NSLog(@"Sending message %@ at %@", note.message, note.location); return note; }]; [_service routeChatWithRequestsWriter:notesWriter eventHandler:^(BOOL done, RTGRouteNote *note, NSError *error) { if (note) { NSString *str =[NSString stringWithFormat:@"%@\nGot message %@ at %@", self.outputLabel.text, note.message, note.location]; self.outputLabel.text = str; NSLog(@"Got message %@ at %@", note.message, note.location); } else if (error) { NSString *str =[NSString stringWithFormat:@"%@\nRPC error: %@", self.outputLabel.text, error]; self.outputLabel.text = str; NSLog(@"RPC error: %@", error); } if (done) { NSLog(@"Chat ended."); } }]; } - (void)viewDidLoad { [super viewDidLoad]; _service = [[RTGRouteGuide alloc] initWithHost:kHostAddress]; } - (void)viewDidAppear:(BOOL)animated { // TODO(makarandd): Set these properties through UI builder self.outputLabel.text = @"RPC log:"; self.outputLabel.numberOfLines = 0; self.outputLabel.font = [UIFont fontWithName:@"Helvetica Neue" size:8.0]; [self execRequest]; } @end grpc-1.3.2/examples/objective-c/route_guide/route_guide_db.json000066400000000000000000000052451310511640000246430ustar00rootroot00000000000000[{ "location": { "latitude": 407838351, "longitude": -746143763 }, "name": "Patriots Path, Mendham, NJ 07945, USA" }, { "location": { "latitude": 408122808, "longitude": -743999179 }, "name": "101 New Jersey 10, Whippany, NJ 07981, USA" }, { "location": { "latitude": 413628156, "longitude": -749015468 }, "name": "U.S. 6, Shohola, PA 18458, USA" }, { "location": { "latitude": 419999544, "longitude": -740371136 }, "name": "5 Conners Road, Kingston, NY 12401, USA" }, { "location": { "latitude": 414008389, "longitude": -743951297 }, "name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA" }, { "location": { "latitude": 419611318, "longitude": -746524769 }, "name": "287 Flugertown Road, Livingston Manor, NY 12758, USA" }, { "location": { "latitude": 406109563, "longitude": -742186778 }, "name": "4001 Tremley Point Road, Linden, NJ 07036, USA" }, { "location": { "latitude": 416802456, "longitude": -742370183 }, "name": "352 South Mountain Road, Wallkill, NY 12589, USA" }, { "location": { "latitude": 412950425, "longitude": -741077389 }, "name": "Bailey Turn Road, Harriman, NY 10926, USA" }, { "location": { "latitude": 412144655, "longitude": -743949739 }, "name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA" }, { "location": { "latitude": 404306372, "longitude": -741079661 }, "name": "" }, { "location": { "latitude": 403966326, "longitude": -748519297 }, "name": "" }, { "location": { "latitude": 405002031, "longitude": -748407866 }, "name": "" }, { "location": { "latitude": 409532885, "longitude": -742200683 }, "name": "" }, { "location": { "latitude": 416851321, "longitude": -742674555 }, "name": "" }, { "location": { "latitude": 406411633, "longitude": -741722051 }, "name": "3387 Richmond Terrace, Staten Island, NY 10303, USA" }, { "location": { "latitude": 413069058, "longitude": -744597778 }, "name": "261 Van Sickle Road, Goshen, NY 10924, USA" }, { "location": { "latitude": 418465462, "longitude": -746859398 }, "name": "" }, { "location": { "latitude": 411733222, "longitude": -744228360 }, "name": "" }, { "location": { "latitude": 410248224, "longitude": -747127767 }, "name": "3 Hasta Way, Newton, NJ 07860, USA" }] grpc-1.3.2/examples/php/000077500000000000000000000000001310511640000150445ustar00rootroot00000000000000grpc-1.3.2/examples/php/.gitignore000066400000000000000000000000261310511640000170320ustar00rootroot00000000000000composer.lock vendor/ grpc-1.3.2/examples/php/README.md000066400000000000000000000022451310511640000163260ustar00rootroot00000000000000gRPC in 3 minutes (PHP) =========================== PREREQUISITES ------------- This requires `php` >=5.5, `phpize`, `pecl`, `phpunit` INSTALL ------- - Install the gRPC PHP extension ```sh $ [sudo] pecl install grpc ``` - Clone this repository ```sh $ git clone -b $(curl -L http://grpc.io/release) https://github.com/grpc/grpc ``` - Install composer ``` $ cd examples/php $ curl -sS https://getcomposer.org/installer | php $ php composer.phar install ``` TRY IT! ------- - Run the server Please follow the instruction in [Node][] to run the server ``` $ cd examples/node $ npm install $ cd dynamic_codegen or cd static_codegen $ node greeter_server.js ``` - Run the client ``` $ cd examples/php $ ./run_greeter_client.sh ``` NOTE ---- This directory has a copy of `helloworld.proto` because it currently depends on some Protocol Buffer 2.0 syntax. There is no proto3 support for PHP yet. TUTORIAL -------- You can find a more detailed tutorial in [gRPC Basics: PHP][] [Node]:https://github.com/grpc/grpc/tree/master/examples/node [gRPC Basics: PHP]:http://www.grpc.io/docs/tutorials/basic/php.html grpc-1.3.2/examples/php/composer.json000066400000000000000000000002721310511640000175670ustar00rootroot00000000000000{ "name": "grpc/grpc-demo", "description": "gRPC example for PHP", "require": { "grpc/grpc": "^v1.1.0" }, "autoload": { "psr-4": { "": "route_guide/" } } } grpc-1.3.2/examples/php/greeter_client.php000066400000000000000000000043731310511640000205570ustar00rootroot00000000000000 Grpc\ChannelCredentials::createInsecure(), ]); $request = new Helloworld\HelloRequest(); $request->setName($name); list($reply, $status) = $client->SayHello($request)->wait(); $message = $reply->getMessage(); return $message; } $name = !empty($argv[1]) ? $argv[1] : 'world'; echo greet($name)."\n"; grpc-1.3.2/examples/php/helloworld.pb.php000066400000000000000000000027101310511640000203300ustar00rootroot00000000000000name; } public function setName($var) { GPBUtil::checkString($var, True); $this->name = $var; } } class HelloReply extends \Google\Protobuf\Internal\Message { private $message = ''; public function getMessage() { return $this->message; } public function setMessage($var) { GPBUtil::checkString($var, True); $this->message = $var; } } $pool = DescriptorPool::getGeneratedPool(); $pool->internalAddGeneratedFile(hex2bin( "0ae6010a1068656c6c6f776f726c642e70726f746f120a68656c6c6f776f" . "726c64221c0a0c48656c6c6f52657175657374120c0a046e616d65180120" . "012809221d0a0a48656c6c6f5265706c79120f0a076d6573736167651801" . "2001280932490a0747726565746572123e0a0853617948656c6c6f12182e" . "68656c6c6f776f726c642e48656c6c6f526571756573741a162e68656c6c" . "6f776f726c642e48656c6c6f5265706c79220042360a1b696f2e67727063" . "2e6578616d706c65732e68656c6c6f776f726c64420f48656c6c6f576f72" . "6c6450726f746f5001a20203484c57620670726f746f33" )); grpc-1.3.2/examples/php/helloworld_grpc_pb.php000066400000000000000000000046761310511640000214410ustar00rootroot00000000000000_simpleRequest('/helloworld.Greeter/SayHello', $argument, ['\Helloworld\HelloReply', 'decode'], $metadata, $options); } } } grpc-1.3.2/examples/php/route_guide/000077500000000000000000000000001310511640000173575ustar00rootroot00000000000000grpc-1.3.2/examples/php/route_guide/README.md000066400000000000000000000003261310511640000206370ustar00rootroot00000000000000#gRPC Basics: PHP sample code The files in this folder are the samples used in [gRPC Basics: PHP][], a detailed tutorial for using gRPC in PHP. [gRPC Basics: PHP]:http://www.grpc.io/docs/tutorials/basic/php.html grpc-1.3.2/examples/php/route_guide/route_guide.pb.php000066400000000000000000000120171310511640000230040ustar00rootroot00000000000000latitude; } public function setLatitude($var) { GPBUtil::checkInt32($var); $this->latitude = $var; } public function getLongitude() { return $this->longitude; } public function setLongitude($var) { GPBUtil::checkInt32($var); $this->longitude = $var; } } class Rectangle extends \Google\Protobuf\Internal\Message { private $lo = null; private $hi = null; public function getLo() { return $this->lo; } public function setLo(&$var) { GPBUtil::checkMessage($var, \Routeguide\Point::class); $this->lo = $var; } public function getHi() { return $this->hi; } public function setHi(&$var) { GPBUtil::checkMessage($var, \Routeguide\Point::class); $this->hi = $var; } } class Feature extends \Google\Protobuf\Internal\Message { private $name = ''; private $location = null; public function getName() { return $this->name; } public function setName($var) { GPBUtil::checkString($var, True); $this->name = $var; } public function getLocation() { return $this->location; } public function setLocation(&$var) { GPBUtil::checkMessage($var, \Routeguide\Point::class); $this->location = $var; } } class RouteNote extends \Google\Protobuf\Internal\Message { private $location = null; private $message = ''; public function getLocation() { return $this->location; } public function setLocation(&$var) { GPBUtil::checkMessage($var, \Routeguide\Point::class); $this->location = $var; } public function getMessage() { return $this->message; } public function setMessage($var) { GPBUtil::checkString($var, True); $this->message = $var; } } class RouteSummary extends \Google\Protobuf\Internal\Message { private $point_count = 0; private $feature_count = 0; private $distance = 0; private $elapsed_time = 0; public function getPointCount() { return $this->point_count; } public function setPointCount($var) { GPBUtil::checkInt32($var); $this->point_count = $var; } public function getFeatureCount() { return $this->feature_count; } public function setFeatureCount($var) { GPBUtil::checkInt32($var); $this->feature_count = $var; } public function getDistance() { return $this->distance; } public function setDistance($var) { GPBUtil::checkInt32($var); $this->distance = $var; } public function getElapsedTime() { return $this->elapsed_time; } public function setElapsedTime($var) { GPBUtil::checkInt32($var); $this->elapsed_time = $var; } } $pool = DescriptorPool::getGeneratedPool(); $pool->internalAddGeneratedFile(hex2bin( "0ac5050a11726f7574655f67756964652e70726f746f120a726f75746567" . "75696465222c0a05506f696e7412100a086c617469747564651801200128" . "0512110a096c6f6e67697475646518022001280522490a0952656374616e" . "676c65121d0a026c6f18012001280b32112e726f75746567756964652e50" . "6f696e74121d0a02686918022001280b32112e726f75746567756964652e" . "506f696e74223c0a0746656174757265120c0a046e616d65180120012809" . "12230a086c6f636174696f6e18022001280b32112e726f75746567756964" . "652e506f696e7422410a09526f7574654e6f746512230a086c6f63617469" . "6f6e18012001280b32112e726f75746567756964652e506f696e74120f0a" . "076d65737361676518022001280922620a0c526f75746553756d6d617279" . "12130a0b706f696e745f636f756e7418012001280512150a0d6665617475" . "72655f636f756e7418022001280512100a0864697374616e636518032001" . "280512140a0c656c61707365645f74696d651804200128053285020a0a52" . "6f757465477569646512360a0a4765744665617475726512112e726f7574" . "6567756964652e506f696e741a132e726f75746567756964652e46656174" . "7572652200123e0a0c4c697374466561747572657312152e726f75746567" . "756964652e52656374616e676c651a132e726f75746567756964652e4665" . "617475726522003001123e0a0b5265636f7264526f75746512112e726f75" . "746567756964652e506f696e741a182e726f75746567756964652e526f75" . "746553756d6d61727922002801123f0a09526f7574654368617412152e72" . "6f75746567756964652e526f7574654e6f74651a152e726f757465677569" . "64652e526f7574654e6f746522002801300142360a1b696f2e677270632e" . "6578616d706c65732e726f7574656775696465420f526f75746547756964" . "6550726f746f5001a20203525447620670726f746f33" )); grpc-1.3.2/examples/php/route_guide/route_guide_client.php000066400000000000000000000157061310511640000237520ustar00rootroot00000000000000 Grpc\ChannelCredentials::createInsecure(), ]); function printFeature($feature) { $name = $feature->getName(); if (!$name) { $name_str = 'no feature'; } else { $name_str = "feature called $name"; } echo sprintf("Found %s \n at %f, %f\n", $name_str, $feature->getLocation()->getLatitude() / COORD_FACTOR, $feature->getLocation()->getLongitude() / COORD_FACTOR); } /** * Run the getFeature demo. Calls getFeature with a point known to have a * feature and a point known not to have a feature. */ function runGetFeature() { echo "Running GetFeature...\n"; global $client; $point = new Routeguide\Point(); $points = array( array(409146138, -746188906), array(0, 0), ); foreach ($points as $p) { $point->setLatitude($p[0]); $point->setLongitude($p[1]); // make a unary grpc call list($feature, $status) = $client->GetFeature($point)->wait(); printFeature($feature); } } /** * Run the listFeatures demo. Calls listFeatures with a rectangle * containing all of the features in the pre-generated * database. Prints each response as it comes in. */ function runListFeatures() { echo "Running ListFeatures...\n"; global $client; $lo_point = new Routeguide\Point(); $hi_point = new Routeguide\Point(); $lo_point->setLatitude(400000000); $lo_point->setLongitude(-750000000); $hi_point->setLatitude(420000000); $hi_point->setLongitude(-730000000); $rectangle = new Routeguide\Rectangle(); $rectangle->setLo($lo_point); $rectangle->setHi($hi_point); // start the server streaming call $call = $client->ListFeatures($rectangle); // an iterator over the server streaming responses $features = $call->responses(); foreach ($features as $feature) { printFeature($feature); } } /** * Run the recordRoute demo. Sends several randomly chosen points from the * pre-generated feature database with a variable delay in between. Prints * the statistics when they are sent from the server. */ function runRecordRoute() { echo "Running RecordRoute...\n"; global $client, $argv; // start the client streaming call $call = $client->RecordRoute(); $db = json_decode(file_get_contents($argv[1]), true); $num_points_in_db = count($db); $num_points = 10; for ($i = 0; $i < $num_points; ++$i) { $point = new Routeguide\Point(); $index = rand(0, $num_points_in_db - 1); $lat = $db[$index]['location']['latitude']; $long = $db[$index]['location']['longitude']; $feature_name = $db[$index]['name']; $point->setLatitude($lat); $point->setLongitude($long); echo sprintf("Visiting point %f, %f,\n with feature name: %s\n", $lat / COORD_FACTOR, $long / COORD_FACTOR, $feature_name ? $feature_name : ''); usleep(rand(300000, 800000)); $call->write($point); } list($route_summary, $status) = $call->wait(); echo sprintf("Finished trip with %d points\nPassed %d features\n". "Travelled %d meters\nIt took %d seconds\n", $route_summary->getPointCount(), $route_summary->getFeatureCount(), $route_summary->getDistance(), $route_summary->getElapsedTime()); } /** * Run the routeChat demo. Send some chat messages, and print any chat * messages that are sent from the server. */ function runRouteChat() { echo "Running RouteChat...\n"; global $client; // start the bidirectional streaming call $call = $client->RouteChat(); $notes = array( array(1, 1, 'first message'), array(1, 2, 'second message'), array(2, 1, 'third message'), array(1, 1, 'fourth message'), array(1, 1, 'fifth message'), ); foreach ($notes as $n) { $point = new Routeguide\Point(); $point->setLatitude($lat = $n[0]); $point->setLongitude($long = $n[1]); $route_note = new Routeguide\RouteNote(); $route_note->setLocation($point); $route_note->setMessage($message = $n[2]); echo sprintf("Sending message: '%s' at (%d, %d)\n", $message, $lat, $long); // send a bunch of messages to the server $call->write($route_note); } $call->writesDone(); // read from the server until there's no more while ($route_note_reply = $call->read()) { echo sprintf("Previous left message at (%d, %d): '%s'\n", $route_note_reply->getLocation()->getLatitude(), $route_note_reply->getLocation()->getLongitude(), $route_note_reply->getMessage()); } } /** * Run all of the demos in order. */ function main() { runGetFeature(); runListFeatures(); runRecordRoute(); runRouteChat(); } if (empty($argv[1])) { echo 'Usage: php -d extension=grpc.so route_guide_client.php '. "\n"; exit(1); } main(); grpc-1.3.2/examples/php/route_guide/route_guide_grpc_pb.php000066400000000000000000000104411310511640000240770ustar00rootroot00000000000000_simpleRequest('/routeguide.RouteGuide/GetFeature', $argument, ['\Routeguide\Feature', 'decode'], $metadata, $options); } /** * A server-to-client streaming RPC. * * Obtains the Features available within the given Rectangle. Results are * streamed rather than returned at once (e.g. in a response message with a * repeated field), as the rectangle may cover a large area and contain a * huge number of features. * @param \Routeguide\Rectangle $argument input argument * @param array $metadata metadata * @param array $options call options */ public function ListFeatures(\Routeguide\Rectangle $argument, $metadata = [], $options = []) { return $this->_serverStreamRequest('/routeguide.RouteGuide/ListFeatures', $argument, ['\Routeguide\Feature', 'decode'], $metadata, $options); } /** * A client-to-server streaming RPC. * * Accepts a stream of Points on a route being traversed, returning a * RouteSummary when traversal is completed. * @param array $metadata metadata * @param array $options call options */ public function RecordRoute($metadata = [], $options = []) { return $this->_clientStreamRequest('/routeguide.RouteGuide/RecordRoute', ['\Routeguide\RouteSummary','decode'], $metadata, $options); } /** * A Bidirectional streaming RPC. * * Accepts a stream of RouteNotes sent while a route is being traversed, * while receiving other RouteNotes (e.g. from other users). * @param array $metadata metadata * @param array $options call options */ public function RouteChat($metadata = [], $options = []) { return $this->_bidiRequest('/routeguide.RouteGuide/RouteChat', ['\Routeguide\RouteNote','decode'], $metadata, $options); } } } grpc-1.3.2/examples/php/route_guide/run_route_guide_client.sh000077500000000000000000000032511310511640000244540ustar00rootroot00000000000000#!/bin/bash # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. set -e cd $(dirname $0) php -d extension=grpc.so -d max_execution_time=300 \ route_guide_client.php \ ../../node/static_codegen/route_guide/route_guide_db.json grpc-1.3.2/examples/php/run_greeter_client.sh000077500000000000000000000031521310511640000212630ustar00rootroot00000000000000#!/bin/bash # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. set -e cd $(dirname $0) php -d extension=grpc.so -d max_execution_time=300 \ greeter_client.php $1 grpc-1.3.2/examples/protos/000077500000000000000000000000001310511640000156035ustar00rootroot00000000000000grpc-1.3.2/examples/protos/BUILD000066400000000000000000000037061310511640000163730ustar00rootroot00000000000000# Copyright 2017, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package(default_visibility = ["//visibility:public"]) load("//bazel:grpc_build_system.bzl", "grpc_proto_library") grpc_proto_library( name = "auth_sample", srcs = ["auth_sample.proto"], ) grpc_proto_library( name = "hellostreamingworld", srcs = ["hellostreamingworld.proto"], ) grpc_proto_library( name = "helloworld", srcs = ["helloworld.proto"], ) grpc_proto_library( name = "route_guide", srcs = ["route_guide.proto"], ) grpc-1.3.2/examples/protos/README.md000066400000000000000000000002631310511640000170630ustar00rootroot00000000000000# Example protos ## Contents - [helloworld.proto] - The simple example used in the overview. - [route_guide.proto] - An example service described in detail in the tutorial. grpc-1.3.2/examples/protos/auth_sample.proto000066400000000000000000000041651310511640000212000ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package grpc.testing; option objc_class_prefix = "AUTH"; // Unary request. message Request { // Whether Response should include username. bool fill_username = 4; // Whether Response should include OAuth scope. bool fill_oauth_scope = 5; } // Unary response, as configured by the request. message Response { // The user the request came from, for verifying authentication was // successful. string username = 2; // OAuth scope. string oauth_scope = 3; } service TestService { // One request followed by one response. rpc UnaryCall(Request) returns (Response); } grpc-1.3.2/examples/protos/hellostreamingworld.proto000066400000000000000000000040361310511640000227600ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; option java_package = "ex.grpc"; option objc_class_prefix = "HSW"; package hellostreamingworld; // The greeting service definition. service MultiGreeter { // Sends multiple greetings rpc sayHello (HelloRequest) returns (stream HelloReply) {} } // The request message containing the user's name and how many greetings // they want. message HelloRequest { string name = 1; string num_greetings = 2; } // A response message containing a greeting message HelloReply { string message = 1; } grpc-1.3.2/examples/protos/helloworld.proto000066400000000000000000000040551310511640000210470ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; option java_multiple_files = true; option java_package = "io.grpc.examples.helloworld"; option java_outer_classname = "HelloWorldProto"; option objc_class_prefix = "HLW"; package helloworld; // The greeting service definition. service Greeter { // Sends a greeting rpc SayHello (HelloRequest) returns (HelloReply) {} } // The request message containing the user's name. message HelloRequest { string name = 1; } // The response message containing the greetings message HelloReply { string message = 1; } grpc-1.3.2/examples/protos/route_guide.proto000066400000000000000000000105471310511640000212120ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; option java_multiple_files = true; option java_package = "io.grpc.examples.routeguide"; option java_outer_classname = "RouteGuideProto"; option objc_class_prefix = "RTG"; package routeguide; // Interface exported by the server. service RouteGuide { // A simple RPC. // // Obtains the feature at a given position. // // A feature with an empty name is returned if there's no feature at the given // position. rpc GetFeature(Point) returns (Feature) {} // A server-to-client streaming RPC. // // Obtains the Features available within the given Rectangle. Results are // streamed rather than returned at once (e.g. in a response message with a // repeated field), as the rectangle may cover a large area and contain a // huge number of features. rpc ListFeatures(Rectangle) returns (stream Feature) {} // A client-to-server streaming RPC. // // Accepts a stream of Points on a route being traversed, returning a // RouteSummary when traversal is completed. rpc RecordRoute(stream Point) returns (RouteSummary) {} // A Bidirectional streaming RPC. // // Accepts a stream of RouteNotes sent while a route is being traversed, // while receiving other RouteNotes (e.g. from other users). rpc RouteChat(stream RouteNote) returns (stream RouteNote) {} } // Points are represented as latitude-longitude pairs in the E7 representation // (degrees multiplied by 10**7 and rounded to the nearest integer). // Latitudes should be in the range +/- 90 degrees and longitude should be in // the range +/- 180 degrees (inclusive). message Point { int32 latitude = 1; int32 longitude = 2; } // A latitude-longitude rectangle, represented as two diagonally opposite // points "lo" and "hi". message Rectangle { // One corner of the rectangle. Point lo = 1; // The other corner of the rectangle. Point hi = 2; } // A feature names something at a given point. // // If a feature could not be named, the name is empty. message Feature { // The name of the feature. string name = 1; // The point where the feature is detected. Point location = 2; } // A RouteNote is a message sent while at a given point. message RouteNote { // The location from which the message is sent. Point location = 1; // The message to be sent. string message = 2; } // A RouteSummary is received in response to a RecordRoute rpc. // // It contains the number of individual points received, the number of // detected features, and the total distance covered as the cumulative sum of // the distance between each point. message RouteSummary { // The number of points received. int32 point_count = 1; // The number of known features passed while traversing the route. int32 feature_count = 2; // The distance covered in metres. int32 distance = 3; // The duration of the traversal in seconds. int32 elapsed_time = 4; } grpc-1.3.2/examples/python/000077500000000000000000000000001310511640000155765ustar00rootroot00000000000000grpc-1.3.2/examples/python/README.md000066400000000000000000000001471310511640000170570ustar00rootroot00000000000000[This code's documentation lives on the grpc.io site.](http://www.grpc.io/docs/quickstart/python.html) grpc-1.3.2/examples/python/helloworld/000077500000000000000000000000001310511640000177515ustar00rootroot00000000000000grpc-1.3.2/examples/python/helloworld/.gitignore000066400000000000000000000000061310511640000217350ustar00rootroot00000000000000*.pyc grpc-1.3.2/examples/python/helloworld/README.md000066400000000000000000000001471310511640000212320ustar00rootroot00000000000000[This code's documentation lives on the grpc.io site.](http://www.grpc.io/docs/quickstart/python.html) grpc-1.3.2/examples/python/helloworld/greeter_client.py000066400000000000000000000036731310511640000233270ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """The Python implementation of the GRPC helloworld.Greeter client.""" from __future__ import print_function import grpc import helloworld_pb2 import helloworld_pb2_grpc def run(): channel = grpc.insecure_channel('localhost:50051') stub = helloworld_pb2_grpc.GreeterStub(channel) response = stub.SayHello(helloworld_pb2.HelloRequest(name='you')) print("Greeter client received: " + response.message) if __name__ == '__main__': run() grpc-1.3.2/examples/python/helloworld/greeter_server.py000066400000000000000000000043351310511640000233530ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """The Python implementation of the GRPC helloworld.Greeter server.""" from concurrent import futures import time import grpc import helloworld_pb2 import helloworld_pb2_grpc _ONE_DAY_IN_SECONDS = 60 * 60 * 24 class Greeter(helloworld_pb2_grpc.GreeterServicer): def SayHello(self, request, context): return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name) def serve(): server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) server.add_insecure_port('[::]:50051') server.start() try: while True: time.sleep(_ONE_DAY_IN_SECONDS) except KeyboardInterrupt: server.stop(0) if __name__ == '__main__': serve() grpc-1.3.2/examples/python/helloworld/helloworld_pb2.py000066400000000000000000000177221310511640000232520ustar00rootroot00000000000000# Generated by the protocol buffer compiler. DO NOT EDIT! # source: helloworld.proto import sys _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database from google.protobuf import descriptor_pb2 # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() DESCRIPTOR = _descriptor.FileDescriptor( name='helloworld.proto', package='helloworld', syntax='proto3', serialized_pb=_b('\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x36\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\xa2\x02\x03HLWb\x06proto3') ) _sym_db.RegisterFileDescriptor(DESCRIPTOR) _HELLOREQUEST = _descriptor.Descriptor( name='HelloRequest', full_name='helloworld.HelloRequest', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='name', full_name='helloworld.HelloRequest.name', index=0, number=1, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=32, serialized_end=60, ) _HELLOREPLY = _descriptor.Descriptor( name='HelloReply', full_name='helloworld.HelloReply', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='message', full_name='helloworld.HelloReply.message', index=0, number=1, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=62, serialized_end=91, ) DESCRIPTOR.message_types_by_name['HelloRequest'] = _HELLOREQUEST DESCRIPTOR.message_types_by_name['HelloReply'] = _HELLOREPLY HelloRequest = _reflection.GeneratedProtocolMessageType('HelloRequest', (_message.Message,), dict( DESCRIPTOR = _HELLOREQUEST, __module__ = 'helloworld_pb2' # @@protoc_insertion_point(class_scope:helloworld.HelloRequest) )) _sym_db.RegisterMessage(HelloRequest) HelloReply = _reflection.GeneratedProtocolMessageType('HelloReply', (_message.Message,), dict( DESCRIPTOR = _HELLOREPLY, __module__ = 'helloworld_pb2' # @@protoc_insertion_point(class_scope:helloworld.HelloReply) )) _sym_db.RegisterMessage(HelloReply) DESCRIPTOR.has_options = True DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW')) try: # THESE ELEMENTS WILL BE DEPRECATED. # Please use the generated *_pb2_grpc.py files instead. import grpc from grpc.framework.common import cardinality from grpc.framework.interfaces.face import utilities as face_utilities from grpc.beta import implementations as beta_implementations from grpc.beta import interfaces as beta_interfaces class GreeterStub(object): """The greeting service definition. """ def __init__(self, channel): """Constructor. Args: channel: A grpc.Channel. """ self.SayHello = channel.unary_unary( '/helloworld.Greeter/SayHello', request_serializer=HelloRequest.SerializeToString, response_deserializer=HelloReply.FromString, ) class GreeterServicer(object): """The greeting service definition. """ def SayHello(self, request, context): """Sends a greeting """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def add_GreeterServicer_to_server(servicer, server): rpc_method_handlers = { 'SayHello': grpc.unary_unary_rpc_method_handler( servicer.SayHello, request_deserializer=HelloRequest.FromString, response_serializer=HelloReply.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler( 'helloworld.Greeter', rpc_method_handlers) server.add_generic_rpc_handlers((generic_handler,)) class BetaGreeterServicer(object): """The Beta API is deprecated for 0.15.0 and later. It is recommended to use the GA API (classes and functions in this file not marked beta) for all further purposes. This class was generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0.""" """The greeting service definition. """ def SayHello(self, request, context): """Sends a greeting """ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED) class BetaGreeterStub(object): """The Beta API is deprecated for 0.15.0 and later. It is recommended to use the GA API (classes and functions in this file not marked beta) for all further purposes. This class was generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0.""" """The greeting service definition. """ def SayHello(self, request, timeout, metadata=None, with_call=False, protocol_options=None): """Sends a greeting """ raise NotImplementedError() SayHello.future = None def beta_create_Greeter_server(servicer, pool=None, pool_size=None, default_timeout=None, maximum_timeout=None): """The Beta API is deprecated for 0.15.0 and later. It is recommended to use the GA API (classes and functions in this file not marked beta) for all further purposes. This function was generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0""" request_deserializers = { ('helloworld.Greeter', 'SayHello'): HelloRequest.FromString, } response_serializers = { ('helloworld.Greeter', 'SayHello'): HelloReply.SerializeToString, } method_implementations = { ('helloworld.Greeter', 'SayHello'): face_utilities.unary_unary_inline(servicer.SayHello), } server_options = beta_implementations.server_options(request_deserializers=request_deserializers, response_serializers=response_serializers, thread_pool=pool, thread_pool_size=pool_size, default_timeout=default_timeout, maximum_timeout=maximum_timeout) return beta_implementations.server(method_implementations, options=server_options) def beta_create_Greeter_stub(channel, host=None, metadata_transformer=None, pool=None, pool_size=None): """The Beta API is deprecated for 0.15.0 and later. It is recommended to use the GA API (classes and functions in this file not marked beta) for all further purposes. This function was generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0""" request_serializers = { ('helloworld.Greeter', 'SayHello'): HelloRequest.SerializeToString, } response_deserializers = { ('helloworld.Greeter', 'SayHello'): HelloReply.FromString, } cardinalities = { 'SayHello': cardinality.Cardinality.UNARY_UNARY, } stub_options = beta_implementations.stub_options(host=host, metadata_transformer=metadata_transformer, request_serializers=request_serializers, response_deserializers=response_deserializers, thread_pool=pool, thread_pool_size=pool_size) return beta_implementations.dynamic_stub(channel, 'helloworld.Greeter', cardinalities, options=stub_options) except ImportError: pass # @@protoc_insertion_point(module_scope) grpc-1.3.2/examples/python/helloworld/helloworld_pb2_grpc.py000066400000000000000000000025421310511640000242570ustar00rootroot00000000000000import grpc from grpc.framework.common import cardinality from grpc.framework.interfaces.face import utilities as face_utilities import helloworld_pb2 as helloworld__pb2 class GreeterStub(object): """The greeting service definition. """ def __init__(self, channel): """Constructor. Args: channel: A grpc.Channel. """ self.SayHello = channel.unary_unary( '/helloworld.Greeter/SayHello', request_serializer=helloworld__pb2.HelloRequest.SerializeToString, response_deserializer=helloworld__pb2.HelloReply.FromString, ) class GreeterServicer(object): """The greeting service definition. """ def SayHello(self, request, context): """Sends a greeting """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def add_GreeterServicer_to_server(servicer, server): rpc_method_handlers = { 'SayHello': grpc.unary_unary_rpc_method_handler( servicer.SayHello, request_deserializer=helloworld__pb2.HelloRequest.FromString, response_serializer=helloworld__pb2.HelloReply.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler( 'helloworld.Greeter', rpc_method_handlers) server.add_generic_rpc_handlers((generic_handler,)) grpc-1.3.2/examples/python/multiplex/000077500000000000000000000000001310511640000176215ustar00rootroot00000000000000grpc-1.3.2/examples/python/multiplex/.gitignore000066400000000000000000000000061310511640000216050ustar00rootroot00000000000000*.pyc grpc-1.3.2/examples/python/multiplex/README.md000066400000000000000000000002711310511640000211000ustar00rootroot00000000000000An example showing two stubs sharing a channel and two servicers sharing a server. More complete documentation lives at [grpc.io](http://www.grpc.io/docs/tutorials/basic/python.html). grpc-1.3.2/examples/python/multiplex/helloworld_pb2.py000066400000000000000000000177221310511640000231220ustar00rootroot00000000000000# Generated by the protocol buffer compiler. DO NOT EDIT! # source: helloworld.proto import sys _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database from google.protobuf import descriptor_pb2 # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() DESCRIPTOR = _descriptor.FileDescriptor( name='helloworld.proto', package='helloworld', syntax='proto3', serialized_pb=_b('\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x36\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\xa2\x02\x03HLWb\x06proto3') ) _sym_db.RegisterFileDescriptor(DESCRIPTOR) _HELLOREQUEST = _descriptor.Descriptor( name='HelloRequest', full_name='helloworld.HelloRequest', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='name', full_name='helloworld.HelloRequest.name', index=0, number=1, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=32, serialized_end=60, ) _HELLOREPLY = _descriptor.Descriptor( name='HelloReply', full_name='helloworld.HelloReply', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='message', full_name='helloworld.HelloReply.message', index=0, number=1, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=62, serialized_end=91, ) DESCRIPTOR.message_types_by_name['HelloRequest'] = _HELLOREQUEST DESCRIPTOR.message_types_by_name['HelloReply'] = _HELLOREPLY HelloRequest = _reflection.GeneratedProtocolMessageType('HelloRequest', (_message.Message,), dict( DESCRIPTOR = _HELLOREQUEST, __module__ = 'helloworld_pb2' # @@protoc_insertion_point(class_scope:helloworld.HelloRequest) )) _sym_db.RegisterMessage(HelloRequest) HelloReply = _reflection.GeneratedProtocolMessageType('HelloReply', (_message.Message,), dict( DESCRIPTOR = _HELLOREPLY, __module__ = 'helloworld_pb2' # @@protoc_insertion_point(class_scope:helloworld.HelloReply) )) _sym_db.RegisterMessage(HelloReply) DESCRIPTOR.has_options = True DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW')) try: # THESE ELEMENTS WILL BE DEPRECATED. # Please use the generated *_pb2_grpc.py files instead. import grpc from grpc.framework.common import cardinality from grpc.framework.interfaces.face import utilities as face_utilities from grpc.beta import implementations as beta_implementations from grpc.beta import interfaces as beta_interfaces class GreeterStub(object): """The greeting service definition. """ def __init__(self, channel): """Constructor. Args: channel: A grpc.Channel. """ self.SayHello = channel.unary_unary( '/helloworld.Greeter/SayHello', request_serializer=HelloRequest.SerializeToString, response_deserializer=HelloReply.FromString, ) class GreeterServicer(object): """The greeting service definition. """ def SayHello(self, request, context): """Sends a greeting """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def add_GreeterServicer_to_server(servicer, server): rpc_method_handlers = { 'SayHello': grpc.unary_unary_rpc_method_handler( servicer.SayHello, request_deserializer=HelloRequest.FromString, response_serializer=HelloReply.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler( 'helloworld.Greeter', rpc_method_handlers) server.add_generic_rpc_handlers((generic_handler,)) class BetaGreeterServicer(object): """The Beta API is deprecated for 0.15.0 and later. It is recommended to use the GA API (classes and functions in this file not marked beta) for all further purposes. This class was generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0.""" """The greeting service definition. """ def SayHello(self, request, context): """Sends a greeting """ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED) class BetaGreeterStub(object): """The Beta API is deprecated for 0.15.0 and later. It is recommended to use the GA API (classes and functions in this file not marked beta) for all further purposes. This class was generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0.""" """The greeting service definition. """ def SayHello(self, request, timeout, metadata=None, with_call=False, protocol_options=None): """Sends a greeting """ raise NotImplementedError() SayHello.future = None def beta_create_Greeter_server(servicer, pool=None, pool_size=None, default_timeout=None, maximum_timeout=None): """The Beta API is deprecated for 0.15.0 and later. It is recommended to use the GA API (classes and functions in this file not marked beta) for all further purposes. This function was generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0""" request_deserializers = { ('helloworld.Greeter', 'SayHello'): HelloRequest.FromString, } response_serializers = { ('helloworld.Greeter', 'SayHello'): HelloReply.SerializeToString, } method_implementations = { ('helloworld.Greeter', 'SayHello'): face_utilities.unary_unary_inline(servicer.SayHello), } server_options = beta_implementations.server_options(request_deserializers=request_deserializers, response_serializers=response_serializers, thread_pool=pool, thread_pool_size=pool_size, default_timeout=default_timeout, maximum_timeout=maximum_timeout) return beta_implementations.server(method_implementations, options=server_options) def beta_create_Greeter_stub(channel, host=None, metadata_transformer=None, pool=None, pool_size=None): """The Beta API is deprecated for 0.15.0 and later. It is recommended to use the GA API (classes and functions in this file not marked beta) for all further purposes. This function was generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0""" request_serializers = { ('helloworld.Greeter', 'SayHello'): HelloRequest.SerializeToString, } response_deserializers = { ('helloworld.Greeter', 'SayHello'): HelloReply.FromString, } cardinalities = { 'SayHello': cardinality.Cardinality.UNARY_UNARY, } stub_options = beta_implementations.stub_options(host=host, metadata_transformer=metadata_transformer, request_serializers=request_serializers, response_deserializers=response_deserializers, thread_pool=pool, thread_pool_size=pool_size) return beta_implementations.dynamic_stub(channel, 'helloworld.Greeter', cardinalities, options=stub_options) except ImportError: pass # @@protoc_insertion_point(module_scope) grpc-1.3.2/examples/python/multiplex/helloworld_pb2_grpc.py000066400000000000000000000025421310511640000241270ustar00rootroot00000000000000import grpc from grpc.framework.common import cardinality from grpc.framework.interfaces.face import utilities as face_utilities import helloworld_pb2 as helloworld__pb2 class GreeterStub(object): """The greeting service definition. """ def __init__(self, channel): """Constructor. Args: channel: A grpc.Channel. """ self.SayHello = channel.unary_unary( '/helloworld.Greeter/SayHello', request_serializer=helloworld__pb2.HelloRequest.SerializeToString, response_deserializer=helloworld__pb2.HelloReply.FromString, ) class GreeterServicer(object): """The greeting service definition. """ def SayHello(self, request, context): """Sends a greeting """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def add_GreeterServicer_to_server(servicer, server): rpc_method_handlers = { 'SayHello': grpc.unary_unary_rpc_method_handler( servicer.SayHello, request_deserializer=helloworld__pb2.HelloRequest.FromString, response_serializer=helloworld__pb2.HelloReply.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler( 'helloworld.Greeter', rpc_method_handlers) server.add_generic_rpc_handlers((generic_handler,)) grpc-1.3.2/examples/python/multiplex/multiplex_client.py000066400000000000000000000120401310511640000235510ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """A client that makes both Greeter and RouteGuide RPCs.""" from __future__ import print_function import random import time import grpc import helloworld_pb2 import helloworld_pb2_grpc import route_guide_pb2 import route_guide_pb2_grpc import route_guide_resources def make_route_note(message, latitude, longitude): return route_guide_pb2.RouteNote( message=message, location=route_guide_pb2.Point(latitude=latitude, longitude=longitude)) def guide_get_one_feature(route_guide_stub, point): feature = route_guide_stub.GetFeature(point) if not feature.location: print("Server returned incomplete feature") return if feature.name: print("Feature called %s at %s" % (feature.name, feature.location)) else: print("Found no feature at %s" % feature.location) def guide_get_feature(route_guide_stub): guide_get_one_feature( route_guide_stub, route_guide_pb2.Point(latitude=409146138, longitude=-746188906)) guide_get_one_feature( route_guide_stub, route_guide_pb2.Point(latitude=0, longitude=0)) def guide_list_features(route_guide_stub): rectangle = route_guide_pb2.Rectangle( lo=route_guide_pb2.Point(latitude=400000000, longitude=-750000000), hi=route_guide_pb2.Point(latitude=420000000, longitude=-730000000)) print("Looking for features between 40, -75 and 42, -73") features = route_guide_stub.ListFeatures(rectangle) for feature in features: print("Feature called %s at %s" % (feature.name, feature.location)) def generate_route(feature_list): for _ in range(0, 10): random_feature = feature_list[random.randint(0, len(feature_list) - 1)] print("Visiting point %s" % random_feature.location) yield random_feature.location time.sleep(random.uniform(0.5, 1.5)) def guide_record_route(route_guide_stub): feature_list = route_guide_resources.read_route_guide_database() route_iterator = generate_route(feature_list) route_summary = route_guide_stub.RecordRoute(route_iterator) print("Finished trip with %s points " % route_summary.point_count) print("Passed %s features " % route_summary.feature_count) print("Travelled %s meters " % route_summary.distance) print("It took %s seconds " % route_summary.elapsed_time) def generate_messages(): messages = [ make_route_note("First message", 0, 0), make_route_note("Second message", 0, 1), make_route_note("Third message", 1, 0), make_route_note("Fourth message", 0, 0), make_route_note("Fifth message", 1, 0), ] for msg in messages: print("Sending %s at %s" % (msg.message, msg.location)) yield msg time.sleep(random.uniform(0.5, 1.0)) def guide_route_chat(route_guide_stub): responses = route_guide_stub.RouteChat(generate_messages()) for response in responses: print("Received message %s at %s" % (response.message, response.location)) def run(): channel = grpc.insecure_channel('localhost:50051') greeter_stub = helloworld_pb2_grpc.GreeterStub(channel) route_guide_stub = route_guide_pb2_grpc.RouteGuideStub(channel) greeter_response = greeter_stub.SayHello( helloworld_pb2.HelloRequest(name='you')) print("Greeter client received: " + greeter_response.message) print("-------------- GetFeature --------------") guide_get_feature(route_guide_stub) print("-------------- ListFeatures --------------") guide_list_features(route_guide_stub) print("-------------- RecordRoute --------------") guide_record_route(route_guide_stub) print("-------------- RouteChat --------------") guide_route_chat(route_guide_stub) if __name__ == '__main__': run() grpc-1.3.2/examples/python/multiplex/multiplex_server.py000066400000000000000000000121661310511640000236120ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """A gRPC server servicing both Greeter and RouteGuide RPCs.""" from concurrent import futures import time import math import grpc import helloworld_pb2 import helloworld_pb2_grpc import route_guide_pb2 import route_guide_pb2_grpc import route_guide_resources _ONE_DAY_IN_SECONDS = 60 * 60 * 24 def _get_feature(feature_db, point): """Returns Feature at given location or None.""" for feature in feature_db: if feature.location == point: return feature return None def _get_distance(start, end): """Distance between two points.""" coord_factor = 10000000.0 lat_1 = start.latitude / coord_factor lat_2 = end.latitude / coord_factor lon_1 = start.longitude / coord_factor lon_2 = end.longitude / coord_factor lat_rad_1 = math.radians(lat_1) lat_rad_2 = math.radians(lat_2) delta_lat_rad = math.radians(lat_2 - lat_1) delta_lon_rad = math.radians(lon_2 - lon_1) a = (pow(math.sin(delta_lat_rad / 2), 2) + (math.cos(lat_rad_1) * math.cos(lat_rad_2) * pow(math.sin(delta_lon_rad / 2), 2))) c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) R = 6371000; # metres return R * c; class _GreeterServicer(helloworld_pb2_grpc.GreeterServicer): def SayHello(self, request, context): return helloworld_pb2.HelloReply(message='Hello, {}!'.format(request.name)) class _RouteGuideServicer(route_guide_pb2_grpc.RouteGuideServicer): """Provides methods that implement functionality of route guide server.""" def __init__(self): self.db = route_guide_resources.read_route_guide_database() def GetFeature(self, request, context): feature = _get_feature(self.db, request) if feature is None: return route_guide_pb2.Feature(name="", location=request) else: return feature def ListFeatures(self, request, context): left = min(request.lo.longitude, request.hi.longitude) right = max(request.lo.longitude, request.hi.longitude) top = max(request.lo.latitude, request.hi.latitude) bottom = min(request.lo.latitude, request.hi.latitude) for feature in self.db: if (feature.location.longitude >= left and feature.location.longitude <= right and feature.location.latitude >= bottom and feature.location.latitude <= top): yield feature def RecordRoute(self, request_iterator, context): point_count = 0 feature_count = 0 distance = 0.0 prev_point = None start_time = time.time() for point in request_iterator: point_count += 1 if _get_feature(self.db, point): feature_count += 1 if prev_point: distance += _get_distance(prev_point, point) prev_point = point elapsed_time = time.time() - start_time return route_guide_pb2.RouteSummary(point_count=point_count, feature_count=feature_count, distance=int(distance), elapsed_time=int(elapsed_time)) def RouteChat(self, request_iterator, context): prev_notes = [] for new_note in request_iterator: for prev_note in prev_notes: if prev_note.location == new_note.location: yield prev_note prev_notes.append(new_note) def serve(): server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) helloworld_pb2_grpc.add_GreeterServicer_to_server(_GreeterServicer(), server) route_guide_pb2_grpc.add_RouteGuideServicer_to_server( _RouteGuideServicer(), server) server.add_insecure_port('[::]:50051') server.start() try: while True: time.sleep(_ONE_DAY_IN_SECONDS) except KeyboardInterrupt: server.stop(0) if __name__ == '__main__': serve() grpc-1.3.2/examples/python/multiplex/route_guide_db.json000066400000000000000000000327101310511640000234770ustar00rootroot00000000000000[{ "location": { "latitude": 407838351, "longitude": -746143763 }, "name": "Patriots Path, Mendham, NJ 07945, USA" }, { "location": { "latitude": 408122808, "longitude": -743999179 }, "name": "101 New Jersey 10, Whippany, NJ 07981, USA" }, { "location": { "latitude": 413628156, "longitude": -749015468 }, "name": "U.S. 6, Shohola, PA 18458, USA" }, { "location": { "latitude": 419999544, "longitude": -740371136 }, "name": "5 Conners Road, Kingston, NY 12401, USA" }, { "location": { "latitude": 414008389, "longitude": -743951297 }, "name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA" }, { "location": { "latitude": 419611318, "longitude": -746524769 }, "name": "287 Flugertown Road, Livingston Manor, NY 12758, USA" }, { "location": { "latitude": 406109563, "longitude": -742186778 }, "name": "4001 Tremley Point Road, Linden, NJ 07036, USA" }, { "location": { "latitude": 416802456, "longitude": -742370183 }, "name": "352 South Mountain Road, Wallkill, NY 12589, USA" }, { "location": { "latitude": 412950425, "longitude": -741077389 }, "name": "Bailey Turn Road, Harriman, NY 10926, USA" }, { "location": { "latitude": 412144655, "longitude": -743949739 }, "name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA" }, { "location": { "latitude": 415736605, "longitude": -742847522 }, "name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA" }, { "location": { "latitude": 413843930, "longitude": -740501726 }, "name": "162 Merrill Road, Highland Mills, NY 10930, USA" }, { "location": { "latitude": 410873075, "longitude": -744459023 }, "name": "Clinton Road, West Milford, NJ 07480, USA" }, { "location": { "latitude": 412346009, "longitude": -744026814 }, "name": "16 Old Brook Lane, Warwick, NY 10990, USA" }, { "location": { "latitude": 402948455, "longitude": -747903913 }, "name": "3 Drake Lane, Pennington, NJ 08534, USA" }, { "location": { "latitude": 406337092, "longitude": -740122226 }, "name": "6324 8th Avenue, Brooklyn, NY 11220, USA" }, { "location": { "latitude": 406421967, "longitude": -747727624 }, "name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA" }, { "location": { "latitude": 416318082, "longitude": -749677716 }, "name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA" }, { "location": { "latitude": 415301720, "longitude": -748416257 }, "name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA" }, { "location": { "latitude": 402647019, "longitude": -747071791 }, "name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA" }, { "location": { "latitude": 412567807, "longitude": -741058078 }, "name": "New York State Reference Route 987E, Southfields, NY 10975, USA" }, { "location": { "latitude": 416855156, "longitude": -744420597 }, "name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA" }, { "location": { "latitude": 404663628, "longitude": -744820157 }, "name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA" }, { "location": { "latitude": 407113723, "longitude": -749746483 }, "name": "" }, { "location": { "latitude": 402133926, "longitude": -743613249 }, "name": "" }, { "location": { "latitude": 400273442, "longitude": -741220915 }, "name": "" }, { "location": { "latitude": 411236786, "longitude": -744070769 }, "name": "" }, { "location": { "latitude": 411633782, "longitude": -746784970 }, "name": "211-225 Plains Road, Augusta, NJ 07822, USA" }, { "location": { "latitude": 415830701, "longitude": -742952812 }, "name": "" }, { "location": { "latitude": 413447164, "longitude": -748712898 }, "name": "165 Pedersen Ridge Road, Milford, PA 18337, USA" }, { "location": { "latitude": 405047245, "longitude": -749800722 }, "name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA" }, { "location": { "latitude": 418858923, "longitude": -746156790 }, "name": "" }, { "location": { "latitude": 417951888, "longitude": -748484944 }, "name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA" }, { "location": { "latitude": 407033786, "longitude": -743977337 }, "name": "26 East 3rd Street, New Providence, NJ 07974, USA" }, { "location": { "latitude": 417548014, "longitude": -740075041 }, "name": "" }, { "location": { "latitude": 410395868, "longitude": -744972325 }, "name": "" }, { "location": { "latitude": 404615353, "longitude": -745129803 }, "name": "" }, { "location": { "latitude": 406589790, "longitude": -743560121 }, "name": "611 Lawrence Avenue, Westfield, NJ 07090, USA" }, { "location": { "latitude": 414653148, "longitude": -740477477 }, "name": "18 Lannis Avenue, New Windsor, NY 12553, USA" }, { "location": { "latitude": 405957808, "longitude": -743255336 }, "name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA" }, { "location": { "latitude": 411733589, "longitude": -741648093 }, "name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA" }, { "location": { "latitude": 412676291, "longitude": -742606606 }, "name": "1270 Lakes Road, Monroe, NY 10950, USA" }, { "location": { "latitude": 409224445, "longitude": -748286738 }, "name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA" }, { "location": { "latitude": 406523420, "longitude": -742135517 }, "name": "652 Garden Street, Elizabeth, NJ 07202, USA" }, { "location": { "latitude": 401827388, "longitude": -740294537 }, "name": "349 Sea Spray Court, Neptune City, NJ 07753, USA" }, { "location": { "latitude": 410564152, "longitude": -743685054 }, "name": "13-17 Stanley Street, West Milford, NJ 07480, USA" }, { "location": { "latitude": 408472324, "longitude": -740726046 }, "name": "47 Industrial Avenue, Teterboro, NJ 07608, USA" }, { "location": { "latitude": 412452168, "longitude": -740214052 }, "name": "5 White Oak Lane, Stony Point, NY 10980, USA" }, { "location": { "latitude": 409146138, "longitude": -746188906 }, "name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA" }, { "location": { "latitude": 404701380, "longitude": -744781745 }, "name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA" }, { "location": { "latitude": 409642566, "longitude": -746017679 }, "name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA" }, { "location": { "latitude": 408031728, "longitude": -748645385 }, "name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA" }, { "location": { "latitude": 413700272, "longitude": -742135189 }, "name": "367 Prospect Road, Chester, NY 10918, USA" }, { "location": { "latitude": 404310607, "longitude": -740282632 }, "name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA" }, { "location": { "latitude": 409319800, "longitude": -746201391 }, "name": "11 Ward Street, Mount Arlington, NJ 07856, USA" }, { "location": { "latitude": 406685311, "longitude": -742108603 }, "name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA" }, { "location": { "latitude": 419018117, "longitude": -749142781 }, "name": "43 Dreher Road, Roscoe, NY 12776, USA" }, { "location": { "latitude": 412856162, "longitude": -745148837 }, "name": "Swan Street, Pine Island, NY 10969, USA" }, { "location": { "latitude": 416560744, "longitude": -746721964 }, "name": "66 Pleasantview Avenue, Monticello, NY 12701, USA" }, { "location": { "latitude": 405314270, "longitude": -749836354 }, "name": "" }, { "location": { "latitude": 414219548, "longitude": -743327440 }, "name": "" }, { "location": { "latitude": 415534177, "longitude": -742900616 }, "name": "565 Winding Hills Road, Montgomery, NY 12549, USA" }, { "location": { "latitude": 406898530, "longitude": -749127080 }, "name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA" }, { "location": { "latitude": 407586880, "longitude": -741670168 }, "name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA" }, { "location": { "latitude": 400106455, "longitude": -742870190 }, "name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA" }, { "location": { "latitude": 400066188, "longitude": -746793294 }, "name": "" }, { "location": { "latitude": 418803880, "longitude": -744102673 }, "name": "40 Mountain Road, Napanoch, NY 12458, USA" }, { "location": { "latitude": 414204288, "longitude": -747895140 }, "name": "" }, { "location": { "latitude": 414777405, "longitude": -740615601 }, "name": "" }, { "location": { "latitude": 415464475, "longitude": -747175374 }, "name": "48 North Road, Forestburgh, NY 12777, USA" }, { "location": { "latitude": 404062378, "longitude": -746376177 }, "name": "" }, { "location": { "latitude": 405688272, "longitude": -749285130 }, "name": "" }, { "location": { "latitude": 400342070, "longitude": -748788996 }, "name": "" }, { "location": { "latitude": 401809022, "longitude": -744157964 }, "name": "" }, { "location": { "latitude": 404226644, "longitude": -740517141 }, "name": "9 Thompson Avenue, Leonardo, NJ 07737, USA" }, { "location": { "latitude": 410322033, "longitude": -747871659 }, "name": "" }, { "location": { "latitude": 407100674, "longitude": -747742727 }, "name": "" }, { "location": { "latitude": 418811433, "longitude": -741718005 }, "name": "213 Bush Road, Stone Ridge, NY 12484, USA" }, { "location": { "latitude": 415034302, "longitude": -743850945 }, "name": "" }, { "location": { "latitude": 411349992, "longitude": -743694161 }, "name": "" }, { "location": { "latitude": 404839914, "longitude": -744759616 }, "name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA" }, { "location": { "latitude": 414638017, "longitude": -745957854 }, "name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA" }, { "location": { "latitude": 412127800, "longitude": -740173578 }, "name": "" }, { "location": { "latitude": 401263460, "longitude": -747964303 }, "name": "" }, { "location": { "latitude": 412843391, "longitude": -749086026 }, "name": "" }, { "location": { "latitude": 418512773, "longitude": -743067823 }, "name": "" }, { "location": { "latitude": 404318328, "longitude": -740835638 }, "name": "42-102 Main Street, Belford, NJ 07718, USA" }, { "location": { "latitude": 419020746, "longitude": -741172328 }, "name": "" }, { "location": { "latitude": 404080723, "longitude": -746119569 }, "name": "" }, { "location": { "latitude": 401012643, "longitude": -744035134 }, "name": "" }, { "location": { "latitude": 404306372, "longitude": -741079661 }, "name": "" }, { "location": { "latitude": 403966326, "longitude": -748519297 }, "name": "" }, { "location": { "latitude": 405002031, "longitude": -748407866 }, "name": "" }, { "location": { "latitude": 409532885, "longitude": -742200683 }, "name": "" }, { "location": { "latitude": 416851321, "longitude": -742674555 }, "name": "" }, { "location": { "latitude": 406411633, "longitude": -741722051 }, "name": "3387 Richmond Terrace, Staten Island, NY 10303, USA" }, { "location": { "latitude": 413069058, "longitude": -744597778 }, "name": "261 Van Sickle Road, Goshen, NY 10924, USA" }, { "location": { "latitude": 418465462, "longitude": -746859398 }, "name": "" }, { "location": { "latitude": 411733222, "longitude": -744228360 }, "name": "" }, { "location": { "latitude": 410248224, "longitude": -747127767 }, "name": "3 Hasta Way, Newton, NJ 07860, USA" }] grpc-1.3.2/examples/python/multiplex/route_guide_pb2.py000066400000000000000000000513201310511640000232520ustar00rootroot00000000000000# Generated by the protocol buffer compiler. DO NOT EDIT! # source: route_guide.proto import sys _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database from google.protobuf import descriptor_pb2 # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() DESCRIPTOR = _descriptor.FileDescriptor( name='route_guide.proto', package='routeguide', syntax='proto3', serialized_pb=_b('\n\x11route_guide.proto\x12\nrouteguide\",\n\x05Point\x12\x10\n\x08latitude\x18\x01 \x01(\x05\x12\x11\n\tlongitude\x18\x02 \x01(\x05\"I\n\tRectangle\x12\x1d\n\x02lo\x18\x01 \x01(\x0b\x32\x11.routeguide.Point\x12\x1d\n\x02hi\x18\x02 \x01(\x0b\x32\x11.routeguide.Point\"<\n\x07\x46\x65\x61ture\x12\x0c\n\x04name\x18\x01 \x01(\t\x12#\n\x08location\x18\x02 \x01(\x0b\x32\x11.routeguide.Point\"A\n\tRouteNote\x12#\n\x08location\x18\x01 \x01(\x0b\x32\x11.routeguide.Point\x12\x0f\n\x07message\x18\x02 \x01(\t\"b\n\x0cRouteSummary\x12\x13\n\x0bpoint_count\x18\x01 \x01(\x05\x12\x15\n\rfeature_count\x18\x02 \x01(\x05\x12\x10\n\x08\x64istance\x18\x03 \x01(\x05\x12\x14\n\x0c\x65lapsed_time\x18\x04 \x01(\x05\x32\x85\x02\n\nRouteGuide\x12\x36\n\nGetFeature\x12\x11.routeguide.Point\x1a\x13.routeguide.Feature\"\x00\x12>\n\x0cListFeatures\x12\x15.routeguide.Rectangle\x1a\x13.routeguide.Feature\"\x00\x30\x01\x12>\n\x0bRecordRoute\x12\x11.routeguide.Point\x1a\x18.routeguide.RouteSummary\"\x00(\x01\x12?\n\tRouteChat\x12\x15.routeguide.RouteNote\x1a\x15.routeguide.RouteNote\"\x00(\x01\x30\x01\x42\x36\n\x1bio.grpc.examples.routeguideB\x0fRouteGuideProtoP\x01\xa2\x02\x03RTGb\x06proto3') ) _sym_db.RegisterFileDescriptor(DESCRIPTOR) _POINT = _descriptor.Descriptor( name='Point', full_name='routeguide.Point', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='latitude', full_name='routeguide.Point.latitude', index=0, number=1, type=5, cpp_type=1, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='longitude', full_name='routeguide.Point.longitude', index=1, number=2, type=5, cpp_type=1, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=33, serialized_end=77, ) _RECTANGLE = _descriptor.Descriptor( name='Rectangle', full_name='routeguide.Rectangle', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='lo', full_name='routeguide.Rectangle.lo', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='hi', full_name='routeguide.Rectangle.hi', index=1, number=2, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=79, serialized_end=152, ) _FEATURE = _descriptor.Descriptor( name='Feature', full_name='routeguide.Feature', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='name', full_name='routeguide.Feature.name', index=0, number=1, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='location', full_name='routeguide.Feature.location', index=1, number=2, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=154, serialized_end=214, ) _ROUTENOTE = _descriptor.Descriptor( name='RouteNote', full_name='routeguide.RouteNote', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='location', full_name='routeguide.RouteNote.location', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='message', full_name='routeguide.RouteNote.message', index=1, number=2, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=216, serialized_end=281, ) _ROUTESUMMARY = _descriptor.Descriptor( name='RouteSummary', full_name='routeguide.RouteSummary', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='point_count', full_name='routeguide.RouteSummary.point_count', index=0, number=1, type=5, cpp_type=1, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='feature_count', full_name='routeguide.RouteSummary.feature_count', index=1, number=2, type=5, cpp_type=1, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='distance', full_name='routeguide.RouteSummary.distance', index=2, number=3, type=5, cpp_type=1, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='elapsed_time', full_name='routeguide.RouteSummary.elapsed_time', index=3, number=4, type=5, cpp_type=1, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=283, serialized_end=381, ) _RECTANGLE.fields_by_name['lo'].message_type = _POINT _RECTANGLE.fields_by_name['hi'].message_type = _POINT _FEATURE.fields_by_name['location'].message_type = _POINT _ROUTENOTE.fields_by_name['location'].message_type = _POINT DESCRIPTOR.message_types_by_name['Point'] = _POINT DESCRIPTOR.message_types_by_name['Rectangle'] = _RECTANGLE DESCRIPTOR.message_types_by_name['Feature'] = _FEATURE DESCRIPTOR.message_types_by_name['RouteNote'] = _ROUTENOTE DESCRIPTOR.message_types_by_name['RouteSummary'] = _ROUTESUMMARY Point = _reflection.GeneratedProtocolMessageType('Point', (_message.Message,), dict( DESCRIPTOR = _POINT, __module__ = 'route_guide_pb2' # @@protoc_insertion_point(class_scope:routeguide.Point) )) _sym_db.RegisterMessage(Point) Rectangle = _reflection.GeneratedProtocolMessageType('Rectangle', (_message.Message,), dict( DESCRIPTOR = _RECTANGLE, __module__ = 'route_guide_pb2' # @@protoc_insertion_point(class_scope:routeguide.Rectangle) )) _sym_db.RegisterMessage(Rectangle) Feature = _reflection.GeneratedProtocolMessageType('Feature', (_message.Message,), dict( DESCRIPTOR = _FEATURE, __module__ = 'route_guide_pb2' # @@protoc_insertion_point(class_scope:routeguide.Feature) )) _sym_db.RegisterMessage(Feature) RouteNote = _reflection.GeneratedProtocolMessageType('RouteNote', (_message.Message,), dict( DESCRIPTOR = _ROUTENOTE, __module__ = 'route_guide_pb2' # @@protoc_insertion_point(class_scope:routeguide.RouteNote) )) _sym_db.RegisterMessage(RouteNote) RouteSummary = _reflection.GeneratedProtocolMessageType('RouteSummary', (_message.Message,), dict( DESCRIPTOR = _ROUTESUMMARY, __module__ = 'route_guide_pb2' # @@protoc_insertion_point(class_scope:routeguide.RouteSummary) )) _sym_db.RegisterMessage(RouteSummary) DESCRIPTOR.has_options = True DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\033io.grpc.examples.routeguideB\017RouteGuideProtoP\001\242\002\003RTG')) try: # THESE ELEMENTS WILL BE DEPRECATED. # Please use the generated *_pb2_grpc.py files instead. import grpc from grpc.framework.common import cardinality from grpc.framework.interfaces.face import utilities as face_utilities from grpc.beta import implementations as beta_implementations from grpc.beta import interfaces as beta_interfaces class RouteGuideStub(object): """Interface exported by the server. """ def __init__(self, channel): """Constructor. Args: channel: A grpc.Channel. """ self.GetFeature = channel.unary_unary( '/routeguide.RouteGuide/GetFeature', request_serializer=Point.SerializeToString, response_deserializer=Feature.FromString, ) self.ListFeatures = channel.unary_stream( '/routeguide.RouteGuide/ListFeatures', request_serializer=Rectangle.SerializeToString, response_deserializer=Feature.FromString, ) self.RecordRoute = channel.stream_unary( '/routeguide.RouteGuide/RecordRoute', request_serializer=Point.SerializeToString, response_deserializer=RouteSummary.FromString, ) self.RouteChat = channel.stream_stream( '/routeguide.RouteGuide/RouteChat', request_serializer=RouteNote.SerializeToString, response_deserializer=RouteNote.FromString, ) class RouteGuideServicer(object): """Interface exported by the server. """ def GetFeature(self, request, context): """A simple RPC. Obtains the feature at a given position. A feature with an empty name is returned if there's no feature at the given position. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def ListFeatures(self, request, context): """A server-to-client streaming RPC. Obtains the Features available within the given Rectangle. Results are streamed rather than returned at once (e.g. in a response message with a repeated field), as the rectangle may cover a large area and contain a huge number of features. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def RecordRoute(self, request_iterator, context): """A client-to-server streaming RPC. Accepts a stream of Points on a route being traversed, returning a RouteSummary when traversal is completed. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def RouteChat(self, request_iterator, context): """A Bidirectional streaming RPC. Accepts a stream of RouteNotes sent while a route is being traversed, while receiving other RouteNotes (e.g. from other users). """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def add_RouteGuideServicer_to_server(servicer, server): rpc_method_handlers = { 'GetFeature': grpc.unary_unary_rpc_method_handler( servicer.GetFeature, request_deserializer=Point.FromString, response_serializer=Feature.SerializeToString, ), 'ListFeatures': grpc.unary_stream_rpc_method_handler( servicer.ListFeatures, request_deserializer=Rectangle.FromString, response_serializer=Feature.SerializeToString, ), 'RecordRoute': grpc.stream_unary_rpc_method_handler( servicer.RecordRoute, request_deserializer=Point.FromString, response_serializer=RouteSummary.SerializeToString, ), 'RouteChat': grpc.stream_stream_rpc_method_handler( servicer.RouteChat, request_deserializer=RouteNote.FromString, response_serializer=RouteNote.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler( 'routeguide.RouteGuide', rpc_method_handlers) server.add_generic_rpc_handlers((generic_handler,)) class BetaRouteGuideServicer(object): """The Beta API is deprecated for 0.15.0 and later. It is recommended to use the GA API (classes and functions in this file not marked beta) for all further purposes. This class was generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0.""" """Interface exported by the server. """ def GetFeature(self, request, context): """A simple RPC. Obtains the feature at a given position. A feature with an empty name is returned if there's no feature at the given position. """ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED) def ListFeatures(self, request, context): """A server-to-client streaming RPC. Obtains the Features available within the given Rectangle. Results are streamed rather than returned at once (e.g. in a response message with a repeated field), as the rectangle may cover a large area and contain a huge number of features. """ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED) def RecordRoute(self, request_iterator, context): """A client-to-server streaming RPC. Accepts a stream of Points on a route being traversed, returning a RouteSummary when traversal is completed. """ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED) def RouteChat(self, request_iterator, context): """A Bidirectional streaming RPC. Accepts a stream of RouteNotes sent while a route is being traversed, while receiving other RouteNotes (e.g. from other users). """ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED) class BetaRouteGuideStub(object): """The Beta API is deprecated for 0.15.0 and later. It is recommended to use the GA API (classes and functions in this file not marked beta) for all further purposes. This class was generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0.""" """Interface exported by the server. """ def GetFeature(self, request, timeout, metadata=None, with_call=False, protocol_options=None): """A simple RPC. Obtains the feature at a given position. A feature with an empty name is returned if there's no feature at the given position. """ raise NotImplementedError() GetFeature.future = None def ListFeatures(self, request, timeout, metadata=None, with_call=False, protocol_options=None): """A server-to-client streaming RPC. Obtains the Features available within the given Rectangle. Results are streamed rather than returned at once (e.g. in a response message with a repeated field), as the rectangle may cover a large area and contain a huge number of features. """ raise NotImplementedError() def RecordRoute(self, request_iterator, timeout, metadata=None, with_call=False, protocol_options=None): """A client-to-server streaming RPC. Accepts a stream of Points on a route being traversed, returning a RouteSummary when traversal is completed. """ raise NotImplementedError() RecordRoute.future = None def RouteChat(self, request_iterator, timeout, metadata=None, with_call=False, protocol_options=None): """A Bidirectional streaming RPC. Accepts a stream of RouteNotes sent while a route is being traversed, while receiving other RouteNotes (e.g. from other users). """ raise NotImplementedError() def beta_create_RouteGuide_server(servicer, pool=None, pool_size=None, default_timeout=None, maximum_timeout=None): """The Beta API is deprecated for 0.15.0 and later. It is recommended to use the GA API (classes and functions in this file not marked beta) for all further purposes. This function was generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0""" request_deserializers = { ('routeguide.RouteGuide', 'GetFeature'): Point.FromString, ('routeguide.RouteGuide', 'ListFeatures'): Rectangle.FromString, ('routeguide.RouteGuide', 'RecordRoute'): Point.FromString, ('routeguide.RouteGuide', 'RouteChat'): RouteNote.FromString, } response_serializers = { ('routeguide.RouteGuide', 'GetFeature'): Feature.SerializeToString, ('routeguide.RouteGuide', 'ListFeatures'): Feature.SerializeToString, ('routeguide.RouteGuide', 'RecordRoute'): RouteSummary.SerializeToString, ('routeguide.RouteGuide', 'RouteChat'): RouteNote.SerializeToString, } method_implementations = { ('routeguide.RouteGuide', 'GetFeature'): face_utilities.unary_unary_inline(servicer.GetFeature), ('routeguide.RouteGuide', 'ListFeatures'): face_utilities.unary_stream_inline(servicer.ListFeatures), ('routeguide.RouteGuide', 'RecordRoute'): face_utilities.stream_unary_inline(servicer.RecordRoute), ('routeguide.RouteGuide', 'RouteChat'): face_utilities.stream_stream_inline(servicer.RouteChat), } server_options = beta_implementations.server_options(request_deserializers=request_deserializers, response_serializers=response_serializers, thread_pool=pool, thread_pool_size=pool_size, default_timeout=default_timeout, maximum_timeout=maximum_timeout) return beta_implementations.server(method_implementations, options=server_options) def beta_create_RouteGuide_stub(channel, host=None, metadata_transformer=None, pool=None, pool_size=None): """The Beta API is deprecated for 0.15.0 and later. It is recommended to use the GA API (classes and functions in this file not marked beta) for all further purposes. This function was generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0""" request_serializers = { ('routeguide.RouteGuide', 'GetFeature'): Point.SerializeToString, ('routeguide.RouteGuide', 'ListFeatures'): Rectangle.SerializeToString, ('routeguide.RouteGuide', 'RecordRoute'): Point.SerializeToString, ('routeguide.RouteGuide', 'RouteChat'): RouteNote.SerializeToString, } response_deserializers = { ('routeguide.RouteGuide', 'GetFeature'): Feature.FromString, ('routeguide.RouteGuide', 'ListFeatures'): Feature.FromString, ('routeguide.RouteGuide', 'RecordRoute'): RouteSummary.FromString, ('routeguide.RouteGuide', 'RouteChat'): RouteNote.FromString, } cardinalities = { 'GetFeature': cardinality.Cardinality.UNARY_UNARY, 'ListFeatures': cardinality.Cardinality.UNARY_STREAM, 'RecordRoute': cardinality.Cardinality.STREAM_UNARY, 'RouteChat': cardinality.Cardinality.STREAM_STREAM, } stub_options = beta_implementations.stub_options(host=host, metadata_transformer=metadata_transformer, request_serializers=request_serializers, response_deserializers=response_deserializers, thread_pool=pool, thread_pool_size=pool_size) return beta_implementations.dynamic_stub(channel, 'routeguide.RouteGuide', cardinalities, options=stub_options) except ImportError: pass # @@protoc_insertion_point(module_scope) grpc-1.3.2/examples/python/multiplex/route_guide_pb2_grpc.py000066400000000000000000000103031310511640000242610ustar00rootroot00000000000000import grpc from grpc.framework.common import cardinality from grpc.framework.interfaces.face import utilities as face_utilities import route_guide_pb2 as route__guide__pb2 class RouteGuideStub(object): """Interface exported by the server. """ def __init__(self, channel): """Constructor. Args: channel: A grpc.Channel. """ self.GetFeature = channel.unary_unary( '/routeguide.RouteGuide/GetFeature', request_serializer=route__guide__pb2.Point.SerializeToString, response_deserializer=route__guide__pb2.Feature.FromString, ) self.ListFeatures = channel.unary_stream( '/routeguide.RouteGuide/ListFeatures', request_serializer=route__guide__pb2.Rectangle.SerializeToString, response_deserializer=route__guide__pb2.Feature.FromString, ) self.RecordRoute = channel.stream_unary( '/routeguide.RouteGuide/RecordRoute', request_serializer=route__guide__pb2.Point.SerializeToString, response_deserializer=route__guide__pb2.RouteSummary.FromString, ) self.RouteChat = channel.stream_stream( '/routeguide.RouteGuide/RouteChat', request_serializer=route__guide__pb2.RouteNote.SerializeToString, response_deserializer=route__guide__pb2.RouteNote.FromString, ) class RouteGuideServicer(object): """Interface exported by the server. """ def GetFeature(self, request, context): """A simple RPC. Obtains the feature at a given position. A feature with an empty name is returned if there's no feature at the given position. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def ListFeatures(self, request, context): """A server-to-client streaming RPC. Obtains the Features available within the given Rectangle. Results are streamed rather than returned at once (e.g. in a response message with a repeated field), as the rectangle may cover a large area and contain a huge number of features. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def RecordRoute(self, request_iterator, context): """A client-to-server streaming RPC. Accepts a stream of Points on a route being traversed, returning a RouteSummary when traversal is completed. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def RouteChat(self, request_iterator, context): """A Bidirectional streaming RPC. Accepts a stream of RouteNotes sent while a route is being traversed, while receiving other RouteNotes (e.g. from other users). """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def add_RouteGuideServicer_to_server(servicer, server): rpc_method_handlers = { 'GetFeature': grpc.unary_unary_rpc_method_handler( servicer.GetFeature, request_deserializer=route__guide__pb2.Point.FromString, response_serializer=route__guide__pb2.Feature.SerializeToString, ), 'ListFeatures': grpc.unary_stream_rpc_method_handler( servicer.ListFeatures, request_deserializer=route__guide__pb2.Rectangle.FromString, response_serializer=route__guide__pb2.Feature.SerializeToString, ), 'RecordRoute': grpc.stream_unary_rpc_method_handler( servicer.RecordRoute, request_deserializer=route__guide__pb2.Point.FromString, response_serializer=route__guide__pb2.RouteSummary.SerializeToString, ), 'RouteChat': grpc.stream_stream_rpc_method_handler( servicer.RouteChat, request_deserializer=route__guide__pb2.RouteNote.FromString, response_serializer=route__guide__pb2.RouteNote.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler( 'routeguide.RouteGuide', rpc_method_handlers) server.add_generic_rpc_handlers((generic_handler,)) grpc-1.3.2/examples/python/multiplex/route_guide_resources.py000066400000000000000000000042551310511640000246060ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Common resources used in the gRPC route guide example.""" import json import route_guide_pb2 def read_route_guide_database(): """Reads the route guide database. Returns: The full contents of the route guide database as a sequence of route_guide_pb2.Features. """ feature_list = [] with open("route_guide_db.json") as route_guide_db_file: for item in json.load(route_guide_db_file): feature = route_guide_pb2.Feature( name=item["name"], location=route_guide_pb2.Point( latitude=item["location"]["latitude"], longitude=item["location"]["longitude"])) feature_list.append(feature) return feature_list grpc-1.3.2/examples/python/multiplex/run_codegen.py000066400000000000000000000036221310511640000224660ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Generates protocol messages and gRPC stubs.""" from grpc_tools import protoc protoc.main( ( '', '-I../../protos', '--python_out=.', '--grpc_python_out=.', '../../protos/helloworld.proto', ) ) protoc.main( ( '', '-I../../protos', '--python_out=.', '--grpc_python_out=.', '../../protos/route_guide.proto', ) ) grpc-1.3.2/examples/python/route_guide/000077500000000000000000000000001310511640000201115ustar00rootroot00000000000000grpc-1.3.2/examples/python/route_guide/.gitignore000066400000000000000000000000061310511640000220750ustar00rootroot00000000000000*.pyc grpc-1.3.2/examples/python/route_guide/README.md000066400000000000000000000001541310511640000213700ustar00rootroot00000000000000[This code's documentation lives on the grpc.io site.](http://www.grpc.io/docs/tutorials/basic/python.html) grpc-1.3.2/examples/python/route_guide/route_guide_client.py000066400000000000000000000111121310511640000243300ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """The Python implementation of the gRPC route guide client.""" from __future__ import print_function import random import time import grpc import route_guide_pb2 import route_guide_pb2_grpc import route_guide_resources def make_route_note(message, latitude, longitude): return route_guide_pb2.RouteNote( message=message, location=route_guide_pb2.Point(latitude=latitude, longitude=longitude)) def guide_get_one_feature(stub, point): feature = stub.GetFeature(point) if not feature.location: print("Server returned incomplete feature") return if feature.name: print("Feature called %s at %s" % (feature.name, feature.location)) else: print("Found no feature at %s" % feature.location) def guide_get_feature(stub): guide_get_one_feature(stub, route_guide_pb2.Point(latitude=409146138, longitude=-746188906)) guide_get_one_feature(stub, route_guide_pb2.Point(latitude=0, longitude=0)) def guide_list_features(stub): rectangle = route_guide_pb2.Rectangle( lo=route_guide_pb2.Point(latitude=400000000, longitude=-750000000), hi=route_guide_pb2.Point(latitude=420000000, longitude=-730000000)) print("Looking for features between 40, -75 and 42, -73") features = stub.ListFeatures(rectangle) for feature in features: print("Feature called %s at %s" % (feature.name, feature.location)) def generate_route(feature_list): for _ in range(0, 10): random_feature = feature_list[random.randint(0, len(feature_list) - 1)] print("Visiting point %s" % random_feature.location) yield random_feature.location time.sleep(random.uniform(0.5, 1.5)) def guide_record_route(stub): feature_list = route_guide_resources.read_route_guide_database() route_iterator = generate_route(feature_list) route_summary = stub.RecordRoute(route_iterator) print("Finished trip with %s points " % route_summary.point_count) print("Passed %s features " % route_summary.feature_count) print("Travelled %s meters " % route_summary.distance) print("It took %s seconds " % route_summary.elapsed_time) def generate_messages(): messages = [ make_route_note("First message", 0, 0), make_route_note("Second message", 0, 1), make_route_note("Third message", 1, 0), make_route_note("Fourth message", 0, 0), make_route_note("Fifth message", 1, 0), ] for msg in messages: print("Sending %s at %s" % (msg.message, msg.location)) yield msg time.sleep(random.uniform(0.5, 1.0)) def guide_route_chat(stub): responses = stub.RouteChat(generate_messages()) for response in responses: print("Received message %s at %s" % (response.message, response.location)) def run(): channel = grpc.insecure_channel('localhost:50051') stub = route_guide_pb2_grpc.RouteGuideStub(channel) print("-------------- GetFeature --------------") guide_get_feature(stub) print("-------------- ListFeatures --------------") guide_list_features(stub) print("-------------- RecordRoute --------------") guide_record_route(stub) print("-------------- RouteChat --------------") guide_route_chat(stub) if __name__ == '__main__': run() grpc-1.3.2/examples/python/route_guide/route_guide_db.json000066400000000000000000000327101310511640000237670ustar00rootroot00000000000000[{ "location": { "latitude": 407838351, "longitude": -746143763 }, "name": "Patriots Path, Mendham, NJ 07945, USA" }, { "location": { "latitude": 408122808, "longitude": -743999179 }, "name": "101 New Jersey 10, Whippany, NJ 07981, USA" }, { "location": { "latitude": 413628156, "longitude": -749015468 }, "name": "U.S. 6, Shohola, PA 18458, USA" }, { "location": { "latitude": 419999544, "longitude": -740371136 }, "name": "5 Conners Road, Kingston, NY 12401, USA" }, { "location": { "latitude": 414008389, "longitude": -743951297 }, "name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA" }, { "location": { "latitude": 419611318, "longitude": -746524769 }, "name": "287 Flugertown Road, Livingston Manor, NY 12758, USA" }, { "location": { "latitude": 406109563, "longitude": -742186778 }, "name": "4001 Tremley Point Road, Linden, NJ 07036, USA" }, { "location": { "latitude": 416802456, "longitude": -742370183 }, "name": "352 South Mountain Road, Wallkill, NY 12589, USA" }, { "location": { "latitude": 412950425, "longitude": -741077389 }, "name": "Bailey Turn Road, Harriman, NY 10926, USA" }, { "location": { "latitude": 412144655, "longitude": -743949739 }, "name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA" }, { "location": { "latitude": 415736605, "longitude": -742847522 }, "name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA" }, { "location": { "latitude": 413843930, "longitude": -740501726 }, "name": "162 Merrill Road, Highland Mills, NY 10930, USA" }, { "location": { "latitude": 410873075, "longitude": -744459023 }, "name": "Clinton Road, West Milford, NJ 07480, USA" }, { "location": { "latitude": 412346009, "longitude": -744026814 }, "name": "16 Old Brook Lane, Warwick, NY 10990, USA" }, { "location": { "latitude": 402948455, "longitude": -747903913 }, "name": "3 Drake Lane, Pennington, NJ 08534, USA" }, { "location": { "latitude": 406337092, "longitude": -740122226 }, "name": "6324 8th Avenue, Brooklyn, NY 11220, USA" }, { "location": { "latitude": 406421967, "longitude": -747727624 }, "name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA" }, { "location": { "latitude": 416318082, "longitude": -749677716 }, "name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA" }, { "location": { "latitude": 415301720, "longitude": -748416257 }, "name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA" }, { "location": { "latitude": 402647019, "longitude": -747071791 }, "name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA" }, { "location": { "latitude": 412567807, "longitude": -741058078 }, "name": "New York State Reference Route 987E, Southfields, NY 10975, USA" }, { "location": { "latitude": 416855156, "longitude": -744420597 }, "name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA" }, { "location": { "latitude": 404663628, "longitude": -744820157 }, "name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA" }, { "location": { "latitude": 407113723, "longitude": -749746483 }, "name": "" }, { "location": { "latitude": 402133926, "longitude": -743613249 }, "name": "" }, { "location": { "latitude": 400273442, "longitude": -741220915 }, "name": "" }, { "location": { "latitude": 411236786, "longitude": -744070769 }, "name": "" }, { "location": { "latitude": 411633782, "longitude": -746784970 }, "name": "211-225 Plains Road, Augusta, NJ 07822, USA" }, { "location": { "latitude": 415830701, "longitude": -742952812 }, "name": "" }, { "location": { "latitude": 413447164, "longitude": -748712898 }, "name": "165 Pedersen Ridge Road, Milford, PA 18337, USA" }, { "location": { "latitude": 405047245, "longitude": -749800722 }, "name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA" }, { "location": { "latitude": 418858923, "longitude": -746156790 }, "name": "" }, { "location": { "latitude": 417951888, "longitude": -748484944 }, "name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA" }, { "location": { "latitude": 407033786, "longitude": -743977337 }, "name": "26 East 3rd Street, New Providence, NJ 07974, USA" }, { "location": { "latitude": 417548014, "longitude": -740075041 }, "name": "" }, { "location": { "latitude": 410395868, "longitude": -744972325 }, "name": "" }, { "location": { "latitude": 404615353, "longitude": -745129803 }, "name": "" }, { "location": { "latitude": 406589790, "longitude": -743560121 }, "name": "611 Lawrence Avenue, Westfield, NJ 07090, USA" }, { "location": { "latitude": 414653148, "longitude": -740477477 }, "name": "18 Lannis Avenue, New Windsor, NY 12553, USA" }, { "location": { "latitude": 405957808, "longitude": -743255336 }, "name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA" }, { "location": { "latitude": 411733589, "longitude": -741648093 }, "name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA" }, { "location": { "latitude": 412676291, "longitude": -742606606 }, "name": "1270 Lakes Road, Monroe, NY 10950, USA" }, { "location": { "latitude": 409224445, "longitude": -748286738 }, "name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA" }, { "location": { "latitude": 406523420, "longitude": -742135517 }, "name": "652 Garden Street, Elizabeth, NJ 07202, USA" }, { "location": { "latitude": 401827388, "longitude": -740294537 }, "name": "349 Sea Spray Court, Neptune City, NJ 07753, USA" }, { "location": { "latitude": 410564152, "longitude": -743685054 }, "name": "13-17 Stanley Street, West Milford, NJ 07480, USA" }, { "location": { "latitude": 408472324, "longitude": -740726046 }, "name": "47 Industrial Avenue, Teterboro, NJ 07608, USA" }, { "location": { "latitude": 412452168, "longitude": -740214052 }, "name": "5 White Oak Lane, Stony Point, NY 10980, USA" }, { "location": { "latitude": 409146138, "longitude": -746188906 }, "name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA" }, { "location": { "latitude": 404701380, "longitude": -744781745 }, "name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA" }, { "location": { "latitude": 409642566, "longitude": -746017679 }, "name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA" }, { "location": { "latitude": 408031728, "longitude": -748645385 }, "name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA" }, { "location": { "latitude": 413700272, "longitude": -742135189 }, "name": "367 Prospect Road, Chester, NY 10918, USA" }, { "location": { "latitude": 404310607, "longitude": -740282632 }, "name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA" }, { "location": { "latitude": 409319800, "longitude": -746201391 }, "name": "11 Ward Street, Mount Arlington, NJ 07856, USA" }, { "location": { "latitude": 406685311, "longitude": -742108603 }, "name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA" }, { "location": { "latitude": 419018117, "longitude": -749142781 }, "name": "43 Dreher Road, Roscoe, NY 12776, USA" }, { "location": { "latitude": 412856162, "longitude": -745148837 }, "name": "Swan Street, Pine Island, NY 10969, USA" }, { "location": { "latitude": 416560744, "longitude": -746721964 }, "name": "66 Pleasantview Avenue, Monticello, NY 12701, USA" }, { "location": { "latitude": 405314270, "longitude": -749836354 }, "name": "" }, { "location": { "latitude": 414219548, "longitude": -743327440 }, "name": "" }, { "location": { "latitude": 415534177, "longitude": -742900616 }, "name": "565 Winding Hills Road, Montgomery, NY 12549, USA" }, { "location": { "latitude": 406898530, "longitude": -749127080 }, "name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA" }, { "location": { "latitude": 407586880, "longitude": -741670168 }, "name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA" }, { "location": { "latitude": 400106455, "longitude": -742870190 }, "name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA" }, { "location": { "latitude": 400066188, "longitude": -746793294 }, "name": "" }, { "location": { "latitude": 418803880, "longitude": -744102673 }, "name": "40 Mountain Road, Napanoch, NY 12458, USA" }, { "location": { "latitude": 414204288, "longitude": -747895140 }, "name": "" }, { "location": { "latitude": 414777405, "longitude": -740615601 }, "name": "" }, { "location": { "latitude": 415464475, "longitude": -747175374 }, "name": "48 North Road, Forestburgh, NY 12777, USA" }, { "location": { "latitude": 404062378, "longitude": -746376177 }, "name": "" }, { "location": { "latitude": 405688272, "longitude": -749285130 }, "name": "" }, { "location": { "latitude": 400342070, "longitude": -748788996 }, "name": "" }, { "location": { "latitude": 401809022, "longitude": -744157964 }, "name": "" }, { "location": { "latitude": 404226644, "longitude": -740517141 }, "name": "9 Thompson Avenue, Leonardo, NJ 07737, USA" }, { "location": { "latitude": 410322033, "longitude": -747871659 }, "name": "" }, { "location": { "latitude": 407100674, "longitude": -747742727 }, "name": "" }, { "location": { "latitude": 418811433, "longitude": -741718005 }, "name": "213 Bush Road, Stone Ridge, NY 12484, USA" }, { "location": { "latitude": 415034302, "longitude": -743850945 }, "name": "" }, { "location": { "latitude": 411349992, "longitude": -743694161 }, "name": "" }, { "location": { "latitude": 404839914, "longitude": -744759616 }, "name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA" }, { "location": { "latitude": 414638017, "longitude": -745957854 }, "name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA" }, { "location": { "latitude": 412127800, "longitude": -740173578 }, "name": "" }, { "location": { "latitude": 401263460, "longitude": -747964303 }, "name": "" }, { "location": { "latitude": 412843391, "longitude": -749086026 }, "name": "" }, { "location": { "latitude": 418512773, "longitude": -743067823 }, "name": "" }, { "location": { "latitude": 404318328, "longitude": -740835638 }, "name": "42-102 Main Street, Belford, NJ 07718, USA" }, { "location": { "latitude": 419020746, "longitude": -741172328 }, "name": "" }, { "location": { "latitude": 404080723, "longitude": -746119569 }, "name": "" }, { "location": { "latitude": 401012643, "longitude": -744035134 }, "name": "" }, { "location": { "latitude": 404306372, "longitude": -741079661 }, "name": "" }, { "location": { "latitude": 403966326, "longitude": -748519297 }, "name": "" }, { "location": { "latitude": 405002031, "longitude": -748407866 }, "name": "" }, { "location": { "latitude": 409532885, "longitude": -742200683 }, "name": "" }, { "location": { "latitude": 416851321, "longitude": -742674555 }, "name": "" }, { "location": { "latitude": 406411633, "longitude": -741722051 }, "name": "3387 Richmond Terrace, Staten Island, NY 10303, USA" }, { "location": { "latitude": 413069058, "longitude": -744597778 }, "name": "261 Van Sickle Road, Goshen, NY 10924, USA" }, { "location": { "latitude": 418465462, "longitude": -746859398 }, "name": "" }, { "location": { "latitude": 411733222, "longitude": -744228360 }, "name": "" }, { "location": { "latitude": 410248224, "longitude": -747127767 }, "name": "3 Hasta Way, Newton, NJ 07860, USA" }] grpc-1.3.2/examples/python/route_guide/route_guide_pb2.py000066400000000000000000000513201310511640000235420ustar00rootroot00000000000000# Generated by the protocol buffer compiler. DO NOT EDIT! # source: route_guide.proto import sys _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database from google.protobuf import descriptor_pb2 # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() DESCRIPTOR = _descriptor.FileDescriptor( name='route_guide.proto', package='routeguide', syntax='proto3', serialized_pb=_b('\n\x11route_guide.proto\x12\nrouteguide\",\n\x05Point\x12\x10\n\x08latitude\x18\x01 \x01(\x05\x12\x11\n\tlongitude\x18\x02 \x01(\x05\"I\n\tRectangle\x12\x1d\n\x02lo\x18\x01 \x01(\x0b\x32\x11.routeguide.Point\x12\x1d\n\x02hi\x18\x02 \x01(\x0b\x32\x11.routeguide.Point\"<\n\x07\x46\x65\x61ture\x12\x0c\n\x04name\x18\x01 \x01(\t\x12#\n\x08location\x18\x02 \x01(\x0b\x32\x11.routeguide.Point\"A\n\tRouteNote\x12#\n\x08location\x18\x01 \x01(\x0b\x32\x11.routeguide.Point\x12\x0f\n\x07message\x18\x02 \x01(\t\"b\n\x0cRouteSummary\x12\x13\n\x0bpoint_count\x18\x01 \x01(\x05\x12\x15\n\rfeature_count\x18\x02 \x01(\x05\x12\x10\n\x08\x64istance\x18\x03 \x01(\x05\x12\x14\n\x0c\x65lapsed_time\x18\x04 \x01(\x05\x32\x85\x02\n\nRouteGuide\x12\x36\n\nGetFeature\x12\x11.routeguide.Point\x1a\x13.routeguide.Feature\"\x00\x12>\n\x0cListFeatures\x12\x15.routeguide.Rectangle\x1a\x13.routeguide.Feature\"\x00\x30\x01\x12>\n\x0bRecordRoute\x12\x11.routeguide.Point\x1a\x18.routeguide.RouteSummary\"\x00(\x01\x12?\n\tRouteChat\x12\x15.routeguide.RouteNote\x1a\x15.routeguide.RouteNote\"\x00(\x01\x30\x01\x42\x36\n\x1bio.grpc.examples.routeguideB\x0fRouteGuideProtoP\x01\xa2\x02\x03RTGb\x06proto3') ) _sym_db.RegisterFileDescriptor(DESCRIPTOR) _POINT = _descriptor.Descriptor( name='Point', full_name='routeguide.Point', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='latitude', full_name='routeguide.Point.latitude', index=0, number=1, type=5, cpp_type=1, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='longitude', full_name='routeguide.Point.longitude', index=1, number=2, type=5, cpp_type=1, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=33, serialized_end=77, ) _RECTANGLE = _descriptor.Descriptor( name='Rectangle', full_name='routeguide.Rectangle', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='lo', full_name='routeguide.Rectangle.lo', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='hi', full_name='routeguide.Rectangle.hi', index=1, number=2, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=79, serialized_end=152, ) _FEATURE = _descriptor.Descriptor( name='Feature', full_name='routeguide.Feature', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='name', full_name='routeguide.Feature.name', index=0, number=1, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='location', full_name='routeguide.Feature.location', index=1, number=2, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=154, serialized_end=214, ) _ROUTENOTE = _descriptor.Descriptor( name='RouteNote', full_name='routeguide.RouteNote', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='location', full_name='routeguide.RouteNote.location', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='message', full_name='routeguide.RouteNote.message', index=1, number=2, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=216, serialized_end=281, ) _ROUTESUMMARY = _descriptor.Descriptor( name='RouteSummary', full_name='routeguide.RouteSummary', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='point_count', full_name='routeguide.RouteSummary.point_count', index=0, number=1, type=5, cpp_type=1, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='feature_count', full_name='routeguide.RouteSummary.feature_count', index=1, number=2, type=5, cpp_type=1, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='distance', full_name='routeguide.RouteSummary.distance', index=2, number=3, type=5, cpp_type=1, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='elapsed_time', full_name='routeguide.RouteSummary.elapsed_time', index=3, number=4, type=5, cpp_type=1, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], serialized_start=283, serialized_end=381, ) _RECTANGLE.fields_by_name['lo'].message_type = _POINT _RECTANGLE.fields_by_name['hi'].message_type = _POINT _FEATURE.fields_by_name['location'].message_type = _POINT _ROUTENOTE.fields_by_name['location'].message_type = _POINT DESCRIPTOR.message_types_by_name['Point'] = _POINT DESCRIPTOR.message_types_by_name['Rectangle'] = _RECTANGLE DESCRIPTOR.message_types_by_name['Feature'] = _FEATURE DESCRIPTOR.message_types_by_name['RouteNote'] = _ROUTENOTE DESCRIPTOR.message_types_by_name['RouteSummary'] = _ROUTESUMMARY Point = _reflection.GeneratedProtocolMessageType('Point', (_message.Message,), dict( DESCRIPTOR = _POINT, __module__ = 'route_guide_pb2' # @@protoc_insertion_point(class_scope:routeguide.Point) )) _sym_db.RegisterMessage(Point) Rectangle = _reflection.GeneratedProtocolMessageType('Rectangle', (_message.Message,), dict( DESCRIPTOR = _RECTANGLE, __module__ = 'route_guide_pb2' # @@protoc_insertion_point(class_scope:routeguide.Rectangle) )) _sym_db.RegisterMessage(Rectangle) Feature = _reflection.GeneratedProtocolMessageType('Feature', (_message.Message,), dict( DESCRIPTOR = _FEATURE, __module__ = 'route_guide_pb2' # @@protoc_insertion_point(class_scope:routeguide.Feature) )) _sym_db.RegisterMessage(Feature) RouteNote = _reflection.GeneratedProtocolMessageType('RouteNote', (_message.Message,), dict( DESCRIPTOR = _ROUTENOTE, __module__ = 'route_guide_pb2' # @@protoc_insertion_point(class_scope:routeguide.RouteNote) )) _sym_db.RegisterMessage(RouteNote) RouteSummary = _reflection.GeneratedProtocolMessageType('RouteSummary', (_message.Message,), dict( DESCRIPTOR = _ROUTESUMMARY, __module__ = 'route_guide_pb2' # @@protoc_insertion_point(class_scope:routeguide.RouteSummary) )) _sym_db.RegisterMessage(RouteSummary) DESCRIPTOR.has_options = True DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\033io.grpc.examples.routeguideB\017RouteGuideProtoP\001\242\002\003RTG')) try: # THESE ELEMENTS WILL BE DEPRECATED. # Please use the generated *_pb2_grpc.py files instead. import grpc from grpc.framework.common import cardinality from grpc.framework.interfaces.face import utilities as face_utilities from grpc.beta import implementations as beta_implementations from grpc.beta import interfaces as beta_interfaces class RouteGuideStub(object): """Interface exported by the server. """ def __init__(self, channel): """Constructor. Args: channel: A grpc.Channel. """ self.GetFeature = channel.unary_unary( '/routeguide.RouteGuide/GetFeature', request_serializer=Point.SerializeToString, response_deserializer=Feature.FromString, ) self.ListFeatures = channel.unary_stream( '/routeguide.RouteGuide/ListFeatures', request_serializer=Rectangle.SerializeToString, response_deserializer=Feature.FromString, ) self.RecordRoute = channel.stream_unary( '/routeguide.RouteGuide/RecordRoute', request_serializer=Point.SerializeToString, response_deserializer=RouteSummary.FromString, ) self.RouteChat = channel.stream_stream( '/routeguide.RouteGuide/RouteChat', request_serializer=RouteNote.SerializeToString, response_deserializer=RouteNote.FromString, ) class RouteGuideServicer(object): """Interface exported by the server. """ def GetFeature(self, request, context): """A simple RPC. Obtains the feature at a given position. A feature with an empty name is returned if there's no feature at the given position. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def ListFeatures(self, request, context): """A server-to-client streaming RPC. Obtains the Features available within the given Rectangle. Results are streamed rather than returned at once (e.g. in a response message with a repeated field), as the rectangle may cover a large area and contain a huge number of features. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def RecordRoute(self, request_iterator, context): """A client-to-server streaming RPC. Accepts a stream of Points on a route being traversed, returning a RouteSummary when traversal is completed. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def RouteChat(self, request_iterator, context): """A Bidirectional streaming RPC. Accepts a stream of RouteNotes sent while a route is being traversed, while receiving other RouteNotes (e.g. from other users). """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def add_RouteGuideServicer_to_server(servicer, server): rpc_method_handlers = { 'GetFeature': grpc.unary_unary_rpc_method_handler( servicer.GetFeature, request_deserializer=Point.FromString, response_serializer=Feature.SerializeToString, ), 'ListFeatures': grpc.unary_stream_rpc_method_handler( servicer.ListFeatures, request_deserializer=Rectangle.FromString, response_serializer=Feature.SerializeToString, ), 'RecordRoute': grpc.stream_unary_rpc_method_handler( servicer.RecordRoute, request_deserializer=Point.FromString, response_serializer=RouteSummary.SerializeToString, ), 'RouteChat': grpc.stream_stream_rpc_method_handler( servicer.RouteChat, request_deserializer=RouteNote.FromString, response_serializer=RouteNote.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler( 'routeguide.RouteGuide', rpc_method_handlers) server.add_generic_rpc_handlers((generic_handler,)) class BetaRouteGuideServicer(object): """The Beta API is deprecated for 0.15.0 and later. It is recommended to use the GA API (classes and functions in this file not marked beta) for all further purposes. This class was generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0.""" """Interface exported by the server. """ def GetFeature(self, request, context): """A simple RPC. Obtains the feature at a given position. A feature with an empty name is returned if there's no feature at the given position. """ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED) def ListFeatures(self, request, context): """A server-to-client streaming RPC. Obtains the Features available within the given Rectangle. Results are streamed rather than returned at once (e.g. in a response message with a repeated field), as the rectangle may cover a large area and contain a huge number of features. """ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED) def RecordRoute(self, request_iterator, context): """A client-to-server streaming RPC. Accepts a stream of Points on a route being traversed, returning a RouteSummary when traversal is completed. """ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED) def RouteChat(self, request_iterator, context): """A Bidirectional streaming RPC. Accepts a stream of RouteNotes sent while a route is being traversed, while receiving other RouteNotes (e.g. from other users). """ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED) class BetaRouteGuideStub(object): """The Beta API is deprecated for 0.15.0 and later. It is recommended to use the GA API (classes and functions in this file not marked beta) for all further purposes. This class was generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0.""" """Interface exported by the server. """ def GetFeature(self, request, timeout, metadata=None, with_call=False, protocol_options=None): """A simple RPC. Obtains the feature at a given position. A feature with an empty name is returned if there's no feature at the given position. """ raise NotImplementedError() GetFeature.future = None def ListFeatures(self, request, timeout, metadata=None, with_call=False, protocol_options=None): """A server-to-client streaming RPC. Obtains the Features available within the given Rectangle. Results are streamed rather than returned at once (e.g. in a response message with a repeated field), as the rectangle may cover a large area and contain a huge number of features. """ raise NotImplementedError() def RecordRoute(self, request_iterator, timeout, metadata=None, with_call=False, protocol_options=None): """A client-to-server streaming RPC. Accepts a stream of Points on a route being traversed, returning a RouteSummary when traversal is completed. """ raise NotImplementedError() RecordRoute.future = None def RouteChat(self, request_iterator, timeout, metadata=None, with_call=False, protocol_options=None): """A Bidirectional streaming RPC. Accepts a stream of RouteNotes sent while a route is being traversed, while receiving other RouteNotes (e.g. from other users). """ raise NotImplementedError() def beta_create_RouteGuide_server(servicer, pool=None, pool_size=None, default_timeout=None, maximum_timeout=None): """The Beta API is deprecated for 0.15.0 and later. It is recommended to use the GA API (classes and functions in this file not marked beta) for all further purposes. This function was generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0""" request_deserializers = { ('routeguide.RouteGuide', 'GetFeature'): Point.FromString, ('routeguide.RouteGuide', 'ListFeatures'): Rectangle.FromString, ('routeguide.RouteGuide', 'RecordRoute'): Point.FromString, ('routeguide.RouteGuide', 'RouteChat'): RouteNote.FromString, } response_serializers = { ('routeguide.RouteGuide', 'GetFeature'): Feature.SerializeToString, ('routeguide.RouteGuide', 'ListFeatures'): Feature.SerializeToString, ('routeguide.RouteGuide', 'RecordRoute'): RouteSummary.SerializeToString, ('routeguide.RouteGuide', 'RouteChat'): RouteNote.SerializeToString, } method_implementations = { ('routeguide.RouteGuide', 'GetFeature'): face_utilities.unary_unary_inline(servicer.GetFeature), ('routeguide.RouteGuide', 'ListFeatures'): face_utilities.unary_stream_inline(servicer.ListFeatures), ('routeguide.RouteGuide', 'RecordRoute'): face_utilities.stream_unary_inline(servicer.RecordRoute), ('routeguide.RouteGuide', 'RouteChat'): face_utilities.stream_stream_inline(servicer.RouteChat), } server_options = beta_implementations.server_options(request_deserializers=request_deserializers, response_serializers=response_serializers, thread_pool=pool, thread_pool_size=pool_size, default_timeout=default_timeout, maximum_timeout=maximum_timeout) return beta_implementations.server(method_implementations, options=server_options) def beta_create_RouteGuide_stub(channel, host=None, metadata_transformer=None, pool=None, pool_size=None): """The Beta API is deprecated for 0.15.0 and later. It is recommended to use the GA API (classes and functions in this file not marked beta) for all further purposes. This function was generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0""" request_serializers = { ('routeguide.RouteGuide', 'GetFeature'): Point.SerializeToString, ('routeguide.RouteGuide', 'ListFeatures'): Rectangle.SerializeToString, ('routeguide.RouteGuide', 'RecordRoute'): Point.SerializeToString, ('routeguide.RouteGuide', 'RouteChat'): RouteNote.SerializeToString, } response_deserializers = { ('routeguide.RouteGuide', 'GetFeature'): Feature.FromString, ('routeguide.RouteGuide', 'ListFeatures'): Feature.FromString, ('routeguide.RouteGuide', 'RecordRoute'): RouteSummary.FromString, ('routeguide.RouteGuide', 'RouteChat'): RouteNote.FromString, } cardinalities = { 'GetFeature': cardinality.Cardinality.UNARY_UNARY, 'ListFeatures': cardinality.Cardinality.UNARY_STREAM, 'RecordRoute': cardinality.Cardinality.STREAM_UNARY, 'RouteChat': cardinality.Cardinality.STREAM_STREAM, } stub_options = beta_implementations.stub_options(host=host, metadata_transformer=metadata_transformer, request_serializers=request_serializers, response_deserializers=response_deserializers, thread_pool=pool, thread_pool_size=pool_size) return beta_implementations.dynamic_stub(channel, 'routeguide.RouteGuide', cardinalities, options=stub_options) except ImportError: pass # @@protoc_insertion_point(module_scope) grpc-1.3.2/examples/python/route_guide/route_guide_pb2_grpc.py000066400000000000000000000103031310511640000245510ustar00rootroot00000000000000import grpc from grpc.framework.common import cardinality from grpc.framework.interfaces.face import utilities as face_utilities import route_guide_pb2 as route__guide__pb2 class RouteGuideStub(object): """Interface exported by the server. """ def __init__(self, channel): """Constructor. Args: channel: A grpc.Channel. """ self.GetFeature = channel.unary_unary( '/routeguide.RouteGuide/GetFeature', request_serializer=route__guide__pb2.Point.SerializeToString, response_deserializer=route__guide__pb2.Feature.FromString, ) self.ListFeatures = channel.unary_stream( '/routeguide.RouteGuide/ListFeatures', request_serializer=route__guide__pb2.Rectangle.SerializeToString, response_deserializer=route__guide__pb2.Feature.FromString, ) self.RecordRoute = channel.stream_unary( '/routeguide.RouteGuide/RecordRoute', request_serializer=route__guide__pb2.Point.SerializeToString, response_deserializer=route__guide__pb2.RouteSummary.FromString, ) self.RouteChat = channel.stream_stream( '/routeguide.RouteGuide/RouteChat', request_serializer=route__guide__pb2.RouteNote.SerializeToString, response_deserializer=route__guide__pb2.RouteNote.FromString, ) class RouteGuideServicer(object): """Interface exported by the server. """ def GetFeature(self, request, context): """A simple RPC. Obtains the feature at a given position. A feature with an empty name is returned if there's no feature at the given position. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def ListFeatures(self, request, context): """A server-to-client streaming RPC. Obtains the Features available within the given Rectangle. Results are streamed rather than returned at once (e.g. in a response message with a repeated field), as the rectangle may cover a large area and contain a huge number of features. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def RecordRoute(self, request_iterator, context): """A client-to-server streaming RPC. Accepts a stream of Points on a route being traversed, returning a RouteSummary when traversal is completed. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def RouteChat(self, request_iterator, context): """A Bidirectional streaming RPC. Accepts a stream of RouteNotes sent while a route is being traversed, while receiving other RouteNotes (e.g. from other users). """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def add_RouteGuideServicer_to_server(servicer, server): rpc_method_handlers = { 'GetFeature': grpc.unary_unary_rpc_method_handler( servicer.GetFeature, request_deserializer=route__guide__pb2.Point.FromString, response_serializer=route__guide__pb2.Feature.SerializeToString, ), 'ListFeatures': grpc.unary_stream_rpc_method_handler( servicer.ListFeatures, request_deserializer=route__guide__pb2.Rectangle.FromString, response_serializer=route__guide__pb2.Feature.SerializeToString, ), 'RecordRoute': grpc.stream_unary_rpc_method_handler( servicer.RecordRoute, request_deserializer=route__guide__pb2.Point.FromString, response_serializer=route__guide__pb2.RouteSummary.SerializeToString, ), 'RouteChat': grpc.stream_stream_rpc_method_handler( servicer.RouteChat, request_deserializer=route__guide__pb2.RouteNote.FromString, response_serializer=route__guide__pb2.RouteNote.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler( 'routeguide.RouteGuide', rpc_method_handlers) server.add_generic_rpc_handlers((generic_handler,)) grpc-1.3.2/examples/python/route_guide/route_guide_resources.py000066400000000000000000000042551310511640000250760ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Common resources used in the gRPC route guide example.""" import json import route_guide_pb2 def read_route_guide_database(): """Reads the route guide database. Returns: The full contents of the route guide database as a sequence of route_guide_pb2.Features. """ feature_list = [] with open("route_guide_db.json") as route_guide_db_file: for item in json.load(route_guide_db_file): feature = route_guide_pb2.Feature( name=item["name"], location=route_guide_pb2.Point( latitude=item["location"]["latitude"], longitude=item["location"]["longitude"])) feature_list.append(feature) return feature_list grpc-1.3.2/examples/python/route_guide/route_guide_server.py000066400000000000000000000114641310511640000243720ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """The Python implementation of the gRPC route guide server.""" from concurrent import futures import time import math import grpc import route_guide_pb2 import route_guide_pb2_grpc import route_guide_resources _ONE_DAY_IN_SECONDS = 60 * 60 * 24 def get_feature(feature_db, point): """Returns Feature at given location or None.""" for feature in feature_db: if feature.location == point: return feature return None def get_distance(start, end): """Distance between two points.""" coord_factor = 10000000.0 lat_1 = start.latitude / coord_factor lat_2 = end.latitude / coord_factor lon_1 = start.longitude / coord_factor lon_2 = end.longitude / coord_factor lat_rad_1 = math.radians(lat_1) lat_rad_2 = math.radians(lat_2) delta_lat_rad = math.radians(lat_2 - lat_1) delta_lon_rad = math.radians(lon_2 - lon_1) a = (pow(math.sin(delta_lat_rad / 2), 2) + (math.cos(lat_rad_1) * math.cos(lat_rad_2) * pow(math.sin(delta_lon_rad / 2), 2))) c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) R = 6371000; # metres return R * c; class RouteGuideServicer(route_guide_pb2_grpc.RouteGuideServicer): """Provides methods that implement functionality of route guide server.""" def __init__(self): self.db = route_guide_resources.read_route_guide_database() def GetFeature(self, request, context): feature = get_feature(self.db, request) if feature is None: return route_guide_pb2.Feature(name="", location=request) else: return feature def ListFeatures(self, request, context): left = min(request.lo.longitude, request.hi.longitude) right = max(request.lo.longitude, request.hi.longitude) top = max(request.lo.latitude, request.hi.latitude) bottom = min(request.lo.latitude, request.hi.latitude) for feature in self.db: if (feature.location.longitude >= left and feature.location.longitude <= right and feature.location.latitude >= bottom and feature.location.latitude <= top): yield feature def RecordRoute(self, request_iterator, context): point_count = 0 feature_count = 0 distance = 0.0 prev_point = None start_time = time.time() for point in request_iterator: point_count += 1 if get_feature(self.db, point): feature_count += 1 if prev_point: distance += get_distance(prev_point, point) prev_point = point elapsed_time = time.time() - start_time return route_guide_pb2.RouteSummary(point_count=point_count, feature_count=feature_count, distance=int(distance), elapsed_time=int(elapsed_time)) def RouteChat(self, request_iterator, context): prev_notes = [] for new_note in request_iterator: for prev_note in prev_notes: if prev_note.location == new_note.location: yield prev_note prev_notes.append(new_note) def serve(): server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) route_guide_pb2_grpc.add_RouteGuideServicer_to_server( RouteGuideServicer(), server) server.add_insecure_port('[::]:50051') server.start() try: while True: time.sleep(_ONE_DAY_IN_SECONDS) except KeyboardInterrupt: server.stop(0) if __name__ == '__main__': serve() grpc-1.3.2/examples/python/route_guide/run_codegen.py000066400000000000000000000033461310511640000227610ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Runs protoc with the gRPC plugin to generate messages and gRPC stubs.""" from grpc_tools import protoc protoc.main( ( '', '-I../../protos', '--python_out=.', '--grpc_python_out=.', '../../protos/route_guide.proto', ) ) grpc-1.3.2/examples/ruby/000077500000000000000000000000001310511640000152365ustar00rootroot00000000000000grpc-1.3.2/examples/ruby/.gitignore000066400000000000000000000001751310511640000172310ustar00rootroot00000000000000/.bundle/ /.yardoc /Gemfile.lock /_yardoc/ /coverage/ /doc/ /pkg/ /spec/reports/ /tmp/ *.bundle *.so *.o *.a mkmf.log vendor grpc-1.3.2/examples/ruby/Gemfile000066400000000000000000000001121310511640000165230ustar00rootroot00000000000000# -*- ruby -*- # encoding: utf-8 source 'https://rubygems.org/' gemspec grpc-1.3.2/examples/ruby/README.md000066400000000000000000000032711310511640000165200ustar00rootroot00000000000000gRPC in 3 minutes (Ruby) ======================== BACKGROUND ------------- For this sample, we've already generated the server and client stubs from [helloworld.proto][] PREREQUISITES ------------- - Ruby 2.x This requires Ruby 2.x, as the gRPC API surface uses keyword args. If you don't have that installed locally, you can use [RVM][] to use Ruby 2.x for testing without upgrading the version of Ruby on your whole system. RVM is also useful if you don't have the necessary privileges to update your system's Ruby. ```sh $ # RVM installation as specified at https://rvm.io/rvm/install $ gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 $ \curl -sSL https://get.rvm.io | bash -s stable --ruby=ruby-2 $ $ # follow the instructions to ensure that your're using the latest stable version of Ruby $ # and that the rvm command is installed ``` - *N.B* Make sure your run `source $HOME/.rvm/scripts/rvm` as instructed to complete the set-up of RVM. INSTALL ------- - [Install gRPC Ruby][] - Use bundler to install the example package's dependencies ```sh $ # from this directory $ gem install bundler # if you don't already have bundler available $ bundle install ``` Try it! ------- - Run the server ```sh $ # from this directory $ bundle exec ./greeter_server.rb & ``` - Run the client ```sh $ # from this directory $ bundle exec ./greeter_client.rb ``` Tutorial -------- You can find a more detailed tutorial in [gRPC Basics: Ruby][] [helloworld.proto]:../protos/helloworld.proto [RVM]:https://www.rvm.io/ [Install gRPC ruby]:../../src/ruby#installation [gRPC Basics: Ruby]:http://www.grpc.io/docs/tutorials/basic/ruby.html grpc-1.3.2/examples/ruby/errors_and_cancellation/000077500000000000000000000000001310511640000221105ustar00rootroot00000000000000grpc-1.3.2/examples/ruby/errors_and_cancellation/README.md000066400000000000000000000011211310511640000233620ustar00rootroot00000000000000#Errors and Cancelletion code samples for grpc-ruby The examples in this directory show use of grpc errors. On the server side, errors are returned from service implementations by raising a certain `GRPC::BadStatus` exception. On the client side, GRPC errors get raised when either: * the call completes (unary and client-streaming call types) * the response `Enumerable` is iterated through (server-streaming and bidi call types). ## To run the examples here: Start the server: ``` > ruby error_examples_server.rb ``` Then run the client: ``` > ruby error_examples_client.rb ``` grpc-1.3.2/examples/ruby/errors_and_cancellation/error_examples_client.rb000077500000000000000000000070561310511640000270350ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Sample app that connects to an error-throwing implementation of # Route Guide service. # # Usage: $ path/to/route_guide_client.rb this_dir = File.expand_path(File.dirname(__FILE__)) lib_dir = File.join(File.dirname(this_dir), 'lib') $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) require 'grpc' require 'route_guide_services_pb' include Routeguide def run_get_feature_expect_error(stub) resp = stub.get_feature(Point.new) end def run_list_features_expect_error(stub) resps = stub.list_features(Rectangle.new) # NOOP iteration to pick up error resps.each { } end def run_record_route_expect_error(stub) stub.record_route([]) end def run_route_chat_expect_error(stub) resps = stub.route_chat([]) # NOOP iteration to pick up error resps.each { } end def main stub = RouteGuide::Stub.new('localhost:50051', :this_channel_is_insecure) begin run_get_feature_expect_error(stub) rescue GRPC::BadStatus => e puts "===== GetFeature exception: =====" puts e.inspect puts "e.code: #{e.code}" puts "e.details: #{e.details}" puts "e.metadata: #{e.metadata}" puts "=================================" end begin run_list_features_expect_error(stub) rescue GRPC::BadStatus => e error = true puts "===== ListFeatures exception: =====" puts e.inspect puts "e.code: #{e.code}" puts "e.details: #{e.details}" puts "e.metadata: #{e.metadata}" puts "=================================" end begin run_route_chat_expect_error(stub) rescue GRPC::BadStatus => e puts "==== RouteChat exception: ====" puts e.inspect puts "e.code: #{e.code}" puts "e.details: #{e.details}" puts "e.metadata: #{e.metadata}" puts "=================================" end begin run_record_route_expect_error(stub) rescue GRPC::BadStatus => e puts "==== RecordRoute exception: ====" puts e.inspect puts "e.code: #{e.code}" puts "e.details: #{e.details}" puts "e.metadata: #{e.metadata}" puts "=================================" end end main grpc-1.3.2/examples/ruby/errors_and_cancellation/error_examples_server.rb000077500000000000000000000055051310511640000270620ustar00rootroot00000000000000#!/usr/bin/env ruby # -*- coding: utf-8 -*- # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Error-throwing implementation of Route Guide service. # # Usage: $ path/to/route_guide_server.rb this_dir = File.expand_path(File.dirname(__FILE__)) lib_dir = File.join(File.dirname(this_dir), 'lib') $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) require 'grpc' require 'route_guide_services_pb' include Routeguide include GRPC::Core::StatusCodes # CanellingandErrorReturningServiceImpl provides an implementation of the RouteGuide service. class CancellingAndErrorReturningServerImpl < RouteGuide::Service # def get_feature # Note get_feature isn't implemented in this subclass, so the server # will get a gRPC UNIMPLEMENTED error when it's called. def list_features(rectangle, _call) raise "string appears on the client in the 'details' field of a 'GRPC::Unknown' exception" end def record_route(call) raise GRPC::BadStatus.new_status_exception(CANCELLED) end def route_chat(notes) raise GRPC::BadStatus.new_status_exception(ABORTED, details = 'arbitrary', metadata = {somekey: 'val'}) end end def main port = '0.0.0.0:50051' s = GRPC::RpcServer.new s.add_http2_port(port, :this_port_is_insecure) GRPC.logger.info("... running insecurely on #{port}") s.handle(CancellingAndErrorReturningServerImpl.new) s.run_till_terminated end main grpc-1.3.2/examples/ruby/greeter_client.rb000077500000000000000000000040561310511640000205660ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Sample app that connects to a Greeter service. # # Usage: $ path/to/greeter_client.rb this_dir = File.expand_path(File.dirname(__FILE__)) lib_dir = File.join(this_dir, 'lib') $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) require 'grpc' require 'helloworld_services_pb' def main stub = Helloworld::Greeter::Stub.new('localhost:50051', :this_channel_is_insecure) user = ARGV.size > 0 ? ARGV[0] : 'world' message = stub.say_hello(Helloworld::HelloRequest.new(name: user)).message p "Greeting: #{message}" end main grpc-1.3.2/examples/ruby/greeter_server.rb000077500000000000000000000045561310511640000206230ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Sample gRPC server that implements the Greeter::Helloworld service. # # Usage: $ path/to/greeter_server.rb this_dir = File.expand_path(File.dirname(__FILE__)) lib_dir = File.join(this_dir, 'lib') $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) require 'grpc' require 'helloworld_services_pb' # GreeterServer is simple server that implements the Helloworld Greeter server. class GreeterServer < Helloworld::Greeter::Service # say_hello implements the SayHello rpc method. def say_hello(hello_req, _unused_call) Helloworld::HelloReply.new(message: "Hello #{hello_req.name}") end end # main starts an RpcServer that receives requests to GreeterServer at the sample # server port. def main s = GRPC::RpcServer.new s.add_http2_port('0.0.0.0:50051', :this_port_is_insecure) s.handle(GreeterServer) s.run_till_terminated end main grpc-1.3.2/examples/ruby/grpc-demo.gemspec000066400000000000000000000013011310511640000204530ustar00rootroot00000000000000# -*- ruby -*- # encoding: utf-8 Gem::Specification.new do |s| s.name = 'grpc-demo' s.version = '1.0.0' s.authors = ['gRPC Authors'] s.email = 'temiola@google.com' s.homepage = 'https://github.com/grpc/grpc' s.summary = 'gRPC Ruby overview sample' s.description = 'Simple demo of using gRPC from Ruby' s.files = `git ls-files -- ruby/*`.split("\n") s.executables = `git ls-files -- ruby/greeter*.rb ruby/route_guide/*.rb`.split("\n").map do |f| File.basename(f) end s.require_paths = ['lib'] s.platform = Gem::Platform::RUBY s.add_dependency 'grpc', '~> 1.0' s.add_development_dependency 'bundler', '~> 1.7' end grpc-1.3.2/examples/ruby/lib/000077500000000000000000000000001310511640000160045ustar00rootroot00000000000000grpc-1.3.2/examples/ruby/lib/helloworld_pb.rb000066400000000000000000000010731310511640000211660ustar00rootroot00000000000000# Generated by the protocol buffer compiler. DO NOT EDIT! # source: helloworld.proto require 'google/protobuf' Google::Protobuf::DescriptorPool.generated_pool.build do add_message "helloworld.HelloRequest" do optional :name, :string, 1 end add_message "helloworld.HelloReply" do optional :message, :string, 1 end end module Helloworld HelloRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("helloworld.HelloRequest").msgclass HelloReply = Google::Protobuf::DescriptorPool.generated_pool.lookup("helloworld.HelloReply").msgclass end grpc-1.3.2/examples/ruby/lib/helloworld_services_pb.rb000066400000000000000000000040571310511640000230760ustar00rootroot00000000000000# Generated by the protocol buffer compiler. DO NOT EDIT! # Source: helloworld.proto for package 'helloworld' # Original file comments: # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # require 'grpc' require 'helloworld_pb' module Helloworld module Greeter # The greeting service definition. class Service include GRPC::GenericService self.marshal_class_method = :encode self.unmarshal_class_method = :decode self.service_name = 'helloworld.Greeter' # Sends a greeting rpc :SayHello, HelloRequest, HelloReply end Stub = Service.rpc_stub_class end end grpc-1.3.2/examples/ruby/lib/route_guide_pb.rb000066400000000000000000000026201310511640000213250ustar00rootroot00000000000000# Generated by the protocol buffer compiler. DO NOT EDIT! # source: route_guide.proto require 'google/protobuf' Google::Protobuf::DescriptorPool.generated_pool.build do add_message "routeguide.Point" do optional :latitude, :int32, 1 optional :longitude, :int32, 2 end add_message "routeguide.Rectangle" do optional :lo, :message, 1, "routeguide.Point" optional :hi, :message, 2, "routeguide.Point" end add_message "routeguide.Feature" do optional :name, :string, 1 optional :location, :message, 2, "routeguide.Point" end add_message "routeguide.RouteNote" do optional :location, :message, 1, "routeguide.Point" optional :message, :string, 2 end add_message "routeguide.RouteSummary" do optional :point_count, :int32, 1 optional :feature_count, :int32, 2 optional :distance, :int32, 3 optional :elapsed_time, :int32, 4 end end module Routeguide Point = Google::Protobuf::DescriptorPool.generated_pool.lookup("routeguide.Point").msgclass Rectangle = Google::Protobuf::DescriptorPool.generated_pool.lookup("routeguide.Rectangle").msgclass Feature = Google::Protobuf::DescriptorPool.generated_pool.lookup("routeguide.Feature").msgclass RouteNote = Google::Protobuf::DescriptorPool.generated_pool.lookup("routeguide.RouteNote").msgclass RouteSummary = Google::Protobuf::DescriptorPool.generated_pool.lookup("routeguide.RouteSummary").msgclass end grpc-1.3.2/examples/ruby/lib/route_guide_services_pb.rb000066400000000000000000000060501310511640000232310ustar00rootroot00000000000000# Generated by the protocol buffer compiler. DO NOT EDIT! # Source: route_guide.proto for package 'routeguide' # Original file comments: # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # require 'grpc' require 'route_guide_pb' module Routeguide module RouteGuide # Interface exported by the server. class Service include GRPC::GenericService self.marshal_class_method = :encode self.unmarshal_class_method = :decode self.service_name = 'routeguide.RouteGuide' # A simple RPC. # # Obtains the feature at a given position. # # A feature with an empty name is returned if there's no feature at the given # position. rpc :GetFeature, Point, Feature # A server-to-client streaming RPC. # # Obtains the Features available within the given Rectangle. Results are # streamed rather than returned at once (e.g. in a response message with a # repeated field), as the rectangle may cover a large area and contain a # huge number of features. rpc :ListFeatures, Rectangle, stream(Feature) # A client-to-server streaming RPC. # # Accepts a stream of Points on a route being traversed, returning a # RouteSummary when traversal is completed. rpc :RecordRoute, stream(Point), RouteSummary # A Bidirectional streaming RPC. # # Accepts a stream of RouteNotes sent while a route is being traversed, # while receiving other RouteNotes (e.g. from other users). rpc :RouteChat, stream(RouteNote), stream(RouteNote) end Stub = Service.rpc_stub_class end end grpc-1.3.2/examples/ruby/route_guide/000077500000000000000000000000001310511640000175515ustar00rootroot00000000000000grpc-1.3.2/examples/ruby/route_guide/README.md000066400000000000000000000003331310511640000210270ustar00rootroot00000000000000#gRPC Basics: Ruby sample code The files in this folder are the samples used in [gRPC Basics: Ruby][], a detailed tutorial for using gRPC in Ruby. [gRPC Basics: Ruby]:http://www.grpc.io/docs/tutorials/basic/ruby.html grpc-1.3.2/examples/ruby/route_guide/route_guide_client.rb000077500000000000000000000131171310511640000237550ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Sample app that connects to a Route Guide service. # # Usage: $ path/to/route_guide_client.rb path/to/route_guide_db.json & this_dir = File.expand_path(File.dirname(__FILE__)) lib_dir = File.join(File.dirname(this_dir), 'lib') $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) require 'grpc' require 'multi_json' require 'route_guide_services_pb' include Routeguide GET_FEATURE_POINTS = [ Point.new(latitude: 409_146_138, longitude: -746_188_906), Point.new(latitude: 0, longitude: 0) ] # runs a GetFeature rpc. # # - once with a point known to be present in the sample route database # - once with a point that is not in the sample database def run_get_feature(stub) p 'GetFeature' p '----------' GET_FEATURE_POINTS.each do |pt| resp = stub.get_feature(pt) if resp.name != '' p "- found '#{resp.name}' at #{pt.inspect}" else p "- found nothing at #{pt.inspect}" end end end LIST_FEATURES_RECT = Rectangle.new( lo: Point.new(latitude: 400_000_000, longitude: -750_000_000), hi: Point.new(latitude: 420_000_000, longitude: -730_000_000)) # runs a ListFeatures rpc. # # - the rectangle to chosen to include most of the known features # in the sample db. def run_list_features(stub) p 'ListFeatures' p '------------' resps = stub.list_features(LIST_FEATURES_RECT) resps.each do |r| p "- found '#{r.name}' at #{r.location.inspect}" end end # RandomRoute provides an Enumerable that yields a random 'route' of points # from a list of Features. class RandomRoute def initialize(features, size) @features = features @size = size end # yields a point, waiting between 0 and 1 seconds between each yield # # @return an Enumerable that yields a random point def each return enum_for(:each) unless block_given? @size.times do json_feature = @features[rand(0..@features.length)] next if json_feature.nil? location = json_feature['location'] pt = Point.new( Hash[location.each_pair.map { |k, v| [k.to_sym, v] }]) p "- next point is #{pt.inspect}" yield pt sleep(rand(0..1)) end end end # runs a RecordRoute rpc. # # - the rectangle to chosen to include most of the known features # in the sample db. def run_record_route(stub, features) p 'RecordRoute' p '-----------' points_on_route = 10 # arbitrary reqs = RandomRoute.new(features, points_on_route) resp = stub.record_route(reqs.each) p "summary: #{resp.inspect}" end ROUTE_CHAT_NOTES = [ RouteNote.new(message: 'doh - a deer', location: Point.new(latitude: 0, longitude: 0)), RouteNote.new(message: 'ray - a drop of golden sun', location: Point.new(latitude: 0, longitude: 1)), RouteNote.new(message: 'me - the name I call myself', location: Point.new(latitude: 1, longitude: 0)), RouteNote.new(message: 'fa - a longer way to run', location: Point.new(latitude: 1, longitude: 1)), RouteNote.new(message: 'soh - with needle and a thread', location: Point.new(latitude: 0, longitude: 1)) ] # runs a RouteChat rpc. # # sends a canned set of route notes and prints out the responses. def run_route_chat(stub) p 'Route Chat' p '----------' sleeping_enumerator = SleepingEnumerator.new(ROUTE_CHAT_NOTES, 1) stub.route_chat(sleeping_enumerator.each_item) { |r| p "received #{r.inspect}" } end # SleepingEnumerator yields through items, and sleeps between each one class SleepingEnumerator def initialize(items, delay) @items = items @delay = delay end def each_item return enum_for(:each_item) unless block_given? @items.each do |item| sleep @delay p "next item to send is #{item.inspect}" yield item end end end def main stub = RouteGuide::Stub.new('localhost:50051', :this_channel_is_insecure) run_get_feature(stub) run_list_features(stub) run_route_chat(stub) if ARGV.length == 0 p 'no feature database; skipping record_route' exit end raw_data = [] File.open(ARGV[0]) do |f| raw_data = MultiJson.load(f.read) end run_record_route(stub, raw_data) end main grpc-1.3.2/examples/ruby/route_guide/route_guide_server.rb000077500000000000000000000143201310511640000240020ustar00rootroot00000000000000#!/usr/bin/env ruby # -*- coding: utf-8 -*- # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Sample app that connects to a Route Guide service. # # Usage: $ path/to/route_guide_server.rb path/to/route_guide_db.json & this_dir = File.expand_path(File.dirname(__FILE__)) lib_dir = File.join(File.dirname(this_dir), 'lib') $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) require 'grpc' require 'multi_json' require 'route_guide_services_pb' include Routeguide COORD_FACTOR = 1e7 RADIUS = 637_100 # Determines the distance between two points. def calculate_distance(point_a, point_b) to_radians = proc { |x| x * Math::PI / 180 } lat_a = point_a.latitude / COORD_FACTOR lat_b = point_b.latitude / COORD_FACTOR long_a = point_a.longitude / COORD_FACTOR long_b = point_b.longitude / COORD_FACTOR φ1 = to_radians.call(lat_a) φ2 = to_radians.call(lat_b) Δφ = to_radians.call(lat_a - lat_b) Δλ = to_radians.call(long_a - long_b) a = Math.sin(Δφ / 2)**2 + Math.cos(φ1) * Math.cos(φ2) + Math.sin(Δλ / 2)**2 (2 * RADIUS * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))).to_i end # RectangleEnum provides an Enumerator of the points in a feature_db within a # given Rectangle. class RectangleEnum # @param [Hash] feature_db # @param [Rectangle] bounds def initialize(feature_db, bounds) @feature_db = feature_db @bounds = bounds lats = [@bounds.lo.latitude, @bounds.hi.latitude] longs = [@bounds.lo.longitude, @bounds.hi.longitude] @lo_lat, @hi_lat = lats.min, lats.max @lo_long, @hi_long = longs.min, longs.max end # in? determines if location lies within the bounds of this instances # Rectangle. def in?(location) location['longitude'] >= @lo_long && location['longitude'] <= @hi_long && location['latitude'] >= @lo_lat && location['latitude'] <= @hi_lat end # each yields the features in the instances feature_db that lie within the # instance rectangle. def each return enum_for(:each) unless block_given? @feature_db.each_pair do |location, name| next unless in?(location) next if name.nil? || name == '' pt = Point.new( Hash[location.each_pair.map { |k, v| [k.to_sym, v] }]) yield Feature.new(location: pt, name: name) end end end # ServerImpl provides an implementation of the RouteGuide service. class ServerImpl < RouteGuide::Service # @param [Hash] feature_db {location => name} def initialize(feature_db) @feature_db = feature_db @received_notes = Hash.new { |h, k| h[k] = [] } end def get_feature(point, _call) name = @feature_db[{ 'longitude' => point.longitude, 'latitude' => point.latitude }] || '' Feature.new(location: point, name: name) end def list_features(rectangle, _call) RectangleEnum.new(@feature_db, rectangle).each end def record_route(call) started, elapsed_time = 0, 0 distance, count, features, last = 0, 0, 0, nil call.each_remote_read do |point| count += 1 name = @feature_db[{ 'longitude' => point.longitude, 'latitude' => point.latitude }] || '' features += 1 unless name == '' if last.nil? last = point started = Time.now.to_i next end elapsed_time = Time.now.to_i - started distance += calculate_distance(point, last) last = point end RouteSummary.new(point_count: count, feature_count: features, distance: distance, elapsed_time: elapsed_time) end def route_chat(notes) RouteChatEnumerator.new(notes, @received_notes).each_item end end class RouteChatEnumerator def initialize(notes, received_notes) @notes = notes @received_notes = received_notes end def each_item return enum_for(:each_item) unless block_given? begin @notes.each do |n| key = { 'latitude' => n.location.latitude, 'longitude' => n.location.longitude } earlier_msgs = @received_notes[key] @received_notes[key] << n.message # send back the earlier messages at this point earlier_msgs.each do |r| yield RouteNote.new(location: n.location, message: r) end end rescue StandardError => e fail e # signal completion via an error end end end def main if ARGV.length == 0 fail 'Please specify the path to the route_guide json database' end raw_data = [] File.open(ARGV[0]) do |f| raw_data = MultiJson.load(f.read) end feature_db = Hash[raw_data.map { |x| [x['location'], x['name']] }] port = '0.0.0.0:50051' s = GRPC::RpcServer.new s.add_http2_port(port, :this_port_is_insecure) GRPC.logger.info("... running insecurely on #{port}") s.handle(ServerImpl.new(feature_db)) s.run_till_terminated end main grpc-1.3.2/examples/ruby/without_protobuf/000077500000000000000000000000001310511640000206615ustar00rootroot00000000000000grpc-1.3.2/examples/ruby/without_protobuf/README.md000066400000000000000000000003201310511640000221330ustar00rootroot00000000000000gRPC (Ruby) without protobuf ======================== This directory contains a simple example of using gRPC without protobuf. This is mainly intended to show basic usage of the GRPC::GenericService module grpc-1.3.2/examples/ruby/without_protobuf/echo_client.rb000077500000000000000000000037611310511640000234740ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Sample app that connects to a 'EchoWithoutProtobuf' service. # # Usage: $ path/to/echo_client.rb this_dir = File.expand_path(File.dirname(__FILE__)) $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir) require 'grpc' require 'echo_services_noprotobuf' def main stub = EchoWithoutProtobuf::Stub.new('localhost:50051', :this_channel_is_insecure) user = ARGV.size > 0 ? ARGV[0] : 'world' message = stub.echo("hello #{user}") p "Reponse: #{message}" end main grpc-1.3.2/examples/ruby/without_protobuf/echo_server.rb000077500000000000000000000044311310511640000235170ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Sample gRPC server that implements the EchoWithoutProtobuf service. # # Usage: $ path/to/echo_server.rb this_dir = File.expand_path(File.dirname(__FILE__)) $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir) require 'grpc' require 'echo_services_noprotobuf' # EchoServer is simple server that implements the EchoWithoutProtobuf server. class EchoServer < EchoWithoutProtobuf::Service # echo implements the EchoWithoutProtobuf 'Echo' rpc method. def echo(echo_req, _unused_call) echo_req end end # main starts an RpcServer that receives requests to EchoWithoutProtobuf at the sample # server port. def main s = GRPC::RpcServer.new s.add_http2_port('0.0.0.0:50051', :this_port_is_insecure) s.handle(EchoServer) s.run_till_terminated end main grpc-1.3.2/examples/ruby/without_protobuf/echo_services_noprotobuf.rb000066400000000000000000000036501310511640000263100ustar00rootroot00000000000000# Original file comments: # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # require 'grpc' module EchoWithoutProtobuf # The 'echo without protobuf' service definition. class Service include GRPC::GenericService self.marshal_class_method = :try_convert self.unmarshal_class_method = :try_convert self.service_name = 'EchoWithoutProtobuf' # Request and response are plain strings rpc :Echo, String, String end Stub = Service.rpc_stub_class end grpc-1.3.2/gRPC-Core.podspec000066400000000000000000001701501310511640000155030ustar00rootroot00000000000000# This file has been automatically generated from a template file. # Please make modifications to `templates/gRPC-Core.podspec.template` # instead. This file can be regenerated from the template by running # `tools/buildgen/generate_projects.sh`. # gRPC Core CocoaPods podspec # # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Pod::Spec.new do |s| s.name = 'gRPC-Core' version = '1.3.2' s.version = version s.summary = 'Core cross-platform gRPC library, written in C' s.homepage = 'http://www.grpc.io' s.license = 'New BSD' s.authors = { 'The gRPC contributors' => 'grpc-packages@google.com' } s.source = { :git => 'https://github.com/grpc/grpc.git', :tag => "v#{version}", # TODO(jcanizales): Depend explicitly on the nanopb pod, and disable submodules. :submodules => true, } s.ios.deployment_target = '7.0' s.osx.deployment_target = '10.9' s.requires_arc = false name = 'grpc' # When creating a dynamic framework, name it grpc.framework instead of gRPC-Core.framework. # This lets users write their includes like `#include ` as opposed to `#include # `. s.module_name = name # When creating a dynamic framework, copy the headers under `include/grpc/` into the root of # the `Headers/` directory of the framework (i.e., not under `Headers/include/grpc`). # # TODO(jcanizales): Debug why this doesn't work on macOS. s.header_mappings_dir = 'include/grpc' # The above has an undesired effect when creating a static library: It forces users to write # includes like `#include `. `s.header_dir` adds a path prefix to that, and # because Cocoapods lets omit the pod name when including headers of static libraries, the # following lets users write `#include `. s.header_dir = name # The module map created automatically by Cocoapods doesn't work for C libraries like gRPC-Core. s.module_map = 'include/grpc/module.modulemap' # To compile the library, we need the user headers search path (quoted includes) to point to the # root of the repo, and the system headers search path (angled includes) to point to `include/`. # Cocoapods effectively clones the repo under `/Pods/gRPC-Core/`, and sets a build # variable called `$(PODS_ROOT)` to `/Pods/`, so we use that. # # Relying on the file structure under $(PODS_ROOT) isn't officially supported in Cocoapods, as it # is taken as an implementation detail. We've asked for an alternative, and have been told that # what we're doing should keep working: https://github.com/CocoaPods/CocoaPods/issues/4386 # # The `src_root` value of `$(PODS_ROOT)/gRPC-Core` assumes Cocoapods is installing this pod from # its remote repo. For local development of this library, enabled by using `:path` in the Podfile, # that assumption is wrong. In such case, the following settings need to be reset with the # appropriate value of `src_root`. This can be accomplished in the `pre_install` hook of the # Podfile; see `src/objective-c/tests/Podfile` for an example. src_root = '$(PODS_ROOT)/gRPC-Core' s.pod_target_xcconfig = { 'GRPC_SRC_ROOT' => src_root, 'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"', 'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"', # If we don't set these two settings, `include/grpc/support/time.h` and # `src/core/lib/support/string.h` shadow the system `` and ``, breaking the # build. 'USE_HEADERMAP' => 'NO', 'ALWAYS_SEARCH_USER_PATHS' => 'NO', } s.default_subspecs = 'Interface', 'Implementation' s.compiler_flags = '-DGRPC_ARES=0' # Like many other C libraries, gRPC-Core has its public headers under `include//` and its # sources and private headers in other directories outside `include/`. Cocoapods' linter doesn't # allow any header to be listed outside the `header_mappings_dir` (even though doing so works in # practice). Because we need our `header_mappings_dir` to be `include/grpc/` for the reason # mentioned above, we work around the linter limitation by dividing the pod into two subspecs, one # for public headers and the other for implementation. Each gets its own `header_mappings_dir`, # making the linter happy. # # The list of source files is generated by a template: `templates/gRPC-Core.podspec.template`. It # can be regenerated from the template by running `tools/buildgen/generate_projects.sh`. s.subspec 'Interface' do |ss| ss.header_mappings_dir = 'include/grpc' ss.source_files = 'include/grpc/support/alloc.h', 'include/grpc/support/atm.h', 'include/grpc/support/atm_gcc_atomic.h', 'include/grpc/support/atm_gcc_sync.h', 'include/grpc/support/atm_windows.h', 'include/grpc/support/avl.h', 'include/grpc/support/cmdline.h', 'include/grpc/support/cpu.h', 'include/grpc/support/histogram.h', 'include/grpc/support/host_port.h', 'include/grpc/support/log.h', 'include/grpc/support/log_windows.h', 'include/grpc/support/port_platform.h', 'include/grpc/support/string_util.h', 'include/grpc/support/subprocess.h', 'include/grpc/support/sync.h', 'include/grpc/support/sync_generic.h', 'include/grpc/support/sync_posix.h', 'include/grpc/support/sync_windows.h', 'include/grpc/support/thd.h', 'include/grpc/support/time.h', 'include/grpc/support/tls.h', 'include/grpc/support/tls_gcc.h', 'include/grpc/support/tls_msvc.h', 'include/grpc/support/tls_pthread.h', 'include/grpc/support/useful.h', 'include/grpc/impl/codegen/atm.h', 'include/grpc/impl/codegen/atm_gcc_atomic.h', 'include/grpc/impl/codegen/atm_gcc_sync.h', 'include/grpc/impl/codegen/atm_windows.h', 'include/grpc/impl/codegen/gpr_slice.h', 'include/grpc/impl/codegen/gpr_types.h', 'include/grpc/impl/codegen/port_platform.h', 'include/grpc/impl/codegen/sync.h', 'include/grpc/impl/codegen/sync_generic.h', 'include/grpc/impl/codegen/sync_posix.h', 'include/grpc/impl/codegen/sync_windows.h', 'include/grpc/byte_buffer.h', 'include/grpc/byte_buffer_reader.h', 'include/grpc/compression.h', 'include/grpc/grpc.h', 'include/grpc/grpc_posix.h', 'include/grpc/grpc_security_constants.h', 'include/grpc/load_reporting.h', 'include/grpc/slice.h', 'include/grpc/slice_buffer.h', 'include/grpc/status.h', 'include/grpc/impl/codegen/byte_buffer_reader.h', 'include/grpc/impl/codegen/compression_types.h', 'include/grpc/impl/codegen/connectivity_state.h', 'include/grpc/impl/codegen/exec_ctx_fwd.h', 'include/grpc/impl/codegen/grpc_types.h', 'include/grpc/impl/codegen/propagation_bits.h', 'include/grpc/impl/codegen/slice.h', 'include/grpc/impl/codegen/status.h', 'include/grpc/impl/codegen/atm.h', 'include/grpc/impl/codegen/atm_gcc_atomic.h', 'include/grpc/impl/codegen/atm_gcc_sync.h', 'include/grpc/impl/codegen/atm_windows.h', 'include/grpc/impl/codegen/gpr_slice.h', 'include/grpc/impl/codegen/gpr_types.h', 'include/grpc/impl/codegen/port_platform.h', 'include/grpc/impl/codegen/sync.h', 'include/grpc/impl/codegen/sync_generic.h', 'include/grpc/impl/codegen/sync_posix.h', 'include/grpc/impl/codegen/sync_windows.h', 'include/grpc/grpc_security.h', 'include/grpc/census.h' end s.subspec 'Implementation' do |ss| ss.header_mappings_dir = '.' ss.libraries = 'z' ss.dependency "#{s.name}/Interface", version ss.dependency 'BoringSSL', '~> 8.0' # To save you from scrolling, this is the last part of the podspec. ss.source_files = 'src/core/lib/profiling/timers.h', 'src/core/lib/support/arena.h', 'src/core/lib/support/backoff.h', 'src/core/lib/support/block_annotate.h', 'src/core/lib/support/env.h', 'src/core/lib/support/mpscq.h', 'src/core/lib/support/murmur_hash.h', 'src/core/lib/support/spinlock.h', 'src/core/lib/support/stack_lockfree.h', 'src/core/lib/support/string.h', 'src/core/lib/support/string_windows.h', 'src/core/lib/support/thd_internal.h', 'src/core/lib/support/time_precise.h', 'src/core/lib/support/tmpfile.h', 'src/core/lib/profiling/basic_timers.c', 'src/core/lib/profiling/stap_timers.c', 'src/core/lib/support/alloc.c', 'src/core/lib/support/arena.c', 'src/core/lib/support/atm.c', 'src/core/lib/support/avl.c', 'src/core/lib/support/backoff.c', 'src/core/lib/support/cmdline.c', 'src/core/lib/support/cpu_iphone.c', 'src/core/lib/support/cpu_linux.c', 'src/core/lib/support/cpu_posix.c', 'src/core/lib/support/cpu_windows.c', 'src/core/lib/support/env_linux.c', 'src/core/lib/support/env_posix.c', 'src/core/lib/support/env_windows.c', 'src/core/lib/support/histogram.c', 'src/core/lib/support/host_port.c', 'src/core/lib/support/log.c', 'src/core/lib/support/log_android.c', 'src/core/lib/support/log_linux.c', 'src/core/lib/support/log_posix.c', 'src/core/lib/support/log_windows.c', 'src/core/lib/support/mpscq.c', 'src/core/lib/support/murmur_hash.c', 'src/core/lib/support/stack_lockfree.c', 'src/core/lib/support/string.c', 'src/core/lib/support/string_posix.c', 'src/core/lib/support/string_util_windows.c', 'src/core/lib/support/string_windows.c', 'src/core/lib/support/subprocess_posix.c', 'src/core/lib/support/subprocess_windows.c', 'src/core/lib/support/sync.c', 'src/core/lib/support/sync_posix.c', 'src/core/lib/support/sync_windows.c', 'src/core/lib/support/thd.c', 'src/core/lib/support/thd_posix.c', 'src/core/lib/support/thd_windows.c', 'src/core/lib/support/time.c', 'src/core/lib/support/time_posix.c', 'src/core/lib/support/time_precise.c', 'src/core/lib/support/time_windows.c', 'src/core/lib/support/tls_pthread.c', 'src/core/lib/support/tmpfile_msys.c', 'src/core/lib/support/tmpfile_posix.c', 'src/core/lib/support/tmpfile_windows.c', 'src/core/lib/support/wrap_memcpy.c', 'src/core/lib/channel/channel_args.h', 'src/core/lib/channel/channel_stack.h', 'src/core/lib/channel/channel_stack_builder.h', 'src/core/lib/channel/compress_filter.h', 'src/core/lib/channel/connected_channel.h', 'src/core/lib/channel/context.h', 'src/core/lib/channel/deadline_filter.h', 'src/core/lib/channel/handshaker.h', 'src/core/lib/channel/handshaker_factory.h', 'src/core/lib/channel/handshaker_registry.h', 'src/core/lib/channel/http_client_filter.h', 'src/core/lib/channel/http_server_filter.h', 'src/core/lib/channel/message_size_filter.h', 'src/core/lib/compression/algorithm_metadata.h', 'src/core/lib/compression/message_compress.h', 'src/core/lib/debug/trace.h', 'src/core/lib/http/format_request.h', 'src/core/lib/http/httpcli.h', 'src/core/lib/http/parser.h', 'src/core/lib/iomgr/closure.h', 'src/core/lib/iomgr/combiner.h', 'src/core/lib/iomgr/endpoint.h', 'src/core/lib/iomgr/endpoint_pair.h', 'src/core/lib/iomgr/error.h', 'src/core/lib/iomgr/error_internal.h', 'src/core/lib/iomgr/ev_epoll_linux.h', 'src/core/lib/iomgr/ev_poll_posix.h', 'src/core/lib/iomgr/ev_posix.h', 'src/core/lib/iomgr/exec_ctx.h', 'src/core/lib/iomgr/executor.h', 'src/core/lib/iomgr/iocp_windows.h', 'src/core/lib/iomgr/iomgr.h', 'src/core/lib/iomgr/iomgr_internal.h', 'src/core/lib/iomgr/iomgr_posix.h', 'src/core/lib/iomgr/load_file.h', 'src/core/lib/iomgr/lockfree_event.h', 'src/core/lib/iomgr/network_status_tracker.h', 'src/core/lib/iomgr/polling_entity.h', 'src/core/lib/iomgr/pollset.h', 'src/core/lib/iomgr/pollset_set.h', 'src/core/lib/iomgr/pollset_set_windows.h', 'src/core/lib/iomgr/pollset_uv.h', 'src/core/lib/iomgr/pollset_windows.h', 'src/core/lib/iomgr/port.h', 'src/core/lib/iomgr/resolve_address.h', 'src/core/lib/iomgr/resource_quota.h', 'src/core/lib/iomgr/sockaddr.h', 'src/core/lib/iomgr/sockaddr_posix.h', 'src/core/lib/iomgr/sockaddr_utils.h', 'src/core/lib/iomgr/sockaddr_windows.h', 'src/core/lib/iomgr/socket_factory_posix.h', 'src/core/lib/iomgr/socket_mutator.h', 'src/core/lib/iomgr/socket_utils.h', 'src/core/lib/iomgr/socket_utils_posix.h', 'src/core/lib/iomgr/socket_windows.h', 'src/core/lib/iomgr/tcp_client.h', 'src/core/lib/iomgr/tcp_client_posix.h', 'src/core/lib/iomgr/tcp_posix.h', 'src/core/lib/iomgr/tcp_server.h', 'src/core/lib/iomgr/tcp_server_utils_posix.h', 'src/core/lib/iomgr/tcp_uv.h', 'src/core/lib/iomgr/tcp_windows.h', 'src/core/lib/iomgr/time_averaged_stats.h', 'src/core/lib/iomgr/timer.h', 'src/core/lib/iomgr/timer_generic.h', 'src/core/lib/iomgr/timer_heap.h', 'src/core/lib/iomgr/timer_uv.h', 'src/core/lib/iomgr/udp_server.h', 'src/core/lib/iomgr/unix_sockets_posix.h', 'src/core/lib/iomgr/wakeup_fd_cv.h', 'src/core/lib/iomgr/wakeup_fd_pipe.h', 'src/core/lib/iomgr/wakeup_fd_posix.h', 'src/core/lib/iomgr/workqueue.h', 'src/core/lib/iomgr/workqueue_uv.h', 'src/core/lib/iomgr/workqueue_windows.h', 'src/core/lib/json/json.h', 'src/core/lib/json/json_common.h', 'src/core/lib/json/json_reader.h', 'src/core/lib/json/json_writer.h', 'src/core/lib/slice/b64.h', 'src/core/lib/slice/percent_encoding.h', 'src/core/lib/slice/slice_hash_table.h', 'src/core/lib/slice/slice_internal.h', 'src/core/lib/slice/slice_string_helpers.h', 'src/core/lib/surface/api_trace.h', 'src/core/lib/surface/call.h', 'src/core/lib/surface/call_test_only.h', 'src/core/lib/surface/channel.h', 'src/core/lib/surface/channel_init.h', 'src/core/lib/surface/channel_stack_type.h', 'src/core/lib/surface/completion_queue.h', 'src/core/lib/surface/completion_queue_factory.h', 'src/core/lib/surface/event_string.h', 'src/core/lib/surface/init.h', 'src/core/lib/surface/lame_client.h', 'src/core/lib/surface/server.h', 'src/core/lib/surface/validate_metadata.h', 'src/core/lib/transport/bdp_estimator.h', 'src/core/lib/transport/byte_stream.h', 'src/core/lib/transport/connectivity_state.h', 'src/core/lib/transport/error_utils.h', 'src/core/lib/transport/http2_errors.h', 'src/core/lib/transport/metadata.h', 'src/core/lib/transport/metadata_batch.h', 'src/core/lib/transport/pid_controller.h', 'src/core/lib/transport/service_config.h', 'src/core/lib/transport/static_metadata.h', 'src/core/lib/transport/status_conversion.h', 'src/core/lib/transport/timeout_encoding.h', 'src/core/lib/transport/transport.h', 'src/core/lib/transport/transport_impl.h', 'src/core/ext/transport/chttp2/transport/bin_decoder.h', 'src/core/ext/transport/chttp2/transport/bin_encoder.h', 'src/core/ext/transport/chttp2/transport/chttp2_transport.h', 'src/core/ext/transport/chttp2/transport/frame.h', 'src/core/ext/transport/chttp2/transport/frame_data.h', 'src/core/ext/transport/chttp2/transport/frame_goaway.h', 'src/core/ext/transport/chttp2/transport/frame_ping.h', 'src/core/ext/transport/chttp2/transport/frame_rst_stream.h', 'src/core/ext/transport/chttp2/transport/frame_settings.h', 'src/core/ext/transport/chttp2/transport/frame_window_update.h', 'src/core/ext/transport/chttp2/transport/hpack_encoder.h', 'src/core/ext/transport/chttp2/transport/hpack_parser.h', 'src/core/ext/transport/chttp2/transport/hpack_table.h', 'src/core/ext/transport/chttp2/transport/http2_settings.h', 'src/core/ext/transport/chttp2/transport/huffsyms.h', 'src/core/ext/transport/chttp2/transport/incoming_metadata.h', 'src/core/ext/transport/chttp2/transport/internal.h', 'src/core/ext/transport/chttp2/transport/stream_map.h', 'src/core/ext/transport/chttp2/transport/varint.h', 'src/core/ext/transport/chttp2/alpn/alpn.h', 'src/core/lib/security/context/security_context.h', 'src/core/lib/security/credentials/composite/composite_credentials.h', 'src/core/lib/security/credentials/credentials.h', 'src/core/lib/security/credentials/fake/fake_credentials.h', 'src/core/lib/security/credentials/google_default/google_default_credentials.h', 'src/core/lib/security/credentials/iam/iam_credentials.h', 'src/core/lib/security/credentials/jwt/json_token.h', 'src/core/lib/security/credentials/jwt/jwt_credentials.h', 'src/core/lib/security/credentials/jwt/jwt_verifier.h', 'src/core/lib/security/credentials/oauth2/oauth2_credentials.h', 'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h', 'src/core/lib/security/transport/auth_filters.h', 'src/core/lib/security/transport/lb_targets_info.h', 'src/core/lib/security/transport/secure_endpoint.h', 'src/core/lib/security/transport/security_connector.h', 'src/core/lib/security/transport/security_handshaker.h', 'src/core/lib/security/transport/tsi_error.h', 'src/core/lib/security/util/json_util.h', 'src/core/tsi/fake_transport_security.h', 'src/core/tsi/ssl_transport_security.h', 'src/core/tsi/ssl_types.h', 'src/core/tsi/transport_security.h', 'src/core/tsi/transport_security_interface.h', 'src/core/ext/transport/chttp2/server/chttp2_server.h', 'src/core/ext/filters/client_channel/client_channel.h', 'src/core/ext/filters/client_channel/client_channel_factory.h', 'src/core/ext/filters/client_channel/connector.h', 'src/core/ext/filters/client_channel/http_connect_handshaker.h', 'src/core/ext/filters/client_channel/http_proxy.h', 'src/core/ext/filters/client_channel/lb_policy.h', 'src/core/ext/filters/client_channel/lb_policy_factory.h', 'src/core/ext/filters/client_channel/lb_policy_registry.h', 'src/core/ext/filters/client_channel/parse_address.h', 'src/core/ext/filters/client_channel/proxy_mapper.h', 'src/core/ext/filters/client_channel/proxy_mapper_registry.h', 'src/core/ext/filters/client_channel/resolver.h', 'src/core/ext/filters/client_channel/resolver_factory.h', 'src/core/ext/filters/client_channel/resolver_registry.h', 'src/core/ext/filters/client_channel/retry_throttle.h', 'src/core/ext/filters/client_channel/subchannel.h', 'src/core/ext/filters/client_channel/subchannel_index.h', 'src/core/ext/filters/client_channel/uri_parser.h', 'src/core/ext/transport/chttp2/client/chttp2_connector.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h', 'third_party/nanopb/pb.h', 'third_party/nanopb/pb_common.h', 'third_party/nanopb/pb_decode.h', 'third_party/nanopb/pb_encode.h', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h', 'src/core/ext/filters/load_reporting/load_reporting.h', 'src/core/ext/filters/load_reporting/load_reporting_filter.h', 'src/core/ext/census/aggregation.h', 'src/core/ext/census/base_resources.h', 'src/core/ext/census/census_interface.h', 'src/core/ext/census/census_rpc_stats.h', 'src/core/ext/census/gen/census.pb.h', 'src/core/ext/census/gen/trace_context.pb.h', 'src/core/ext/census/grpc_filter.h', 'src/core/ext/census/mlog.h', 'src/core/ext/census/resource.h', 'src/core/ext/census/rpc_metric_id.h', 'src/core/ext/census/trace_context.h', 'src/core/ext/census/trace_label.h', 'src/core/ext/census/trace_propagation.h', 'src/core/ext/census/trace_status.h', 'src/core/ext/census/trace_string.h', 'src/core/ext/census/tracing.h', 'src/core/ext/filters/max_age/max_age_filter.h', 'src/core/lib/surface/init.c', 'src/core/lib/channel/channel_args.c', 'src/core/lib/channel/channel_stack.c', 'src/core/lib/channel/channel_stack_builder.c', 'src/core/lib/channel/compress_filter.c', 'src/core/lib/channel/connected_channel.c', 'src/core/lib/channel/deadline_filter.c', 'src/core/lib/channel/handshaker.c', 'src/core/lib/channel/handshaker_factory.c', 'src/core/lib/channel/handshaker_registry.c', 'src/core/lib/channel/http_client_filter.c', 'src/core/lib/channel/http_server_filter.c', 'src/core/lib/channel/message_size_filter.c', 'src/core/lib/compression/compression.c', 'src/core/lib/compression/message_compress.c', 'src/core/lib/debug/trace.c', 'src/core/lib/http/format_request.c', 'src/core/lib/http/httpcli.c', 'src/core/lib/http/parser.c', 'src/core/lib/iomgr/closure.c', 'src/core/lib/iomgr/combiner.c', 'src/core/lib/iomgr/endpoint.c', 'src/core/lib/iomgr/endpoint_pair_posix.c', 'src/core/lib/iomgr/endpoint_pair_uv.c', 'src/core/lib/iomgr/endpoint_pair_windows.c', 'src/core/lib/iomgr/error.c', 'src/core/lib/iomgr/ev_epoll_linux.c', 'src/core/lib/iomgr/ev_poll_posix.c', 'src/core/lib/iomgr/ev_posix.c', 'src/core/lib/iomgr/exec_ctx.c', 'src/core/lib/iomgr/executor.c', 'src/core/lib/iomgr/iocp_windows.c', 'src/core/lib/iomgr/iomgr.c', 'src/core/lib/iomgr/iomgr_posix.c', 'src/core/lib/iomgr/iomgr_uv.c', 'src/core/lib/iomgr/iomgr_windows.c', 'src/core/lib/iomgr/load_file.c', 'src/core/lib/iomgr/lockfree_event.c', 'src/core/lib/iomgr/network_status_tracker.c', 'src/core/lib/iomgr/polling_entity.c', 'src/core/lib/iomgr/pollset_set_uv.c', 'src/core/lib/iomgr/pollset_set_windows.c', 'src/core/lib/iomgr/pollset_uv.c', 'src/core/lib/iomgr/pollset_windows.c', 'src/core/lib/iomgr/resolve_address_posix.c', 'src/core/lib/iomgr/resolve_address_uv.c', 'src/core/lib/iomgr/resolve_address_windows.c', 'src/core/lib/iomgr/resource_quota.c', 'src/core/lib/iomgr/sockaddr_utils.c', 'src/core/lib/iomgr/socket_factory_posix.c', 'src/core/lib/iomgr/socket_mutator.c', 'src/core/lib/iomgr/socket_utils_common_posix.c', 'src/core/lib/iomgr/socket_utils_linux.c', 'src/core/lib/iomgr/socket_utils_posix.c', 'src/core/lib/iomgr/socket_utils_uv.c', 'src/core/lib/iomgr/socket_utils_windows.c', 'src/core/lib/iomgr/socket_windows.c', 'src/core/lib/iomgr/tcp_client_posix.c', 'src/core/lib/iomgr/tcp_client_uv.c', 'src/core/lib/iomgr/tcp_client_windows.c', 'src/core/lib/iomgr/tcp_posix.c', 'src/core/lib/iomgr/tcp_server_posix.c', 'src/core/lib/iomgr/tcp_server_utils_posix_common.c', 'src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c', 'src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c', 'src/core/lib/iomgr/tcp_server_uv.c', 'src/core/lib/iomgr/tcp_server_windows.c', 'src/core/lib/iomgr/tcp_uv.c', 'src/core/lib/iomgr/tcp_windows.c', 'src/core/lib/iomgr/time_averaged_stats.c', 'src/core/lib/iomgr/timer_generic.c', 'src/core/lib/iomgr/timer_heap.c', 'src/core/lib/iomgr/timer_uv.c', 'src/core/lib/iomgr/udp_server.c', 'src/core/lib/iomgr/unix_sockets_posix.c', 'src/core/lib/iomgr/unix_sockets_posix_noop.c', 'src/core/lib/iomgr/wakeup_fd_cv.c', 'src/core/lib/iomgr/wakeup_fd_eventfd.c', 'src/core/lib/iomgr/wakeup_fd_nospecial.c', 'src/core/lib/iomgr/wakeup_fd_pipe.c', 'src/core/lib/iomgr/wakeup_fd_posix.c', 'src/core/lib/iomgr/workqueue_uv.c', 'src/core/lib/iomgr/workqueue_windows.c', 'src/core/lib/json/json.c', 'src/core/lib/json/json_reader.c', 'src/core/lib/json/json_string.c', 'src/core/lib/json/json_writer.c', 'src/core/lib/slice/b64.c', 'src/core/lib/slice/percent_encoding.c', 'src/core/lib/slice/slice.c', 'src/core/lib/slice/slice_buffer.c', 'src/core/lib/slice/slice_hash_table.c', 'src/core/lib/slice/slice_intern.c', 'src/core/lib/slice/slice_string_helpers.c', 'src/core/lib/surface/alarm.c', 'src/core/lib/surface/api_trace.c', 'src/core/lib/surface/byte_buffer.c', 'src/core/lib/surface/byte_buffer_reader.c', 'src/core/lib/surface/call.c', 'src/core/lib/surface/call_details.c', 'src/core/lib/surface/call_log_batch.c', 'src/core/lib/surface/channel.c', 'src/core/lib/surface/channel_init.c', 'src/core/lib/surface/channel_ping.c', 'src/core/lib/surface/channel_stack_type.c', 'src/core/lib/surface/completion_queue.c', 'src/core/lib/surface/completion_queue_factory.c', 'src/core/lib/surface/event_string.c', 'src/core/lib/surface/lame_client.c', 'src/core/lib/surface/metadata_array.c', 'src/core/lib/surface/server.c', 'src/core/lib/surface/validate_metadata.c', 'src/core/lib/surface/version.c', 'src/core/lib/transport/bdp_estimator.c', 'src/core/lib/transport/byte_stream.c', 'src/core/lib/transport/connectivity_state.c', 'src/core/lib/transport/error_utils.c', 'src/core/lib/transport/metadata.c', 'src/core/lib/transport/metadata_batch.c', 'src/core/lib/transport/pid_controller.c', 'src/core/lib/transport/service_config.c', 'src/core/lib/transport/static_metadata.c', 'src/core/lib/transport/status_conversion.c', 'src/core/lib/transport/timeout_encoding.c', 'src/core/lib/transport/transport.c', 'src/core/lib/transport/transport_op_string.c', 'src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c', 'src/core/ext/transport/chttp2/transport/bin_decoder.c', 'src/core/ext/transport/chttp2/transport/bin_encoder.c', 'src/core/ext/transport/chttp2/transport/chttp2_plugin.c', 'src/core/ext/transport/chttp2/transport/chttp2_transport.c', 'src/core/ext/transport/chttp2/transport/frame_data.c', 'src/core/ext/transport/chttp2/transport/frame_goaway.c', 'src/core/ext/transport/chttp2/transport/frame_ping.c', 'src/core/ext/transport/chttp2/transport/frame_rst_stream.c', 'src/core/ext/transport/chttp2/transport/frame_settings.c', 'src/core/ext/transport/chttp2/transport/frame_window_update.c', 'src/core/ext/transport/chttp2/transport/hpack_encoder.c', 'src/core/ext/transport/chttp2/transport/hpack_parser.c', 'src/core/ext/transport/chttp2/transport/hpack_table.c', 'src/core/ext/transport/chttp2/transport/http2_settings.c', 'src/core/ext/transport/chttp2/transport/huffsyms.c', 'src/core/ext/transport/chttp2/transport/incoming_metadata.c', 'src/core/ext/transport/chttp2/transport/parsing.c', 'src/core/ext/transport/chttp2/transport/stream_lists.c', 'src/core/ext/transport/chttp2/transport/stream_map.c', 'src/core/ext/transport/chttp2/transport/varint.c', 'src/core/ext/transport/chttp2/transport/writing.c', 'src/core/ext/transport/chttp2/alpn/alpn.c', 'src/core/lib/http/httpcli_security_connector.c', 'src/core/lib/security/context/security_context.c', 'src/core/lib/security/credentials/composite/composite_credentials.c', 'src/core/lib/security/credentials/credentials.c', 'src/core/lib/security/credentials/credentials_metadata.c', 'src/core/lib/security/credentials/fake/fake_credentials.c', 'src/core/lib/security/credentials/google_default/credentials_generic.c', 'src/core/lib/security/credentials/google_default/google_default_credentials.c', 'src/core/lib/security/credentials/iam/iam_credentials.c', 'src/core/lib/security/credentials/jwt/json_token.c', 'src/core/lib/security/credentials/jwt/jwt_credentials.c', 'src/core/lib/security/credentials/jwt/jwt_verifier.c', 'src/core/lib/security/credentials/oauth2/oauth2_credentials.c', 'src/core/lib/security/credentials/plugin/plugin_credentials.c', 'src/core/lib/security/credentials/ssl/ssl_credentials.c', 'src/core/lib/security/transport/client_auth_filter.c', 'src/core/lib/security/transport/lb_targets_info.c', 'src/core/lib/security/transport/secure_endpoint.c', 'src/core/lib/security/transport/security_connector.c', 'src/core/lib/security/transport/security_handshaker.c', 'src/core/lib/security/transport/server_auth_filter.c', 'src/core/lib/security/transport/tsi_error.c', 'src/core/lib/security/util/json_util.c', 'src/core/lib/surface/init_secure.c', 'src/core/tsi/fake_transport_security.c', 'src/core/tsi/ssl_transport_security.c', 'src/core/tsi/transport_security.c', 'src/core/ext/transport/chttp2/server/chttp2_server.c', 'src/core/ext/transport/chttp2/client/secure/secure_channel_create.c', 'src/core/ext/filters/client_channel/channel_connectivity.c', 'src/core/ext/filters/client_channel/client_channel.c', 'src/core/ext/filters/client_channel/client_channel_factory.c', 'src/core/ext/filters/client_channel/client_channel_plugin.c', 'src/core/ext/filters/client_channel/connector.c', 'src/core/ext/filters/client_channel/http_connect_handshaker.c', 'src/core/ext/filters/client_channel/http_proxy.c', 'src/core/ext/filters/client_channel/lb_policy.c', 'src/core/ext/filters/client_channel/lb_policy_factory.c', 'src/core/ext/filters/client_channel/lb_policy_registry.c', 'src/core/ext/filters/client_channel/parse_address.c', 'src/core/ext/filters/client_channel/proxy_mapper.c', 'src/core/ext/filters/client_channel/proxy_mapper_registry.c', 'src/core/ext/filters/client_channel/resolver.c', 'src/core/ext/filters/client_channel/resolver_factory.c', 'src/core/ext/filters/client_channel/resolver_registry.c', 'src/core/ext/filters/client_channel/retry_throttle.c', 'src/core/ext/filters/client_channel/subchannel.c', 'src/core/ext/filters/client_channel/subchannel_index.c', 'src/core/ext/filters/client_channel/uri_parser.c', 'src/core/ext/transport/chttp2/client/chttp2_connector.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', 'third_party/nanopb/pb_decode.c', 'third_party/nanopb/pb_encode.c', 'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c', 'src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c', 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.c', 'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c', 'src/core/ext/filters/load_reporting/load_reporting.c', 'src/core/ext/filters/load_reporting/load_reporting_filter.c', 'src/core/ext/census/base_resources.c', 'src/core/ext/census/context.c', 'src/core/ext/census/gen/census.pb.c', 'src/core/ext/census/gen/trace_context.pb.c', 'src/core/ext/census/grpc_context.c', 'src/core/ext/census/grpc_filter.c', 'src/core/ext/census/grpc_plugin.c', 'src/core/ext/census/initialize.c', 'src/core/ext/census/mlog.c', 'src/core/ext/census/operation.c', 'src/core/ext/census/placeholders.c', 'src/core/ext/census/resource.c', 'src/core/ext/census/trace_context.c', 'src/core/ext/census/tracing.c', 'src/core/ext/filters/max_age/max_age_filter.c', 'src/core/plugin_registry/grpc_plugin_registry.c' ss.private_header_files = 'src/core/lib/profiling/timers.h', 'src/core/lib/support/arena.h', 'src/core/lib/support/backoff.h', 'src/core/lib/support/block_annotate.h', 'src/core/lib/support/env.h', 'src/core/lib/support/mpscq.h', 'src/core/lib/support/murmur_hash.h', 'src/core/lib/support/spinlock.h', 'src/core/lib/support/stack_lockfree.h', 'src/core/lib/support/string.h', 'src/core/lib/support/string_windows.h', 'src/core/lib/support/thd_internal.h', 'src/core/lib/support/time_precise.h', 'src/core/lib/support/tmpfile.h', 'src/core/lib/channel/channel_args.h', 'src/core/lib/channel/channel_stack.h', 'src/core/lib/channel/channel_stack_builder.h', 'src/core/lib/channel/compress_filter.h', 'src/core/lib/channel/connected_channel.h', 'src/core/lib/channel/context.h', 'src/core/lib/channel/deadline_filter.h', 'src/core/lib/channel/handshaker.h', 'src/core/lib/channel/handshaker_factory.h', 'src/core/lib/channel/handshaker_registry.h', 'src/core/lib/channel/http_client_filter.h', 'src/core/lib/channel/http_server_filter.h', 'src/core/lib/channel/message_size_filter.h', 'src/core/lib/compression/algorithm_metadata.h', 'src/core/lib/compression/message_compress.h', 'src/core/lib/debug/trace.h', 'src/core/lib/http/format_request.h', 'src/core/lib/http/httpcli.h', 'src/core/lib/http/parser.h', 'src/core/lib/iomgr/closure.h', 'src/core/lib/iomgr/combiner.h', 'src/core/lib/iomgr/endpoint.h', 'src/core/lib/iomgr/endpoint_pair.h', 'src/core/lib/iomgr/error.h', 'src/core/lib/iomgr/error_internal.h', 'src/core/lib/iomgr/ev_epoll_linux.h', 'src/core/lib/iomgr/ev_poll_posix.h', 'src/core/lib/iomgr/ev_posix.h', 'src/core/lib/iomgr/exec_ctx.h', 'src/core/lib/iomgr/executor.h', 'src/core/lib/iomgr/iocp_windows.h', 'src/core/lib/iomgr/iomgr.h', 'src/core/lib/iomgr/iomgr_internal.h', 'src/core/lib/iomgr/iomgr_posix.h', 'src/core/lib/iomgr/load_file.h', 'src/core/lib/iomgr/lockfree_event.h', 'src/core/lib/iomgr/network_status_tracker.h', 'src/core/lib/iomgr/polling_entity.h', 'src/core/lib/iomgr/pollset.h', 'src/core/lib/iomgr/pollset_set.h', 'src/core/lib/iomgr/pollset_set_windows.h', 'src/core/lib/iomgr/pollset_uv.h', 'src/core/lib/iomgr/pollset_windows.h', 'src/core/lib/iomgr/port.h', 'src/core/lib/iomgr/resolve_address.h', 'src/core/lib/iomgr/resource_quota.h', 'src/core/lib/iomgr/sockaddr.h', 'src/core/lib/iomgr/sockaddr_posix.h', 'src/core/lib/iomgr/sockaddr_utils.h', 'src/core/lib/iomgr/sockaddr_windows.h', 'src/core/lib/iomgr/socket_factory_posix.h', 'src/core/lib/iomgr/socket_mutator.h', 'src/core/lib/iomgr/socket_utils.h', 'src/core/lib/iomgr/socket_utils_posix.h', 'src/core/lib/iomgr/socket_windows.h', 'src/core/lib/iomgr/tcp_client.h', 'src/core/lib/iomgr/tcp_client_posix.h', 'src/core/lib/iomgr/tcp_posix.h', 'src/core/lib/iomgr/tcp_server.h', 'src/core/lib/iomgr/tcp_server_utils_posix.h', 'src/core/lib/iomgr/tcp_uv.h', 'src/core/lib/iomgr/tcp_windows.h', 'src/core/lib/iomgr/time_averaged_stats.h', 'src/core/lib/iomgr/timer.h', 'src/core/lib/iomgr/timer_generic.h', 'src/core/lib/iomgr/timer_heap.h', 'src/core/lib/iomgr/timer_uv.h', 'src/core/lib/iomgr/udp_server.h', 'src/core/lib/iomgr/unix_sockets_posix.h', 'src/core/lib/iomgr/wakeup_fd_cv.h', 'src/core/lib/iomgr/wakeup_fd_pipe.h', 'src/core/lib/iomgr/wakeup_fd_posix.h', 'src/core/lib/iomgr/workqueue.h', 'src/core/lib/iomgr/workqueue_uv.h', 'src/core/lib/iomgr/workqueue_windows.h', 'src/core/lib/json/json.h', 'src/core/lib/json/json_common.h', 'src/core/lib/json/json_reader.h', 'src/core/lib/json/json_writer.h', 'src/core/lib/slice/b64.h', 'src/core/lib/slice/percent_encoding.h', 'src/core/lib/slice/slice_hash_table.h', 'src/core/lib/slice/slice_internal.h', 'src/core/lib/slice/slice_string_helpers.h', 'src/core/lib/surface/api_trace.h', 'src/core/lib/surface/call.h', 'src/core/lib/surface/call_test_only.h', 'src/core/lib/surface/channel.h', 'src/core/lib/surface/channel_init.h', 'src/core/lib/surface/channel_stack_type.h', 'src/core/lib/surface/completion_queue.h', 'src/core/lib/surface/completion_queue_factory.h', 'src/core/lib/surface/event_string.h', 'src/core/lib/surface/init.h', 'src/core/lib/surface/lame_client.h', 'src/core/lib/surface/server.h', 'src/core/lib/surface/validate_metadata.h', 'src/core/lib/transport/bdp_estimator.h', 'src/core/lib/transport/byte_stream.h', 'src/core/lib/transport/connectivity_state.h', 'src/core/lib/transport/error_utils.h', 'src/core/lib/transport/http2_errors.h', 'src/core/lib/transport/metadata.h', 'src/core/lib/transport/metadata_batch.h', 'src/core/lib/transport/pid_controller.h', 'src/core/lib/transport/service_config.h', 'src/core/lib/transport/static_metadata.h', 'src/core/lib/transport/status_conversion.h', 'src/core/lib/transport/timeout_encoding.h', 'src/core/lib/transport/transport.h', 'src/core/lib/transport/transport_impl.h', 'src/core/ext/transport/chttp2/transport/bin_decoder.h', 'src/core/ext/transport/chttp2/transport/bin_encoder.h', 'src/core/ext/transport/chttp2/transport/chttp2_transport.h', 'src/core/ext/transport/chttp2/transport/frame.h', 'src/core/ext/transport/chttp2/transport/frame_data.h', 'src/core/ext/transport/chttp2/transport/frame_goaway.h', 'src/core/ext/transport/chttp2/transport/frame_ping.h', 'src/core/ext/transport/chttp2/transport/frame_rst_stream.h', 'src/core/ext/transport/chttp2/transport/frame_settings.h', 'src/core/ext/transport/chttp2/transport/frame_window_update.h', 'src/core/ext/transport/chttp2/transport/hpack_encoder.h', 'src/core/ext/transport/chttp2/transport/hpack_parser.h', 'src/core/ext/transport/chttp2/transport/hpack_table.h', 'src/core/ext/transport/chttp2/transport/http2_settings.h', 'src/core/ext/transport/chttp2/transport/huffsyms.h', 'src/core/ext/transport/chttp2/transport/incoming_metadata.h', 'src/core/ext/transport/chttp2/transport/internal.h', 'src/core/ext/transport/chttp2/transport/stream_map.h', 'src/core/ext/transport/chttp2/transport/varint.h', 'src/core/ext/transport/chttp2/alpn/alpn.h', 'src/core/lib/security/context/security_context.h', 'src/core/lib/security/credentials/composite/composite_credentials.h', 'src/core/lib/security/credentials/credentials.h', 'src/core/lib/security/credentials/fake/fake_credentials.h', 'src/core/lib/security/credentials/google_default/google_default_credentials.h', 'src/core/lib/security/credentials/iam/iam_credentials.h', 'src/core/lib/security/credentials/jwt/json_token.h', 'src/core/lib/security/credentials/jwt/jwt_credentials.h', 'src/core/lib/security/credentials/jwt/jwt_verifier.h', 'src/core/lib/security/credentials/oauth2/oauth2_credentials.h', 'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h', 'src/core/lib/security/transport/auth_filters.h', 'src/core/lib/security/transport/lb_targets_info.h', 'src/core/lib/security/transport/secure_endpoint.h', 'src/core/lib/security/transport/security_connector.h', 'src/core/lib/security/transport/security_handshaker.h', 'src/core/lib/security/transport/tsi_error.h', 'src/core/lib/security/util/json_util.h', 'src/core/tsi/fake_transport_security.h', 'src/core/tsi/ssl_transport_security.h', 'src/core/tsi/ssl_types.h', 'src/core/tsi/transport_security.h', 'src/core/tsi/transport_security_interface.h', 'src/core/ext/transport/chttp2/server/chttp2_server.h', 'src/core/ext/filters/client_channel/client_channel.h', 'src/core/ext/filters/client_channel/client_channel_factory.h', 'src/core/ext/filters/client_channel/connector.h', 'src/core/ext/filters/client_channel/http_connect_handshaker.h', 'src/core/ext/filters/client_channel/http_proxy.h', 'src/core/ext/filters/client_channel/lb_policy.h', 'src/core/ext/filters/client_channel/lb_policy_factory.h', 'src/core/ext/filters/client_channel/lb_policy_registry.h', 'src/core/ext/filters/client_channel/parse_address.h', 'src/core/ext/filters/client_channel/proxy_mapper.h', 'src/core/ext/filters/client_channel/proxy_mapper_registry.h', 'src/core/ext/filters/client_channel/resolver.h', 'src/core/ext/filters/client_channel/resolver_factory.h', 'src/core/ext/filters/client_channel/resolver_registry.h', 'src/core/ext/filters/client_channel/retry_throttle.h', 'src/core/ext/filters/client_channel/subchannel.h', 'src/core/ext/filters/client_channel/subchannel_index.h', 'src/core/ext/filters/client_channel/uri_parser.h', 'src/core/ext/transport/chttp2/client/chttp2_connector.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h', 'third_party/nanopb/pb.h', 'third_party/nanopb/pb_common.h', 'third_party/nanopb/pb_decode.h', 'third_party/nanopb/pb_encode.h', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h', 'src/core/ext/filters/load_reporting/load_reporting.h', 'src/core/ext/filters/load_reporting/load_reporting_filter.h', 'src/core/ext/census/aggregation.h', 'src/core/ext/census/base_resources.h', 'src/core/ext/census/census_interface.h', 'src/core/ext/census/census_rpc_stats.h', 'src/core/ext/census/gen/census.pb.h', 'src/core/ext/census/gen/trace_context.pb.h', 'src/core/ext/census/grpc_filter.h', 'src/core/ext/census/mlog.h', 'src/core/ext/census/resource.h', 'src/core/ext/census/rpc_metric_id.h', 'src/core/ext/census/trace_context.h', 'src/core/ext/census/trace_label.h', 'src/core/ext/census/trace_propagation.h', 'src/core/ext/census/trace_status.h', 'src/core/ext/census/trace_string.h', 'src/core/ext/census/tracing.h', 'src/core/ext/filters/max_age/max_age_filter.h' end s.subspec 'Cronet-Interface' do |ss| ss.header_mappings_dir = 'include/grpc' ss.source_files = 'include/grpc/grpc_cronet.h' end s.subspec 'Cronet-Implementation' do |ss| ss.header_mappings_dir = '.' ss.dependency "#{s.name}/Interface", version ss.dependency "#{s.name}/Implementation", version ss.dependency "#{s.name}/Cronet-Interface", version ss.source_files = 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.c', 'src/core/ext/transport/cronet/transport/cronet_transport.{c,h}', 'third_party/objective_c/Cronet/bidirectional_stream_c.h' end s.subspec 'Tests' do |ss| ss.header_mappings_dir = '.' ss.dependency "#{s.name}/Interface", version ss.dependency "#{s.name}/Implementation", version ss.source_files = 'test/core/end2end/cq_verifier.{c,h}', 'test/core/end2end/end2end_tests.{c,h}', 'test/core/end2end/end2end_test_utils.c', 'test/core/end2end/tests/*.{c,h}', 'test/core/end2end/data/*.{c,h}', 'test/core/util/debugger_macros.{c,h}', 'test/core/util/test_config.{c,h}', 'test/core/util/port.h', 'test/core/util/port.c', 'test/core/util/port_server_client.{c,h}' end end grpc-1.3.2/gRPC-ProtoRPC.podspec000066400000000000000000000054501310511640000162630ustar00rootroot00000000000000# This file has been automatically generated from a template file. # Please make modifications to # `templates/gRPC-ProtoRPC.podspec.template` instead. This file can be # regenerated from the template by running # `tools/buildgen/generate_projects.sh`. # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Pod::Spec.new do |s| s.name = 'gRPC-ProtoRPC' version = '1.3.2' s.version = version s.summary = 'RPC library for Protocol Buffers, based on gRPC' s.homepage = 'http://www.grpc.io' s.license = 'New BSD' s.authors = { 'The gRPC contributors' => 'grpc-packages@google.com' } s.source = { :git => 'https://github.com/grpc/grpc.git', :tag => "v#{version}", } s.ios.deployment_target = '7.0' s.osx.deployment_target = '10.9' name = 'ProtoRPC' s.module_name = name s.header_dir = name src_dir = 'src/objective-c/ProtoRPC' s.source_files = "#{src_dir}/*.{h,m}" s.header_mappings_dir = "#{src_dir}" s.dependency 'gRPC', version s.dependency 'gRPC-RxLibrary', version s.dependency 'Protobuf', '~> 3.0' s.pod_target_xcconfig = { # This is needed by all pods that depend on Protobuf: 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1', # This is needed by all pods that depend on gRPC-RxLibrary: 'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES', } end grpc-1.3.2/gRPC-RxLibrary.podspec000066400000000000000000000047121310511640000165310ustar00rootroot00000000000000# This file has been automatically generated from a template file. # Please make modifications to # `templates/gRPC-RxLibrary.podspec.template` instead. This file can be # regenerated from the template by running # `tools/buildgen/generate_projects.sh`. # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Pod::Spec.new do |s| s.name = 'gRPC-RxLibrary' version = '1.3.2' s.version = version s.summary = 'Reactive Extensions library for iOS/OSX.' s.homepage = 'http://www.grpc.io' s.license = 'New BSD' s.authors = { 'The gRPC contributors' => 'grpc-packages@google.com' } s.source = { :git => 'https://github.com/grpc/grpc.git', :tag => "v#{version}", } s.ios.deployment_target = '7.0' s.osx.deployment_target = '10.9' name = 'RxLibrary' s.module_name = name s.header_dir = name src_dir = 'src/objective-c/RxLibrary' s.source_files = "#{src_dir}/*.{h,m}", "#{src_dir}/**/*.{h,m}" s.private_header_files = "#{src_dir}/private/*.h" s.header_mappings_dir = "#{src_dir}" end grpc-1.3.2/gRPC.podspec000066400000000000000000000054411310511640000146150ustar00rootroot00000000000000# This file has been automatically generated from a template file. # Please make modifications to `templates/gRPC.podspec.template` # instead. This file can be regenerated from the template by running # `tools/buildgen/generate_projects.sh`. # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Pod::Spec.new do |s| s.name = 'gRPC' version = '1.3.2' s.version = version s.summary = 'gRPC client library for iOS/OSX' s.homepage = 'http://www.grpc.io' s.license = 'New BSD' s.authors = { 'The gRPC contributors' => 'grpc-packages@google.com' } s.source = { :git => 'https://github.com/grpc/grpc.git', :tag => "v#{version}", } s.ios.deployment_target = '7.0' s.osx.deployment_target = '10.9' name = 'GRPCClient' s.module_name = name s.header_dir = name src_dir = 'src/objective-c/GRPCClient' s.source_files = "#{src_dir}/*.{h,m}", "#{src_dir}/**/*.{h,m}" s.private_header_files = "#{src_dir}/private/*.h" s.header_mappings_dir = "#{src_dir}" s.dependency 'gRPC-Core', version s.dependency 'gRPC-RxLibrary', version # Certificates, to be able to establish TLS connections: s.resource_bundles = { 'gRPCCertificates' => ['etc/roots.pem'] } s.pod_target_xcconfig = { # This is needed by all pods that depend on gRPC-RxLibrary: 'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES', } end grpc-1.3.2/grpc.bzl000066400000000000000000000106041310511640000141040ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ Bazel macros to declare gRPC libraries automatically generated from proto files. This file declares two macros: - objc_proto_library - objc_grpc_library """ def _lower_underscore_to_upper_camel(str): humps = [] for hump in str.split('_'): humps += [hump[0].upper() + hump[1:]] return "".join(humps) def _file_to_upper_camel(src): elements = src.rpartition('/') upper_camel = _lower_underscore_to_upper_camel(elements[-1]) return "".join(elements[:-1] + [upper_camel]) def _file_with_extension(src, ext): elements = src.rpartition('/') basename = elements[-1].partition('.')[0] return "".join(elements[:-1] + [basename, ext]) def _protoc_invocation(srcs, flags): """Returns a command line to invoke protoc from a genrule, on the given sources, using the given flags. """ protoc_command = "$(location //external:protoc) -I . " srcs_params = "" for src in srcs: srcs_params += " $(location %s)" % (src) return protoc_command + flags + srcs_params def objc_proto_library(name, srcs, visibility=None): """Declares an objc_library for the code generated by protoc from the given proto sources. This generated code doesn't include proto services. """ h_files = [] m_files = [] for src in srcs: src = _file_to_upper_camel(src) h_files += [_file_with_extension(src, ".pbobjc.h")] m_files += [_file_with_extension(src, ".pbobjc.m")] protoc_flags = "--objc_out=$(GENDIR)" native.genrule( name = name + "_codegen", srcs = srcs + ["//external:protoc"], outs = h_files + m_files, cmd = _protoc_invocation(srcs, protoc_flags), ) native.objc_library( name = name, hdrs = h_files, includes = ["."], non_arc_srcs = m_files, deps = ["//external:protobuf_objc"], visibility = visibility, ) def objc_grpc_library(name, services, other_messages, visibility=None): """Declares an objc_library for the code generated by gRPC and protoc from the given proto sources (services and other_messages). The generated code doesn't include proto services of the files passed as other_messages. """ objc_proto_library(name + "_messages", services + other_messages) h_files = [] m_files = [] for src in services: src = _file_to_upper_camel(src) h_files += [_file_with_extension(src, ".pbrpc.h")] m_files += [_file_with_extension(src, ".pbrpc.m")] protoc_flags = ("--grpc_out=$(GENDIR) --plugin=" + "protoc-gen-grpc=$(location //external:grpc_protoc_plugin_objc)") native.genrule( name = name + "_codegen", srcs = services + [ "//external:grpc_protoc_plugin_objc", "//external:protoc", ], outs = h_files + m_files, cmd = _protoc_invocation(services, protoc_flags), ) native.objc_library( name = name, hdrs = h_files, includes = ["."], srcs = m_files, deps = [ ":" + name + "_messages", "//external:proto_objc_rpc", ], visibility = visibility, ) grpc-1.3.2/grpc.def000066400000000000000000000201261310511640000140530ustar00rootroot00000000000000EXPORTS grpc_raw_byte_buffer_create grpc_raw_compressed_byte_buffer_create grpc_byte_buffer_copy grpc_byte_buffer_length grpc_byte_buffer_destroy grpc_byte_buffer_reader_init grpc_byte_buffer_reader_destroy grpc_byte_buffer_reader_next grpc_byte_buffer_reader_readall grpc_raw_byte_buffer_from_reader census_initialize census_shutdown census_supported census_enabled census_context_create census_context_destroy census_context_get_status census_context_initialize_iterator census_context_next_tag census_context_get_tag census_context_encode census_context_decode census_trace_mask census_set_trace_mask census_start_rpc_op_timestamp census_start_client_rpc_op census_set_rpc_client_peer census_start_server_rpc_op census_start_op census_end_op census_trace_print census_trace_scan_start census_get_trace_record census_trace_scan_end census_define_resource census_delete_resource census_resource_id census_record_values grpc_compression_algorithm_parse grpc_compression_algorithm_name grpc_compression_algorithm_for_level grpc_compression_options_init grpc_compression_options_enable_algorithm grpc_compression_options_disable_algorithm grpc_compression_options_is_algorithm_enabled grpc_metadata_array_init grpc_metadata_array_destroy grpc_call_details_init grpc_call_details_destroy grpc_register_plugin grpc_init grpc_shutdown grpc_version_string grpc_g_stands_for grpc_completion_queue_factory_lookup grpc_completion_queue_create_for_next grpc_completion_queue_create_for_pluck grpc_completion_queue_create grpc_completion_queue_next grpc_completion_queue_pluck grpc_completion_queue_shutdown grpc_completion_queue_destroy grpc_alarm_create grpc_alarm_cancel grpc_alarm_destroy grpc_channel_check_connectivity_state grpc_channel_watch_connectivity_state grpc_channel_create_call grpc_channel_ping grpc_channel_register_call grpc_channel_create_registered_call grpc_call_start_batch grpc_call_get_peer grpc_call_set_load_reporting_cost_context grpc_census_call_set_context grpc_census_call_get_context grpc_channel_get_target grpc_channel_get_info grpc_insecure_channel_create grpc_lame_client_channel_create grpc_channel_destroy grpc_call_cancel grpc_call_cancel_with_status grpc_call_destroy grpc_server_request_call grpc_server_register_method grpc_server_request_registered_call grpc_server_create grpc_server_register_completion_queue grpc_server_register_non_listening_completion_queue grpc_server_add_insecure_http2_port grpc_server_start grpc_server_shutdown_and_notify grpc_server_cancel_all_calls grpc_server_destroy grpc_tracer_set_enabled grpc_header_key_is_legal grpc_header_nonbin_value_is_legal grpc_is_binary_header grpc_call_error_to_string grpc_resource_quota_create grpc_resource_quota_ref grpc_resource_quota_unref grpc_resource_quota_resize grpc_resource_quota_arg_vtable grpc_insecure_channel_create_from_fd grpc_server_add_insecure_channel_from_fd grpc_use_signal grpc_auth_property_iterator_next grpc_auth_context_property_iterator grpc_auth_context_peer_identity grpc_auth_context_find_properties_by_name grpc_auth_context_peer_identity_property_name grpc_auth_context_peer_is_authenticated grpc_call_auth_context grpc_auth_context_release grpc_auth_context_add_property grpc_auth_context_add_cstring_property grpc_auth_context_set_peer_identity_property_name grpc_channel_credentials_release grpc_google_default_credentials_create grpc_set_ssl_roots_override_callback grpc_ssl_credentials_create grpc_call_credentials_release grpc_composite_channel_credentials_create grpc_composite_call_credentials_create grpc_google_compute_engine_credentials_create grpc_max_auth_token_lifetime grpc_service_account_jwt_access_credentials_create grpc_google_refresh_token_credentials_create grpc_access_token_credentials_create grpc_google_iam_credentials_create grpc_metadata_credentials_create_from_plugin grpc_secure_channel_create grpc_server_credentials_release grpc_ssl_server_credentials_create grpc_ssl_server_credentials_create_ex grpc_server_add_secure_http2_port grpc_call_set_credentials grpc_server_credentials_set_auth_metadata_processor grpc_slice_ref grpc_slice_unref grpc_slice_new grpc_slice_new_with_user_data grpc_slice_new_with_len grpc_slice_malloc grpc_slice_intern grpc_slice_from_copied_string grpc_slice_from_copied_buffer grpc_slice_from_static_string grpc_slice_from_static_buffer grpc_slice_sub grpc_slice_sub_no_ref grpc_slice_split_tail grpc_slice_split_head grpc_empty_slice grpc_slice_default_hash_impl grpc_slice_default_eq_impl grpc_slice_eq grpc_slice_cmp grpc_slice_str_cmp grpc_slice_buf_cmp grpc_slice_buf_start_eq grpc_slice_rchr grpc_slice_chr grpc_slice_slice grpc_slice_hash grpc_slice_is_equivalent grpc_slice_dup grpc_slice_to_c_string grpc_slice_buffer_init grpc_slice_buffer_destroy grpc_slice_buffer_add grpc_slice_buffer_add_indexed grpc_slice_buffer_addn grpc_slice_buffer_tiny_add grpc_slice_buffer_pop grpc_slice_buffer_reset_and_unref grpc_slice_buffer_swap grpc_slice_buffer_move_into grpc_slice_buffer_trim_end grpc_slice_buffer_move_first grpc_slice_buffer_move_first_into_buffer grpc_slice_buffer_take_first grpc_slice_buffer_undo_take_first gpr_malloc gpr_zalloc gpr_free gpr_realloc gpr_malloc_aligned gpr_free_aligned gpr_set_allocation_functions gpr_get_allocation_functions gpr_avl_create gpr_avl_ref gpr_avl_unref gpr_avl_add gpr_avl_remove gpr_avl_get gpr_avl_maybe_get gpr_avl_is_empty gpr_cmdline_create gpr_cmdline_add_int gpr_cmdline_add_flag gpr_cmdline_add_string gpr_cmdline_on_extra_arg gpr_cmdline_set_survive_failure gpr_cmdline_parse gpr_cmdline_destroy gpr_cmdline_usage_string gpr_cpu_num_cores gpr_cpu_current_cpu gpr_histogram_create gpr_histogram_destroy gpr_histogram_add gpr_histogram_merge gpr_histogram_percentile gpr_histogram_mean gpr_histogram_stddev gpr_histogram_variance gpr_histogram_maximum gpr_histogram_minimum gpr_histogram_count gpr_histogram_sum gpr_histogram_sum_of_squares gpr_histogram_get_contents gpr_histogram_merge_contents gpr_join_host_port gpr_split_host_port gpr_log gpr_log_message gpr_set_log_verbosity gpr_log_verbosity_init gpr_set_log_function gpr_format_message gpr_strdup gpr_asprintf gpr_subprocess_binary_extension gpr_subprocess_create gpr_subprocess_destroy gpr_subprocess_join gpr_subprocess_interrupt gpr_mu_init gpr_mu_destroy gpr_mu_lock gpr_mu_unlock gpr_mu_trylock gpr_cv_init gpr_cv_destroy gpr_cv_wait gpr_cv_signal gpr_cv_broadcast gpr_once_init gpr_event_init gpr_event_set gpr_event_get gpr_event_wait gpr_ref_init gpr_ref gpr_ref_non_zero gpr_refn gpr_unref gpr_ref_is_unique gpr_stats_init gpr_stats_inc gpr_stats_read gpr_thd_new gpr_thd_options_default gpr_thd_options_set_detached gpr_thd_options_set_joinable gpr_thd_options_is_detached gpr_thd_options_is_joinable gpr_thd_currentid gpr_thd_join gpr_time_0 gpr_inf_future gpr_inf_past gpr_time_init gpr_now gpr_convert_clock_type gpr_time_cmp gpr_time_max gpr_time_min gpr_time_add gpr_time_sub gpr_time_from_micros gpr_time_from_nanos gpr_time_from_millis gpr_time_from_seconds gpr_time_from_minutes gpr_time_from_hours gpr_time_to_millis gpr_time_similar gpr_sleep_until gpr_timespec_to_micros grpc-1.3.2/grpc.gemspec000077500000000000000000002030351310511640000147450ustar00rootroot00000000000000# -*- ruby -*- # encoding: utf-8 $LOAD_PATH.push File.expand_path('../src/ruby/lib', __FILE__) require 'grpc/version' Gem::Specification.new do |s| s.name = 'grpc' s.version = GRPC::VERSION s.authors = ['gRPC Authors'] s.email = 'temiola@google.com' s.homepage = 'https://github.com/google/grpc/tree/master/src/ruby' s.summary = 'GRPC system in Ruby' s.description = 'Send RPCs from Ruby using GRPC' s.license = 'BSD-3-Clause' s.required_ruby_version = '>= 2.0.0' s.files = %w( Makefile .yardopts ) s.files += %w( etc/roots.pem ) s.files += Dir.glob('src/ruby/bin/**/*') s.files += Dir.glob('src/ruby/ext/**/*') s.files += Dir.glob('src/ruby/lib/**/*') s.files += Dir.glob('src/ruby/pb/**/*') s.files += Dir.glob('include/grpc/**/*') s.test_files = Dir.glob('src/ruby/spec/**/*') s.bindir = 'src/ruby/bin' s.require_paths = %w( src/ruby/lib src/ruby/bin src/ruby/pb ) s.platform = Gem::Platform::RUBY s.add_dependency 'google-protobuf', '~> 3.1' s.add_dependency 'googleauth', '~> 0.5.1' s.add_development_dependency 'bundler', '~> 1.9' s.add_development_dependency 'facter', '~> 2.4' s.add_development_dependency 'logging', '~> 2.0' s.add_development_dependency 'simplecov', '~> 0.9' s.add_development_dependency 'rake', '~> 10.4' s.add_development_dependency 'rake-compiler', '~> 1.0' s.add_development_dependency 'rake-compiler-dock', '~> 0.5.1' s.add_development_dependency 'rspec', '~> 3.2' s.add_development_dependency 'rubocop', '~> 0.30.0' s.add_development_dependency 'signet', '~> 0.7.0' s.extensions = %w(src/ruby/ext/grpc/extconf.rb) s.files += %w( include/grpc/support/alloc.h ) s.files += %w( include/grpc/support/atm.h ) s.files += %w( include/grpc/support/atm_gcc_atomic.h ) s.files += %w( include/grpc/support/atm_gcc_sync.h ) s.files += %w( include/grpc/support/atm_windows.h ) s.files += %w( include/grpc/support/avl.h ) s.files += %w( include/grpc/support/cmdline.h ) s.files += %w( include/grpc/support/cpu.h ) s.files += %w( include/grpc/support/histogram.h ) s.files += %w( include/grpc/support/host_port.h ) s.files += %w( include/grpc/support/log.h ) s.files += %w( include/grpc/support/log_windows.h ) s.files += %w( include/grpc/support/port_platform.h ) s.files += %w( include/grpc/support/string_util.h ) s.files += %w( include/grpc/support/subprocess.h ) s.files += %w( include/grpc/support/sync.h ) s.files += %w( include/grpc/support/sync_generic.h ) s.files += %w( include/grpc/support/sync_posix.h ) s.files += %w( include/grpc/support/sync_windows.h ) s.files += %w( include/grpc/support/thd.h ) s.files += %w( include/grpc/support/time.h ) s.files += %w( include/grpc/support/tls.h ) s.files += %w( include/grpc/support/tls_gcc.h ) s.files += %w( include/grpc/support/tls_msvc.h ) s.files += %w( include/grpc/support/tls_pthread.h ) s.files += %w( include/grpc/support/useful.h ) s.files += %w( include/grpc/impl/codegen/atm.h ) s.files += %w( include/grpc/impl/codegen/atm_gcc_atomic.h ) s.files += %w( include/grpc/impl/codegen/atm_gcc_sync.h ) s.files += %w( include/grpc/impl/codegen/atm_windows.h ) s.files += %w( include/grpc/impl/codegen/gpr_slice.h ) s.files += %w( include/grpc/impl/codegen/gpr_types.h ) s.files += %w( include/grpc/impl/codegen/port_platform.h ) s.files += %w( include/grpc/impl/codegen/sync.h ) s.files += %w( include/grpc/impl/codegen/sync_generic.h ) s.files += %w( include/grpc/impl/codegen/sync_posix.h ) s.files += %w( include/grpc/impl/codegen/sync_windows.h ) s.files += %w( src/core/lib/profiling/timers.h ) s.files += %w( src/core/lib/support/arena.h ) s.files += %w( src/core/lib/support/backoff.h ) s.files += %w( src/core/lib/support/block_annotate.h ) s.files += %w( src/core/lib/support/env.h ) s.files += %w( src/core/lib/support/mpscq.h ) s.files += %w( src/core/lib/support/murmur_hash.h ) s.files += %w( src/core/lib/support/spinlock.h ) s.files += %w( src/core/lib/support/stack_lockfree.h ) s.files += %w( src/core/lib/support/string.h ) s.files += %w( src/core/lib/support/string_windows.h ) s.files += %w( src/core/lib/support/thd_internal.h ) s.files += %w( src/core/lib/support/time_precise.h ) s.files += %w( src/core/lib/support/tmpfile.h ) s.files += %w( src/core/lib/profiling/basic_timers.c ) s.files += %w( src/core/lib/profiling/stap_timers.c ) s.files += %w( src/core/lib/support/alloc.c ) s.files += %w( src/core/lib/support/arena.c ) s.files += %w( src/core/lib/support/atm.c ) s.files += %w( src/core/lib/support/avl.c ) s.files += %w( src/core/lib/support/backoff.c ) s.files += %w( src/core/lib/support/cmdline.c ) s.files += %w( src/core/lib/support/cpu_iphone.c ) s.files += %w( src/core/lib/support/cpu_linux.c ) s.files += %w( src/core/lib/support/cpu_posix.c ) s.files += %w( src/core/lib/support/cpu_windows.c ) s.files += %w( src/core/lib/support/env_linux.c ) s.files += %w( src/core/lib/support/env_posix.c ) s.files += %w( src/core/lib/support/env_windows.c ) s.files += %w( src/core/lib/support/histogram.c ) s.files += %w( src/core/lib/support/host_port.c ) s.files += %w( src/core/lib/support/log.c ) s.files += %w( src/core/lib/support/log_android.c ) s.files += %w( src/core/lib/support/log_linux.c ) s.files += %w( src/core/lib/support/log_posix.c ) s.files += %w( src/core/lib/support/log_windows.c ) s.files += %w( src/core/lib/support/mpscq.c ) s.files += %w( src/core/lib/support/murmur_hash.c ) s.files += %w( src/core/lib/support/stack_lockfree.c ) s.files += %w( src/core/lib/support/string.c ) s.files += %w( src/core/lib/support/string_posix.c ) s.files += %w( src/core/lib/support/string_util_windows.c ) s.files += %w( src/core/lib/support/string_windows.c ) s.files += %w( src/core/lib/support/subprocess_posix.c ) s.files += %w( src/core/lib/support/subprocess_windows.c ) s.files += %w( src/core/lib/support/sync.c ) s.files += %w( src/core/lib/support/sync_posix.c ) s.files += %w( src/core/lib/support/sync_windows.c ) s.files += %w( src/core/lib/support/thd.c ) s.files += %w( src/core/lib/support/thd_posix.c ) s.files += %w( src/core/lib/support/thd_windows.c ) s.files += %w( src/core/lib/support/time.c ) s.files += %w( src/core/lib/support/time_posix.c ) s.files += %w( src/core/lib/support/time_precise.c ) s.files += %w( src/core/lib/support/time_windows.c ) s.files += %w( src/core/lib/support/tls_pthread.c ) s.files += %w( src/core/lib/support/tmpfile_msys.c ) s.files += %w( src/core/lib/support/tmpfile_posix.c ) s.files += %w( src/core/lib/support/tmpfile_windows.c ) s.files += %w( src/core/lib/support/wrap_memcpy.c ) s.files += %w( include/grpc/byte_buffer.h ) s.files += %w( include/grpc/byte_buffer_reader.h ) s.files += %w( include/grpc/compression.h ) s.files += %w( include/grpc/grpc.h ) s.files += %w( include/grpc/grpc_posix.h ) s.files += %w( include/grpc/grpc_security_constants.h ) s.files += %w( include/grpc/load_reporting.h ) s.files += %w( include/grpc/slice.h ) s.files += %w( include/grpc/slice_buffer.h ) s.files += %w( include/grpc/status.h ) s.files += %w( include/grpc/impl/codegen/byte_buffer_reader.h ) s.files += %w( include/grpc/impl/codegen/compression_types.h ) s.files += %w( include/grpc/impl/codegen/connectivity_state.h ) s.files += %w( include/grpc/impl/codegen/exec_ctx_fwd.h ) s.files += %w( include/grpc/impl/codegen/grpc_types.h ) s.files += %w( include/grpc/impl/codegen/propagation_bits.h ) s.files += %w( include/grpc/impl/codegen/slice.h ) s.files += %w( include/grpc/impl/codegen/status.h ) s.files += %w( include/grpc/impl/codegen/atm.h ) s.files += %w( include/grpc/impl/codegen/atm_gcc_atomic.h ) s.files += %w( include/grpc/impl/codegen/atm_gcc_sync.h ) s.files += %w( include/grpc/impl/codegen/atm_windows.h ) s.files += %w( include/grpc/impl/codegen/gpr_slice.h ) s.files += %w( include/grpc/impl/codegen/gpr_types.h ) s.files += %w( include/grpc/impl/codegen/port_platform.h ) s.files += %w( include/grpc/impl/codegen/sync.h ) s.files += %w( include/grpc/impl/codegen/sync_generic.h ) s.files += %w( include/grpc/impl/codegen/sync_posix.h ) s.files += %w( include/grpc/impl/codegen/sync_windows.h ) s.files += %w( include/grpc/grpc_security.h ) s.files += %w( include/grpc/census.h ) s.files += %w( src/core/lib/channel/channel_args.h ) s.files += %w( src/core/lib/channel/channel_stack.h ) s.files += %w( src/core/lib/channel/channel_stack_builder.h ) s.files += %w( src/core/lib/channel/compress_filter.h ) s.files += %w( src/core/lib/channel/connected_channel.h ) s.files += %w( src/core/lib/channel/context.h ) s.files += %w( src/core/lib/channel/deadline_filter.h ) s.files += %w( src/core/lib/channel/handshaker.h ) s.files += %w( src/core/lib/channel/handshaker_factory.h ) s.files += %w( src/core/lib/channel/handshaker_registry.h ) s.files += %w( src/core/lib/channel/http_client_filter.h ) s.files += %w( src/core/lib/channel/http_server_filter.h ) s.files += %w( src/core/lib/channel/message_size_filter.h ) s.files += %w( src/core/lib/compression/algorithm_metadata.h ) s.files += %w( src/core/lib/compression/message_compress.h ) s.files += %w( src/core/lib/debug/trace.h ) s.files += %w( src/core/lib/http/format_request.h ) s.files += %w( src/core/lib/http/httpcli.h ) s.files += %w( src/core/lib/http/parser.h ) s.files += %w( src/core/lib/iomgr/closure.h ) s.files += %w( src/core/lib/iomgr/combiner.h ) s.files += %w( src/core/lib/iomgr/endpoint.h ) s.files += %w( src/core/lib/iomgr/endpoint_pair.h ) s.files += %w( src/core/lib/iomgr/error.h ) s.files += %w( src/core/lib/iomgr/error_internal.h ) s.files += %w( src/core/lib/iomgr/ev_epoll_linux.h ) s.files += %w( src/core/lib/iomgr/ev_poll_posix.h ) s.files += %w( src/core/lib/iomgr/ev_posix.h ) s.files += %w( src/core/lib/iomgr/exec_ctx.h ) s.files += %w( src/core/lib/iomgr/executor.h ) s.files += %w( src/core/lib/iomgr/iocp_windows.h ) s.files += %w( src/core/lib/iomgr/iomgr.h ) s.files += %w( src/core/lib/iomgr/iomgr_internal.h ) s.files += %w( src/core/lib/iomgr/iomgr_posix.h ) s.files += %w( src/core/lib/iomgr/load_file.h ) s.files += %w( src/core/lib/iomgr/lockfree_event.h ) s.files += %w( src/core/lib/iomgr/network_status_tracker.h ) s.files += %w( src/core/lib/iomgr/polling_entity.h ) s.files += %w( src/core/lib/iomgr/pollset.h ) s.files += %w( src/core/lib/iomgr/pollset_set.h ) s.files += %w( src/core/lib/iomgr/pollset_set_windows.h ) s.files += %w( src/core/lib/iomgr/pollset_uv.h ) s.files += %w( src/core/lib/iomgr/pollset_windows.h ) s.files += %w( src/core/lib/iomgr/port.h ) s.files += %w( src/core/lib/iomgr/resolve_address.h ) s.files += %w( src/core/lib/iomgr/resource_quota.h ) s.files += %w( src/core/lib/iomgr/sockaddr.h ) s.files += %w( src/core/lib/iomgr/sockaddr_posix.h ) s.files += %w( src/core/lib/iomgr/sockaddr_utils.h ) s.files += %w( src/core/lib/iomgr/sockaddr_windows.h ) s.files += %w( src/core/lib/iomgr/socket_factory_posix.h ) s.files += %w( src/core/lib/iomgr/socket_mutator.h ) s.files += %w( src/core/lib/iomgr/socket_utils.h ) s.files += %w( src/core/lib/iomgr/socket_utils_posix.h ) s.files += %w( src/core/lib/iomgr/socket_windows.h ) s.files += %w( src/core/lib/iomgr/tcp_client.h ) s.files += %w( src/core/lib/iomgr/tcp_client_posix.h ) s.files += %w( src/core/lib/iomgr/tcp_posix.h ) s.files += %w( src/core/lib/iomgr/tcp_server.h ) s.files += %w( src/core/lib/iomgr/tcp_server_utils_posix.h ) s.files += %w( src/core/lib/iomgr/tcp_uv.h ) s.files += %w( src/core/lib/iomgr/tcp_windows.h ) s.files += %w( src/core/lib/iomgr/time_averaged_stats.h ) s.files += %w( src/core/lib/iomgr/timer.h ) s.files += %w( src/core/lib/iomgr/timer_generic.h ) s.files += %w( src/core/lib/iomgr/timer_heap.h ) s.files += %w( src/core/lib/iomgr/timer_uv.h ) s.files += %w( src/core/lib/iomgr/udp_server.h ) s.files += %w( src/core/lib/iomgr/unix_sockets_posix.h ) s.files += %w( src/core/lib/iomgr/wakeup_fd_cv.h ) s.files += %w( src/core/lib/iomgr/wakeup_fd_pipe.h ) s.files += %w( src/core/lib/iomgr/wakeup_fd_posix.h ) s.files += %w( src/core/lib/iomgr/workqueue.h ) s.files += %w( src/core/lib/iomgr/workqueue_uv.h ) s.files += %w( src/core/lib/iomgr/workqueue_windows.h ) s.files += %w( src/core/lib/json/json.h ) s.files += %w( src/core/lib/json/json_common.h ) s.files += %w( src/core/lib/json/json_reader.h ) s.files += %w( src/core/lib/json/json_writer.h ) s.files += %w( src/core/lib/slice/b64.h ) s.files += %w( src/core/lib/slice/percent_encoding.h ) s.files += %w( src/core/lib/slice/slice_hash_table.h ) s.files += %w( src/core/lib/slice/slice_internal.h ) s.files += %w( src/core/lib/slice/slice_string_helpers.h ) s.files += %w( src/core/lib/surface/api_trace.h ) s.files += %w( src/core/lib/surface/call.h ) s.files += %w( src/core/lib/surface/call_test_only.h ) s.files += %w( src/core/lib/surface/channel.h ) s.files += %w( src/core/lib/surface/channel_init.h ) s.files += %w( src/core/lib/surface/channel_stack_type.h ) s.files += %w( src/core/lib/surface/completion_queue.h ) s.files += %w( src/core/lib/surface/completion_queue_factory.h ) s.files += %w( src/core/lib/surface/event_string.h ) s.files += %w( src/core/lib/surface/init.h ) s.files += %w( src/core/lib/surface/lame_client.h ) s.files += %w( src/core/lib/surface/server.h ) s.files += %w( src/core/lib/surface/validate_metadata.h ) s.files += %w( src/core/lib/transport/bdp_estimator.h ) s.files += %w( src/core/lib/transport/byte_stream.h ) s.files += %w( src/core/lib/transport/connectivity_state.h ) s.files += %w( src/core/lib/transport/error_utils.h ) s.files += %w( src/core/lib/transport/http2_errors.h ) s.files += %w( src/core/lib/transport/metadata.h ) s.files += %w( src/core/lib/transport/metadata_batch.h ) s.files += %w( src/core/lib/transport/pid_controller.h ) s.files += %w( src/core/lib/transport/service_config.h ) s.files += %w( src/core/lib/transport/static_metadata.h ) s.files += %w( src/core/lib/transport/status_conversion.h ) s.files += %w( src/core/lib/transport/timeout_encoding.h ) s.files += %w( src/core/lib/transport/transport.h ) s.files += %w( src/core/lib/transport/transport_impl.h ) s.files += %w( src/core/ext/transport/chttp2/transport/bin_decoder.h ) s.files += %w( src/core/ext/transport/chttp2/transport/bin_encoder.h ) s.files += %w( src/core/ext/transport/chttp2/transport/chttp2_transport.h ) s.files += %w( src/core/ext/transport/chttp2/transport/frame.h ) s.files += %w( src/core/ext/transport/chttp2/transport/frame_data.h ) s.files += %w( src/core/ext/transport/chttp2/transport/frame_goaway.h ) s.files += %w( src/core/ext/transport/chttp2/transport/frame_ping.h ) s.files += %w( src/core/ext/transport/chttp2/transport/frame_rst_stream.h ) s.files += %w( src/core/ext/transport/chttp2/transport/frame_settings.h ) s.files += %w( src/core/ext/transport/chttp2/transport/frame_window_update.h ) s.files += %w( src/core/ext/transport/chttp2/transport/hpack_encoder.h ) s.files += %w( src/core/ext/transport/chttp2/transport/hpack_parser.h ) s.files += %w( src/core/ext/transport/chttp2/transport/hpack_table.h ) s.files += %w( src/core/ext/transport/chttp2/transport/http2_settings.h ) s.files += %w( src/core/ext/transport/chttp2/transport/huffsyms.h ) s.files += %w( src/core/ext/transport/chttp2/transport/incoming_metadata.h ) s.files += %w( src/core/ext/transport/chttp2/transport/internal.h ) s.files += %w( src/core/ext/transport/chttp2/transport/stream_map.h ) s.files += %w( src/core/ext/transport/chttp2/transport/varint.h ) s.files += %w( src/core/ext/transport/chttp2/alpn/alpn.h ) s.files += %w( src/core/lib/security/context/security_context.h ) s.files += %w( src/core/lib/security/credentials/composite/composite_credentials.h ) s.files += %w( src/core/lib/security/credentials/credentials.h ) s.files += %w( src/core/lib/security/credentials/fake/fake_credentials.h ) s.files += %w( src/core/lib/security/credentials/google_default/google_default_credentials.h ) s.files += %w( src/core/lib/security/credentials/iam/iam_credentials.h ) s.files += %w( src/core/lib/security/credentials/jwt/json_token.h ) s.files += %w( src/core/lib/security/credentials/jwt/jwt_credentials.h ) s.files += %w( src/core/lib/security/credentials/jwt/jwt_verifier.h ) s.files += %w( src/core/lib/security/credentials/oauth2/oauth2_credentials.h ) s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.h ) s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.h ) s.files += %w( src/core/lib/security/transport/auth_filters.h ) s.files += %w( src/core/lib/security/transport/lb_targets_info.h ) s.files += %w( src/core/lib/security/transport/secure_endpoint.h ) s.files += %w( src/core/lib/security/transport/security_connector.h ) s.files += %w( src/core/lib/security/transport/security_handshaker.h ) s.files += %w( src/core/lib/security/transport/tsi_error.h ) s.files += %w( src/core/lib/security/util/json_util.h ) s.files += %w( src/core/tsi/fake_transport_security.h ) s.files += %w( src/core/tsi/ssl_transport_security.h ) s.files += %w( src/core/tsi/ssl_types.h ) s.files += %w( src/core/tsi/transport_security.h ) s.files += %w( src/core/tsi/transport_security_interface.h ) s.files += %w( src/core/ext/transport/chttp2/server/chttp2_server.h ) s.files += %w( src/core/ext/filters/client_channel/client_channel.h ) s.files += %w( src/core/ext/filters/client_channel/client_channel_factory.h ) s.files += %w( src/core/ext/filters/client_channel/connector.h ) s.files += %w( src/core/ext/filters/client_channel/http_connect_handshaker.h ) s.files += %w( src/core/ext/filters/client_channel/http_proxy.h ) s.files += %w( src/core/ext/filters/client_channel/lb_policy.h ) s.files += %w( src/core/ext/filters/client_channel/lb_policy_factory.h ) s.files += %w( src/core/ext/filters/client_channel/lb_policy_registry.h ) s.files += %w( src/core/ext/filters/client_channel/parse_address.h ) s.files += %w( src/core/ext/filters/client_channel/proxy_mapper.h ) s.files += %w( src/core/ext/filters/client_channel/proxy_mapper_registry.h ) s.files += %w( src/core/ext/filters/client_channel/resolver.h ) s.files += %w( src/core/ext/filters/client_channel/resolver_factory.h ) s.files += %w( src/core/ext/filters/client_channel/resolver_registry.h ) s.files += %w( src/core/ext/filters/client_channel/retry_throttle.h ) s.files += %w( src/core/ext/filters/client_channel/subchannel.h ) s.files += %w( src/core/ext/filters/client_channel/subchannel_index.h ) s.files += %w( src/core/ext/filters/client_channel/uri_parser.h ) s.files += %w( src/core/ext/transport/chttp2/client/chttp2_connector.h ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h ) s.files += %w( third_party/nanopb/pb.h ) s.files += %w( third_party/nanopb/pb_common.h ) s.files += %w( third_party/nanopb/pb_decode.h ) s.files += %w( third_party/nanopb/pb_encode.h ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h ) s.files += %w( src/core/ext/filters/load_reporting/load_reporting.h ) s.files += %w( src/core/ext/filters/load_reporting/load_reporting_filter.h ) s.files += %w( src/core/ext/census/aggregation.h ) s.files += %w( src/core/ext/census/base_resources.h ) s.files += %w( src/core/ext/census/census_interface.h ) s.files += %w( src/core/ext/census/census_rpc_stats.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/grpc_filter.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/rpc_metric_id.h ) s.files += %w( src/core/ext/census/trace_context.h ) s.files += %w( src/core/ext/census/trace_label.h ) s.files += %w( src/core/ext/census/trace_propagation.h ) s.files += %w( src/core/ext/census/trace_status.h ) s.files += %w( src/core/ext/census/trace_string.h ) s.files += %w( src/core/ext/census/tracing.h ) s.files += %w( src/core/ext/filters/max_age/max_age_filter.h ) s.files += %w( src/core/lib/surface/init.c ) s.files += %w( src/core/lib/channel/channel_args.c ) s.files += %w( src/core/lib/channel/channel_stack.c ) s.files += %w( src/core/lib/channel/channel_stack_builder.c ) s.files += %w( src/core/lib/channel/compress_filter.c ) s.files += %w( src/core/lib/channel/connected_channel.c ) s.files += %w( src/core/lib/channel/deadline_filter.c ) s.files += %w( src/core/lib/channel/handshaker.c ) s.files += %w( src/core/lib/channel/handshaker_factory.c ) s.files += %w( src/core/lib/channel/handshaker_registry.c ) s.files += %w( src/core/lib/channel/http_client_filter.c ) s.files += %w( src/core/lib/channel/http_server_filter.c ) s.files += %w( src/core/lib/channel/message_size_filter.c ) s.files += %w( src/core/lib/compression/compression.c ) s.files += %w( src/core/lib/compression/message_compress.c ) s.files += %w( src/core/lib/debug/trace.c ) s.files += %w( src/core/lib/http/format_request.c ) s.files += %w( src/core/lib/http/httpcli.c ) s.files += %w( src/core/lib/http/parser.c ) s.files += %w( src/core/lib/iomgr/closure.c ) s.files += %w( src/core/lib/iomgr/combiner.c ) s.files += %w( src/core/lib/iomgr/endpoint.c ) s.files += %w( src/core/lib/iomgr/endpoint_pair_posix.c ) s.files += %w( src/core/lib/iomgr/endpoint_pair_uv.c ) s.files += %w( src/core/lib/iomgr/endpoint_pair_windows.c ) s.files += %w( src/core/lib/iomgr/error.c ) s.files += %w( src/core/lib/iomgr/ev_epoll_linux.c ) s.files += %w( src/core/lib/iomgr/ev_poll_posix.c ) s.files += %w( src/core/lib/iomgr/ev_posix.c ) s.files += %w( src/core/lib/iomgr/exec_ctx.c ) s.files += %w( src/core/lib/iomgr/executor.c ) s.files += %w( src/core/lib/iomgr/iocp_windows.c ) s.files += %w( src/core/lib/iomgr/iomgr.c ) s.files += %w( src/core/lib/iomgr/iomgr_posix.c ) s.files += %w( src/core/lib/iomgr/iomgr_uv.c ) s.files += %w( src/core/lib/iomgr/iomgr_windows.c ) s.files += %w( src/core/lib/iomgr/load_file.c ) s.files += %w( src/core/lib/iomgr/lockfree_event.c ) s.files += %w( src/core/lib/iomgr/network_status_tracker.c ) s.files += %w( src/core/lib/iomgr/polling_entity.c ) s.files += %w( src/core/lib/iomgr/pollset_set_uv.c ) s.files += %w( src/core/lib/iomgr/pollset_set_windows.c ) s.files += %w( src/core/lib/iomgr/pollset_uv.c ) s.files += %w( src/core/lib/iomgr/pollset_windows.c ) s.files += %w( src/core/lib/iomgr/resolve_address_posix.c ) s.files += %w( src/core/lib/iomgr/resolve_address_uv.c ) s.files += %w( src/core/lib/iomgr/resolve_address_windows.c ) s.files += %w( src/core/lib/iomgr/resource_quota.c ) s.files += %w( src/core/lib/iomgr/sockaddr_utils.c ) s.files += %w( src/core/lib/iomgr/socket_factory_posix.c ) s.files += %w( src/core/lib/iomgr/socket_mutator.c ) s.files += %w( src/core/lib/iomgr/socket_utils_common_posix.c ) s.files += %w( src/core/lib/iomgr/socket_utils_linux.c ) s.files += %w( src/core/lib/iomgr/socket_utils_posix.c ) s.files += %w( src/core/lib/iomgr/socket_utils_uv.c ) s.files += %w( src/core/lib/iomgr/socket_utils_windows.c ) s.files += %w( src/core/lib/iomgr/socket_windows.c ) s.files += %w( src/core/lib/iomgr/tcp_client_posix.c ) s.files += %w( src/core/lib/iomgr/tcp_client_uv.c ) s.files += %w( src/core/lib/iomgr/tcp_client_windows.c ) s.files += %w( src/core/lib/iomgr/tcp_posix.c ) s.files += %w( src/core/lib/iomgr/tcp_server_posix.c ) s.files += %w( src/core/lib/iomgr/tcp_server_utils_posix_common.c ) s.files += %w( src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c ) s.files += %w( src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c ) s.files += %w( src/core/lib/iomgr/tcp_server_uv.c ) s.files += %w( src/core/lib/iomgr/tcp_server_windows.c ) s.files += %w( src/core/lib/iomgr/tcp_uv.c ) s.files += %w( src/core/lib/iomgr/tcp_windows.c ) s.files += %w( src/core/lib/iomgr/time_averaged_stats.c ) s.files += %w( src/core/lib/iomgr/timer_generic.c ) s.files += %w( src/core/lib/iomgr/timer_heap.c ) s.files += %w( src/core/lib/iomgr/timer_uv.c ) s.files += %w( src/core/lib/iomgr/udp_server.c ) s.files += %w( src/core/lib/iomgr/unix_sockets_posix.c ) s.files += %w( src/core/lib/iomgr/unix_sockets_posix_noop.c ) s.files += %w( src/core/lib/iomgr/wakeup_fd_cv.c ) s.files += %w( src/core/lib/iomgr/wakeup_fd_eventfd.c ) s.files += %w( src/core/lib/iomgr/wakeup_fd_nospecial.c ) s.files += %w( src/core/lib/iomgr/wakeup_fd_pipe.c ) s.files += %w( src/core/lib/iomgr/wakeup_fd_posix.c ) s.files += %w( src/core/lib/iomgr/workqueue_uv.c ) s.files += %w( src/core/lib/iomgr/workqueue_windows.c ) s.files += %w( src/core/lib/json/json.c ) s.files += %w( src/core/lib/json/json_reader.c ) s.files += %w( src/core/lib/json/json_string.c ) s.files += %w( src/core/lib/json/json_writer.c ) s.files += %w( src/core/lib/slice/b64.c ) s.files += %w( src/core/lib/slice/percent_encoding.c ) s.files += %w( src/core/lib/slice/slice.c ) s.files += %w( src/core/lib/slice/slice_buffer.c ) s.files += %w( src/core/lib/slice/slice_hash_table.c ) s.files += %w( src/core/lib/slice/slice_intern.c ) s.files += %w( src/core/lib/slice/slice_string_helpers.c ) s.files += %w( src/core/lib/surface/alarm.c ) s.files += %w( src/core/lib/surface/api_trace.c ) s.files += %w( src/core/lib/surface/byte_buffer.c ) s.files += %w( src/core/lib/surface/byte_buffer_reader.c ) s.files += %w( src/core/lib/surface/call.c ) s.files += %w( src/core/lib/surface/call_details.c ) s.files += %w( src/core/lib/surface/call_log_batch.c ) s.files += %w( src/core/lib/surface/channel.c ) s.files += %w( src/core/lib/surface/channel_init.c ) s.files += %w( src/core/lib/surface/channel_ping.c ) s.files += %w( src/core/lib/surface/channel_stack_type.c ) s.files += %w( src/core/lib/surface/completion_queue.c ) s.files += %w( src/core/lib/surface/completion_queue_factory.c ) s.files += %w( src/core/lib/surface/event_string.c ) s.files += %w( src/core/lib/surface/lame_client.c ) s.files += %w( src/core/lib/surface/metadata_array.c ) s.files += %w( src/core/lib/surface/server.c ) s.files += %w( src/core/lib/surface/validate_metadata.c ) s.files += %w( src/core/lib/surface/version.c ) s.files += %w( src/core/lib/transport/bdp_estimator.c ) s.files += %w( src/core/lib/transport/byte_stream.c ) s.files += %w( src/core/lib/transport/connectivity_state.c ) s.files += %w( src/core/lib/transport/error_utils.c ) s.files += %w( src/core/lib/transport/metadata.c ) s.files += %w( src/core/lib/transport/metadata_batch.c ) s.files += %w( src/core/lib/transport/pid_controller.c ) s.files += %w( src/core/lib/transport/service_config.c ) s.files += %w( src/core/lib/transport/static_metadata.c ) s.files += %w( src/core/lib/transport/status_conversion.c ) s.files += %w( src/core/lib/transport/timeout_encoding.c ) s.files += %w( src/core/lib/transport/transport.c ) s.files += %w( src/core/lib/transport/transport_op_string.c ) s.files += %w( src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c ) s.files += %w( src/core/ext/transport/chttp2/transport/bin_decoder.c ) s.files += %w( src/core/ext/transport/chttp2/transport/bin_encoder.c ) s.files += %w( src/core/ext/transport/chttp2/transport/chttp2_plugin.c ) s.files += %w( src/core/ext/transport/chttp2/transport/chttp2_transport.c ) s.files += %w( src/core/ext/transport/chttp2/transport/frame_data.c ) s.files += %w( src/core/ext/transport/chttp2/transport/frame_goaway.c ) s.files += %w( src/core/ext/transport/chttp2/transport/frame_ping.c ) s.files += %w( src/core/ext/transport/chttp2/transport/frame_rst_stream.c ) s.files += %w( src/core/ext/transport/chttp2/transport/frame_settings.c ) s.files += %w( src/core/ext/transport/chttp2/transport/frame_window_update.c ) s.files += %w( src/core/ext/transport/chttp2/transport/hpack_encoder.c ) s.files += %w( src/core/ext/transport/chttp2/transport/hpack_parser.c ) s.files += %w( src/core/ext/transport/chttp2/transport/hpack_table.c ) s.files += %w( src/core/ext/transport/chttp2/transport/http2_settings.c ) s.files += %w( src/core/ext/transport/chttp2/transport/huffsyms.c ) s.files += %w( src/core/ext/transport/chttp2/transport/incoming_metadata.c ) s.files += %w( src/core/ext/transport/chttp2/transport/parsing.c ) s.files += %w( src/core/ext/transport/chttp2/transport/stream_lists.c ) s.files += %w( src/core/ext/transport/chttp2/transport/stream_map.c ) s.files += %w( src/core/ext/transport/chttp2/transport/varint.c ) s.files += %w( src/core/ext/transport/chttp2/transport/writing.c ) s.files += %w( src/core/ext/transport/chttp2/alpn/alpn.c ) s.files += %w( src/core/lib/http/httpcli_security_connector.c ) s.files += %w( src/core/lib/security/context/security_context.c ) s.files += %w( src/core/lib/security/credentials/composite/composite_credentials.c ) s.files += %w( src/core/lib/security/credentials/credentials.c ) s.files += %w( src/core/lib/security/credentials/credentials_metadata.c ) s.files += %w( src/core/lib/security/credentials/fake/fake_credentials.c ) s.files += %w( src/core/lib/security/credentials/google_default/credentials_generic.c ) s.files += %w( src/core/lib/security/credentials/google_default/google_default_credentials.c ) s.files += %w( src/core/lib/security/credentials/iam/iam_credentials.c ) s.files += %w( src/core/lib/security/credentials/jwt/json_token.c ) s.files += %w( src/core/lib/security/credentials/jwt/jwt_credentials.c ) s.files += %w( src/core/lib/security/credentials/jwt/jwt_verifier.c ) s.files += %w( src/core/lib/security/credentials/oauth2/oauth2_credentials.c ) s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.c ) s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.c ) s.files += %w( src/core/lib/security/transport/client_auth_filter.c ) s.files += %w( src/core/lib/security/transport/lb_targets_info.c ) s.files += %w( src/core/lib/security/transport/secure_endpoint.c ) s.files += %w( src/core/lib/security/transport/security_connector.c ) s.files += %w( src/core/lib/security/transport/security_handshaker.c ) s.files += %w( src/core/lib/security/transport/server_auth_filter.c ) s.files += %w( src/core/lib/security/transport/tsi_error.c ) s.files += %w( src/core/lib/security/util/json_util.c ) s.files += %w( src/core/lib/surface/init_secure.c ) s.files += %w( src/core/tsi/fake_transport_security.c ) s.files += %w( src/core/tsi/ssl_transport_security.c ) s.files += %w( src/core/tsi/transport_security.c ) s.files += %w( src/core/ext/transport/chttp2/server/chttp2_server.c ) s.files += %w( src/core/ext/transport/chttp2/client/secure/secure_channel_create.c ) s.files += %w( src/core/ext/filters/client_channel/channel_connectivity.c ) s.files += %w( src/core/ext/filters/client_channel/client_channel.c ) s.files += %w( src/core/ext/filters/client_channel/client_channel_factory.c ) s.files += %w( src/core/ext/filters/client_channel/client_channel_plugin.c ) s.files += %w( src/core/ext/filters/client_channel/connector.c ) s.files += %w( src/core/ext/filters/client_channel/http_connect_handshaker.c ) s.files += %w( src/core/ext/filters/client_channel/http_proxy.c ) s.files += %w( src/core/ext/filters/client_channel/lb_policy.c ) s.files += %w( src/core/ext/filters/client_channel/lb_policy_factory.c ) s.files += %w( src/core/ext/filters/client_channel/lb_policy_registry.c ) s.files += %w( src/core/ext/filters/client_channel/parse_address.c ) s.files += %w( src/core/ext/filters/client_channel/proxy_mapper.c ) s.files += %w( src/core/ext/filters/client_channel/proxy_mapper_registry.c ) s.files += %w( src/core/ext/filters/client_channel/resolver.c ) s.files += %w( src/core/ext/filters/client_channel/resolver_factory.c ) s.files += %w( src/core/ext/filters/client_channel/resolver_registry.c ) s.files += %w( src/core/ext/filters/client_channel/retry_throttle.c ) s.files += %w( src/core/ext/filters/client_channel/subchannel.c ) s.files += %w( src/core/ext/filters/client_channel/subchannel_index.c ) s.files += %w( src/core/ext/filters/client_channel/uri_parser.c ) s.files += %w( src/core/ext/transport/chttp2/client/chttp2_connector.c ) s.files += %w( src/core/ext/transport/chttp2/server/insecure/server_chttp2.c ) s.files += %w( src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c ) s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.c ) s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c ) s.files += %w( third_party/nanopb/pb_common.c ) s.files += %w( third_party/nanopb/pb_decode.c ) s.files += %w( third_party/nanopb/pb_encode.c ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.c ) s.files += %w( src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c ) s.files += %w( src/core/ext/filters/load_reporting/load_reporting.c ) s.files += %w( src/core/ext/filters/load_reporting/load_reporting_filter.c ) s.files += %w( src/core/ext/census/base_resources.c ) s.files += %w( src/core/ext/census/context.c ) s.files += %w( src/core/ext/census/gen/census.pb.c ) s.files += %w( src/core/ext/census/gen/trace_context.pb.c ) s.files += %w( src/core/ext/census/grpc_context.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/initialize.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/placeholders.c ) s.files += %w( src/core/ext/census/resource.c ) s.files += %w( src/core/ext/census/trace_context.c ) s.files += %w( src/core/ext/census/tracing.c ) s.files += %w( src/core/ext/filters/max_age/max_age_filter.c ) s.files += %w( src/core/plugin_registry/grpc_plugin_registry.c ) s.files += %w( third_party/boringssl/crypto/aes/internal.h ) s.files += %w( third_party/boringssl/crypto/asn1/asn1_locl.h ) s.files += %w( third_party/boringssl/crypto/bio/internal.h ) s.files += %w( third_party/boringssl/crypto/bn/internal.h ) s.files += %w( third_party/boringssl/crypto/bn/rsaz_exp.h ) s.files += %w( third_party/boringssl/crypto/bytestring/internal.h ) s.files += %w( third_party/boringssl/crypto/cipher/internal.h ) s.files += %w( third_party/boringssl/crypto/conf/conf_def.h ) s.files += %w( third_party/boringssl/crypto/conf/internal.h ) s.files += %w( third_party/boringssl/crypto/curve25519/internal.h ) s.files += %w( third_party/boringssl/crypto/des/internal.h ) s.files += %w( third_party/boringssl/crypto/digest/internal.h ) s.files += %w( third_party/boringssl/crypto/digest/md32_common.h ) s.files += %w( third_party/boringssl/crypto/ec/internal.h ) s.files += %w( third_party/boringssl/crypto/ec/p256-x86_64-table.h ) s.files += %w( third_party/boringssl/crypto/evp/internal.h ) s.files += %w( third_party/boringssl/crypto/internal.h ) s.files += %w( third_party/boringssl/crypto/modes/internal.h ) s.files += %w( third_party/boringssl/crypto/newhope/internal.h ) s.files += %w( third_party/boringssl/crypto/obj/obj_dat.h ) s.files += %w( third_party/boringssl/crypto/obj/obj_xref.h ) s.files += %w( third_party/boringssl/crypto/pkcs8/internal.h ) s.files += %w( third_party/boringssl/crypto/poly1305/internal.h ) s.files += %w( third_party/boringssl/crypto/rand/internal.h ) s.files += %w( third_party/boringssl/crypto/rsa/internal.h ) s.files += %w( third_party/boringssl/crypto/x509/charmap.h ) s.files += %w( third_party/boringssl/crypto/x509/internal.h ) s.files += %w( third_party/boringssl/crypto/x509/vpm_int.h ) s.files += %w( third_party/boringssl/crypto/x509v3/ext_dat.h ) s.files += %w( third_party/boringssl/crypto/x509v3/pcy_int.h ) s.files += %w( third_party/boringssl/include/openssl/aead.h ) s.files += %w( third_party/boringssl/include/openssl/aes.h ) s.files += %w( third_party/boringssl/include/openssl/arm_arch.h ) s.files += %w( third_party/boringssl/include/openssl/asn1.h ) s.files += %w( third_party/boringssl/include/openssl/asn1_mac.h ) s.files += %w( third_party/boringssl/include/openssl/asn1t.h ) s.files += %w( third_party/boringssl/include/openssl/base.h ) s.files += %w( third_party/boringssl/include/openssl/base64.h ) s.files += %w( third_party/boringssl/include/openssl/bio.h ) s.files += %w( third_party/boringssl/include/openssl/blowfish.h ) s.files += %w( third_party/boringssl/include/openssl/bn.h ) s.files += %w( third_party/boringssl/include/openssl/buf.h ) s.files += %w( third_party/boringssl/include/openssl/buffer.h ) s.files += %w( third_party/boringssl/include/openssl/bytestring.h ) s.files += %w( third_party/boringssl/include/openssl/cast.h ) s.files += %w( third_party/boringssl/include/openssl/chacha.h ) s.files += %w( third_party/boringssl/include/openssl/cipher.h ) s.files += %w( third_party/boringssl/include/openssl/cmac.h ) s.files += %w( third_party/boringssl/include/openssl/conf.h ) s.files += %w( third_party/boringssl/include/openssl/cpu.h ) s.files += %w( third_party/boringssl/include/openssl/crypto.h ) s.files += %w( third_party/boringssl/include/openssl/curve25519.h ) s.files += %w( third_party/boringssl/include/openssl/des.h ) s.files += %w( third_party/boringssl/include/openssl/dh.h ) s.files += %w( third_party/boringssl/include/openssl/digest.h ) s.files += %w( third_party/boringssl/include/openssl/dsa.h ) s.files += %w( third_party/boringssl/include/openssl/dtls1.h ) s.files += %w( third_party/boringssl/include/openssl/ec.h ) s.files += %w( third_party/boringssl/include/openssl/ec_key.h ) s.files += %w( third_party/boringssl/include/openssl/ecdh.h ) s.files += %w( third_party/boringssl/include/openssl/ecdsa.h ) s.files += %w( third_party/boringssl/include/openssl/engine.h ) s.files += %w( third_party/boringssl/include/openssl/err.h ) s.files += %w( third_party/boringssl/include/openssl/evp.h ) s.files += %w( third_party/boringssl/include/openssl/ex_data.h ) s.files += %w( third_party/boringssl/include/openssl/hkdf.h ) s.files += %w( third_party/boringssl/include/openssl/hmac.h ) s.files += %w( third_party/boringssl/include/openssl/lhash.h ) s.files += %w( third_party/boringssl/include/openssl/lhash_macros.h ) s.files += %w( third_party/boringssl/include/openssl/md4.h ) s.files += %w( third_party/boringssl/include/openssl/md5.h ) s.files += %w( third_party/boringssl/include/openssl/mem.h ) s.files += %w( third_party/boringssl/include/openssl/newhope.h ) s.files += %w( third_party/boringssl/include/openssl/nid.h ) s.files += %w( third_party/boringssl/include/openssl/obj.h ) s.files += %w( third_party/boringssl/include/openssl/obj_mac.h ) s.files += %w( third_party/boringssl/include/openssl/objects.h ) s.files += %w( third_party/boringssl/include/openssl/opensslconf.h ) s.files += %w( third_party/boringssl/include/openssl/opensslv.h ) s.files += %w( third_party/boringssl/include/openssl/ossl_typ.h ) s.files += %w( third_party/boringssl/include/openssl/pem.h ) s.files += %w( third_party/boringssl/include/openssl/pkcs12.h ) s.files += %w( third_party/boringssl/include/openssl/pkcs7.h ) s.files += %w( third_party/boringssl/include/openssl/pkcs8.h ) s.files += %w( third_party/boringssl/include/openssl/poly1305.h ) s.files += %w( third_party/boringssl/include/openssl/rand.h ) s.files += %w( third_party/boringssl/include/openssl/rc4.h ) s.files += %w( third_party/boringssl/include/openssl/ripemd.h ) s.files += %w( third_party/boringssl/include/openssl/rsa.h ) s.files += %w( third_party/boringssl/include/openssl/safestack.h ) s.files += %w( third_party/boringssl/include/openssl/sha.h ) s.files += %w( third_party/boringssl/include/openssl/srtp.h ) s.files += %w( third_party/boringssl/include/openssl/ssl.h ) s.files += %w( third_party/boringssl/include/openssl/ssl3.h ) s.files += %w( third_party/boringssl/include/openssl/stack.h ) s.files += %w( third_party/boringssl/include/openssl/stack_macros.h ) s.files += %w( third_party/boringssl/include/openssl/thread.h ) s.files += %w( third_party/boringssl/include/openssl/time_support.h ) s.files += %w( third_party/boringssl/include/openssl/tls1.h ) s.files += %w( third_party/boringssl/include/openssl/type_check.h ) s.files += %w( third_party/boringssl/include/openssl/x509.h ) s.files += %w( third_party/boringssl/include/openssl/x509_vfy.h ) s.files += %w( third_party/boringssl/include/openssl/x509v3.h ) s.files += %w( third_party/boringssl/ssl/internal.h ) s.files += %w( src/boringssl/err_data.c ) s.files += %w( third_party/boringssl/crypto/aes/aes.c ) s.files += %w( third_party/boringssl/crypto/aes/mode_wrappers.c ) s.files += %w( third_party/boringssl/crypto/asn1/a_bitstr.c ) s.files += %w( third_party/boringssl/crypto/asn1/a_bool.c ) s.files += %w( third_party/boringssl/crypto/asn1/a_d2i_fp.c ) s.files += %w( third_party/boringssl/crypto/asn1/a_dup.c ) s.files += %w( third_party/boringssl/crypto/asn1/a_enum.c ) s.files += %w( third_party/boringssl/crypto/asn1/a_gentm.c ) s.files += %w( third_party/boringssl/crypto/asn1/a_i2d_fp.c ) s.files += %w( third_party/boringssl/crypto/asn1/a_int.c ) s.files += %w( third_party/boringssl/crypto/asn1/a_mbstr.c ) s.files += %w( third_party/boringssl/crypto/asn1/a_object.c ) s.files += %w( third_party/boringssl/crypto/asn1/a_octet.c ) s.files += %w( third_party/boringssl/crypto/asn1/a_print.c ) s.files += %w( third_party/boringssl/crypto/asn1/a_strnid.c ) s.files += %w( third_party/boringssl/crypto/asn1/a_time.c ) s.files += %w( third_party/boringssl/crypto/asn1/a_type.c ) s.files += %w( third_party/boringssl/crypto/asn1/a_utctm.c ) s.files += %w( third_party/boringssl/crypto/asn1/a_utf8.c ) s.files += %w( third_party/boringssl/crypto/asn1/asn1_lib.c ) s.files += %w( third_party/boringssl/crypto/asn1/asn1_par.c ) s.files += %w( third_party/boringssl/crypto/asn1/asn_pack.c ) s.files += %w( third_party/boringssl/crypto/asn1/f_enum.c ) s.files += %w( third_party/boringssl/crypto/asn1/f_int.c ) s.files += %w( third_party/boringssl/crypto/asn1/f_string.c ) s.files += %w( third_party/boringssl/crypto/asn1/t_bitst.c ) s.files += %w( third_party/boringssl/crypto/asn1/tasn_dec.c ) s.files += %w( third_party/boringssl/crypto/asn1/tasn_enc.c ) s.files += %w( third_party/boringssl/crypto/asn1/tasn_fre.c ) s.files += %w( third_party/boringssl/crypto/asn1/tasn_new.c ) s.files += %w( third_party/boringssl/crypto/asn1/tasn_typ.c ) s.files += %w( third_party/boringssl/crypto/asn1/tasn_utl.c ) s.files += %w( third_party/boringssl/crypto/asn1/x_bignum.c ) s.files += %w( third_party/boringssl/crypto/asn1/x_long.c ) s.files += %w( third_party/boringssl/crypto/base64/base64.c ) s.files += %w( third_party/boringssl/crypto/bio/bio.c ) s.files += %w( third_party/boringssl/crypto/bio/bio_mem.c ) s.files += %w( third_party/boringssl/crypto/bio/buffer.c ) s.files += %w( third_party/boringssl/crypto/bio/connect.c ) s.files += %w( third_party/boringssl/crypto/bio/fd.c ) s.files += %w( third_party/boringssl/crypto/bio/file.c ) s.files += %w( third_party/boringssl/crypto/bio/hexdump.c ) s.files += %w( third_party/boringssl/crypto/bio/pair.c ) s.files += %w( third_party/boringssl/crypto/bio/printf.c ) s.files += %w( third_party/boringssl/crypto/bio/socket.c ) s.files += %w( third_party/boringssl/crypto/bio/socket_helper.c ) s.files += %w( third_party/boringssl/crypto/bn/add.c ) s.files += %w( third_party/boringssl/crypto/bn/asm/x86_64-gcc.c ) s.files += %w( third_party/boringssl/crypto/bn/bn.c ) s.files += %w( third_party/boringssl/crypto/bn/bn_asn1.c ) s.files += %w( third_party/boringssl/crypto/bn/cmp.c ) s.files += %w( third_party/boringssl/crypto/bn/convert.c ) s.files += %w( third_party/boringssl/crypto/bn/ctx.c ) s.files += %w( third_party/boringssl/crypto/bn/div.c ) s.files += %w( third_party/boringssl/crypto/bn/exponentiation.c ) s.files += %w( third_party/boringssl/crypto/bn/gcd.c ) s.files += %w( third_party/boringssl/crypto/bn/generic.c ) s.files += %w( third_party/boringssl/crypto/bn/kronecker.c ) s.files += %w( third_party/boringssl/crypto/bn/montgomery.c ) s.files += %w( third_party/boringssl/crypto/bn/montgomery_inv.c ) s.files += %w( third_party/boringssl/crypto/bn/mul.c ) s.files += %w( third_party/boringssl/crypto/bn/prime.c ) s.files += %w( third_party/boringssl/crypto/bn/random.c ) s.files += %w( third_party/boringssl/crypto/bn/rsaz_exp.c ) s.files += %w( third_party/boringssl/crypto/bn/shift.c ) s.files += %w( third_party/boringssl/crypto/bn/sqrt.c ) s.files += %w( third_party/boringssl/crypto/buf/buf.c ) s.files += %w( third_party/boringssl/crypto/bytestring/asn1_compat.c ) s.files += %w( third_party/boringssl/crypto/bytestring/ber.c ) s.files += %w( third_party/boringssl/crypto/bytestring/cbb.c ) s.files += %w( third_party/boringssl/crypto/bytestring/cbs.c ) s.files += %w( third_party/boringssl/crypto/chacha/chacha.c ) s.files += %w( third_party/boringssl/crypto/cipher/aead.c ) s.files += %w( third_party/boringssl/crypto/cipher/cipher.c ) s.files += %w( third_party/boringssl/crypto/cipher/derive_key.c ) s.files += %w( third_party/boringssl/crypto/cipher/e_aes.c ) s.files += %w( third_party/boringssl/crypto/cipher/e_chacha20poly1305.c ) s.files += %w( third_party/boringssl/crypto/cipher/e_des.c ) s.files += %w( third_party/boringssl/crypto/cipher/e_null.c ) s.files += %w( third_party/boringssl/crypto/cipher/e_rc2.c ) s.files += %w( third_party/boringssl/crypto/cipher/e_rc4.c ) s.files += %w( third_party/boringssl/crypto/cipher/e_ssl3.c ) s.files += %w( third_party/boringssl/crypto/cipher/e_tls.c ) s.files += %w( third_party/boringssl/crypto/cipher/tls_cbc.c ) s.files += %w( third_party/boringssl/crypto/cmac/cmac.c ) s.files += %w( third_party/boringssl/crypto/conf/conf.c ) s.files += %w( third_party/boringssl/crypto/cpu-aarch64-linux.c ) s.files += %w( third_party/boringssl/crypto/cpu-arm-linux.c ) s.files += %w( third_party/boringssl/crypto/cpu-arm.c ) s.files += %w( third_party/boringssl/crypto/cpu-intel.c ) s.files += %w( third_party/boringssl/crypto/cpu-ppc64le.c ) s.files += %w( third_party/boringssl/crypto/crypto.c ) s.files += %w( third_party/boringssl/crypto/curve25519/curve25519.c ) s.files += %w( third_party/boringssl/crypto/curve25519/spake25519.c ) s.files += %w( third_party/boringssl/crypto/curve25519/x25519-x86_64.c ) s.files += %w( third_party/boringssl/crypto/des/des.c ) s.files += %w( third_party/boringssl/crypto/dh/check.c ) s.files += %w( third_party/boringssl/crypto/dh/dh.c ) s.files += %w( third_party/boringssl/crypto/dh/dh_asn1.c ) s.files += %w( third_party/boringssl/crypto/dh/params.c ) s.files += %w( third_party/boringssl/crypto/digest/digest.c ) s.files += %w( third_party/boringssl/crypto/digest/digests.c ) s.files += %w( third_party/boringssl/crypto/dsa/dsa.c ) s.files += %w( third_party/boringssl/crypto/dsa/dsa_asn1.c ) s.files += %w( third_party/boringssl/crypto/ec/ec.c ) s.files += %w( third_party/boringssl/crypto/ec/ec_asn1.c ) s.files += %w( third_party/boringssl/crypto/ec/ec_key.c ) s.files += %w( third_party/boringssl/crypto/ec/ec_montgomery.c ) s.files += %w( third_party/boringssl/crypto/ec/oct.c ) s.files += %w( third_party/boringssl/crypto/ec/p224-64.c ) s.files += %w( third_party/boringssl/crypto/ec/p256-64.c ) s.files += %w( third_party/boringssl/crypto/ec/p256-x86_64.c ) s.files += %w( third_party/boringssl/crypto/ec/simple.c ) s.files += %w( third_party/boringssl/crypto/ec/util-64.c ) s.files += %w( third_party/boringssl/crypto/ec/wnaf.c ) s.files += %w( third_party/boringssl/crypto/ecdh/ecdh.c ) s.files += %w( third_party/boringssl/crypto/ecdsa/ecdsa.c ) s.files += %w( third_party/boringssl/crypto/ecdsa/ecdsa_asn1.c ) s.files += %w( third_party/boringssl/crypto/engine/engine.c ) s.files += %w( third_party/boringssl/crypto/err/err.c ) s.files += %w( third_party/boringssl/crypto/evp/digestsign.c ) s.files += %w( third_party/boringssl/crypto/evp/evp.c ) s.files += %w( third_party/boringssl/crypto/evp/evp_asn1.c ) s.files += %w( third_party/boringssl/crypto/evp/evp_ctx.c ) s.files += %w( third_party/boringssl/crypto/evp/p_dsa_asn1.c ) s.files += %w( third_party/boringssl/crypto/evp/p_ec.c ) s.files += %w( third_party/boringssl/crypto/evp/p_ec_asn1.c ) s.files += %w( third_party/boringssl/crypto/evp/p_rsa.c ) s.files += %w( third_party/boringssl/crypto/evp/p_rsa_asn1.c ) s.files += %w( third_party/boringssl/crypto/evp/pbkdf.c ) s.files += %w( third_party/boringssl/crypto/evp/print.c ) s.files += %w( third_party/boringssl/crypto/evp/sign.c ) s.files += %w( third_party/boringssl/crypto/ex_data.c ) s.files += %w( third_party/boringssl/crypto/hkdf/hkdf.c ) s.files += %w( third_party/boringssl/crypto/hmac/hmac.c ) s.files += %w( third_party/boringssl/crypto/lhash/lhash.c ) s.files += %w( third_party/boringssl/crypto/md4/md4.c ) s.files += %w( third_party/boringssl/crypto/md5/md5.c ) s.files += %w( third_party/boringssl/crypto/mem.c ) s.files += %w( third_party/boringssl/crypto/modes/cbc.c ) s.files += %w( third_party/boringssl/crypto/modes/cfb.c ) s.files += %w( third_party/boringssl/crypto/modes/ctr.c ) s.files += %w( third_party/boringssl/crypto/modes/gcm.c ) s.files += %w( third_party/boringssl/crypto/modes/ofb.c ) s.files += %w( third_party/boringssl/crypto/newhope/error_correction.c ) s.files += %w( third_party/boringssl/crypto/newhope/newhope.c ) s.files += %w( third_party/boringssl/crypto/newhope/ntt.c ) s.files += %w( third_party/boringssl/crypto/newhope/poly.c ) s.files += %w( third_party/boringssl/crypto/newhope/precomp.c ) s.files += %w( third_party/boringssl/crypto/newhope/reduce.c ) s.files += %w( third_party/boringssl/crypto/obj/obj.c ) s.files += %w( third_party/boringssl/crypto/obj/obj_xref.c ) s.files += %w( third_party/boringssl/crypto/pem/pem_all.c ) s.files += %w( third_party/boringssl/crypto/pem/pem_info.c ) s.files += %w( third_party/boringssl/crypto/pem/pem_lib.c ) s.files += %w( third_party/boringssl/crypto/pem/pem_oth.c ) s.files += %w( third_party/boringssl/crypto/pem/pem_pk8.c ) s.files += %w( third_party/boringssl/crypto/pem/pem_pkey.c ) s.files += %w( third_party/boringssl/crypto/pem/pem_x509.c ) s.files += %w( third_party/boringssl/crypto/pem/pem_xaux.c ) s.files += %w( third_party/boringssl/crypto/pkcs8/p5_pbe.c ) s.files += %w( third_party/boringssl/crypto/pkcs8/p5_pbev2.c ) s.files += %w( third_party/boringssl/crypto/pkcs8/p8_pkey.c ) s.files += %w( third_party/boringssl/crypto/pkcs8/pkcs8.c ) s.files += %w( third_party/boringssl/crypto/poly1305/poly1305.c ) s.files += %w( third_party/boringssl/crypto/poly1305/poly1305_arm.c ) s.files += %w( third_party/boringssl/crypto/poly1305/poly1305_vec.c ) s.files += %w( third_party/boringssl/crypto/rand/deterministic.c ) s.files += %w( third_party/boringssl/crypto/rand/rand.c ) s.files += %w( third_party/boringssl/crypto/rand/urandom.c ) s.files += %w( third_party/boringssl/crypto/rand/windows.c ) s.files += %w( third_party/boringssl/crypto/rc4/rc4.c ) s.files += %w( third_party/boringssl/crypto/refcount_c11.c ) s.files += %w( third_party/boringssl/crypto/refcount_lock.c ) s.files += %w( third_party/boringssl/crypto/rsa/blinding.c ) s.files += %w( third_party/boringssl/crypto/rsa/padding.c ) s.files += %w( third_party/boringssl/crypto/rsa/rsa.c ) s.files += %w( third_party/boringssl/crypto/rsa/rsa_asn1.c ) s.files += %w( third_party/boringssl/crypto/rsa/rsa_impl.c ) s.files += %w( third_party/boringssl/crypto/sha/sha1.c ) s.files += %w( third_party/boringssl/crypto/sha/sha256.c ) s.files += %w( third_party/boringssl/crypto/sha/sha512.c ) s.files += %w( third_party/boringssl/crypto/stack/stack.c ) s.files += %w( third_party/boringssl/crypto/thread.c ) s.files += %w( third_party/boringssl/crypto/thread_none.c ) s.files += %w( third_party/boringssl/crypto/thread_pthread.c ) s.files += %w( third_party/boringssl/crypto/thread_win.c ) s.files += %w( third_party/boringssl/crypto/time_support.c ) s.files += %w( third_party/boringssl/crypto/x509/a_digest.c ) s.files += %w( third_party/boringssl/crypto/x509/a_sign.c ) s.files += %w( third_party/boringssl/crypto/x509/a_strex.c ) s.files += %w( third_party/boringssl/crypto/x509/a_verify.c ) s.files += %w( third_party/boringssl/crypto/x509/algorithm.c ) s.files += %w( third_party/boringssl/crypto/x509/asn1_gen.c ) s.files += %w( third_party/boringssl/crypto/x509/by_dir.c ) s.files += %w( third_party/boringssl/crypto/x509/by_file.c ) s.files += %w( third_party/boringssl/crypto/x509/i2d_pr.c ) s.files += %w( third_party/boringssl/crypto/x509/pkcs7.c ) s.files += %w( third_party/boringssl/crypto/x509/rsa_pss.c ) s.files += %w( third_party/boringssl/crypto/x509/t_crl.c ) s.files += %w( third_party/boringssl/crypto/x509/t_req.c ) s.files += %w( third_party/boringssl/crypto/x509/t_x509.c ) s.files += %w( third_party/boringssl/crypto/x509/t_x509a.c ) s.files += %w( third_party/boringssl/crypto/x509/x509.c ) s.files += %w( third_party/boringssl/crypto/x509/x509_att.c ) s.files += %w( third_party/boringssl/crypto/x509/x509_cmp.c ) s.files += %w( third_party/boringssl/crypto/x509/x509_d2.c ) s.files += %w( third_party/boringssl/crypto/x509/x509_def.c ) s.files += %w( third_party/boringssl/crypto/x509/x509_ext.c ) s.files += %w( third_party/boringssl/crypto/x509/x509_lu.c ) s.files += %w( third_party/boringssl/crypto/x509/x509_obj.c ) s.files += %w( third_party/boringssl/crypto/x509/x509_r2x.c ) s.files += %w( third_party/boringssl/crypto/x509/x509_req.c ) s.files += %w( third_party/boringssl/crypto/x509/x509_set.c ) s.files += %w( third_party/boringssl/crypto/x509/x509_trs.c ) s.files += %w( third_party/boringssl/crypto/x509/x509_txt.c ) s.files += %w( third_party/boringssl/crypto/x509/x509_v3.c ) s.files += %w( third_party/boringssl/crypto/x509/x509_vfy.c ) s.files += %w( third_party/boringssl/crypto/x509/x509_vpm.c ) s.files += %w( third_party/boringssl/crypto/x509/x509cset.c ) s.files += %w( third_party/boringssl/crypto/x509/x509name.c ) s.files += %w( third_party/boringssl/crypto/x509/x509rset.c ) s.files += %w( third_party/boringssl/crypto/x509/x509spki.c ) s.files += %w( third_party/boringssl/crypto/x509/x509type.c ) s.files += %w( third_party/boringssl/crypto/x509/x_algor.c ) s.files += %w( third_party/boringssl/crypto/x509/x_all.c ) s.files += %w( third_party/boringssl/crypto/x509/x_attrib.c ) s.files += %w( third_party/boringssl/crypto/x509/x_crl.c ) s.files += %w( third_party/boringssl/crypto/x509/x_exten.c ) s.files += %w( third_party/boringssl/crypto/x509/x_info.c ) s.files += %w( third_party/boringssl/crypto/x509/x_name.c ) s.files += %w( third_party/boringssl/crypto/x509/x_pkey.c ) s.files += %w( third_party/boringssl/crypto/x509/x_pubkey.c ) s.files += %w( third_party/boringssl/crypto/x509/x_req.c ) s.files += %w( third_party/boringssl/crypto/x509/x_sig.c ) s.files += %w( third_party/boringssl/crypto/x509/x_spki.c ) s.files += %w( third_party/boringssl/crypto/x509/x_val.c ) s.files += %w( third_party/boringssl/crypto/x509/x_x509.c ) s.files += %w( third_party/boringssl/crypto/x509/x_x509a.c ) s.files += %w( third_party/boringssl/crypto/x509v3/pcy_cache.c ) s.files += %w( third_party/boringssl/crypto/x509v3/pcy_data.c ) s.files += %w( third_party/boringssl/crypto/x509v3/pcy_lib.c ) s.files += %w( third_party/boringssl/crypto/x509v3/pcy_map.c ) s.files += %w( third_party/boringssl/crypto/x509v3/pcy_node.c ) s.files += %w( third_party/boringssl/crypto/x509v3/pcy_tree.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_akey.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_akeya.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_alt.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_bcons.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_bitst.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_conf.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_cpols.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_crld.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_enum.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_extku.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_genn.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_ia5.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_info.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_int.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_lib.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_ncons.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_pci.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_pcia.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_pcons.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_pku.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_pmaps.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_prn.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_purp.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_skey.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_sxnet.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_utl.c ) s.files += %w( third_party/boringssl/ssl/custom_extensions.c ) s.files += %w( third_party/boringssl/ssl/d1_both.c ) s.files += %w( third_party/boringssl/ssl/d1_lib.c ) s.files += %w( third_party/boringssl/ssl/d1_pkt.c ) s.files += %w( third_party/boringssl/ssl/d1_srtp.c ) s.files += %w( third_party/boringssl/ssl/dtls_method.c ) s.files += %w( third_party/boringssl/ssl/dtls_record.c ) s.files += %w( third_party/boringssl/ssl/handshake_client.c ) s.files += %w( third_party/boringssl/ssl/handshake_server.c ) s.files += %w( third_party/boringssl/ssl/s3_both.c ) s.files += %w( third_party/boringssl/ssl/s3_enc.c ) s.files += %w( third_party/boringssl/ssl/s3_lib.c ) s.files += %w( third_party/boringssl/ssl/s3_pkt.c ) s.files += %w( third_party/boringssl/ssl/ssl_aead_ctx.c ) s.files += %w( third_party/boringssl/ssl/ssl_asn1.c ) s.files += %w( third_party/boringssl/ssl/ssl_buffer.c ) s.files += %w( third_party/boringssl/ssl/ssl_cert.c ) s.files += %w( third_party/boringssl/ssl/ssl_cipher.c ) s.files += %w( third_party/boringssl/ssl/ssl_ecdh.c ) s.files += %w( third_party/boringssl/ssl/ssl_file.c ) s.files += %w( third_party/boringssl/ssl/ssl_lib.c ) s.files += %w( third_party/boringssl/ssl/ssl_rsa.c ) s.files += %w( third_party/boringssl/ssl/ssl_session.c ) s.files += %w( third_party/boringssl/ssl/ssl_stat.c ) s.files += %w( third_party/boringssl/ssl/t1_enc.c ) s.files += %w( third_party/boringssl/ssl/t1_lib.c ) s.files += %w( third_party/boringssl/ssl/tls13_both.c ) s.files += %w( third_party/boringssl/ssl/tls13_client.c ) s.files += %w( third_party/boringssl/ssl/tls13_enc.c ) s.files += %w( third_party/boringssl/ssl/tls13_server.c ) s.files += %w( third_party/boringssl/ssl/tls_method.c ) s.files += %w( third_party/boringssl/ssl/tls_record.c ) s.files += %w( third_party/zlib/crc32.h ) s.files += %w( third_party/zlib/deflate.h ) s.files += %w( third_party/zlib/gzguts.h ) s.files += %w( third_party/zlib/inffast.h ) s.files += %w( third_party/zlib/inffixed.h ) s.files += %w( third_party/zlib/inflate.h ) s.files += %w( third_party/zlib/inftrees.h ) s.files += %w( third_party/zlib/trees.h ) s.files += %w( third_party/zlib/zconf.h ) s.files += %w( third_party/zlib/zlib.h ) s.files += %w( third_party/zlib/zutil.h ) s.files += %w( third_party/zlib/adler32.c ) s.files += %w( third_party/zlib/compress.c ) s.files += %w( third_party/zlib/crc32.c ) s.files += %w( third_party/zlib/deflate.c ) s.files += %w( third_party/zlib/gzclose.c ) s.files += %w( third_party/zlib/gzlib.c ) s.files += %w( third_party/zlib/gzread.c ) s.files += %w( third_party/zlib/gzwrite.c ) s.files += %w( third_party/zlib/infback.c ) s.files += %w( third_party/zlib/inffast.c ) s.files += %w( third_party/zlib/inflate.c ) s.files += %w( third_party/zlib/inftrees.c ) s.files += %w( third_party/zlib/trees.c ) s.files += %w( third_party/zlib/uncompr.c ) s.files += %w( third_party/zlib/zutil.c ) s.files += %w( third_party/cares/cares/ares.h ) s.files += %w( third_party/cares/cares/ares_data.h ) s.files += %w( third_party/cares/cares/ares_dns.h ) s.files += %w( third_party/cares/cares/ares_getenv.h ) s.files += %w( third_party/cares/cares/ares_getopt.h ) s.files += %w( third_party/cares/cares/ares_inet_net_pton.h ) s.files += %w( third_party/cares/cares/ares_iphlpapi.h ) s.files += %w( third_party/cares/cares/ares_ipv6.h ) s.files += %w( third_party/cares/cares/ares_library_init.h ) s.files += %w( third_party/cares/cares/ares_llist.h ) s.files += %w( third_party/cares/cares/ares_nowarn.h ) s.files += %w( third_party/cares/cares/ares_platform.h ) s.files += %w( third_party/cares/cares/ares_private.h ) s.files += %w( third_party/cares/cares/ares_rules.h ) s.files += %w( third_party/cares/cares/ares_setup.h ) s.files += %w( third_party/cares/cares/ares_strcasecmp.h ) s.files += %w( third_party/cares/cares/ares_strdup.h ) s.files += %w( third_party/cares/cares/ares_version.h ) s.files += %w( third_party/cares/cares/bitncmp.h ) s.files += %w( third_party/cares/cares/config-win32.h ) s.files += %w( third_party/cares/cares/setup_once.h ) s.files += %w( third_party/cares/ares_build.h ) s.files += %w( third_party/cares/config_linux/ares_config.h ) s.files += %w( third_party/cares/config_darwin/ares_config.h ) s.files += %w( third_party/cares/cares/ares__close_sockets.c ) s.files += %w( third_party/cares/cares/ares__get_hostent.c ) s.files += %w( third_party/cares/cares/ares__read_line.c ) s.files += %w( third_party/cares/cares/ares__timeval.c ) s.files += %w( third_party/cares/cares/ares_cancel.c ) s.files += %w( third_party/cares/cares/ares_create_query.c ) s.files += %w( third_party/cares/cares/ares_data.c ) s.files += %w( third_party/cares/cares/ares_destroy.c ) s.files += %w( third_party/cares/cares/ares_expand_name.c ) s.files += %w( third_party/cares/cares/ares_expand_string.c ) s.files += %w( third_party/cares/cares/ares_fds.c ) s.files += %w( third_party/cares/cares/ares_free_hostent.c ) s.files += %w( third_party/cares/cares/ares_free_string.c ) s.files += %w( third_party/cares/cares/ares_getenv.c ) s.files += %w( third_party/cares/cares/ares_gethostbyaddr.c ) s.files += %w( third_party/cares/cares/ares_gethostbyname.c ) s.files += %w( third_party/cares/cares/ares_getnameinfo.c ) s.files += %w( third_party/cares/cares/ares_getopt.c ) s.files += %w( third_party/cares/cares/ares_getsock.c ) s.files += %w( third_party/cares/cares/ares_init.c ) s.files += %w( third_party/cares/cares/ares_library_init.c ) s.files += %w( third_party/cares/cares/ares_llist.c ) s.files += %w( third_party/cares/cares/ares_mkquery.c ) s.files += %w( third_party/cares/cares/ares_nowarn.c ) s.files += %w( third_party/cares/cares/ares_options.c ) s.files += %w( third_party/cares/cares/ares_parse_a_reply.c ) s.files += %w( third_party/cares/cares/ares_parse_aaaa_reply.c ) s.files += %w( third_party/cares/cares/ares_parse_mx_reply.c ) s.files += %w( third_party/cares/cares/ares_parse_naptr_reply.c ) s.files += %w( third_party/cares/cares/ares_parse_ns_reply.c ) s.files += %w( third_party/cares/cares/ares_parse_ptr_reply.c ) s.files += %w( third_party/cares/cares/ares_parse_soa_reply.c ) s.files += %w( third_party/cares/cares/ares_parse_srv_reply.c ) s.files += %w( third_party/cares/cares/ares_parse_txt_reply.c ) s.files += %w( third_party/cares/cares/ares_platform.c ) s.files += %w( third_party/cares/cares/ares_process.c ) s.files += %w( third_party/cares/cares/ares_query.c ) s.files += %w( third_party/cares/cares/ares_search.c ) s.files += %w( third_party/cares/cares/ares_send.c ) s.files += %w( third_party/cares/cares/ares_strcasecmp.c ) s.files += %w( third_party/cares/cares/ares_strdup.c ) s.files += %w( third_party/cares/cares/ares_strerror.c ) s.files += %w( third_party/cares/cares/ares_timeout.c ) s.files += %w( third_party/cares/cares/ares_version.c ) s.files += %w( third_party/cares/cares/ares_writev.c ) s.files += %w( third_party/cares/cares/bitncmp.c ) s.files += %w( third_party/cares/cares/inet_net_pton.c ) s.files += %w( third_party/cares/cares/inet_ntop.c ) s.files += %w( third_party/cares/cares/windows_port.c ) end grpc-1.3.2/include/000077500000000000000000000000001310511640000140625ustar00rootroot00000000000000grpc-1.3.2/include/grpc++/000077500000000000000000000000001310511640000151435ustar00rootroot00000000000000grpc-1.3.2/include/grpc++/alarm.h000066400000000000000000000070441310511640000164150ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /// An Alarm posts the user provided tag to its associated completion queue upon /// expiry or cancellation. #ifndef GRPCXX_ALARM_H #define GRPCXX_ALARM_H #include #include #include #include #include #include struct grpc_alarm; namespace grpc { class CompletionQueue; /// A thin wrapper around \a grpc_alarm (see / \a / src/core/surface/alarm.h). class Alarm : private GrpcLibraryCodegen { public: /// Create a completion queue alarm instance associated to \a cq. /// /// Once the alarm expires (at \a deadline) or it's cancelled (see \a Cancel), /// an event with tag \a tag will be added to \a cq. If the alarm expired, the /// event's success bit will be true, false otherwise (ie, upon cancellation). /// \internal We rely on the presence of \a cq for grpc initialization. If \a /// cq were ever to be removed, a reference to a static /// internal::GrpcLibraryInitializer instance would need to be introduced /// here. \endinternal. template Alarm(CompletionQueue* cq, const T& deadline, void* tag) : tag_(tag), alarm_(grpc_alarm_create(cq->cq(), TimePoint(deadline).raw_time(), static_cast(&tag_))) {} /// Destroy the given completion queue alarm, cancelling it in the process. ~Alarm() { grpc_alarm_destroy(alarm_); } /// Cancel a completion queue alarm. Calling this function over an alarm that /// has already fired has no effect. void Cancel() { grpc_alarm_cancel(alarm_); } private: class AlarmEntry : public CompletionQueueTag { public: AlarmEntry(void* tag) : tag_(tag) {} bool FinalizeResult(void** tag, bool* status) override { *tag = tag_; return true; } private: void* tag_; }; AlarmEntry tag_; grpc_alarm* const alarm_; // owned }; } // namespace grpc #endif // GRPCXX_ALARM_H grpc-1.3.2/include/grpc++/channel.h000066400000000000000000000074401310511640000167310ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_CHANNEL_H #define GRPCXX_CHANNEL_H #include #include #include #include #include #include struct grpc_channel; namespace grpc { /// Channels represent a connection to an endpoint. Created by \a CreateChannel. class Channel final : public ChannelInterface, public CallHook, public std::enable_shared_from_this, private GrpcLibraryCodegen { public: ~Channel(); /// Get the current channel state. If the channel is in IDLE and /// \a try_to_connect is set to true, try to connect. grpc_connectivity_state GetState(bool try_to_connect) override; /// Returns the LB policy name, or the empty string if not yet available. grpc::string GetLoadBalancingPolicyName() const; /// Returns the service config in JSON form, or the empty string if /// not available. grpc::string GetServiceConfigJSON() const; private: template friend Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method, ClientContext* context, const InputMessage& request, OutputMessage* result); friend std::shared_ptr CreateChannelInternal( const grpc::string& host, grpc_channel* c_channel); Channel(const grpc::string& host, grpc_channel* c_channel); Call CreateCall(const RpcMethod& method, ClientContext* context, CompletionQueue* cq) override; void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) override; void* RegisterMethod(const char* method) override; void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline, CompletionQueue* cq, void* tag) override; bool WaitForStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline) override; const grpc::string host_; grpc_channel* const c_channel_; // owned }; } // namespace grpc #endif // GRPCXX_CHANNEL_H grpc-1.3.2/include/grpc++/client_context.h000066400000000000000000000045451310511640000203460ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /// A ClientContext allows the person implementing a service client to: /// /// - Add custom metadata key-value pairs that will propagated to the server /// side. /// - Control call settings such as compression and authentication. /// - Initial and trailing metadata coming from the server. /// - Get performance metrics (ie, census). /// /// Context settings are only relevant to the call they are invoked with, that /// is to say, they aren't sticky. Some of these settings, such as the /// compression options, can be made persistant at channel construction time /// (see \a grpc::CreateCustomChannel). /// /// \warning ClientContext instances should \em not be reused across rpcs. #ifndef GRPCXX_CLIENT_CONTEXT_H #define GRPCXX_CLIENT_CONTEXT_H #include #endif // GRPCXX_CLIENT_CONTEXT_H grpc-1.3.2/include/grpc++/completion_queue.h000066400000000000000000000032771310511640000207020ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_COMPLETION_QUEUE_H #define GRPCXX_COMPLETION_QUEUE_H #include #endif // GRPCXX_COMPLETION_QUEUE_H grpc-1.3.2/include/grpc++/create_channel.h000066400000000000000000000054311310511640000202520ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_CREATE_CHANNEL_H #define GRPCXX_CREATE_CHANNEL_H #include #include #include #include #include namespace grpc { /// Create a new \a Channel pointing to \a target /// /// \param target The URI of the endpoint to connect to. /// \param creds Credentials to use for the created channel. If it does not hold /// an object or is invalid, a lame channel is returned. std::shared_ptr CreateChannel( const grpc::string& target, const std::shared_ptr& creds); /// Create a new \em custom \a Channel pointing to \a target /// /// \warning For advanced use and testing ONLY. Override default channel /// arguments only if necessary. /// /// \param target The URI of the endpoint to connect to. /// \param creds Credentials to use for the created channel. If it does not hold /// an object or is invalid, a lame channel is returned. /// \param args Options for channel creation. std::shared_ptr CreateCustomChannel( const grpc::string& target, const std::shared_ptr& creds, const ChannelArguments& args); } // namespace grpc #endif // GRPCXX_CREATE_CHANNEL_H grpc-1.3.2/include/grpc++/create_channel_posix.h000066400000000000000000000051201310511640000214670ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_CREATE_CHANNEL_POSIX_H #define GRPCXX_CREATE_CHANNEL_POSIX_H #include #include #include #include namespace grpc { #ifdef GPR_SUPPORT_CHANNELS_FROM_FD /// Create a new \a Channel communicating over given file descriptor /// /// \param target The name of the target. /// \param fd The file descriptor representing a socket. std::shared_ptr CreateInsecureChannelFromFd(const grpc::string& target, int fd); /// Create a new \a Channel communicating over given file descriptor with custom /// channel arguments /// /// \param target The name of the target. /// \param fd The file descriptor representing a socket. /// \param args Options for channel creation. std::shared_ptr CreateCustomInsecureChannelFromFd( const grpc::string& target, int fd, const ChannelArguments& args); #endif // GPR_SUPPORT_CHANNELS_FROM_FD } // namespace grpc #endif // GRPCXX_CREATE_CHANNEL_POSIX_H grpc-1.3.2/include/grpc++/ext/000077500000000000000000000000001310511640000157435ustar00rootroot00000000000000grpc-1.3.2/include/grpc++/ext/health_check_service_server_builder_option.h000066400000000000000000000050041310511640000267210ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_EXT_HEALTH_CHECK_SERVICE_SERVER_BUILDER_OPTION_H #define GRPCXX_EXT_HEALTH_CHECK_SERVICE_SERVER_BUILDER_OPTION_H #include #include #include #include namespace grpc { class HealthCheckServiceServerBuilderOption : public ServerBuilderOption { public: // The ownership of hc will be taken and transferred to the grpc server. // To explicitly disable default service, pass in a nullptr. explicit HealthCheckServiceServerBuilderOption( std::unique_ptr hc); ~HealthCheckServiceServerBuilderOption() override {} void UpdateArguments(ChannelArguments* args) override; void UpdatePlugins( std::vector>* plugins) override; private: std::unique_ptr hc_; }; } // namespace grpc #endif // GRPCXX_EXT_HEALTH_CHECK_SERVICE_SERVER_BUILDER_OPTION_H grpc-1.3.2/include/grpc++/ext/proto_server_reflection_plugin.h000066400000000000000000000051531310511640000244410ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_EXT_PROTO_SERVER_REFLECTION_PLUGIN_H #define GRPCXX_EXT_PROTO_SERVER_REFLECTION_PLUGIN_H #include #include namespace grpc { class ServerInitializer; class ProtoServerReflection; } // namespace grpc namespace grpc { namespace reflection { class ProtoServerReflectionPlugin : public ::grpc::ServerBuilderPlugin { public: ProtoServerReflectionPlugin(); ::grpc::string name() override; void InitServer(::grpc::ServerInitializer* si) override; void Finish(::grpc::ServerInitializer* si) override; void ChangeArguments(const ::grpc::string& name, void* value) override; bool has_async_methods() const override; bool has_sync_methods() const override; private: std::shared_ptr reflection_service_; }; // Add proto reflection plugin to ServerBuilder. This function should be called // at the static initialization time. void InitProtoReflectionServerBuilderPlugin(); } // namespace reflection } // namespace grpc #endif // GRPCXX_EXT_PROTO_SERVER_REFLECTION_PLUGIN_H grpc-1.3.2/include/grpc++/generic/000077500000000000000000000000001310511640000165575ustar00rootroot00000000000000grpc-1.3.2/include/grpc++/generic/async_generic_service.h000066400000000000000000000050741310511640000232670ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_GENERIC_ASYNC_GENERIC_SERVICE_H #define GRPCXX_GENERIC_ASYNC_GENERIC_SERVICE_H #include #include struct grpc_server; namespace grpc { typedef ServerAsyncReaderWriter GenericServerAsyncReaderWriter; class GenericServerContext final : public ServerContext { public: const grpc::string& method() const { return method_; } const grpc::string& host() const { return host_; } private: friend class Server; friend class ServerInterface; grpc::string method_; grpc::string host_; }; class AsyncGenericService final { public: AsyncGenericService() : server_(nullptr) {} void RequestCall(GenericServerContext* ctx, GenericServerAsyncReaderWriter* reader_writer, CompletionQueue* call_cq, ServerCompletionQueue* notification_cq, void* tag); private: friend class Server; Server* server_; }; } // namespace grpc #endif // GRPCXX_GENERIC_ASYNC_GENERIC_SERVICE_H grpc-1.3.2/include/grpc++/generic/generic_stub.h000066400000000000000000000045251310511640000214070ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_GENERIC_GENERIC_STUB_H #define GRPCXX_GENERIC_GENERIC_STUB_H #include #include namespace grpc { class CompletionQueue; typedef ClientAsyncReaderWriter GenericClientAsyncReaderWriter; // Generic stubs provide a type-unsafe interface to call gRPC methods // by name. class GenericStub final { public: explicit GenericStub(std::shared_ptr channel) : channel_(channel) {} // begin a call to a named method std::unique_ptr Call( ClientContext* context, const grpc::string& method, CompletionQueue* cq, void* tag); private: std::shared_ptr channel_; }; } // namespace grpc #endif // GRPCXX_GENERIC_GENERIC_STUB_H grpc-1.3.2/include/grpc++/grpc++.h000066400000000000000000000062561310511640000164060ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /// \mainpage gRPC C++ API /// /// The gRPC C++ API mainly consists of the following classes: /// - grpc::Channel, which represents the connection to an endpoint. See [the /// gRPC Concepts page](http://www.grpc.io/docs/guides/concepts.html) for more /// details. Channels are created by the factory function grpc::CreateChannel. /// - grpc::CompletionQueue, the producer-consumer queue used for all /// asynchronous communication with the gRPC runtime. /// - grpc::ClientContext and grpc::ServerContext, where optional configuration /// for an RPC can be set, such as setting custom metadata to be conveyed to the /// peer, compression settings, authentication, etc. /// - grpc::Server, representing a gRPC server, created by grpc::ServerBuilder. /// /// Streaming calls are handled with the streaming classes in /// \ref sync_stream.h and /// \ref async_stream.h. /// /// Refer to the /// [examples](https://github.com/grpc/grpc/blob/master/examples/cpp) /// for code putting these pieces into play. #ifndef GRPCXX_GRPCXX_H #define GRPCXX_GRPCXX_H // Pragma for http://include-what-you-use.org/ tool, tells that following // headers are not private for grpc++.h and are part of its interface. // IWYU pragma: begin_exports #include #include #include #include #include #include #include #include #include #include // IWYU pragma: end_exports namespace grpc { grpc::string Version(); } // namespace grpc #endif // GRPCXX_GRPCXX_H grpc-1.3.2/include/grpc++/health_check_service_interface.h000066400000000000000000000052231310511640000234600ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_HEALTH_CHECK_SERVICE_INTERFACE_H #define GRPCXX_HEALTH_CHECK_SERVICE_INTERFACE_H #include namespace grpc { const char kHealthCheckServiceInterfaceArg[] = "grpc.health_check_service_interface"; // The gRPC server uses this interface to expose the health checking service // without depending on protobuf. class HealthCheckServiceInterface { public: virtual ~HealthCheckServiceInterface() {} // Set or change the serving status of the given service_name. virtual void SetServingStatus(const grpc::string& service_name, bool serving) = 0; // Apply to all registered service names. virtual void SetServingStatus(bool serving) = 0; }; // Enable/disable the default health checking service. This applies to all C++ // servers created afterwards. For each server, user can override the default // with a HealthCheckServiceServerBuilderOption. // NOT thread safe. void EnableDefaultHealthCheckService(bool enable); // NOT thread safe. bool DefaultHealthCheckServiceEnabled(); } // namespace grpc #endif // GRPCXX_HEALTH_CHECK_SERVICE_INTERFACE_H grpc-1.3.2/include/grpc++/impl/000077500000000000000000000000001310511640000161045ustar00rootroot00000000000000grpc-1.3.2/include/grpc++/impl/README.md000066400000000000000000000003001310511640000173540ustar00rootroot00000000000000**The APIs in this directory are not stable!** This directory contains header files that need to be installed but are not part of the public API. Users should not use these headers directly. grpc-1.3.2/include/grpc++/impl/call.h000066400000000000000000000032361310511640000171740ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CALL_H #define GRPCXX_IMPL_CALL_H #include #endif // GRPCXX_IMPL_CALL_H grpc-1.3.2/include/grpc++/impl/channel_argument_option.h000066400000000000000000000040751310511640000231650ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CHANNEL_ARGUMENT_OPTION_H #define GRPCXX_IMPL_CHANNEL_ARGUMENT_OPTION_H #include #include #include #include namespace grpc { std::unique_ptr MakeChannelArgumentOption( const grpc::string &name, const grpc::string &value); std::unique_ptr MakeChannelArgumentOption( const grpc::string &name, int value); } // namespace grpc #endif // GRPCXX_IMPL_CHANNEL_ARGUMENT_OPTION_H grpc-1.3.2/include/grpc++/impl/client_unary_call.h000066400000000000000000000033221310511640000217440ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CLIENT_UNARY_CALL_H #define GRPCXX_IMPL_CLIENT_UNARY_CALL_H #include #endif // GRPCXX_IMPL_CLIENT_UNARY_CALL_H grpc-1.3.2/include/grpc++/impl/codegen/000077500000000000000000000000001310511640000175105ustar00rootroot00000000000000grpc-1.3.2/include/grpc++/impl/codegen/async_stream.h000066400000000000000000000603341310511640000223570ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_ASYNC_STREAM_H #define GRPCXX_IMPL_CODEGEN_ASYNC_STREAM_H #include #include #include #include #include #include namespace grpc { class CompletionQueue; /// Common interface for all client side asynchronous streaming. class ClientAsyncStreamingInterface { public: virtual ~ClientAsyncStreamingInterface() {} /// Request notification of the reading of the initial metadata. Completion /// will be notified by \a tag on the associated completion queue. /// This call is optional, but if it is used, it cannot be used concurrently /// with or after the \a Read method. /// /// \param[in] tag Tag identifying this request. virtual void ReadInitialMetadata(void* tag) = 0; /// Indicate that the stream is to be finished and request notification /// Should not be used concurrently with other operations /// /// \param[out] status To be updated with the operation status. /// \param[in] tag Tag identifying this request. virtual void Finish(Status* status, void* tag) = 0; }; /// An interface that yields a sequence of messages of type \a R. template class AsyncReaderInterface { public: virtual ~AsyncReaderInterface() {} /// Read a message of type \a R into \a msg. Completion will be notified by \a /// tag on the associated completion queue. /// This is thread-safe with respect to \a Write or \a WritesDone methods. It /// should not be called concurrently with other streaming APIs /// on the same stream. It is not meaningful to call it concurrently /// with another \a Read on the same stream since reads on the same stream /// are delivered in order. /// /// \param[out] msg Where to eventually store the read message. /// \param[in] tag The tag identifying the operation. virtual void Read(R* msg, void* tag) = 0; }; /// An interface that can be fed a sequence of messages of type \a W. template class AsyncWriterInterface { public: virtual ~AsyncWriterInterface() {} /// Request the writing of \a msg with identifying tag \a tag. /// /// Only one write may be outstanding at any given time. This means that /// after calling Write, one must wait to receive \a tag from the completion /// queue BEFORE calling Write again. /// This is thread-safe with respect to \a Read /// /// \param[in] msg The message to be written. /// \param[in] tag The tag identifying the operation. virtual void Write(const W& msg, void* tag) = 0; /// Request the writing of \a msg using WriteOptions \a options with /// identifying tag \a tag. /// /// Only one write may be outstanding at any given time. This means that /// after calling Write, one must wait to receive \a tag from the completion /// queue BEFORE calling Write again. /// WriteOptions \a options is used to set the write options of this message. /// This is thread-safe with respect to \a Read /// /// \param[in] msg The message to be written. /// \param[in] options The WriteOptions to be used to write this message. /// \param[in] tag The tag identifying the operation. virtual void Write(const W& msg, WriteOptions options, void* tag) = 0; /// Request the writing of \a msg and coalesce it with the writing /// of trailing metadata, using WriteOptions \a options with identifying tag /// \a tag. /// /// For client, WriteLast is equivalent of performing Write and WritesDone in /// a single step. /// For server, WriteLast buffers the \a msg. The writing of \a msg is held /// until Finish is called, where \a msg and trailing metadata are coalesced /// and write is initiated. Note that WriteLast can only buffer \a msg up to /// the flow control window size. If \a msg size is larger than the window /// size, it will be sent on wire without buffering. /// /// \param[in] msg The message to be written. /// \param[in] options The WriteOptions to be used to write this message. /// \param[in] tag The tag identifying the operation. void WriteLast(const W& msg, WriteOptions options, void* tag) { Write(msg, options.set_last_message(), tag); } }; template class ClientAsyncReaderInterface : public ClientAsyncStreamingInterface, public AsyncReaderInterface {}; template class ClientAsyncReader final : public ClientAsyncReaderInterface { public: /// Create a stream and write the first request out. template ClientAsyncReader(ChannelInterface* channel, CompletionQueue* cq, const RpcMethod& method, ClientContext* context, const W& request, void* tag) : context_(context), call_(channel->CreateCall(method, context, cq)) { init_ops_.set_output_tag(tag); init_ops_.SendInitialMetadata(context->send_initial_metadata_, context->initial_metadata_flags()); // TODO(ctiller): don't assert GPR_CODEGEN_ASSERT(init_ops_.SendMessage(request).ok()); init_ops_.ClientSendClose(); call_.PerformOps(&init_ops_); } void ReadInitialMetadata(void* tag) override { GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_); meta_ops_.set_output_tag(tag); meta_ops_.RecvInitialMetadata(context_); call_.PerformOps(&meta_ops_); } void Read(R* msg, void* tag) override { read_ops_.set_output_tag(tag); if (!context_->initial_metadata_received_) { read_ops_.RecvInitialMetadata(context_); } read_ops_.RecvMessage(msg); call_.PerformOps(&read_ops_); } void Finish(Status* status, void* tag) override { finish_ops_.set_output_tag(tag); if (!context_->initial_metadata_received_) { finish_ops_.RecvInitialMetadata(context_); } finish_ops_.ClientRecvStatus(context_, status); call_.PerformOps(&finish_ops_); } private: ClientContext* context_; Call call_; CallOpSet init_ops_; CallOpSet meta_ops_; CallOpSet> read_ops_; CallOpSet finish_ops_; }; /// Common interface for client side asynchronous writing. template class ClientAsyncWriterInterface : public ClientAsyncStreamingInterface, public AsyncWriterInterface { public: /// Signal the client is done with the writes. /// Thread-safe with respect to \a Read /// /// \param[in] tag The tag identifying the operation. virtual void WritesDone(void* tag) = 0; }; template class ClientAsyncWriter final : public ClientAsyncWriterInterface { public: template ClientAsyncWriter(ChannelInterface* channel, CompletionQueue* cq, const RpcMethod& method, ClientContext* context, R* response, void* tag) : context_(context), call_(channel->CreateCall(method, context, cq)) { finish_ops_.RecvMessage(response); finish_ops_.AllowNoMessage(); // if corked bit is set in context, we buffer up the initial metadata to // coalesce with later message to be sent. No op is performed. if (context_->initial_metadata_corked_) { write_ops_.SendInitialMetadata(context->send_initial_metadata_, context->initial_metadata_flags()); } else { write_ops_.set_output_tag(tag); write_ops_.SendInitialMetadata(context->send_initial_metadata_, context->initial_metadata_flags()); call_.PerformOps(&write_ops_); } } void ReadInitialMetadata(void* tag) override { GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_); meta_ops_.set_output_tag(tag); meta_ops_.RecvInitialMetadata(context_); call_.PerformOps(&meta_ops_); } void Write(const W& msg, void* tag) override { write_ops_.set_output_tag(tag); // TODO(ctiller): don't assert GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok()); call_.PerformOps(&write_ops_); } void Write(const W& msg, WriteOptions options, void* tag) override { write_ops_.set_output_tag(tag); if (options.is_last_message()) { options.set_buffer_hint(); write_ops_.ClientSendClose(); } // TODO(ctiller): don't assert GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok()); call_.PerformOps(&write_ops_); } void WritesDone(void* tag) override { write_ops_.set_output_tag(tag); write_ops_.ClientSendClose(); call_.PerformOps(&write_ops_); } void Finish(Status* status, void* tag) override { finish_ops_.set_output_tag(tag); if (!context_->initial_metadata_received_) { finish_ops_.RecvInitialMetadata(context_); } finish_ops_.ClientRecvStatus(context_, status); call_.PerformOps(&finish_ops_); } private: ClientContext* context_; Call call_; CallOpSet meta_ops_; CallOpSet write_ops_; CallOpSet finish_ops_; }; /// Client-side interface for asynchronous bi-directional streaming. template class ClientAsyncReaderWriterInterface : public ClientAsyncStreamingInterface, public AsyncWriterInterface, public AsyncReaderInterface { public: /// Signal the client is done with the writes. /// Thread-safe with respect to \a Read /// /// \param[in] tag The tag identifying the operation. virtual void WritesDone(void* tag) = 0; }; template class ClientAsyncReaderWriter final : public ClientAsyncReaderWriterInterface { public: ClientAsyncReaderWriter(ChannelInterface* channel, CompletionQueue* cq, const RpcMethod& method, ClientContext* context, void* tag) : context_(context), call_(channel->CreateCall(method, context, cq)) { if (context_->initial_metadata_corked_) { // if corked bit is set in context, we buffer up the initial metadata to // coalesce with later message to be sent. No op is performed. write_ops_.SendInitialMetadata(context->send_initial_metadata_, context->initial_metadata_flags()); } else { write_ops_.set_output_tag(tag); write_ops_.SendInitialMetadata(context->send_initial_metadata_, context->initial_metadata_flags()); call_.PerformOps(&write_ops_); } } void ReadInitialMetadata(void* tag) override { GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_); meta_ops_.set_output_tag(tag); meta_ops_.RecvInitialMetadata(context_); call_.PerformOps(&meta_ops_); } void Read(R* msg, void* tag) override { read_ops_.set_output_tag(tag); if (!context_->initial_metadata_received_) { read_ops_.RecvInitialMetadata(context_); } read_ops_.RecvMessage(msg); call_.PerformOps(&read_ops_); } void Write(const W& msg, void* tag) override { write_ops_.set_output_tag(tag); // TODO(ctiller): don't assert GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok()); call_.PerformOps(&write_ops_); } void Write(const W& msg, WriteOptions options, void* tag) override { write_ops_.set_output_tag(tag); if (options.is_last_message()) { options.set_buffer_hint(); write_ops_.ClientSendClose(); } // TODO(ctiller): don't assert GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok()); call_.PerformOps(&write_ops_); } void WritesDone(void* tag) override { write_ops_.set_output_tag(tag); write_ops_.ClientSendClose(); call_.PerformOps(&write_ops_); } void Finish(Status* status, void* tag) override { finish_ops_.set_output_tag(tag); if (!context_->initial_metadata_received_) { finish_ops_.RecvInitialMetadata(context_); } finish_ops_.ClientRecvStatus(context_, status); call_.PerformOps(&finish_ops_); } private: ClientContext* context_; Call call_; CallOpSet meta_ops_; CallOpSet> read_ops_; CallOpSet write_ops_; CallOpSet finish_ops_; }; template class ServerAsyncReaderInterface : public ServerAsyncStreamingInterface, public AsyncReaderInterface { public: virtual void Finish(const W& msg, const Status& status, void* tag) = 0; virtual void FinishWithError(const Status& status, void* tag) = 0; }; template class ServerAsyncReader final : public ServerAsyncReaderInterface { public: explicit ServerAsyncReader(ServerContext* ctx) : call_(nullptr, nullptr, nullptr), ctx_(ctx) {} void SendInitialMetadata(void* tag) override { GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_); meta_ops_.set_output_tag(tag); meta_ops_.SendInitialMetadata(ctx_->initial_metadata_, ctx_->initial_metadata_flags()); if (ctx_->compression_level_set()) { meta_ops_.set_compression_level(ctx_->compression_level()); } ctx_->sent_initial_metadata_ = true; call_.PerformOps(&meta_ops_); } void Read(R* msg, void* tag) override { read_ops_.set_output_tag(tag); read_ops_.RecvMessage(msg); call_.PerformOps(&read_ops_); } void Finish(const W& msg, const Status& status, void* tag) override { finish_ops_.set_output_tag(tag); if (!ctx_->sent_initial_metadata_) { finish_ops_.SendInitialMetadata(ctx_->initial_metadata_, ctx_->initial_metadata_flags()); if (ctx_->compression_level_set()) { finish_ops_.set_compression_level(ctx_->compression_level()); } ctx_->sent_initial_metadata_ = true; } // The response is dropped if the status is not OK. if (status.ok()) { finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, finish_ops_.SendMessage(msg)); } else { finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status); } call_.PerformOps(&finish_ops_); } void FinishWithError(const Status& status, void* tag) override { GPR_CODEGEN_ASSERT(!status.ok()); finish_ops_.set_output_tag(tag); if (!ctx_->sent_initial_metadata_) { finish_ops_.SendInitialMetadata(ctx_->initial_metadata_, ctx_->initial_metadata_flags()); if (ctx_->compression_level_set()) { finish_ops_.set_compression_level(ctx_->compression_level()); } ctx_->sent_initial_metadata_ = true; } finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status); call_.PerformOps(&finish_ops_); } private: void BindCall(Call* call) override { call_ = *call; } Call call_; ServerContext* ctx_; CallOpSet meta_ops_; CallOpSet> read_ops_; CallOpSet finish_ops_; }; template class ServerAsyncWriterInterface : public ServerAsyncStreamingInterface, public AsyncWriterInterface { public: virtual void Finish(const Status& status, void* tag) = 0; /// Request the writing of \a msg and coalesce it with trailing metadata which /// contains \a status, using WriteOptions options with identifying tag \a /// tag. /// /// WriteAndFinish is equivalent of performing WriteLast and Finish in a /// single step. /// /// \param[in] msg The message to be written. /// \param[in] options The WriteOptions to be used to write this message. /// \param[in] status The Status that server returns to client. /// \param[in] tag The tag identifying the operation. virtual void WriteAndFinish(const W& msg, WriteOptions options, const Status& status, void* tag) = 0; }; template class ServerAsyncWriter final : public ServerAsyncWriterInterface { public: explicit ServerAsyncWriter(ServerContext* ctx) : call_(nullptr, nullptr, nullptr), ctx_(ctx) {} void SendInitialMetadata(void* tag) override { GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_); meta_ops_.set_output_tag(tag); meta_ops_.SendInitialMetadata(ctx_->initial_metadata_, ctx_->initial_metadata_flags()); if (ctx_->compression_level_set()) { meta_ops_.set_compression_level(ctx_->compression_level()); } ctx_->sent_initial_metadata_ = true; call_.PerformOps(&meta_ops_); } void Write(const W& msg, void* tag) override { write_ops_.set_output_tag(tag); EnsureInitialMetadataSent(&write_ops_); // TODO(ctiller): don't assert GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok()); call_.PerformOps(&write_ops_); } void Write(const W& msg, WriteOptions options, void* tag) override { write_ops_.set_output_tag(tag); if (options.is_last_message()) { options.set_buffer_hint(); } EnsureInitialMetadataSent(&write_ops_); // TODO(ctiller): don't assert GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok()); call_.PerformOps(&write_ops_); } void WriteAndFinish(const W& msg, WriteOptions options, const Status& status, void* tag) override { write_ops_.set_output_tag(tag); EnsureInitialMetadataSent(&write_ops_); options.set_buffer_hint(); GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok()); write_ops_.ServerSendStatus(ctx_->trailing_metadata_, status); call_.PerformOps(&write_ops_); } void Finish(const Status& status, void* tag) override { finish_ops_.set_output_tag(tag); EnsureInitialMetadataSent(&finish_ops_); finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status); call_.PerformOps(&finish_ops_); } private: void BindCall(Call* call) override { call_ = *call; } template void EnsureInitialMetadataSent(T* ops) { if (!ctx_->sent_initial_metadata_) { ops->SendInitialMetadata(ctx_->initial_metadata_, ctx_->initial_metadata_flags()); if (ctx_->compression_level_set()) { ops->set_compression_level(ctx_->compression_level()); } ctx_->sent_initial_metadata_ = true; } } Call call_; ServerContext* ctx_; CallOpSet meta_ops_; CallOpSet write_ops_; CallOpSet finish_ops_; }; /// Server-side interface for asynchronous bi-directional streaming. template class ServerAsyncReaderWriterInterface : public ServerAsyncStreamingInterface, public AsyncWriterInterface, public AsyncReaderInterface { public: virtual void Finish(const Status& status, void* tag) = 0; /// Request the writing of \a msg and coalesce it with trailing metadata which /// contains \a status, using WriteOptions options with identifying tag \a /// tag. /// /// WriteAndFinish is equivalent of performing WriteLast and Finish in a /// single step. /// /// \param[in] msg The message to be written. /// \param[in] options The WriteOptions to be used to write this message. /// \param[in] status The Status that server returns to client. /// \param[in] tag The tag identifying the operation. virtual void WriteAndFinish(const W& msg, WriteOptions options, const Status& status, void* tag) = 0; }; template class ServerAsyncReaderWriter final : public ServerAsyncReaderWriterInterface { public: explicit ServerAsyncReaderWriter(ServerContext* ctx) : call_(nullptr, nullptr, nullptr), ctx_(ctx) {} void SendInitialMetadata(void* tag) override { GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_); meta_ops_.set_output_tag(tag); meta_ops_.SendInitialMetadata(ctx_->initial_metadata_, ctx_->initial_metadata_flags()); if (ctx_->compression_level_set()) { meta_ops_.set_compression_level(ctx_->compression_level()); } ctx_->sent_initial_metadata_ = true; call_.PerformOps(&meta_ops_); } void Read(R* msg, void* tag) override { read_ops_.set_output_tag(tag); read_ops_.RecvMessage(msg); call_.PerformOps(&read_ops_); } void Write(const W& msg, void* tag) override { write_ops_.set_output_tag(tag); EnsureInitialMetadataSent(&write_ops_); // TODO(ctiller): don't assert GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok()); call_.PerformOps(&write_ops_); } void Write(const W& msg, WriteOptions options, void* tag) override { write_ops_.set_output_tag(tag); if (options.is_last_message()) { options.set_buffer_hint(); } EnsureInitialMetadataSent(&write_ops_); GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok()); call_.PerformOps(&write_ops_); } void WriteAndFinish(const W& msg, WriteOptions options, const Status& status, void* tag) override { write_ops_.set_output_tag(tag); EnsureInitialMetadataSent(&write_ops_); options.set_buffer_hint(); GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok()); write_ops_.ServerSendStatus(ctx_->trailing_metadata_, status); call_.PerformOps(&write_ops_); } void Finish(const Status& status, void* tag) override { finish_ops_.set_output_tag(tag); EnsureInitialMetadataSent(&finish_ops_); finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status); call_.PerformOps(&finish_ops_); } private: friend class ::grpc::Server; void BindCall(Call* call) override { call_ = *call; } template void EnsureInitialMetadataSent(T* ops) { if (!ctx_->sent_initial_metadata_) { ops->SendInitialMetadata(ctx_->initial_metadata_, ctx_->initial_metadata_flags()); if (ctx_->compression_level_set()) { ops->set_compression_level(ctx_->compression_level()); } ctx_->sent_initial_metadata_ = true; } } Call call_; ServerContext* ctx_; CallOpSet meta_ops_; CallOpSet> read_ops_; CallOpSet write_ops_; CallOpSet finish_ops_; }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_ASYNC_STREAM_H grpc-1.3.2/include/grpc++/impl/codegen/async_unary_call.h000066400000000000000000000152631310511640000232160ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_ASYNC_UNARY_CALL_H #define GRPCXX_IMPL_CODEGEN_ASYNC_UNARY_CALL_H #include #include #include #include #include #include namespace grpc { class CompletionQueue; extern CoreCodegenInterface* g_core_codegen_interface; template class ClientAsyncResponseReaderInterface { public: virtual ~ClientAsyncResponseReaderInterface() {} virtual void ReadInitialMetadata(void* tag) = 0; virtual void Finish(R* msg, Status* status, void* tag) = 0; }; template class ClientAsyncResponseReader final : public ClientAsyncResponseReaderInterface { public: template ClientAsyncResponseReader(ChannelInterface* channel, CompletionQueue* cq, const RpcMethod& method, ClientContext* context, const W& request) : context_(context), call_(channel->CreateCall(method, context, cq)), collection_(std::make_shared()) { collection_->init_buf_.SetCollection(collection_); collection_->init_buf_.SendInitialMetadata( context->send_initial_metadata_, context->initial_metadata_flags()); // TODO(ctiller): don't assert GPR_CODEGEN_ASSERT(collection_->init_buf_.SendMessage(request).ok()); collection_->init_buf_.ClientSendClose(); call_.PerformOps(&collection_->init_buf_); } void ReadInitialMetadata(void* tag) { GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_); collection_->meta_buf_.SetCollection(collection_); collection_->meta_buf_.set_output_tag(tag); collection_->meta_buf_.RecvInitialMetadata(context_); call_.PerformOps(&collection_->meta_buf_); } void Finish(R* msg, Status* status, void* tag) { collection_->finish_buf_.SetCollection(collection_); collection_->finish_buf_.set_output_tag(tag); if (!context_->initial_metadata_received_) { collection_->finish_buf_.RecvInitialMetadata(context_); } collection_->finish_buf_.RecvMessage(msg); collection_->finish_buf_.AllowNoMessage(); collection_->finish_buf_.ClientRecvStatus(context_, status); call_.PerformOps(&collection_->finish_buf_); } private: ClientContext* context_; Call call_; class CallOpSetCollection : public CallOpSetCollectionInterface { public: SneakyCallOpSet init_buf_; CallOpSet meta_buf_; CallOpSet, CallOpClientRecvStatus> finish_buf_; }; std::shared_ptr collection_; }; template class ServerAsyncResponseWriter final : public ServerAsyncStreamingInterface { public: explicit ServerAsyncResponseWriter(ServerContext* ctx) : call_(nullptr, nullptr, nullptr), ctx_(ctx) {} void SendInitialMetadata(void* tag) override { GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_); meta_buf_.set_output_tag(tag); meta_buf_.SendInitialMetadata(ctx_->initial_metadata_, ctx_->initial_metadata_flags()); if (ctx_->compression_level_set()) { meta_buf_.set_compression_level(ctx_->compression_level()); } ctx_->sent_initial_metadata_ = true; call_.PerformOps(&meta_buf_); } void Finish(const W& msg, const Status& status, void* tag) { finish_buf_.set_output_tag(tag); if (!ctx_->sent_initial_metadata_) { finish_buf_.SendInitialMetadata(ctx_->initial_metadata_, ctx_->initial_metadata_flags()); if (ctx_->compression_level_set()) { finish_buf_.set_compression_level(ctx_->compression_level()); } ctx_->sent_initial_metadata_ = true; } // The response is dropped if the status is not OK. if (status.ok()) { finish_buf_.ServerSendStatus(ctx_->trailing_metadata_, finish_buf_.SendMessage(msg)); } else { finish_buf_.ServerSendStatus(ctx_->trailing_metadata_, status); } call_.PerformOps(&finish_buf_); } void FinishWithError(const Status& status, void* tag) { GPR_CODEGEN_ASSERT(!status.ok()); finish_buf_.set_output_tag(tag); if (!ctx_->sent_initial_metadata_) { finish_buf_.SendInitialMetadata(ctx_->initial_metadata_, ctx_->initial_metadata_flags()); if (ctx_->compression_level_set()) { finish_buf_.set_compression_level(ctx_->compression_level()); } ctx_->sent_initial_metadata_ = true; } finish_buf_.ServerSendStatus(ctx_->trailing_metadata_, status); call_.PerformOps(&finish_buf_); } private: void BindCall(Call* call) override { call_ = *call; } Call call_; ServerContext* ctx_; CallOpSet meta_buf_; CallOpSet finish_buf_; }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_ASYNC_UNARY_CALL_H grpc-1.3.2/include/grpc++/impl/codegen/call.h000066400000000000000000000535471310511640000206120ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_CALL_H #define GRPCXX_IMPL_CODEGEN_CALL_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct grpc_byte_buffer; namespace grpc { class ByteBuffer; class Call; class CallHook; class CompletionQueue; extern CoreCodegenInterface* g_core_codegen_interface; const char kBinaryErrorDetailsKey[] = "grpc-status-details-bin"; // TODO(yangg) if the map is changed before we send, the pointers will be a // mess. Make sure it does not happen. inline grpc_metadata* FillMetadataArray( const std::multimap& metadata, size_t* metadata_count, const grpc::string& optional_error_details) { *metadata_count = metadata.size() + (optional_error_details.empty() ? 0 : 1); if (*metadata_count == 0) { return nullptr; } grpc_metadata* metadata_array = (grpc_metadata*)(g_core_codegen_interface->gpr_malloc( (*metadata_count) * sizeof(grpc_metadata))); size_t i = 0; for (auto iter = metadata.cbegin(); iter != metadata.cend(); ++iter, ++i) { metadata_array[i].key = SliceReferencingString(iter->first); metadata_array[i].value = SliceReferencingString(iter->second); } if (!optional_error_details.empty()) { metadata_array[i].key = g_core_codegen_interface->grpc_slice_from_static_buffer( kBinaryErrorDetailsKey, sizeof(kBinaryErrorDetailsKey) - 1); metadata_array[i].value = SliceReferencingString(optional_error_details); } return metadata_array; } /// Per-message write options. class WriteOptions { public: WriteOptions() : flags_(0), last_message_(false) {} WriteOptions(const WriteOptions& other) : flags_(other.flags_), last_message_(other.last_message_) {} /// Clear all flags. inline void Clear() { flags_ = 0; } /// Returns raw flags bitset. inline uint32_t flags() const { return flags_; } /// Sets flag for the disabling of compression for the next message write. /// /// \sa GRPC_WRITE_NO_COMPRESS inline WriteOptions& set_no_compression() { SetBit(GRPC_WRITE_NO_COMPRESS); return *this; } /// Clears flag for the disabling of compression for the next message write. /// /// \sa GRPC_WRITE_NO_COMPRESS inline WriteOptions& clear_no_compression() { ClearBit(GRPC_WRITE_NO_COMPRESS); return *this; } /// Get value for the flag indicating whether compression for the next /// message write is forcefully disabled. /// /// \sa GRPC_WRITE_NO_COMPRESS inline bool get_no_compression() const { return GetBit(GRPC_WRITE_NO_COMPRESS); } /// Sets flag indicating that the write may be buffered and need not go out on /// the wire immediately. /// /// \sa GRPC_WRITE_BUFFER_HINT inline WriteOptions& set_buffer_hint() { SetBit(GRPC_WRITE_BUFFER_HINT); return *this; } /// Clears flag indicating that the write may be buffered and need not go out /// on the wire immediately. /// /// \sa GRPC_WRITE_BUFFER_HINT inline WriteOptions& clear_buffer_hint() { ClearBit(GRPC_WRITE_BUFFER_HINT); return *this; } /// Get value for the flag indicating that the write may be buffered and need /// not go out on the wire immediately. /// /// \sa GRPC_WRITE_BUFFER_HINT inline bool get_buffer_hint() const { return GetBit(GRPC_WRITE_BUFFER_HINT); } /// corked bit: aliases set_buffer_hint currently, with the intent that /// set_buffer_hint will be removed in the future inline WriteOptions& set_corked() { SetBit(GRPC_WRITE_BUFFER_HINT); return *this; } inline WriteOptions& clear_corked() { ClearBit(GRPC_WRITE_BUFFER_HINT); return *this; } inline bool is_corked() const { return GetBit(GRPC_WRITE_BUFFER_HINT); } /// last-message bit: indicates this is the last message in a stream /// client-side: makes Write the equivalent of performing Write, WritesDone /// in a single step /// server-side: hold the Write until the service handler returns (sync api) /// or until Finish is called (async api) inline WriteOptions& set_last_message() { last_message_ = true; return *this; } /// Clears flag indicating that this is the last message in a stream, /// disabling coalescing. inline WriteOptions& clear_last_messsage() { last_message_ = false; return *this; } /// Get value for the flag indicating that this is the last message, and /// should be coalesced with trailing metadata. /// /// \sa GRPC_WRITE_LAST_MESSAGE bool is_last_message() const { return last_message_; } WriteOptions& operator=(const WriteOptions& rhs) { flags_ = rhs.flags_; return *this; } private: void SetBit(const uint32_t mask) { flags_ |= mask; } void ClearBit(const uint32_t mask) { flags_ &= ~mask; } bool GetBit(const uint32_t mask) const { return (flags_ & mask) != 0; } uint32_t flags_; bool last_message_; }; /// Default argument for CallOpSet. I is unused by the class, but can be /// used for generating multiple names for the same thing. template class CallNoOp { protected: void AddOp(grpc_op* ops, size_t* nops) {} void FinishOp(bool* status) {} }; class CallOpSendInitialMetadata { public: CallOpSendInitialMetadata() : send_(false) { maybe_compression_level_.is_set = false; } void SendInitialMetadata( const std::multimap& metadata, uint32_t flags) { maybe_compression_level_.is_set = false; send_ = true; flags_ = flags; initial_metadata_ = FillMetadataArray(metadata, &initial_metadata_count_, ""); } void set_compression_level(grpc_compression_level level) { maybe_compression_level_.is_set = true; maybe_compression_level_.level = level; } protected: void AddOp(grpc_op* ops, size_t* nops) { if (!send_) return; grpc_op* op = &ops[(*nops)++]; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->flags = flags_; op->reserved = NULL; op->data.send_initial_metadata.count = initial_metadata_count_; op->data.send_initial_metadata.metadata = initial_metadata_; op->data.send_initial_metadata.maybe_compression_level.is_set = maybe_compression_level_.is_set; op->data.send_initial_metadata.maybe_compression_level.level = maybe_compression_level_.level; } void FinishOp(bool* status) { if (!send_) return; g_core_codegen_interface->gpr_free(initial_metadata_); send_ = false; } bool send_; uint32_t flags_; size_t initial_metadata_count_; grpc_metadata* initial_metadata_; struct { bool is_set; grpc_compression_level level; } maybe_compression_level_; }; class CallOpSendMessage { public: CallOpSendMessage() : send_buf_(nullptr), own_buf_(false) {} /// Send \a message using \a options for the write. The \a options are cleared /// after use. template Status SendMessage(const M& message, WriteOptions options) GRPC_MUST_USE_RESULT; template Status SendMessage(const M& message) GRPC_MUST_USE_RESULT; protected: void AddOp(grpc_op* ops, size_t* nops) { if (send_buf_ == nullptr) return; grpc_op* op = &ops[(*nops)++]; op->op = GRPC_OP_SEND_MESSAGE; op->flags = write_options_.flags(); op->reserved = NULL; op->data.send_message.send_message = send_buf_; // Flags are per-message: clear them after use. write_options_.Clear(); } void FinishOp(bool* status) { if (own_buf_) g_core_codegen_interface->grpc_byte_buffer_destroy(send_buf_); send_buf_ = nullptr; } private: grpc_byte_buffer* send_buf_; WriteOptions write_options_; bool own_buf_; }; template Status CallOpSendMessage::SendMessage(const M& message, WriteOptions options) { write_options_ = options; return SerializationTraits::Serialize(message, &send_buf_, &own_buf_); } template Status CallOpSendMessage::SendMessage(const M& message) { return SendMessage(message, WriteOptions()); } template class CallOpRecvMessage { public: CallOpRecvMessage() : got_message(false), message_(nullptr), allow_not_getting_message_(false) {} void RecvMessage(R* message) { message_ = message; } // Do not change status if no message is received. void AllowNoMessage() { allow_not_getting_message_ = true; } bool got_message; protected: void AddOp(grpc_op* ops, size_t* nops) { if (message_ == nullptr) return; grpc_op* op = &ops[(*nops)++]; op->op = GRPC_OP_RECV_MESSAGE; op->flags = 0; op->reserved = NULL; op->data.recv_message.recv_message = &recv_buf_; } void FinishOp(bool* status) { if (message_ == nullptr) return; if (recv_buf_) { if (*status) { got_message = *status = SerializationTraits::Deserialize(recv_buf_, message_).ok(); } else { got_message = false; g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_); } } else { got_message = false; if (!allow_not_getting_message_) { *status = false; } } message_ = nullptr; } private: R* message_; grpc_byte_buffer* recv_buf_; bool allow_not_getting_message_; }; namespace CallOpGenericRecvMessageHelper { class DeserializeFunc { public: virtual Status Deserialize(grpc_byte_buffer* buf) = 0; virtual ~DeserializeFunc() {} }; template class DeserializeFuncType final : public DeserializeFunc { public: DeserializeFuncType(R* message) : message_(message) {} Status Deserialize(grpc_byte_buffer* buf) override { return SerializationTraits::Deserialize(buf, message_); } ~DeserializeFuncType() override {} private: R* message_; // Not a managed pointer because management is external to this }; } // namespace CallOpGenericRecvMessageHelper class CallOpGenericRecvMessage { public: CallOpGenericRecvMessage() : got_message(false), allow_not_getting_message_(false) {} template void RecvMessage(R* message) { // Use an explicit base class pointer to avoid resolution error in the // following unique_ptr::reset for some old implementations. CallOpGenericRecvMessageHelper::DeserializeFunc* func = new CallOpGenericRecvMessageHelper::DeserializeFuncType(message); deserialize_.reset(func); } // Do not change status if no message is received. void AllowNoMessage() { allow_not_getting_message_ = true; } bool got_message; protected: void AddOp(grpc_op* ops, size_t* nops) { if (!deserialize_) return; grpc_op* op = &ops[(*nops)++]; op->op = GRPC_OP_RECV_MESSAGE; op->flags = 0; op->reserved = NULL; op->data.recv_message.recv_message = &recv_buf_; } void FinishOp(bool* status) { if (!deserialize_) return; if (recv_buf_) { if (*status) { got_message = true; *status = deserialize_->Deserialize(recv_buf_).ok(); } else { got_message = false; g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_); } } else { got_message = false; if (!allow_not_getting_message_) { *status = false; } } deserialize_.reset(); } private: std::unique_ptr deserialize_; grpc_byte_buffer* recv_buf_; bool allow_not_getting_message_; }; class CallOpClientSendClose { public: CallOpClientSendClose() : send_(false) {} void ClientSendClose() { send_ = true; } protected: void AddOp(grpc_op* ops, size_t* nops) { if (!send_) return; grpc_op* op = &ops[(*nops)++]; op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; op->flags = 0; op->reserved = NULL; } void FinishOp(bool* status) { send_ = false; } private: bool send_; }; class CallOpServerSendStatus { public: CallOpServerSendStatus() : send_status_available_(false) {} void ServerSendStatus( const std::multimap& trailing_metadata, const Status& status) { send_error_details_ = status.error_details(); trailing_metadata_ = FillMetadataArray( trailing_metadata, &trailing_metadata_count_, send_error_details_); send_status_available_ = true; send_status_code_ = static_cast(GetCanonicalCode(status)); send_error_message_ = status.error_message(); } protected: void AddOp(grpc_op* ops, size_t* nops) { if (!send_status_available_) return; grpc_op* op = &ops[(*nops)++]; op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; op->data.send_status_from_server.trailing_metadata_count = trailing_metadata_count_; op->data.send_status_from_server.trailing_metadata = trailing_metadata_; op->data.send_status_from_server.status = send_status_code_; error_message_slice_ = SliceReferencingString(send_error_message_); op->data.send_status_from_server.status_details = send_error_message_.empty() ? nullptr : &error_message_slice_; op->flags = 0; op->reserved = NULL; } void FinishOp(bool* status) { if (!send_status_available_) return; g_core_codegen_interface->gpr_free(trailing_metadata_); send_status_available_ = false; } private: bool send_status_available_; grpc_status_code send_status_code_; grpc::string send_error_details_; grpc::string send_error_message_; size_t trailing_metadata_count_; grpc_metadata* trailing_metadata_; grpc_slice error_message_slice_; }; class CallOpRecvInitialMetadata { public: CallOpRecvInitialMetadata() : metadata_map_(nullptr) {} void RecvInitialMetadata(ClientContext* context) { context->initial_metadata_received_ = true; metadata_map_ = &context->recv_initial_metadata_; } protected: void AddOp(grpc_op* ops, size_t* nops) { if (metadata_map_ == nullptr) return; grpc_op* op = &ops[(*nops)++]; op->op = GRPC_OP_RECV_INITIAL_METADATA; op->data.recv_initial_metadata.recv_initial_metadata = metadata_map_->arr(); op->flags = 0; op->reserved = NULL; } void FinishOp(bool* status) { if (metadata_map_ == nullptr) return; metadata_map_->FillMap(); metadata_map_ = nullptr; } private: MetadataMap* metadata_map_; }; class CallOpClientRecvStatus { public: CallOpClientRecvStatus() : recv_status_(nullptr) {} void ClientRecvStatus(ClientContext* context, Status* status) { metadata_map_ = &context->trailing_metadata_; recv_status_ = status; error_message_ = g_core_codegen_interface->grpc_empty_slice(); } protected: void AddOp(grpc_op* ops, size_t* nops) { if (recv_status_ == nullptr) return; grpc_op* op = &ops[(*nops)++]; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.trailing_metadata = metadata_map_->arr(); op->data.recv_status_on_client.status = &status_code_; op->data.recv_status_on_client.status_details = &error_message_; op->flags = 0; op->reserved = NULL; } void FinishOp(bool* status) { if (recv_status_ == nullptr) return; metadata_map_->FillMap(); grpc::string binary_error_details; auto iter = metadata_map_->map()->find(kBinaryErrorDetailsKey); if (iter != metadata_map_->map()->end()) { binary_error_details = grpc::string(iter->second.begin(), iter->second.length()); } *recv_status_ = Status(static_cast(status_code_), grpc::string(GRPC_SLICE_START_PTR(error_message_), GRPC_SLICE_END_PTR(error_message_)), binary_error_details); g_core_codegen_interface->grpc_slice_unref(error_message_); recv_status_ = nullptr; } private: MetadataMap* metadata_map_; Status* recv_status_; grpc_status_code status_code_; grpc_slice error_message_; }; /// An abstract collection of CallOpSet's, to be used whenever /// CallOpSet objects must be thought of as a group. Each member /// of the group should have a shared_ptr back to the collection, /// as will the object that instantiates the collection, allowing /// for automatic ref-counting. In practice, any actual use should /// derive from this base class. This is specifically necessary if /// some of the CallOpSet's in the collection are "Sneaky" and don't /// report back to the C++ layer CQ operations class CallOpSetCollectionInterface : public std::enable_shared_from_this {}; /// An abstract collection of call ops, used to generate the /// grpc_call_op structure to pass down to the lower layers, /// and as it is-a CompletionQueueTag, also massages the final /// completion into the correct form for consumption in the C++ /// API. class CallOpSetInterface : public CompletionQueueTag { public: CallOpSetInterface() {} /// Fills in grpc_op, starting from ops[*nops] and moving /// upwards. virtual void FillOps(grpc_op* ops, size_t* nops) = 0; /// Mark this as belonging to a collection if needed void SetCollection(std::shared_ptr collection) { collection_ = collection; } protected: std::shared_ptr collection_; }; /// Primary implementaiton of CallOpSetInterface. /// Since we cannot use variadic templates, we declare slots up to /// the maximum count of ops we'll need in a set. We leverage the /// empty base class optimization to slim this class (especially /// when there are many unused slots used). To avoid duplicate base classes, /// the template parmeter for CallNoOp is varied by argument position. template , class Op2 = CallNoOp<2>, class Op3 = CallNoOp<3>, class Op4 = CallNoOp<4>, class Op5 = CallNoOp<5>, class Op6 = CallNoOp<6>> class CallOpSet : public CallOpSetInterface, public Op1, public Op2, public Op3, public Op4, public Op5, public Op6 { public: CallOpSet() : return_tag_(this) {} void FillOps(grpc_op* ops, size_t* nops) override { this->Op1::AddOp(ops, nops); this->Op2::AddOp(ops, nops); this->Op3::AddOp(ops, nops); this->Op4::AddOp(ops, nops); this->Op5::AddOp(ops, nops); this->Op6::AddOp(ops, nops); } bool FinalizeResult(void** tag, bool* status) override { this->Op1::FinishOp(status); this->Op2::FinishOp(status); this->Op3::FinishOp(status); this->Op4::FinishOp(status); this->Op5::FinishOp(status); this->Op6::FinishOp(status); *tag = return_tag_; collection_.reset(); // drop the ref at this point return true; } void set_output_tag(void* return_tag) { return_tag_ = return_tag; } private: void* return_tag_; }; /// A CallOpSet that does not post completions to the completion queue. /// /// Allows hiding some completions that the C core must generate from /// C++ users. template , class Op2 = CallNoOp<2>, class Op3 = CallNoOp<3>, class Op4 = CallNoOp<4>, class Op5 = CallNoOp<5>, class Op6 = CallNoOp<6>> class SneakyCallOpSet : public CallOpSet { public: bool FinalizeResult(void** tag, bool* status) override { typedef CallOpSet Base; return Base::FinalizeResult(tag, status) && false; } }; // Straightforward wrapping of the C call object class Call final { public: /* call is owned by the caller */ Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq) : call_hook_(call_hook), cq_(cq), call_(call), max_receive_message_size_(-1) {} Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq, int max_receive_message_size) : call_hook_(call_hook), cq_(cq), call_(call), max_receive_message_size_(max_receive_message_size) {} void PerformOps(CallOpSetInterface* ops) { call_hook_->PerformOpsOnCall(ops, this); } grpc_call* call() const { return call_; } CompletionQueue* cq() const { return cq_; } int max_receive_message_size() const { return max_receive_message_size_; } private: CallHook* call_hook_; CompletionQueue* cq_; grpc_call* call_; int max_receive_message_size_; }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_CALL_H grpc-1.3.2/include/grpc++/impl/codegen/call_hook.h000066400000000000000000000036711310511640000216230ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_CALL_HOOK_H #define GRPCXX_IMPL_CODEGEN_CALL_HOOK_H namespace grpc { class CallOpSetInterface; class Call; /// Channel and Server implement this to allow them to hook performing ops class CallHook { public: virtual ~CallHook() {} virtual void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) = 0; }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_CALL_HOOK_H grpc-1.3.2/include/grpc++/impl/codegen/channel_interface.h000066400000000000000000000121001310511640000233030ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_CHANNEL_INTERFACE_H #define GRPCXX_IMPL_CODEGEN_CHANNEL_INTERFACE_H #include #include #include namespace grpc { class Call; class ClientContext; class RpcMethod; class CallOpSetInterface; class CompletionQueue; template class ClientReader; template class ClientWriter; template class ClientReaderWriter; template class ClientAsyncReader; template class ClientAsyncWriter; template class ClientAsyncReaderWriter; template class ClientAsyncResponseReader; /// Codegen interface for \a grpc::Channel. class ChannelInterface { public: virtual ~ChannelInterface() {} /// Get the current channel state. If the channel is in IDLE and /// \a try_to_connect is set to true, try to connect. virtual grpc_connectivity_state GetState(bool try_to_connect) = 0; /// Return the \a tag on \a cq when the channel state is changed or \a /// deadline expires. \a GetState needs to called to get the current state. template void NotifyOnStateChange(grpc_connectivity_state last_observed, T deadline, CompletionQueue* cq, void* tag) { TimePoint deadline_tp(deadline); NotifyOnStateChangeImpl(last_observed, deadline_tp.raw_time(), cq, tag); } /// Blocking wait for channel state change or \a deadline expiration. /// \a GetState needs to called to get the current state. template bool WaitForStateChange(grpc_connectivity_state last_observed, T deadline) { TimePoint deadline_tp(deadline); return WaitForStateChangeImpl(last_observed, deadline_tp.raw_time()); } /// Wait for this channel to be connected template bool WaitForConnected(T deadline) { grpc_connectivity_state state; while ((state = GetState(true)) != GRPC_CHANNEL_READY) { if (!WaitForStateChange(state, deadline)) return false; } return true; } private: template friend class ::grpc::ClientReader; template friend class ::grpc::ClientWriter; template friend class ::grpc::ClientReaderWriter; template friend class ::grpc::ClientAsyncReader; template friend class ::grpc::ClientAsyncWriter; template friend class ::grpc::ClientAsyncReaderWriter; template friend class ::grpc::ClientAsyncResponseReader; template friend Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method, ClientContext* context, const InputMessage& request, OutputMessage* result); friend class ::grpc::RpcMethod; virtual Call CreateCall(const RpcMethod& method, ClientContext* context, CompletionQueue* cq) = 0; virtual void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) = 0; virtual void* RegisterMethod(const char* method) = 0; virtual void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline, CompletionQueue* cq, void* tag) = 0; virtual bool WaitForStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline) = 0; }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_CHANNEL_INTERFACE_H grpc-1.3.2/include/grpc++/impl/codegen/client_context.h000066400000000000000000000340161310511640000227070ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /// A ClientContext allows the person implementing a service client to: /// /// - Add custom metadata key-value pairs that will propagated to the server /// side. /// - Control call settings such as compression and authentication. /// - Initial and trailing metadata coming from the server. /// - Get performance metrics (ie, census). /// /// Context settings are only relevant to the call they are invoked with, that /// is to say, they aren't sticky. Some of these settings, such as the /// compression options, can be made persistent at channel construction time /// (see \a grpc::CreateCustomChannel). /// /// \warning ClientContext instances should \em not be reused across rpcs. #ifndef GRPCXX_IMPL_CODEGEN_CLIENT_CONTEXT_H #define GRPCXX_IMPL_CODEGEN_CLIENT_CONTEXT_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct census_context; struct grpc_call; namespace grpc { class Channel; class ChannelInterface; class CompletionQueue; class CallCredentials; class RpcMethod; template class ClientReader; template class ClientWriter; template class ClientReaderWriter; template class ClientAsyncReader; template class ClientAsyncWriter; template class ClientAsyncReaderWriter; template class ClientAsyncResponseReader; class ServerContext; /// Options for \a ClientContext::FromServerContext specifying which traits from /// the \a ServerContext to propagate (copy) from it into a new \a /// ClientContext. /// /// \see ClientContext::FromServerContext class PropagationOptions { public: PropagationOptions() : propagate_(GRPC_PROPAGATE_DEFAULTS) {} PropagationOptions& enable_deadline_propagation() { propagate_ |= GRPC_PROPAGATE_DEADLINE; return *this; } PropagationOptions& disable_deadline_propagation() { propagate_ &= ~GRPC_PROPAGATE_DEADLINE; return *this; } PropagationOptions& enable_census_stats_propagation() { propagate_ |= GRPC_PROPAGATE_CENSUS_STATS_CONTEXT; return *this; } PropagationOptions& disable_census_stats_propagation() { propagate_ &= ~GRPC_PROPAGATE_CENSUS_STATS_CONTEXT; return *this; } PropagationOptions& enable_census_tracing_propagation() { propagate_ |= GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT; return *this; } PropagationOptions& disable_census_tracing_propagation() { propagate_ &= ~GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT; return *this; } PropagationOptions& enable_cancellation_propagation() { propagate_ |= GRPC_PROPAGATE_CANCELLATION; return *this; } PropagationOptions& disable_cancellation_propagation() { propagate_ &= ~GRPC_PROPAGATE_CANCELLATION; return *this; } uint32_t c_bitmask() const { return propagate_; } private: uint32_t propagate_; }; namespace testing { class InteropClientContextInspector; } // namespace testing class ClientContext { public: ClientContext(); ~ClientContext(); /// Create a new \a ClientContext as a child of an incoming server call, /// according to \a options (\see PropagationOptions). /// /// \param server_context The source server context to use as the basis for /// constructing the client context. /// \param options The options controlling what to copy from the \a /// server_context. /// /// \return A newly constructed \a ClientContext instance based on \a /// server_context, with traits propagated (copied) according to \a options. static std::unique_ptr FromServerContext( const ServerContext& server_context, PropagationOptions options = PropagationOptions()); /// Add the (\a meta_key, \a meta_value) pair to the metadata associated with /// a client call. These are made available at the server side by the \a /// grpc::ServerContext::client_metadata() method. /// /// \warning This method should only be called before invoking the rpc. /// /// \param meta_key The metadata key. If \a meta_value is binary data, it must /// end in "-bin". /// \param meta_value The metadata value. If its value is binary, it must be /// base64-encoding (see https://tools.ietf.org/html/rfc4648#section-4) and \a /// meta_key must end in "-bin". void AddMetadata(const grpc::string& meta_key, const grpc::string& meta_value); /// Return a collection of initial metadata key-value pairs. Note that keys /// may happen more than once (ie, a \a std::multimap is returned). /// /// \warning This method should only be called after initial metadata has been /// received. For streaming calls, see \a /// ClientReaderInterface::WaitForInitialMetadata(). /// /// \return A multimap of initial metadata key-value pairs from the server. const std::multimap& GetServerInitialMetadata() const { GPR_CODEGEN_ASSERT(initial_metadata_received_); return *recv_initial_metadata_.map(); } /// Return a collection of trailing metadata key-value pairs. Note that keys /// may happen more than once (ie, a \a std::multimap is returned). /// /// \warning This method is only callable once the stream has finished. /// /// \return A multimap of metadata trailing key-value pairs from the server. const std::multimap& GetServerTrailingMetadata() const { // TODO(yangg) check finished return *trailing_metadata_.map(); } /// Set the deadline for the client call. /// /// \warning This method should only be called before invoking the rpc. /// /// \param deadline the deadline for the client call. Units are determined by /// the type used. template void set_deadline(const T& deadline) { TimePoint deadline_tp(deadline); deadline_ = deadline_tp.raw_time(); } /// EXPERIMENTAL: Set this request to be idempotent void set_idempotent(bool idempotent) { idempotent_ = idempotent; } /// EXPERIMENTAL: Set this request to be cacheable void set_cacheable(bool cacheable) { cacheable_ = cacheable; } /// EXPERIMENTAL: Trigger wait-for-ready or not on this request void set_wait_for_ready(bool wait_for_ready) { wait_for_ready_ = wait_for_ready; wait_for_ready_explicitly_set_ = true; } /// DEPRECATED: Use set_wait_for_ready() instead. void set_fail_fast(bool fail_fast) { set_wait_for_ready(!fail_fast); } /// Return the deadline for the client call. std::chrono::system_clock::time_point deadline() const { return Timespec2Timepoint(deadline_); } /// Return a \a gpr_timespec representation of the client call's deadline. gpr_timespec raw_deadline() const { return deadline_; } /// Set the per call authority header (see /// https://tools.ietf.org/html/rfc7540#section-8.1.2.3). void set_authority(const grpc::string& authority) { authority_ = authority; } /// Return the authentication context for this client call. /// /// \see grpc::AuthContext. std::shared_ptr auth_context() const { if (auth_context_.get() == nullptr) { auth_context_ = CreateAuthContext(call_); } return auth_context_; } /// Set credentials for the client call. /// /// A credentials object encapsulates all the state needed by a client to /// authenticate with a server and make various assertions, e.g., about the /// client’s identity, role, or whether it is authorized to make a particular /// call. /// /// \see http://www.grpc.io/docs/guides/auth.html void set_credentials(const std::shared_ptr& creds) { creds_ = creds; } /// Return the compression algorithm to be used by the client call. grpc_compression_algorithm compression_algorithm() const { return compression_algorithm_; } /// Set \a algorithm to be the compression algorithm used for the client call. /// /// \param algorithm The compression algorithm used for the client call. void set_compression_algorithm(grpc_compression_algorithm algorithm); /// Flag whether the initial metadata should be \a corked /// /// If \a corked is true, then the initial metadata will be colasced with the /// write of first message in the stream. /// /// \param corked The flag indicating whether the initial metadata is to be /// corked or not. void set_initial_metadata_corked(bool corked) { initial_metadata_corked_ = corked; } /// Return the peer uri in a string. /// /// \warning This value is never authenticated or subject to any security /// related code. It must not be used for any authentication related /// functionality. Instead, use auth_context. /// /// \return The call's peer URI. grpc::string peer() const; /// Get and set census context. void set_census_context(struct census_context* ccp) { census_context_ = ccp; } struct census_context* census_context() const { return census_context_; } /// Send a best-effort out-of-band cancel. The call could be in any stage. /// e.g. if it is already finished, it may still return success. /// /// There is no guarantee the call will be cancelled. void TryCancel(); /// Global Callbacks /// /// Can be set exactly once per application to install hooks whenever /// a client context is constructed and destructed. class GlobalCallbacks { public: virtual ~GlobalCallbacks() {} virtual void DefaultConstructor(ClientContext* context) = 0; virtual void Destructor(ClientContext* context) = 0; }; static void SetGlobalCallbacks(GlobalCallbacks* callbacks); // Should be used for framework-level extensions only. // Applications never need to call this method. grpc_call* c_call() { return call_; } private: // Disallow copy and assign. ClientContext(const ClientContext&); ClientContext& operator=(const ClientContext&); friend class ::grpc::testing::InteropClientContextInspector; friend class CallOpClientRecvStatus; friend class CallOpRecvInitialMetadata; friend class Channel; template friend class ::grpc::ClientReader; template friend class ::grpc::ClientWriter; template friend class ::grpc::ClientReaderWriter; template friend class ::grpc::ClientAsyncReader; template friend class ::grpc::ClientAsyncWriter; template friend class ::grpc::ClientAsyncReaderWriter; template friend class ::grpc::ClientAsyncResponseReader; template friend Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method, ClientContext* context, const InputMessage& request, OutputMessage* result); grpc_call* call() const { return call_; } void set_call(grpc_call* call, const std::shared_ptr& channel); uint32_t initial_metadata_flags() const { return (idempotent_ ? GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST : 0) | (wait_for_ready_ ? GRPC_INITIAL_METADATA_WAIT_FOR_READY : 0) | (cacheable_ ? GRPC_INITIAL_METADATA_CACHEABLE_REQUEST : 0) | (wait_for_ready_explicitly_set_ ? GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET : 0) | (initial_metadata_corked_ ? GRPC_INITIAL_METADATA_CORKED : 0); } grpc::string authority() { return authority_; } bool initial_metadata_received_; bool wait_for_ready_; bool wait_for_ready_explicitly_set_; bool idempotent_; bool cacheable_; std::shared_ptr channel_; std::mutex mu_; grpc_call* call_; bool call_canceled_; gpr_timespec deadline_; grpc::string authority_; std::shared_ptr creds_; mutable std::shared_ptr auth_context_; struct census_context* census_context_; std::multimap send_initial_metadata_; MetadataMap recv_initial_metadata_; MetadataMap trailing_metadata_; grpc_call* propagate_from_call_; PropagationOptions propagation_options_; grpc_compression_algorithm compression_algorithm_; bool initial_metadata_corked_; }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_CLIENT_CONTEXT_H grpc-1.3.2/include/grpc++/impl/codegen/client_unary_call.h000066400000000000000000000062771310511640000233640ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_CLIENT_UNARY_CALL_H #define GRPCXX_IMPL_CODEGEN_CLIENT_UNARY_CALL_H #include #include #include #include #include namespace grpc { class Channel; class ClientContext; class CompletionQueue; class RpcMethod; // Wrapper that performs a blocking unary call template Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method, ClientContext* context, const InputMessage& request, OutputMessage* result) { CompletionQueue cq; Call call(channel->CreateCall(method, context, &cq)); CallOpSet, CallOpClientSendClose, CallOpClientRecvStatus> ops; Status status = ops.SendMessage(request); if (!status.ok()) { return status; } ops.SendInitialMetadata(context->send_initial_metadata_, context->initial_metadata_flags()); ops.RecvInitialMetadata(context); ops.RecvMessage(result); ops.ClientSendClose(); ops.ClientRecvStatus(context, &status); call.PerformOps(&ops); if (cq.Pluck(&ops)) { if (!ops.got_message && status.ok()) { return Status(StatusCode::UNIMPLEMENTED, "No message returned for unary request"); } } else { GPR_CODEGEN_ASSERT(!status.ok()); } return status; } } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_CLIENT_UNARY_CALL_H grpc-1.3.2/include/grpc++/impl/codegen/completion_queue.h000066400000000000000000000256741310511640000232540ustar00rootroot00000000000000/* * * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /// A completion queue implements a concurrent producer-consumer queue, with /// two main API-exposed methods: \a Next and \a AsyncNext. These /// methods are the essential component of the gRPC C++ asynchronous API. /// There is also a \a Shutdown method to indicate that a given completion queue /// will no longer have regular events. This must be called before the /// completion queue is destroyed. /// All completion queue APIs are thread-safe and may be used concurrently with /// any other completion queue API invocation; it is acceptable to have /// multiple threads calling \a Next or \a AsyncNext on the same or different /// completion queues, or to call these methods concurrently with a \a Shutdown /// elsewhere. /// \remark{All other API calls on completion queue should be completed before /// a completion queue destructor is called.} #ifndef GRPCXX_IMPL_CODEGEN_COMPLETION_QUEUE_H #define GRPCXX_IMPL_CODEGEN_COMPLETION_QUEUE_H #include #include #include #include #include #include struct grpc_completion_queue; namespace grpc { template class ClientReader; template class ClientWriter; template class ClientReaderWriter; template class ServerReader; template class ServerWriter; namespace internal { template class ServerReaderWriterBody; } template class RpcMethodHandler; template class ClientStreamingHandler; template class ServerStreamingHandler; template class BidiStreamingHandler; class UnknownMethodHandler; class Channel; class ChannelInterface; class ClientContext; class CompletionQueueTag; class CompletionQueue; class RpcMethod; class Server; class ServerBuilder; class ServerContext; extern CoreCodegenInterface* g_core_codegen_interface; /// A thin wrapper around \ref grpc_completion_queue (see \ref /// src/core/lib/surface/completion_queue.h). /// See \ref doc/cpp/perf_notes.md for notes on best practices for high /// performance servers. class CompletionQueue : private GrpcLibraryCodegen { public: /// Default constructor. Implicitly creates a \a grpc_completion_queue /// instance. CompletionQueue() { cq_ = g_core_codegen_interface->grpc_completion_queue_create(nullptr); InitialAvalanching(); // reserve this for the future shutdown } /// Wrap \a take, taking ownership of the instance. /// /// \param take The completion queue instance to wrap. Ownership is taken. explicit CompletionQueue(grpc_completion_queue* take); /// Destructor. Destroys the owned wrapped completion queue / instance. ~CompletionQueue() { g_core_codegen_interface->grpc_completion_queue_destroy(cq_); } /// Tri-state return for AsyncNext: SHUTDOWN, GOT_EVENT, TIMEOUT. enum NextStatus { SHUTDOWN, ///< The completion queue has been shutdown. GOT_EVENT, ///< Got a new event; \a tag will be filled in with its ///< associated value; \a ok indicating its success. TIMEOUT ///< deadline was reached. }; /// Read from the queue, blocking up to \a deadline (or the queue's shutdown). /// Both \a tag and \a ok are updated upon success (if an event is available /// within the \a deadline). A \a tag points to an arbitrary location usually /// employed to uniquely identify an event. /// /// \param tag[out] Upon sucess, updated to point to the event's tag. /// \param ok[out] Upon sucess, true if read a regular event, false otherwise. /// \param deadline[in] How long to block in wait for an event. /// /// \return The type of event read. template NextStatus AsyncNext(void** tag, bool* ok, const T& deadline) { TimePoint deadline_tp(deadline); return AsyncNextInternal(tag, ok, deadline_tp.raw_time()); } /// Read from the queue, blocking until an event is available or the queue is /// shutting down. /// /// \param tag[out] Updated to point to the read event's tag. /// \param ok[out] true if read a regular event, false otherwise. /// /// \return true if read a regular event, false if the queue is shutting down. bool Next(void** tag, bool* ok) { return (AsyncNextInternal(tag, ok, g_core_codegen_interface->gpr_inf_future( GPR_CLOCK_REALTIME)) != SHUTDOWN); } /// Request the shutdown of the queue. /// /// \warning This method must be called at some point if this completion queue /// is accessed with Next or AsyncNext. Once invoked, \a Next /// will start to return false and \a AsyncNext will return \a /// NextStatus::SHUTDOWN. Only once either one of these methods does that /// (that is, once the queue has been \em drained) can an instance of this /// class be destroyed. void Shutdown(); /// Returns a \em raw pointer to the underlying \a grpc_completion_queue /// instance. /// /// \warning Remember that the returned instance is owned. No transfer of /// owership is performed. grpc_completion_queue* cq() { return cq_; } /// Manage state of avalanching operations : completion queue tags that /// trigger other completion queue operations. The underlying core completion /// queue should not really shutdown until all avalanching operations have /// been finalized. Note that we maintain the requirement that an avalanche /// registration must take place before CQ shutdown (which must be maintained /// elsehwere) void InitialAvalanching() { gpr_atm_rel_store(&avalanches_in_flight_, static_cast(1)); } void RegisterAvalanching() { gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_, static_cast(1)); }; void CompleteAvalanching(); private: // Friend synchronous wrappers so that they can access Pluck(), which is // a semi-private API geared towards the synchronous implementation. template friend class ::grpc::ClientReader; template friend class ::grpc::ClientWriter; template friend class ::grpc::ClientReaderWriter; template friend class ::grpc::ServerReader; template friend class ::grpc::ServerWriter; template friend class ::grpc::internal::ServerReaderWriterBody; template friend class RpcMethodHandler; template friend class ClientStreamingHandler; template friend class ServerStreamingHandler; template friend class TemplatedBidiStreamingHandler; friend class UnknownMethodHandler; friend class ::grpc::Server; friend class ::grpc::ServerContext; template friend Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method, ClientContext* context, const InputMessage& request, OutputMessage* result); NextStatus AsyncNextInternal(void** tag, bool* ok, gpr_timespec deadline); /// Wraps \a grpc_completion_queue_pluck. /// \warning Must not be mixed with calls to \a Next. bool Pluck(CompletionQueueTag* tag) { auto deadline = g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME); auto ev = g_core_codegen_interface->grpc_completion_queue_pluck( cq_, tag, deadline, nullptr); bool ok = ev.success != 0; void* ignored = tag; GPR_CODEGEN_ASSERT(tag->FinalizeResult(&ignored, &ok)); GPR_CODEGEN_ASSERT(ignored == tag); // Ignore mutations by FinalizeResult: Pluck returns the C API status return ev.success != 0; } /// Performs a single polling pluck on \a tag. /// \warning Must not be mixed with calls to \a Next. void TryPluck(CompletionQueueTag* tag) { auto deadline = g_core_codegen_interface->gpr_time_0(GPR_CLOCK_REALTIME); auto ev = g_core_codegen_interface->grpc_completion_queue_pluck( cq_, tag, deadline, nullptr); if (ev.type == GRPC_QUEUE_TIMEOUT) return; bool ok = ev.success != 0; void* ignored = tag; // the tag must be swallowed if using TryPluck GPR_CODEGEN_ASSERT(!tag->FinalizeResult(&ignored, &ok)); } grpc_completion_queue* cq_; // owned gpr_atm avalanches_in_flight_; }; /// A specific type of completion queue used by the processing of notifications /// by servers. Instantiated by \a ServerBuilder. class ServerCompletionQueue : public CompletionQueue { public: bool IsFrequentlyPolled() { return is_frequently_polled_; } private: bool is_frequently_polled_; friend class ServerBuilder; /// \param is_frequently_polled Informs the GRPC library about whether the /// server completion queue would be actively polled (by calling Next() or /// AsyncNext()). By default all server completion queues are assumed to be /// frequently polled. ServerCompletionQueue(bool is_frequently_polled = true) : is_frequently_polled_(is_frequently_polled) {} }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_COMPLETION_QUEUE_H grpc-1.3.2/include/grpc++/impl/codegen/completion_queue_tag.h000066400000000000000000000042511310511640000240730ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_COMPLETION_QUEUE_TAG_H #define GRPCXX_IMPL_CODEGEN_COMPLETION_QUEUE_TAG_H namespace grpc { /// An interface allowing implementors to process and filter event tags. class CompletionQueueTag { public: virtual ~CompletionQueueTag() {} // Called prior to returning from Next(), return value is the status of the // operation (return status is the default thing to do). If this function // returns false, the tag is dropped and not returned from the completion // queue virtual bool FinalizeResult(void** tag, bool* status) = 0; }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_COMPLETION_QUEUE_TAG_H grpc-1.3.2/include/grpc++/impl/codegen/config.h000066400000000000000000000041161310511640000211300ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_CONFIG_H #define GRPCXX_IMPL_CODEGEN_CONFIG_H #ifndef GRPC_CUSTOM_STRING #include #define GRPC_CUSTOM_STRING std::string #endif // The following macros are deprecated and appear only for users // with PB files generated using gRPC 1.0.x plugins. They should // not be used in new code #define GRPC_OVERRIDE override // deprecated #define GRPC_FINAL final // deprecated namespace grpc { typedef GRPC_CUSTOM_STRING string; using std::to_string; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_CONFIG_H grpc-1.3.2/include/grpc++/impl/codegen/config_protobuf.h000066400000000000000000000105111310511640000230440ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_CONFIG_PROTOBUF_H #define GRPCXX_IMPL_CODEGEN_CONFIG_PROTOBUF_H #ifndef GRPC_CUSTOM_PROTOBUF_INT64 #include #define GRPC_CUSTOM_PROTOBUF_INT64 ::google::protobuf::int64 #endif #ifndef GRPC_CUSTOM_MESSAGE #ifdef GRPC_USE_PROTO_LITE #include #define GRPC_CUSTOM_MESSAGE ::google::protobuf::MessageLite #else #include #define GRPC_CUSTOM_MESSAGE ::google::protobuf::Message #endif #endif #ifndef GRPC_CUSTOM_DESCRIPTOR #include #include #define GRPC_CUSTOM_DESCRIPTOR ::google::protobuf::Descriptor #define GRPC_CUSTOM_DESCRIPTORPOOL ::google::protobuf::DescriptorPool #define GRPC_CUSTOM_FIELDDESCRIPTOR ::google::protobuf::FieldDescriptor #define GRPC_CUSTOM_FILEDESCRIPTOR ::google::protobuf::FileDescriptor #define GRPC_CUSTOM_FILEDESCRIPTORPROTO ::google::protobuf::FileDescriptorProto #define GRPC_CUSTOM_METHODDESCRIPTOR ::google::protobuf::MethodDescriptor #define GRPC_CUSTOM_SERVICEDESCRIPTOR ::google::protobuf::ServiceDescriptor #define GRPC_CUSTOM_SOURCELOCATION ::google::protobuf::SourceLocation #endif #ifndef GRPC_CUSTOM_DESCRIPTORDATABASE #include #define GRPC_CUSTOM_DESCRIPTORDATABASE ::google::protobuf::DescriptorDatabase #define GRPC_CUSTOM_SIMPLEDESCRIPTORDATABASE \ ::google::protobuf::SimpleDescriptorDatabase #endif #ifndef GRPC_CUSTOM_ZEROCOPYOUTPUTSTREAM #include #include #define GRPC_CUSTOM_ZEROCOPYOUTPUTSTREAM \ ::google::protobuf::io::ZeroCopyOutputStream #define GRPC_CUSTOM_ZEROCOPYINPUTSTREAM \ ::google::protobuf::io::ZeroCopyInputStream #define GRPC_CUSTOM_CODEDINPUTSTREAM ::google::protobuf::io::CodedInputStream #endif namespace grpc { namespace protobuf { typedef GRPC_CUSTOM_MESSAGE Message; typedef GRPC_CUSTOM_PROTOBUF_INT64 int64; typedef GRPC_CUSTOM_DESCRIPTOR Descriptor; typedef GRPC_CUSTOM_DESCRIPTORPOOL DescriptorPool; typedef GRPC_CUSTOM_DESCRIPTORDATABASE DescriptorDatabase; typedef GRPC_CUSTOM_FIELDDESCRIPTOR FieldDescriptor; typedef GRPC_CUSTOM_FILEDESCRIPTOR FileDescriptor; typedef GRPC_CUSTOM_FILEDESCRIPTORPROTO FileDescriptorProto; typedef GRPC_CUSTOM_METHODDESCRIPTOR MethodDescriptor; typedef GRPC_CUSTOM_SERVICEDESCRIPTOR ServiceDescriptor; typedef GRPC_CUSTOM_SIMPLEDESCRIPTORDATABASE SimpleDescriptorDatabase; typedef GRPC_CUSTOM_SOURCELOCATION SourceLocation; namespace io { typedef GRPC_CUSTOM_ZEROCOPYOUTPUTSTREAM ZeroCopyOutputStream; typedef GRPC_CUSTOM_ZEROCOPYINPUTSTREAM ZeroCopyInputStream; typedef GRPC_CUSTOM_CODEDINPUTSTREAM CodedInputStream; } // namespace io } // namespace protobuf } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_CONFIG_PROTOBUF_H grpc-1.3.2/include/grpc++/impl/codegen/core_codegen.h000066400000000000000000000107131310511640000222770ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_CORE_CODEGEN_H #define GRPCXX_IMPL_CODEGEN_CORE_CODEGEN_H // This file should be compiled as part of grpc++. #include #include #include namespace grpc { /// Implementation of the core codegen interface. class CoreCodegen : public CoreCodegenInterface { private: grpc_completion_queue* grpc_completion_queue_create(void* reserved) override; void grpc_completion_queue_destroy(grpc_completion_queue* cq) override; grpc_event grpc_completion_queue_pluck(grpc_completion_queue* cq, void* tag, gpr_timespec deadline, void* reserved) override; void* gpr_malloc(size_t size) override; void gpr_free(void* p) override; void gpr_mu_init(gpr_mu* mu) override; void gpr_mu_destroy(gpr_mu* mu) override; void gpr_mu_lock(gpr_mu* mu) override; void gpr_mu_unlock(gpr_mu* mu) override; void gpr_cv_init(gpr_cv* cv) override; void gpr_cv_destroy(gpr_cv* cv) override; int gpr_cv_wait(gpr_cv* cv, gpr_mu* mu, gpr_timespec abs_deadline) override; void gpr_cv_signal(gpr_cv* cv) override; void gpr_cv_broadcast(gpr_cv* cv) override; void grpc_byte_buffer_destroy(grpc_byte_buffer* bb) override; int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader* reader, grpc_byte_buffer* buffer) override; void grpc_byte_buffer_reader_destroy( grpc_byte_buffer_reader* reader) override; int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader* reader, grpc_slice* slice) override; grpc_byte_buffer* grpc_raw_byte_buffer_create(grpc_slice* slice, size_t nslices) override; grpc_slice grpc_empty_slice() override; grpc_slice grpc_slice_malloc(size_t length) override; void grpc_slice_unref(grpc_slice slice) override; grpc_slice grpc_slice_split_tail(grpc_slice* s, size_t split) override; void grpc_slice_buffer_add(grpc_slice_buffer* sb, grpc_slice slice) override; void grpc_slice_buffer_pop(grpc_slice_buffer* sb) override; grpc_slice grpc_slice_from_static_buffer(const void* buffer, size_t length) override; grpc_slice grpc_slice_from_copied_buffer(const void* buffer, size_t length) override; void grpc_metadata_array_init(grpc_metadata_array* array) override; void grpc_metadata_array_destroy(grpc_metadata_array* array) override; gpr_timespec gpr_inf_future(gpr_clock_type type) override; gpr_timespec gpr_time_0(gpr_clock_type type) override; virtual const Status& ok() override; virtual const Status& cancelled() override; void assert_fail(const char* failed_assertion, const char* file, int line) override; }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_CORE_CODEGEN_H grpc-1.3.2/include/grpc++/impl/codegen/core_codegen_interface.h000066400000000000000000000132141310511640000243160ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_CORE_CODEGEN_INTERFACE_H #define GRPCXX_IMPL_CODEGEN_CORE_CODEGEN_INTERFACE_H #include #include #include #include #include extern "C" { struct grpc_byte_buffer; } namespace grpc { /// Interface between the codegen library and the minimal subset of core /// features required by the generated code. /// /// All undocumented methods are simply forwarding the call to their namesakes. /// Please refer to their corresponding documentation for details. /// /// \warning This interface should be considered internal and private. class CoreCodegenInterface { public: /// Upon a failed assertion, log the error. virtual void assert_fail(const char* failed_assertion, const char* file, int line) = 0; virtual grpc_completion_queue* grpc_completion_queue_create( void* reserved) = 0; virtual void grpc_completion_queue_destroy(grpc_completion_queue* cq) = 0; virtual grpc_event grpc_completion_queue_pluck(grpc_completion_queue* cq, void* tag, gpr_timespec deadline, void* reserved) = 0; virtual void* gpr_malloc(size_t size) = 0; virtual void gpr_free(void* p) = 0; virtual void gpr_mu_init(gpr_mu* mu) = 0; virtual void gpr_mu_destroy(gpr_mu* mu) = 0; virtual void gpr_mu_lock(gpr_mu* mu) = 0; virtual void gpr_mu_unlock(gpr_mu* mu) = 0; virtual void gpr_cv_init(gpr_cv* cv) = 0; virtual void gpr_cv_destroy(gpr_cv* cv) = 0; virtual int gpr_cv_wait(gpr_cv* cv, gpr_mu* mu, gpr_timespec abs_deadline) = 0; virtual void gpr_cv_signal(gpr_cv* cv) = 0; virtual void gpr_cv_broadcast(gpr_cv* cv) = 0; virtual void grpc_byte_buffer_destroy(grpc_byte_buffer* bb) = 0; virtual int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader* reader, grpc_byte_buffer* buffer) GRPC_MUST_USE_RESULT = 0; virtual void grpc_byte_buffer_reader_destroy( grpc_byte_buffer_reader* reader) = 0; virtual int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader* reader, grpc_slice* slice) = 0; virtual grpc_byte_buffer* grpc_raw_byte_buffer_create(grpc_slice* slice, size_t nslices) = 0; virtual grpc_slice grpc_empty_slice() = 0; virtual grpc_slice grpc_slice_malloc(size_t length) = 0; virtual void grpc_slice_unref(grpc_slice slice) = 0; virtual grpc_slice grpc_slice_split_tail(grpc_slice* s, size_t split) = 0; virtual void grpc_slice_buffer_add(grpc_slice_buffer* sb, grpc_slice slice) = 0; virtual void grpc_slice_buffer_pop(grpc_slice_buffer* sb) = 0; virtual grpc_slice grpc_slice_from_static_buffer(const void* buffer, size_t length) = 0; virtual grpc_slice grpc_slice_from_copied_buffer(const void* buffer, size_t length) = 0; virtual void grpc_metadata_array_init(grpc_metadata_array* array) = 0; virtual void grpc_metadata_array_destroy(grpc_metadata_array* array) = 0; virtual const Status& ok() = 0; virtual const Status& cancelled() = 0; virtual gpr_timespec gpr_inf_future(gpr_clock_type type) = 0; virtual gpr_timespec gpr_time_0(gpr_clock_type type) = 0; }; extern CoreCodegenInterface* g_core_codegen_interface; /// Codegen specific version of \a GPR_ASSERT. #define GPR_CODEGEN_ASSERT(x) \ do { \ if (!(x)) { \ grpc::g_core_codegen_interface->assert_fail(#x, __FILE__, __LINE__); \ } \ } while (0) } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_CORE_CODEGEN_INTERFACE_H grpc-1.3.2/include/grpc++/impl/codegen/create_auth_context.h000066400000000000000000000036411310511640000237150ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_CREATE_AUTH_CONTEXT_H #define GRPCXX_IMPL_CODEGEN_CREATE_AUTH_CONTEXT_H #include #include #include namespace grpc { std::shared_ptr CreateAuthContext(grpc_call* call); } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_CREATE_AUTH_CONTEXT_H grpc-1.3.2/include/grpc++/impl/codegen/grpc_library.h000066400000000000000000000053371310511640000223500ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_GRPC_LIBRARY_H #define GRPCXX_IMPL_CODEGEN_GRPC_LIBRARY_H #include namespace grpc { class GrpcLibraryInterface { public: virtual void init() = 0; virtual void shutdown() = 0; }; /// Initialized by \a grpc::GrpcLibraryInitializer from /// extern GrpcLibraryInterface* g_glip; /// Classes that require gRPC to be initialized should inherit from this class. class GrpcLibraryCodegen { public: GrpcLibraryCodegen(bool call_grpc_init = true) : grpc_init_called_(false) { if (call_grpc_init) { GPR_CODEGEN_ASSERT(g_glip && "gRPC library not initialized. See " "grpc::internal::GrpcLibraryInitializer."); g_glip->init(); grpc_init_called_ = true; } } virtual ~GrpcLibraryCodegen() { if (grpc_init_called_) { GPR_CODEGEN_ASSERT(g_glip && "gRPC library not initialized. See " "grpc::internal::GrpcLibraryInitializer."); g_glip->shutdown(); } } private: bool grpc_init_called_; }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_GRPC_LIBRARY_H grpc-1.3.2/include/grpc++/impl/codegen/metadata_map.h000066400000000000000000000047471310511640000223120ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_METADATA_MAP_H #define GRPCXX_IMPL_CODEGEN_METADATA_MAP_H #include namespace grpc { class MetadataMap { public: MetadataMap() { memset(&arr_, 0, sizeof(arr_)); } ~MetadataMap() { g_core_codegen_interface->grpc_metadata_array_destroy(&arr_); } void FillMap() { for (size_t i = 0; i < arr_.count; i++) { // TODO(yangg) handle duplicates? map_.insert(std::pair( StringRefFromSlice(&arr_.metadata[i].key), StringRefFromSlice(&arr_.metadata[i].value))); } } std::multimap *map() { return &map_; } const std::multimap *map() const { return &map_; } grpc_metadata_array *arr() { return &arr_; } private: grpc_metadata_array arr_; std::multimap map_; }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_METADATA_MAP_H grpc-1.3.2/include/grpc++/impl/codegen/method_handler_impl.h000066400000000000000000000253611310511640000236660ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H #define GRPCXX_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H #include #include #include namespace grpc { // A wrapper class of an application provided rpc method handler. template class RpcMethodHandler : public MethodHandler { public: RpcMethodHandler(std::function func, ServiceType* service) : func_(func), service_(service) {} void RunHandler(const HandlerParameter& param) final { RequestType req; Status status = SerializationTraits::Deserialize(param.request, &req); ResponseType rsp; if (status.ok()) { status = func_(service_, param.server_context, &req, &rsp); } GPR_CODEGEN_ASSERT(!param.server_context->sent_initial_metadata_); CallOpSet ops; ops.SendInitialMetadata(param.server_context->initial_metadata_, param.server_context->initial_metadata_flags()); if (param.server_context->compression_level_set()) { ops.set_compression_level(param.server_context->compression_level()); } if (status.ok()) { status = ops.SendMessage(rsp); } ops.ServerSendStatus(param.server_context->trailing_metadata_, status); param.call->PerformOps(&ops); param.call->cq()->Pluck(&ops); } private: // Application provided rpc handler function. std::function func_; // The class the above handler function lives in. ServiceType* service_; }; // A wrapper class of an application provided client streaming handler. template class ClientStreamingHandler : public MethodHandler { public: ClientStreamingHandler( std::function*, ResponseType*)> func, ServiceType* service) : func_(func), service_(service) {} void RunHandler(const HandlerParameter& param) final { ServerReader reader(param.call, param.server_context); ResponseType rsp; Status status = func_(service_, param.server_context, &reader, &rsp); GPR_CODEGEN_ASSERT(!param.server_context->sent_initial_metadata_); CallOpSet ops; ops.SendInitialMetadata(param.server_context->initial_metadata_, param.server_context->initial_metadata_flags()); if (param.server_context->compression_level_set()) { ops.set_compression_level(param.server_context->compression_level()); } if (status.ok()) { status = ops.SendMessage(rsp); } ops.ServerSendStatus(param.server_context->trailing_metadata_, status); param.call->PerformOps(&ops); param.call->cq()->Pluck(&ops); } private: std::function*, ResponseType*)> func_; ServiceType* service_; }; // A wrapper class of an application provided server streaming handler. template class ServerStreamingHandler : public MethodHandler { public: ServerStreamingHandler( std::function*)> func, ServiceType* service) : func_(func), service_(service) {} void RunHandler(const HandlerParameter& param) final { RequestType req; Status status = SerializationTraits::Deserialize(param.request, &req); if (status.ok()) { ServerWriter writer(param.call, param.server_context); status = func_(service_, param.server_context, &req, &writer); } CallOpSet ops; if (!param.server_context->sent_initial_metadata_) { ops.SendInitialMetadata(param.server_context->initial_metadata_, param.server_context->initial_metadata_flags()); if (param.server_context->compression_level_set()) { ops.set_compression_level(param.server_context->compression_level()); } } ops.ServerSendStatus(param.server_context->trailing_metadata_, status); param.call->PerformOps(&ops); param.call->cq()->Pluck(&ops); } private: std::function*)> func_; ServiceType* service_; }; // A wrapper class of an application provided bidi-streaming handler. // This also applies to server-streamed implementation of a unary method // with the additional requirement that such methods must have done a // write for status to be ok // Since this is used by more than 1 class, the service is not passed in. // Instead, it is expected to be an implicitly-captured argument of func // (through bind or something along those lines) template class TemplatedBidiStreamingHandler : public MethodHandler { public: TemplatedBidiStreamingHandler( std::function func) : func_(func), write_needed_(WriteNeeded) {} void RunHandler(const HandlerParameter& param) final { Streamer stream(param.call, param.server_context); Status status = func_(param.server_context, &stream); CallOpSet ops; if (!param.server_context->sent_initial_metadata_) { ops.SendInitialMetadata(param.server_context->initial_metadata_, param.server_context->initial_metadata_flags()); if (param.server_context->compression_level_set()) { ops.set_compression_level(param.server_context->compression_level()); } if (write_needed_ && status.ok()) { // If we needed a write but never did one, we need to mark the // status as a fail status = Status(StatusCode::INTERNAL, "Service did not provide response message"); } } ops.ServerSendStatus(param.server_context->trailing_metadata_, status); param.call->PerformOps(&ops); param.call->cq()->Pluck(&ops); } private: std::function func_; const bool write_needed_; }; template class BidiStreamingHandler : public TemplatedBidiStreamingHandler< ServerReaderWriter, false> { public: BidiStreamingHandler( std::function*)> func, ServiceType* service) : TemplatedBidiStreamingHandler< ServerReaderWriter, false>(std::bind( func, service, std::placeholders::_1, std::placeholders::_2)) {} }; template class StreamedUnaryHandler : public TemplatedBidiStreamingHandler< ServerUnaryStreamer, true> { public: explicit StreamedUnaryHandler( std::function*)> func) : TemplatedBidiStreamingHandler< ServerUnaryStreamer, true>(func) {} }; template class SplitServerStreamingHandler : public TemplatedBidiStreamingHandler< ServerSplitStreamer, false> { public: explicit SplitServerStreamingHandler( std::function*)> func) : TemplatedBidiStreamingHandler< ServerSplitStreamer, false>(func) {} }; // Handle unknown method by returning UNIMPLEMENTED error. class UnknownMethodHandler : public MethodHandler { public: template static void FillOps(ServerContext* context, T* ops) { Status status(StatusCode::UNIMPLEMENTED, ""); if (!context->sent_initial_metadata_) { ops->SendInitialMetadata(context->initial_metadata_, context->initial_metadata_flags()); if (context->compression_level_set()) { ops->set_compression_level(context->compression_level()); } context->sent_initial_metadata_ = true; } ops->ServerSendStatus(context->trailing_metadata_, status); } void RunHandler(const HandlerParameter& param) final { CallOpSet ops; FillOps(param.server_context, &ops); param.call->PerformOps(&ops); param.call->cq()->Pluck(&ops); } }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H grpc-1.3.2/include/grpc++/impl/codegen/proto_utils.h000066400000000000000000000202541310511640000222470ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_PROTO_UTILS_H #define GRPCXX_IMPL_CODEGEN_PROTO_UTILS_H #include #include #include #include #include #include #include #include namespace grpc { extern CoreCodegenInterface* g_core_codegen_interface; namespace internal { class GrpcBufferWriterPeer; const int kGrpcBufferWriterMaxBufferLength = 8192; class GrpcBufferWriter final : public ::grpc::protobuf::io::ZeroCopyOutputStream { public: explicit GrpcBufferWriter(grpc_byte_buffer** bp, int block_size) : block_size_(block_size), byte_count_(0), have_backup_(false) { *bp = g_core_codegen_interface->grpc_raw_byte_buffer_create(NULL, 0); slice_buffer_ = &(*bp)->data.raw.slice_buffer; } ~GrpcBufferWriter() override { if (have_backup_) { g_core_codegen_interface->grpc_slice_unref(backup_slice_); } } bool Next(void** data, int* size) override { if (have_backup_) { slice_ = backup_slice_; have_backup_ = false; } else { slice_ = g_core_codegen_interface->grpc_slice_malloc(block_size_); } *data = GRPC_SLICE_START_PTR(slice_); // On win x64, int is only 32bit GPR_CODEGEN_ASSERT(GRPC_SLICE_LENGTH(slice_) <= INT_MAX); byte_count_ += * size = (int)GRPC_SLICE_LENGTH(slice_); g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_); return true; } void BackUp(int count) override { g_core_codegen_interface->grpc_slice_buffer_pop(slice_buffer_); if (count == block_size_) { backup_slice_ = slice_; } else { backup_slice_ = g_core_codegen_interface->grpc_slice_split_tail( &slice_, GRPC_SLICE_LENGTH(slice_) - count); g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_); } // It's dangerous to keep an inlined grpc_slice as the backup slice, since // on a following Next() call, a reference will be returned to this slice // via GRPC_SLICE_START_PTR, which will not be an adddress held by // slice_buffer_. have_backup_ = backup_slice_.refcount != NULL; byte_count_ -= count; } grpc::protobuf::int64 ByteCount() const override { return byte_count_; } private: friend class GrpcBufferWriterPeer; const int block_size_; int64_t byte_count_; grpc_slice_buffer* slice_buffer_; bool have_backup_; grpc_slice backup_slice_; grpc_slice slice_; }; class GrpcBufferReader final : public ::grpc::protobuf::io::ZeroCopyInputStream { public: explicit GrpcBufferReader(grpc_byte_buffer* buffer) : byte_count_(0), backup_count_(0), status_() { if (!g_core_codegen_interface->grpc_byte_buffer_reader_init(&reader_, buffer)) { status_ = Status(StatusCode::INTERNAL, "Couldn't initialize byte buffer reader"); } } ~GrpcBufferReader() override { g_core_codegen_interface->grpc_byte_buffer_reader_destroy(&reader_); } bool Next(const void** data, int* size) override { if (!status_.ok()) { return false; } if (backup_count_ > 0) { *data = GRPC_SLICE_START_PTR(slice_) + GRPC_SLICE_LENGTH(slice_) - backup_count_; GPR_CODEGEN_ASSERT(backup_count_ <= INT_MAX); *size = (int)backup_count_; backup_count_ = 0; return true; } if (!g_core_codegen_interface->grpc_byte_buffer_reader_next(&reader_, &slice_)) { return false; } g_core_codegen_interface->grpc_slice_unref(slice_); *data = GRPC_SLICE_START_PTR(slice_); // On win x64, int is only 32bit GPR_CODEGEN_ASSERT(GRPC_SLICE_LENGTH(slice_) <= INT_MAX); byte_count_ += * size = (int)GRPC_SLICE_LENGTH(slice_); return true; } Status status() const { return status_; } void BackUp(int count) override { backup_count_ = count; } bool Skip(int count) override { const void* data; int size; while (Next(&data, &size)) { if (size >= count) { BackUp(size - count); return true; } // size < count; count -= size; } // error or we have too large count; return false; } grpc::protobuf::int64 ByteCount() const override { return byte_count_ - backup_count_; } private: int64_t byte_count_; int64_t backup_count_; grpc_byte_buffer_reader reader_; grpc_slice slice_; Status status_; }; } // namespace internal template class SerializationTraits::value>::type> { public: static Status Serialize(const grpc::protobuf::Message& msg, grpc_byte_buffer** bp, bool* own_buffer) { *own_buffer = true; int byte_size = msg.ByteSize(); if (byte_size <= internal::kGrpcBufferWriterMaxBufferLength) { grpc_slice slice = g_core_codegen_interface->grpc_slice_malloc(byte_size); GPR_CODEGEN_ASSERT( GRPC_SLICE_END_PTR(slice) == msg.SerializeWithCachedSizesToArray(GRPC_SLICE_START_PTR(slice))); *bp = g_core_codegen_interface->grpc_raw_byte_buffer_create(&slice, 1); g_core_codegen_interface->grpc_slice_unref(slice); return g_core_codegen_interface->ok(); } else { internal::GrpcBufferWriter writer( bp, internal::kGrpcBufferWriterMaxBufferLength); return msg.SerializeToZeroCopyStream(&writer) ? g_core_codegen_interface->ok() : Status(StatusCode::INTERNAL, "Failed to serialize message"); } } static Status Deserialize(grpc_byte_buffer* buffer, grpc::protobuf::Message* msg) { if (buffer == nullptr) { return Status(StatusCode::INTERNAL, "No payload"); } Status result = g_core_codegen_interface->ok(); { internal::GrpcBufferReader reader(buffer); if (!reader.status().ok()) { return reader.status(); } ::grpc::protobuf::io::CodedInputStream decoder(&reader); decoder.SetTotalBytesLimit(INT_MAX, INT_MAX); if (!msg->ParseFromCodedStream(&decoder)) { result = Status(StatusCode::INTERNAL, msg->InitializationErrorString()); } if (!decoder.ConsumedEntireMessage()) { result = Status(StatusCode::INTERNAL, "Did not read entire message"); } } g_core_codegen_interface->grpc_byte_buffer_destroy(buffer); return result; } }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_PROTO_UTILS_H grpc-1.3.2/include/grpc++/impl/codegen/rpc_method.h000066400000000000000000000050641310511640000220120ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_RPC_METHOD_H #define GRPCXX_IMPL_CODEGEN_RPC_METHOD_H #include #include namespace grpc { class RpcMethod { public: enum RpcType { NORMAL_RPC = 0, CLIENT_STREAMING, // request streaming SERVER_STREAMING, // response streaming BIDI_STREAMING }; RpcMethod(const char* name, RpcType type) : name_(name), method_type_(type), channel_tag_(NULL) {} RpcMethod(const char* name, RpcType type, const std::shared_ptr& channel) : name_(name), method_type_(type), channel_tag_(channel->RegisterMethod(name)) {} const char* name() const { return name_; } RpcType method_type() const { return method_type_; } void SetMethodType(RpcType type) { method_type_ = type; } void* channel_tag() const { return channel_tag_; } private: const char* const name_; RpcType method_type_; void* const channel_tag_; }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_RPC_METHOD_H grpc-1.3.2/include/grpc++/impl/codegen/rpc_service_method.h000066400000000000000000000063121310511640000235270ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_RPC_SERVICE_METHOD_H #define GRPCXX_IMPL_CODEGEN_RPC_SERVICE_METHOD_H #include #include #include #include #include #include #include #include extern "C" { struct grpc_byte_buffer; } namespace grpc { class ServerContext; class StreamContextInterface; // Base class for running an RPC handler. class MethodHandler { public: virtual ~MethodHandler() {} struct HandlerParameter { HandlerParameter(Call* c, ServerContext* context, grpc_byte_buffer* req) : call(c), server_context(context), request(req) {} Call* call; ServerContext* server_context; // Handler required to grpc_byte_buffer_destroy this grpc_byte_buffer* request; }; virtual void RunHandler(const HandlerParameter& param) = 0; }; // Server side rpc method class class RpcServiceMethod : public RpcMethod { public: // Takes ownership of the handler RpcServiceMethod(const char* name, RpcMethod::RpcType type, MethodHandler* handler) : RpcMethod(name, type), server_tag_(nullptr), handler_(handler) {} void set_server_tag(void* tag) { server_tag_ = tag; } void* server_tag() const { return server_tag_; } // if MethodHandler is nullptr, then this is an async method MethodHandler* handler() const { return handler_.get(); } void ResetHandler() { handler_.reset(); } void SetHandler(MethodHandler* handler) { handler_.reset(handler); } private: void* server_tag_; std::unique_ptr handler_; }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_RPC_SERVICE_METHOD_H grpc-1.3.2/include/grpc++/impl/codegen/security/000077500000000000000000000000001310511640000213575ustar00rootroot00000000000000grpc-1.3.2/include/grpc++/impl/codegen/security/auth_context.h000066400000000000000000000077071310511640000242500ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_SECURITY_AUTH_CONTEXT_H #define GRPCXX_IMPL_CODEGEN_SECURITY_AUTH_CONTEXT_H #include #include #include #include struct grpc_auth_context; struct grpc_auth_property; struct grpc_auth_property_iterator; namespace grpc { class SecureAuthContext; typedef std::pair AuthProperty; class AuthPropertyIterator : public std::iterator { public: ~AuthPropertyIterator(); AuthPropertyIterator& operator++(); AuthPropertyIterator operator++(int); bool operator==(const AuthPropertyIterator& rhs) const; bool operator!=(const AuthPropertyIterator& rhs) const; const AuthProperty operator*(); protected: AuthPropertyIterator(); AuthPropertyIterator(const grpc_auth_property* property, const grpc_auth_property_iterator* iter); private: friend class SecureAuthContext; const grpc_auth_property* property_; // The following items form a grpc_auth_property_iterator. const grpc_auth_context* ctx_; size_t index_; const char* name_; }; /// Class encapsulating the Authentication Information. /// /// It includes the secure identity of the peer, the type of secure transport /// used as well as any other properties required by the authorization layer. class AuthContext { public: virtual ~AuthContext() {} /// Returns true if the peer is authenticated. virtual bool IsPeerAuthenticated() const = 0; /// A peer identity. /// /// It is, in general, comprised of one or more properties (in which case they /// have the same name). virtual std::vector GetPeerIdentity() const = 0; virtual grpc::string GetPeerIdentityPropertyName() const = 0; /// Returns all the property values with the given name. virtual std::vector FindPropertyValues( const grpc::string& name) const = 0; /// Iteration over all the properties. virtual AuthPropertyIterator begin() const = 0; virtual AuthPropertyIterator end() const = 0; // Mutation functions: should only be used by an AuthMetadataProcessor. virtual void AddProperty(const grpc::string& key, const grpc::string_ref& value) = 0; virtual bool SetPeerIdentityPropertyName(const grpc::string& name) = 0; }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_SECURITY_AUTH_CONTEXT_H grpc-1.3.2/include/grpc++/impl/codegen/serialization_traits.h000066400000000000000000000056531310511640000241350ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_SERIALIZATION_TRAITS_H #define GRPCXX_IMPL_CODEGEN_SERIALIZATION_TRAITS_H namespace grpc { /// Defines how to serialize and deserialize some type. /// /// Used for hooking different message serialization API's into GRPC. /// Each SerializationTraits implementation must provide the following /// functions: /// static Status Serialize(const Message& msg, /// grpc_byte_buffer** buffer, /// bool* own_buffer); /// static Status Deserialize(grpc_byte_buffer* buffer, /// Message* msg, /// int max_receive_message_size); /// /// Serialize is required to convert message to a grpc_byte_buffer, and /// to store a pointer to that byte buffer at *buffer. *own_buffer should /// be set to true if the caller owns said byte buffer, or false if /// ownership is retained elsewhere. /// /// Deserialize is required to convert buffer into the message stored at /// msg. max_receive_message_size is passed in as a bound on the maximum /// number of message bytes Deserialize should accept. /// /// Both functions return a Status, allowing them to explain what went /// wrong if required. template class SerializationTraits; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_SERIALIZATION_TRAITS_H grpc-1.3.2/include/grpc++/impl/codegen/server_context.h000066400000000000000000000203061310511640000227340ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_SERVER_CONTEXT_H #define GRPCXX_IMPL_CODEGEN_SERVER_CONTEXT_H #include #include #include #include #include #include #include #include #include #include struct grpc_metadata; struct grpc_call; struct census_context; namespace grpc { class ClientContext; template class ServerAsyncReader; template class ServerAsyncWriter; template class ServerAsyncResponseWriter; template class ServerAsyncReaderWriter; template class ServerReader; template class ServerWriter; namespace internal { template class ServerReaderWriterBody; } template class RpcMethodHandler; template class ClientStreamingHandler; template class ServerStreamingHandler; template class BidiStreamingHandler; class UnknownMethodHandler; class Call; class CallOpBuffer; class CompletionQueue; class Server; class ServerInterface; namespace testing { class InteropServerContextInspector; class ServerContextTestSpouse; } // namespace testing // Interface of server side rpc context. class ServerContext { public: ServerContext(); // for async calls ~ServerContext(); std::chrono::system_clock::time_point deadline() const { return Timespec2Timepoint(deadline_); } gpr_timespec raw_deadline() const { return deadline_; } void AddInitialMetadata(const grpc::string& key, const grpc::string& value); void AddTrailingMetadata(const grpc::string& key, const grpc::string& value); // IsCancelled is always safe to call when using sync API // When using async API, it is only safe to call IsCancelled after // the AsyncNotifyWhenDone tag has been delivered bool IsCancelled() const; // Cancel the Call from the server. This is a best-effort API and depending on // when it is called, the RPC may still appear successful to the client. // For example, if TryCancel() is called on a separate thread, it might race // with the server handler which might return success to the client before // TryCancel() was even started by the thread. // // It is the caller's responsibility to prevent such races and ensure that if // TryCancel() is called, the serverhandler must return Status::CANCELLED. The // only exception is that if the serverhandler is already returning an error // status code, it is ok to not return Status::CANCELLED even if TryCancel() // was called. void TryCancel() const; const std::multimap& client_metadata() const { return *client_metadata_.map(); } grpc_compression_level compression_level() const { return compression_level_; } void set_compression_level(grpc_compression_level level) { compression_level_set_ = true; compression_level_ = level; } bool compression_level_set() const { return compression_level_set_; } grpc_compression_algorithm compression_algorithm() const { return compression_algorithm_; } void set_compression_algorithm(grpc_compression_algorithm algorithm); // Set the load reporting costs in \a cost_data for the call. void SetLoadReportingCosts(const std::vector& cost_data); std::shared_ptr auth_context() const { if (auth_context_.get() == nullptr) { auth_context_ = CreateAuthContext(call_); } return auth_context_; } // Return the peer uri in a string. // WARNING: this value is never authenticated or subject to any security // related code. It must not be used for any authentication related // functionality. Instead, use auth_context. grpc::string peer() const; const struct census_context* census_context() const; // Async only. Has to be called before the rpc starts. // Returns the tag in completion queue when the rpc finishes. // IsCancelled() can then be called to check whether the rpc was cancelled. void AsyncNotifyWhenDone(void* tag) { has_notify_when_done_tag_ = true; async_notify_when_done_tag_ = tag; } // Should be used for framework-level extensions only. // Applications never need to call this method. grpc_call* c_call() { return call_; } private: friend class ::grpc::testing::InteropServerContextInspector; friend class ::grpc::testing::ServerContextTestSpouse; friend class ::grpc::ServerInterface; friend class ::grpc::Server; template friend class ::grpc::ServerAsyncReader; template friend class ::grpc::ServerAsyncWriter; template friend class ::grpc::ServerAsyncResponseWriter; template friend class ::grpc::ServerAsyncReaderWriter; template friend class ::grpc::ServerReader; template friend class ::grpc::ServerWriter; template friend class ::grpc::internal::ServerReaderWriterBody; template friend class RpcMethodHandler; template friend class ClientStreamingHandler; template friend class ServerStreamingHandler; template friend class TemplatedBidiStreamingHandler; friend class UnknownMethodHandler; friend class ::grpc::ClientContext; // Prevent copying. ServerContext(const ServerContext&); ServerContext& operator=(const ServerContext&); class CompletionOp; void BeginCompletionOp(Call* call); ServerContext(gpr_timespec deadline, grpc_metadata_array* arr); void set_call(grpc_call* call) { call_ = call; } uint32_t initial_metadata_flags() const { return 0; } CompletionOp* completion_op_; bool has_notify_when_done_tag_; void* async_notify_when_done_tag_; gpr_timespec deadline_; grpc_call* call_; CompletionQueue* cq_; bool sent_initial_metadata_; mutable std::shared_ptr auth_context_; MetadataMap client_metadata_; std::multimap initial_metadata_; std::multimap trailing_metadata_; bool compression_level_set_; grpc_compression_level compression_level_; grpc_compression_algorithm compression_algorithm_; }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_SERVER_CONTEXT_H grpc-1.3.2/include/grpc++/impl/codegen/server_interface.h000066400000000000000000000235221310511640000232130ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_SERVER_INTERFACE_H #define GRPCXX_IMPL_CODEGEN_SERVER_INTERFACE_H #include #include #include #include #include namespace grpc { class AsyncGenericService; class GenericServerContext; class RpcService; class ServerAsyncStreamingInterface; class ServerCompletionQueue; class ServerContext; class ServerCredentials; class Service; class ThreadPoolInterface; extern CoreCodegenInterface* g_core_codegen_interface; /// Models a gRPC server. /// /// Servers are configured and started via \a grpc::ServerBuilder. class ServerInterface : public CallHook { public: virtual ~ServerInterface() {} /// Shutdown the server, blocking until all rpc processing finishes. /// Forcefully terminate pending calls after \a deadline expires. /// /// All completion queue associated with the server (for example, for async /// serving) must be shutdown *after* this method has returned: /// See \a ServerBuilder::AddCompletionQueue for details. /// /// \param deadline How long to wait until pending rpcs are forcefully /// terminated. template void Shutdown(const T& deadline) { ShutdownInternal(TimePoint(deadline).raw_time()); } /// Shutdown the server, waiting for all rpc processing to finish. /// /// All completion queue associated with the server (for example, for async /// serving) must be shutdown *after* this method has returned: /// See \a ServerBuilder::AddCompletionQueue for details. void Shutdown() { ShutdownInternal( g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_MONOTONIC)); } /// Block waiting for all work to complete. /// /// \warning The server must be either shutting down or some other thread must /// call \a Shutdown for this function to ever return. virtual void Wait() = 0; protected: friend class Service; /// Register a service. This call does not take ownership of the service. /// The service must exist for the lifetime of the Server instance. virtual bool RegisterService(const grpc::string* host, Service* service) = 0; /// Register a generic service. This call does not take ownership of the /// service. The service must exist for the lifetime of the Server instance. virtual void RegisterAsyncGenericService(AsyncGenericService* service) = 0; /// Tries to bind \a server to the given \a addr. /// /// It can be invoked multiple times. /// /// \param addr The address to try to bind to the server (eg, localhost:1234, /// 192.168.1.1:31416, [::1]:27182, etc.). /// \params creds The credentials associated with the server. /// /// \return bound port number on sucess, 0 on failure. /// /// \warning It's an error to call this method on an already started server. virtual int AddListeningPort(const grpc::string& addr, ServerCredentials* creds) = 0; /// Start the server. /// /// \param cqs Completion queues for handling asynchronous services. The /// caller is required to keep all completion queues live until the server is /// destroyed. /// \param num_cqs How many completion queues does \a cqs hold. /// /// \return true on a successful shutdown. virtual bool Start(ServerCompletionQueue** cqs, size_t num_cqs) = 0; virtual void ShutdownInternal(gpr_timespec deadline) = 0; virtual int max_receive_message_size() const = 0; virtual grpc_server* server() = 0; virtual void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) = 0; class BaseAsyncRequest : public CompletionQueueTag { public: BaseAsyncRequest(ServerInterface* server, ServerContext* context, ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, void* tag, bool delete_on_finalize); virtual ~BaseAsyncRequest(); bool FinalizeResult(void** tag, bool* status) override; protected: ServerInterface* const server_; ServerContext* const context_; ServerAsyncStreamingInterface* const stream_; CompletionQueue* const call_cq_; void* const tag_; const bool delete_on_finalize_; grpc_call* call_; }; class RegisteredAsyncRequest : public BaseAsyncRequest { public: RegisteredAsyncRequest(ServerInterface* server, ServerContext* context, ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, void* tag); // uses BaseAsyncRequest::FinalizeResult protected: void IssueRequest(void* registered_method, grpc_byte_buffer** payload, ServerCompletionQueue* notification_cq); }; class NoPayloadAsyncRequest final : public RegisteredAsyncRequest { public: NoPayloadAsyncRequest(void* registered_method, ServerInterface* server, ServerContext* context, ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, ServerCompletionQueue* notification_cq, void* tag) : RegisteredAsyncRequest(server, context, stream, call_cq, tag) { IssueRequest(registered_method, nullptr, notification_cq); } // uses RegisteredAsyncRequest::FinalizeResult }; template class PayloadAsyncRequest final : public RegisteredAsyncRequest { public: PayloadAsyncRequest(void* registered_method, ServerInterface* server, ServerContext* context, ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, ServerCompletionQueue* notification_cq, void* tag, Message* request) : RegisteredAsyncRequest(server, context, stream, call_cq, tag), request_(request) { IssueRequest(registered_method, &payload_, notification_cq); } bool FinalizeResult(void** tag, bool* status) override { bool serialization_status = *status && payload_ && SerializationTraits::Deserialize(payload_, request_).ok(); bool ret = RegisteredAsyncRequest::FinalizeResult(tag, status); *status = serialization_status && *status; return ret; } private: grpc_byte_buffer* payload_; Message* const request_; }; class GenericAsyncRequest : public BaseAsyncRequest { public: GenericAsyncRequest(ServerInterface* server, GenericServerContext* context, ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, ServerCompletionQueue* notification_cq, void* tag, bool delete_on_finalize); bool FinalizeResult(void** tag, bool* status) override; private: grpc_call_details call_details_; }; template void RequestAsyncCall(RpcServiceMethod* method, ServerContext* context, ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, ServerCompletionQueue* notification_cq, void* tag, Message* message) { GPR_CODEGEN_ASSERT(method); new PayloadAsyncRequest(method->server_tag(), this, context, stream, call_cq, notification_cq, tag, message); } void RequestAsyncCall(RpcServiceMethod* method, ServerContext* context, ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, ServerCompletionQueue* notification_cq, void* tag) { GPR_CODEGEN_ASSERT(method); new NoPayloadAsyncRequest(method->server_tag(), this, context, stream, call_cq, notification_cq, tag); } void RequestAsyncGenericCall(GenericServerContext* context, ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, ServerCompletionQueue* notification_cq, void* tag) { new GenericAsyncRequest(this, context, stream, call_cq, notification_cq, tag, true); } }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_SERVER_INTERFACE_H grpc-1.3.2/include/grpc++/impl/codegen/service_type.h000066400000000000000000000143321310511640000223650ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_SERVICE_TYPE_H #define GRPCXX_IMPL_CODEGEN_SERVICE_TYPE_H #include #include #include #include #include #include namespace grpc { class Call; class CompletionQueue; class Server; class ServerInterface; class ServerCompletionQueue; class ServerContext; class ServerAsyncStreamingInterface { public: virtual ~ServerAsyncStreamingInterface() {} virtual void SendInitialMetadata(void* tag) = 0; private: friend class ServerInterface; virtual void BindCall(Call* call) = 0; }; class Service { public: Service() : server_(nullptr) {} virtual ~Service() {} bool has_async_methods() const { for (auto it = methods_.begin(); it != methods_.end(); ++it) { if (*it && (*it)->handler() == nullptr) { return true; } } return false; } bool has_synchronous_methods() const { for (auto it = methods_.begin(); it != methods_.end(); ++it) { if (*it && (*it)->handler() != nullptr) { return true; } } return false; } bool has_generic_methods() const { for (auto it = methods_.begin(); it != methods_.end(); ++it) { if (it->get() == nullptr) { return true; } } return false; } protected: template void RequestAsyncUnary(int index, ServerContext* context, Message* request, ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, ServerCompletionQueue* notification_cq, void* tag) { server_->RequestAsyncCall(methods_[index].get(), context, stream, call_cq, notification_cq, tag, request); } void RequestAsyncClientStreaming(int index, ServerContext* context, ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, ServerCompletionQueue* notification_cq, void* tag) { server_->RequestAsyncCall(methods_[index].get(), context, stream, call_cq, notification_cq, tag); } template void RequestAsyncServerStreaming(int index, ServerContext* context, Message* request, ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, ServerCompletionQueue* notification_cq, void* tag) { server_->RequestAsyncCall(methods_[index].get(), context, stream, call_cq, notification_cq, tag, request); } void RequestAsyncBidiStreaming(int index, ServerContext* context, ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, ServerCompletionQueue* notification_cq, void* tag) { server_->RequestAsyncCall(methods_[index].get(), context, stream, call_cq, notification_cq, tag); } void AddMethod(RpcServiceMethod* method) { methods_.emplace_back(method); } void MarkMethodAsync(int index) { GPR_CODEGEN_ASSERT( methods_[index].get() != nullptr && "Cannot mark the method as 'async' because it has already been " "marked as 'generic'."); methods_[index]->ResetHandler(); } void MarkMethodGeneric(int index) { GPR_CODEGEN_ASSERT( methods_[index]->handler() != nullptr && "Cannot mark the method as 'generic' because it has already been " "marked as 'async'."); methods_[index].reset(); } void MarkMethodStreamed(int index, MethodHandler* streamed_method) { GPR_CODEGEN_ASSERT(methods_[index] && methods_[index]->handler() && "Cannot mark an async or generic method Streamed"); methods_[index]->SetHandler(streamed_method); // From the server's point of view, streamed unary is a special // case of BIDI_STREAMING that has 1 read and 1 write, in that order, // and split server-side streaming is BIDI_STREAMING with 1 read and // any number of writes, in that order methods_[index]->SetMethodType(::grpc::RpcMethod::BIDI_STREAMING); } private: friend class Server; friend class ServerInterface; ServerInterface* server_; std::vector> methods_; }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_SERVICE_TYPE_H grpc-1.3.2/include/grpc++/impl/codegen/slice.h000066400000000000000000000051551310511640000207660ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_SLICE_H #define GRPCXX_IMPL_CODEGEN_SLICE_H #include #include namespace grpc { inline grpc::string_ref StringRefFromSlice(const grpc_slice* slice) { return grpc::string_ref( reinterpret_cast(GRPC_SLICE_START_PTR(*slice)), GRPC_SLICE_LENGTH(*slice)); } inline grpc::string StringFromCopiedSlice(grpc_slice slice) { return grpc::string(reinterpret_cast(GRPC_SLICE_START_PTR(slice)), GRPC_SLICE_LENGTH(slice)); } inline grpc_slice SliceReferencingString(const grpc::string& str) { return g_core_codegen_interface->grpc_slice_from_static_buffer(str.data(), str.length()); } inline grpc_slice SliceFromCopiedString(const grpc::string& str) { return g_core_codegen_interface->grpc_slice_from_copied_buffer(str.data(), str.length()); } } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_SLICE_H grpc-1.3.2/include/grpc++/impl/codegen/status.h000066400000000000000000000062601310511640000212100ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_STATUS_H #define GRPCXX_IMPL_CODEGEN_STATUS_H #include #include namespace grpc { /// Did it work? If it didn't, why? /// /// See \a grpc::StatusCode for details on the available code and their meaning. class Status { public: /// Construct an OK instance. Status() : code_(StatusCode::OK) {} /// Construct an instance with associated \a code and \a error_message Status(StatusCode code, const grpc::string& error_message) : code_(code), error_message_(error_message) {} /// Construct an instance with \a code, \a error_message and \a error_details Status(StatusCode code, const grpc::string& error_message, const grpc::string& error_details) : code_(code), error_message_(error_message), binary_error_details_(error_details) {} // Pre-defined special status objects. /// An OK pre-defined instance. static const Status& OK; /// A CANCELLED pre-defined instance. static const Status& CANCELLED; /// Return the instance's error code. StatusCode error_code() const { return code_; } /// Return the instance's error message. grpc::string error_message() const { return error_message_; } /// Return the (binary) error details. // Usually it contains a serialized google.rpc.Status proto. grpc::string error_details() const { return binary_error_details_; } /// Is the status OK? bool ok() const { return code_ == StatusCode::OK; } private: StatusCode code_; grpc::string error_message_; grpc::string binary_error_details_; }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_STATUS_H grpc-1.3.2/include/grpc++/impl/codegen/status_code_enum.h000066400000000000000000000147631310511640000232350ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_STATUS_CODE_ENUM_H #define GRPCXX_IMPL_CODEGEN_STATUS_CODE_ENUM_H namespace grpc { enum StatusCode { /// Not an error; returned on success. OK = 0, /// The operation was cancelled (typically by the caller). CANCELLED = 1, /// Unknown error. An example of where this error may be returned is if a /// Status value received from another address space belongs to an error-space /// that is not known in this address space. Also errors raised by APIs that /// do not return enough error information may be converted to this error. UNKNOWN = 2, /// Client specified an invalid argument. Note that this differs from /// FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments that are /// problematic regardless of the state of the system (e.g., a malformed file /// name). INVALID_ARGUMENT = 3, /// Deadline expired before operation could complete. For operations that /// change the state of the system, this error may be returned even if the /// operation has completed successfully. For example, a successful response /// from a server could have been delayed long enough for the deadline to /// expire. DEADLINE_EXCEEDED = 4, /// Some requested entity (e.g., file or directory) was not found. NOT_FOUND = 5, /// Some entity that we attempted to create (e.g., file or directory) already /// exists. ALREADY_EXISTS = 6, /// The caller does not have permission to execute the specified operation. /// PERMISSION_DENIED must not be used for rejections caused by exhausting /// some resource (use RESOURCE_EXHAUSTED instead for those errors). /// PERMISSION_DENIED must not be used if the caller can not be identified /// (use UNAUTHENTICATED instead for those errors). PERMISSION_DENIED = 7, /// The request does not have valid authentication credentials for the /// operation. UNAUTHENTICATED = 16, /// Some resource has been exhausted, perhaps a per-user quota, or perhaps the /// entire file system is out of space. RESOURCE_EXHAUSTED = 8, /// Operation was rejected because the system is not in a state required for /// the operation's execution. For example, directory to be deleted may be /// non-empty, an rmdir operation is applied to a non-directory, etc. /// /// A litmus test that may help a service implementor in deciding /// between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE: /// (a) Use UNAVAILABLE if the client can retry just the failing call. /// (b) Use ABORTED if the client should retry at a higher-level /// (e.g., restarting a read-modify-write sequence). /// (c) Use FAILED_PRECONDITION if the client should not retry until /// the system state has been explicitly fixed. E.g., if an "rmdir" /// fails because the directory is non-empty, FAILED_PRECONDITION /// should be returned since the client should not retry unless /// they have first fixed up the directory by deleting files from it. /// (d) Use FAILED_PRECONDITION if the client performs conditional /// REST Get/Update/Delete on a resource and the resource on the /// server does not match the condition. E.g., conflicting /// read-modify-write on the same resource. FAILED_PRECONDITION = 9, /// The operation was aborted, typically due to a concurrency issue like /// sequencer check failures, transaction aborts, etc. /// /// See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, /// and UNAVAILABLE. ABORTED = 10, /// Operation was attempted past the valid range. E.g., seeking or reading /// past end of file. /// /// Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed /// if the system state changes. For example, a 32-bit file system will /// generate INVALID_ARGUMENT if asked to read at an offset that is not in the /// range [0,2^32-1], but it will generate OUT_OF_RANGE if asked to read from /// an offset past the current file size. /// /// There is a fair bit of overlap between FAILED_PRECONDITION and /// OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific error) /// when it applies so that callers who are iterating through a space can /// easily look for an OUT_OF_RANGE error to detect when they are done. OUT_OF_RANGE = 11, /// Operation is not implemented or not supported/enabled in this service. UNIMPLEMENTED = 12, /// Internal errors. Means some invariants expected by underlying System has /// been broken. If you see one of these errors, Something is very broken. INTERNAL = 13, /// The service is currently unavailable. This is a most likely a transient /// condition and may be corrected by retrying with a backoff. /// /// See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, /// and UNAVAILABLE. UNAVAILABLE = 14, /// Unrecoverable data loss or corruption. DATA_LOSS = 15, /// Force users to include a default branch: DO_NOT_USE = -1 }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_STATUS_CODE_ENUM_H grpc-1.3.2/include/grpc++/impl/codegen/status_helper.h000066400000000000000000000035271310511640000225520ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_STATUS_HELPER_H #define GRPCXX_IMPL_CODEGEN_STATUS_HELPER_H #include namespace grpc { inline StatusCode GetCanonicalCode(const Status& status) { return status.error_code(); } } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_STATUS_HELPER_H grpc-1.3.2/include/grpc++/impl/codegen/string_ref.h000066400000000000000000000125761310511640000220360ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_STRING_REF_H #define GRPCXX_IMPL_CODEGEN_STRING_REF_H #include #include #include #include #include #include namespace grpc { /// This class is a non owning reference to a string. /// /// It should be a strict subset of the upcoming std::string_ref. /// /// \see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html /// /// The constexpr is dropped or replaced with const for legacy compiler /// compatibility. class string_ref { public: // types typedef const char* const_iterator; typedef std::reverse_iterator const_reverse_iterator; // constants const static size_t npos; // construct/copy. string_ref() : data_(nullptr), length_(0) {} string_ref(const string_ref& other) : data_(other.data_), length_(other.length_) {} string_ref& operator=(const string_ref& rhs) { data_ = rhs.data_; length_ = rhs.length_; return *this; } string_ref(const char* s) : data_(s), length_(strlen(s)) {} string_ref(const char* s, size_t l) : data_(s), length_(l) {} string_ref(const grpc::string& s) : data_(s.data()), length_(s.length()) {} // iterators const_iterator begin() const { return data_; } const_iterator end() const { return data_ + length_; } const_iterator cbegin() const { return data_; } const_iterator cend() const { return data_ + length_; } const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); } const_reverse_iterator crend() const { return const_reverse_iterator(begin()); } // capacity size_t size() const { return length_; } size_t length() const { return length_; } size_t max_size() const { return length_; } bool empty() const { return length_ == 0; } // element access const char* data() const { return data_; } // string operations int compare(string_ref x) const { size_t min_size = length_ < x.length_ ? length_ : x.length_; int r = memcmp(data_, x.data_, min_size); if (r < 0) return -1; if (r > 0) return 1; if (length_ < x.length_) return -1; if (length_ > x.length_) return 1; return 0; } bool starts_with(string_ref x) const { return length_ >= x.length_ && (memcmp(data_, x.data_, x.length_) == 0); } bool ends_with(string_ref x) const { return length_ >= x.length_ && (memcmp(data_ + (length_ - x.length_), x.data_, x.length_) == 0); } size_t find(string_ref s) const { auto it = std::search(cbegin(), cend(), s.cbegin(), s.cend()); return it == cend() ? npos : std::distance(cbegin(), it); } size_t find(char c) const { auto it = std::find(cbegin(), cend(), c); return it == cend() ? npos : std::distance(cbegin(), it); } string_ref substr(size_t pos, size_t n = npos) const { if (pos > length_) pos = length_; if (n > (length_ - pos)) n = length_ - pos; return string_ref(data_ + pos, n); } private: const char* data_; size_t length_; }; // Comparison operators inline bool operator==(string_ref x, string_ref y) { return x.compare(y) == 0; } inline bool operator!=(string_ref x, string_ref y) { return x.compare(y) != 0; } inline bool operator<(string_ref x, string_ref y) { return x.compare(y) < 0; } inline bool operator<=(string_ref x, string_ref y) { return x.compare(y) <= 0; } inline bool operator>(string_ref x, string_ref y) { return x.compare(y) > 0; } inline bool operator>=(string_ref x, string_ref y) { return x.compare(y) >= 0; } inline std::ostream& operator<<(std::ostream& out, const string_ref& string) { return out << grpc::string(string.begin(), string.end()); } } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_STRING_REF_H grpc-1.3.2/include/grpc++/impl/codegen/stub_options.h000066400000000000000000000033461310511640000224170ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_STUB_OPTIONS_H #define GRPCXX_IMPL_CODEGEN_STUB_OPTIONS_H namespace grpc { class StubOptions {}; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_STUB_OPTIONS_H grpc-1.3.2/include/grpc++/impl/codegen/sync_stream.h000066400000000000000000000542161310511640000222200ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_SYNC_STREAM_H #define GRPCXX_IMPL_CODEGEN_SYNC_STREAM_H #include #include #include #include #include #include #include #include namespace grpc { /// Common interface for all synchronous client side streaming. class ClientStreamingInterface { public: virtual ~ClientStreamingInterface() {} /// Wait until the stream finishes, and return the final status. When the /// client side declares it has no more message to send, either implicitly or /// by calling \a WritesDone(), it needs to make sure there is no more message /// to be received from the server, either implicitly or by getting a false /// from a \a Read(). /// /// This function will return either: /// - when all incoming messages have been read and the server has returned /// status. /// - OR when the server has returned a non-OK status. virtual Status Finish() = 0; }; /// Common interface for all synchronous server side streaming. class ServerStreamingInterface { public: virtual ~ServerStreamingInterface() {} /// Blocking send initial metadata to client. virtual void SendInitialMetadata() = 0; }; /// An interface that yields a sequence of messages of type \a R. template class ReaderInterface { public: virtual ~ReaderInterface() {} /// Upper bound on the next message size available for reading on this stream virtual bool NextMessageSize(uint32_t* sz) = 0; /// Blocking read a message and parse to \a msg. Returns \a true on success. /// This is thread-safe with respect to \a Write or \WritesDone methods on /// the same stream. It should not be called concurrently with another \a /// Read on the same stream as the order of delivery will not be defined. /// /// \param[out] msg The read message. /// /// \return \a false when there will be no more incoming messages, either /// because the other side has called \a WritesDone() or the stream has failed /// (or been cancelled). virtual bool Read(R* msg) = 0; }; /// An interface that can be fed a sequence of messages of type \a W. template class WriterInterface { public: virtual ~WriterInterface() {} /// Blocking write \a msg to the stream with WriteOptions \a options. /// This is thread-safe with respect to \a Read /// /// \param msg The message to be written to the stream. /// \param options The WriteOptions affecting the write operation. /// /// \return \a true on success, \a false when the stream has been closed. virtual bool Write(const W& msg, WriteOptions options) = 0; /// Blocking write \a msg to the stream with default write options. /// This is thread-safe with respect to \a Read /// /// \param msg The message to be written to the stream. /// /// \return \a true on success, \a false when the stream has been closed. inline bool Write(const W& msg) { return Write(msg, WriteOptions()); } /// Write \a msg and coalesce it with the writing of trailing metadata, using /// WriteOptions \a options. /// /// For client, WriteLast is equivalent of performing Write and WritesDone in /// a single step. \a msg and trailing metadata are coalesced and sent on wire /// by calling this function. /// For server, WriteLast buffers the \a msg. The writing of \a msg is held /// until the service handler returns, where \a msg and trailing metadata are /// coalesced and sent on wire. Note that WriteLast can only buffer \a msg up /// to the flow control window size. If \a msg size is larger than the window /// size, it will be sent on wire without buffering. /// /// \param[in] msg The message to be written to the stream. /// \param[in] options The WriteOptions to be used to write this message. void WriteLast(const W& msg, WriteOptions options) { Write(msg, options.set_last_message()); } }; /// Client-side interface for streaming reads of message of type \a R. template class ClientReaderInterface : public ClientStreamingInterface, public ReaderInterface { public: /// Blocking wait for initial metadata from server. The received metadata /// can only be accessed after this call returns. Should only be called before /// the first read. Calling this method is optional, and if it is not called /// the metadata will be available in ClientContext after the first read. virtual void WaitForInitialMetadata() = 0; }; template class ClientReader final : public ClientReaderInterface { public: /// Blocking create a stream and write the first request out. template ClientReader(ChannelInterface* channel, const RpcMethod& method, ClientContext* context, const W& request) : context_(context), call_(channel->CreateCall(method, context, &cq_)) { CallOpSet ops; ops.SendInitialMetadata(context->send_initial_metadata_, context->initial_metadata_flags()); // TODO(ctiller): don't assert GPR_CODEGEN_ASSERT(ops.SendMessage(request).ok()); ops.ClientSendClose(); call_.PerformOps(&ops); cq_.Pluck(&ops); } void WaitForInitialMetadata() override { GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_); CallOpSet ops; ops.RecvInitialMetadata(context_); call_.PerformOps(&ops); cq_.Pluck(&ops); /// status ignored } bool NextMessageSize(uint32_t* sz) override { *sz = call_.max_receive_message_size(); return true; } bool Read(R* msg) override { CallOpSet> ops; if (!context_->initial_metadata_received_) { ops.RecvInitialMetadata(context_); } ops.RecvMessage(msg); call_.PerformOps(&ops); return cq_.Pluck(&ops) && ops.got_message; } Status Finish() override { CallOpSet ops; Status status; ops.ClientRecvStatus(context_, &status); call_.PerformOps(&ops); GPR_CODEGEN_ASSERT(cq_.Pluck(&ops)); return status; } private: ClientContext* context_; CompletionQueue cq_; Call call_; }; /// Client-side interface for streaming writes of message of type \a W. template class ClientWriterInterface : public ClientStreamingInterface, public WriterInterface { public: /// Half close writing from the client. /// Block until currently-pending writes are completed. /// Thread safe with respect to \a Read operations only /// /// \return Whether the writes were successful. virtual bool WritesDone() = 0; }; template class ClientWriter : public ClientWriterInterface { public: /// Blocking create a stream. template ClientWriter(ChannelInterface* channel, const RpcMethod& method, ClientContext* context, R* response) : context_(context), call_(channel->CreateCall(method, context, &cq_)) { finish_ops_.RecvMessage(response); finish_ops_.AllowNoMessage(); if (!context_->initial_metadata_corked_) { CallOpSet ops; ops.SendInitialMetadata(context->send_initial_metadata_, context->initial_metadata_flags()); call_.PerformOps(&ops); cq_.Pluck(&ops); } } void WaitForInitialMetadata() { GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_); CallOpSet ops; ops.RecvInitialMetadata(context_); call_.PerformOps(&ops); cq_.Pluck(&ops); // status ignored } using WriterInterface::Write; bool Write(const W& msg, WriteOptions options) override { CallOpSet ops; if (options.is_last_message()) { options.set_buffer_hint(); ops.ClientSendClose(); } if (context_->initial_metadata_corked_) { ops.SendInitialMetadata(context_->send_initial_metadata_, context_->initial_metadata_flags()); context_->set_initial_metadata_corked(false); } if (!ops.SendMessage(msg, options).ok()) { return false; } call_.PerformOps(&ops); return cq_.Pluck(&ops); } bool WritesDone() override { CallOpSet ops; ops.ClientSendClose(); call_.PerformOps(&ops); return cq_.Pluck(&ops); } /// Read the final response and wait for the final status. Status Finish() override { Status status; if (!context_->initial_metadata_received_) { finish_ops_.RecvInitialMetadata(context_); } finish_ops_.ClientRecvStatus(context_, &status); call_.PerformOps(&finish_ops_); GPR_CODEGEN_ASSERT(cq_.Pluck(&finish_ops_)); return status; } private: ClientContext* context_; CallOpSet finish_ops_; CompletionQueue cq_; Call call_; }; /// Client-side interface for bi-directional streaming. template class ClientReaderWriterInterface : public ClientStreamingInterface, public WriterInterface, public ReaderInterface { public: /// Blocking wait for initial metadata from server. The received metadata /// can only be accessed after this call returns. Should only be called before /// the first read. Calling this method is optional, and if it is not called /// the metadata will be available in ClientContext after the first read. virtual void WaitForInitialMetadata() = 0; /// Block until currently-pending writes are completed. /// Thread-safe with respect to \a Read /// /// \return Whether the writes were successful. virtual bool WritesDone() = 0; }; template class ClientReaderWriter final : public ClientReaderWriterInterface { public: /// Blocking create a stream. ClientReaderWriter(ChannelInterface* channel, const RpcMethod& method, ClientContext* context) : context_(context), call_(channel->CreateCall(method, context, &cq_)) { if (!context_->initial_metadata_corked_) { CallOpSet ops; ops.SendInitialMetadata(context->send_initial_metadata_, context->initial_metadata_flags()); call_.PerformOps(&ops); cq_.Pluck(&ops); } } void WaitForInitialMetadata() override { GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_); CallOpSet ops; ops.RecvInitialMetadata(context_); call_.PerformOps(&ops); cq_.Pluck(&ops); // status ignored } bool NextMessageSize(uint32_t* sz) override { *sz = call_.max_receive_message_size(); return true; } bool Read(R* msg) override { CallOpSet> ops; if (!context_->initial_metadata_received_) { ops.RecvInitialMetadata(context_); } ops.RecvMessage(msg); call_.PerformOps(&ops); return cq_.Pluck(&ops) && ops.got_message; } using WriterInterface::Write; bool Write(const W& msg, WriteOptions options) override { CallOpSet ops; if (options.is_last_message()) { options.set_buffer_hint(); ops.ClientSendClose(); } if (context_->initial_metadata_corked_) { ops.SendInitialMetadata(context_->send_initial_metadata_, context_->initial_metadata_flags()); context_->set_initial_metadata_corked(false); } if (!ops.SendMessage(msg, options).ok()) { return false; } call_.PerformOps(&ops); return cq_.Pluck(&ops); } bool WritesDone() override { CallOpSet ops; ops.ClientSendClose(); call_.PerformOps(&ops); return cq_.Pluck(&ops); } Status Finish() override { CallOpSet ops; if (!context_->initial_metadata_received_) { ops.RecvInitialMetadata(context_); } Status status; ops.ClientRecvStatus(context_, &status); call_.PerformOps(&ops); GPR_CODEGEN_ASSERT(cq_.Pluck(&ops)); return status; } private: ClientContext* context_; CompletionQueue cq_; Call call_; }; /// Server-side interface for streaming reads of message of type \a R. template class ServerReaderInterface : public ServerStreamingInterface, public ReaderInterface {}; template class ServerReader final : public ServerReaderInterface { public: ServerReader(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {} void SendInitialMetadata() override { GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_); CallOpSet ops; ops.SendInitialMetadata(ctx_->initial_metadata_, ctx_->initial_metadata_flags()); if (ctx_->compression_level_set()) { ops.set_compression_level(ctx_->compression_level()); } ctx_->sent_initial_metadata_ = true; call_->PerformOps(&ops); call_->cq()->Pluck(&ops); } bool NextMessageSize(uint32_t* sz) override { *sz = call_->max_receive_message_size(); return true; } bool Read(R* msg) override { CallOpSet> ops; ops.RecvMessage(msg); call_->PerformOps(&ops); return call_->cq()->Pluck(&ops) && ops.got_message; } private: Call* const call_; ServerContext* const ctx_; }; /// Server-side interface for streaming writes of message of type \a W. template class ServerWriterInterface : public ServerStreamingInterface, public WriterInterface {}; template class ServerWriter final : public ServerWriterInterface { public: ServerWriter(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {} void SendInitialMetadata() override { GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_); CallOpSet ops; ops.SendInitialMetadata(ctx_->initial_metadata_, ctx_->initial_metadata_flags()); if (ctx_->compression_level_set()) { ops.set_compression_level(ctx_->compression_level()); } ctx_->sent_initial_metadata_ = true; call_->PerformOps(&ops); call_->cq()->Pluck(&ops); } using WriterInterface::Write; bool Write(const W& msg, WriteOptions options) override { if (options.is_last_message()) { options.set_buffer_hint(); } CallOpSet ops; if (!ops.SendMessage(msg, options).ok()) { return false; } if (!ctx_->sent_initial_metadata_) { ops.SendInitialMetadata(ctx_->initial_metadata_, ctx_->initial_metadata_flags()); if (ctx_->compression_level_set()) { ops.set_compression_level(ctx_->compression_level()); } ctx_->sent_initial_metadata_ = true; } call_->PerformOps(&ops); return call_->cq()->Pluck(&ops); } private: Call* const call_; ServerContext* const ctx_; }; /// Server-side interface for bi-directional streaming. template class ServerReaderWriterInterface : public ServerStreamingInterface, public WriterInterface, public ReaderInterface {}; // Actual implementation of bi-directional streaming namespace internal { template class ServerReaderWriterBody final { public: ServerReaderWriterBody(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {} void SendInitialMetadata() { GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_); CallOpSet ops; ops.SendInitialMetadata(ctx_->initial_metadata_, ctx_->initial_metadata_flags()); if (ctx_->compression_level_set()) { ops.set_compression_level(ctx_->compression_level()); } ctx_->sent_initial_metadata_ = true; call_->PerformOps(&ops); call_->cq()->Pluck(&ops); } bool NextMessageSize(uint32_t* sz) { *sz = call_->max_receive_message_size(); return true; } bool Read(R* msg) { CallOpSet> ops; ops.RecvMessage(msg); call_->PerformOps(&ops); return call_->cq()->Pluck(&ops) && ops.got_message; } bool Write(const W& msg, WriteOptions options) { if (options.is_last_message()) { options.set_buffer_hint(); } CallOpSet ops; if (!ops.SendMessage(msg, options).ok()) { return false; } if (!ctx_->sent_initial_metadata_) { ops.SendInitialMetadata(ctx_->initial_metadata_, ctx_->initial_metadata_flags()); if (ctx_->compression_level_set()) { ops.set_compression_level(ctx_->compression_level()); } ctx_->sent_initial_metadata_ = true; } call_->PerformOps(&ops); return call_->cq()->Pluck(&ops); } private: Call* const call_; ServerContext* const ctx_; }; } // class to represent the user API for a bidirectional streaming call template class ServerReaderWriter final : public ServerReaderWriterInterface { public: ServerReaderWriter(Call* call, ServerContext* ctx) : body_(call, ctx) {} void SendInitialMetadata() override { body_.SendInitialMetadata(); } bool NextMessageSize(uint32_t* sz) override { return body_.NextMessageSize(sz); } bool Read(R* msg) override { return body_.Read(msg); } using WriterInterface::Write; bool Write(const W& msg, WriteOptions options) override { return body_.Write(msg, options); } private: internal::ServerReaderWriterBody body_; }; /// A class to represent a flow-controlled unary call. This is something /// of a hybrid between conventional unary and streaming. This is invoked /// through a unary call on the client side, but the server responds to it /// as though it were a single-ping-pong streaming call. The server can use /// the \a NextMessageSize method to determine an upper-bound on the size of /// the message. /// A key difference relative to streaming: ServerUnaryStreamer /// must have exactly 1 Read and exactly 1 Write, in that order, to function /// correctly. Otherwise, the RPC is in error. template class ServerUnaryStreamer final : public ServerReaderWriterInterface { public: ServerUnaryStreamer(Call* call, ServerContext* ctx) : body_(call, ctx), read_done_(false), write_done_(false) {} void SendInitialMetadata() override { body_.SendInitialMetadata(); } bool NextMessageSize(uint32_t* sz) override { return body_.NextMessageSize(sz); } bool Read(RequestType* request) override { if (read_done_) { return false; } read_done_ = true; return body_.Read(request); } using WriterInterface::Write; bool Write(const ResponseType& response, WriteOptions options) override { if (write_done_ || !read_done_) { return false; } write_done_ = true; return body_.Write(response, options); } private: internal::ServerReaderWriterBody body_; bool read_done_; bool write_done_; }; /// A class to represent a flow-controlled server-side streaming call. /// This is something of a hybrid between server-side and bidi streaming. /// This is invoked through a server-side streaming call on the client side, /// but the server responds to it as though it were a bidi streaming call that /// must first have exactly 1 Read and then any number of Writes. template class ServerSplitStreamer final : public ServerReaderWriterInterface { public: ServerSplitStreamer(Call* call, ServerContext* ctx) : body_(call, ctx), read_done_(false) {} void SendInitialMetadata() override { body_.SendInitialMetadata(); } bool NextMessageSize(uint32_t* sz) override { return body_.NextMessageSize(sz); } bool Read(RequestType* request) override { if (read_done_) { return false; } read_done_ = true; return body_.Read(request); } using WriterInterface::Write; bool Write(const ResponseType& response, WriteOptions options) override { return read_done_ && body_.Write(response, options); } private: internal::ServerReaderWriterBody body_; bool read_done_; }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_SYNC_STREAM_H grpc-1.3.2/include/grpc++/impl/codegen/thrift_serializer.h000066400000000000000000000154151310511640000234200ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_THRIFT_SERIALIZER_H #define GRPCXX_IMPL_CODEGEN_THRIFT_SERIALIZER_H #include #include #include #include #include #include #include #include #include #include #include namespace apache { namespace thrift { namespace util { using apache::thrift::protocol::TBinaryProtocolT; using apache::thrift::protocol::TCompactProtocolT; using apache::thrift::protocol::TMessageType; using apache::thrift::protocol::TNetworkBigEndian; using apache::thrift::transport::TMemoryBuffer; using apache::thrift::transport::TBufferBase; using apache::thrift::transport::TTransport; template class ThriftSerializer { public: ThriftSerializer() : prepared_(false), last_deserialized_(false), serialize_version_(false) {} virtual ~ThriftSerializer() {} // Serialize the passed type into the internal buffer // and returns a pointer to internal buffer and its size template void Serialize(const T& fields, const uint8_t** serialized_buffer, size_t* serialized_len) { // prepare or reset buffer if (!prepared_ || last_deserialized_) { prepare(); } else { buffer_->resetBuffer(); } last_deserialized_ = false; // if required serialize protocol version if (serialize_version_) { protocol_->writeMessageBegin("", TMessageType(0), 0); } // serialize fields into buffer fields.write(protocol_.get()); // write the end of message if (serialize_version_) { protocol_->writeMessageEnd(); } uint8_t* byte_buffer; uint32_t byte_buffer_size; buffer_->getBuffer(&byte_buffer, &byte_buffer_size); *serialized_buffer = byte_buffer; *serialized_len = byte_buffer_size; } // Serialize the passed type into the byte buffer template void Serialize(const T& fields, grpc_byte_buffer** bp) { const uint8_t* byte_buffer; size_t byte_buffer_size; Serialize(fields, &byte_buffer, &byte_buffer_size); grpc_slice slice = grpc_slice_from_copied_buffer( reinterpret_cast(byte_buffer), byte_buffer_size); *bp = grpc_raw_byte_buffer_create(&slice, 1); grpc_slice_unref(slice); } // Deserialize the passed char array into the passed type, returns the number // of bytes that have been consumed from the passed string. template uint32_t Deserialize(uint8_t* serialized_buffer, size_t length, T* fields) { // prepare buffer if necessary if (!prepared_) { prepare(); } last_deserialized_ = true; // reset buffer transport buffer_->resetBuffer(serialized_buffer, length); // read the protocol version if necessary if (serialize_version_) { std::string name = ""; TMessageType mt = static_cast(0); int32_t seq_id = 0; protocol_->readMessageBegin(name, mt, seq_id); } // deserialize buffer into fields uint32_t len = fields->read(protocol_.get()); // read the end of message if (serialize_version_) { protocol_->readMessageEnd(); } return len; } // Deserialize the passed byte buffer to passed type, returns the number // of bytes consumed from byte buffer template uint32_t Deserialize(grpc_byte_buffer* buffer, T* msg) { grpc_byte_buffer_reader reader; grpc_byte_buffer_reader_init(&reader, buffer); grpc_slice slice = grpc_byte_buffer_reader_readall(&reader); uint32_t len = Deserialize(GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice), msg); grpc_slice_unref(slice); grpc_byte_buffer_reader_destroy(&reader); return len; } // set serialization version flag void SetSerializeVersion(bool value) { serialize_version_ = value; } // Set the container size limit to deserialize // This function should be called after buffer_ is initialized void SetContainerSizeLimit(int32_t container_limit) { if (!prepared_) { prepare(); } protocol_->setContainerSizeLimit(container_limit); } // Set the string size limit to deserialize // This function should be called after buffer_ is initialized void SetStringSizeLimit(int32_t string_limit) { if (!prepared_) { prepare(); } protocol_->setStringSizeLimit(string_limit); } private: bool prepared_; bool last_deserialized_; boost::shared_ptr buffer_; std::shared_ptr protocol_; bool serialize_version_; void prepare() { buffer_ = boost::make_shared(); // create a protocol for the memory buffer transport protocol_ = std::make_shared(buffer_); prepared_ = true; } }; // ThriftSerializer typedef ThriftSerializer> ThriftSerializerBinary; typedef ThriftSerializer> ThriftSerializerCompact; } // namespace util } // namespace thrift } // namespace apache #endif // GRPCXX_IMPL_CODEGEN_THRIFT_SERIALIZER_H grpc-1.3.2/include/grpc++/impl/codegen/thrift_utils.h000066400000000000000000000057171310511640000224130ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_THRIFT_UTILS_H #define GRPCXX_IMPL_CODEGEN_THRIFT_UTILS_H #include #include #include #include #include #include #include #include #include #include namespace grpc { using apache::thrift::util::ThriftSerializerCompact; template class SerializationTraits::value>::type> { public: static Status Serialize(const T& msg, grpc_byte_buffer** bp, bool* own_buffer) { *own_buffer = true; ThriftSerializerCompact serializer; serializer.Serialize(msg, bp); return Status(StatusCode::OK, "ok"); } static Status Deserialize(grpc_byte_buffer* buffer, T* msg, int max_receive_message_size) { if (!buffer) { return Status(StatusCode::INTERNAL, "No payload"); } ThriftSerializerCompact deserializer; deserializer.Deserialize(buffer, msg); grpc_byte_buffer_destroy(buffer); return Status(StatusCode::OK, "ok"); } }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_THRIFT_UTILS_H grpc-1.3.2/include/grpc++/impl/codegen/time.h000066400000000000000000000066641310511640000206330ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_CODEGEN_TIME_H #define GRPCXX_IMPL_CODEGEN_TIME_H #include #include namespace grpc { /* If you are trying to use CompletionQueue::AsyncNext with a time class that isn't either gpr_timespec or std::chrono::system_clock::time_point, you will most likely be looking at this comment as your compiler will have fired an error below. In order to fix this issue, you have two potential solutions: 1. Use gpr_timespec or std::chrono::system_clock::time_point instead 2. Specialize the TimePoint class with whichever time class that you want to use here. See below for two examples of how to do this. */ template class TimePoint { public: TimePoint(const T& time) { you_need_a_specialization_of_TimePoint(); } gpr_timespec raw_time() { gpr_timespec t; return t; } private: void you_need_a_specialization_of_TimePoint(); }; template <> class TimePoint { public: TimePoint(const gpr_timespec& time) : time_(time) {} gpr_timespec raw_time() { return time_; } private: gpr_timespec time_; }; } // namespace grpc #include #include namespace grpc { // from and to should be absolute time. void Timepoint2Timespec(const std::chrono::system_clock::time_point& from, gpr_timespec* to); void TimepointHR2Timespec( const std::chrono::high_resolution_clock::time_point& from, gpr_timespec* to); std::chrono::system_clock::time_point Timespec2Timepoint(gpr_timespec t); template <> class TimePoint { public: TimePoint(const std::chrono::system_clock::time_point& time) { Timepoint2Timespec(time, &time_); } gpr_timespec raw_time() const { return time_; } private: gpr_timespec time_; }; } // namespace grpc #endif // GRPCXX_IMPL_CODEGEN_TIME_H grpc-1.3.2/include/grpc++/impl/grpc_library.h000066400000000000000000000051641310511640000207420ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_GRPC_LIBRARY_H #define GRPCXX_IMPL_GRPC_LIBRARY_H #include #include #include #include #include namespace grpc { namespace internal { class GrpcLibrary final : public GrpcLibraryInterface { public: void init() override { grpc_init(); } void shutdown() override { grpc_shutdown(); } }; static GrpcLibrary g_gli; static CoreCodegen g_core_codegen; /// Instantiating this class ensures the proper initialization of gRPC. class GrpcLibraryInitializer final { public: GrpcLibraryInitializer() { if (grpc::g_glip == nullptr) { grpc::g_glip = &g_gli; } if (grpc::g_core_codegen_interface == nullptr) { grpc::g_core_codegen_interface = &g_core_codegen; } } /// A no-op method to force the linker to reference this class, which will /// take care of initializing and shutting down the gRPC runtime. int summon() { return 0; } }; } // namespace internal } // namespace grpc #endif // GRPCXX_IMPL_GRPC_LIBRARY_H grpc-1.3.2/include/grpc++/impl/method_handler_impl.h000066400000000000000000000033321310511640000222540ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_METHOD_HANDLER_IMPL_H #define GRPCXX_IMPL_METHOD_HANDLER_IMPL_H #include #endif // GRPCXX_IMPL_METHOD_HANDLER_IMPL_H grpc-1.3.2/include/grpc++/impl/rpc_method.h000066400000000000000000000032661310511640000204100ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_RPC_METHOD_H #define GRPCXX_IMPL_RPC_METHOD_H #include #endif // GRPCXX_IMPL_RPC_METHOD_H grpc-1.3.2/include/grpc++/impl/rpc_service_method.h000066400000000000000000000033261310511640000221250ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_RPC_SERVICE_METHOD_H #define GRPCXX_IMPL_RPC_SERVICE_METHOD_H #include #endif // GRPCXX_IMPL_RPC_SERVICE_METHOD_H grpc-1.3.2/include/grpc++/impl/serialization_traits.h000066400000000000000000000033361310511640000225250ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_SERIALIZATION_TRAITS_H #define GRPCXX_IMPL_SERIALIZATION_TRAITS_H #include #endif // GRPCXX_IMPL_SERIALIZATION_TRAITS_H grpc-1.3.2/include/grpc++/impl/server_builder_option.h000066400000000000000000000044121310511640000226620ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_SERVER_BUILDER_OPTION_H #define GRPCXX_IMPL_SERVER_BUILDER_OPTION_H #include #include #include #include namespace grpc { /// Interface to pass an option to a \a ServerBuilder. class ServerBuilderOption { public: virtual ~ServerBuilderOption() {} /// Alter the \a ChannelArguments used to create the gRPC server. virtual void UpdateArguments(ChannelArguments* args) = 0; /// Alter the ServerBuilderPlugin map that will be added into ServerBuilder. virtual void UpdatePlugins( std::vector>* plugins) = 0; }; } // namespace grpc #endif // GRPCXX_IMPL_SERVER_BUILDER_OPTION_H grpc-1.3.2/include/grpc++/impl/server_builder_plugin.h000066400000000000000000000052521310511640000226530ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_SERVER_BUILDER_PLUGIN_H #define GRPCXX_IMPL_SERVER_BUILDER_PLUGIN_H #include #include namespace grpc { class ServerInitializer; class ChannelArguments; class ServerBuilderPlugin { public: virtual ~ServerBuilderPlugin() {} virtual grpc::string name() = 0; // InitServer will be called in ServerBuilder::BuildAndStart(), after the // Server instance is created. virtual void InitServer(ServerInitializer* si) = 0; // Finish will be called at the end of ServerBuilder::BuildAndStart(). virtual void Finish(ServerInitializer* si) = 0; // ChangeArguments is an interface that can be used in // ServerBuilderOption::UpdatePlugins virtual void ChangeArguments(const grpc::string& name, void* value) = 0; // UpdateChannelArguments will be called in ServerBuilder::BuildAndStart(), // before the Server instance is created. virtual void UpdateChannelArguments(ChannelArguments* args) {} virtual bool has_sync_methods() const { return false; } virtual bool has_async_methods() const { return false; } }; } // namespace grpc #endif // GRPCXX_IMPL_SERVER_BUILDER_PLUGIN_H grpc-1.3.2/include/grpc++/impl/server_initializer.h000066400000000000000000000044171310511640000221740ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_SERVER_INITIALIZER_H #define GRPCXX_IMPL_SERVER_INITIALIZER_H #include #include #include namespace grpc { class Server; class Service; class ServerInitializer { public: ServerInitializer(Server* server) : server_(server) {} bool RegisterService(std::shared_ptr service) { if (!server_->RegisterService(nullptr, service.get())) { return false; } default_services_.push_back(service); return true; } const std::vector* GetServiceList() { return &server_->services_; } private: Server* server_; std::vector > default_services_; }; } // namespace grpc #endif // GRPCXX_IMPL_SERVER_INITIALIZER_H grpc-1.3.2/include/grpc++/impl/service_type.h000066400000000000000000000032761310511640000207660ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_SERVICE_TYPE_H #define GRPCXX_IMPL_SERVICE_TYPE_H #include #endif // GRPCXX_IMPL_SERVICE_TYPE_H grpc-1.3.2/include/grpc++/impl/sync_cxx11.h000066400000000000000000000032661310511640000202640ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_SYNC_CXX11_H #define GRPCXX_IMPL_SYNC_CXX11_H #include #endif // GRPCXX_IMPL_SYNC_CXX11_H grpc-1.3.2/include/grpc++/impl/sync_no_cxx11.h000066400000000000000000000033021310511640000207470ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_IMPL_SYNC_NO_CXX11_H #define GRPCXX_IMPL_SYNC_NO_CXX11_H #include #endif // GRPCXX_IMPL_SYNC_NO_CXX11_H grpc-1.3.2/include/grpc++/resource_quota.h000066400000000000000000000053341310511640000203610ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_RESOURCE_QUOTA_H #define GRPCXX_RESOURCE_QUOTA_H struct grpc_resource_quota; #include #include namespace grpc { /// ResourceQuota represents a bound on memory usage by the gRPC library. /// A ResourceQuota can be attached to a server (via ServerBuilder), or a client /// channel (via ChannelArguments). gRPC will attempt to keep memory used by /// all attached entities below the ResourceQuota bound. class ResourceQuota final : private GrpcLibraryCodegen { public: explicit ResourceQuota(const grpc::string& name); ResourceQuota(); ~ResourceQuota(); /// Resize this ResourceQuota to a new size. If new_size is smaller than the /// current size of the pool, memory usage will be monotonically decreased /// until it falls under new_size. No time bound is given for this to occur /// however. ResourceQuota& Resize(size_t new_size); grpc_resource_quota* c_resource_quota() const { return impl_; } private: ResourceQuota(const ResourceQuota& rhs); ResourceQuota& operator=(const ResourceQuota& rhs); grpc_resource_quota* const impl_; }; } // namespace grpc #endif // GRPCXX_RESOURCE_QUOTA_H grpc-1.3.2/include/grpc++/security/000077500000000000000000000000001310511640000170125ustar00rootroot00000000000000grpc-1.3.2/include/grpc++/security/auth_context.h000066400000000000000000000033231310511640000216710ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_SECURITY_AUTH_CONTEXT_H #define GRPCXX_SECURITY_AUTH_CONTEXT_H #include #endif // GRPCXX_SECURITY_AUTH_CONTEXT_H grpc-1.3.2/include/grpc++/security/auth_metadata_processor.h000066400000000000000000000060511310511640000240650ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_SECURITY_AUTH_METADATA_PROCESSOR_H #define GRPCXX_SECURITY_AUTH_METADATA_PROCESSOR_H #include #include #include #include namespace grpc { class AuthMetadataProcessor { public: typedef std::multimap InputMetadata; typedef std::multimap OutputMetadata; virtual ~AuthMetadataProcessor() {} // If this method returns true, the Process function will be scheduled in // a different thread from the one processing the call. virtual bool IsBlocking() const { return true; } // context is read/write: it contains the properties of the channel peer and // it is the job of the Process method to augment it with properties derived // from the passed-in auth_metadata. // consumed_auth_metadata needs to be filled with metadata that has been // consumed by the processor and will be removed from the call. // response_metadata is the metadata that will be sent as part of the // response. // If the return value is not Status::OK, the rpc call will be aborted with // the error code and error message sent back to the client. virtual Status Process(const InputMetadata& auth_metadata, AuthContext* context, OutputMetadata* consumed_auth_metadata, OutputMetadata* response_metadata) = 0; }; } // namespace grpc #endif // GRPCXX_SECURITY_AUTH_METADATA_PROCESSOR_H grpc-1.3.2/include/grpc++/security/credentials.h000066400000000000000000000225261310511640000214670ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_SECURITY_CREDENTIALS_H #define GRPCXX_SECURITY_CREDENTIALS_H #include #include #include #include #include #include struct grpc_call; namespace grpc { class ChannelArguments; class Channel; class SecureChannelCredentials; class CallCredentials; class SecureCallCredentials; /// A channel credentials object encapsulates all the state needed by a client /// to authenticate with a server for a given channel. /// It can make various assertions, e.g., about the client’s identity, role /// for all the calls on that channel. /// /// \see http://www.grpc.io/docs/guides/auth.html class ChannelCredentials : private GrpcLibraryCodegen { public: ChannelCredentials(); ~ChannelCredentials(); protected: friend std::shared_ptr CompositeChannelCredentials( const std::shared_ptr& channel_creds, const std::shared_ptr& call_creds); virtual SecureChannelCredentials* AsSecureCredentials() = 0; private: friend std::shared_ptr CreateCustomChannel( const grpc::string& target, const std::shared_ptr& creds, const ChannelArguments& args); virtual std::shared_ptr CreateChannel( const grpc::string& target, const ChannelArguments& args) = 0; }; /// A call credentials object encapsulates the state needed by a client to /// authenticate with a server for a given call on a channel. /// /// \see http://www.grpc.io/docs/guides/auth.html class CallCredentials : private GrpcLibraryCodegen { public: CallCredentials(); ~CallCredentials(); /// Apply this instance's credentials to \a call. virtual bool ApplyToCall(grpc_call* call) = 0; protected: friend std::shared_ptr CompositeChannelCredentials( const std::shared_ptr& channel_creds, const std::shared_ptr& call_creds); friend std::shared_ptr CompositeCallCredentials( const std::shared_ptr& creds1, const std::shared_ptr& creds2); virtual SecureCallCredentials* AsSecureCredentials() = 0; }; /// Options used to build SslCredentials. struct SslCredentialsOptions { /// The buffer containing the PEM encoding of the server root certificates. If /// this parameter is empty, the default roots will be used. The default /// roots can be overridden using the \a GRPC_DEFAULT_SSL_ROOTS_FILE_PATH /// environment variable pointing to a file on the file system containing the /// roots. grpc::string pem_root_certs; /// The buffer containing the PEM encoding of the client's private key. This /// parameter can be empty if the client does not have a private key. grpc::string pem_private_key; /// The buffer containing the PEM encoding of the client's certificate chain. /// This parameter can be empty if the client does not have a certificate /// chain. grpc::string pem_cert_chain; }; // Factories for building different types of Credentials The functions may // return empty shared_ptr when credentials cannot be created. If a // Credentials pointer is returned, it can still be invalid when used to create // a channel. A lame channel will be created then and all rpcs will fail on it. /// Builds credentials with reasonable defaults. /// /// \warning Only use these credentials when connecting to a Google endpoint. /// Using these credentials to connect to any other service may result in this /// service being able to impersonate your client for requests to Google /// services. std::shared_ptr GoogleDefaultCredentials(); /// Builds SSL Credentials given SSL specific options std::shared_ptr SslCredentials( const SslCredentialsOptions& options); /// Builds credentials for use when running in GCE /// /// \warning Only use these credentials when connecting to a Google endpoint. /// Using these credentials to connect to any other service may result in this /// service being able to impersonate your client for requests to Google /// services. std::shared_ptr GoogleComputeEngineCredentials(); /// Builds Service Account JWT Access credentials. /// json_key is the JSON key string containing the client's private key. /// token_lifetime_seconds is the lifetime in seconds of each Json Web Token /// (JWT) created with this credentials. It should not exceed /// grpc_max_auth_token_lifetime or will be cropped to this value. std::shared_ptr ServiceAccountJWTAccessCredentials( const grpc::string& json_key, long token_lifetime_seconds); /// Builds refresh token credentials. /// json_refresh_token is the JSON string containing the refresh token along /// with a client_id and client_secret. /// /// \warning Only use these credentials when connecting to a Google endpoint. /// Using these credentials to connect to any other service may result in this /// service being able to impersonate your client for requests to Google /// services. std::shared_ptr GoogleRefreshTokenCredentials( const grpc::string& json_refresh_token); /// Builds access token credentials. /// access_token is an oauth2 access token that was fetched using an out of band /// mechanism. /// /// \warning Only use these credentials when connecting to a Google endpoint. /// Using these credentials to connect to any other service may result in this /// service being able to impersonate your client for requests to Google /// services. std::shared_ptr AccessTokenCredentials( const grpc::string& access_token); /// Builds IAM credentials. /// /// \warning Only use these credentials when connecting to a Google endpoint. /// Using these credentials to connect to any other service may result in this /// service being able to impersonate your client for requests to Google /// services. std::shared_ptr GoogleIAMCredentials( const grpc::string& authorization_token, const grpc::string& authority_selector); /// Combines a channel credentials and a call credentials into a composite /// channel credentials. std::shared_ptr CompositeChannelCredentials( const std::shared_ptr& channel_creds, const std::shared_ptr& call_creds); /// Combines two call credentials objects into a composite call credentials. std::shared_ptr CompositeCallCredentials( const std::shared_ptr& creds1, const std::shared_ptr& creds2); /// Credentials for an unencrypted, unauthenticated channel std::shared_ptr InsecureChannelCredentials(); /// Credentials for a channel using Cronet. std::shared_ptr CronetChannelCredentials(void* engine); // User defined metadata credentials. class MetadataCredentialsPlugin { public: virtual ~MetadataCredentialsPlugin() {} // If this method returns true, the Process function will be scheduled in // a different thread from the one processing the call. virtual bool IsBlocking() const { return true; } // Type of credentials this plugin is implementing. virtual const char* GetType() const { return ""; } // Gets the auth metatada produced by this plugin. // The fully qualified method name is: // service_url + "/" + method_name. // The channel_auth_context contains (among other things), the identity of // the server. virtual Status GetMetadata( grpc::string_ref service_url, grpc::string_ref method_name, const AuthContext& channel_auth_context, std::multimap* metadata) = 0; }; std::shared_ptr MetadataCredentialsFromPlugin( std::unique_ptr plugin); } // namespace grpc #endif // GRPCXX_SECURITY_CREDENTIALS_H grpc-1.3.2/include/grpc++/security/server_credentials.h000066400000000000000000000074751310511640000230630ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_SECURITY_SERVER_CREDENTIALS_H #define GRPCXX_SECURITY_SERVER_CREDENTIALS_H #include #include #include #include #include struct grpc_server; namespace grpc { class Server; // Wrapper around \a grpc_server_credentials, a way to authenticate a server. class ServerCredentials { public: virtual ~ServerCredentials(); // This method is not thread-safe and has to be called before the server is // started. The last call to this function wins. virtual void SetAuthMetadataProcessor( const std::shared_ptr& processor) = 0; private: friend class ::grpc::Server; /// Tries to bind \a server to the given \a addr (eg, localhost:1234, /// 192.168.1.1:31416, [::1]:27182, etc.) /// /// \return bound port number on sucess, 0 on failure. // TODO(dgq): the "port" part seems to be a misnomer. virtual int AddPortToServer(const grpc::string& addr, grpc_server* server) = 0; }; /// Options to create ServerCredentials with SSL struct SslServerCredentialsOptions { // Deprecated SslServerCredentialsOptions() : force_client_auth(false), client_certificate_request(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE) {} SslServerCredentialsOptions( grpc_ssl_client_certificate_request_type request_type) : force_client_auth(false), client_certificate_request(request_type) {} struct PemKeyCertPair { grpc::string private_key; grpc::string cert_chain; }; grpc::string pem_root_certs; std::vector pem_key_cert_pairs; // Deprecated bool force_client_auth; // If both force_client_auth and client_certificate_request fields are set, // force_client_auth takes effect i.e // REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY will be enforced. grpc_ssl_client_certificate_request_type client_certificate_request; }; /// Builds SSL ServerCredentials given SSL specific options std::shared_ptr SslServerCredentials( const SslServerCredentialsOptions& options); /// Builds insecure server credentials. std::shared_ptr InsecureServerCredentials(); } // namespace grpc #endif // GRPCXX_SECURITY_SERVER_CREDENTIALS_H grpc-1.3.2/include/grpc++/server.h000066400000000000000000000205711310511640000166270ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_SERVER_H #define GRPCXX_SERVER_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct grpc_server; namespace grpc { class AsyncGenericService; class HealthCheckServiceInterface; class ServerContext; class ServerInitializer; /// Models a gRPC server. /// /// Servers are configured and started via \a grpc::ServerBuilder. class Server final : public ServerInterface, private GrpcLibraryCodegen { public: ~Server(); /// Block waiting for all work to complete. /// /// \warning The server must be either shutting down or some other thread must /// call \a Shutdown for this function to ever return. void Wait() override; /// Global Callbacks /// /// Can be set exactly once per application to install hooks whenever /// a server event occurs class GlobalCallbacks { public: virtual ~GlobalCallbacks() {} /// Called before server is created. virtual void UpdateArguments(ChannelArguments* args) {} /// Called before application callback for each synchronous server request virtual void PreSynchronousRequest(ServerContext* context) = 0; /// Called after application callback for each synchronous server request virtual void PostSynchronousRequest(ServerContext* context) = 0; /// Called before server is started. virtual void PreServerStart(Server* server) {} /// Called after a server port is added. virtual void AddPort(Server* server, int port) {} }; /// Set the global callback object. Can only be called once. Does not take /// ownership of callbacks, and expects the pointed to object to be alive /// until all server objects in the process have been destroyed. static void SetGlobalCallbacks(GlobalCallbacks* callbacks); // Returns a \em raw pointer to the underlying grpc_server instance. grpc_server* c_server(); /// Returns the health check service. HealthCheckServiceInterface* GetHealthCheckService() const { return health_check_service_.get(); } private: friend class AsyncGenericService; friend class ServerBuilder; friend class ServerInitializer; class SyncRequest; class AsyncRequest; class ShutdownRequest; /// SyncRequestThreadManager is an implementation of ThreadManager. This class /// is responsible for polling for incoming RPCs and calling the RPC handlers. /// This is only used in case of a Sync server (i.e a server exposing a sync /// interface) class SyncRequestThreadManager; class UnimplementedAsyncRequestContext; class UnimplementedAsyncRequest; class UnimplementedAsyncResponse; /// Server constructors. To be used by \a ServerBuilder only. /// /// \param max_message_size Maximum message length that the channel can /// receive. /// /// \param args The channel args /// /// \param sync_server_cqs The completion queues to use if the server is a /// synchronous server (or a hybrid server). The server polls for new RPCs on /// these queues /// /// \param min_pollers The minimum number of polling threads per server /// completion queue (in param sync_server_cqs) to use for listening to /// incoming requests (used only in case of sync server) /// /// \param max_pollers The maximum number of polling threads per server /// completion queue (in param sync_server_cqs) to use for listening to /// incoming requests (used only in case of sync server) /// /// \param sync_cq_timeout_msec The timeout to use when calling AsyncNext() on /// server completion queues passed via sync_server_cqs param. Server(int max_message_size, ChannelArguments* args, std::shared_ptr>> sync_server_cqs, int min_pollers, int max_pollers, int sync_cq_timeout_msec); /// Register a service. This call does not take ownership of the service. /// The service must exist for the lifetime of the Server instance. bool RegisterService(const grpc::string* host, Service* service) override; /// Register a generic service. This call does not take ownership of the /// service. The service must exist for the lifetime of the Server instance. void RegisterAsyncGenericService(AsyncGenericService* service) override; /// Tries to bind \a server to the given \a addr. /// /// It can be invoked multiple times. /// /// \param addr The address to try to bind to the server (eg, localhost:1234, /// 192.168.1.1:31416, [::1]:27182, etc.). /// \params creds The credentials associated with the server. /// /// \return bound port number on sucess, 0 on failure. /// /// \warning It's an error to call this method on an already started server. int AddListeningPort(const grpc::string& addr, ServerCredentials* creds) override; /// Start the server. /// /// \param cqs Completion queues for handling asynchronous services. The /// caller is required to keep all completion queues live until the server is /// destroyed. /// \param num_cqs How many completion queues does \a cqs hold. /// /// \return true on a successful shutdown. bool Start(ServerCompletionQueue** cqs, size_t num_cqs) override; void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) override; void ShutdownInternal(gpr_timespec deadline) override; int max_receive_message_size() const override { return max_receive_message_size_; }; grpc_server* server() override { return server_; }; ServerInitializer* initializer(); const int max_receive_message_size_; /// The following completion queues are ONLY used in case of Sync API i.e if /// the server has any services with sync methods. The server uses these /// completion queues to poll for new RPCs std::shared_ptr>> sync_server_cqs_; /// List of ThreadManager instances (one for each cq in the sync_server_cqs) std::vector> sync_req_mgrs_; // Sever status std::mutex mu_; bool started_; bool shutdown_; bool shutdown_notified_; // Was notify called on the shutdown_cv_ std::condition_variable shutdown_cv_; std::shared_ptr global_callbacks_; std::vector services_; bool has_generic_service_; // Pointer to the wrapped grpc_server. grpc_server* server_; std::unique_ptr server_initializer_; std::unique_ptr health_check_service_; bool health_check_service_disabled_; }; } // namespace grpc #endif // GRPCXX_SERVER_H grpc-1.3.2/include/grpc++/server_builder.h000066400000000000000000000220151310511640000203300ustar00rootroot00000000000000/* * * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_SERVER_BUILDER_H #define GRPCXX_SERVER_BUILDER_H #include #include #include #include #include #include #include #include #include #include #include struct grpc_resource_quota; namespace grpc { class AsyncGenericService; class ResourceQuota; class CompletionQueue; class RpcService; class Server; class ServerCompletionQueue; class ServerCredentials; class Service; namespace testing { class ServerBuilderPluginTest; } // namespace testing /// A builder class for the creation and startup of \a grpc::Server instances. class ServerBuilder { public: ServerBuilder(); ~ServerBuilder(); enum SyncServerOption { NUM_CQS, MIN_POLLERS, MAX_POLLERS, CQ_TIMEOUT_MSEC }; /// Register a service. This call does not take ownership of the service. /// The service must exist for the lifetime of the \a Server instance returned /// by \a BuildAndStart(). /// Matches requests with any :authority ServerBuilder& RegisterService(Service* service); /// Register a generic service. /// Matches requests with any :authority ServerBuilder& RegisterAsyncGenericService(AsyncGenericService* service); /// Register a service. This call does not take ownership of the service. /// The service must exist for the lifetime of the \a Server instance returned /// by BuildAndStart(). /// Only matches requests with :authority \a host ServerBuilder& RegisterService(const grpc::string& host, Service* service); /// Set max receive message size in bytes. ServerBuilder& SetMaxReceiveMessageSize(int max_receive_message_size) { max_receive_message_size_ = max_receive_message_size; return *this; } /// Set max send message size in bytes. ServerBuilder& SetMaxSendMessageSize(int max_send_message_size) { max_send_message_size_ = max_send_message_size; return *this; } /// \deprecated For backward compatibility. ServerBuilder& SetMaxMessageSize(int max_message_size) { return SetMaxReceiveMessageSize(max_message_size); } /// Set the support status for compression algorithms. All algorithms are /// enabled by default. /// /// Incoming calls compressed with an unsupported algorithm will fail with /// GRPC_STATUS_UNIMPLEMENTED. ServerBuilder& SetCompressionAlgorithmSupportStatus( grpc_compression_algorithm algorithm, bool enabled); /// The default compression level to use for all channel calls in the /// absence of a call-specific level. ServerBuilder& SetDefaultCompressionLevel(grpc_compression_level level); /// The default compression algorithm to use for all channel calls in the /// absence of a call-specific level. Note that it overrides any compression /// level set by \a SetDefaultCompressionLevel. ServerBuilder& SetDefaultCompressionAlgorithm( grpc_compression_algorithm algorithm); /// Set the attached buffer pool for this server ServerBuilder& SetResourceQuota(const ResourceQuota& resource_quota); ServerBuilder& SetOption(std::unique_ptr option); /// Only useful if this is a Synchronous server. ServerBuilder& SetSyncServerOption(SyncServerOption option, int value); /// Add a channel argument (an escape hatch to tuning core library parameters /// directly) template ServerBuilder& AddChannelArgument(const grpc::string& arg, const T& value) { return SetOption(MakeChannelArgumentOption(arg, value)); } /// Tries to bind \a server to the given \a addr. /// /// It can be invoked multiple times. /// /// \param addr The address to try to bind to the server (eg, localhost:1234, /// 192.168.1.1:31416, [::1]:27182, etc.). /// \params creds The credentials associated with the server. /// \param selected_port[out] Upon success, updated to contain the port /// number. \a nullptr otherwise. /// // TODO(dgq): the "port" part seems to be a misnomer. ServerBuilder& AddListeningPort(const grpc::string& addr, std::shared_ptr creds, int* selected_port = nullptr); /// Add a completion queue for handling asynchronous services. /// /// Caller is required to shutdown the server prior to shutting down the /// returned completion queue. A typical usage scenario: /// /// // While building the server: /// ServerBuilder builder; /// ... /// cq_ = builder.AddCompletionQueue(); /// server_ = builder.BuildAndStart(); /// /// // While shutting down the server; /// server_->Shutdown(); /// cq_->Shutdown(); // Always *after* the associated server's Shutdown()! /// /// \param is_frequently_polled This is an optional parameter to inform GRPC /// library about whether this completion queue would be frequently polled /// (i.e by calling Next() or AsyncNext()). The default value is 'true' and is /// the recommended setting. Setting this to 'false' (i.e not polling the /// completion queue frequently) will have a significantly negative /// performance impact and hence should not be used in production use cases. std::unique_ptr AddCompletionQueue( bool is_frequently_polled = true); /// Return a running server which is ready for processing calls. std::unique_ptr BuildAndStart(); /// For internal use only: Register a ServerBuilderPlugin factory function. static void InternalAddPluginFactory( std::unique_ptr (*CreatePlugin)()); private: friend class ::grpc::testing::ServerBuilderPluginTest; struct Port { grpc::string addr; std::shared_ptr creds; int* selected_port; }; struct SyncServerSettings { SyncServerSettings() : num_cqs(1), min_pollers(1), max_pollers(INT_MAX), cq_timeout_msec(1000) {} // Number of server completion queues to create to listen to incoming RPCs. int num_cqs; // Minimum number of threads per completion queue that should be listening // to incoming RPCs. int min_pollers; // Maximum number of threads per completion queue that can be listening to // incoming RPCs. int max_pollers; // The timeout for server completion queue's AsyncNext call. int cq_timeout_msec; }; typedef std::unique_ptr HostString; struct NamedService { explicit NamedService(Service* s) : service(s) {} NamedService(const grpc::string& h, Service* s) : host(new grpc::string(h)), service(s) {} HostString host; Service* service; }; int max_receive_message_size_; int max_send_message_size_; std::vector> options_; std::vector> services_; std::vector ports_; SyncServerSettings sync_server_settings_; // List of completion queues added via AddCompletionQueue() method std::vector cqs_; std::shared_ptr creds_; std::vector> plugins_; grpc_resource_quota* resource_quota_; AsyncGenericService* generic_service_; struct { bool is_set; grpc_compression_level level; } maybe_default_compression_level_; struct { bool is_set; grpc_compression_algorithm algorithm; } maybe_default_compression_algorithm_; uint32_t enabled_compression_algorithms_bitset_; }; } // namespace grpc #endif // GRPCXX_SERVER_BUILDER_H grpc-1.3.2/include/grpc++/server_context.h000066400000000000000000000032671310511640000203760ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_SERVER_CONTEXT_H #define GRPCXX_SERVER_CONTEXT_H #include #endif // GRPCXX_SERVER_CONTEXT_H grpc-1.3.2/include/grpc++/server_posix.h000066400000000000000000000040771310511640000200540ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_SERVER_POSIX_H #define GRPCXX_SERVER_POSIX_H #include #include #include namespace grpc { #ifdef GPR_SUPPORT_CHANNELS_FROM_FD /// Adds new client to a \a Server communicating over given file descriptor /// /// \param server The server to add a client to. /// \param fd The file descriptor representing a socket. void AddInsecureChannelFromFd(Server* server, int fd); #endif // GPR_SUPPORT_CHANNELS_FROM_FD } // namespace grpc #endif // GRPCXX_SERVER_POSIX_H grpc-1.3.2/include/grpc++/support/000077500000000000000000000000001310511640000166575ustar00rootroot00000000000000grpc-1.3.2/include/grpc++/support/async_stream.h000066400000000000000000000033071310511640000215230ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_SUPPORT_ASYNC_STREAM_H #define GRPCXX_SUPPORT_ASYNC_STREAM_H #include #endif // GRPCXX_SUPPORT_ASYNC_STREAM_H grpc-1.3.2/include/grpc++/support/async_unary_call.h000066400000000000000000000033271310511640000223630ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_SUPPORT_ASYNC_UNARY_CALL_H #define GRPCXX_SUPPORT_ASYNC_UNARY_CALL_H #include #endif // GRPCXX_SUPPORT_ASYNC_UNARY_CALL_H grpc-1.3.2/include/grpc++/support/byte_buffer.h000066400000000000000000000066551310511640000213400ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_SUPPORT_BYTE_BUFFER_H #define GRPCXX_SUPPORT_BYTE_BUFFER_H #include #include #include #include #include #include #include #include namespace grpc { /// A sequence of bytes. class ByteBuffer final { public: /// Constuct an empty buffer. ByteBuffer() : buffer_(nullptr) {} /// Construct buffer from \a slices, of which there are \a nslices. ByteBuffer(const Slice* slices, size_t nslices); /// Constuct a byte buffer by referencing elements of existing buffer /// \a buf. Wrapper of core function grpc_byte_buffer_copy ByteBuffer(const ByteBuffer& buf); ~ByteBuffer(); ByteBuffer& operator=(const ByteBuffer&); /// Dump (read) the buffer contents into \a slices. Status Dump(std::vector* slices) const; /// Remove all data. void Clear(); /// Buffer size in bytes. size_t Length() const; /// Swap the state of *this and *other. void Swap(ByteBuffer* other); private: friend class SerializationTraits; // takes ownership void set_buffer(grpc_byte_buffer* buf) { if (buffer_) { Clear(); } buffer_ = buf; } // For \a SerializationTraits's usage. grpc_byte_buffer* buffer() const { return buffer_; } grpc_byte_buffer* buffer_; }; template <> class SerializationTraits { public: static Status Deserialize(grpc_byte_buffer* byte_buffer, ByteBuffer* dest) { dest->set_buffer(byte_buffer); return Status::OK; } static Status Serialize(const ByteBuffer& source, grpc_byte_buffer** buffer, bool* own_buffer) { *buffer = grpc_byte_buffer_copy(source.buffer()); *own_buffer = true; return Status::OK; } }; } // namespace grpc #endif // GRPCXX_SUPPORT_BYTE_BUFFER_H grpc-1.3.2/include/grpc++/support/channel_arguments.h000066400000000000000000000127341310511640000225340ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_SUPPORT_CHANNEL_ARGUMENTS_H #define GRPCXX_SUPPORT_CHANNEL_ARGUMENTS_H #include #include #include #include #include namespace grpc { namespace testing { class ChannelArgumentsTest; } // namespace testing class ResourceQuota; /// Options for channel creation. The user can use generic setters to pass /// key value pairs down to c channel creation code. For grpc related options, /// concrete setters are provided. class ChannelArguments { public: ChannelArguments(); ~ChannelArguments(); ChannelArguments(const ChannelArguments& other); ChannelArguments& operator=(ChannelArguments other) { Swap(other); return *this; } void Swap(ChannelArguments& other); /// Dump arguments in this instance to \a channel_args. Does not take /// ownership of \a channel_args. /// /// Note that the underlying arguments are shared. Changes made to either \a /// channel_args or this instance would be reflected on both. void SetChannelArgs(grpc_channel_args* channel_args) const; // gRPC specific channel argument setters /// Set target name override for SSL host name checking. This option is for /// testing only and should never be used in production. void SetSslTargetNameOverride(const grpc::string& name); // TODO(yangg) add flow control options /// Set the compression algorithm for the channel. void SetCompressionAlgorithm(grpc_compression_algorithm algorithm); /// Set the socket mutator for the channel. void SetSocketMutator(grpc_socket_mutator* mutator); /// The given string will be sent at the front of the user agent string. void SetUserAgentPrefix(const grpc::string& user_agent_prefix); /// The given buffer pool will be attached to the constructed channel void SetResourceQuota(const ResourceQuota& resource_quota); /// Sets the max receive and send message sizes. void SetMaxReceiveMessageSize(int size); void SetMaxSendMessageSize(int size); /// Set LB policy name. /// Note that if the name resolver returns only balancer addresses, the /// grpclb LB policy will be used, regardless of what is specified here. void SetLoadBalancingPolicyName(const grpc::string& lb_policy_name); /// Set service config in JSON form. /// Primarily meant for use in unit tests. void SetServiceConfigJSON(const grpc::string& service_config_json); // Generic channel argument setters. Only for advanced use cases. /// Set an integer argument \a value under \a key. void SetInt(const grpc::string& key, int value); // Generic channel argument setter. Only for advanced use cases. /// Set a pointer argument \a value under \a key. Owership is not transferred. void SetPointer(const grpc::string& key, void* value); void SetPointerWithVtable(const grpc::string& key, void* value, const grpc_arg_pointer_vtable* vtable); /// Set a textual argument \a value under \a key. void SetString(const grpc::string& key, const grpc::string& value); /// Return (by value) a c grpc_channel_args structure which points to /// arguments owned by this ChannelArguments instance grpc_channel_args c_channel_args() const { grpc_channel_args out; out.num_args = args_.size(); out.args = args_.empty() ? NULL : const_cast(&args_[0]); return out; } private: friend class SecureChannelCredentials; friend class testing::ChannelArgumentsTest; /// Default pointer argument operations. struct PointerVtableMembers { static void* Copy(void* in) { return in; } static void Destroy(grpc_exec_ctx* exec_ctx, void* in) {} static int Compare(void* a, void* b) { if (a < b) return -1; if (a > b) return 1; return 0; } }; // Returns empty string when it is not set. grpc::string GetSslTargetNameOverride() const; std::vector args_; std::list strings_; }; } // namespace grpc #endif // GRPCXX_SUPPORT_CHANNEL_ARGUMENTS_H grpc-1.3.2/include/grpc++/support/config.h000066400000000000000000000032571310511640000203040ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_SUPPORT_CONFIG_H #define GRPCXX_SUPPORT_CONFIG_H #include #endif // GRPCXX_SUPPORT_CONFIG_H grpc-1.3.2/include/grpc++/support/error_details.h000066400000000000000000000045501310511640000216720ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_SUPPORT_ERROR_DETAILS_H #define GRPCXX_SUPPORT_ERROR_DETAILS_H #include namespace google { namespace rpc { class Status; } // namespace rpc } // namespace google namespace grpc { // Maps a grpc::Status to a google::rpc::Status. // The given \a to object will be cleared. // On success, returns status with OK. // Returns status with INVALID_ARGUMENT, if failed to deserialize. // Returns status with FAILED_PRECONDITION, if \a to is nullptr. Status ExtractErrorDetails(const Status& from, ::google::rpc::Status* to); // Maps google::rpc::Status to a grpc::Status. // Returns OK on success. // Returns status with FAILED_PRECONDITION if \a to is nullptr. Status SetErrorDetails(const ::google::rpc::Status& from, Status* to); } // namespace grpc #endif // GRPCXX_SUPPORT_ERROR_DETAILS_H grpc-1.3.2/include/grpc++/support/slice.h000066400000000000000000000061201310511640000201260ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_SUPPORT_SLICE_H #define GRPCXX_SUPPORT_SLICE_H #include #include namespace grpc { /// A wrapper around \a grpc_slice. /// /// A slice represents a contiguous reference counted array of bytes. /// It is cheap to take references to a slice, and it is cheap to create a /// slice pointing to a subset of another slice. class Slice final { public: /// Construct an empty slice. Slice(); // Destructor - drops one reference. ~Slice(); enum AddRef { ADD_REF }; /// Construct a slice from \a slice, adding a reference. Slice(grpc_slice slice, AddRef); enum StealRef { STEAL_REF }; /// Construct a slice from \a slice, stealing a reference. Slice(grpc_slice slice, StealRef); /// Copy constructor, adds a reference. Slice(const Slice& other); /// Assignment, reference count is unchanged. Slice& operator=(Slice other) { std::swap(slice_, other.slice_); return *this; } /// Byte size. size_t size() const { return GRPC_SLICE_LENGTH(slice_); } /// Raw pointer to the beginning (first element) of the slice. const uint8_t* begin() const { return GRPC_SLICE_START_PTR(slice_); } /// Raw pointer to the end (one byte \em past the last element) of the slice. const uint8_t* end() const { return GRPC_SLICE_END_PTR(slice_); } /// Raw C slice. Caller needs to call grpc_slice_unref when done. grpc_slice c_slice() const { return grpc_slice_ref(slice_); } private: friend class ByteBuffer; grpc_slice slice_; }; } // namespace grpc #endif // GRPCXX_SUPPORT_SLICE_H grpc-1.3.2/include/grpc++/support/status.h000066400000000000000000000032571310511640000203620ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_SUPPORT_STATUS_H #define GRPCXX_SUPPORT_STATUS_H #include #endif // GRPCXX_SUPPORT_STATUS_H grpc-1.3.2/include/grpc++/support/status_code_enum.h000066400000000000000000000033271310511640000223760ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_SUPPORT_STATUS_CODE_ENUM_H #define GRPCXX_SUPPORT_STATUS_CODE_ENUM_H #include #endif // GRPCXX_SUPPORT_STATUS_CODE_ENUM_H grpc-1.3.2/include/grpc++/support/string_ref.h000066400000000000000000000032771310511640000212030ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_SUPPORT_STRING_REF_H #define GRPCXX_SUPPORT_STRING_REF_H #include #endif // GRPCXX_SUPPORT_STRING_REF_H grpc-1.3.2/include/grpc++/support/stub_options.h000066400000000000000000000033071310511640000215630ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_SUPPORT_STUB_OPTIONS_H #define GRPCXX_SUPPORT_STUB_OPTIONS_H #include #endif // GRPCXX_SUPPORT_STUB_OPTIONS_H grpc-1.3.2/include/grpc++/support/sync_stream.h000066400000000000000000000033031310511640000213560ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_SUPPORT_SYNC_STREAM_H #define GRPCXX_SUPPORT_SYNC_STREAM_H #include #endif // GRPCXX_SUPPORT_SYNC_STREAM_H grpc-1.3.2/include/grpc++/support/time.h000066400000000000000000000032471310511640000177740ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_SUPPORT_TIME_H #define GRPCXX_SUPPORT_TIME_H #include #endif // GRPCXX_SUPPORT_TIME_H grpc-1.3.2/include/grpc++/test/000077500000000000000000000000001310511640000161225ustar00rootroot00000000000000grpc-1.3.2/include/grpc++/test/server_context_test_spouse.h000066400000000000000000000060321310511640000240030ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_TEST_SERVER_CONTEXT_TEST_SPOUSE_H #define GRPCXX_TEST_SERVER_CONTEXT_TEST_SPOUSE_H #include #include namespace grpc { namespace testing { // A test-only class to access private members and methods of ServerContext. class ServerContextTestSpouse { public: explicit ServerContextTestSpouse(ServerContext* ctx) : ctx_(ctx) {} // Inject client metadata to the ServerContext for the test. The test spouse // must be alive when ServerContext::client_metadata is called. void AddClientMetadata(const grpc::string& key, const grpc::string& value) { client_metadata_storage_.insert( std::pair(key, value)); ctx_->client_metadata_.map()->clear(); for (auto iter = client_metadata_storage_.begin(); iter != client_metadata_storage_.end(); ++iter) { ctx_->client_metadata_.map()->insert( std::pair( iter->first.c_str(), grpc::string_ref(iter->second.data(), iter->second.size()))); } } std::multimap GetInitialMetadata() const { return ctx_->initial_metadata_; } std::multimap GetTrailingMetadata() const { return ctx_->trailing_metadata_; } private: ServerContext* ctx_; // not owned std::multimap client_metadata_storage_; }; } // namespace testing } // namespace grpc #endif // GRPCXX_TEST_SERVER_CONTEXT_TEST_SPOUSE_H grpc-1.3.2/include/grpc/000077500000000000000000000000001310511640000150155ustar00rootroot00000000000000grpc-1.3.2/include/grpc/byte_buffer.h000066400000000000000000000104241310511640000174630ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_BYTE_BUFFER_H #define GRPC_BYTE_BUFFER_H #include #include #ifdef __cplusplus extern "C" { #endif /** Returns a RAW byte buffer instance over the given slices (up to \a nslices). * * Increases the reference count for all \a slices processed. The user is * responsible for invoking grpc_byte_buffer_destroy on the returned instance.*/ GRPCAPI grpc_byte_buffer *grpc_raw_byte_buffer_create(grpc_slice *slices, size_t nslices); /** Returns a *compressed* RAW byte buffer instance over the given slices (up to * \a nslices). The \a compression argument defines the compression algorithm * used to generate the data in \a slices. * * Increases the reference count for all \a slices processed. The user is * responsible for invoking grpc_byte_buffer_destroy on the returned instance.*/ GRPCAPI grpc_byte_buffer *grpc_raw_compressed_byte_buffer_create( grpc_slice *slices, size_t nslices, grpc_compression_algorithm compression); /** Copies input byte buffer \a bb. * * Increases the reference count of all the source slices. The user is * responsible for calling grpc_byte_buffer_destroy over the returned copy. */ GRPCAPI grpc_byte_buffer *grpc_byte_buffer_copy(grpc_byte_buffer *bb); /** Returns the size of the given byte buffer, in bytes. */ GRPCAPI size_t grpc_byte_buffer_length(grpc_byte_buffer *bb); /** Destroys \a byte_buffer deallocating all its memory. */ GRPCAPI void grpc_byte_buffer_destroy(grpc_byte_buffer *byte_buffer); /** Reader for byte buffers. Iterates over slices in the byte buffer */ struct grpc_byte_buffer_reader; typedef struct grpc_byte_buffer_reader grpc_byte_buffer_reader; /** Initialize \a reader to read over \a buffer. * Returns 1 upon success, 0 otherwise. */ GRPCAPI int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader, grpc_byte_buffer *buffer); /** Cleanup and destroy \a reader */ GRPCAPI void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader); /** Updates \a slice with the next piece of data from from \a reader and returns * 1. Returns 0 at the end of the stream. Caller is responsible for calling * grpc_slice_unref on the result. */ GRPCAPI int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader *reader, grpc_slice *slice); /** Merge all data from \a reader into single slice */ GRPCAPI grpc_slice grpc_byte_buffer_reader_readall(grpc_byte_buffer_reader *reader); /** Returns a RAW byte buffer instance from the output of \a reader. */ GRPCAPI grpc_byte_buffer *grpc_raw_byte_buffer_from_reader( grpc_byte_buffer_reader *reader); #ifdef __cplusplus } #endif #endif /* GRPC_BYTE_BUFFER_H */ grpc-1.3.2/include/grpc/byte_buffer_reader.h000066400000000000000000000033011310511640000210010ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_BYTE_BUFFER_READER_H #define GRPC_BYTE_BUFFER_READER_H #include #endif /* GRPC_BYTE_BUFFER_READER_H */ grpc-1.3.2/include/grpc/census.h000066400000000000000000000544011310511640000164720ustar00rootroot00000000000000/* * * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* RPC-internal Census API's. These are designed to be generic enough that * they can (ultimately) be used in many different RPC systems (with differing * implementations). */ #ifndef GRPC_CENSUS_H #define GRPC_CENSUS_H #include #ifdef __cplusplus extern "C" { #endif /* Identify census features that can be enabled via census_initialize(). */ enum census_features { CENSUS_FEATURE_NONE = 0, /* Do not enable census. */ CENSUS_FEATURE_TRACING = 1, /* Enable census tracing. */ CENSUS_FEATURE_STATS = 2, /* Enable Census stats collection. */ CENSUS_FEATURE_CPU = 4, /* Enable Census CPU usage collection. */ CENSUS_FEATURE_ALL = CENSUS_FEATURE_TRACING | CENSUS_FEATURE_STATS | CENSUS_FEATURE_CPU }; /** Shutdown and startup census subsystem. The 'features' argument should be * the OR (|) of census_features values. If census fails to initialize, then * census_initialize() will return -1, otherwise the set of enabled features * (which may be smaller than that provided in the `features` argument, see * census_supported()) is returned. It is an error to call census_initialize() * more than once (without an intervening census_shutdown()). These functions * are not thread-safe. */ CENSUSAPI int census_initialize(int features); CENSUSAPI void census_shutdown(void); /** Return the features supported by the current census implementation (not all * features will be available on all platforms). */ CENSUSAPI int census_supported(void); /** Return the census features currently enabled. */ CENSUSAPI int census_enabled(void); /** A Census Context is a handle used by Census to represent the current tracing and stats collection information. Contexts should be propagated across RPC's (this is the responsibility of the local RPC system). A context is typically used as the first argument to most census functions. Conceptually, they should be thought of as specific to a single RPC/thread. The user visible context representation is that of a collection of key:value string pairs, each of which is termed a 'tag'; these form the basis against which Census metrics will be recorded. Keys are unique within a context. */ typedef struct census_context census_context; /* A tag is a key:value pair. Both keys and values are nil-terminated strings, containing printable ASCII characters (decimal 32-126). Keys must be at least one character in length. Both keys and values can have at most CENSUS_MAX_TAG_KB_LEN characters (including the terminating nil). The maximum number of tags that can be propagated is CENSUS_MAX_PROPAGATED_TAGS. Users should also remember that some systems may have limits on, e.g., the number of bytes that can be transmitted as metadata, and that larger tags means more memory consumed and time in processing. */ typedef struct { const char *key; const char *value; uint8_t flags; } census_tag; /* Maximum length of a tag's key or value. */ #define CENSUS_MAX_TAG_KV_LEN 255 /* Maximum number of propagatable tags. */ #define CENSUS_MAX_PROPAGATED_TAGS 255 /* Tag flags. */ #define CENSUS_TAG_PROPAGATE 1 /* Tag should be propagated over RPC */ #define CENSUS_TAG_STATS 2 /* Tag will be used for statistics aggregation */ #define CENSUS_TAG_RESERVED 4 /* Reserved for internal use. */ /* Flag values 4,8,16,32,64,128 are reserved for future/internal use. Clients should not use or rely on their values. */ #define CENSUS_TAG_IS_PROPAGATED(flags) (flags & CENSUS_TAG_PROPAGATE) #define CENSUS_TAG_IS_STATS(flags) (flags & CENSUS_TAG_STATS) /* An instance of this structure is kept by every context, and records the basic information associated with the creation of that context. */ typedef struct { int n_propagated_tags; /* number of propagated tags */ int n_local_tags; /* number of non-propagated (local) tags */ int n_deleted_tags; /* number of tags that were deleted */ int n_added_tags; /* number of tags that were added */ int n_modified_tags; /* number of tags that were modified */ int n_invalid_tags; /* number of tags with bad keys or values (e.g. longer than CENSUS_MAX_TAG_KV_LEN) */ int n_ignored_tags; /* number of tags ignored because of CENSUS_MAX_PROPAGATED_TAGS limit. */ } census_context_status; /* Create a new context, adding and removing tags from an existing context. This will copy all tags from the 'tags' input, so it is recommended to add as many tags in a single operation as is practical for the client. @param base Base context to build upon. Can be NULL. @param tags A set of tags to be added/changed/deleted. Tags with keys that are in 'tags', but not 'base', are added to the context. Keys that are in both 'tags' and 'base' will have their value/flags modified. Tags with keys in both, but with NULL values, will be deleted from the context. Tags with invalid (too long or short) keys or values will be ignored. If adding a tag will result in more than CENSUS_MAX_PROPAGATED_TAGS in either binary or non-binary tags, they will be ignored, as will deletions of tags that don't exist. @param ntags number of tags in 'tags' @param status If not NULL, will return a pointer to a census_context_status structure containing information about the new context and status of the tags used in its creation. @return A new, valid census_context. */ CENSUSAPI census_context *census_context_create( const census_context *base, const census_tag *tags, int ntags, census_context_status const **status); /* Destroy a context. Once this function has been called, the context cannot be reused. */ CENSUSAPI void census_context_destroy(census_context *context); /* Get a pointer to the original status from the context creation. */ CENSUSAPI const census_context_status *census_context_get_status( const census_context *context); /* Structure used for iterating over the tags in a context. API clients should not use or reference internal fields - neither their contents or presence/absence are guaranteed. */ typedef struct { const census_context *context; int base; int index; char *kvm; } census_context_iterator; /* Initialize a census_tag_iterator. Must be called before first use. */ CENSUSAPI void census_context_initialize_iterator( const census_context *context, census_context_iterator *iterator); /* Get the contents of the "next" tag in the context. If there are no more tags, returns 0 (and 'tag' contents will be unchanged), otherwise returns 1. */ CENSUSAPI int census_context_next_tag(census_context_iterator *iterator, census_tag *tag); /* Get a context tag by key. Returns 0 if the key is not present. */ CENSUSAPI int census_context_get_tag(const census_context *context, const char *key, census_tag *tag); /* Tag set encode/decode functionality. These functions are intended for use by RPC systems only, for purposes of transmitting/receiving contexts. */ /* Encode a context into a buffer. @param context context to be encoded @param buffer buffer into which the context will be encoded. @param buf_size number of available bytes in buffer. @return The number of buffer bytes consumed for the encoded context, or zero if the buffer was of insufficient size. */ CENSUSAPI size_t census_context_encode(const census_context *context, char *buffer, size_t buf_size); /* Decode context buffer encoded with census_context_encode(). Returns NULL if there is an error in parsing either buffer. */ CENSUSAPI census_context *census_context_decode(const char *buffer, size_t size); /* Distributed traces can have a number of options. */ enum census_trace_mask_values { CENSUS_TRACE_MASK_NONE = 0, /* Default, empty flags */ CENSUS_TRACE_MASK_IS_SAMPLED = 1 /* RPC tracing enabled for this context. */ }; /** Get the current trace mask associated with this context. The value returned will be the logical OR of census_trace_mask_values values. */ CENSUSAPI int census_trace_mask(const census_context *context); /** Set the trace mask associated with a context. */ CENSUSAPI void census_set_trace_mask(int trace_mask); /* The concept of "operation" is a fundamental concept for Census. In an RPC system, an operation typically represents a single RPC, or a significant sub-part thereof (e.g. a single logical "read" RPC to a distributed storage system might do several other actions in parallel, from looking up metadata indices to making requests of other services - each of these could be a sub-operation with the larger RPC operation). Census uses operations for the following: CPU accounting: If enabled, census will measure the thread CPU time consumed between operation start and end times. Active operations: Census will maintain information on all currently active operations. Distributed tracing: Each operation serves as a logical trace span. Stats collection: Stats are broken down by operation (e.g. latency breakdown for each unique RPC path). The following functions serve to delineate the start and stop points for each logical operation. */ /** This structure represents a timestamp as used by census to record the time at which an operation begins. */ typedef struct { /* Use gpr_timespec for default implementation. High performance * implementations should use a cycle-counter based timestamp. */ gpr_timespec ts; } census_timestamp; /** Mark the beginning of an RPC operation. The information required to call the functions to record the start of RPC operations (both client and server) may not be callable at the true start time of the operation, due to information not being available (e.g. the census context data will not be available in a server RPC until at least initial metadata has been processed). To ensure correct CPU accounting and latency recording, RPC systems can call this function to get the timestamp of operation beginning. This can later be used as an argument to census_start_{client,server}_rpc_op(). NB: for correct CPU accounting, the system must guarantee that the same thread is used for all request processing after this function is called. @return A timestamp representing the operation start time. */ CENSUSAPI census_timestamp census_start_rpc_op_timestamp(void); /** Represent functions to map RPC name ID to service/method names. Census breaks down all RPC stats by service and method names. We leave the definition and format of these to the RPC system. For efficiency purposes, we encode these as a single 64 bit identifier, and allow the RPC system to provide a structure for functions that can convert these to service and method strings. TODO(aveitch): Instead of providing this as an argument to the rpc_start_op() functions, maybe it should be set once at census initialization. */ typedef struct { const char *(*get_rpc_service_name)(int64_t id); const char *(*get_rpc_method_name)(int64_t id); } census_rpc_name_info; /** Start a client rpc operation. This function should be called as early in the client RPC path as possible. This function will create a new context. If the context argument is non-null, then the new context will inherit all its properties, with the following changes: - create a new operation ID for the new context, marking it as a child of the previous operation. - use the new RPC path and peer information for tracing and stats collection purposes, rather than those from the original context If the context argument is NULL, then a new root context is created. This is particularly important for tracing purposes (the trace spans generated will be unassociated with any other trace spans, except those downstream). The trace_mask will be used for tracing operations associated with the new context. In some RPC systems (e.g. where load balancing is used), peer information may not be available at the time the operation starts. In this case, use a NULL value for peer, and set it later using the census_set_rpc_client_peer() function. @param context The parent context. Can be NULL. @param rpc_name_id The rpc name identifier to be associated with this RPC. @param rpc_name_info Used to decode rpc_name_id. @param peer RPC peer. If not available at the time, NULL can be used, and a later census_set_rpc_client_peer() call made. @param trace_mask An OR of census_trace_mask_values values. Only used in the creation of a new root context (context == NULL). @param start_time A timestamp returned from census_start_rpc_op_timestamp(). Can be NULL. Used to set the true time the operation begins. @return A new census context. */ CENSUSAPI census_context *census_start_client_rpc_op( const census_context *context, int64_t rpc_name_id, const census_rpc_name_info *rpc_name_info, const char *peer, int trace_mask, const census_timestamp *start_time); /** Add peer information to a context representing a client RPC operation. */ CENSUSAPI void census_set_rpc_client_peer(census_context *context, const char *peer); /** Start a server RPC operation. Returns a new context to be used in future census calls. If buffer is non-NULL, then the buffer contents should represent the client context, as generated by census_context_serialize(). If buffer is NULL, a new root context is created. @param buffer Buffer containing bytes output from census_context_serialize(). @param rpc_name_id The rpc name identifier to be associated with this RPC. @param rpc_name_info Used to decode rpc_name_id. @param peer RPC peer. @param trace_mask An OR of census_trace_mask_values values. Only used in the creation of a new root context (buffer == NULL). @param start_time A timestamp returned from census_start_rpc_op_timestamp(). Can be NULL. Used to set the true time the operation begins. @return A new census context. */ CENSUSAPI census_context *census_start_server_rpc_op( const char *buffer, int64_t rpc_name_id, const census_rpc_name_info *rpc_name_info, const char *peer, int trace_mask, census_timestamp *start_time); /** Start a new, non-RPC operation. In general, this function works very similarly to census_start_client_rpc_op, with the primary difference being the replacement of host/path information with the more generic family/name tags. If the context argument is non-null, then the new context will inherit all its properties, with the following changes: - create a new operation ID for the new context, marking it as a child of the previous operation. - use the family and name information for tracing and stats collection purposes, rather than those from the original context If the context argument is NULL, then a new root context is created. This is particularly important for tracing purposes (the trace spans generated will be unassociated with any other trace spans, except those downstream). The trace_mask will be used for tracing operations associated with the new context. @param context The base context. Can be NULL. @param family Family name to associate with the trace @param name Name within family to associate with traces/stats @param trace_mask An OR of census_trace_mask_values values. Only used if context is NULL. @return A new census context. */ CENSUSAPI census_context *census_start_op(census_context *context, const char *family, const char *name, int trace_mask); /** End an operation started by any of the census_start_*_op*() calls. The context used in this call will no longer be valid once this function completes. @param context Context associated with operation which is ending. @param status status associated with the operation. Not interpreted by census. */ CENSUSAPI void census_end_op(census_context *context, int status); #define CENSUS_TRACE_RECORD_START_OP ((uint32_t)0) #define CENSUS_TRACE_RECORD_END_OP ((uint32_t)1) /** Insert a trace record into the trace stream. The record consists of an arbitrary size buffer, the size of which is provided in 'n'. @param context Trace context @param type User-defined type to associate with trace entry. @param buffer Pointer to buffer to use @param n Number of bytes in buffer */ CENSUSAPI void census_trace_print(census_context *context, uint32_t type, const char *buffer, size_t n); /** Trace record. */ typedef struct { census_timestamp timestamp; /* Time of record creation */ uint64_t trace_id; /* Trace ID associated with record */ uint64_t op_id; /* Operation ID associated with record */ uint32_t type; /* Type (as used in census_trace_print() */ const char *buffer; /* Buffer (from census_trace_print() */ size_t buf_size; /* Number of bytes inside buffer */ } census_trace_record; /** Start a scan of existing trace records. While a scan is ongoing, addition of new trace records will be blocked if the underlying trace buffers fill up, so trace processing systems should endeavor to complete reading as soon as possible. @param consume if non-zero, indicates that reading records also "consumes" the previously read record - i.e. releases space in the trace log while scanning is ongoing. @returns 0 on success, non-zero on failure (e.g. if a scan is already ongoing) */ CENSUSAPI int census_trace_scan_start(int consume); /** Get a trace record. The data pointed to by the trace buffer is guaranteed stable until the next census_get_trace_record() call (if the consume argument to census_trace_scan_start was non-zero) or census_trace_scan_end() is called (otherwise). @param trace_record structure that will be filled in with oldest trace record. @returns -1 if an error occurred (e.g. no previous call to census_trace_scan_start()), 0 if there is no more trace data (and trace_record will not be modified) or 1 otherwise. */ CENSUSAPI int census_get_trace_record(census_trace_record *trace_record); /** End a scan previously started by census_trace_scan_start() */ CENSUSAPI void census_trace_scan_end(); /* Core stats collection API's. The following concepts are used: * Resource: Users record measurements for a single resource. Examples include RPC latency, CPU seconds consumed, and bytes transmitted. * Aggregation: An aggregation of a set of measurements. Census supports the following aggregation types: * Distribution - statistical distribution information, used for recording average, standard deviation etc. Can include a histogram. * Interval - a count of events that happen in a rolling time window. * View: A view is a combination of a Resource, a set of tag keys and an Aggregation. When a measurement for a Resource matches the View tags, it is recorded (for each unique set of tag values) using the Aggregation type. Each resource can have an arbitrary number of views by which it will be broken down. Census uses protos to define each of the above, and output results. This ensures unification across the different language and runtime implementations. The proto definitions can be found in src/proto/census. */ /* Define a new resource. `resource_pb` should contain an encoded Resource protobuf, `resource_pb_size` being the size of the buffer. Returns a -ve value on error, or a positive (>= 0) resource id (for use in census_delete_resource() and census_record_values()). In order to be valid, a resource must have a name, and at least one numerator in its unit type. The resource name must be unique, and an error will be returned if it is not. */ CENSUSAPI int32_t census_define_resource(const uint8_t *resource_pb, size_t resource_pb_size); /* Delete a resource created by census_define_resource(). */ CENSUSAPI void census_delete_resource(int32_t resource_id); /* Determine the id of a resource, given its name. returns -1 if the resource does not exist. */ CENSUSAPI int32_t census_resource_id(const char *name); /* A single value to be recorded comprises two parts: an ID for the particular * resource and the value to be recorded against it. */ typedef struct { int32_t resource_id; double value; } census_value; /* Record new usage values against the given context. */ CENSUSAPI void census_record_values(census_context *context, census_value *values, size_t nvalues); #ifdef __cplusplus } #endif #endif /* GRPC_CENSUS_H */ grpc-1.3.2/include/grpc/compression.h000066400000000000000000000065211310511640000175330ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_COMPRESSION_H #define GRPC_COMPRESSION_H #include #include #include #include #ifdef __cplusplus extern "C" { #endif /** Parses the first \a name_length bytes of \a name as a * grpc_compression_algorithm instance, updating \a algorithm. Returns 1 upon * success, 0 otherwise. */ GRPCAPI int grpc_compression_algorithm_parse( grpc_slice value, grpc_compression_algorithm *algorithm); /** Updates \a name with the encoding name corresponding to a valid \a * algorithm. Note that \a name is statically allocated and must *not* be freed. * Returns 1 upon success, 0 otherwise. */ GRPCAPI int grpc_compression_algorithm_name( grpc_compression_algorithm algorithm, char **name); /** Returns the compression algorithm corresponding to \a level for the * compression algorithms encoded in the \a accepted_encodings bitset. * * It abort()s for unknown levels . */ GRPCAPI grpc_compression_algorithm grpc_compression_algorithm_for_level( grpc_compression_level level, uint32_t accepted_encodings); GRPCAPI void grpc_compression_options_init(grpc_compression_options *opts); /** Mark \a algorithm as enabled in \a opts. */ GRPCAPI void grpc_compression_options_enable_algorithm( grpc_compression_options *opts, grpc_compression_algorithm algorithm); /** Mark \a algorithm as disabled in \a opts. */ GRPCAPI void grpc_compression_options_disable_algorithm( grpc_compression_options *opts, grpc_compression_algorithm algorithm); /** Returns true if \a algorithm is marked as enabled in \a opts. */ GRPCAPI int grpc_compression_options_is_algorithm_enabled( const grpc_compression_options *opts, grpc_compression_algorithm algorithm); #ifdef __cplusplus } #endif #endif /* GRPC_COMPRESSION_H */ grpc-1.3.2/include/grpc/grpc.h000066400000000000000000000561161310511640000161320ustar00rootroot00000000000000/* * * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_GRPC_H #define GRPC_GRPC_H #include #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /*! \mainpage GRPC Core * * The GRPC Core library is a low-level library designed to be wrapped by higher * level libraries. The top-level API is provided in grpc.h. Security related * functionality lives in grpc_security.h. */ GRPCAPI void grpc_metadata_array_init(grpc_metadata_array *array); GRPCAPI void grpc_metadata_array_destroy(grpc_metadata_array *array); GRPCAPI void grpc_call_details_init(grpc_call_details *details); GRPCAPI void grpc_call_details_destroy(grpc_call_details *details); /** Registers a plugin to be initialized and destroyed with the library. The \a init and \a destroy functions will be invoked as part of \a grpc_init() and \a grpc_shutdown(), respectively. Note that these functions can be invoked an arbitrary number of times (and hence so will \a init and \a destroy). It is safe to pass NULL to either argument. Plugins are destroyed in the reverse order they were initialized. */ GRPCAPI void grpc_register_plugin(void (*init)(void), void (*destroy)(void)); /** Initialize the grpc library. It is not safe to call any other grpc functions before calling this. (To avoid overhead, little checking is done, and some things may work. We do not warrant that they will continue to do so in future revisions of this library). */ GRPCAPI void grpc_init(void); /** Shut down the grpc library. No memory is used by grpc after this call returns, nor are any instructions executing within the grpc library. Prior to calling, all application owned grpc objects must have been destroyed. */ GRPCAPI void grpc_shutdown(void); /** Return a string representing the current version of grpc */ GRPCAPI const char *grpc_version_string(void); /** Return a string specifying what the 'g' in gRPC stands for */ GRPCAPI const char *grpc_g_stands_for(void); /** Specifies the type of APIs to use to pop events from the completion queue */ typedef enum { /* Events are popped out by calling grpc_completion_queue_next() API ONLY */ GRPC_CQ_NEXT = 1, /* Events are popped out by calling grpc_completion_queue_pluck() API ONLY */ GRPC_CQ_PLUCK } grpc_cq_completion_type; /** Completion queues internally MAY maintain a set of file descriptors in a structure called 'pollset'. This enum specifies if a completion queue has an associated pollset and any restrictions on the type of file descriptors that can be present in the pollset. I/O progress can only be made when grpc_completion_queue_next() or grpc_completion_queue_pluck() are called on the completion queue (unless the grpc_cq_polling_type is GRPC_CQ_NON_POLLING) and hence it is very important to actively call these APIs */ typedef enum { /** The completion queue will have an associated pollset and there is no restriction on the type of file descriptors the pollset may contain */ GRPC_CQ_DEFAULT_POLLING, /* Similar to GRPC_CQ_DEFAULT_POLLING except that the completion queues will not contain any 'listening file descriptors' (i.e file descriptors used to listen to incoming channels) */ GRPC_CQ_NON_LISTENING, /* The completion queue will not have an associated pollset. Note that grpc_completion_queue_next() or grpc_completion_queue_pluck() MUST still be called to pop events from the completion queue; it is not required to call them actively to make I/O progress */ GRPC_CQ_NON_POLLING } grpc_cq_polling_type; #define GRPC_CQ_CURRENT_VERSION 1 typedef struct grpc_completion_queue_attributes { /* The version number of this structure. More fields might be added to this structure in future. */ int version; /* Set to GRPC_CQ_CURRENT_VERSION */ grpc_cq_completion_type cq_completion_type; grpc_cq_polling_type cq_polling_type; } grpc_completion_queue_attributes; /** The completion queue factory structure is opaque to the callers of grpc */ typedef struct grpc_completion_queue_factory grpc_completion_queue_factory; /** Returns the completion queue factory based on the attributes. MAY return a NULL if no factory can be found */ GRPCAPI const grpc_completion_queue_factory * grpc_completion_queue_factory_lookup( const grpc_completion_queue_attributes *attributes); /** Helper function to create a completion queue with grpc_cq_completion_type of GRPC_CQ_NEXT and grpc_cq_polling_type of GRPC_CQ_DEFAULT_POLLING */ GRPCAPI grpc_completion_queue *grpc_completion_queue_create_for_next( void *reserved); /** Helper function to create a completion queue with grpc_cq_completion_type of GRPC_CQ_PLUCK and grpc_cq_polling_type of GRPC_CQ_DEFAULT_POLLING */ GRPCAPI grpc_completion_queue *grpc_completion_queue_create_for_pluck( void *reserved); /** Create a completion queue */ GRPCAPI grpc_completion_queue *grpc_completion_queue_create(void *reserved); /** Blocks until an event is available, the completion queue is being shut down, or deadline is reached. Returns a grpc_event with type GRPC_QUEUE_TIMEOUT on timeout, otherwise a grpc_event describing the event that occurred. Callers must not call grpc_completion_queue_next and grpc_completion_queue_pluck simultaneously on the same completion queue. */ GRPCAPI grpc_event grpc_completion_queue_next(grpc_completion_queue *cq, gpr_timespec deadline, void *reserved); /** Blocks until an event with tag 'tag' is available, the completion queue is being shutdown or deadline is reached. Returns a grpc_event with type GRPC_QUEUE_TIMEOUT on timeout, otherwise a grpc_event describing the event that occurred. Callers must not call grpc_completion_queue_next and grpc_completion_queue_pluck simultaneously on the same completion queue. Completion queues support a maximum of GRPC_MAX_COMPLETION_QUEUE_PLUCKERS concurrently executing plucks at any time. */ GRPCAPI grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cq, void *tag, gpr_timespec deadline, void *reserved); /** Maximum number of outstanding grpc_completion_queue_pluck executions per completion queue */ #define GRPC_MAX_COMPLETION_QUEUE_PLUCKERS 6 /** Begin destruction of a completion queue. Once all possible events are drained then grpc_completion_queue_next will start to produce GRPC_QUEUE_SHUTDOWN events only. At that point it's safe to call grpc_completion_queue_destroy. After calling this function applications should ensure that no NEW work is added to be published on this completion queue. */ GRPCAPI void grpc_completion_queue_shutdown(grpc_completion_queue *cq); /** Destroy a completion queue. The caller must ensure that the queue is drained and no threads are executing grpc_completion_queue_next */ GRPCAPI void grpc_completion_queue_destroy(grpc_completion_queue *cq); /** Create a completion queue alarm instance associated to \a cq. * * Once the alarm expires (at \a deadline) or it's cancelled (see \a * grpc_alarm_cancel), an event with tag \a tag will be added to \a cq. If the * alarm expired, the event's success bit will be true, false otherwise (ie, * upon cancellation). */ GRPCAPI grpc_alarm *grpc_alarm_create(grpc_completion_queue *cq, gpr_timespec deadline, void *tag); /** Cancel a completion queue alarm. Calling this function over an alarm that * has already fired has no effect. */ GRPCAPI void grpc_alarm_cancel(grpc_alarm *alarm); /** Destroy the given completion queue alarm, cancelling it in the process. */ GRPCAPI void grpc_alarm_destroy(grpc_alarm *alarm); /** Check the connectivity state of a channel. */ GRPCAPI grpc_connectivity_state grpc_channel_check_connectivity_state( grpc_channel *channel, int try_to_connect); /** Watch for a change in connectivity state. Once the channel connectivity state is different from last_observed_state, tag will be enqueued on cq with success=1. If deadline expires BEFORE the state is changed, tag will be enqueued on cq with success=0. */ GRPCAPI void grpc_channel_watch_connectivity_state( grpc_channel *channel, grpc_connectivity_state last_observed_state, gpr_timespec deadline, grpc_completion_queue *cq, void *tag); /** Create a call given a grpc_channel, in order to call 'method'. All completions are sent to 'completion_queue'. 'method' and 'host' need only live through the invocation of this function. If parent_call is non-NULL, it must be a server-side call. It will be used to propagate properties from the server call to this new client call, depending on the value of \a propagation_mask (see propagation_bits.h for possible values). */ GRPCAPI grpc_call *grpc_channel_create_call( grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_completion_queue *completion_queue, grpc_slice method, const grpc_slice *host, gpr_timespec deadline, void *reserved); /** Ping the channels peer (load balanced channels will select one sub-channel to ping); if the channel is not connected, posts a failed. */ GRPCAPI void grpc_channel_ping(grpc_channel *channel, grpc_completion_queue *cq, void *tag, void *reserved); /** Pre-register a method/host pair on a channel. */ GRPCAPI void *grpc_channel_register_call(grpc_channel *channel, const char *method, const char *host, void *reserved); /** Create a call given a handle returned from grpc_channel_register_call. \sa grpc_channel_create_call. */ GRPCAPI grpc_call *grpc_channel_create_registered_call( grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_completion_queue *completion_queue, void *registered_call_handle, gpr_timespec deadline, void *reserved); /** Start a batch of operations defined in the array ops; when complete, post a completion of type 'tag' to the completion queue bound to the call. The order of ops specified in the batch has no significance. Only one operation of each type can be active at once in any given batch. If a call to grpc_call_start_batch returns GRPC_CALL_OK you must call grpc_completion_queue_next or grpc_completion_queue_pluck on the completion queue associated with 'call' for work to be performed. If a call to grpc_call_start_batch returns any value other than GRPC_CALL_OK it is guaranteed that no state associated with 'call' is changed and it is not appropriate to call grpc_completion_queue_next or grpc_completion_queue_pluck consequent to the failed grpc_call_start_batch call. THREAD SAFETY: access to grpc_call_start_batch in multi-threaded environment needs to be synchronized. As an optimization, you may synchronize batches containing just send operations independently from batches containing just receive operations. */ GRPCAPI grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops, size_t nops, void *tag, void *reserved); /** Returns a newly allocated string representing the endpoint to which this call is communicating with. The string is in the uri format accepted by grpc_channel_create. The returned string should be disposed of with gpr_free(). WARNING: this value is never authenticated or subject to any security related code. It must not be used for any authentication related functionality. Instead, use grpc_auth_context. */ GRPCAPI char *grpc_call_get_peer(grpc_call *call); struct grpc_load_reporting_cost_context; /* Associate costs contained in \a cost_context to \a call. */ GRPCAPI void grpc_call_set_load_reporting_cost_context( grpc_call *call, struct grpc_load_reporting_cost_context *context); struct census_context; /** Set census context for a call; Must be called before first call to grpc_call_start_batch(). */ GRPCAPI void grpc_census_call_set_context(grpc_call *call, struct census_context *context); /** Retrieve the calls current census context. */ GRPCAPI struct census_context *grpc_census_call_get_context(grpc_call *call); /** Return a newly allocated string representing the target a channel was created for. */ GRPCAPI char *grpc_channel_get_target(grpc_channel *channel); /** Request info about the channel. \a channel_info indicates what information is being requested and how that information will be returned. \a channel_info is owned by the caller. */ GRPCAPI void grpc_channel_get_info(grpc_channel *channel, const grpc_channel_info *channel_info); /** Create a client channel to 'target'. Additional channel level configuration MAY be provided by grpc_channel_args, though the expectation is that most clients will want to simply pass NULL. See grpc_channel_args definition for more on this. The data in 'args' need only live through the invocation of this function. */ GRPCAPI grpc_channel *grpc_insecure_channel_create( const char *target, const grpc_channel_args *args, void *reserved); /** Create a lame client: this client fails every operation attempted on it. */ GRPCAPI grpc_channel *grpc_lame_client_channel_create( const char *target, grpc_status_code error_code, const char *error_message); /** Close and destroy a grpc channel */ GRPCAPI void grpc_channel_destroy(grpc_channel *channel); /* Error handling for grpc_call Most grpc_call functions return a grpc_error. If the error is not GRPC_OK then the operation failed due to some unsatisfied precondition. If a grpc_call fails, it's guaranteed that no change to the call state has been made. */ /** Called by clients to cancel an RPC on the server. Can be called multiple times, from any thread. THREAD-SAFETY grpc_call_cancel and grpc_call_cancel_with_status are thread-safe, and can be called at any point before grpc_call_destroy is called.*/ GRPCAPI grpc_call_error grpc_call_cancel(grpc_call *call, void *reserved); /** Called by clients to cancel an RPC on the server. Can be called multiple times, from any thread. If a status has not been received for the call, set it to the status code and description passed in. Importantly, this function does not send status nor description to the remote endpoint. */ GRPCAPI grpc_call_error grpc_call_cancel_with_status(grpc_call *call, grpc_status_code status, const char *description, void *reserved); /** Destroy a call. THREAD SAFETY: grpc_call_destroy is thread-compatible */ GRPCAPI void grpc_call_destroy(grpc_call *call); /** Request notification of a new call. Once a call is received, a notification tagged with \a tag_new is added to \a cq_for_notification. \a call, \a details and \a request_metadata are updated with the appropriate call information. \a cq_bound_to_call is bound to \a call, and batch operation notifications for that call will be posted to \a cq_bound_to_call. Note that \a cq_for_notification must have been registered to the server via \a grpc_server_register_completion_queue. */ GRPCAPI grpc_call_error grpc_server_request_call( grpc_server *server, grpc_call **call, grpc_call_details *details, grpc_metadata_array *request_metadata, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new); /** How to handle payloads for a registered method */ typedef enum { /** Don't try to read the payload */ GRPC_SRM_PAYLOAD_NONE, /** Read the initial payload as a byte buffer */ GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER } grpc_server_register_method_payload_handling; /** Registers a method in the server. Methods to this (host, method) pair will not be reported by grpc_server_request_call, but instead be reported by grpc_server_request_registered_call when passed the appropriate registered_method (as returned by this function). Must be called before grpc_server_start. Returns NULL on failure. */ GRPCAPI void *grpc_server_register_method( grpc_server *server, const char *method, const char *host, grpc_server_register_method_payload_handling payload_handling, uint32_t flags); /** Request notification of a new pre-registered call. 'cq_for_notification' must have been registered to the server via grpc_server_register_completion_queue. */ GRPCAPI grpc_call_error grpc_server_request_registered_call( grpc_server *server, void *registered_method, grpc_call **call, gpr_timespec *deadline, grpc_metadata_array *request_metadata, grpc_byte_buffer **optional_payload, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new); /** Create a server. Additional configuration for each incoming channel can be specified with args. If no additional configuration is needed, args can be NULL. See grpc_channel_args for more. The data in 'args' need only live through the invocation of this function. */ GRPCAPI grpc_server *grpc_server_create(const grpc_channel_args *args, void *reserved); /** Register a completion queue with the server. Must be done for any notification completion queue that is passed to grpc_server_request_*_call and to grpc_server_shutdown_and_notify. Must be performed prior to grpc_server_start. */ GRPCAPI void grpc_server_register_completion_queue(grpc_server *server, grpc_completion_queue *cq, void *reserved); /** Register a non-listening completion queue with the server. This API is similar to grpc_server_register_completion_queue except that the server will not use this completion_queue to listen to any incoming channels. Registering a non-listening completion queue will have negative performance impact and hence this API is not recommended for production use cases. */ GRPCAPI void grpc_server_register_non_listening_completion_queue( grpc_server *server, grpc_completion_queue *q, void *reserved); /** Add a HTTP2 over plaintext over tcp listener. Returns bound port number on success, 0 on failure. REQUIRES: server not started */ GRPCAPI int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr); /** Start a server - tells all listeners to start listening */ GRPCAPI void grpc_server_start(grpc_server *server); /** Begin shutting down a server. After completion, no new calls or connections will be admitted. Existing calls will be allowed to complete. Send a GRPC_OP_COMPLETE event when there are no more calls being serviced. Shutdown is idempotent, and all tags will be notified at once if multiple grpc_server_shutdown_and_notify calls are made. 'cq' must have been registered to this server via grpc_server_register_completion_queue. */ GRPCAPI void grpc_server_shutdown_and_notify(grpc_server *server, grpc_completion_queue *cq, void *tag); /** Cancel all in-progress calls. Only usable after shutdown. */ GRPCAPI void grpc_server_cancel_all_calls(grpc_server *server); /** Destroy a server. Shutdown must have completed beforehand (i.e. all tags generated by grpc_server_shutdown_and_notify must have been received, and at least one call to grpc_server_shutdown_and_notify must have been made). */ GRPCAPI void grpc_server_destroy(grpc_server *server); /** Enable or disable a tracer. Tracers (usually controlled by the environment variable GRPC_TRACE) allow printf-style debugging on GRPC internals, and are useful for tracking down problems in the field. Use of this function is not strictly thread-safe, but the thread-safety issues raised by it should not be of concern. */ GRPCAPI int grpc_tracer_set_enabled(const char *name, int enabled); /** Check whether a metadata key is legal (will be accepted by core) */ GRPCAPI int grpc_header_key_is_legal(grpc_slice slice); /** Check whether a non-binary metadata value is legal (will be accepted by core) */ GRPCAPI int grpc_header_nonbin_value_is_legal(grpc_slice slice); /** Check whether a metadata key corresponds to a binary value */ GRPCAPI int grpc_is_binary_header(grpc_slice slice); /** Convert grpc_call_error values to a string */ GRPCAPI const char *grpc_call_error_to_string(grpc_call_error error); /** Create a buffer pool */ GRPCAPI grpc_resource_quota *grpc_resource_quota_create(const char *trace_name); /** Add a reference to a buffer pool */ GRPCAPI void grpc_resource_quota_ref(grpc_resource_quota *resource_quota); /** Drop a reference to a buffer pool */ GRPCAPI void grpc_resource_quota_unref(grpc_resource_quota *resource_quota); /** Update the size of a buffer pool */ GRPCAPI void grpc_resource_quota_resize(grpc_resource_quota *resource_quota, size_t new_size); /** Fetch a vtable for a grpc_channel_arg that points to a grpc_resource_quota */ GRPCAPI const grpc_arg_pointer_vtable *grpc_resource_quota_arg_vtable(void); #ifdef __cplusplus } #endif #endif /* GRPC_GRPC_H */ grpc-1.3.2/include/grpc/grpc_cronet.h000066400000000000000000000035521310511640000175000ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_GRPC_CRONET_H #define GRPC_GRPC_CRONET_H #include #ifdef __cplusplus extern "C" { #endif GRPCAPI grpc_channel *grpc_cronet_secure_channel_create( void *engine, const char *target, const grpc_channel_args *args, void *reserved); #ifdef __cplusplus } #endif #endif /* GRPC_GRPC_CRONET_H */ grpc-1.3.2/include/grpc/grpc_posix.h000066400000000000000000000063671310511640000173570ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_GRPC_POSIX_H #define GRPC_GRPC_POSIX_H #include #include #include #ifdef __cplusplus extern "C" { #endif /*! \mainpage GRPC Core POSIX * * The GRPC Core POSIX library provides some POSIX-specific low-level * functionality on top of GRPC Core. */ /** Create a client channel to 'target' using file descriptor 'fd'. The 'target' argument will be used to indicate the name for this channel. See the comment for grpc_insecure_channel_create for description of 'args' argument. */ GRPCAPI grpc_channel *grpc_insecure_channel_create_from_fd( const char *target, int fd, const grpc_channel_args *args); /** Add the connected communication channel based on file descriptor 'fd' to the 'server'. The 'fd' must be an open file descriptor corresponding to a connected socket. Events from the file descriptor may come on any of the server completion queues (i.e completion queues registered via the grpc_server_register_completion_queue API). The 'reserved' pointer MUST be NULL. */ GRPCAPI void grpc_server_add_insecure_channel_from_fd(grpc_server *server, void *reserved, int fd); /** GRPC Core POSIX library may internally use signals to optimize some work. The library uses (SIGRTMIN + 6) signal by default. Use this API to instruct the library to use a different signal i.e 'signum' instead. Note: - To prevent GRPC library from using any signals, pass a 'signum' of -1 - This API is optional but if called, it MUST be called before grpc_init() */ GRPCAPI void grpc_use_signal(int signum); #ifdef __cplusplus } #endif #endif /* GRPC_GRPC_POSIX_H */ grpc-1.3.2/include/grpc/grpc_security.h000066400000000000000000000426121310511640000200550ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_GRPC_SECURITY_H #define GRPC_GRPC_SECURITY_H #include #include #include #ifdef __cplusplus extern "C" { #endif /* --- Authentication Context. --- */ typedef struct grpc_auth_context grpc_auth_context; typedef struct grpc_auth_property_iterator { const grpc_auth_context *ctx; size_t index; const char *name; } grpc_auth_property_iterator; /* value, if not NULL, is guaranteed to be NULL terminated. */ typedef struct grpc_auth_property { char *name; char *value; size_t value_length; } grpc_auth_property; /* Returns NULL when the iterator is at the end. */ GRPCAPI const grpc_auth_property *grpc_auth_property_iterator_next( grpc_auth_property_iterator *it); /* Iterates over the auth context. */ GRPCAPI grpc_auth_property_iterator grpc_auth_context_property_iterator(const grpc_auth_context *ctx); /* Gets the peer identity. Returns an empty iterator (first _next will return NULL) if the peer is not authenticated. */ GRPCAPI grpc_auth_property_iterator grpc_auth_context_peer_identity(const grpc_auth_context *ctx); /* Finds a property in the context. May return an empty iterator (first _next will return NULL) if no property with this name was found in the context. */ GRPCAPI grpc_auth_property_iterator grpc_auth_context_find_properties_by_name( const grpc_auth_context *ctx, const char *name); /* Gets the name of the property that indicates the peer identity. Will return NULL if the peer is not authenticated. */ GRPCAPI const char *grpc_auth_context_peer_identity_property_name( const grpc_auth_context *ctx); /* Returns 1 if the peer is authenticated, 0 otherwise. */ GRPCAPI int grpc_auth_context_peer_is_authenticated( const grpc_auth_context *ctx); /* Gets the auth context from the call. Caller needs to call grpc_auth_context_release on the returned context. */ GRPCAPI grpc_auth_context *grpc_call_auth_context(grpc_call *call); /* Releases the auth context returned from grpc_call_auth_context. */ GRPCAPI void grpc_auth_context_release(grpc_auth_context *context); /* -- The following auth context methods should only be called by a server metadata processor to set properties extracted from auth metadata. -- */ /* Add a property. */ GRPCAPI void grpc_auth_context_add_property(grpc_auth_context *ctx, const char *name, const char *value, size_t value_length); /* Add a C string property. */ GRPCAPI void grpc_auth_context_add_cstring_property(grpc_auth_context *ctx, const char *name, const char *value); /* Sets the property name. Returns 1 if successful or 0 in case of failure (which means that no property with this name exists). */ GRPCAPI int grpc_auth_context_set_peer_identity_property_name( grpc_auth_context *ctx, const char *name); /* --- grpc_channel_credentials object. --- A channel credentials object represents a way to authenticate a client on a channel. */ typedef struct grpc_channel_credentials grpc_channel_credentials; /* Releases a channel credentials object. The creator of the credentials object is responsible for its release. */ GRPCAPI void grpc_channel_credentials_release(grpc_channel_credentials *creds); /* Creates default credentials to connect to a google gRPC service. WARNING: Do NOT use this credentials to connect to a non-google service as this could result in an oauth2 token leak. */ GRPCAPI grpc_channel_credentials *grpc_google_default_credentials_create(void); /* Callback for getting the SSL roots override from the application. In case of success, *pem_roots_certs must be set to a NULL terminated string containing the list of PEM encoded root certificates. The ownership is passed to the core and freed (laster by the core) with gpr_free. If this function fails and GRPC_DEFAULT_SSL_ROOTS_FILE_PATH environment is set to a valid path, it will override the roots specified this func */ typedef grpc_ssl_roots_override_result (*grpc_ssl_roots_override_callback)( char **pem_root_certs); /* Setup a callback to override the default TLS/SSL roots. This function is not thread-safe and must be called at initialization time before any ssl credentials are created to have the desired side effect. If GRPC_DEFAULT_SSL_ROOTS_FILE_PATH environment is set to a valid path, the callback will not be called. */ GRPCAPI void grpc_set_ssl_roots_override_callback( grpc_ssl_roots_override_callback cb); /* Object that holds a private key / certificate chain pair in PEM format. */ typedef struct { /* private_key is the NULL-terminated string containing the PEM encoding of the client's private key. */ const char *private_key; /* cert_chain is the NULL-terminated string containing the PEM encoding of the client's certificate chain. */ const char *cert_chain; } grpc_ssl_pem_key_cert_pair; /* Creates an SSL credentials object. - pem_roots_cert is the NULL-terminated string containing the PEM encoding of the server root certificates. If this parameter is NULL, the implementation will first try to dereference the file pointed by the GRPC_DEFAULT_SSL_ROOTS_FILE_PATH environment variable, and if that fails, try to get the roots set by grpc_override_ssl_default_roots. Eventually, if all these fail, it will try to get the roots from a well-known place on disk (in the grpc install directory). - pem_key_cert_pair is a pointer on the object containing client's private key and certificate chain. This parameter can be NULL if the client does not have such a key/cert pair. */ GRPCAPI grpc_channel_credentials *grpc_ssl_credentials_create( const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair, void *reserved); /* --- grpc_call_credentials object. A call credentials object represents a way to authenticate on a particular call. These credentials can be composed with a channel credentials object so that they are sent with every call on this channel. */ typedef struct grpc_call_credentials grpc_call_credentials; /* Releases a call credentials object. The creator of the credentials object is responsible for its release. */ GRPCAPI void grpc_call_credentials_release(grpc_call_credentials *creds); /* Creates a composite channel credentials object. */ GRPCAPI grpc_channel_credentials *grpc_composite_channel_credentials_create( grpc_channel_credentials *channel_creds, grpc_call_credentials *call_creds, void *reserved); /* Creates a composite call credentials object. */ GRPCAPI grpc_call_credentials *grpc_composite_call_credentials_create( grpc_call_credentials *creds1, grpc_call_credentials *creds2, void *reserved); /* Creates a compute engine credentials object for connecting to Google. WARNING: Do NOT use this credentials to connect to a non-google service as this could result in an oauth2 token leak. */ GRPCAPI grpc_call_credentials *grpc_google_compute_engine_credentials_create( void *reserved); GRPCAPI gpr_timespec grpc_max_auth_token_lifetime(); /* Creates a JWT credentials object. May return NULL if the input is invalid. - json_key is the JSON key string containing the client's private key. - token_lifetime is the lifetime of each Json Web Token (JWT) created with this credentials. It should not exceed grpc_max_auth_token_lifetime or will be cropped to this value. */ GRPCAPI grpc_call_credentials * grpc_service_account_jwt_access_credentials_create(const char *json_key, gpr_timespec token_lifetime, void *reserved); /* Creates an Oauth2 Refresh Token credentials object for connecting to Google. May return NULL if the input is invalid. WARNING: Do NOT use this credentials to connect to a non-google service as this could result in an oauth2 token leak. - json_refresh_token is the JSON string containing the refresh token itself along with a client_id and client_secret. */ GRPCAPI grpc_call_credentials *grpc_google_refresh_token_credentials_create( const char *json_refresh_token, void *reserved); /* Creates an Oauth2 Access Token credentials with an access token that was aquired by an out of band mechanism. */ GRPCAPI grpc_call_credentials *grpc_access_token_credentials_create( const char *access_token, void *reserved); /* Creates an IAM credentials object for connecting to Google. */ GRPCAPI grpc_call_credentials *grpc_google_iam_credentials_create( const char *authorization_token, const char *authority_selector, void *reserved); /* Callback function to be called by the metadata credentials plugin implementation when the metadata is ready. - user_data is the opaque pointer that was passed in the get_metadata method of the grpc_metadata_credentials_plugin (see below). - creds_md is an array of credentials metadata produced by the plugin. It may be set to NULL in case of an error. - num_creds_md is the number of items in the creds_md array. - status must be GRPC_STATUS_OK in case of success or another specific error code otherwise. - error_details contains details about the error if any. In case of success it should be NULL and will be otherwise ignored. */ typedef void (*grpc_credentials_plugin_metadata_cb)( void *user_data, const grpc_metadata *creds_md, size_t num_creds_md, grpc_status_code status, const char *error_details); /* Context that can be used by metadata credentials plugin in order to create auth related metadata. */ typedef struct { /* The fully qualifed service url. */ const char *service_url; /* The method name of the RPC being called (not fully qualified). The fully qualified method name can be built from the service_url: full_qualified_method_name = ctx->service_url + '/' + ctx->method_name. */ const char *method_name; /* The auth_context of the channel which gives the server's identity. */ const grpc_auth_context *channel_auth_context; /* Reserved for future use. */ void *reserved; } grpc_auth_metadata_context; /* grpc_metadata_credentials plugin is an API user provided structure used to create grpc_credentials objects that can be set on a channel (composed) or a call. See grpc_credentials_metadata_create_from_plugin below. The grpc client stack will call the get_metadata method of the plugin for every call in scope for the credentials created from it. */ typedef struct { /* The implementation of this method has to be non-blocking. - context is the information that can be used by the plugin to create auth metadata. - cb is the callback that needs to be called when the metadata is ready. - user_data needs to be passed as the first parameter of the callback. */ void (*get_metadata)(void *state, grpc_auth_metadata_context context, grpc_credentials_plugin_metadata_cb cb, void *user_data); /* Destroys the plugin state. */ void (*destroy)(void *state); /* State that will be set as the first parameter of the methods above. */ void *state; /* Type of credentials that this plugin is implementing. */ const char *type; } grpc_metadata_credentials_plugin; /* Creates a credentials object from a plugin. */ GRPCAPI grpc_call_credentials *grpc_metadata_credentials_create_from_plugin( grpc_metadata_credentials_plugin plugin, void *reserved); /* --- Secure channel creation. --- */ /* Creates a secure channel using the passed-in credentials. */ GRPCAPI grpc_channel *grpc_secure_channel_create( grpc_channel_credentials *creds, const char *target, const grpc_channel_args *args, void *reserved); /* --- grpc_server_credentials object. --- A server credentials object represents a way to authenticate a server. */ typedef struct grpc_server_credentials grpc_server_credentials; /* Releases a server_credentials object. The creator of the server_credentials object is responsible for its release. */ GRPCAPI void grpc_server_credentials_release(grpc_server_credentials *creds); /* Deprecated in favor of grpc_ssl_server_credentials_create_ex. Creates an SSL server_credentials object. - pem_roots_cert is the NULL-terminated string containing the PEM encoding of the client root certificates. This parameter may be NULL if the server does not want the client to be authenticated with SSL. - pem_key_cert_pairs is an array private key / certificate chains of the server. This parameter cannot be NULL. - num_key_cert_pairs indicates the number of items in the private_key_files and cert_chain_files parameters. It should be at least 1. - force_client_auth, if set to non-zero will force the client to authenticate with an SSL cert. Note that this option is ignored if pem_root_certs is NULL. */ GRPCAPI grpc_server_credentials *grpc_ssl_server_credentials_create( const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, size_t num_key_cert_pairs, int force_client_auth, void *reserved); /* Same as grpc_ssl_server_credentials_create method except uses grpc_ssl_client_certificate_request_type enum to support more ways to authenticate client cerificates.*/ GRPCAPI grpc_server_credentials *grpc_ssl_server_credentials_create_ex( const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, size_t num_key_cert_pairs, grpc_ssl_client_certificate_request_type client_certificate_request, void *reserved); /* --- Server-side secure ports. --- */ /* Add a HTTP2 over an encrypted link over tcp listener. Returns bound port number on success, 0 on failure. REQUIRES: server not started */ GRPCAPI int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, grpc_server_credentials *creds); /* --- Call specific credentials. --- */ /* Sets a credentials to a call. Can only be called on the client side before grpc_call_start_batch. */ GRPCAPI grpc_call_error grpc_call_set_credentials(grpc_call *call, grpc_call_credentials *creds); /* --- Auth Metadata Processing --- */ /* Callback function that is called when the metadata processing is done. - Consumed metadata will be removed from the set of metadata available on the call. consumed_md may be NULL if no metadata has been consumed. - Response metadata will be set on the response. response_md may be NULL. - status is GRPC_STATUS_OK for success or a specific status for an error. Common error status for auth metadata processing is either GRPC_STATUS_UNAUTHENTICATED in case of an authentication failure or GRPC_STATUS PERMISSION_DENIED in case of an authorization failure. - error_details gives details about the error. May be NULL. */ typedef void (*grpc_process_auth_metadata_done_cb)( void *user_data, const grpc_metadata *consumed_md, size_t num_consumed_md, const grpc_metadata *response_md, size_t num_response_md, grpc_status_code status, const char *error_details); /* Pluggable server-side metadata processor object. */ typedef struct { /* The context object is read/write: it contains the properties of the channel peer and it is the job of the process function to augment it with properties derived from the passed-in metadata. The lifetime of these objects is guaranteed until cb is invoked. */ void (*process)(void *state, grpc_auth_context *context, const grpc_metadata *md, size_t num_md, grpc_process_auth_metadata_done_cb cb, void *user_data); void (*destroy)(void *state); void *state; } grpc_auth_metadata_processor; GRPCAPI void grpc_server_credentials_set_auth_metadata_processor( grpc_server_credentials *creds, grpc_auth_metadata_processor processor); #ifdef __cplusplus } #endif #endif /* GRPC_GRPC_SECURITY_H */ grpc-1.3.2/include/grpc/grpc_security_constants.h000066400000000000000000000113151310511640000221450ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_GRPC_SECURITY_CONSTANTS_H #define GRPC_GRPC_SECURITY_CONSTANTS_H #ifdef __cplusplus extern "C" { #endif #define GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME "transport_security_type" #define GRPC_SSL_TRANSPORT_SECURITY_TYPE "ssl" #define GRPC_X509_CN_PROPERTY_NAME "x509_common_name" #define GRPC_X509_SAN_PROPERTY_NAME "x509_subject_alternative_name" #define GRPC_X509_PEM_CERT_PROPERTY_NAME "x509_pem_cert" /* Environment variable that points to the default SSL roots file. This file must be a PEM encoded file with all the roots such as the one that can be downloaded from https://pki.google.com/roots.pem. */ #define GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR \ "GRPC_DEFAULT_SSL_ROOTS_FILE_PATH" /* Environment variable that points to the google default application credentials json key or refresh token. Used in the grpc_google_default_credentials_create function. */ #define GRPC_GOOGLE_CREDENTIALS_ENV_VAR "GOOGLE_APPLICATION_CREDENTIALS" /* Results for the SSL roots override callback. */ typedef enum { GRPC_SSL_ROOTS_OVERRIDE_OK, GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY, /* Do not try fallback options. */ GRPC_SSL_ROOTS_OVERRIDE_FAIL } grpc_ssl_roots_override_result; typedef enum { /* Server does not request client certificate. A client can present a self signed or signed certificates if it wishes to do so and they would be accepted. */ GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, /* Server requests client certificate but does not enforce that the client presents a certificate. If the client presents a certificate, the client authentication is left to the application based on the metadata like certificate etc. The key cert pair should still be valid for the SSL connection to be established. */ GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY, /* Server requests client certificate but does not enforce that the client presents a certificate. If the client presents a certificate, the client authentication is done by grpc framework (The client needs to either present a signed cert or skip no certificate for a successful connection). The key cert pair should still be valid for the SSL connection to be established. */ GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY, /* Server requests client certificate but enforces that the client presents a certificate. If the client presents a certificate, the client authentication is left to the application based on the metadata like certificate etc. The key cert pair should still be valid for the SSL connection to be established. */ GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY, /* Server requests client certificate but enforces that the client presents a certificate. The cerificate presented by the client is verified by grpc framework (The client needs to present signed certs for a successful connection). The key cert pair should still be valid for the SSL connection to be established. */ GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY } grpc_ssl_client_certificate_request_type; #ifdef __cplusplus } #endif #endif /* GRPC_GRPC_SECURITY_CONSTANTS_H */ grpc-1.3.2/include/grpc/impl/000077500000000000000000000000001310511640000157565ustar00rootroot00000000000000grpc-1.3.2/include/grpc/impl/codegen/000077500000000000000000000000001310511640000173625ustar00rootroot00000000000000grpc-1.3.2/include/grpc/impl/codegen/atm.h000066400000000000000000000101231310511640000203110ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_IMPL_CODEGEN_ATM_H #define GRPC_IMPL_CODEGEN_ATM_H /* This interface provides atomic operations and barriers. It is internal to gpr support code and should not be used outside it. If an operation with acquire semantics precedes another memory access by the same thread, the operation will precede that other access as seen by other threads. If an operation with release semantics follows another memory access by the same thread, the operation will follow that other access as seen by other threads. Routines with "acq" or "full" in the name have acquire semantics. Routines with "rel" or "full" in the name have release semantics. Routines with "no_barrier" in the name have neither acquire not release semantics. The routines may be implemented as macros. // Atomic operations act on an intergral_type gpr_atm that is guaranteed to // be the same size as a pointer. typedef intptr_t gpr_atm; // A memory barrier, providing both acquire and release semantics, but not // otherwise acting on memory. void gpr_atm_full_barrier(void); // Atomically return *p, with acquire semantics. gpr_atm gpr_atm_acq_load(gpr_atm *p); // Atomically set *p = value, with release semantics. void gpr_atm_rel_store(gpr_atm *p, gpr_atm value); // Atomically add delta to *p, and return the old value of *p, with // the barriers specified. gpr_atm gpr_atm_no_barrier_fetch_add(gpr_atm *p, gpr_atm delta); gpr_atm gpr_atm_full_fetch_add(gpr_atm *p, gpr_atm delta); // Atomically, if *p==o, set *p=n and return non-zero otherwise return 0, // with the barriers specified if the operation succeeds. int gpr_atm_no_barrier_cas(gpr_atm *p, gpr_atm o, gpr_atm n); int gpr_atm_acq_cas(gpr_atm *p, gpr_atm o, gpr_atm n); int gpr_atm_rel_cas(gpr_atm *p, gpr_atm o, gpr_atm n); // Atomically, set *p=n and return the old value of *p gpr_atm gpr_atm_full_xchg(gpr_atm *p, gpr_atm n); */ #include #if defined(GPR_GCC_ATOMIC) #include #elif defined(GPR_GCC_SYNC) #include #elif defined(GPR_WINDOWS_ATOMIC) #include #else #error could not determine platform for atm #endif /** Adds \a delta to \a *value, clamping the result to the range specified by \a min and \a max. Returns the new value. */ gpr_atm gpr_atm_no_barrier_clamped_add(gpr_atm *value, gpr_atm delta, gpr_atm min, gpr_atm max); #endif /* GRPC_IMPL_CODEGEN_ATM_H */ grpc-1.3.2/include/grpc/impl/codegen/atm_gcc_atomic.h000066400000000000000000000076241310511640000224750ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_IMPL_CODEGEN_ATM_GCC_ATOMIC_H #define GRPC_IMPL_CODEGEN_ATM_GCC_ATOMIC_H /* atm_platform.h for gcc and gcc-like compilers with the __atomic_* interface. */ #include typedef intptr_t gpr_atm; #define GPR_ATM_MAX INTPTR_MAX #ifdef GPR_LOW_LEVEL_COUNTERS extern gpr_atm gpr_counter_atm_cas; extern gpr_atm gpr_counter_atm_add; #define GPR_ATM_INC_COUNTER(counter) \ __atomic_fetch_add(&counter, 1, __ATOMIC_RELAXED) #define GPR_ATM_INC_CAS_THEN(blah) \ (GPR_ATM_INC_COUNTER(gpr_counter_atm_cas), blah) #define GPR_ATM_INC_ADD_THEN(blah) \ (GPR_ATM_INC_COUNTER(gpr_counter_atm_add), blah) #else #define GPR_ATM_INC_CAS_THEN(blah) blah #define GPR_ATM_INC_ADD_THEN(blah) blah #endif #define gpr_atm_full_barrier() (__atomic_thread_fence(__ATOMIC_SEQ_CST)) #define gpr_atm_acq_load(p) (__atomic_load_n((p), __ATOMIC_ACQUIRE)) #define gpr_atm_no_barrier_load(p) (__atomic_load_n((p), __ATOMIC_RELAXED)) #define gpr_atm_rel_store(p, value) \ (__atomic_store_n((p), (intptr_t)(value), __ATOMIC_RELEASE)) #define gpr_atm_no_barrier_store(p, value) \ (__atomic_store_n((p), (intptr_t)(value), __ATOMIC_RELAXED)) #define gpr_atm_no_barrier_fetch_add(p, delta) \ GPR_ATM_INC_ADD_THEN( \ __atomic_fetch_add((p), (intptr_t)(delta), __ATOMIC_RELAXED)) #define gpr_atm_full_fetch_add(p, delta) \ GPR_ATM_INC_ADD_THEN( \ __atomic_fetch_add((p), (intptr_t)(delta), __ATOMIC_ACQ_REL)) static __inline int gpr_atm_no_barrier_cas(gpr_atm *p, gpr_atm o, gpr_atm n) { return GPR_ATM_INC_CAS_THEN(__atomic_compare_exchange_n( p, &o, n, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED)); } static __inline int gpr_atm_acq_cas(gpr_atm *p, gpr_atm o, gpr_atm n) { return GPR_ATM_INC_CAS_THEN(__atomic_compare_exchange_n( p, &o, n, 0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)); } static __inline int gpr_atm_rel_cas(gpr_atm *p, gpr_atm o, gpr_atm n) { return GPR_ATM_INC_CAS_THEN(__atomic_compare_exchange_n( p, &o, n, 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED)); } static __inline int gpr_atm_full_cas(gpr_atm *p, gpr_atm o, gpr_atm n) { return GPR_ATM_INC_CAS_THEN(__atomic_compare_exchange_n( p, &o, n, 0, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED)); } #define gpr_atm_full_xchg(p, n) \ GPR_ATM_INC_CAS_THEN(__atomic_exchange_n((p), (n), __ATOMIC_ACQ_REL)) #endif /* GRPC_IMPL_CODEGEN_ATM_GCC_ATOMIC_H */ grpc-1.3.2/include/grpc/impl/codegen/atm_gcc_sync.h000066400000000000000000000065631310511640000221760ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_IMPL_CODEGEN_ATM_GCC_SYNC_H #define GRPC_IMPL_CODEGEN_ATM_GCC_SYNC_H /* variant of atm_platform.h for gcc and gcc-like compiers with __sync_* interface */ #include typedef intptr_t gpr_atm; #define GPR_ATM_MAX INTPTR_MAX #define GPR_ATM_COMPILE_BARRIER_() __asm__ __volatile__("" : : : "memory") #if defined(__i386) || defined(__x86_64__) /* All loads are acquire loads and all stores are release stores. */ #define GPR_ATM_LS_BARRIER_() GPR_ATM_COMPILE_BARRIER_() #else #define GPR_ATM_LS_BARRIER_() gpr_atm_full_barrier() #endif #define gpr_atm_full_barrier() (__sync_synchronize()) static __inline gpr_atm gpr_atm_acq_load(const gpr_atm *p) { gpr_atm value = *p; GPR_ATM_LS_BARRIER_(); return value; } static __inline gpr_atm gpr_atm_no_barrier_load(const gpr_atm *p) { gpr_atm value = *p; GPR_ATM_COMPILE_BARRIER_(); return value; } static __inline void gpr_atm_rel_store(gpr_atm *p, gpr_atm value) { GPR_ATM_LS_BARRIER_(); *p = value; } static __inline void gpr_atm_no_barrier_store(gpr_atm *p, gpr_atm value) { GPR_ATM_COMPILE_BARRIER_(); *p = value; } #undef GPR_ATM_LS_BARRIER_ #undef GPR_ATM_COMPILE_BARRIER_ #define gpr_atm_no_barrier_fetch_add(p, delta) \ gpr_atm_full_fetch_add((p), (delta)) #define gpr_atm_full_fetch_add(p, delta) (__sync_fetch_and_add((p), (delta))) #define gpr_atm_no_barrier_cas(p, o, n) gpr_atm_acq_cas((p), (o), (n)) #define gpr_atm_acq_cas(p, o, n) (__sync_bool_compare_and_swap((p), (o), (n))) #define gpr_atm_rel_cas(p, o, n) gpr_atm_acq_cas((p), (o), (n)) #define gpr_atm_full_cas(p, o, n) gpr_atm_acq_cas((p), (o), (n)) static __inline gpr_atm gpr_atm_full_xchg(gpr_atm *p, gpr_atm n) { gpr_atm cur; do { cur = gpr_atm_acq_load(p); } while (!gpr_atm_rel_cas(p, cur, n)); return cur; } #endif /* GRPC_IMPL_CODEGEN_ATM_GCC_SYNC_H */ grpc-1.3.2/include/grpc/impl/codegen/atm_windows.h000066400000000000000000000120731310511640000220710ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_IMPL_CODEGEN_ATM_WINDOWS_H #define GRPC_IMPL_CODEGEN_ATM_WINDOWS_H /* Win32 variant of atm_platform.h */ #include typedef intptr_t gpr_atm; #define GPR_ATM_MAX INTPTR_MAX #define gpr_atm_full_barrier MemoryBarrier static __inline gpr_atm gpr_atm_acq_load(const gpr_atm *p) { gpr_atm result = *p; gpr_atm_full_barrier(); return result; } static __inline gpr_atm gpr_atm_no_barrier_load(const gpr_atm *p) { /* TODO(dklempner): Can we implement something better here? */ return gpr_atm_acq_load(p); } static __inline void gpr_atm_rel_store(gpr_atm *p, gpr_atm value) { gpr_atm_full_barrier(); *p = value; } static __inline void gpr_atm_no_barrier_store(gpr_atm *p, gpr_atm value) { /* TODO(ctiller): Can we implement something better here? */ gpr_atm_rel_store(p, value); } static __inline int gpr_atm_no_barrier_cas(gpr_atm *p, gpr_atm o, gpr_atm n) { /* InterlockedCompareExchangePointerNoFence() not available on vista or windows7 */ #ifdef GPR_ARCH_64 return o == (gpr_atm)InterlockedCompareExchangeAcquire64( (volatile LONGLONG *)p, (LONGLONG)n, (LONGLONG)o); #else return o == (gpr_atm)InterlockedCompareExchangeAcquire((volatile LONG *)p, (LONG)n, (LONG)o); #endif } static __inline int gpr_atm_acq_cas(gpr_atm *p, gpr_atm o, gpr_atm n) { #ifdef GPR_ARCH_64 return o == (gpr_atm)InterlockedCompareExchangeAcquire64( (volatile LONGLONG *)p, (LONGLONG)n, (LONGLONG)o); #else return o == (gpr_atm)InterlockedCompareExchangeAcquire((volatile LONG *)p, (LONG)n, (LONG)o); #endif } static __inline int gpr_atm_rel_cas(gpr_atm *p, gpr_atm o, gpr_atm n) { #ifdef GPR_ARCH_64 return o == (gpr_atm)InterlockedCompareExchangeRelease64( (volatile LONGLONG *)p, (LONGLONG)n, (LONGLONG)o); #else return o == (gpr_atm)InterlockedCompareExchangeRelease((volatile LONG *)p, (LONG)n, (LONG)o); #endif } static __inline int gpr_atm_full_cas(gpr_atm *p, gpr_atm o, gpr_atm n) { #ifdef GPR_ARCH_64 return o == (gpr_atm)InterlockedCompareExchange64((volatile LONGLONG *)p, (LONGLONG)n, (LONGLONG)o); #else return o == (gpr_atm)InterlockedCompareExchange((volatile LONG *)p, (LONG)n, (LONG)o); #endif } static __inline gpr_atm gpr_atm_no_barrier_fetch_add(gpr_atm *p, gpr_atm delta) { /* Use the CAS operation to get pointer-sized fetch and add */ gpr_atm old; do { old = *p; } while (!gpr_atm_no_barrier_cas(p, old, old + delta)); return old; } static __inline gpr_atm gpr_atm_full_fetch_add(gpr_atm *p, gpr_atm delta) { /* Use a CAS operation to get pointer-sized fetch and add */ gpr_atm old; #ifdef GPR_ARCH_64 do { old = *p; } while (old != (gpr_atm)InterlockedCompareExchange64((volatile LONGLONG *)p, (LONGLONG)old + delta, (LONGLONG)old)); #else do { old = *p; } while (old != (gpr_atm)InterlockedCompareExchange( (volatile LONG *)p, (LONG)old + delta, (LONG)old)); #endif return old; } static __inline gpr_atm gpr_atm_full_xchg(gpr_atm *p, gpr_atm n) { return (gpr_atm)InterlockedExchangePointer((PVOID *)p, (PVOID)n); } #endif /* GRPC_IMPL_CODEGEN_ATM_WINDOWS_H */ grpc-1.3.2/include/grpc/impl/codegen/byte_buffer_reader.h000066400000000000000000000040671310511640000233600ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_IMPL_CODEGEN_BYTE_BUFFER_READER_H #define GRPC_IMPL_CODEGEN_BYTE_BUFFER_READER_H #ifdef __cplusplus extern "C" { #endif struct grpc_byte_buffer; struct grpc_byte_buffer_reader { struct grpc_byte_buffer *buffer_in; struct grpc_byte_buffer *buffer_out; /* Different current objects correspond to different types of byte buffers */ union { /* Index into a slice buffer's array of slices */ unsigned index; } current; }; #ifdef __cplusplus } #endif #endif /* GRPC_IMPL_CODEGEN_BYTE_BUFFER_READER_H */ grpc-1.3.2/include/grpc/impl/codegen/compression_types.h000066400000000000000000000112041310511640000233160ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_IMPL_CODEGEN_COMPRESSION_TYPES_H #define GRPC_IMPL_CODEGEN_COMPRESSION_TYPES_H #include #include #ifdef __cplusplus extern "C" { #endif /** To be used as initial metadata key for the request of a concrete compression * algorithm */ #define GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY \ "grpc-internal-encoding-request" /** To be used in channel arguments. * * \addtogroup grpc_arg_keys * \{ */ /** Default compression algorithm for the channel. * Its value is an int from the \a grpc_compression_algorithm enum. */ #define GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM \ "grpc.default_compression_algorithm" /** Default compression level for the channel. * Its value is an int from the \a grpc_compression_level enum. */ #define GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL "grpc.default_compression_level" /** Compression algorithms supported by the channel. * Its value is a bitset (an int). Bits correspond to algorithms in \a * grpc_compression_algorithm. For example, its LSB corresponds to * GRPC_COMPRESS_NONE, the next bit to GRPC_COMPRESS_DEFLATE, etc. * Unset bits disable support for the algorithm. By default all algorithms are * supported. It's not possible to disable GRPC_COMPRESS_NONE (the attempt will * be ignored). */ #define GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET \ "grpc.compression_enabled_algorithms_bitset" /** \} */ /* The various compression algorithms supported by gRPC */ typedef enum { GRPC_COMPRESS_NONE = 0, GRPC_COMPRESS_DEFLATE, GRPC_COMPRESS_GZIP, /* TODO(ctiller): snappy */ GRPC_COMPRESS_ALGORITHMS_COUNT } grpc_compression_algorithm; /** Compression levels allow a party with knowledge of its peer's accepted * encodings to request compression in an abstract way. The level-algorithm * mapping is performed internally and depends on the peer's supported * compression algorithms. */ typedef enum { GRPC_COMPRESS_LEVEL_NONE = 0, GRPC_COMPRESS_LEVEL_LOW, GRPC_COMPRESS_LEVEL_MED, GRPC_COMPRESS_LEVEL_HIGH, GRPC_COMPRESS_LEVEL_COUNT } grpc_compression_level; typedef struct grpc_compression_options { /** All algs are enabled by default. This option corresponds to the channel * argument key behind \a GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET */ uint32_t enabled_algorithms_bitset; /** The default channel compression level. It'll be used in the absence of * call specific settings. This option corresponds to the channel argument key * behind \a GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL. If present, takes * precedence over \a default_algorithm. * TODO(dgq): currently only available for server channels. */ struct { bool is_set; grpc_compression_level level; } default_level; /** The default channel compression algorithm. It'll be used in the absence of * call specific settings. This option corresponds to the channel argument key * behind \a GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM. */ struct { bool is_set; grpc_compression_algorithm algorithm; } default_algorithm; } grpc_compression_options; #ifdef __cplusplus } #endif #endif /* GRPC_IMPL_CODEGEN_COMPRESSION_TYPES_H */ grpc-1.3.2/include/grpc/impl/codegen/connectivity_state.h000066400000000000000000000043501310511640000234530ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_IMPL_CODEGEN_CONNECTIVITY_STATE_H #define GRPC_IMPL_CODEGEN_CONNECTIVITY_STATE_H #ifdef __cplusplus extern "C" { #endif /** Connectivity state of a channel. */ typedef enum { /** channel has just been initialized */ GRPC_CHANNEL_INIT = -1, /** channel is idle */ GRPC_CHANNEL_IDLE, /** channel is connecting */ GRPC_CHANNEL_CONNECTING, /** channel is ready for work */ GRPC_CHANNEL_READY, /** channel has seen a failure but expects to recover */ GRPC_CHANNEL_TRANSIENT_FAILURE, /** channel has seen a failure that it cannot recover from */ GRPC_CHANNEL_SHUTDOWN } grpc_connectivity_state; #ifdef __cplusplus } #endif #endif /* GRPC_IMPL_CODEGEN_CONNECTIVITY_STATE_H */ grpc-1.3.2/include/grpc/impl/codegen/exec_ctx_fwd.h000066400000000000000000000034171310511640000222020ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_IMPL_CODEGEN_EXEC_CTX_FWD_H #define GRPC_IMPL_CODEGEN_EXEC_CTX_FWD_H /* forward declaration for exec_ctx.h */ struct grpc_exec_ctx; typedef struct grpc_exec_ctx grpc_exec_ctx; #endif /* GRPC_IMPL_CODEGEN_EXEC_CTX_FWD_H */ grpc-1.3.2/include/grpc/impl/codegen/gpr_slice.h000066400000000000000000000074401310511640000215070ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_IMPL_CODEGEN_GPR_SLICE_H #define GRPC_IMPL_CODEGEN_GPR_SLICE_H /* WARNING: Please do not use this header. This was added as a temporary measure * to not break some of the external projects that depend on gpr_slice_* * functions. We are actively working on moving all the gpr_slice_* references * to grpc_slice_* and this file will be removed * */ /* TODO (sreek) - Allowed by default but will be very soon turned off */ #define GRPC_ALLOW_GPR_SLICE_FUNCTIONS 1 #ifdef GRPC_ALLOW_GPR_SLICE_FUNCTIONS #define gpr_slice_refcount grpc_slice_refcount #define gpr_slice grpc_slice #define gpr_slice_buffer grpc_slice_buffer #define gpr_slice_ref grpc_slice_ref #define gpr_slice_unref grpc_slice_unref #define gpr_slice_new grpc_slice_new #define gpr_slice_new_with_user_data grpc_slice_new_with_user_data #define gpr_slice_new_with_len grpc_slice_new_with_len #define gpr_slice_malloc grpc_slice_malloc #define gpr_slice_from_copied_string grpc_slice_from_copied_string #define gpr_slice_from_copied_buffer grpc_slice_from_copied_buffer #define gpr_slice_from_static_string grpc_slice_from_static_string #define gpr_slice_sub grpc_slice_sub #define gpr_slice_sub_no_ref grpc_slice_sub_no_ref #define gpr_slice_split_tail grpc_slice_split_tail #define gpr_slice_split_head grpc_slice_split_head #define gpr_slice_cmp grpc_slice_cmp #define gpr_slice_str_cmp grpc_slice_str_cmp #define gpr_slice_buffer grpc_slice_buffer #define gpr_slice_buffer_init grpc_slice_buffer_init #define gpr_slice_buffer_destroy grpc_slice_buffer_destroy #define gpr_slice_buffer_add grpc_slice_buffer_add #define gpr_slice_buffer_add_indexed grpc_slice_buffer_add_indexed #define gpr_slice_buffer_addn grpc_slice_buffer_addn #define gpr_slice_buffer_tiny_add grpc_slice_buffer_tiny_add #define gpr_slice_buffer_pop grpc_slice_buffer_pop #define gpr_slice_buffer_reset_and_unref grpc_slice_buffer_reset_and_unref #define gpr_slice_buffer_swap grpc_slice_buffer_swap #define gpr_slice_buffer_move_into grpc_slice_buffer_move_into #define gpr_slice_buffer_trim_end grpc_slice_buffer_trim_end #define gpr_slice_buffer_move_first grpc_slice_buffer_move_first #define gpr_slice_buffer_take_first grpc_slice_buffer_take_first #endif /* GRPC_ALLOW_GPR_SLICE_FUNCTIONS */ #endif /* GRPC_IMPL_CODEGEN_GPR_SLICE_H */ grpc-1.3.2/include/grpc/impl/codegen/gpr_types.h000066400000000000000000000053071310511640000215540ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_IMPL_CODEGEN_GPR_TYPES_H #define GRPC_IMPL_CODEGEN_GPR_TYPES_H #include #include #include #ifdef __cplusplus extern "C" { #endif /* The clocks we support. */ typedef enum { /* Monotonic clock. Epoch undefined. Always moves forwards. */ GPR_CLOCK_MONOTONIC = 0, /* Realtime clock. May jump forwards or backwards. Settable by the system administrator. Has its epoch at 0:00:00 UTC 1 Jan 1970. */ GPR_CLOCK_REALTIME, /* CPU cycle time obtained by rdtsc instruction on x86 platforms. Epoch undefined. Degrades to GPR_CLOCK_REALTIME on other platforms. */ GPR_CLOCK_PRECISE, /* Unmeasurable clock type: no base, created by taking the difference between two times */ GPR_TIMESPAN } gpr_clock_type; /* Analogous to struct timespec. On some machines, absolute times may be in * local time. */ typedef struct gpr_timespec { int64_t tv_sec; int32_t tv_nsec; /** Against which clock was this time measured? (or GPR_TIMESPAN if this is a relative time meaure) */ gpr_clock_type clock_type; } gpr_timespec; #ifdef __cplusplus } #endif #endif /* GRPC_IMPL_CODEGEN_GPR_TYPES_H */ grpc-1.3.2/include/grpc/impl/codegen/grpc_types.h000066400000000000000000000555541310511640000217300ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_IMPL_CODEGEN_GRPC_TYPES_H #define GRPC_IMPL_CODEGEN_GRPC_TYPES_H #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif typedef enum { GRPC_BB_RAW /* Future types may include GRPC_BB_PROTOBUF, etc. */ } grpc_byte_buffer_type; typedef struct grpc_byte_buffer { void *reserved; grpc_byte_buffer_type type; union { struct { void *reserved[8]; } reserved; struct { grpc_compression_algorithm compression; grpc_slice_buffer slice_buffer; } raw; } data; } grpc_byte_buffer; /** Completion Queues enable notification of the completion of asynchronous actions. */ typedef struct grpc_completion_queue grpc_completion_queue; /** An alarm associated with a completion queue. */ typedef struct grpc_alarm grpc_alarm; /** The Channel interface allows creation of Call objects. */ typedef struct grpc_channel grpc_channel; /** A server listens to some port and responds to request calls */ typedef struct grpc_server grpc_server; /** A Call represents an RPC. When created, it is in a configuration state allowing properties to be set until it is invoked. After invoke, the Call can have messages written to it and read from it. */ typedef struct grpc_call grpc_call; /** The Socket Mutator interface allows changes on socket options */ typedef struct grpc_socket_mutator grpc_socket_mutator; /** The Socket Factory interface creates and binds sockets */ typedef struct grpc_socket_factory grpc_socket_factory; /** Type specifier for grpc_arg */ typedef enum { GRPC_ARG_STRING, GRPC_ARG_INTEGER, GRPC_ARG_POINTER } grpc_arg_type; typedef struct grpc_arg_pointer_vtable { void *(*copy)(void *p); void (*destroy)(grpc_exec_ctx *exec_ctx, void *p); int (*cmp)(void *p, void *q); } grpc_arg_pointer_vtable; /** A single argument... each argument has a key and a value A note on naming keys: Keys are namespaced into groups, usually grouped by library, and are keys for module XYZ are named XYZ.key1, XYZ.key2, etc. Module names must be restricted to the regex [A-Za-z][_A-Za-z0-9]{,15}. Key names must be restricted to the regex [A-Za-z][_A-Za-z0-9]{,47}. GRPC core library keys are prefixed by grpc. Library authors are strongly encouraged to \#define symbolic constants for their keys so that it's possible to change them in the future. */ typedef struct { grpc_arg_type type; char *key; union { char *string; int integer; struct { void *p; const grpc_arg_pointer_vtable *vtable; } pointer; } value; } grpc_arg; /** An array of arguments that can be passed around. Used to set optional channel-level configuration. These configuration options are modelled as key-value pairs as defined by grpc_arg; keys are strings to allow easy backwards-compatible extension by arbitrary parties. All evaluation is performed at channel creation time (i.e. the values in this structure need only live through the creation invocation). See the description of the \ref grpc_arg_keys "available args" for more details. */ typedef struct { size_t num_args; grpc_arg *args; } grpc_channel_args; /** \defgroup grpc_arg_keys * Channel argument keys. * \{ */ /** If non-zero, enable census for tracing and stats collection. */ #define GRPC_ARG_ENABLE_CENSUS "grpc.census" /** If non-zero, enable load reporting. */ #define GRPC_ARG_ENABLE_LOAD_REPORTING "grpc.loadreporting" /** Request that optional features default to off (regardless of what they usually default to) - to enable tight control over what gets enabled */ #define GRPC_ARG_MINIMAL_STACK "grpc.minimal_stack" /** Maximum number of concurrent incoming streams to allow on a http2 connection. Int valued. */ #define GRPC_ARG_MAX_CONCURRENT_STREAMS "grpc.max_concurrent_streams" /** Maximum message length that the channel can receive. Int valued, bytes. -1 means unlimited. */ #define GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH "grpc.max_receive_message_length" /** \deprecated For backward compatibility. */ #define GRPC_ARG_MAX_MESSAGE_LENGTH GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH /** Maximum message length that the channel can send. Int valued, bytes. -1 means unlimited. */ #define GRPC_ARG_MAX_SEND_MESSAGE_LENGTH "grpc.max_send_message_length" /** Maximum time that a channel may have no outstanding rpcs. Int valued, milliseconds. INT_MAX means unlimited. */ #define GRPC_ARG_MAX_CONNECTION_IDLE_MS "grpc.max_connection_idle_ms" /** Maximum time that a channel may exist. Int valued, milliseconds. INT_MAX means unlimited. */ #define GRPC_ARG_MAX_CONNECTION_AGE_MS "grpc.max_connection_age_ms" /** Grace period after the chennel reaches its max age. Int valued, milliseconds. INT_MAX means unlimited. */ #define GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS "grpc.max_connection_age_grace_ms" /** Initial sequence number for http2 transports. Int valued. */ #define GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER \ "grpc.http2.initial_sequence_number" /** Amount to read ahead on individual streams. Defaults to 64kb, larger values can help throughput on high-latency connections. NOTE: at some point we'd like to auto-tune this, and this parameter will become a no-op. Int valued, bytes. */ #define GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES "grpc.http2.lookahead_bytes" /** How much memory to use for hpack decoding. Int valued, bytes. */ #define GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER \ "grpc.http2.hpack_table_size.decoder" /** How much memory to use for hpack encoding. Int valued, bytes. */ #define GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER \ "grpc.http2.hpack_table_size.encoder" /** How big a frame are we willing to receive via HTTP2. Min 16384, max 16777215. Larger values give lower CPU usage for large messages, but more head of line blocking for small messages. */ #define GRPC_ARG_HTTP2_MAX_FRAME_SIZE "grpc.http2.max_frame_size" /** Should BDP probing be performed? */ #define GRPC_ARG_HTTP2_BDP_PROBE "grpc.http2.bdp_probe" /** Minimum time (in milliseconds) between successive ping frames being sent */ #define GRPC_ARG_HTTP2_MIN_TIME_BETWEEN_PINGS_MS \ "grpc.http2.min_time_between_pings_ms" /** How many pings can we send before needing to send a data frame or header frame? (0 indicates that an infinite number of pings can be sent without sending a data frame or header frame) */ #define GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA \ "grpc.http2.max_pings_without_data" /** How many misbehaving pings the server can bear before sending goaway and closing the transport? (0 indicates that the server can bear an infinite number of misbehaving pings) */ #define GRPC_ARG_HTTP2_MAX_PING_STRIKES "grpc.http2.max_ping_strikes" /** Minimum allowed time between two pings without sending any data frame. Int valued, seconds */ #define GRPC_ARG_HTTP2_MIN_PING_INTERVAL_WITHOUT_DATA_MS \ "grpc.http2.min_ping_interval_without_data_ms" /** How much data are we willing to queue up per stream if GRPC_WRITE_BUFFER_HINT is set? This is an upper bound */ #define GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE "grpc.http2.write_buffer_size" /** Should we allow receipt of true-binary data on http2 connections? Defaults to on (1) */ #define GRPC_ARG_HTTP2_ENABLE_TRUE_BINARY "grpc.http2.true_binary" /** After a duration of this time the client/server pings its peer to see if the transport is still alive. Int valued, milliseconds. */ #define GRPC_ARG_KEEPALIVE_TIME_MS "grpc.keepalive_time_ms" /** After waiting for a duration of this time, if the keepalive ping sender does not receive the ping ack, it will close the transport. Int valued, milliseconds. */ #define GRPC_ARG_KEEPALIVE_TIMEOUT_MS "grpc.keepalive_timeout_ms" /** Is it permissible to send keepalive pings without any outstanding streams. Int valued, 0(false)/1(true). */ #define GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS \ "grpc.keepalive_permit_without_calls" /** Default authority to pass if none specified on call construction. A string. * */ #define GRPC_ARG_DEFAULT_AUTHORITY "grpc.default_authority" /** Primary user agent: goes at the start of the user-agent metadata sent on each request. A string. */ #define GRPC_ARG_PRIMARY_USER_AGENT_STRING "grpc.primary_user_agent" /** Secondary user agent: goes at the end of the user-agent metadata sent on each request. A string. */ #define GRPC_ARG_SECONDARY_USER_AGENT_STRING "grpc.secondary_user_agent" /** The maximum time between subsequent connection attempts, in ms */ #define GRPC_ARG_MAX_RECONNECT_BACKOFF_MS "grpc.max_reconnect_backoff_ms" /** The time between the first and second connection attempts, in ms */ #define GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS \ "grpc.initial_reconnect_backoff_ms" /* The caller of the secure_channel_create functions may override the target name used for SSL host name checking using this channel argument which is of type \a GRPC_ARG_STRING. This *should* be used for testing only. If this argument is not specified, the name used for SSL host name checking will be the target parameter (assuming that the secure channel is an SSL channel). If this parameter is specified and the underlying is not an SSL channel, it will just be ignored. */ #define GRPC_SSL_TARGET_NAME_OVERRIDE_ARG "grpc.ssl_target_name_override" /* Maximum metadata size, in bytes. */ #define GRPC_ARG_MAX_METADATA_SIZE "grpc.max_metadata_size" /** If non-zero, allow the use of SO_REUSEPORT if it's available (default 1) */ #define GRPC_ARG_ALLOW_REUSEPORT "grpc.so_reuseport" /** If non-zero, a pointer to a buffer pool (use grpc_resource_quota_arg_vtable to fetch an appropriate pointer arg vtable) */ #define GRPC_ARG_RESOURCE_QUOTA "grpc.resource_quota" /** If non-zero, expand wildcard addresses to a list of local addresses. */ #define GRPC_ARG_EXPAND_WILDCARD_ADDRS "grpc.expand_wildcard_addrs" /** Service config data in JSON form. Not intended for use outside of tests. */ #define GRPC_ARG_SERVICE_CONFIG "grpc.service_config" /** LB policy name. */ #define GRPC_ARG_LB_POLICY_NAME "grpc.lb_policy_name" /** The grpc_socket_mutator instance that set the socket options. A pointer. */ #define GRPC_ARG_SOCKET_MUTATOR "grpc.socket_mutator" /** The grpc_socket_factory instance to create and bind sockets. A pointer. */ #define GRPC_ARG_SOCKET_FACTORY "grpc.socket_factory" /** If non-zero, Cronet transport will coalesce packets to fewer frames when * possible. */ #define GRPC_ARG_USE_CRONET_PACKET_COALESCING \ "grpc.use_cronet_packet_coalescing" /* Channel arg (integer) setting how large a slice to try and read from the wire each time recvmsg (or equivalent) is called */ #define GRPC_ARG_TCP_READ_CHUNK_SIZE "grpc.experimental.tcp_read_chunk_size" #define GRPC_TCP_DEFAULT_READ_SLICE_SIZE 8192 #define GRPC_ARG_TCP_MIN_READ_CHUNK_SIZE \ "grpc.experimental.tcp_min_read_chunk_size" #define GRPC_ARG_TCP_MAX_READ_CHUNK_SIZE \ "grpc.experimental.tcp_max_read_chunk_size" /** \} */ /** Result of a grpc call. If the caller satisfies the prerequisites of a particular operation, the grpc_call_error returned will be GRPC_CALL_OK. Receiving any other value listed here is an indication of a bug in the caller. */ typedef enum grpc_call_error { /** everything went ok */ GRPC_CALL_OK = 0, /** something failed, we don't know what */ GRPC_CALL_ERROR, /** this method is not available on the server */ GRPC_CALL_ERROR_NOT_ON_SERVER, /** this method is not available on the client */ GRPC_CALL_ERROR_NOT_ON_CLIENT, /** this method must be called before server_accept */ GRPC_CALL_ERROR_ALREADY_ACCEPTED, /** this method must be called before invoke */ GRPC_CALL_ERROR_ALREADY_INVOKED, /** this method must be called after invoke */ GRPC_CALL_ERROR_NOT_INVOKED, /** this call is already finished (writes_done or write_status has already been called) */ GRPC_CALL_ERROR_ALREADY_FINISHED, /** there is already an outstanding read/write operation on the call */ GRPC_CALL_ERROR_TOO_MANY_OPERATIONS, /** the flags value was illegal for this call */ GRPC_CALL_ERROR_INVALID_FLAGS, /** invalid metadata was passed to this call */ GRPC_CALL_ERROR_INVALID_METADATA, /** invalid message was passed to this call */ GRPC_CALL_ERROR_INVALID_MESSAGE, /** completion queue for notification has not been registered with the server */ GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE, /** this batch of operations leads to more operations than allowed */ GRPC_CALL_ERROR_BATCH_TOO_BIG, /** payload type requested is not the type registered */ GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH } grpc_call_error; /* Default send/receive message size limits in bytes. -1 for unlimited. */ /* TODO(roth) Make this match the default receive limit after next release */ #define GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH -1 #define GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH (4 * 1024 * 1024) /* Write Flags: */ /** Hint that the write may be buffered and need not go out on the wire immediately. GRPC is free to buffer the message until the next non-buffered write, or until writes_done, but it need not buffer completely or at all. */ #define GRPC_WRITE_BUFFER_HINT (0x00000001u) /** Force compression to be disabled for a particular write (start_write/add_metadata). Illegal on invoke/accept. */ #define GRPC_WRITE_NO_COMPRESS (0x00000002u) /** Mask of all valid flags. */ #define GRPC_WRITE_USED_MASK (GRPC_WRITE_BUFFER_HINT | GRPC_WRITE_NO_COMPRESS) /* Initial metadata flags */ /** Signal that the call is idempotent */ #define GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST (0x00000010u) /** Signal that the call should not return UNAVAILABLE before it has started */ #define GRPC_INITIAL_METADATA_WAIT_FOR_READY (0x00000020u) /** Signal that the call is cacheable. GRPC is free to use GET verb */ #define GRPC_INITIAL_METADATA_CACHEABLE_REQUEST (0x00000040u) /** Signal that GRPC_INITIAL_METADATA_WAIT_FOR_READY was explicitly set by the calling application. */ #define GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET (0x00000080u) /** Signal that the initial metadata should be corked */ #define GRPC_INITIAL_METADATA_CORKED (0x00000100u) /** Mask of all valid flags */ #define GRPC_INITIAL_METADATA_USED_MASK \ (GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST | \ GRPC_INITIAL_METADATA_WAIT_FOR_READY | \ GRPC_INITIAL_METADATA_CACHEABLE_REQUEST | \ GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET | \ GRPC_INITIAL_METADATA_CORKED) /** A single metadata element */ typedef struct grpc_metadata { /* the key, value values are expected to line up with grpc_mdelem: if changing them, update metadata.h at the same time. */ grpc_slice key; grpc_slice value; uint32_t flags; /** The following fields are reserved for grpc internal use. There is no need to initialize them, and they will be set to garbage during calls to grpc. */ struct { void *obfuscated[4]; } internal_data; } grpc_metadata; /** The type of completion (for grpc_event) */ typedef enum grpc_completion_type { /** Shutting down */ GRPC_QUEUE_SHUTDOWN, /** No event before timeout */ GRPC_QUEUE_TIMEOUT, /** Operation completion */ GRPC_OP_COMPLETE } grpc_completion_type; /** The result of an operation. Returned by a completion queue when the operation started with tag. */ typedef struct grpc_event { /** The type of the completion. */ grpc_completion_type type; /** non-zero if the operation was successful, 0 upon failure. Only GRPC_OP_COMPLETE can succeed or fail. */ int success; /** The tag passed to grpc_call_start_batch etc to start this operation. Only GRPC_OP_COMPLETE has a tag. */ void *tag; } grpc_event; typedef struct { size_t count; size_t capacity; grpc_metadata *metadata; } grpc_metadata_array; typedef struct { grpc_slice method; grpc_slice host; gpr_timespec deadline; uint32_t flags; void *reserved; } grpc_call_details; typedef enum { /** Send initial metadata: one and only one instance MUST be sent for each call, unless the call was cancelled - in which case this can be skipped. This op completes after all bytes of metadata have been accepted by outgoing flow control. */ GRPC_OP_SEND_INITIAL_METADATA = 0, /** Send a message: 0 or more of these operations can occur for each call. This op completes after all bytes for the message have been accepted by outgoing flow control. */ GRPC_OP_SEND_MESSAGE, /** Send a close from the client: one and only one instance MUST be sent from the client, unless the call was cancelled - in which case this can be skipped. This op completes after all bytes for the call (including the close) have passed outgoing flow control. */ GRPC_OP_SEND_CLOSE_FROM_CLIENT, /** Send status from the server: one and only one instance MUST be sent from the server unless the call was cancelled - in which case this can be skipped. This op completes after all bytes for the call (including the status) have passed outgoing flow control. */ GRPC_OP_SEND_STATUS_FROM_SERVER, /** Receive initial metadata: one and only one MUST be made on the client, must not be made on the server. This op completes after all initial metadata has been read from the peer. */ GRPC_OP_RECV_INITIAL_METADATA, /** Receive a message: 0 or more of these operations can occur for each call. This op completes after all bytes of the received message have been read, or after a half-close has been received on this call. */ GRPC_OP_RECV_MESSAGE, /** Receive status on the client: one and only one must be made on the client. This operation always succeeds, meaning ops paired with this operation will also appear to succeed, even though they may not have. In that case the status will indicate some failure. This op completes after all activity on the call has completed. */ GRPC_OP_RECV_STATUS_ON_CLIENT, /** Receive close on the server: one and only one must be made on the server. This op completes after the close has been received by the server. This operation always succeeds, meaning ops paired with this operation will also appear to succeed, even though they may not have. */ GRPC_OP_RECV_CLOSE_ON_SERVER } grpc_op_type; struct grpc_byte_buffer; /** Operation data: one field for each op type (except SEND_CLOSE_FROM_CLIENT which has no arguments) */ typedef struct grpc_op { /** Operation type, as defined by grpc_op_type */ grpc_op_type op; /** Write flags bitset for grpc_begin_messages */ uint32_t flags; /** Reserved for future usage */ void *reserved; union { /** Reserved for future usage */ struct { void *reserved[8]; } reserved; struct { size_t count; grpc_metadata *metadata; /** If \a is_set, \a compression_level will be used for the call. * Otherwise, \a compression_level won't be considered */ struct { uint8_t is_set; grpc_compression_level level; } maybe_compression_level; } send_initial_metadata; struct { struct grpc_byte_buffer *send_message; } send_message; struct { size_t trailing_metadata_count; grpc_metadata *trailing_metadata; grpc_status_code status; /* optional: set to NULL if no details need sending, non-NULL if they do * pointer will not be retained past the start_batch call */ grpc_slice *status_details; } send_status_from_server; /** ownership of the array is with the caller, but ownership of the elements stays with the call object (ie key, value members are owned by the call object, recv_initial_metadata->array is owned by the caller). After the operation completes, call grpc_metadata_array_destroy on this value, or reuse it in a future op. */ struct { grpc_metadata_array *recv_initial_metadata; } recv_initial_metadata; /** ownership of the byte buffer is moved to the caller; the caller must call grpc_byte_buffer_destroy on this value, or reuse it in a future op. */ struct { struct grpc_byte_buffer **recv_message; } recv_message; struct { /** ownership of the array is with the caller, but ownership of the elements stays with the call object (ie key, value members are owned by the call object, trailing_metadata->array is owned by the caller). After the operation completes, call grpc_metadata_array_destroy on this value, or reuse it in a future op. */ grpc_metadata_array *trailing_metadata; grpc_status_code *status; grpc_slice *status_details; } recv_status_on_client; struct { /** out argument, set to 1 if the call failed in any way (seen as a cancellation on the server), or 0 if the call succeeded */ int *cancelled; } recv_close_on_server; } data; } grpc_op; /** Information requested from the channel. */ typedef struct { /* If non-NULL, will be set to point to a string indicating the LB * policy name. Caller takes ownership. */ char **lb_policy_name; /* If non-NULL, will be set to point to a string containing the * service config used by the channel in JSON form. */ char **service_config_json; } grpc_channel_info; typedef struct grpc_resource_quota grpc_resource_quota; #ifdef __cplusplus } #endif #endif /* GRPC_IMPL_CODEGEN_GRPC_TYPES_H */ grpc-1.3.2/include/grpc/impl/codegen/port_platform.h000066400000000000000000000271761310511640000224400ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_IMPL_CODEGEN_PORT_PLATFORM_H #define GRPC_IMPL_CODEGEN_PORT_PLATFORM_H /* * Define GPR_BACKWARDS_COMPATIBILITY_MODE to try harder to be ABI * compatible with older platforms (currently only on Linux) * Causes: * - some libc calls to be gotten via dlsym * - some syscalls to be made directly */ /* Get windows.h included everywhere (we need it) */ #if defined(_WIN64) || defined(WIN64) || defined(_WIN32) || defined(WIN32) #ifndef WIN32_LEAN_AND_MEAN #define GRPC_WIN32_LEAN_AND_MEAN_WAS_NOT_DEFINED #define WIN32_LEAN_AND_MEAN #endif /* WIN32_LEAN_AND_MEAN */ #ifndef NOMINMAX #define GRPC_NOMINMX_WAS_NOT_DEFINED #define NOMINMAX #endif /* NOMINMAX */ #ifndef _WIN32_WINNT #error \ "Please compile grpc with _WIN32_WINNT of at least 0x600 (aka Windows Vista)" #else /* !defined(_WIN32_WINNT) */ #if (_WIN32_WINNT < 0x0600) #error \ "Please compile grpc with _WIN32_WINNT of at least 0x600 (aka Windows Vista)" #endif /* _WIN32_WINNT < 0x0600 */ #endif /* defined(_WIN32_WINNT) */ #include #ifdef GRPC_WIN32_LEAN_AND_MEAN_WAS_NOT_DEFINED #undef GRPC_WIN32_LEAN_AND_MEAN_WAS_NOT_DEFINED #undef WIN32_LEAN_AND_MEAN #endif /* GRPC_WIN32_LEAN_AND_MEAN_WAS_NOT_DEFINED */ #ifdef GRPC_NOMINMAX_WAS_NOT_DEFINED #undef GRPC_NOMINMAX_WAS_NOT_DEFINED #undef NOMINMAX #endif /* GRPC_WIN32_LEAN_AND_MEAN_WAS_NOT_DEFINED */ #endif /* defined(_WIN64) || defined(WIN64) || defined(_WIN32) || \ defined(WIN32) */ /* Override this file with one for your platform if you need to redefine things. */ #if !defined(GPR_NO_AUTODETECT_PLATFORM) #if defined(_WIN64) || defined(WIN64) || defined(_WIN32) || defined(WIN32) #if defined(_WIN64) || defined(WIN64) #define GPR_ARCH_64 1 #else #define GPR_ARCH_32 1 #endif #define GPR_PLATFORM_STRING "windows" #define GPR_WINDOWS 1 #define GPR_WINDOWS_SUBPROCESS 1 #define GPR_WINDOWS_ENV #ifdef __MSYS__ #define GPR_GETPID_IN_UNISTD_H 1 #define GPR_MSYS_TMPFILE #define GPR_POSIX_LOG #define GPR_POSIX_STRING #define GPR_POSIX_TIME #else #define GPR_GETPID_IN_PROCESS_H 1 #define GPR_WINDOWS_TMPFILE #define GPR_WINDOWS_LOG #define GPR_WINDOWS_CRASH_HANDLER 1 #define GPR_WINDOWS_STRING #define GPR_WINDOWS_TIME #endif #ifdef __GNUC__ #define GPR_GCC_ATOMIC 1 #define GPR_GCC_TLS 1 #else #define GPR_WINDOWS_ATOMIC 1 #define GPR_MSVC_TLS 1 #endif #elif defined(GPR_MANYLINUX1) // TODO(atash): manylinux1 is just another __linux__ but with ancient // libraries; it should be integrated with the `__linux__` definitions below. #define GPR_PLATFORM_STRING "manylinux" #define GPR_POSIX_CRASH_HANDLER 1 #define GPR_CPU_POSIX 1 #define GPR_GCC_ATOMIC 1 #define GPR_GCC_TLS 1 #define GPR_LINUX 1 #define GPR_LINUX_LOG 1 #define GPR_SUPPORT_CHANNELS_FROM_FD 1 #define GPR_LINUX_ENV 1 #define GPR_POSIX_TMPFILE 1 #define GPR_POSIX_STRING 1 #define GPR_POSIX_SUBPROCESS 1 #define GPR_POSIX_SYNC 1 #define GPR_POSIX_TIME 1 #define GPR_GETPID_IN_UNISTD_H 1 #ifdef _LP64 #define GPR_ARCH_64 1 #else /* _LP64 */ #define GPR_ARCH_32 1 #endif /* _LP64 */ #elif defined(ANDROID) || defined(__ANDROID__) #define GPR_PLATFORM_STRING "android" #define GPR_ANDROID 1 #ifdef _LP64 #define GPR_ARCH_64 1 #else /* _LP64 */ #define GPR_ARCH_32 1 #endif /* _LP64 */ #define GPR_CPU_POSIX 1 #define GPR_GCC_SYNC 1 #define GPR_GCC_TLS 1 #define GPR_POSIX_ENV 1 #define GPR_POSIX_TMPFILE 1 #define GPR_ANDROID_LOG 1 #define GPR_POSIX_STRING 1 #define GPR_POSIX_SUBPROCESS 1 #define GPR_POSIX_SYNC 1 #define GPR_POSIX_TIME 1 #define GPR_GETPID_IN_UNISTD_H 1 #define GPR_SUPPORT_CHANNELS_FROM_FD 1 #elif defined(__linux__) #define GPR_PLATFORM_STRING "linux" #ifndef _BSD_SOURCE #define _BSD_SOURCE #endif #ifndef _DEFAULT_SOURCE #define _DEFAULT_SOURCE #endif #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #define GPR_CPU_LINUX 1 #define GPR_GCC_ATOMIC 1 #define GPR_GCC_TLS 1 #define GPR_LINUX 1 #define GPR_LINUX_LOG #define GPR_SUPPORT_CHANNELS_FROM_FD 1 #define GPR_LINUX_ENV 1 #define GPR_POSIX_TMPFILE 1 #define GPR_POSIX_STRING 1 #define GPR_POSIX_SUBPROCESS 1 #define GPR_POSIX_SYNC 1 #define GPR_POSIX_TIME 1 #define GPR_GETPID_IN_UNISTD_H 1 #ifdef _LP64 #define GPR_ARCH_64 1 #else /* _LP64 */ #define GPR_ARCH_32 1 #endif /* _LP64 */ #ifdef __GLIBC__ #define GPR_POSIX_CRASH_HANDLER 1 #else /* musl libc */ #define GPR_MUSL_LIBC_COMPAT 1 #endif #elif defined(__APPLE__) #include #include #ifndef _BSD_SOURCE #define _BSD_SOURCE #endif #if TARGET_OS_IPHONE #define GPR_FORBID_UNREACHABLE_CODE 1 #define GPR_PLATFORM_STRING "ios" #define GPR_CPU_IPHONE 1 #define GPR_PTHREAD_TLS 1 #else /* TARGET_OS_IPHONE */ #define GPR_PLATFORM_STRING "osx" #ifdef __MAC_OS_X_VERSION_MIN_REQUIRED #if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_7 #define GPR_CPU_IPHONE 1 #define GPR_PTHREAD_TLS 1 #else /* __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_7 */ #define GPR_CPU_POSIX 1 #define GPR_GCC_TLS 1 #endif #else /* __MAC_OS_X_VERSION_MIN_REQUIRED */ #define GPR_CPU_POSIX 1 #define GPR_GCC_TLS 1 #endif #define GPR_POSIX_CRASH_HANDLER 1 #endif #define GPR_APPLE 1 #define GPR_GCC_ATOMIC 1 #define GPR_POSIX_LOG 1 #define GPR_POSIX_ENV 1 #define GPR_POSIX_TMPFILE 1 #define GPR_POSIX_STRING 1 #define GPR_POSIX_SUBPROCESS 1 #define GPR_POSIX_SYNC 1 #define GPR_POSIX_TIME 1 #define GPR_GETPID_IN_UNISTD_H 1 #define GPR_SUPPORT_CHANNELS_FROM_FD 1 #ifdef _LP64 #define GPR_ARCH_64 1 #else /* _LP64 */ #define GPR_ARCH_32 1 #endif /* _LP64 */ #elif defined(__FreeBSD__) #define GPR_PLATFORM_STRING "freebsd" #ifndef _BSD_SOURCE #define _BSD_SOURCE #endif #define GPR_FREEBSD 1 #define GPR_CPU_POSIX 1 #define GPR_GCC_ATOMIC 1 #define GPR_GCC_TLS 1 #define GPR_POSIX_LOG 1 #define GPR_POSIX_ENV 1 #define GPR_POSIX_TMPFILE 1 #define GPR_POSIX_STRING 1 #define GPR_POSIX_SUBPROCESS 1 #define GPR_POSIX_SYNC 1 #define GPR_POSIX_TIME 1 #define GPR_GETPID_IN_UNISTD_H 1 #define GPR_SUPPORT_CHANNELS_FROM_FD 1 #ifdef _LP64 #define GPR_ARCH_64 1 #else /* _LP64 */ #define GPR_ARCH_32 1 #endif /* _LP64 */ #elif defined(__native_client__) #define GPR_PLATFORM_STRING "nacl" #ifndef _BSD_SOURCE #define _BSD_SOURCE #endif #ifndef _DEFAULT_SOURCE #define _DEFAULT_SOURCE #endif #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #define GPR_NACL 1 #define GPR_CPU_POSIX 1 #define GPR_GCC_ATOMIC 1 #define GPR_GCC_TLS 1 #define GPR_POSIX_LOG 1 #define GPR_POSIX_ENV 1 #define GPR_POSIX_TMPFILE 1 #define GPR_POSIX_STRING 1 #define GPR_POSIX_SUBPROCESS 1 #define GPR_POSIX_SYNC 1 #define GPR_POSIX_TIME 1 #define GPR_GETPID_IN_UNISTD_H 1 #ifdef _LP64 #define GPR_ARCH_64 1 #else /* _LP64 */ #define GPR_ARCH_32 1 #endif /* _LP64 */ #else #error "Could not auto-detect platform" #endif #endif /* GPR_NO_AUTODETECT_PLATFORM */ #ifndef GPR_PLATFORM_STRING #warning "GPR_PLATFORM_STRING not auto-detected" #define GPR_PLATFORM_STRING "unknown" #endif #ifdef GPR_GCOV #undef GPR_FORBID_UNREACHABLE_CODE #define GPR_FORBID_UNREACHABLE_CODE 1 #endif #ifdef _MSC_VER #ifdef _PYTHON_MSVC // The Python 3.5 Windows runtime is missing InetNtop #define GPR_WIN_INET_NTOP #endif // _PYTHON_MSVC #if _MSC_VER < 1700 typedef __int8 int8_t; typedef __int16 int16_t; typedef __int32 int32_t; typedef __int64 int64_t; typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; #else #include #endif /* _MSC_VER < 1700 */ #else #include #endif /* _MSC_VER */ /* Cache line alignment */ #ifndef GPR_CACHELINE_SIZE_LOG #if defined(__i386__) || defined(__x86_64__) #define GPR_CACHELINE_SIZE_LOG 6 #endif #ifndef GPR_CACHELINE_SIZE_LOG /* A reasonable default guess. Note that overestimates tend to waste more space, while underestimates tend to waste more time. */ #define GPR_CACHELINE_SIZE_LOG 6 #endif /* GPR_CACHELINE_SIZE_LOG */ #endif /* GPR_CACHELINE_SIZE_LOG */ #define GPR_CACHELINE_SIZE (1 << GPR_CACHELINE_SIZE_LOG) /* scrub GCC_ATOMIC if it's not available on this compiler */ #if defined(GPR_GCC_ATOMIC) && !defined(__ATOMIC_RELAXED) #undef GPR_GCC_ATOMIC #define GPR_GCC_SYNC 1 #endif /* Validate platform combinations */ #if defined(GPR_GCC_ATOMIC) + defined(GPR_GCC_SYNC) + \ defined(GPR_WINDOWS_ATOMIC) != \ 1 #error Must define exactly one of GPR_GCC_ATOMIC, GPR_GCC_SYNC, GPR_WINDOWS_ATOMIC #endif #if defined(GPR_ARCH_32) + defined(GPR_ARCH_64) != 1 #error Must define exactly one of GPR_ARCH_32, GPR_ARCH_64 #endif #if defined(GPR_CPU_LINUX) + defined(GPR_CPU_POSIX) + defined(GPR_WINDOWS) + \ defined(GPR_CPU_IPHONE) + defined(GPR_CPU_CUSTOM) != \ 1 #error Must define exactly one of GPR_CPU_LINUX, GPR_CPU_POSIX, GPR_WINDOWS, GPR_CPU_IPHONE, GPR_CPU_CUSTOM #endif #if defined(GPR_MSVC_TLS) + defined(GPR_GCC_TLS) + defined(GPR_PTHREAD_TLS) + \ defined(GPR_CUSTOM_TLS) != \ 1 #error Must define exactly one of GPR_MSVC_TLS, GPR_GCC_TLS, GPR_PTHREAD_TLS, GPR_CUSTOM_TLS #endif /* maximum alignment needed for any type on this platform, rounded up to a power of two */ #define GPR_MAX_ALIGNMENT 16 #ifndef GRPC_ARES #ifdef GPR_WINDOWS #define GRPC_ARES 0 #else #define GRPC_ARES 1 #endif #endif #ifndef GRPC_MUST_USE_RESULT #if defined(__GNUC__) && !defined(__MINGW32__) #define GRPC_MUST_USE_RESULT __attribute__((warn_unused_result)) #define GPR_ALIGN_STRUCT(n) __attribute__((aligned(n))) #else #define GRPC_MUST_USE_RESULT #define GPR_ALIGN_STRUCT(n) #endif #endif #ifndef GPR_PRINT_FORMAT_CHECK #ifdef __GNUC__ #define GPR_PRINT_FORMAT_CHECK(FORMAT_STR, ARGS) \ __attribute__((format(printf, FORMAT_STR, ARGS))) #else #define GPR_PRINT_FORMAT_CHECK(FORMAT_STR, ARGS) #endif #endif /* GPR_PRINT_FORMAT_CHECK */ #if GPR_FORBID_UNREACHABLE_CODE #define GPR_UNREACHABLE_CODE(STATEMENT) #else #define GPR_UNREACHABLE_CODE(STATEMENT) \ do { \ gpr_log(GPR_ERROR, "Should never reach here."); \ abort(); \ STATEMENT; \ } while (0) #endif /* GPR_FORBID_UNREACHABLE_CODE */ #ifndef GPRAPI #define GPRAPI #endif #ifndef GRPCAPI #define GRPCAPI GPRAPI #endif #ifndef CENSUSAPI #define CENSUSAPI GRPCAPI #endif #endif /* GRPC_IMPL_CODEGEN_PORT_PLATFORM_H */ grpc-1.3.2/include/grpc/impl/codegen/propagation_bits.h000066400000000000000000000055021310511640000231010ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_IMPL_CODEGEN_PROPAGATION_BITS_H #define GRPC_IMPL_CODEGEN_PROPAGATION_BITS_H #include #ifdef __cplusplus extern "C" { #endif /* Propagation bits: this can be bitwise or-ed to form propagation_mask for * grpc_call */ /** Propagate deadline */ #define GRPC_PROPAGATE_DEADLINE ((uint32_t)1) /** Propagate census context */ #define GRPC_PROPAGATE_CENSUS_STATS_CONTEXT ((uint32_t)2) #define GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT ((uint32_t)4) /** Propagate cancellation */ #define GRPC_PROPAGATE_CANCELLATION ((uint32_t)8) /* Default propagation mask: clients of the core API are encouraged to encode deltas from this in their implementations... ie write: GRPC_PROPAGATE_DEFAULTS & ~GRPC_PROPAGATE_DEADLINE to disable deadline propagation. Doing so gives flexibility in the future to define new propagation types that are default inherited or not. */ #define GRPC_PROPAGATE_DEFAULTS \ ((uint32_t)(( \ 0xffff | GRPC_PROPAGATE_DEADLINE | GRPC_PROPAGATE_CENSUS_STATS_CONTEXT | \ GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT | GRPC_PROPAGATE_CANCELLATION))) #ifdef __cplusplus } #endif #endif /* GRPC_IMPL_CODEGEN_PROPAGATION_BITS_H */ grpc-1.3.2/include/grpc/impl/codegen/slice.h000066400000000000000000000144261310511640000206410ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_IMPL_CODEGEN_SLICE_H #define GRPC_IMPL_CODEGEN_SLICE_H #include #include #include #include typedef struct grpc_slice grpc_slice; /* Slice API A slice represents a contiguous reference counted array of bytes. It is cheap to take references to a slice, and it is cheap to create a slice pointing to a subset of another slice. The data-structure for slices is exposed here to allow non-gpr code to build slices from whatever data they have available. When defining interfaces that handle slices, care should be taken to define reference ownership semantics (who should call unref?) and mutability constraints (is the callee allowed to modify the slice?) */ typedef struct grpc_slice_refcount_vtable { void (*ref)(void *); void (*unref)(grpc_exec_ctx *exec_ctx, void *); int (*eq)(grpc_slice a, grpc_slice b); uint32_t (*hash)(grpc_slice slice); } grpc_slice_refcount_vtable; /* Reference count container for grpc_slice. Contains function pointers to increment and decrement reference counts. Implementations should cleanup when the reference count drops to zero. Typically client code should not touch this, and use grpc_slice_malloc, grpc_slice_new, or grpc_slice_new_with_len instead. */ typedef struct grpc_slice_refcount { const grpc_slice_refcount_vtable *vtable; /* If a subset of this slice is taken, use this pointer for the refcount. Typically points back to the refcount itself, however iterning implementations can use this to avoid a verification step on each hash or equality check */ struct grpc_slice_refcount *sub_refcount; } grpc_slice_refcount; #define GRPC_SLICE_INLINED_SIZE (sizeof(size_t) + sizeof(uint8_t *) - 1) /* A grpc_slice s, if initialized, represents the byte range s.bytes[0..s.length-1]. It can have an associated ref count which has a destruction routine to be run when the ref count reaches zero (see grpc_slice_new() and grp_slice_unref()). Multiple grpc_slice values may share a ref count. If the slice does not have a refcount, it represents an inlined small piece of data that is copied by value. */ struct grpc_slice { struct grpc_slice_refcount *refcount; union { struct { uint8_t *bytes; size_t length; } refcounted; struct { uint8_t length; uint8_t bytes[GRPC_SLICE_INLINED_SIZE]; } inlined; } data; }; #define GRPC_SLICE_BUFFER_INLINE_ELEMENTS 8 /* Represents an expandable array of slices, to be interpreted as a single item. */ typedef struct { /* This is for internal use only. External users (i.e any code outside grpc * core) MUST NOT use this field */ grpc_slice *base_slices; /* slices in the array (Points to the first valid grpc_slice in the array) */ grpc_slice *slices; /* the number of slices in the array */ size_t count; /* the number of slices allocated in the array. External users (i.e any code * outside grpc core) MUST NOT use this field */ size_t capacity; /* the combined length of all slices in the array */ size_t length; /* inlined elements to avoid allocations */ grpc_slice inlined[GRPC_SLICE_BUFFER_INLINE_ELEMENTS]; } grpc_slice_buffer; #define GRPC_SLICE_START_PTR(slice) \ ((slice).refcount ? (slice).data.refcounted.bytes \ : (slice).data.inlined.bytes) #define GRPC_SLICE_LENGTH(slice) \ ((slice).refcount ? (slice).data.refcounted.length \ : (slice).data.inlined.length) #define GRPC_SLICE_SET_LENGTH(slice, newlen) \ ((slice).refcount ? ((slice).data.refcounted.length = (size_t)(newlen)) \ : ((slice).data.inlined.length = (uint8_t)(newlen))) #define GRPC_SLICE_END_PTR(slice) \ GRPC_SLICE_START_PTR(slice) + GRPC_SLICE_LENGTH(slice) #define GRPC_SLICE_IS_EMPTY(slice) (GRPC_SLICE_LENGTH(slice) == 0) #ifdef GRPC_ALLOW_GPR_SLICE_FUNCTIONS /* Duplicate GPR_* definitions */ #define GPR_SLICE_START_PTR(slice) \ ((slice).refcount ? (slice).data.refcounted.bytes \ : (slice).data.inlined.bytes) #define GPR_SLICE_LENGTH(slice) \ ((slice).refcount ? (slice).data.refcounted.length \ : (slice).data.inlined.length) #define GPR_SLICE_SET_LENGTH(slice, newlen) \ ((slice).refcount ? ((slice).data.refcounted.length = (size_t)(newlen)) \ : ((slice).data.inlined.length = (uint8_t)(newlen))) #define GPR_SLICE_END_PTR(slice) \ GRPC_SLICE_START_PTR(slice) + GRPC_SLICE_LENGTH(slice) #define GPR_SLICE_IS_EMPTY(slice) (GRPC_SLICE_LENGTH(slice) == 0) #endif /* GRPC_ALLOW_GPR_SLICE_FUNCTIONS */ #endif /* GRPC_IMPL_CODEGEN_SLICE_H */ grpc-1.3.2/include/grpc/impl/codegen/status.h000066400000000000000000000153371310511640000210670ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_IMPL_CODEGEN_STATUS_H #define GRPC_IMPL_CODEGEN_STATUS_H #ifdef __cplusplus extern "C" { #endif typedef enum { /* Not an error; returned on success */ GRPC_STATUS_OK = 0, /* The operation was cancelled (typically by the caller). */ GRPC_STATUS_CANCELLED = 1, /* Unknown error. An example of where this error may be returned is if a Status value received from another address space belongs to an error-space that is not known in this address space. Also errors raised by APIs that do not return enough error information may be converted to this error. */ GRPC_STATUS_UNKNOWN = 2, /* Client specified an invalid argument. Note that this differs from FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments that are problematic regardless of the state of the system (e.g., a malformed file name). */ GRPC_STATUS_INVALID_ARGUMENT = 3, /* Deadline expired before operation could complete. For operations that change the state of the system, this error may be returned even if the operation has completed successfully. For example, a successful response from a server could have been delayed long enough for the deadline to expire. */ GRPC_STATUS_DEADLINE_EXCEEDED = 4, /* Some requested entity (e.g., file or directory) was not found. */ GRPC_STATUS_NOT_FOUND = 5, /* Some entity that we attempted to create (e.g., file or directory) already exists. */ GRPC_STATUS_ALREADY_EXISTS = 6, /* The caller does not have permission to execute the specified operation. PERMISSION_DENIED must not be used for rejections caused by exhausting some resource (use RESOURCE_EXHAUSTED instead for those errors). PERMISSION_DENIED must not be used if the caller can not be identified (use UNAUTHENTICATED instead for those errors). */ GRPC_STATUS_PERMISSION_DENIED = 7, /* The request does not have valid authentication credentials for the operation. */ GRPC_STATUS_UNAUTHENTICATED = 16, /* Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system is out of space. */ GRPC_STATUS_RESOURCE_EXHAUSTED = 8, /* Operation was rejected because the system is not in a state required for the operation's execution. For example, directory to be deleted may be non-empty, an rmdir operation is applied to a non-directory, etc. A litmus test that may help a service implementor in deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE: (a) Use UNAVAILABLE if the client can retry just the failing call. (b) Use ABORTED if the client should retry at a higher-level (e.g., restarting a read-modify-write sequence). (c) Use FAILED_PRECONDITION if the client should not retry until the system state has been explicitly fixed. E.g., if an "rmdir" fails because the directory is non-empty, FAILED_PRECONDITION should be returned since the client should not retry unless they have first fixed up the directory by deleting files from it. (d) Use FAILED_PRECONDITION if the client performs conditional REST Get/Update/Delete on a resource and the resource on the server does not match the condition. E.g., conflicting read-modify-write on the same resource. */ GRPC_STATUS_FAILED_PRECONDITION = 9, /* The operation was aborted, typically due to a concurrency issue like sequencer check failures, transaction aborts, etc. See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE. */ GRPC_STATUS_ABORTED = 10, /* Operation was attempted past the valid range. E.g., seeking or reading past end of file. Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed if the system state changes. For example, a 32-bit file system will generate INVALID_ARGUMENT if asked to read at an offset that is not in the range [0,2^32-1], but it will generate OUT_OF_RANGE if asked to read from an offset past the current file size. There is a fair bit of overlap between FAILED_PRECONDITION and OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific error) when it applies so that callers who are iterating through a space can easily look for an OUT_OF_RANGE error to detect when they are done. */ GRPC_STATUS_OUT_OF_RANGE = 11, /* Operation is not implemented or not supported/enabled in this service. */ GRPC_STATUS_UNIMPLEMENTED = 12, /* Internal errors. Means some invariants expected by underlying system has been broken. If you see one of these errors, something is very broken. */ GRPC_STATUS_INTERNAL = 13, /* The service is currently unavailable. This is a most likely a transient condition and may be corrected by retrying with a backoff. See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE. */ GRPC_STATUS_UNAVAILABLE = 14, /* Unrecoverable data loss or corruption. */ GRPC_STATUS_DATA_LOSS = 15, /* Force users to include a default branch: */ GRPC_STATUS__DO_NOT_USE = -1 } grpc_status_code; #ifdef __cplusplus } #endif #endif /* GRPC_IMPL_CODEGEN_STATUS_H */ grpc-1.3.2/include/grpc/impl/codegen/sync.h000066400000000000000000000054571310511640000205220ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_IMPL_CODEGEN_SYNC_H #define GRPC_IMPL_CODEGEN_SYNC_H /* Synchronization primitives for GPR. The type gpr_mu provides a non-reentrant mutex (lock). The type gpr_cv provides a condition variable. The type gpr_once provides for one-time initialization. The type gpr_event provides one-time-setting, reading, and waiting of a void*, with memory barriers. The type gpr_refcount provides an object reference counter, with memory barriers suitable to control object lifetimes. The type gpr_stats_counter provides an atomic statistics counter. It provides no memory barriers. */ #ifdef __cplusplus extern "C" { #endif /* Platform-specific type declarations of gpr_mu and gpr_cv. */ #include #include #if defined(GPR_POSIX_SYNC) #include #elif defined(GPR_WINDOWS) #include #elif !defined(GPR_CUSTOM_SYNC) #error Unable to determine platform for sync #endif #ifdef __cplusplus } #endif #endif /* GRPC_IMPL_CODEGEN_SYNC_H */ grpc-1.3.2/include/grpc/impl/codegen/sync_generic.h000066400000000000000000000040071310511640000222040ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_IMPL_CODEGEN_SYNC_GENERIC_H #define GRPC_IMPL_CODEGEN_SYNC_GENERIC_H /* Generic type defintions for gpr_sync. */ #include /* gpr_event */ typedef struct { gpr_atm state; } gpr_event; #define GPR_EVENT_INIT \ { 0 } /* gpr_refcount */ typedef struct { gpr_atm count; } gpr_refcount; /* gpr_stats_counter */ typedef struct { gpr_atm value; } gpr_stats_counter; #define GPR_STATS_INIT \ { 0 } #endif /* GRPC_IMPL_CODEGEN_SYNC_GENERIC_H */ grpc-1.3.2/include/grpc/impl/codegen/sync_posix.h000066400000000000000000000035521310511640000217360ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_IMPL_CODEGEN_SYNC_POSIX_H #define GRPC_IMPL_CODEGEN_SYNC_POSIX_H #include #include typedef pthread_mutex_t gpr_mu; typedef pthread_cond_t gpr_cv; typedef pthread_once_t gpr_once; #define GPR_ONCE_INIT PTHREAD_ONCE_INIT #endif /* GRPC_IMPL_CODEGEN_SYNC_POSIX_H */ grpc-1.3.2/include/grpc/impl/codegen/sync_windows.h000066400000000000000000000036561310511640000222730ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_IMPL_CODEGEN_SYNC_WINDOWS_H #define GRPC_IMPL_CODEGEN_SYNC_WINDOWS_H #include typedef struct { CRITICAL_SECTION cs; /* Not an SRWLock until Vista is unsupported */ int locked; } gpr_mu; typedef CONDITION_VARIABLE gpr_cv; typedef INIT_ONCE gpr_once; #define GPR_ONCE_INIT INIT_ONCE_STATIC_INIT #endif /* GRPC_IMPL_CODEGEN_SYNC_WINDOWS_H */ grpc-1.3.2/include/grpc/load_reporting.h000066400000000000000000000045721310511640000202060ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_LOAD_REPORTING_H #define GRPC_LOAD_REPORTING_H #include #include #ifdef __cplusplus extern "C" { #endif /** Metadata key for the gRPC LB load balancer token. * * The value corresponding to this key is an opaque token that is given to the * frontend as part of each pick; the frontend sends this token to the backend * in each request it sends when using that pick. The token is used by the * backend to verify the request and to allow the backend to report load to the * gRPC LB system. */ #define GRPC_LB_TOKEN_MD_KEY "lb-token" /** A sequence of values for load reporting purposes */ typedef struct grpc_load_reporting_cost_context { grpc_slice *values; size_t values_count; } grpc_load_reporting_cost_context; #ifdef __cplusplus } #endif #endif /* GRPC_LOAD_REPORTING_H */ grpc-1.3.2/include/grpc/module.modulemap000066400000000000000000000004311310511640000202050ustar00rootroot00000000000000framework module grpc { umbrella header "grpc.h" header "byte_buffer_reader.h" header "grpc_security.h" header "grpc_security_constants.h" header "support/alloc.h" header "support/port_platform.h" header "support/string_util.h" export * module * { export * } } grpc-1.3.2/include/grpc/slice.h000066400000000000000000000160271310511640000162730ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SLICE_H #define GRPC_SLICE_H #include #include #ifdef __cplusplus extern "C" { #endif /* Increment the refcount of s. Requires slice is initialized. Returns s. */ GPRAPI grpc_slice grpc_slice_ref(grpc_slice s); /* Decrement the ref count of s. If the ref count of s reaches zero, all slices sharing the ref count are destroyed, and considered no longer initialized. If s is ultimately derived from a call to grpc_slice_new(start, len, dest) where dest!=NULL , then (*dest)(start) is called, else if s is ultimately derived from a call to grpc_slice_new_with_len(start, len, dest) where dest!=NULL , then (*dest)(start, len). Requires s initialized. */ GPRAPI void grpc_slice_unref(grpc_slice s); /* Create a slice pointing at some data. Calls malloc to allocate a refcount for the object, and arranges that destroy will be called with the pointer passed in at destruction. */ GPRAPI grpc_slice grpc_slice_new(void *p, size_t len, void (*destroy)(void *)); /* Equivalent to grpc_slice_new, but with a separate pointer that is passed to the destroy function. This function can be useful when the data is part of a larger structure that must be destroyed when the data is no longer needed. */ GPRAPI grpc_slice grpc_slice_new_with_user_data(void *p, size_t len, void (*destroy)(void *), void *user_data); /* Equivalent to grpc_slice_new, but with a two argument destroy function that also takes the slice length. */ GPRAPI grpc_slice grpc_slice_new_with_len(void *p, size_t len, void (*destroy)(void *, size_t)); /* Equivalent to grpc_slice_new(malloc(len), len, free), but saves one malloc() call. Aborts if malloc() fails. */ GPRAPI grpc_slice grpc_slice_malloc(size_t length); /* Intern a slice: The return value for two invocations of this function with the same sequence of bytes is a slice which points to the same memory. */ GPRAPI grpc_slice grpc_slice_intern(grpc_slice slice); /* Create a slice by copying a string. Does not preserve null terminators. Equivalent to: size_t len = strlen(source); grpc_slice slice = grpc_slice_malloc(len); memcpy(slice->data, source, len); */ GPRAPI grpc_slice grpc_slice_from_copied_string(const char *source); /* Create a slice by copying a buffer. Equivalent to: grpc_slice slice = grpc_slice_malloc(len); memcpy(slice->data, source, len); */ GPRAPI grpc_slice grpc_slice_from_copied_buffer(const char *source, size_t len); /* Create a slice pointing to constant memory */ GPRAPI grpc_slice grpc_slice_from_static_string(const char *source); /* Create a slice pointing to constant memory */ GPRAPI grpc_slice grpc_slice_from_static_buffer(const void *source, size_t len); /* Return a result slice derived from s, which shares a ref count with s, where result.data==s.data+begin, and result.length==end-begin. The ref count of s is increased by one. Requires s initialized, begin <= end, begin <= s.length, and end <= source->length. */ GPRAPI grpc_slice grpc_slice_sub(grpc_slice s, size_t begin, size_t end); /* The same as grpc_slice_sub, but without altering the ref count */ GPRAPI grpc_slice grpc_slice_sub_no_ref(grpc_slice s, size_t begin, size_t end); /* Splits s into two: modifies s to be s[0:split], and returns a new slice, sharing a refcount with s, that contains s[split:s.length]. Requires s intialized, split <= s.length */ GPRAPI grpc_slice grpc_slice_split_tail(grpc_slice *s, size_t split); /* Splits s into two: modifies s to be s[split:s.length], and returns a new slice, sharing a refcount with s, that contains s[0:split]. Requires s intialized, split <= s.length */ GPRAPI grpc_slice grpc_slice_split_head(grpc_slice *s, size_t split); GPRAPI grpc_slice grpc_empty_slice(void); GPRAPI uint32_t grpc_slice_default_hash_impl(grpc_slice s); GPRAPI int grpc_slice_default_eq_impl(grpc_slice a, grpc_slice b); GPRAPI int grpc_slice_eq(grpc_slice a, grpc_slice b); /* Returns <0 if a < b, ==0 if a == b, >0 if a > b The order is arbitrary, and is not guaranteed to be stable across different versions of the API. */ GPRAPI int grpc_slice_cmp(grpc_slice a, grpc_slice b); GPRAPI int grpc_slice_str_cmp(grpc_slice a, const char *b); GPRAPI int grpc_slice_buf_cmp(grpc_slice a, const void *b, size_t blen); /* return non-zero if the first blen bytes of a are equal to b */ GPRAPI int grpc_slice_buf_start_eq(grpc_slice a, const void *b, size_t blen); /* return the index of the last instance of \a c in \a s, or -1 if not found */ GPRAPI int grpc_slice_rchr(grpc_slice s, char c); GPRAPI int grpc_slice_chr(grpc_slice s, char c); /* return the index of the first occurance of \a needle in \a haystack, or -1 if * it's not found */ GPRAPI int grpc_slice_slice(grpc_slice haystack, grpc_slice needle); GPRAPI uint32_t grpc_slice_hash(grpc_slice s); /* Do two slices point at the same memory, with the same length If a or b is inlined, actually compares data */ GPRAPI int grpc_slice_is_equivalent(grpc_slice a, grpc_slice b); /* Return a slice pointing to newly allocated memory that has the same contents * as \a s */ GPRAPI grpc_slice grpc_slice_dup(grpc_slice a); /* Return a copy of slice as a C string. Offers no protection against embedded NULL's. Returned string must be freed with gpr_free. */ GPRAPI char *grpc_slice_to_c_string(grpc_slice s); #ifdef __cplusplus } #endif #endif /* GRPC_SLICE_H */ grpc-1.3.2/include/grpc/slice_buffer.h000066400000000000000000000110211310511640000176110ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SLICE_BUFFER_H #define GRPC_SLICE_BUFFER_H #include #ifdef __cplusplus extern "C" { #endif /* initialize a slice buffer */ GPRAPI void grpc_slice_buffer_init(grpc_slice_buffer *sb); /* destroy a slice buffer - unrefs any held elements */ GPRAPI void grpc_slice_buffer_destroy(grpc_slice_buffer *sb); /* Add an element to a slice buffer - takes ownership of the slice. This function is allowed to concatenate the passed in slice to the end of some other slice if desired by the slice buffer. */ GPRAPI void grpc_slice_buffer_add(grpc_slice_buffer *sb, grpc_slice slice); /* add an element to a slice buffer - takes ownership of the slice and returns the index of the slice. Guarantees that the slice will not be concatenated at the end of another slice (i.e. the data for this slice will begin at the first byte of the slice at the returned index in sb->slices) The implementation MAY decide to concatenate data at the end of a small slice added in this fashion. */ GPRAPI size_t grpc_slice_buffer_add_indexed(grpc_slice_buffer *sb, grpc_slice slice); GPRAPI void grpc_slice_buffer_addn(grpc_slice_buffer *sb, grpc_slice *slices, size_t n); /* add a very small (less than 8 bytes) amount of data to the end of a slice buffer: returns a pointer into which to add the data */ GPRAPI uint8_t *grpc_slice_buffer_tiny_add(grpc_slice_buffer *sb, size_t len); /* pop the last buffer, but don't unref it */ GPRAPI void grpc_slice_buffer_pop(grpc_slice_buffer *sb); /* clear a slice buffer, unref all elements */ GPRAPI void grpc_slice_buffer_reset_and_unref(grpc_slice_buffer *sb); /* swap the contents of two slice buffers */ GPRAPI void grpc_slice_buffer_swap(grpc_slice_buffer *a, grpc_slice_buffer *b); /* move all of the elements of src into dst */ GPRAPI void grpc_slice_buffer_move_into(grpc_slice_buffer *src, grpc_slice_buffer *dst); /* remove n bytes from the end of a slice buffer */ GPRAPI void grpc_slice_buffer_trim_end(grpc_slice_buffer *src, size_t n, grpc_slice_buffer *garbage); /* move the first n bytes of src into dst */ GPRAPI void grpc_slice_buffer_move_first(grpc_slice_buffer *src, size_t n, grpc_slice_buffer *dst); /* move the first n bytes of src into dst (copying them) */ GPRAPI void grpc_slice_buffer_move_first_into_buffer(grpc_exec_ctx *exec_ctx, grpc_slice_buffer *src, size_t n, void *dst); /* take the first slice in the slice buffer */ GPRAPI grpc_slice grpc_slice_buffer_take_first(grpc_slice_buffer *src); /* undo the above with (a possibly different) \a slice */ GPRAPI void grpc_slice_buffer_undo_take_first(grpc_slice_buffer *src, grpc_slice slice); #ifdef __cplusplus } #endif #endif /* GRPC_SLICE_BUFFER_H */ grpc-1.3.2/include/grpc/status.h000066400000000000000000000032211310511640000165070ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_STATUS_H #define GRPC_STATUS_H #include #endif /* GRPC_STATUS_H */ grpc-1.3.2/include/grpc/support/000077500000000000000000000000001310511640000165315ustar00rootroot00000000000000grpc-1.3.2/include/grpc/support/alloc.h000066400000000000000000000062731310511640000200040ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_ALLOC_H #define GRPC_SUPPORT_ALLOC_H #include #include #ifdef __cplusplus extern "C" { #endif typedef struct gpr_allocation_functions { void *(*malloc_fn)(size_t size); void *(*zalloc_fn)(size_t size); /* if NULL, uses malloc_fn then memset */ void *(*realloc_fn)(void *ptr, size_t size); void (*free_fn)(void *ptr); } gpr_allocation_functions; /* malloc. * If size==0, always returns NULL. Otherwise this function never returns NULL. * The pointer returned is suitably aligned for any kind of variable it could * contain. */ GPRAPI void *gpr_malloc(size_t size); /* like malloc, but zero all bytes before returning them */ GPRAPI void *gpr_zalloc(size_t size); /* free */ GPRAPI void gpr_free(void *ptr); /* realloc, never returns NULL */ GPRAPI void *gpr_realloc(void *p, size_t size); /* aligned malloc, never returns NULL, will align to 1 << alignment_log */ GPRAPI void *gpr_malloc_aligned(size_t size, size_t alignment_log); /* free memory allocated by gpr_malloc_aligned */ GPRAPI void gpr_free_aligned(void *ptr); /** Request the family of allocation functions in \a functions be used. NOTE * that this request will be honored in a *best effort* basis and that no * guarantees are made about the default functions (eg, malloc) being called. * The functions.free_fn implementation must be a no-op for NULL input. */ GPRAPI void gpr_set_allocation_functions(gpr_allocation_functions functions); /** Return the family of allocation functions currently in effect. */ GPRAPI gpr_allocation_functions gpr_get_allocation_functions(); #ifdef __cplusplus } #endif #endif /* GRPC_SUPPORT_ALLOC_H */ grpc-1.3.2/include/grpc/support/atm.h000066400000000000000000000032351310511640000174660ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_ATM_H #define GRPC_SUPPORT_ATM_H #include #endif /* GRPC_SUPPORT_ATM_H */ grpc-1.3.2/include/grpc/support/atm_gcc_atomic.h000066400000000000000000000033111310511640000216310ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_ATM_GCC_ATOMIC_H #define GRPC_SUPPORT_ATM_GCC_ATOMIC_H #include #endif /* GRPC_SUPPORT_ATM_GCC_ATOMIC_H */ grpc-1.3.2/include/grpc/support/atm_gcc_sync.h000066400000000000000000000033011310511640000213300ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_ATM_GCC_SYNC_H #define GRPC_SUPPORT_ATM_GCC_SYNC_H #include #endif /* GRPC_SUPPORT_ATM_GCC_SYNC_H */ grpc-1.3.2/include/grpc/support/atm_windows.h000066400000000000000000000032751310511640000212440ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_ATM_WINDOWS_H #define GRPC_SUPPORT_ATM_WINDOWS_H #include #endif /* GRPC_SUPPORT_ATM_WINDOWS_H */ grpc-1.3.2/include/grpc/support/avl.h000066400000000000000000000072751310511640000174770ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_AVL_H #define GRPC_SUPPORT_AVL_H #include /** internal node of an AVL tree */ typedef struct gpr_avl_node { gpr_refcount refs; void *key; void *value; struct gpr_avl_node *left; struct gpr_avl_node *right; long height; } gpr_avl_node; typedef struct gpr_avl_vtable { /** destroy a key */ void (*destroy_key)(void *key); /** copy a key, returning new value */ void *(*copy_key)(void *key); /** compare key1, key2; return <0 if key1 < key2, >0 if key1 > key2, 0 if key1 == key2 */ long (*compare_keys)(void *key1, void *key2); /** destroy a value */ void (*destroy_value)(void *value); /** copy a value */ void *(*copy_value)(void *value); } gpr_avl_vtable; /** "pointer" to an AVL tree - this is a reference counted object - use gpr_avl_ref to add a reference, gpr_avl_unref when done with a reference */ typedef struct gpr_avl { const gpr_avl_vtable *vtable; gpr_avl_node *root; } gpr_avl; /** create an immutable AVL tree */ GPRAPI gpr_avl gpr_avl_create(const gpr_avl_vtable *vtable); /** add a reference to an existing tree - returns the tree as a convenience */ GPRAPI gpr_avl gpr_avl_ref(gpr_avl avl); /** remove a reference to a tree - destroying it if there are no references left */ GPRAPI void gpr_avl_unref(gpr_avl avl); /** return a new tree with (key, value) added to avl. implicitly unrefs avl to allow easy chaining. if key exists in avl, the new tree's key entry updated (i.e. a duplicate is not created) */ GPRAPI gpr_avl gpr_avl_add(gpr_avl avl, void *key, void *value); /** return a new tree with key deleted implicitly unrefs avl to allow easy chaining. */ GPRAPI gpr_avl gpr_avl_remove(gpr_avl avl, void *key); /** lookup key, and return the associated value. does not mutate avl. returns NULL if key is not found. */ GPRAPI void *gpr_avl_get(gpr_avl avl, void *key); /** Return 1 if avl contains key, 0 otherwise; if it has the key, sets *value to its value*/ GPRAPI int gpr_avl_maybe_get(gpr_avl avl, void *key, void **value); /** Return 1 if avl is empty, 0 otherwise */ GPRAPI int gpr_avl_is_empty(gpr_avl avl); #endif /* GRPC_SUPPORT_AVL_H */ grpc-1.3.2/include/grpc/support/cmdline.h000066400000000000000000000077151310511640000203270ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_CMDLINE_H #define GRPC_SUPPORT_CMDLINE_H #include #ifdef __cplusplus extern "C" { #endif /* Simple command line parser. Supports flags that can be specified as -foo, --foo, --no-foo, -no-foo, etc And integers, strings that can be specified as -foo=4, -foo blah, etc No support for short command line options (but we may get that in the future.) Usage (for a program with a single flag argument 'foo'): int main(int argc, char **argv) { gpr_cmdline *cl; int verbose = 0; cl = gpr_cmdline_create("My cool tool"); gpr_cmdline_add_int(cl, "verbose", "Produce verbose output?", &verbose); gpr_cmdline_parse(cl, argc, argv); gpr_cmdline_destroy(cl); if (verbose) { gpr_log(GPR_INFO, "Goodbye cruel world!"); } return 0; } */ typedef struct gpr_cmdline gpr_cmdline; /* Construct a command line parser: takes a short description of the tool doing the parsing */ GPRAPI gpr_cmdline *gpr_cmdline_create(const char *description); /* Add an integer parameter, with a name (used on the command line) and some helpful text (used in the command usage) */ GPRAPI void gpr_cmdline_add_int(gpr_cmdline *cl, const char *name, const char *help, int *value); /* The same, for a boolean flag */ GPRAPI void gpr_cmdline_add_flag(gpr_cmdline *cl, const char *name, const char *help, int *value); /* And for a string */ GPRAPI void gpr_cmdline_add_string(gpr_cmdline *cl, const char *name, const char *help, char **value); /* Set a callback for non-named arguments */ GPRAPI void gpr_cmdline_on_extra_arg( gpr_cmdline *cl, const char *name, const char *help, void (*on_extra_arg)(void *user_data, const char *arg), void *user_data); /* Enable surviving failure: default behavior is to exit the process */ GPRAPI void gpr_cmdline_set_survive_failure(gpr_cmdline *cl); /* Parse the command line; returns 1 on success, on failure either dies (by default) or returns 0 if gpr_cmdline_set_survive_failure() has been called */ GPRAPI int gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv); /* Destroy the parser */ GPRAPI void gpr_cmdline_destroy(gpr_cmdline *cl); /* Get a string describing usage */ GPRAPI char *gpr_cmdline_usage_string(gpr_cmdline *cl, const char *argv0); #ifdef __cplusplus } #endif #endif /* GRPC_SUPPORT_CMDLINE_H */ grpc-1.3.2/include/grpc/support/cpu.h000066400000000000000000000043761310511640000175030ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_CPU_H #define GRPC_SUPPORT_CPU_H #include #ifdef __cplusplus extern "C" { #endif /* Interface providing CPU information for currently running system */ /* Return the number of CPU cores on the current system. Will return 0 if the information is not available. */ GPRAPI unsigned gpr_cpu_num_cores(void); /* Return the CPU on which the current thread is executing; N.B. This should be considered advisory only - it is possible that the thread is switched to a different CPU at any time. Returns a value in range [0, gpr_cpu_num_cores() - 1] */ GPRAPI unsigned gpr_cpu_current_cpu(void); #ifdef __cplusplus } // extern "C" #endif #endif /* GRPC_SUPPORT_CPU_H */ grpc-1.3.2/include/grpc/support/histogram.h000066400000000000000000000066101310511640000207020ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_HISTOGRAM_H #define GRPC_SUPPORT_HISTOGRAM_H #include #include #ifdef __cplusplus extern "C" { #endif typedef struct gpr_histogram gpr_histogram; GPRAPI gpr_histogram *gpr_histogram_create(double resolution, double max_bucket_start); GPRAPI void gpr_histogram_destroy(gpr_histogram *h); GPRAPI void gpr_histogram_add(gpr_histogram *h, double x); /* The following merges the second histogram into the first. It only works if they have the same buckets and resolution. Returns 0 on failure, 1 on success */ GPRAPI int gpr_histogram_merge(gpr_histogram *dst, const gpr_histogram *src); GPRAPI double gpr_histogram_percentile(gpr_histogram *histogram, double percentile); GPRAPI double gpr_histogram_mean(gpr_histogram *histogram); GPRAPI double gpr_histogram_stddev(gpr_histogram *histogram); GPRAPI double gpr_histogram_variance(gpr_histogram *histogram); GPRAPI double gpr_histogram_maximum(gpr_histogram *histogram); GPRAPI double gpr_histogram_minimum(gpr_histogram *histogram); GPRAPI double gpr_histogram_count(gpr_histogram *histogram); GPRAPI double gpr_histogram_sum(gpr_histogram *histogram); GPRAPI double gpr_histogram_sum_of_squares(gpr_histogram *histogram); GPRAPI const uint32_t *gpr_histogram_get_contents(gpr_histogram *histogram, size_t *count); GPRAPI void gpr_histogram_merge_contents(gpr_histogram *histogram, const uint32_t *data, size_t data_count, double min_seen, double max_seen, double sum, double sum_of_squares, double count); #ifdef __cplusplus } #endif #endif /* GRPC_SUPPORT_HISTOGRAM_H */ grpc-1.3.2/include/grpc/support/host_port.h000066400000000000000000000052431310511640000207270ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_HOST_PORT_H #define GRPC_SUPPORT_HOST_PORT_H #include #ifdef __cplusplus extern "C" { #endif /* Given a host and port, creates a newly-allocated string of the form "host:port" or "[ho:st]:port", depending on whether the host contains colons like an IPv6 literal. If the host is already bracketed, then additional brackets will not be added. Usage is similar to gpr_asprintf: returns the number of bytes written (excluding the final '\0'), and *out points to a string which must later be destroyed using gpr_free(). In the unlikely event of an error, returns -1 and sets *out to NULL. */ GPRAPI int gpr_join_host_port(char **out, const char *host, int port); /* Given a name in the form "host:port" or "[ho:st]:port", split into hostname and port number, into newly allocated strings, which must later be destroyed using gpr_free(). Return 1 on success, 0 on failure. Guarantees *host and *port == NULL on failure. */ GPRAPI int gpr_split_host_port(const char *name, char **host, char **port); #ifdef __cplusplus } #endif #endif /* GRPC_SUPPORT_HOST_PORT_H */ grpc-1.3.2/include/grpc/support/log.h000066400000000000000000000103011310511640000174560ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_LOG_H #define GRPC_SUPPORT_LOG_H #include #include #include /* for abort() */ #include #ifdef __cplusplus extern "C" { #endif /* GPR log API. Usage (within grpc): int argument1 = 3; char* argument2 = "hello"; gpr_log(GPR_DEBUG, "format string %d", argument1); gpr_log(GPR_INFO, "hello world"); gpr_log(GPR_ERROR, "%d %s!!", argument1, argument2); */ /* The severity of a log message - use the #defines below when calling into gpr_log to additionally supply file and line data */ typedef enum gpr_log_severity { GPR_LOG_SEVERITY_DEBUG, GPR_LOG_SEVERITY_INFO, GPR_LOG_SEVERITY_ERROR } gpr_log_severity; #define GPR_LOG_VERBOSITY_UNSET -1 /* Returns a string representation of the log severity */ const char *gpr_log_severity_string(gpr_log_severity severity); /* Macros to build log contexts at various severity levels */ #define GPR_DEBUG __FILE__, __LINE__, GPR_LOG_SEVERITY_DEBUG #define GPR_INFO __FILE__, __LINE__, GPR_LOG_SEVERITY_INFO #define GPR_ERROR __FILE__, __LINE__, GPR_LOG_SEVERITY_ERROR /* Log a message. It's advised to use GPR_xxx above to generate the context * for each message */ GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format, ...) GPR_PRINT_FORMAT_CHECK(4, 5); GPRAPI void gpr_log_message(const char *file, int line, gpr_log_severity severity, const char *message); /* Set global log verbosity */ GPRAPI void gpr_set_log_verbosity(gpr_log_severity min_severity_to_print); GPRAPI void gpr_log_verbosity_init(); /* Log overrides: applications can use this API to intercept logging calls and use their own implementations */ typedef struct { const char *file; int line; gpr_log_severity severity; const char *message; } gpr_log_func_args; typedef void (*gpr_log_func)(gpr_log_func_args *args); GPRAPI void gpr_set_log_function(gpr_log_func func); /* abort() the process if x is zero, having written a line to the log. Intended for internal invariants. If the error can be recovered from, without the possibility of corruption, or might best be reflected via an exception in a higher-level language, consider returning error code. */ #define GPR_ASSERT(x) \ do { \ if (!(x)) { \ gpr_log(GPR_ERROR, "assertion failed: %s", #x); \ abort(); \ } \ } while (0) #ifdef __cplusplus } #endif #endif /* GRPC_SUPPORT_LOG_H */ grpc-1.3.2/include/grpc/support/log_windows.h000066400000000000000000000037601310511640000212430ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_LOG_WINDOWS_H #define GRPC_SUPPORT_LOG_WINDOWS_H #include #ifdef __cplusplus extern "C" { #endif /* Returns a string allocated with gpr_malloc that contains a UTF-8 * formatted error message, corresponding to the error messageid. * Use in conjunction with GetLastError() et al. */ GPRAPI char *gpr_format_message(int messageid); #ifdef __cplusplus } #endif #endif /* GRPC_SUPPORT_LOG_WINDOWS_H */ grpc-1.3.2/include/grpc/support/port_platform.h000066400000000000000000000033051310511640000215730ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_PORT_PLATFORM_H #define GRPC_SUPPORT_PORT_PLATFORM_H #include #endif /* GRPC_SUPPORT_PORT_PLATFORM_H */ grpc-1.3.2/include/grpc/support/string_util.h000066400000000000000000000046211310511640000212500ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_STRING_UTIL_H #define GRPC_SUPPORT_STRING_UTIL_H #include #ifdef __cplusplus extern "C" { #endif /* String utility functions */ /* Returns a copy of src that can be passed to gpr_free(). If allocation fails or if src is NULL, returns NULL. */ GPRAPI char *gpr_strdup(const char *src); /* printf to a newly-allocated string. The set of supported formats may vary between platforms. On success, returns the number of bytes printed (excluding the final '\0'), and *strp points to a string which must later be destroyed with gpr_free(). On error, returns -1 and sets *strp to NULL. If the format string is bad, the result is undefined. */ GPRAPI int gpr_asprintf(char **strp, const char *format, ...) GPR_PRINT_FORMAT_CHECK(2, 3); #ifdef __cplusplus } #endif #endif /* GRPC_SUPPORT_STRING_UTIL_H */ grpc-1.3.2/include/grpc/support/subprocess.h000066400000000000000000000043561310511640000211020ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_SUBPROCESS_H #define GRPC_SUPPORT_SUBPROCESS_H #include #ifdef __cplusplus extern "C" { #endif typedef struct gpr_subprocess gpr_subprocess; /* .exe on windows, empty on unices */ GPRAPI const char *gpr_subprocess_binary_extension(); GPRAPI gpr_subprocess *gpr_subprocess_create(int argc, const char **argv); /* if subprocess has not been joined, kill it */ GPRAPI void gpr_subprocess_destroy(gpr_subprocess *p); /* returns exit status; can be called at most once */ GPRAPI int gpr_subprocess_join(gpr_subprocess *p); GPRAPI void gpr_subprocess_interrupt(gpr_subprocess *p); #ifdef __cplusplus } // extern "C" #endif #endif /* GRPC_SUPPORT_SUBPROCESS_H */ grpc-1.3.2/include/grpc/support/sync.h000066400000000000000000000271451310511640000176670ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_SYNC_H #define GRPC_SUPPORT_SYNC_H #include /* for gpr_timespec */ #include #ifdef __cplusplus extern "C" { #endif /* --- Mutex interface --- At most one thread may hold an exclusive lock on a mutex at any given time. Actions taken by a thread that holds a mutex exclusively happen after actions taken by all previous holders of the mutex. Variables of type gpr_mu are uninitialized when first declared. */ /* Initialize *mu. Requires: *mu uninitialized. */ GPRAPI void gpr_mu_init(gpr_mu *mu); /* Cause *mu no longer to be initialized, freeing any memory in use. Requires: *mu initialized; no other concurrent operation on *mu. */ GPRAPI void gpr_mu_destroy(gpr_mu *mu); /* Wait until no thread has a lock on *mu, cause the calling thread to own an exclusive lock on *mu, then return. May block indefinitely or crash if the calling thread has a lock on *mu. Requires: *mu initialized. */ GPRAPI void gpr_mu_lock(gpr_mu *mu); /* Release an exclusive lock on *mu held by the calling thread. Requires: *mu initialized; the calling thread holds an exclusive lock on *mu. */ GPRAPI void gpr_mu_unlock(gpr_mu *mu); /* Without blocking, attempt to acquire an exclusive lock on *mu for the calling thread, then return non-zero iff success. Fail, if any thread holds the lock; succeeds with high probability if no thread holds the lock. Requires: *mu initialized. */ GPRAPI int gpr_mu_trylock(gpr_mu *mu); /* --- Condition variable interface --- A while-loop should be used with gpr_cv_wait() when waiting for conditions to become true. See the example below. Variables of type gpr_cv are uninitialized when first declared. */ /* Initialize *cv. Requires: *cv uninitialized. */ GPRAPI void gpr_cv_init(gpr_cv *cv); /* Cause *cv no longer to be initialized, freeing any memory in use. Requires: *cv initialized; no other concurrent operation on *cv.*/ GPRAPI void gpr_cv_destroy(gpr_cv *cv); /* Atomically release *mu and wait on *cv. When the calling thread is woken from *cv or the deadline abs_deadline is exceeded, execute gpr_mu_lock(mu) and return whether the deadline was exceeded. Use abs_deadline==gpr_inf_future for no deadline. abs_deadline can be either an absolute deadline, or a GPR_TIMESPAN. May return even when not woken explicitly. Requires: *mu and *cv initialized; the calling thread holds an exclusive lock on *mu. */ GPRAPI int gpr_cv_wait(gpr_cv *cv, gpr_mu *mu, gpr_timespec abs_deadline); /* If any threads are waiting on *cv, wake at least one. Clients may treat this as an optimization of gpr_cv_broadcast() for use in the case where waking more than one waiter is not useful. Requires: *cv initialized. */ GPRAPI void gpr_cv_signal(gpr_cv *cv); /* Wake all threads waiting on *cv. Requires: *cv initialized. */ GPRAPI void gpr_cv_broadcast(gpr_cv *cv); /* --- One-time initialization --- gpr_once must be declared with static storage class, and initialized with GPR_ONCE_INIT. e.g., static gpr_once once_var = GPR_ONCE_INIT; */ /* Ensure that (*init_routine)() has been called exactly once (for the specified gpr_once instance) and then return. If multiple threads call gpr_once() on the same gpr_once instance, one of them will call (*init_routine)(), and the others will block until that call finishes.*/ GPRAPI void gpr_once_init(gpr_once *once, void (*init_routine)(void)); /* --- One-time event notification --- These operations act on a gpr_event, which should be initialized with gpr_ev_init(), or with GPR_EVENT_INIT if static, e.g., static gpr_event event_var = GPR_EVENT_INIT; It requires no destruction. */ /* Initialize *ev. */ GPRAPI void gpr_event_init(gpr_event *ev); /* Set *ev so that gpr_event_get() and gpr_event_wait() will return value. Requires: *ev initialized; value != NULL; no prior or concurrent calls to gpr_event_set(ev, ...) since initialization. */ GPRAPI void gpr_event_set(gpr_event *ev, void *value); /* Return the value set by gpr_event_set(ev, ...), or NULL if no such call has completed. If the result is non-NULL, all operations that occurred prior to the gpr_event_set(ev, ...) set will be visible after this call returns. Requires: *ev initialized. This operation is faster than acquiring a mutex on most platforms. */ GPRAPI void *gpr_event_get(gpr_event *ev); /* Wait until *ev is set by gpr_event_set(ev, ...), or abs_deadline is exceeded, then return gpr_event_get(ev). Requires: *ev initialized. Use abs_deadline==gpr_inf_future for no deadline. When the event has been signalled before the call, this operation is faster than acquiring a mutex on most platforms. */ GPRAPI void *gpr_event_wait(gpr_event *ev, gpr_timespec abs_deadline); /* --- Reference counting --- These calls act on the type gpr_refcount. It requires no destruction. */ /* Initialize *r to value n. */ GPRAPI void gpr_ref_init(gpr_refcount *r, int n); /* Increment the reference count *r. Requires *r initialized. */ GPRAPI void gpr_ref(gpr_refcount *r); /* Increment the reference count *r. Requires *r initialized. Crashes if refcount is zero */ GPRAPI void gpr_ref_non_zero(gpr_refcount *r); /* Increment the reference count *r by n. Requires *r initialized, n > 0. */ GPRAPI void gpr_refn(gpr_refcount *r, int n); /* Decrement the reference count *r and return non-zero iff it has reached zero. . Requires *r initialized. */ GPRAPI int gpr_unref(gpr_refcount *r); /* Return non-zero iff the reference count of *r is one, and thus is owned by exactly one object. */ GPRAPI int gpr_ref_is_unique(gpr_refcount *r); /* --- Stats counters --- These calls act on the integral type gpr_stats_counter. It requires no destruction. Static instances may be initialized with gpr_stats_counter c = GPR_STATS_INIT; Beware: These operations do not imply memory barriers. Do not use them to synchronize other events. */ /* Initialize *c to the value n. */ GPRAPI void gpr_stats_init(gpr_stats_counter *c, intptr_t n); /* *c += inc. Requires: *c initialized. */ GPRAPI void gpr_stats_inc(gpr_stats_counter *c, intptr_t inc); /* Return *c. Requires: *c initialized. */ GPRAPI intptr_t gpr_stats_read(const gpr_stats_counter *c); /* ==================Example use of interface=================== A producer-consumer queue of up to N integers, illustrating the use of the calls in this interface. */ #if 0 #define N 4 typedef struct queue { gpr_cv non_empty; /* Signalled when length becomes non-zero. */ gpr_cv non_full; /* Signalled when length becomes non-N. */ gpr_mu mu; /* Protects all fields below. (That is, except during initialization or destruction, the fields below should be accessed only by a thread that holds mu.) */ int head; /* Index of head of queue 0..N-1. */ int length; /* Number of valid elements in queue 0..N. */ int elem[N]; /* elem[head .. head+length-1] are queue elements. */ } queue; /* Initialize *q. */ void queue_init(queue *q) { gpr_mu_init(&q->mu); gpr_cv_init(&q->non_empty); gpr_cv_init(&q->non_full); q->head = 0; q->length = 0; } /* Free storage associated with *q. */ void queue_destroy(queue *q) { gpr_mu_destroy(&q->mu); gpr_cv_destroy(&q->non_empty); gpr_cv_destroy(&q->non_full); } /* Wait until there is room in *q, then append x to *q. */ void queue_append(queue *q, int x) { gpr_mu_lock(&q->mu); /* To wait for a predicate without a deadline, loop on the negation of the predicate, and use gpr_cv_wait(..., gpr_inf_future) inside the loop to release the lock, wait, and reacquire on each iteration. Code that makes the condition true should use gpr_cv_broadcast() on the corresponding condition variable. The predicate must be on state protected by the lock. */ while (q->length == N) { gpr_cv_wait(&q->non_full, &q->mu, gpr_inf_future); } if (q->length == 0) { /* Wake threads blocked in queue_remove(). */ /* It's normal to use gpr_cv_broadcast() or gpr_signal() while holding the lock. */ gpr_cv_broadcast(&q->non_empty); } q->elem[(q->head + q->length) % N] = x; q->length++; gpr_mu_unlock(&q->mu); } /* If it can be done without blocking, append x to *q and return non-zero. Otherwise return 0. */ int queue_try_append(queue *q, int x) { int result = 0; if (gpr_mu_trylock(&q->mu)) { if (q->length != N) { if (q->length == 0) { /* Wake threads blocked in queue_remove(). */ gpr_cv_broadcast(&q->non_empty); } q->elem[(q->head + q->length) % N] = x; q->length++; result = 1; } gpr_mu_unlock(&q->mu); } return result; } /* Wait until the *q is non-empty or deadline abs_deadline passes. If the queue is non-empty, remove its head entry, place it in *head, and return non-zero. Otherwise return 0. */ int queue_remove(queue *q, int *head, gpr_timespec abs_deadline) { int result = 0; gpr_mu_lock(&q->mu); /* To wait for a predicate with a deadline, loop on the negation of the predicate or until gpr_cv_wait() returns true. Code that makes the condition true should use gpr_cv_broadcast() on the corresponding condition variable. The predicate must be on state protected by the lock. */ while (q->length == 0 && !gpr_cv_wait(&q->non_empty, &q->mu, abs_deadline)) { } if (q->length != 0) { /* Queue is non-empty. */ result = 1; if (q->length == N) { /* Wake threads blocked in queue_append(). */ gpr_cv_broadcast(&q->non_full); } *head = q->elem[q->head]; q->head = (q->head + 1) % N; q->length--; } /* else deadline exceeded */ gpr_mu_unlock(&q->mu); return result; } #endif /* 0 */ #ifdef __cplusplus } #endif #endif /* GRPC_SUPPORT_SYNC_H */ grpc-1.3.2/include/grpc/support/sync_generic.h000066400000000000000000000033011310511640000213470ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_SYNC_GENERIC_H #define GRPC_SUPPORT_SYNC_GENERIC_H #include #endif /* GRPC_SUPPORT_SYNC_GENERIC_H */ grpc-1.3.2/include/grpc/support/sync_posix.h000066400000000000000000000032711310511640000211030ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_SYNC_POSIX_H #define GRPC_SUPPORT_SYNC_POSIX_H #include #endif /* GRPC_SUPPORT_SYNC_POSIX_H */ grpc-1.3.2/include/grpc/support/sync_windows.h000066400000000000000000000033011310511640000214250ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_SYNC_WINDOWS_H #define GRPC_SUPPORT_SYNC_WINDOWS_H #include #endif /* GRPC_SUPPORT_SYNC_WINDOWS_H */ grpc-1.3.2/include/grpc/support/thd.h000066400000000000000000000067641310511640000174760ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_THD_H #define GRPC_SUPPORT_THD_H /* Thread interface for GPR. Types gpr_thd_id a thread identifier. (Currently no calls take a thread identifier. It exists for future extensibility.) gpr_thd_options options used when creating a thread */ #include #ifdef __cplusplus extern "C" { #endif typedef uintptr_t gpr_thd_id; /* Thread creation options. */ typedef struct { int flags; /* Opaque field. Get and set with accessors below. */ } gpr_thd_options; /* Create a new thread running (*thd_body)(arg) and place its thread identifier in *t, and return true. If there are insufficient resources, return false. If options==NULL, default options are used. The thread is immediately runnable, and exits when (*thd_body)() returns. */ GPRAPI int gpr_thd_new(gpr_thd_id *t, void (*thd_body)(void *arg), void *arg, const gpr_thd_options *options); /* Return a gpr_thd_options struct with all fields set to defaults. */ GPRAPI gpr_thd_options gpr_thd_options_default(void); /* Set the thread to become detached on startup - this is the default. */ GPRAPI void gpr_thd_options_set_detached(gpr_thd_options *options); /* Set the thread to become joinable - mutually exclusive with detached. */ GPRAPI void gpr_thd_options_set_joinable(gpr_thd_options *options); /* Returns non-zero if the option detached is set. */ GPRAPI int gpr_thd_options_is_detached(const gpr_thd_options *options); /* Returns non-zero if the option joinable is set. */ GPRAPI int gpr_thd_options_is_joinable(const gpr_thd_options *options); /* Returns the identifier of the current thread. */ GPRAPI gpr_thd_id gpr_thd_currentid(void); /* Blocks until the specified thread properly terminates. Calling this on a detached thread has unpredictable results. */ GPRAPI void gpr_thd_join(gpr_thd_id t); #ifdef __cplusplus } #endif #endif /* GRPC_SUPPORT_THD_H */ grpc-1.3.2/include/grpc/support/time.h000066400000000000000000000100701310511640000176360ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_TIME_H #define GRPC_SUPPORT_TIME_H #include #include #include #ifdef __cplusplus extern "C" { #endif /* Time constants. */ GPRAPI gpr_timespec gpr_time_0(gpr_clock_type type); /* The zero time interval. */ GPRAPI gpr_timespec gpr_inf_future(gpr_clock_type type); /* The far future */ GPRAPI gpr_timespec gpr_inf_past(gpr_clock_type type); /* The far past. */ #define GPR_MS_PER_SEC 1000 #define GPR_US_PER_SEC 1000000 #define GPR_NS_PER_SEC 1000000000 #define GPR_NS_PER_MS 1000000 #define GPR_NS_PER_US 1000 #define GPR_US_PER_MS 1000 /* initialize time subsystem */ GPRAPI void gpr_time_init(void); /* Return the current time measured from the given clocks epoch. */ GPRAPI gpr_timespec gpr_now(gpr_clock_type clock); /* Convert a timespec from one clock to another */ GPRAPI gpr_timespec gpr_convert_clock_type(gpr_timespec t, gpr_clock_type target_clock); /* Return -ve, 0, or +ve according to whether a < b, a == b, or a > b respectively. */ GPRAPI int gpr_time_cmp(gpr_timespec a, gpr_timespec b); GPRAPI gpr_timespec gpr_time_max(gpr_timespec a, gpr_timespec b); GPRAPI gpr_timespec gpr_time_min(gpr_timespec a, gpr_timespec b); /* Add and subtract times. Calculations saturate at infinities. */ GPRAPI gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b); GPRAPI gpr_timespec gpr_time_sub(gpr_timespec a, gpr_timespec b); /* Return a timespec representing a given number of time units. INT64_MIN is interpreted as gpr_inf_past, and INT64_MAX as gpr_inf_future. */ GPRAPI gpr_timespec gpr_time_from_micros(int64_t x, gpr_clock_type clock_type); GPRAPI gpr_timespec gpr_time_from_nanos(int64_t x, gpr_clock_type clock_type); GPRAPI gpr_timespec gpr_time_from_millis(int64_t x, gpr_clock_type clock_type); GPRAPI gpr_timespec gpr_time_from_seconds(int64_t x, gpr_clock_type clock_type); GPRAPI gpr_timespec gpr_time_from_minutes(int64_t x, gpr_clock_type clock_type); GPRAPI gpr_timespec gpr_time_from_hours(int64_t x, gpr_clock_type clock_type); GPRAPI int32_t gpr_time_to_millis(gpr_timespec timespec); /* Return 1 if two times are equal or within threshold of each other, 0 otherwise */ GPRAPI int gpr_time_similar(gpr_timespec a, gpr_timespec b, gpr_timespec threshold); /* Sleep until at least 'until' - an absolute timeout */ GPRAPI void gpr_sleep_until(gpr_timespec until); GPRAPI double gpr_timespec_to_micros(gpr_timespec t); #ifdef __cplusplus } #endif #endif /* GRPC_SUPPORT_TIME_H */ grpc-1.3.2/include/grpc/support/tls.h000066400000000000000000000050231310511640000175040ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_TLS_H #define GRPC_SUPPORT_TLS_H #include /* Thread local storage. A minimal wrapper that should be implementable across many compilers, and implementable efficiently across most modern compilers. Thread locals have type intptr_t. Declaring a thread local variable 'foo': GPR_TLS_DECL(foo); Thread locals always have static scope. Initializing a thread local (must be done at library initialization time): gpr_tls_init(&foo); Destroying a thread local: gpr_tls_destroy(&foo); Setting a thread local (returns new_value): gpr_tls_set(&foo, new_value); Accessing a thread local: current_value = gpr_tls_get(&foo); ALL functions here may be implemented as macros. */ #ifdef GPR_GCC_TLS #include #endif #ifdef GPR_MSVC_TLS #include #endif #ifdef GPR_PTHREAD_TLS #include #endif #endif /* GRPC_SUPPORT_TLS_H */ grpc-1.3.2/include/grpc/support/tls_gcc.h000066400000000000000000000063051310511640000203240ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_TLS_GCC_H #define GRPC_SUPPORT_TLS_GCC_H #include #include /* Thread local storage based on gcc compiler primitives. #include tls.h to use this - and see that file for documentation */ #ifndef NDEBUG struct gpr_gcc_thread_local { intptr_t value; bool *inited; }; #define GPR_TLS_DECL(name) \ static bool name##_inited = false; \ static __thread struct gpr_gcc_thread_local name = {0, &(name##_inited)} #define gpr_tls_init(tls) \ do { \ GPR_ASSERT(*((tls)->inited) == false); \ *((tls)->inited) = true; \ } while (0) /* It is allowed to call gpr_tls_init after gpr_tls_destroy is called. */ #define gpr_tls_destroy(tls) \ do { \ GPR_ASSERT(*((tls)->inited)); \ *((tls)->inited) = false; \ } while (0) #define gpr_tls_set(tls, new_value) \ do { \ GPR_ASSERT(*((tls)->inited)); \ (tls)->value = (new_value); \ } while (0) #define gpr_tls_get(tls) \ ({ \ GPR_ASSERT(*((tls)->inited)); \ (tls)->value; \ }) #else /* NDEBUG */ struct gpr_gcc_thread_local { intptr_t value; }; #define GPR_TLS_DECL(name) \ static __thread struct gpr_gcc_thread_local name = {0} #define gpr_tls_init(tls) \ do { \ } while (0) #define gpr_tls_destroy(tls) \ do { \ } while (0) #define gpr_tls_set(tls, new_value) (((tls)->value) = (new_value)) #define gpr_tls_get(tls) ((tls)->value) #endif /* NDEBUG */ #endif /* GRPC_SUPPORT_TLS_GCC_H */ grpc-1.3.2/include/grpc/support/tls_msvc.h000066400000000000000000000042471310511640000205430ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_TLS_MSVC_H #define GRPC_SUPPORT_TLS_MSVC_H /* Thread local storage based on ms visual c compiler primitives. #include tls.h to use this - and see that file for documentation */ struct gpr_msvc_thread_local { intptr_t value; }; #define GPR_TLS_DECL(name) \ static __declspec(thread) struct gpr_msvc_thread_local name = {0} #define gpr_tls_init(tls) \ do { \ } while (0) #define gpr_tls_destroy(tls) \ do { \ } while (0) #define gpr_tls_set(tls, new_value) (((tls)->value) = (new_value)) #define gpr_tls_get(tls) ((tls)->value) #endif /* GRPC_SUPPORT_TLS_MSVC_H */ grpc-1.3.2/include/grpc/support/tls_pthread.h000066400000000000000000000045051310511640000212170ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_TLS_PTHREAD_H #define GRPC_SUPPORT_TLS_PTHREAD_H #include /* for GPR_ASSERT */ #include /* Thread local storage based on pthread library calls. #include tls.h to use this - and see that file for documentation */ struct gpr_pthread_thread_local { pthread_key_t key; }; #define GPR_TLS_DECL(name) static struct gpr_pthread_thread_local name = {0} #define gpr_tls_init(tls) GPR_ASSERT(0 == pthread_key_create(&(tls)->key, NULL)) #define gpr_tls_destroy(tls) pthread_key_delete((tls)->key) #define gpr_tls_get(tls) ((intptr_t)pthread_getspecific((tls)->key)) #ifdef __cplusplus extern "C" { #endif intptr_t gpr_tls_set(struct gpr_pthread_thread_local *tls, intptr_t value); #ifdef __cplusplus } #endif #endif /* GRPC_SUPPORT_TLS_PTHREAD_H */ grpc-1.3.2/include/grpc/support/useful.h000066400000000000000000000062221310511640000202070ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_SUPPORT_USEFUL_H #define GRPC_SUPPORT_USEFUL_H /* useful macros that don't belong anywhere else */ #define GPR_MIN(a, b) ((a) < (b) ? (a) : (b)) #define GPR_MAX(a, b) ((a) > (b) ? (a) : (b)) #define GPR_CLAMP(a, min, max) ((a) < (min) ? (min) : (a) > (max) ? (max) : (a)) /* rotl, rotr assume x is unsigned */ #define GPR_ROTL(x, n) (((x) << (n)) | ((x) >> (sizeof(x) * 8 - (n)))) #define GPR_ROTR(x, n) (((x) >> (n)) | ((x) << (sizeof(x) * 8 - (n)))) #define GPR_ARRAY_SIZE(array) (sizeof(array) / sizeof(*(array))) #define GPR_SWAP(type, a, b) \ do { \ type x = a; \ a = b; \ b = x; \ } while (0) /** Set the \a n-th bit of \a i (a mutable pointer). */ #define GPR_BITSET(i, n) ((*(i)) |= (1u << (n))) /** Clear the \a n-th bit of \a i (a mutable pointer). */ #define GPR_BITCLEAR(i, n) ((*(i)) &= ~(1u << (n))) /** Get the \a n-th bit of \a i */ #define GPR_BITGET(i, n) (((i) & (1u << (n))) != 0) #define GPR_INTERNAL_HEXDIGIT_BITCOUNT(x) \ ((x) - (((x) >> 1) & 0x77777777) - (((x) >> 2) & 0x33333333) - \ (((x) >> 3) & 0x11111111)) /** Returns number of bits set in bitset \a i */ #define GPR_BITCOUNT(i) \ (((GPR_INTERNAL_HEXDIGIT_BITCOUNT(i) + \ (GPR_INTERNAL_HEXDIGIT_BITCOUNT(i) >> 4)) & \ 0x0f0f0f0f) % \ 255) #define GPR_ICMP(a, b) ((a) < (b) ? -1 : ((a) > (b) ? 1 : 0)) #define GPR_HASH_POINTER(x, range) \ ((((size_t)x) >> 4) ^ (((size_t)x) >> 9) ^ (((size_t)x) >> 14)) % (range) #endif /* GRPC_SUPPORT_USEFUL_H */ grpc-1.3.2/package.json000066400000000000000000000053501310511640000147300ustar00rootroot00000000000000{ "name": "grpc", "version": "1.3.2", "author": "Google Inc.", "description": "gRPC Library for Node", "homepage": "http://www.grpc.io/", "repository": { "type": "git", "url": "https://github.com/grpc/grpc.git" }, "bugs": "https://github.com/grpc/grpc/issues", "contributors": [ { "name": "Michael Lumish", "email": "mlumish@google.com" } ], "directories": { "lib": "src/node/src" }, "scripts": { "lint": "node ./node_modules/jshint/bin/jshint src/node/src src/node/test src/node/interop src/node/index.js --exclude-path=src/node/.jshintignore", "test": "./node_modules/.bin/mocha src/node/test && npm run-script lint", "electron-build": "./node_modules/.bin/node-pre-gyp configure build --runtime=electron --disturl=https://atom.io/download/atom-shell", "gen_docs": "./node_modules/.bin/jsdoc -c src/node/jsdoc_conf.json", "coverage": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha src/node/test", "install": "./node_modules/.bin/node-pre-gyp install --fallback-to-build --library=static_library" }, "bundledDependencies": [ "node-pre-gyp" ], "dependencies": { "arguejs": "^0.2.3", "lodash": "^4.15.0", "nan": "^2.0.0", "node-pre-gyp": "^0.6.0", "protobufjs": "^5.0.0" }, "devDependencies": { "async": "^2.0.1", "body-parser": "^1.15.2", "electron-mocha": "^3.1.1", "express": "^4.14.0", "google-auth-library": "^0.9.2", "google-protobuf": "^3.0.0", "istanbul": "^0.4.4", "jsdoc": "^3.3.2", "jshint": "^2.5.0", "minimist": "^1.1.0", "mocha": "^3.0.2", "mocha-jenkins-reporter": "^0.2.3", "poisson-process": "^0.2.1" }, "engines": { "node": ">=4" }, "binary": { "module_name": "grpc_node", "module_path": "src/node/extension_binary", "host": "https://storage.googleapis.com/", "remote_path": "grpc-precompiled-binaries/node/{name}/v{version}", "package_name": "{node_abi}-{platform}-{arch}.tar.gz" }, "files": [ "LICENSE", "src/node/README.md", "src/proto", "etc", "src/node/index.js", "src/node/src", "src/node/ext", "include/grpc", "src/core", "src/boringssl", "src/zlib", "third_party/nanopb", "third_party/zlib", "third_party/boringssl", "binding.gyp" ], "main": "src/node/index.js", "license": "BSD-3-Clause", "jshintConfig": { "bitwise": true, "curly": true, "eqeqeq": true, "esnext": true, "freeze": true, "immed": true, "indent": 2, "latedef": "nofunc", "maxlen": 80, "mocha": true, "newcap": true, "node": true, "noarg": true, "quotmark": "single", "strict": true, "trailing": true, "undef": true, "unused": "vars" } } grpc-1.3.2/package.xml000066400000000000000000003040741310511640000145640ustar00rootroot00000000000000 grpc pecl.php.net A high performance, open source, general RPC framework that puts mobile and HTTP/2 first. Remote Procedure Calls (RPCs) provide a useful abstraction for building distributed applications and services. The libraries in this repository provide a concrete implementation of the gRPC protocol, layered over HTTP/2. These libraries enable communication between clients and servers using any combination of the supported languages. Stanley Cheung stanleycheung grpc-packages@google.com yes 2017-05-05 1.3.2 1.3.2 beta beta BSD - Fixed some memory leaks #9559, #10996 5.5.0 1.4.0 grpc 0.5.0 0.5.0 alpha alpha 2015-06-16 BSD First alpha release 0.5.1 0.5.1 alpha alpha 2015-07-09 BSD Update to wrap gRPC C Core version 0.10.0 0.6.0 0.6.0 beta beta 2015-09-24 BSD - support per message compression disable - expose per-call host override option - expose connectivity API - expose channel target and call peer - add user-agent - update to wrap gRPC C core library beta version 0.11.0 0.6.1 0.6.0 beta beta 2015-10-21 BSD - fixed undefined constant fatal error when run with apache/nginx #2275 0.7.0 0.7.0 beta beta 2016-01-13 BSD - Breaking change to Credentials class (removed) #3765 - Replaced by ChannelCredentials and CallCredentials class #3765 - New plugin based metadata auth API #4394 - Explicit ChannelCredentials::createInsecure() call 0.8.0 0.8.0 beta beta 2016-02-24 BSD - Simplify gRPC PHP installation #4517 - Wrap gRPC core library version 0.13 0.8.1 0.8.1 beta beta 2016-03-01 BSD - Increase unit test code coverage #5225 0.14.0 0.14.0 beta beta 2016-04-19 BSD - wrap grpc C core version 0.14.0 - destroy grpc_byte_buffer after startBatch #6096 0.15.0 0.15.0 beta beta 2016-05-18 BSD - Updated functions with TSRM macros for ZTS support #6607 - Load default roots.pem via grpc_set_ssl_roots_override_callback #6848 1.0.0RC1 1.0.0RC1 stable stable 2016-07-13 BSD - GA release - Fix shutdown hang problem #4017 1.0.0RC2 1.0.0RC2 stable stable 2016-07-21 BSD - PHP7 Support #7464 1.0.0RC3 1.0.0RC3 stable stable 2016-07-28 BSD - PHP7 Support continued, reduce code duplication #7543 1.0.0RC4 1.0.0RC4 stable stable 2016-08-09 BSD - Fixed Ubuntu compile error #7571, #7642 1.0.0 1.0.0 stable stable 2016-08-18 BSD - gRPC 1.0.0 release 1.0.1RC1 1.0.1RC1 beta beta 2016-10-06 BSD - Reject metadata keys which are not legal #7881 1.0.1 1.0.1 stable stable 2016-10-27 BSD - Reject metadata keys which are not legal #7881 1.1.0RC1 1.1.0RC1 beta beta 2017-01-13 BSD - PHP Proto3 adoption #8179 - Various bug fixes 1.1.0 1.1.0 stable stable 2017-01-31 BSD - PHP Proto3 adoption #8179 - Various bug fixes 1.2.0RC1 1.2.0RC1 beta beta 2017-03-01 BSD - Added arg info macros #9751 - Updated codegen to be consistent with protobuf #9492 1.2.0 1.2.0 stable stable 2017-03-20 BSD - Added arg info macros #9751 - Updated codegen to be consistent with protobuf #9492 grpc-1.3.2/requirements.txt000066400000000000000000000001771310511640000157300ustar00rootroot00000000000000# GRPC Python setup requirements coverage>=4.0 cython>=0.23 enum34>=1.0.4 futures>=2.2.0 protobuf>=3.2.0 six>=1.10 wheel>=0.29 grpc-1.3.2/setup.cfg000066400000000000000000000003771310511640000142670ustar00rootroot00000000000000# Setup settings for GRPC Python [coverage:run] plugins = Cython.Coverage [build] build_base=python_build [build_ext] inplace=1 [build_package_protos] exclude=.*protoc_plugin/protoc_plugin_test\.proto$ # Style settings [yapf] based_on_style = google grpc-1.3.2/setup.py000066400000000000000000000267201310511640000141600ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """A setup module for the GRPC Python package.""" from distutils import cygwinccompiler from distutils import extension as _extension from distutils import util import os import os.path import pkg_resources import platform import re import shlex import shutil import sys import sysconfig import setuptools from setuptools.command import egg_info # Redirect the manifest template from MANIFEST.in to PYTHON-MANIFEST.in. egg_info.manifest_maker.template = 'PYTHON-MANIFEST.in' PY3 = sys.version_info.major == 3 PYTHON_STEM = os.path.join('src', 'python', 'grpcio') CORE_INCLUDE = ('include', '.',) BORINGSSL_INCLUDE = (os.path.join('third_party', 'boringssl', 'include'),) ZLIB_INCLUDE = (os.path.join('third_party', 'zlib'),) CARES_INCLUDE = ( os.path.join('third_party', 'cares'), os.path.join('third_party', 'cares', 'cares'),) if 'linux' in sys.platform: CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_linux'),) if 'darwin' in sys.platform: CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_darwin'),) README = os.path.join(PYTHON_STEM, 'README.rst') # Ensure we're in the proper directory whether or not we're being used by pip. os.chdir(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, os.path.abspath(PYTHON_STEM)) # Break import-style to ensure we can actually find our in-repo dependencies. import _spawn_patch import commands import grpc_core_dependencies import grpc_version _spawn_patch.monkeypatch_spawn() LICENSE = '3-clause BSD' # Environment variable to determine whether or not the Cython extension should # *use* Cython or use the generated C files. Note that this requires the C files # to have been generated by building first *with* Cython support. Even if this # is set to false, if the script detects that the generated `.c` file isn't # present, then it will still attempt to use Cython. BUILD_WITH_CYTHON = os.environ.get('GRPC_PYTHON_BUILD_WITH_CYTHON', False) # Environment variable to determine whether or not to enable coverage analysis # in Cython modules. ENABLE_CYTHON_TRACING = os.environ.get( 'GRPC_PYTHON_ENABLE_CYTHON_TRACING', False) # Environment variable specifying whether or not there's interest in setting up # documentation building. ENABLE_DOCUMENTATION_BUILD = os.environ.get( 'GRPC_PYTHON_ENABLE_DOCUMENTATION_BUILD', False) # There are some situations (like on Windows) where CC, CFLAGS, and LDFLAGS are # entirely ignored/dropped/forgotten by distutils and its Cygwin/MinGW support. # We use these environment variables to thus get around that without locking # ourselves in w.r.t. the multitude of operating systems this ought to build on. # We can also use these variables as a way to inject environment-specific # compiler/linker flags. We assume GCC-like compilers and/or MinGW as a # reasonable default. EXTRA_ENV_COMPILE_ARGS = os.environ.get('GRPC_PYTHON_CFLAGS', None) EXTRA_ENV_LINK_ARGS = os.environ.get('GRPC_PYTHON_LDFLAGS', None) if EXTRA_ENV_COMPILE_ARGS is None: EXTRA_ENV_COMPILE_ARGS = '' if 'win32' in sys.platform and sys.version_info < (3, 5): # We use define flags here and don't directly add to DEFINE_MACROS below to # ensure that the expert user/builder has a way of turning it off (via the # envvars) without adding yet more GRPC-specific envvars. # See https://sourceforge.net/p/mingw-w64/bugs/363/ if '32' in platform.architecture()[0]: EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime32 -D_timeb=__timeb32 -D_ftime_s=_ftime32_s' else: EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime64 -D_timeb=__timeb64' elif 'win32' in sys.platform: EXTRA_ENV_COMPILE_ARGS += ' -D_PYTHON_MSVC' elif "linux" in sys.platform or "darwin" in sys.platform: EXTRA_ENV_COMPILE_ARGS += ' -fvisibility=hidden -fno-wrapv' if EXTRA_ENV_LINK_ARGS is None: EXTRA_ENV_LINK_ARGS = '' if "linux" in sys.platform or "darwin" in sys.platform: EXTRA_ENV_LINK_ARGS += ' -lpthread' elif "win32" in sys.platform and sys.version_info < (3, 5): msvcr = cygwinccompiler.get_msvcr()[0] # TODO(atash) sift through the GCC specs to see if libstdc++ can have any # influence on the linkage outcome on MinGW for non-C++ programs. EXTRA_ENV_LINK_ARGS += ( ' -static-libgcc -static-libstdc++ -mcrtdll={msvcr} ' '-static'.format(msvcr=msvcr)) if "linux" in sys.platform: EXTRA_ENV_LINK_ARGS += ' -Wl,-wrap,memcpy' EXTRA_COMPILE_ARGS = shlex.split(EXTRA_ENV_COMPILE_ARGS) EXTRA_LINK_ARGS = shlex.split(EXTRA_ENV_LINK_ARGS) CYTHON_EXTENSION_PACKAGE_NAMES = () CYTHON_EXTENSION_MODULE_NAMES = ('grpc._cython.cygrpc',) CYTHON_HELPER_C_FILES = () CORE_C_FILES = tuple(grpc_core_dependencies.CORE_SOURCE_FILES) if "win32" in sys.platform and "64bit" in platform.architecture()[0]: CORE_C_FILES = filter(lambda x: 'third_party/cares' not in x, CORE_C_FILES) EXTENSION_INCLUDE_DIRECTORIES = ( (PYTHON_STEM,) + CORE_INCLUDE + BORINGSSL_INCLUDE + ZLIB_INCLUDE + CARES_INCLUDE) EXTENSION_LIBRARIES = () if "linux" in sys.platform: EXTENSION_LIBRARIES += ('rt',) if not "win32" in sys.platform: EXTENSION_LIBRARIES += ('m',) if "win32" in sys.platform: EXTENSION_LIBRARIES += ('advapi32', 'ws2_32',) DEFINE_MACROS = ( ('OPENSSL_NO_ASM', 1), ('_WIN32_WINNT', 0x600), ('GPR_BACKWARDS_COMPATIBILITY_MODE', 1),) if "win32" in sys.platform: DEFINE_MACROS += (('WIN32_LEAN_AND_MEAN', 1), ('CARES_STATICLIB', 1),) if '64bit' in platform.architecture()[0]: # TODO(zyc): Re-enble c-ares on x64 windows after fixing the # ares_library_init compilation issue DEFINE_MACROS += (('MS_WIN64', 1), ('GRPC_ARES', 0),) elif sys.version_info >= (3, 5): # For some reason, this is needed to get access to inet_pton/inet_ntop # on msvc, but only for 32 bits DEFINE_MACROS += (('NTDDI_VERSION', 0x06000000),) else: DEFINE_MACROS += (('HAVE_CONFIG_H', 1),) LDFLAGS = tuple(EXTRA_LINK_ARGS) CFLAGS = tuple(EXTRA_COMPILE_ARGS) if "linux" in sys.platform or "darwin" in sys.platform: pymodinit_type = 'PyObject*' if PY3 else 'void' pymodinit = '__attribute__((visibility ("default"))) {}'.format(pymodinit_type) DEFINE_MACROS += (('PyMODINIT_FUNC', pymodinit),) # By default, Python3 distutils enforces compatibility of # c plugins (.so files) with the OSX version Python3 was built with. # For Python3.4, this is OSX 10.6, but we need Thread Local Support (__thread) if 'darwin' in sys.platform and PY3: mac_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET') if mac_target and (pkg_resources.parse_version(mac_target) < pkg_resources.parse_version('10.7.0')): os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.7' os.environ['_PYTHON_HOST_PLATFORM'] = re.sub( r'macosx-[0-9]+\.[0-9]+-(.+)', r'macosx-10.7-\1', util.get_platform()) def cython_extensions_and_necessity(): cython_module_files = [os.path.join(PYTHON_STEM, name.replace('.', '/') + '.pyx') for name in CYTHON_EXTENSION_MODULE_NAMES] extensions = [ _extension.Extension( name=module_name, sources=[module_file] + list(CYTHON_HELPER_C_FILES) + list(CORE_C_FILES), include_dirs=list(EXTENSION_INCLUDE_DIRECTORIES), libraries=list(EXTENSION_LIBRARIES), define_macros=list(DEFINE_MACROS), extra_compile_args=list(CFLAGS), extra_link_args=list(LDFLAGS), ) for (module_name, module_file) in zip(list(CYTHON_EXTENSION_MODULE_NAMES), cython_module_files) ] need_cython = BUILD_WITH_CYTHON if not BUILD_WITH_CYTHON: need_cython = need_cython or not commands.check_and_update_cythonization(extensions) return commands.try_cythonize(extensions, linetracing=ENABLE_CYTHON_TRACING, mandatory=BUILD_WITH_CYTHON), need_cython CYTHON_EXTENSION_MODULES, need_cython = cython_extensions_and_necessity() PACKAGE_DIRECTORIES = { '': PYTHON_STEM, } INSTALL_REQUIRES = ( 'six>=1.5.2', # TODO(atash): eventually split the grpcio package into a metapackage # depending on protobuf and the runtime component (independent of protobuf) 'protobuf>=3.2.0', ) if not PY3: INSTALL_REQUIRES += ('futures>=2.2.0', 'enum34>=1.0.4') SETUP_REQUIRES = INSTALL_REQUIRES + ( 'sphinx>=1.3', 'sphinx_rtd_theme>=0.1.8', 'six>=1.10', ) if ENABLE_DOCUMENTATION_BUILD else () try: import Cython except ImportError: if BUILD_WITH_CYTHON: sys.stderr.write( "You requested a Cython build via GRPC_PYTHON_BUILD_WITH_CYTHON, " "but do not have Cython installed. We won't stop you from using " "other commands, but the extension files will fail to build.\n") elif need_cython: sys.stderr.write( 'We could not find Cython. Setup may take 10-20 minutes.\n') SETUP_REQUIRES += ('cython>=0.23',) COMMAND_CLASS = { 'doc': commands.SphinxDocumentation, 'build_project_metadata': commands.BuildProjectMetadata, 'build_py': commands.BuildPy, 'build_ext': commands.BuildExt, 'gather': commands.Gather, } # Ensure that package data is copied over before any commands have been run: credentials_dir = os.path.join(PYTHON_STEM, 'grpc', '_cython', '_credentials') try: os.mkdir(credentials_dir) except OSError: pass shutil.copyfile(os.path.join('etc', 'roots.pem'), os.path.join(credentials_dir, 'roots.pem')) PACKAGE_DATA = { # Binaries that may or may not be present in the final installation, but are # mentioned here for completeness. 'grpc._cython': [ '_credentials/roots.pem', '_windows/grpc_c.32.python', '_windows/grpc_c.64.python', ], } PACKAGES = setuptools.find_packages(PYTHON_STEM) setuptools.setup( name='grpcio', version=grpc_version.VERSION, description='HTTP/2-based RPC framework', author='The gRPC Authors', author_email='grpc-io@googlegroups.com', url='http://www.grpc.io', license=LICENSE, long_description=open(README).read(), ext_modules=CYTHON_EXTENSION_MODULES, packages=list(PACKAGES), package_dir=PACKAGE_DIRECTORIES, package_data=PACKAGE_DATA, install_requires=INSTALL_REQUIRES, setup_requires=SETUP_REQUIRES, cmdclass=COMMAND_CLASS, ) grpc-1.3.2/src/000077500000000000000000000000001310511640000132265ustar00rootroot00000000000000grpc-1.3.2/src/benchmark/000077500000000000000000000000001310511640000151605ustar00rootroot00000000000000grpc-1.3.2/src/benchmark/gen_build_yaml.py000077500000000000000000000037561310511640000205220ustar00rootroot00000000000000#!/usr/bin/env python2.7 # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import os import sys import glob import yaml os.chdir(os.path.dirname(sys.argv[0])+'/../..') out = {} out['libs'] = [{ 'name': 'benchmark', 'build': 'private', 'language': 'c++', 'secure': 'no', 'defaults': 'benchmark', 'src': sorted(glob.glob('third_party/benchmark/src/*.cc')), 'headers': sorted( glob.glob('third_party/benchmark/src/*.h') + glob.glob('third_party/benchmark/include/benchmark/*.h')), }] print yaml.dump(out) grpc-1.3.2/src/boringssl/000077500000000000000000000000001310511640000152305ustar00rootroot00000000000000grpc-1.3.2/src/boringssl/err_data.c000066400000000000000000000733511310511640000171660ustar00rootroot00000000000000/* Copyright (c) 2015, Google Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* This file was generated by err_data_generate.go. */ #include #include #include OPENSSL_COMPILE_ASSERT(ERR_LIB_NONE == 1, library_values_changed_1); OPENSSL_COMPILE_ASSERT(ERR_LIB_SYS == 2, library_values_changed_2); OPENSSL_COMPILE_ASSERT(ERR_LIB_BN == 3, library_values_changed_3); OPENSSL_COMPILE_ASSERT(ERR_LIB_RSA == 4, library_values_changed_4); OPENSSL_COMPILE_ASSERT(ERR_LIB_DH == 5, library_values_changed_5); OPENSSL_COMPILE_ASSERT(ERR_LIB_EVP == 6, library_values_changed_6); OPENSSL_COMPILE_ASSERT(ERR_LIB_BUF == 7, library_values_changed_7); OPENSSL_COMPILE_ASSERT(ERR_LIB_OBJ == 8, library_values_changed_8); OPENSSL_COMPILE_ASSERT(ERR_LIB_PEM == 9, library_values_changed_9); OPENSSL_COMPILE_ASSERT(ERR_LIB_DSA == 10, library_values_changed_10); OPENSSL_COMPILE_ASSERT(ERR_LIB_X509 == 11, library_values_changed_11); OPENSSL_COMPILE_ASSERT(ERR_LIB_ASN1 == 12, library_values_changed_12); OPENSSL_COMPILE_ASSERT(ERR_LIB_CONF == 13, library_values_changed_13); OPENSSL_COMPILE_ASSERT(ERR_LIB_CRYPTO == 14, library_values_changed_14); OPENSSL_COMPILE_ASSERT(ERR_LIB_EC == 15, library_values_changed_15); OPENSSL_COMPILE_ASSERT(ERR_LIB_SSL == 16, library_values_changed_16); OPENSSL_COMPILE_ASSERT(ERR_LIB_BIO == 17, library_values_changed_17); OPENSSL_COMPILE_ASSERT(ERR_LIB_PKCS7 == 18, library_values_changed_18); OPENSSL_COMPILE_ASSERT(ERR_LIB_PKCS8 == 19, library_values_changed_19); OPENSSL_COMPILE_ASSERT(ERR_LIB_X509V3 == 20, library_values_changed_20); OPENSSL_COMPILE_ASSERT(ERR_LIB_RAND == 21, library_values_changed_21); OPENSSL_COMPILE_ASSERT(ERR_LIB_ENGINE == 22, library_values_changed_22); OPENSSL_COMPILE_ASSERT(ERR_LIB_OCSP == 23, library_values_changed_23); OPENSSL_COMPILE_ASSERT(ERR_LIB_UI == 24, library_values_changed_24); OPENSSL_COMPILE_ASSERT(ERR_LIB_COMP == 25, library_values_changed_25); OPENSSL_COMPILE_ASSERT(ERR_LIB_ECDSA == 26, library_values_changed_26); OPENSSL_COMPILE_ASSERT(ERR_LIB_ECDH == 27, library_values_changed_27); OPENSSL_COMPILE_ASSERT(ERR_LIB_HMAC == 28, library_values_changed_28); OPENSSL_COMPILE_ASSERT(ERR_LIB_DIGEST == 29, library_values_changed_29); OPENSSL_COMPILE_ASSERT(ERR_LIB_CIPHER == 30, library_values_changed_30); OPENSSL_COMPILE_ASSERT(ERR_LIB_HKDF == 31, library_values_changed_31); OPENSSL_COMPILE_ASSERT(ERR_LIB_USER == 32, library_values_changed_32); OPENSSL_COMPILE_ASSERT(ERR_NUM_LIBS == 33, library_values_changed_num); const uint32_t kOpenSSLReasonValues[] = { 0xc320838, 0xc328852, 0xc330861, 0xc338871, 0xc340880, 0xc348899, 0xc3508a5, 0xc3588c2, 0xc3608d4, 0xc3688e2, 0xc3708f2, 0xc3788ff, 0xc38090f, 0xc38891a, 0xc390930, 0xc39893f, 0xc3a0953, 0xc3a8845, 0xc3b00ea, 0x10320845, 0x103293ab, 0x103313b7, 0x103393d0, 0x103413e3, 0x10348e8b, 0x10350c19, 0x103593f6, 0x1036140b, 0x1036941e, 0x1037143d, 0x10379456, 0x1038146b, 0x10389489, 0x10391498, 0x103994b4, 0x103a14cf, 0x103a94de, 0x103b14fa, 0x103b9515, 0x103c152c, 0x103c80ea, 0x103d153d, 0x103d9551, 0x103e1570, 0x103e957f, 0x103f1596, 0x103f95a9, 0x10400bea, 0x104095bc, 0x104115da, 0x104195ed, 0x10421607, 0x10429617, 0x1043162b, 0x10439641, 0x10441659, 0x1044966e, 0x10451682, 0x10459694, 0x104605fb, 0x1046893f, 0x104716a9, 0x104796c0, 0x104816d5, 0x104896e3, 0x14320bcd, 0x14328bdb, 0x14330bea, 0x14338bfc, 0x143400ac, 0x143480ea, 0x18320083, 0x18328ee1, 0x183300ac, 0x18338ef7, 0x18340f0b, 0x183480ea, 0x18350f20, 0x18358f38, 0x18360f4d, 0x18368f61, 0x18370f85, 0x18378f9b, 0x18380faf, 0x18388fbf, 0x18390a57, 0x18398fcf, 0x183a0fe4, 0x183a8ff8, 0x183b0c25, 0x183b9005, 0x183c1017, 0x183c9022, 0x183d1032, 0x183d9043, 0x183e1054, 0x183e9066, 0x183f108f, 0x183f90a8, 0x184010c0, 0x184086d3, 0x203210e7, 0x243210f3, 0x24328985, 0x24331105, 0x24339112, 0x2434111f, 0x24349131, 0x24351140, 0x2435915d, 0x2436116a, 0x24369178, 0x24371186, 0x24379194, 0x2438119d, 0x243891aa, 0x243911bd, 0x28320c0d, 0x28328c25, 0x28330bea, 0x28338c38, 0x28340c19, 0x283480ac, 0x283500ea, 0x2c3228ca, 0x2c32a8d8, 0x2c3328ea, 0x2c33a8fc, 0x2c342910, 0x2c34a922, 0x2c35293d, 0x2c35a94f, 0x2c362962, 0x2c36832d, 0x2c37296f, 0x2c37a981, 0x2c382994, 0x2c38a9ab, 0x2c3929b9, 0x2c39a9c9, 0x2c3a29db, 0x2c3aa9ef, 0x2c3b2a00, 0x2c3baa1f, 0x2c3c2a33, 0x2c3caa49, 0x2c3d2a62, 0x2c3daa7f, 0x2c3e2a90, 0x2c3eaa9e, 0x2c3f2ab6, 0x2c3faace, 0x2c402adb, 0x2c4090e7, 0x2c412aec, 0x2c41aaff, 0x2c4210c0, 0x2c42ab10, 0x2c430720, 0x2c43aa11, 0x30320000, 0x30328015, 0x3033001f, 0x30338038, 0x3034004a, 0x30348064, 0x3035006b, 0x30358083, 0x30360094, 0x303680ac, 0x303700b9, 0x303780c8, 0x303800ea, 0x303880f7, 0x3039010a, 0x30398125, 0x303a013a, 0x303a814e, 0x303b0162, 0x303b8173, 0x303c018c, 0x303c81a9, 0x303d01b7, 0x303d81cb, 0x303e01db, 0x303e81f4, 0x303f0204, 0x303f8217, 0x30400226, 0x30408232, 0x30410247, 0x30418257, 0x3042026e, 0x3042827b, 0x3043028e, 0x3043829d, 0x304402b2, 0x304482d3, 0x304502e6, 0x304582f9, 0x30460312, 0x3046832d, 0x3047034a, 0x30478363, 0x30480371, 0x30488382, 0x30490391, 0x304983a9, 0x304a03bb, 0x304a83cf, 0x304b03ee, 0x304b8401, 0x304c040c, 0x304c841d, 0x304d0429, 0x304d843f, 0x304e044d, 0x304e8463, 0x304f0475, 0x304f8487, 0x3050049a, 0x305084ad, 0x305104be, 0x305184ce, 0x305204e6, 0x305284fb, 0x30530513, 0x30538527, 0x3054053f, 0x30548558, 0x30550571, 0x3055858e, 0x30560599, 0x305685b1, 0x305705c1, 0x305785d2, 0x305805e5, 0x305885fb, 0x30590604, 0x30598619, 0x305a062c, 0x305a863b, 0x305b065b, 0x305b866a, 0x305c068b, 0x305c86a7, 0x305d06b3, 0x305d86d3, 0x305e06ef, 0x305e8700, 0x305f0716, 0x305f8720, 0x34320b47, 0x34328b5b, 0x34330b78, 0x34338b8b, 0x34340b9a, 0x34348bb7, 0x3c320083, 0x3c328c62, 0x3c330c7b, 0x3c338c96, 0x3c340cb3, 0x3c348cdd, 0x3c350cf8, 0x3c358d1e, 0x3c360d37, 0x3c368d4f, 0x3c370d60, 0x3c378d6e, 0x3c380d7b, 0x3c388d8f, 0x3c390c25, 0x3c398da3, 0x3c3a0db7, 0x3c3a88ff, 0x3c3b0dc7, 0x3c3b8de2, 0x3c3c0df4, 0x3c3c8e0a, 0x3c3d0e14, 0x3c3d8e28, 0x3c3e0e36, 0x3c3e8e5b, 0x3c3f0c4e, 0x3c3f8e44, 0x3c4000ac, 0x3c4080ea, 0x3c410cce, 0x3c418d0d, 0x403216fa, 0x40329710, 0x4033173e, 0x40339748, 0x4034175f, 0x4034977d, 0x4035178d, 0x4035979f, 0x403617ac, 0x403697b8, 0x403717cd, 0x403797df, 0x403817ea, 0x403897fc, 0x40390e8b, 0x4039980c, 0x403a181f, 0x403a9840, 0x403b1851, 0x403b9861, 0x403c0064, 0x403c8083, 0x403d18aa, 0x403d98c0, 0x403e18cf, 0x403e98e2, 0x403f18fc, 0x403f990a, 0x4040191f, 0x40409933, 0x40411950, 0x4041996b, 0x40421984, 0x40429997, 0x404319ab, 0x404399c3, 0x404419da, 0x404480ac, 0x404519ef, 0x40459a01, 0x40461a25, 0x40469a45, 0x40471a53, 0x40479a7a, 0x40481ab7, 0x40489ad0, 0x40491ae7, 0x40499b01, 0x404a1b18, 0x404a9b36, 0x404b1b4e, 0x404b9b65, 0x404c1b7b, 0x404c9b8d, 0x404d1bae, 0x404d9bd0, 0x404e1be4, 0x404e9bf1, 0x404f1c1e, 0x404f9c47, 0x40501c71, 0x40509c85, 0x40511ca0, 0x40519cb0, 0x40521cc7, 0x40529ceb, 0x40531d03, 0x40539d16, 0x40541d2b, 0x40549d4e, 0x40551d5c, 0x40559d79, 0x40561d86, 0x40569d9f, 0x40571db7, 0x40579dca, 0x40581ddf, 0x40589e06, 0x40591e35, 0x40599e62, 0x405a1e76, 0x405a9e86, 0x405b1e9e, 0x405b9eaf, 0x405c1ec2, 0x405c9ed3, 0x405d1ee0, 0x405d9ef7, 0x405e1f17, 0x405e8a95, 0x405f1f38, 0x405f9f45, 0x40601f53, 0x40609f75, 0x40611f9d, 0x40619fb2, 0x40621fc9, 0x40629fda, 0x40631feb, 0x4063a000, 0x40642017, 0x4064a043, 0x4065205e, 0x4065a075, 0x4066208d, 0x4066a0b7, 0x406720e2, 0x4067a103, 0x40682116, 0x4068a137, 0x40692169, 0x4069a197, 0x406a21b8, 0x406aa1d8, 0x406b2360, 0x406ba383, 0x406c2399, 0x406ca5c5, 0x406d25f4, 0x406da61c, 0x406e264a, 0x406ea662, 0x406f2681, 0x406fa696, 0x407026a9, 0x4070a6c6, 0x40710800, 0x4071a6d8, 0x407226eb, 0x4072a704, 0x4073271c, 0x4073936d, 0x40742730, 0x4074a74a, 0x4075275b, 0x4075a76f, 0x4076277d, 0x407691aa, 0x407727a2, 0x4077a7c4, 0x407827df, 0x4078a818, 0x4079282f, 0x4079a845, 0x407a2851, 0x407aa864, 0x407b2879, 0x407ba88b, 0x407c28a0, 0x407ca8a9, 0x407d2152, 0x407d9c57, 0x407e27f4, 0x407e9e16, 0x407f1a67, 0x407f9887, 0x40801c2e, 0x40809a8f, 0x40811cd9, 0x40819c08, 0x40822635, 0x4082986d, 0x40831df1, 0x4083a028, 0x40841aa3, 0x40849e4e, 0x41f4228b, 0x41f9231d, 0x41fe2210, 0x41fea3ec, 0x41ff24dd, 0x420322a4, 0x420822c6, 0x4208a302, 0x420921f4, 0x4209a33c, 0x420a224b, 0x420aa22b, 0x420b226b, 0x420ba2e4, 0x420c24f9, 0x420ca3b9, 0x420d23d3, 0x420da40a, 0x42122424, 0x421724c0, 0x4217a466, 0x421c2488, 0x421f2443, 0x42212510, 0x422624a3, 0x422b25a9, 0x422ba572, 0x422c2591, 0x422ca54c, 0x422d252b, 0x4432072b, 0x4432873a, 0x44330746, 0x44338754, 0x44340767, 0x44348778, 0x4435077f, 0x44358789, 0x4436079c, 0x443687b2, 0x443707c4, 0x443787d1, 0x443807e0, 0x443887e8, 0x44390800, 0x4439880e, 0x443a0821, 0x4c3211d4, 0x4c3291e4, 0x4c3311f7, 0x4c339217, 0x4c3400ac, 0x4c3480ea, 0x4c351223, 0x4c359231, 0x4c36124d, 0x4c369260, 0x4c37126f, 0x4c37927d, 0x4c381292, 0x4c38929e, 0x4c3912be, 0x4c3992e8, 0x4c3a1301, 0x4c3a931a, 0x4c3b05fb, 0x4c3b9333, 0x4c3c1345, 0x4c3c9354, 0x4c3d136d, 0x4c3d937c, 0x4c3e1389, 0x50322b22, 0x5032ab31, 0x50332b3c, 0x5033ab4c, 0x50342b65, 0x5034ab7f, 0x50352b8d, 0x5035aba3, 0x50362bb5, 0x5036abcb, 0x50372be4, 0x5037abf7, 0x50382c0f, 0x5038ac20, 0x50392c35, 0x5039ac49, 0x503a2c69, 0x503aac7f, 0x503b2c97, 0x503baca9, 0x503c2cc5, 0x503cacdc, 0x503d2cf5, 0x503dad0b, 0x503e2d18, 0x503ead2e, 0x503f2d40, 0x503f8382, 0x50402d53, 0x5040ad63, 0x50412d7d, 0x5041ad8c, 0x50422da6, 0x5042adc3, 0x50432dd3, 0x5043ade3, 0x50442df2, 0x5044843f, 0x50452e06, 0x5045ae24, 0x50462e37, 0x5046ae4d, 0x50472e5f, 0x5047ae74, 0x50482e9a, 0x5048aea8, 0x50492ebb, 0x5049aed0, 0x504a2ee6, 0x504aaef6, 0x504b2f16, 0x504baf29, 0x504c2f4c, 0x504caf7a, 0x504d2f8c, 0x504dafa9, 0x504e2fc4, 0x504eafe0, 0x504f2ff2, 0x504fb009, 0x50503018, 0x505086ef, 0x5051302b, 0x58320ec9, 0x68320e8b, 0x68328c25, 0x68330c38, 0x68338e99, 0x68340ea9, 0x683480ea, 0x6c320e67, 0x6c328bfc, 0x6c330e72, 0x74320a0b, 0x78320970, 0x78328985, 0x78330991, 0x78338083, 0x783409a0, 0x783489b5, 0x783509d4, 0x783589f6, 0x78360a0b, 0x78368a21, 0x78370a31, 0x78378a44, 0x78380a57, 0x78388a69, 0x78390a76, 0x78398a95, 0x783a0aaa, 0x783a8ab8, 0x783b0ac2, 0x783b8ad6, 0x783c0aed, 0x783c8b02, 0x783d0b19, 0x783d8b2e, 0x783e0a84, 0x7c3210d6, }; const size_t kOpenSSLReasonValuesLen = sizeof(kOpenSSLReasonValues) / sizeof(kOpenSSLReasonValues[0]); const char kOpenSSLReasonStringData[] = "ASN1_LENGTH_MISMATCH\0" "AUX_ERROR\0" "BAD_GET_ASN1_OBJECT_CALL\0" "BAD_OBJECT_HEADER\0" "BMPSTRING_IS_WRONG_LENGTH\0" "BN_LIB\0" "BOOLEAN_IS_WRONG_LENGTH\0" "BUFFER_TOO_SMALL\0" "CONTEXT_NOT_INITIALISED\0" "DECODE_ERROR\0" "DEPTH_EXCEEDED\0" "DIGEST_AND_KEY_TYPE_NOT_SUPPORTED\0" "ENCODE_ERROR\0" "ERROR_GETTING_TIME\0" "EXPECTING_AN_ASN1_SEQUENCE\0" "EXPECTING_AN_INTEGER\0" "EXPECTING_AN_OBJECT\0" "EXPECTING_A_BOOLEAN\0" "EXPECTING_A_TIME\0" "EXPLICIT_LENGTH_MISMATCH\0" "EXPLICIT_TAG_NOT_CONSTRUCTED\0" "FIELD_MISSING\0" "FIRST_NUM_TOO_LARGE\0" "HEADER_TOO_LONG\0" "ILLEGAL_BITSTRING_FORMAT\0" "ILLEGAL_BOOLEAN\0" "ILLEGAL_CHARACTERS\0" "ILLEGAL_FORMAT\0" "ILLEGAL_HEX\0" "ILLEGAL_IMPLICIT_TAG\0" "ILLEGAL_INTEGER\0" "ILLEGAL_NESTED_TAGGING\0" "ILLEGAL_NULL\0" "ILLEGAL_NULL_VALUE\0" "ILLEGAL_OBJECT\0" "ILLEGAL_OPTIONAL_ANY\0" "ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE\0" "ILLEGAL_TAGGED_ANY\0" "ILLEGAL_TIME_VALUE\0" "INTEGER_NOT_ASCII_FORMAT\0" "INTEGER_TOO_LARGE_FOR_LONG\0" "INVALID_BIT_STRING_BITS_LEFT\0" "INVALID_BMPSTRING_LENGTH\0" "INVALID_DIGIT\0" "INVALID_MODIFIER\0" "INVALID_NUMBER\0" "INVALID_OBJECT_ENCODING\0" "INVALID_SEPARATOR\0" "INVALID_TIME_FORMAT\0" "INVALID_UNIVERSALSTRING_LENGTH\0" "INVALID_UTF8STRING\0" "LIST_ERROR\0" "MISSING_ASN1_EOS\0" "MISSING_EOC\0" "MISSING_SECOND_NUMBER\0" "MISSING_VALUE\0" "MSTRING_NOT_UNIVERSAL\0" "MSTRING_WRONG_TAG\0" "NESTED_ASN1_ERROR\0" "NESTED_ASN1_STRING\0" "NON_HEX_CHARACTERS\0" "NOT_ASCII_FORMAT\0" "NOT_ENOUGH_DATA\0" "NO_MATCHING_CHOICE_TYPE\0" "NULL_IS_WRONG_LENGTH\0" "OBJECT_NOT_ASCII_FORMAT\0" "ODD_NUMBER_OF_CHARS\0" "SECOND_NUMBER_TOO_LARGE\0" "SEQUENCE_LENGTH_MISMATCH\0" "SEQUENCE_NOT_CONSTRUCTED\0" "SEQUENCE_OR_SET_NEEDS_CONFIG\0" "SHORT_LINE\0" "STREAMING_NOT_SUPPORTED\0" "STRING_TOO_LONG\0" "STRING_TOO_SHORT\0" "TAG_VALUE_TOO_HIGH\0" "TIME_NOT_ASCII_FORMAT\0" "TOO_LONG\0" "TYPE_NOT_CONSTRUCTED\0" "TYPE_NOT_PRIMITIVE\0" "UNEXPECTED_EOC\0" "UNIVERSALSTRING_IS_WRONG_LENGTH\0" "UNKNOWN_FORMAT\0" "UNKNOWN_MESSAGE_DIGEST_ALGORITHM\0" "UNKNOWN_SIGNATURE_ALGORITHM\0" "UNKNOWN_TAG\0" "UNSUPPORTED_ANY_DEFINED_BY_TYPE\0" "UNSUPPORTED_PUBLIC_KEY_TYPE\0" "UNSUPPORTED_TYPE\0" "WRONG_PUBLIC_KEY_TYPE\0" "WRONG_TAG\0" "WRONG_TYPE\0" "BAD_FOPEN_MODE\0" "BROKEN_PIPE\0" "CONNECT_ERROR\0" "ERROR_SETTING_NBIO\0" "INVALID_ARGUMENT\0" "IN_USE\0" "KEEPALIVE\0" "NBIO_CONNECT_ERROR\0" "NO_HOSTNAME_SPECIFIED\0" "NO_PORT_SPECIFIED\0" "NO_SUCH_FILE\0" "NULL_PARAMETER\0" "SYS_LIB\0" "UNABLE_TO_CREATE_SOCKET\0" "UNINITIALIZED\0" "UNSUPPORTED_METHOD\0" "WRITE_TO_READ_ONLY_BIO\0" "ARG2_LT_ARG3\0" "BAD_ENCODING\0" "BAD_RECIPROCAL\0" "BIGNUM_TOO_LONG\0" "BITS_TOO_SMALL\0" "CALLED_WITH_EVEN_MODULUS\0" "DIV_BY_ZERO\0" "EXPAND_ON_STATIC_BIGNUM_DATA\0" "INPUT_NOT_REDUCED\0" "INVALID_RANGE\0" "NEGATIVE_NUMBER\0" "NOT_A_SQUARE\0" "NOT_INITIALIZED\0" "NO_INVERSE\0" "PRIVATE_KEY_TOO_LARGE\0" "P_IS_NOT_PRIME\0" "TOO_MANY_ITERATIONS\0" "TOO_MANY_TEMPORARY_VARIABLES\0" "AES_KEY_SETUP_FAILED\0" "BAD_DECRYPT\0" "BAD_KEY_LENGTH\0" "CTRL_NOT_IMPLEMENTED\0" "CTRL_OPERATION_NOT_IMPLEMENTED\0" "DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH\0" "INITIALIZATION_ERROR\0" "INPUT_NOT_INITIALIZED\0" "INVALID_AD_SIZE\0" "INVALID_KEY_LENGTH\0" "INVALID_NONCE_SIZE\0" "INVALID_OPERATION\0" "IV_TOO_LARGE\0" "NO_CIPHER_SET\0" "NO_DIRECTION_SET\0" "OUTPUT_ALIASES_INPUT\0" "TAG_TOO_LARGE\0" "TOO_LARGE\0" "UNSUPPORTED_AD_SIZE\0" "UNSUPPORTED_INPUT_SIZE\0" "UNSUPPORTED_KEY_SIZE\0" "UNSUPPORTED_NONCE_SIZE\0" "UNSUPPORTED_TAG_SIZE\0" "WRONG_FINAL_BLOCK_LENGTH\0" "LIST_CANNOT_BE_NULL\0" "MISSING_CLOSE_SQUARE_BRACKET\0" "MISSING_EQUAL_SIGN\0" "NO_CLOSE_BRACE\0" "UNABLE_TO_CREATE_NEW_SECTION\0" "VARIABLE_HAS_NO_VALUE\0" "BAD_GENERATOR\0" "INVALID_PUBKEY\0" "MODULUS_TOO_LARGE\0" "NO_PRIVATE_VALUE\0" "BAD_Q_VALUE\0" "BAD_VERSION\0" "MISSING_PARAMETERS\0" "NEED_NEW_SETUP_VALUES\0" "BIGNUM_OUT_OF_RANGE\0" "COORDINATES_OUT_OF_RANGE\0" "D2I_ECPKPARAMETERS_FAILURE\0" "EC_GROUP_NEW_BY_NAME_FAILURE\0" "GROUP2PKPARAMETERS_FAILURE\0" "GROUP_MISMATCH\0" "I2D_ECPKPARAMETERS_FAILURE\0" "INCOMPATIBLE_OBJECTS\0" "INVALID_COFACTOR\0" "INVALID_COMPRESSED_POINT\0" "INVALID_COMPRESSION_BIT\0" "INVALID_ENCODING\0" "INVALID_FIELD\0" "INVALID_FORM\0" "INVALID_GROUP_ORDER\0" "INVALID_PRIVATE_KEY\0" "MISSING_PRIVATE_KEY\0" "NON_NAMED_CURVE\0" "PKPARAMETERS2GROUP_FAILURE\0" "POINT_AT_INFINITY\0" "POINT_IS_NOT_ON_CURVE\0" "SLOT_FULL\0" "UNDEFINED_GENERATOR\0" "UNKNOWN_GROUP\0" "UNKNOWN_ORDER\0" "WRONG_CURVE_PARAMETERS\0" "WRONG_ORDER\0" "KDF_FAILED\0" "POINT_ARITHMETIC_FAILURE\0" "BAD_SIGNATURE\0" "NOT_IMPLEMENTED\0" "RANDOM_NUMBER_GENERATION_FAILED\0" "OPERATION_NOT_SUPPORTED\0" "COMMAND_NOT_SUPPORTED\0" "DIFFERENT_KEY_TYPES\0" "DIFFERENT_PARAMETERS\0" "EXPECTING_AN_EC_KEY_KEY\0" "EXPECTING_AN_RSA_KEY\0" "EXPECTING_A_DSA_KEY\0" "ILLEGAL_OR_UNSUPPORTED_PADDING_MODE\0" "INVALID_DIGEST_LENGTH\0" "INVALID_DIGEST_TYPE\0" "INVALID_KEYBITS\0" "INVALID_MGF1_MD\0" "INVALID_PADDING_MODE\0" "INVALID_PSS_SALTLEN\0" "KEYS_NOT_SET\0" "NO_DEFAULT_DIGEST\0" "NO_KEY_SET\0" "NO_MDC2_SUPPORT\0" "NO_NID_FOR_CURVE\0" "NO_OPERATION_SET\0" "NO_PARAMETERS_SET\0" "OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE\0" "OPERATON_NOT_INITIALIZED\0" "UNKNOWN_PUBLIC_KEY_TYPE\0" "UNSUPPORTED_ALGORITHM\0" "OUTPUT_TOO_LARGE\0" "UNKNOWN_NID\0" "BAD_BASE64_DECODE\0" "BAD_END_LINE\0" "BAD_IV_CHARS\0" "BAD_PASSWORD_READ\0" "CIPHER_IS_NULL\0" "ERROR_CONVERTING_PRIVATE_KEY\0" "NOT_DEK_INFO\0" "NOT_ENCRYPTED\0" "NOT_PROC_TYPE\0" "NO_START_LINE\0" "READ_KEY\0" "SHORT_HEADER\0" "UNSUPPORTED_CIPHER\0" "UNSUPPORTED_ENCRYPTION\0" "BAD_PKCS12_DATA\0" "BAD_PKCS12_VERSION\0" "CIPHER_HAS_NO_OBJECT_IDENTIFIER\0" "CRYPT_ERROR\0" "ENCRYPT_ERROR\0" "ERROR_SETTING_CIPHER_PARAMS\0" "INCORRECT_PASSWORD\0" "KEYGEN_FAILURE\0" "KEY_GEN_ERROR\0" "METHOD_NOT_SUPPORTED\0" "MISSING_MAC\0" "MULTIPLE_PRIVATE_KEYS_IN_PKCS12\0" "PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED\0" "PKCS12_TOO_DEEPLY_NESTED\0" "PRIVATE_KEY_DECODE_ERROR\0" "PRIVATE_KEY_ENCODE_ERROR\0" "UNKNOWN_ALGORITHM\0" "UNKNOWN_CIPHER\0" "UNKNOWN_CIPHER_ALGORITHM\0" "UNKNOWN_DIGEST\0" "UNKNOWN_HASH\0" "UNSUPPORTED_PRIVATE_KEY_ALGORITHM\0" "BAD_E_VALUE\0" "BAD_FIXED_HEADER_DECRYPT\0" "BAD_PAD_BYTE_COUNT\0" "BAD_RSA_PARAMETERS\0" "BLOCK_TYPE_IS_NOT_01\0" "BN_NOT_INITIALIZED\0" "CANNOT_RECOVER_MULTI_PRIME_KEY\0" "CRT_PARAMS_ALREADY_GIVEN\0" "CRT_VALUES_INCORRECT\0" "DATA_LEN_NOT_EQUAL_TO_MOD_LEN\0" "DATA_TOO_LARGE\0" "DATA_TOO_LARGE_FOR_KEY_SIZE\0" "DATA_TOO_LARGE_FOR_MODULUS\0" "DATA_TOO_SMALL\0" "DATA_TOO_SMALL_FOR_KEY_SIZE\0" "DIGEST_TOO_BIG_FOR_RSA_KEY\0" "D_E_NOT_CONGRUENT_TO_1\0" "EMPTY_PUBLIC_KEY\0" "FIRST_OCTET_INVALID\0" "INCONSISTENT_SET_OF_CRT_VALUES\0" "INTERNAL_ERROR\0" "INVALID_MESSAGE_LENGTH\0" "KEY_SIZE_TOO_SMALL\0" "LAST_OCTET_INVALID\0" "MUST_HAVE_AT_LEAST_TWO_PRIMES\0" "NO_PUBLIC_EXPONENT\0" "NULL_BEFORE_BLOCK_MISSING\0" "N_NOT_EQUAL_P_Q\0" "OAEP_DECODING_ERROR\0" "ONLY_ONE_OF_P_Q_GIVEN\0" "OUTPUT_BUFFER_TOO_SMALL\0" "PADDING_CHECK_FAILED\0" "PKCS_DECODING_ERROR\0" "SLEN_CHECK_FAILED\0" "SLEN_RECOVERY_FAILED\0" "UNKNOWN_ALGORITHM_TYPE\0" "UNKNOWN_PADDING_TYPE\0" "VALUE_MISSING\0" "WRONG_SIGNATURE_LENGTH\0" "APP_DATA_IN_HANDSHAKE\0" "ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT\0" "BAD_ALERT\0" "BAD_CHANGE_CIPHER_SPEC\0" "BAD_DATA_RETURNED_BY_CALLBACK\0" "BAD_DH_P_LENGTH\0" "BAD_DIGEST_LENGTH\0" "BAD_ECC_CERT\0" "BAD_ECPOINT\0" "BAD_HANDSHAKE_RECORD\0" "BAD_HELLO_REQUEST\0" "BAD_LENGTH\0" "BAD_PACKET_LENGTH\0" "BAD_RSA_ENCRYPT\0" "BAD_SRTP_MKI_VALUE\0" "BAD_SRTP_PROTECTION_PROFILE_LIST\0" "BAD_SSL_FILETYPE\0" "BAD_WRITE_RETRY\0" "BIO_NOT_SET\0" "BLOCK_CIPHER_PAD_IS_WRONG\0" "BUFFERED_MESSAGES_ON_CIPHER_CHANGE\0" "CA_DN_LENGTH_MISMATCH\0" "CA_DN_TOO_LONG\0" "CCS_RECEIVED_EARLY\0" "CERTIFICATE_VERIFY_FAILED\0" "CERT_CB_ERROR\0" "CERT_LENGTH_MISMATCH\0" "CHANNEL_ID_NOT_P256\0" "CHANNEL_ID_SIGNATURE_INVALID\0" "CIPHER_OR_HASH_UNAVAILABLE\0" "CLIENTHELLO_PARSE_FAILED\0" "CLIENTHELLO_TLSEXT\0" "CONNECTION_REJECTED\0" "CONNECTION_TYPE_NOT_SET\0" "CUSTOM_EXTENSION_ERROR\0" "DATA_LENGTH_TOO_LONG\0" "DECRYPTION_FAILED\0" "DECRYPTION_FAILED_OR_BAD_RECORD_MAC\0" "DH_PUBLIC_VALUE_LENGTH_IS_WRONG\0" "DH_P_TOO_LONG\0" "DIGEST_CHECK_FAILED\0" "DOWNGRADE_DETECTED\0" "DTLS_MESSAGE_TOO_BIG\0" "DUPLICATE_EXTENSION\0" "DUPLICATE_KEY_SHARE\0" "ECC_CERT_NOT_FOR_SIGNING\0" "EMS_STATE_INCONSISTENT\0" "ENCRYPTED_LENGTH_TOO_LONG\0" "ERROR_ADDING_EXTENSION\0" "ERROR_IN_RECEIVED_CIPHER_LIST\0" "ERROR_PARSING_EXTENSION\0" "EXCESSIVE_MESSAGE_SIZE\0" "EXTRA_DATA_IN_MESSAGE\0" "FRAGMENT_MISMATCH\0" "GOT_NEXT_PROTO_WITHOUT_EXTENSION\0" "HANDSHAKE_FAILURE_ON_CLIENT_HELLO\0" "HTTPS_PROXY_REQUEST\0" "HTTP_REQUEST\0" "INAPPROPRIATE_FALLBACK\0" "INVALID_ALPN_PROTOCOL\0" "INVALID_COMMAND\0" "INVALID_COMPRESSION_LIST\0" "INVALID_MESSAGE\0" "INVALID_OUTER_RECORD_TYPE\0" "INVALID_SSL_SESSION\0" "INVALID_TICKET_KEYS_LENGTH\0" "LENGTH_MISMATCH\0" "LIBRARY_HAS_NO_CIPHERS\0" "MISSING_EXTENSION\0" "MISSING_KEY_SHARE\0" "MISSING_RSA_CERTIFICATE\0" "MISSING_TMP_DH_KEY\0" "MISSING_TMP_ECDH_KEY\0" "MIXED_SPECIAL_OPERATOR_WITH_GROUPS\0" "MTU_TOO_SMALL\0" "NEGOTIATED_BOTH_NPN_AND_ALPN\0" "NESTED_GROUP\0" "NO_CERTIFICATES_RETURNED\0" "NO_CERTIFICATE_ASSIGNED\0" "NO_CERTIFICATE_SET\0" "NO_CIPHERS_AVAILABLE\0" "NO_CIPHERS_PASSED\0" "NO_CIPHERS_SPECIFIED\0" "NO_CIPHER_MATCH\0" "NO_COMMON_SIGNATURE_ALGORITHMS\0" "NO_COMPRESSION_SPECIFIED\0" "NO_GROUPS_SPECIFIED\0" "NO_METHOD_SPECIFIED\0" "NO_P256_SUPPORT\0" "NO_PRIVATE_KEY_ASSIGNED\0" "NO_RENEGOTIATION\0" "NO_REQUIRED_DIGEST\0" "NO_SHARED_CIPHER\0" "NULL_SSL_CTX\0" "NULL_SSL_METHOD_PASSED\0" "OLD_SESSION_CIPHER_NOT_RETURNED\0" "OLD_SESSION_VERSION_NOT_RETURNED\0" "PARSE_TLSEXT\0" "PATH_TOO_LONG\0" "PEER_DID_NOT_RETURN_A_CERTIFICATE\0" "PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE\0" "PROTOCOL_IS_SHUTDOWN\0" "PSK_IDENTITY_NOT_FOUND\0" "PSK_NO_CLIENT_CB\0" "PSK_NO_SERVER_CB\0" "READ_TIMEOUT_EXPIRED\0" "RECORD_LENGTH_MISMATCH\0" "RECORD_TOO_LARGE\0" "RENEGOTIATION_EMS_MISMATCH\0" "RENEGOTIATION_ENCODING_ERR\0" "RENEGOTIATION_MISMATCH\0" "REQUIRED_CIPHER_MISSING\0" "RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION\0" "RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION\0" "SCSV_RECEIVED_WHEN_RENEGOTIATING\0" "SERVERHELLO_TLSEXT\0" "SESSION_ID_CONTEXT_UNINITIALIZED\0" "SESSION_MAY_NOT_BE_CREATED\0" "SHUTDOWN_WHILE_IN_INIT\0" "SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER\0" "SRTP_COULD_NOT_ALLOCATE_PROFILES\0" "SRTP_UNKNOWN_PROTECTION_PROFILE\0" "SSL3_EXT_INVALID_SERVERNAME\0" "SSLV3_ALERT_BAD_CERTIFICATE\0" "SSLV3_ALERT_BAD_RECORD_MAC\0" "SSLV3_ALERT_CERTIFICATE_EXPIRED\0" "SSLV3_ALERT_CERTIFICATE_REVOKED\0" "SSLV3_ALERT_CERTIFICATE_UNKNOWN\0" "SSLV3_ALERT_CLOSE_NOTIFY\0" "SSLV3_ALERT_DECOMPRESSION_FAILURE\0" "SSLV3_ALERT_HANDSHAKE_FAILURE\0" "SSLV3_ALERT_ILLEGAL_PARAMETER\0" "SSLV3_ALERT_NO_CERTIFICATE\0" "SSLV3_ALERT_UNEXPECTED_MESSAGE\0" "SSLV3_ALERT_UNSUPPORTED_CERTIFICATE\0" "SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION\0" "SSL_HANDSHAKE_FAILURE\0" "SSL_SESSION_ID_CONTEXT_TOO_LONG\0" "TLSV1_ALERT_ACCESS_DENIED\0" "TLSV1_ALERT_DECODE_ERROR\0" "TLSV1_ALERT_DECRYPTION_FAILED\0" "TLSV1_ALERT_DECRYPT_ERROR\0" "TLSV1_ALERT_EXPORT_RESTRICTION\0" "TLSV1_ALERT_INAPPROPRIATE_FALLBACK\0" "TLSV1_ALERT_INSUFFICIENT_SECURITY\0" "TLSV1_ALERT_INTERNAL_ERROR\0" "TLSV1_ALERT_NO_RENEGOTIATION\0" "TLSV1_ALERT_PROTOCOL_VERSION\0" "TLSV1_ALERT_RECORD_OVERFLOW\0" "TLSV1_ALERT_UNKNOWN_CA\0" "TLSV1_ALERT_USER_CANCELLED\0" "TLSV1_BAD_CERTIFICATE_HASH_VALUE\0" "TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE\0" "TLSV1_CERTIFICATE_UNOBTAINABLE\0" "TLSV1_UNRECOGNIZED_NAME\0" "TLSV1_UNSUPPORTED_EXTENSION\0" "TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST\0" "TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG\0" "TOO_MANY_EMPTY_FRAGMENTS\0" "TOO_MANY_KEY_UPDATES\0" "TOO_MANY_WARNING_ALERTS\0" "UNABLE_TO_FIND_ECDH_PARAMETERS\0" "UNEXPECTED_EXTENSION\0" "UNEXPECTED_MESSAGE\0" "UNEXPECTED_OPERATOR_IN_GROUP\0" "UNEXPECTED_RECORD\0" "UNKNOWN_ALERT_TYPE\0" "UNKNOWN_CERTIFICATE_TYPE\0" "UNKNOWN_CIPHER_RETURNED\0" "UNKNOWN_CIPHER_TYPE\0" "UNKNOWN_KEY_EXCHANGE_TYPE\0" "UNKNOWN_PROTOCOL\0" "UNKNOWN_SSL_VERSION\0" "UNKNOWN_STATE\0" "UNSAFE_LEGACY_RENEGOTIATION_DISABLED\0" "UNSUPPORTED_COMPRESSION_ALGORITHM\0" "UNSUPPORTED_ELLIPTIC_CURVE\0" "UNSUPPORTED_PROTOCOL\0" "UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY\0" "WRONG_CERTIFICATE_TYPE\0" "WRONG_CIPHER_RETURNED\0" "WRONG_CURVE\0" "WRONG_MESSAGE_TYPE\0" "WRONG_SIGNATURE_TYPE\0" "WRONG_SSL_VERSION\0" "WRONG_VERSION_NUMBER\0" "X509_LIB\0" "X509_VERIFICATION_SETUP_PROBLEMS\0" "AKID_MISMATCH\0" "BAD_PKCS7_VERSION\0" "BAD_X509_FILETYPE\0" "BASE64_DECODE_ERROR\0" "CANT_CHECK_DH_KEY\0" "CERT_ALREADY_IN_HASH_TABLE\0" "CRL_ALREADY_DELTA\0" "CRL_VERIFY_FAILURE\0" "IDP_MISMATCH\0" "INVALID_DIRECTORY\0" "INVALID_FIELD_NAME\0" "INVALID_PSS_PARAMETERS\0" "INVALID_TRUST\0" "ISSUER_MISMATCH\0" "KEY_TYPE_MISMATCH\0" "KEY_VALUES_MISMATCH\0" "LOADING_CERT_DIR\0" "LOADING_DEFAULTS\0" "NAME_TOO_LONG\0" "NEWER_CRL_NOT_NEWER\0" "NOT_PKCS7_SIGNED_DATA\0" "NO_CERTIFICATES_INCLUDED\0" "NO_CERT_SET_FOR_US_TO_VERIFY\0" "NO_CRLS_INCLUDED\0" "NO_CRL_NUMBER\0" "PUBLIC_KEY_DECODE_ERROR\0" "PUBLIC_KEY_ENCODE_ERROR\0" "SHOULD_RETRY\0" "UNKNOWN_KEY_TYPE\0" "UNKNOWN_PURPOSE_ID\0" "UNKNOWN_TRUST_ID\0" "WRONG_LOOKUP_TYPE\0" "BAD_IP_ADDRESS\0" "BAD_OBJECT\0" "BN_DEC2BN_ERROR\0" "BN_TO_ASN1_INTEGER_ERROR\0" "CANNOT_FIND_FREE_FUNCTION\0" "DIRNAME_ERROR\0" "DISTPOINT_ALREADY_SET\0" "DUPLICATE_ZONE_ID\0" "ERROR_CONVERTING_ZONE\0" "ERROR_CREATING_EXTENSION\0" "ERROR_IN_EXTENSION\0" "EXPECTED_A_SECTION_NAME\0" "EXTENSION_EXISTS\0" "EXTENSION_NAME_ERROR\0" "EXTENSION_NOT_FOUND\0" "EXTENSION_SETTING_NOT_SUPPORTED\0" "EXTENSION_VALUE_ERROR\0" "ILLEGAL_EMPTY_EXTENSION\0" "ILLEGAL_HEX_DIGIT\0" "INCORRECT_POLICY_SYNTAX_TAG\0" "INVALID_BOOLEAN_STRING\0" "INVALID_EXTENSION_STRING\0" "INVALID_MULTIPLE_RDNS\0" "INVALID_NAME\0" "INVALID_NULL_ARGUMENT\0" "INVALID_NULL_NAME\0" "INVALID_NULL_VALUE\0" "INVALID_NUMBERS\0" "INVALID_OBJECT_IDENTIFIER\0" "INVALID_OPTION\0" "INVALID_POLICY_IDENTIFIER\0" "INVALID_PROXY_POLICY_SETTING\0" "INVALID_PURPOSE\0" "INVALID_SECTION\0" "INVALID_SYNTAX\0" "ISSUER_DECODE_ERROR\0" "NEED_ORGANIZATION_AND_NUMBERS\0" "NO_CONFIG_DATABASE\0" "NO_ISSUER_CERTIFICATE\0" "NO_ISSUER_DETAILS\0" "NO_POLICY_IDENTIFIER\0" "NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED\0" "NO_PUBLIC_KEY\0" "NO_SUBJECT_DETAILS\0" "ODD_NUMBER_OF_DIGITS\0" "OPERATION_NOT_DEFINED\0" "OTHERNAME_ERROR\0" "POLICY_LANGUAGE_ALREADY_DEFINED\0" "POLICY_PATH_LENGTH\0" "POLICY_PATH_LENGTH_ALREADY_DEFINED\0" "POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY\0" "SECTION_NOT_FOUND\0" "UNABLE_TO_GET_ISSUER_DETAILS\0" "UNABLE_TO_GET_ISSUER_KEYID\0" "UNKNOWN_BIT_STRING_ARGUMENT\0" "UNKNOWN_EXTENSION\0" "UNKNOWN_EXTENSION_NAME\0" "UNKNOWN_OPTION\0" "UNSUPPORTED_OPTION\0" "USER_TOO_LONG\0" ""; grpc-1.3.2/src/boringssl/gen_build_yaml.py000077500000000000000000000123651310511640000205660ustar00rootroot00000000000000#!/usr/bin/env python2.7 # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import shutil import sys import os import yaml sys.dont_write_bytecode = True boring_ssl_root = os.path.abspath(os.path.join( os.path.dirname(sys.argv[0]), '../../third_party/boringssl')) sys.path.append(os.path.join(boring_ssl_root, 'util')) try: import generate_build_files except ImportError: print yaml.dump({}) sys.exit() def map_dir(filename): if filename[0:4] == 'src/': return 'third_party/boringssl/' + filename[4:] else: return 'src/boringssl/' + filename def map_testarg(arg): if '/' in arg: return 'third_party/boringssl/' + arg else: return arg class Grpc(object): yaml = None def WriteFiles(self, files, asm_outputs): self.yaml = { '#': 'generated with tools/buildgen/gen_boring_ssl_build_yaml.py', 'raw_boringssl_build_output_for_debugging': { 'files': files, 'asm_outputs': asm_outputs, }, 'libs': [ { 'name': 'boringssl', 'build': 'private', 'language': 'c', 'secure': 'no', 'src': sorted( map_dir(f) for f in files['ssl'] + files['crypto'] ), 'headers': sorted( map_dir(f) for f in files['ssl_headers'] + files['ssl_internal_headers'] + files['crypto_headers'] + files['crypto_internal_headers'] ), 'boringssl': True, 'defaults': 'boringssl', }, { 'name': 'boringssl_test_util', 'build': 'private', 'language': 'c++', 'secure': 'no', 'boringssl': True, 'defaults': 'boringssl', 'src': [ map_dir(f) for f in sorted(files['test_support']) ], } ] + [ { 'name': 'boringssl_%s_lib' % os.path.splitext(os.path.basename(test))[0], 'build': 'private', 'secure': 'no', 'language': 'c' if os.path.splitext(test)[1] == '.c' else 'c++', 'src': [map_dir(test)], 'vs_proj_dir': 'test/boringssl', 'boringssl': True, 'defaults': 'boringssl', 'deps': [ 'boringssl_test_util', 'boringssl', ] } for test in sorted(files['test']) ], 'targets': [ { 'name': 'boringssl_%s' % os.path.splitext(os.path.basename(test))[0], 'build': 'test', 'run': False, 'secure': 'no', 'language': 'c++', 'src': [], 'vs_proj_dir': 'test/boringssl', 'boringssl': True, 'defaults': 'boringssl', 'deps': [ 'boringssl_%s_lib' % os.path.splitext(os.path.basename(test))[0], 'boringssl_test_util', 'boringssl', ] } for test in sorted(files['test']) ], 'tests': [ { 'name': 'boringssl_%s' % os.path.basename(test[0]), 'args': [map_testarg(arg) for arg in test[1:]], 'exclude_configs': ['asan'], 'ci_platforms': ['linux', 'mac', 'posix', 'windows'], 'platforms': ['linux', 'mac', 'posix', 'windows'], 'flaky': False, 'language': 'c++', 'boringssl': True, 'defaults': 'boringssl', 'cpu_cost': 1.0 } for test in files['tests'] ] } os.chdir(os.path.dirname(sys.argv[0])) os.mkdir('src') try: for f in os.listdir(boring_ssl_root): os.symlink(os.path.join(boring_ssl_root, f), os.path.join('src', f)) g = Grpc() generate_build_files.main([g]) print yaml.dump(g.yaml) finally: shutil.rmtree('src') grpc-1.3.2/src/c-ares/000077500000000000000000000000001310511640000144005ustar00rootroot00000000000000grpc-1.3.2/src/c-ares/CMakeLists.txt000066400000000000000000000042701310511640000171430ustar00rootroot00000000000000# c-ares cmake file for gRPC # # This is currently very experimental, and unsupported. # # Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. string(TOLOWER ${CMAKE_SYSTEM_NAME} cares_system_name) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../third_party/cares) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../third_party/cares/cares) if(${cares_system_name} MATCHES windows) add_definitions(-DCARES_STATICLIB=1) add_definitions(-DWIN32_LEAN_AND_MEAN=1) else() include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../third_party/cares/config_${cares_system_name}) add_definitions(-DHAVE_CONFIG_H=1) add_definitions(-D_GNU_SOURCE=1) endif() file(GLOB lib_sources ../../third_party/cares/cares/*.c) add_library(cares ${lib_sources}) grpc-1.3.2/src/c-ares/gen_build_yaml.py000077500000000000000000000144141310511640000177330ustar00rootroot00000000000000#!/usr/bin/env python2.7 # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import re import os import sys import yaml os.chdir(os.path.dirname(sys.argv[0])+'/../..') out = {} try: def gen_ares_build(x): subprocess.call("third_party/cares/cares/buildconf", shell=True) subprocess.call("third_party/cares/cares/configure", shell=True) def config_platform(x): if 'linux' in sys.platform: return 'src/cares/cares/config_linux/ares_config.h' if 'darwin' in sys.platform: return 'src/cares/cares/config_darwin/ares_config.h' if not os.path.isfile('third_party/cares/cares/ares_config.h'): gen_ares_build(x) return 'third_party/cares/cares/ares_config.h' def ares_build(x): if os.path.isfile('src/cares/cares/ares_build.h'): return 'src/cares/cares/ares_build.h' if not os.path.isfile('third_party/cares/cares/ares_build.h'): gen_ares_build(x) return 'third_party/cares/cares/ares_build.h' out['libs'] = [{ 'name': 'ares', 'defaults': 'ares', 'build': 'private', 'language': 'c', 'secure': 'no', 'src': [ "third_party/cares/cares/ares__close_sockets.c", "third_party/cares/cares/ares__get_hostent.c", "third_party/cares/cares/ares__read_line.c", "third_party/cares/cares/ares__timeval.c", "third_party/cares/cares/ares_cancel.c", "third_party/cares/cares/ares_create_query.c", "third_party/cares/cares/ares_data.c", "third_party/cares/cares/ares_destroy.c", "third_party/cares/cares/ares_expand_name.c", "third_party/cares/cares/ares_expand_string.c", "third_party/cares/cares/ares_fds.c", "third_party/cares/cares/ares_free_hostent.c", "third_party/cares/cares/ares_free_string.c", "third_party/cares/cares/ares_getenv.c", "third_party/cares/cares/ares_gethostbyaddr.c", "third_party/cares/cares/ares_gethostbyname.c", "third_party/cares/cares/ares_getnameinfo.c", "third_party/cares/cares/ares_getopt.c", "third_party/cares/cares/ares_getsock.c", "third_party/cares/cares/ares_init.c", "third_party/cares/cares/ares_library_init.c", "third_party/cares/cares/ares_llist.c", "third_party/cares/cares/ares_mkquery.c", "third_party/cares/cares/ares_nowarn.c", "third_party/cares/cares/ares_options.c", "third_party/cares/cares/ares_parse_a_reply.c", "third_party/cares/cares/ares_parse_aaaa_reply.c", "third_party/cares/cares/ares_parse_mx_reply.c", "third_party/cares/cares/ares_parse_naptr_reply.c", "third_party/cares/cares/ares_parse_ns_reply.c", "third_party/cares/cares/ares_parse_ptr_reply.c", "third_party/cares/cares/ares_parse_soa_reply.c", "third_party/cares/cares/ares_parse_srv_reply.c", "third_party/cares/cares/ares_parse_txt_reply.c", "third_party/cares/cares/ares_platform.c", "third_party/cares/cares/ares_process.c", "third_party/cares/cares/ares_query.c", "third_party/cares/cares/ares_search.c", "third_party/cares/cares/ares_send.c", "third_party/cares/cares/ares_strcasecmp.c", "third_party/cares/cares/ares_strdup.c", "third_party/cares/cares/ares_strerror.c", "third_party/cares/cares/ares_timeout.c", "third_party/cares/cares/ares_version.c", "third_party/cares/cares/ares_writev.c", "third_party/cares/cares/bitncmp.c", "third_party/cares/cares/inet_net_pton.c", "third_party/cares/cares/inet_ntop.c", "third_party/cares/cares/windows_port.c", ], 'headers': [ "third_party/cares/cares/ares.h", "third_party/cares/cares/ares_data.h", "third_party/cares/cares/ares_dns.h", "third_party/cares/cares/ares_getenv.h", "third_party/cares/cares/ares_getopt.h", "third_party/cares/cares/ares_inet_net_pton.h", "third_party/cares/cares/ares_iphlpapi.h", "third_party/cares/cares/ares_ipv6.h", "third_party/cares/cares/ares_library_init.h", "third_party/cares/cares/ares_llist.h", "third_party/cares/cares/ares_nowarn.h", "third_party/cares/cares/ares_platform.h", "third_party/cares/cares/ares_private.h", "third_party/cares/cares/ares_rules.h", "third_party/cares/cares/ares_setup.h", "third_party/cares/cares/ares_strcasecmp.h", "third_party/cares/cares/ares_strdup.h", "third_party/cares/cares/ares_version.h", "third_party/cares/cares/bitncmp.h", "third_party/cares/cares/config-win32.h", "third_party/cares/cares/setup_once.h", "third_party/cares/ares_build.h", "third_party/cares/config_linux/ares_config.h", "third_party/cares/config_darwin/ares_config.h" ], }] except: pass print yaml.dump(out) grpc-1.3.2/src/compiler/000077500000000000000000000000001310511640000150405ustar00rootroot00000000000000grpc-1.3.2/src/compiler/README.md000066400000000000000000000003201310511640000163120ustar00rootroot00000000000000# Overview This directory contains source code for gRPC protocol buffer compiler (*protoc*) plugins. Along with `protoc`, these plugins are used to generate gRPC client and server stubs from `.proto` files. grpc-1.3.2/src/compiler/config.h000066400000000000000000000071111310511640000164560ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef SRC_COMPILER_CONFIG_H #define SRC_COMPILER_CONFIG_H #include #ifndef GRPC_CUSTOM_CODEGENERATOR #include #define GRPC_CUSTOM_CODEGENERATOR ::google::protobuf::compiler::CodeGenerator #define GRPC_CUSTOM_GENERATORCONTEXT \ ::google::protobuf::compiler::GeneratorContext #endif #ifndef GRPC_CUSTOM_PRINTER #include #include #include #define GRPC_CUSTOM_PRINTER ::google::protobuf::io::Printer #define GRPC_CUSTOM_CODEDOUTPUTSTREAM ::google::protobuf::io::CodedOutputStream #define GRPC_CUSTOM_STRINGOUTPUTSTREAM \ ::google::protobuf::io::StringOutputStream #endif #ifndef GRPC_CUSTOM_PLUGINMAIN #include #define GRPC_CUSTOM_PLUGINMAIN ::google::protobuf::compiler::PluginMain #endif #ifndef GRPC_CUSTOM_PARSEGENERATORPARAMETER #include #define GRPC_CUSTOM_PARSEGENERATORPARAMETER \ ::google::protobuf::compiler::ParseGeneratorParameter #endif #ifndef GRPC_CUSTOM_STRING #include #define GRPC_CUSTOM_STRING std::string #endif namespace grpc { typedef GRPC_CUSTOM_STRING string; namespace protobuf { namespace compiler { typedef GRPC_CUSTOM_CODEGENERATOR CodeGenerator; typedef GRPC_CUSTOM_GENERATORCONTEXT GeneratorContext; static inline int PluginMain(int argc, char* argv[], const CodeGenerator* generator) { return GRPC_CUSTOM_PLUGINMAIN(argc, argv, generator); } static inline void ParseGeneratorParameter( const string& parameter, std::vector >* options) { GRPC_CUSTOM_PARSEGENERATORPARAMETER(parameter, options); } } // namespace compiler namespace io { typedef GRPC_CUSTOM_PRINTER Printer; typedef GRPC_CUSTOM_CODEDOUTPUTSTREAM CodedOutputStream; typedef GRPC_CUSTOM_STRINGOUTPUTSTREAM StringOutputStream; } // namespace io } // namespace protobuf } // namespace grpc #endif // SRC_COMPILER_CONFIG_H grpc-1.3.2/src/compiler/cpp_generator.cc000066400000000000000000001557441310511640000202170ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "src/compiler/cpp_generator.h" #include namespace grpc_cpp_generator { namespace { grpc::string message_header_ext() { return ".pb.h"; } grpc::string service_header_ext() { return ".grpc.pb.h"; } template grpc::string as_string(T x) { std::ostringstream out; out << x; return out.str(); } inline bool ClientOnlyStreaming(const grpc_generator::Method *method) { return method->ClientStreaming() && !method->ServerStreaming(); } inline bool ServerOnlyStreaming(const grpc_generator::Method *method) { return !method->ClientStreaming() && method->ServerStreaming(); } grpc::string FilenameIdentifier(const grpc::string &filename) { grpc::string result; for (unsigned i = 0; i < filename.size(); i++) { char c = filename[i]; if (isalnum(c)) { result.push_back(c); } else { static char hex[] = "0123456789abcdef"; result.push_back('_'); result.push_back(hex[(c >> 4) & 0xf]); result.push_back(hex[c & 0xf]); } } return result; } } // namespace template T *array_end(T (&array)[N]) { return array + N; } void PrintIncludes(grpc_generator::Printer *printer, const std::vector &headers, const Parameters ¶ms) { std::map vars; vars["l"] = params.use_system_headers ? '<' : '"'; vars["r"] = params.use_system_headers ? '>' : '"'; auto &s = params.grpc_search_path; if (!s.empty()) { vars["l"] += s; if (s[s.size() - 1] != '/') { vars["l"] += '/'; } } for (auto i = headers.begin(); i != headers.end(); i++) { vars["h"] = *i; printer->Print(vars, "#include $l$$h$$r$\n"); } } grpc::string GetHeaderPrologue(grpc_generator::File *file, const Parameters & /*params*/) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. auto printer = file->CreatePrinter(&output); std::map vars; vars["filename"] = file->filename(); vars["filename_identifier"] = FilenameIdentifier(file->filename()); vars["filename_base"] = file->filename_without_ext(); vars["message_header_ext"] = message_header_ext(); printer->Print(vars, "// Generated by the gRPC C++ plugin.\n"); printer->Print(vars, "// If you make any local change, they will be lost.\n"); printer->Print(vars, "// source: $filename$\n"); grpc::string leading_comments = file->GetLeadingComments("//"); if (!leading_comments.empty()) { printer->Print(vars, "// Original file comments:\n"); printer->Print(leading_comments.c_str()); } printer->Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n"); printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n"); printer->Print(vars, "\n"); printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n"); printer->Print(vars, "\n"); } return output; } grpc::string GetHeaderIncludes(grpc_generator::File *file, const Parameters ¶ms) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. auto printer = file->CreatePrinter(&output); std::map vars; static const char *headers_strs[] = { "grpc++/impl/codegen/async_stream.h", "grpc++/impl/codegen/async_unary_call.h", "grpc++/impl/codegen/method_handler_impl.h", "grpc++/impl/codegen/proto_utils.h", "grpc++/impl/codegen/rpc_method.h", "grpc++/impl/codegen/service_type.h", "grpc++/impl/codegen/status.h", "grpc++/impl/codegen/stub_options.h", "grpc++/impl/codegen/sync_stream.h"}; std::vector headers(headers_strs, array_end(headers_strs)); PrintIncludes(printer.get(), headers, params); printer->Print(vars, "\n"); printer->Print(vars, "namespace grpc {\n"); printer->Print(vars, "class CompletionQueue;\n"); printer->Print(vars, "class Channel;\n"); printer->Print(vars, "class RpcService;\n"); printer->Print(vars, "class ServerCompletionQueue;\n"); printer->Print(vars, "class ServerContext;\n"); printer->Print(vars, "} // namespace grpc\n\n"); if (!file->package().empty()) { std::vector parts = file->package_parts(); for (auto part = parts.begin(); part != parts.end(); part++) { vars["part"] = *part; printer->Print(vars, "namespace $part$ {\n"); } printer->Print(vars, "\n"); } } return output; } void PrintHeaderClientMethodInterfaces( grpc_generator::Printer *printer, const grpc_generator::Method *method, std::map *vars, bool is_public) { (*vars)["Method"] = method->name(); (*vars)["Request"] = method->input_type_name(); (*vars)["Response"] = method->output_type_name(); if (is_public) { if (method->NoStreaming()) { printer->Print( *vars, "virtual ::grpc::Status $Method$(::grpc::ClientContext* context, " "const $Request$& request, $Response$* response) = 0;\n"); printer->Print(*vars, "std::unique_ptr< " "::grpc::ClientAsyncResponseReaderInterface< $Response$>> " "Async$Method$(::grpc::ClientContext* context, " "const $Request$& request, " "::grpc::CompletionQueue* cq) {\n"); printer->Indent(); printer->Print(*vars, "return std::unique_ptr< " "::grpc::ClientAsyncResponseReaderInterface< $Response$>>(" "Async$Method$Raw(context, request, cq));\n"); printer->Outdent(); printer->Print("}\n"); } else if (ClientOnlyStreaming(method)) { printer->Print( *vars, "std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>" " $Method$(" "::grpc::ClientContext* context, $Response$* response) {\n"); printer->Indent(); printer->Print( *vars, "return std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>" "($Method$Raw(context, response));\n"); printer->Outdent(); printer->Print("}\n"); printer->Print( *vars, "std::unique_ptr< ::grpc::ClientAsyncWriterInterface< $Request$>>" " Async$Method$(::grpc::ClientContext* context, $Response$* " "response, " "::grpc::CompletionQueue* cq, void* tag) {\n"); printer->Indent(); printer->Print(*vars, "return std::unique_ptr< " "::grpc::ClientAsyncWriterInterface< $Request$>>(" "Async$Method$Raw(context, response, cq, tag));\n"); printer->Outdent(); printer->Print("}\n"); } else if (ServerOnlyStreaming(method)) { printer->Print( *vars, "std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>" " $Method$(::grpc::ClientContext* context, const $Request$& request)" " {\n"); printer->Indent(); printer->Print( *vars, "return std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>" "($Method$Raw(context, request));\n"); printer->Outdent(); printer->Print("}\n"); printer->Print( *vars, "std::unique_ptr< ::grpc::ClientAsyncReaderInterface< $Response$>> " "Async$Method$(" "::grpc::ClientContext* context, const $Request$& request, " "::grpc::CompletionQueue* cq, void* tag) {\n"); printer->Indent(); printer->Print(*vars, "return std::unique_ptr< " "::grpc::ClientAsyncReaderInterface< $Response$>>(" "Async$Method$Raw(context, request, cq, tag));\n"); printer->Outdent(); printer->Print("}\n"); } else if (method->BidiStreaming()) { printer->Print(*vars, "std::unique_ptr< ::grpc::ClientReaderWriterInterface< " "$Request$, $Response$>> " "$Method$(::grpc::ClientContext* context) {\n"); printer->Indent(); printer->Print( *vars, "return std::unique_ptr< " "::grpc::ClientReaderWriterInterface< $Request$, $Response$>>(" "$Method$Raw(context));\n"); printer->Outdent(); printer->Print("}\n"); printer->Print( *vars, "std::unique_ptr< " "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>> " "Async$Method$(::grpc::ClientContext* context, " "::grpc::CompletionQueue* cq, void* tag) {\n"); printer->Indent(); printer->Print( *vars, "return std::unique_ptr< " "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>>(" "Async$Method$Raw(context, cq, tag));\n"); printer->Outdent(); printer->Print("}\n"); } } else { if (method->NoStreaming()) { printer->Print( *vars, "virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* " "Async$Method$Raw(::grpc::ClientContext* context, " "const $Request$& request, " "::grpc::CompletionQueue* cq) = 0;\n"); } else if (ClientOnlyStreaming(method)) { printer->Print( *vars, "virtual ::grpc::ClientWriterInterface< $Request$>*" " $Method$Raw(" "::grpc::ClientContext* context, $Response$* response) = 0;\n"); printer->Print(*vars, "virtual ::grpc::ClientAsyncWriterInterface< $Request$>*" " Async$Method$Raw(::grpc::ClientContext* context, " "$Response$* response, " "::grpc::CompletionQueue* cq, void* tag) = 0;\n"); } else if (ServerOnlyStreaming(method)) { printer->Print( *vars, "virtual ::grpc::ClientReaderInterface< $Response$>* $Method$Raw(" "::grpc::ClientContext* context, const $Request$& request) = 0;\n"); printer->Print( *vars, "virtual ::grpc::ClientAsyncReaderInterface< $Response$>* " "Async$Method$Raw(" "::grpc::ClientContext* context, const $Request$& request, " "::grpc::CompletionQueue* cq, void* tag) = 0;\n"); } else if (method->BidiStreaming()) { printer->Print(*vars, "virtual ::grpc::ClientReaderWriterInterface< $Request$, " "$Response$>* " "$Method$Raw(::grpc::ClientContext* context) = 0;\n"); printer->Print(*vars, "virtual ::grpc::ClientAsyncReaderWriterInterface< " "$Request$, $Response$>* " "Async$Method$Raw(::grpc::ClientContext* context, " "::grpc::CompletionQueue* cq, void* tag) = 0;\n"); } } } void PrintHeaderClientMethod(grpc_generator::Printer *printer, const grpc_generator::Method *method, std::map *vars, bool is_public) { (*vars)["Method"] = method->name(); (*vars)["Request"] = method->input_type_name(); (*vars)["Response"] = method->output_type_name(); if (is_public) { if (method->NoStreaming()) { printer->Print( *vars, "::grpc::Status $Method$(::grpc::ClientContext* context, " "const $Request$& request, $Response$* response) override;\n"); printer->Print( *vars, "std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> " "Async$Method$(::grpc::ClientContext* context, " "const $Request$& request, " "::grpc::CompletionQueue* cq) {\n"); printer->Indent(); printer->Print(*vars, "return std::unique_ptr< " "::grpc::ClientAsyncResponseReader< $Response$>>(" "Async$Method$Raw(context, request, cq));\n"); printer->Outdent(); printer->Print("}\n"); } else if (ClientOnlyStreaming(method)) { printer->Print( *vars, "std::unique_ptr< ::grpc::ClientWriter< $Request$>>" " $Method$(" "::grpc::ClientContext* context, $Response$* response) {\n"); printer->Indent(); printer->Print(*vars, "return std::unique_ptr< ::grpc::ClientWriter< $Request$>>" "($Method$Raw(context, response));\n"); printer->Outdent(); printer->Print("}\n"); printer->Print(*vars, "std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>" " Async$Method$(::grpc::ClientContext* context, " "$Response$* response, " "::grpc::CompletionQueue* cq, void* tag) {\n"); printer->Indent(); printer->Print( *vars, "return std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>(" "Async$Method$Raw(context, response, cq, tag));\n"); printer->Outdent(); printer->Print("}\n"); } else if (ServerOnlyStreaming(method)) { printer->Print( *vars, "std::unique_ptr< ::grpc::ClientReader< $Response$>>" " $Method$(::grpc::ClientContext* context, const $Request$& request)" " {\n"); printer->Indent(); printer->Print( *vars, "return std::unique_ptr< ::grpc::ClientReader< $Response$>>" "($Method$Raw(context, request));\n"); printer->Outdent(); printer->Print("}\n"); printer->Print( *vars, "std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> " "Async$Method$(" "::grpc::ClientContext* context, const $Request$& request, " "::grpc::CompletionQueue* cq, void* tag) {\n"); printer->Indent(); printer->Print( *vars, "return std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>>(" "Async$Method$Raw(context, request, cq, tag));\n"); printer->Outdent(); printer->Print("}\n"); } else if (method->BidiStreaming()) { printer->Print( *vars, "std::unique_ptr< ::grpc::ClientReaderWriter< $Request$, $Response$>>" " $Method$(::grpc::ClientContext* context) {\n"); printer->Indent(); printer->Print(*vars, "return std::unique_ptr< " "::grpc::ClientReaderWriter< $Request$, $Response$>>(" "$Method$Raw(context));\n"); printer->Outdent(); printer->Print("}\n"); printer->Print(*vars, "std::unique_ptr< ::grpc::ClientAsyncReaderWriter< " "$Request$, $Response$>> " "Async$Method$(::grpc::ClientContext* context, " "::grpc::CompletionQueue* cq, void* tag) {\n"); printer->Indent(); printer->Print(*vars, "return std::unique_ptr< " "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>>(" "Async$Method$Raw(context, cq, tag));\n"); printer->Outdent(); printer->Print("}\n"); } } else { if (method->NoStreaming()) { printer->Print(*vars, "::grpc::ClientAsyncResponseReader< $Response$>* " "Async$Method$Raw(::grpc::ClientContext* context, " "const $Request$& request, " "::grpc::CompletionQueue* cq) override;\n"); } else if (ClientOnlyStreaming(method)) { printer->Print(*vars, "::grpc::ClientWriter< $Request$>* $Method$Raw(" "::grpc::ClientContext* context, $Response$* response) " "override;\n"); printer->Print(*vars, "::grpc::ClientAsyncWriter< $Request$>* Async$Method$Raw(" "::grpc::ClientContext* context, $Response$* response, " "::grpc::CompletionQueue* cq, void* tag) override;\n"); } else if (ServerOnlyStreaming(method)) { printer->Print(*vars, "::grpc::ClientReader< $Response$>* $Method$Raw(" "::grpc::ClientContext* context, const $Request$& request)" " override;\n"); printer->Print( *vars, "::grpc::ClientAsyncReader< $Response$>* Async$Method$Raw(" "::grpc::ClientContext* context, const $Request$& request, " "::grpc::CompletionQueue* cq, void* tag) override;\n"); } else if (method->BidiStreaming()) { printer->Print(*vars, "::grpc::ClientReaderWriter< $Request$, $Response$>* " "$Method$Raw(::grpc::ClientContext* context) override;\n"); printer->Print(*vars, "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* " "Async$Method$Raw(::grpc::ClientContext* context, " "::grpc::CompletionQueue* cq, void* tag) override;\n"); } } } void PrintHeaderClientMethodData(grpc_generator::Printer *printer, const grpc_generator::Method *method, std::map *vars) { (*vars)["Method"] = method->name(); printer->Print(*vars, "const ::grpc::RpcMethod rpcmethod_$Method$_;\n"); } void PrintHeaderServerMethodSync(grpc_generator::Printer *printer, const grpc_generator::Method *method, std::map *vars) { (*vars)["Method"] = method->name(); (*vars)["Request"] = method->input_type_name(); (*vars)["Response"] = method->output_type_name(); printer->Print(method->GetLeadingComments("//").c_str()); if (method->NoStreaming()) { printer->Print(*vars, "virtual ::grpc::Status $Method$(" "::grpc::ServerContext* context, const $Request$* request, " "$Response$* response);\n"); } else if (ClientOnlyStreaming(method)) { printer->Print(*vars, "virtual ::grpc::Status $Method$(" "::grpc::ServerContext* context, " "::grpc::ServerReader< $Request$>* reader, " "$Response$* response);\n"); } else if (ServerOnlyStreaming(method)) { printer->Print(*vars, "virtual ::grpc::Status $Method$(" "::grpc::ServerContext* context, const $Request$* request, " "::grpc::ServerWriter< $Response$>* writer);\n"); } else if (method->BidiStreaming()) { printer->Print( *vars, "virtual ::grpc::Status $Method$(" "::grpc::ServerContext* context, " "::grpc::ServerReaderWriter< $Response$, $Request$>* stream);" "\n"); } printer->Print(method->GetTrailingComments("//").c_str()); } void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer, const grpc_generator::Method *method, std::map *vars) { (*vars)["Method"] = method->name(); (*vars)["Request"] = method->input_type_name(); (*vars)["Response"] = method->output_type_name(); printer->Print(*vars, "template \n"); printer->Print(*vars, "class WithAsyncMethod_$Method$ : public BaseClass {\n"); printer->Print( " private:\n" " void BaseClassMustBeDerivedFromService(const Service *service) {}\n"); printer->Print(" public:\n"); printer->Indent(); printer->Print(*vars, "WithAsyncMethod_$Method$() {\n" " ::grpc::Service::MarkMethodAsync($Idx$);\n" "}\n"); printer->Print(*vars, "~WithAsyncMethod_$Method$() override {\n" " BaseClassMustBeDerivedFromService(this);\n" "}\n"); if (method->NoStreaming()) { printer->Print( *vars, "// disable synchronous version of this method\n" "::grpc::Status $Method$(" "::grpc::ServerContext* context, const $Request$* request, " "$Response$* response) final override {\n" " abort();\n" " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" "}\n"); printer->Print( *vars, "void Request$Method$(" "::grpc::ServerContext* context, $Request$* request, " "::grpc::ServerAsyncResponseWriter< $Response$>* response, " "::grpc::CompletionQueue* new_call_cq, " "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n"); printer->Print(*vars, " ::grpc::Service::RequestAsyncUnary($Idx$, context, " "request, response, new_call_cq, notification_cq, tag);\n"); printer->Print("}\n"); } else if (ClientOnlyStreaming(method)) { printer->Print( *vars, "// disable synchronous version of this method\n" "::grpc::Status $Method$(" "::grpc::ServerContext* context, " "::grpc::ServerReader< $Request$>* reader, " "$Response$* response) final override {\n" " abort();\n" " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" "}\n"); printer->Print( *vars, "void Request$Method$(" "::grpc::ServerContext* context, " "::grpc::ServerAsyncReader< $Response$, $Request$>* reader, " "::grpc::CompletionQueue* new_call_cq, " "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n"); printer->Print(*vars, " ::grpc::Service::RequestAsyncClientStreaming($Idx$, " "context, reader, new_call_cq, notification_cq, tag);\n"); printer->Print("}\n"); } else if (ServerOnlyStreaming(method)) { printer->Print( *vars, "// disable synchronous version of this method\n" "::grpc::Status $Method$(" "::grpc::ServerContext* context, const $Request$* request, " "::grpc::ServerWriter< $Response$>* writer) final override " "{\n" " abort();\n" " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" "}\n"); printer->Print( *vars, "void Request$Method$(" "::grpc::ServerContext* context, $Request$* request, " "::grpc::ServerAsyncWriter< $Response$>* writer, " "::grpc::CompletionQueue* new_call_cq, " "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n"); printer->Print( *vars, " ::grpc::Service::RequestAsyncServerStreaming($Idx$, " "context, request, writer, new_call_cq, notification_cq, tag);\n"); printer->Print("}\n"); } else if (method->BidiStreaming()) { printer->Print( *vars, "// disable synchronous version of this method\n" "::grpc::Status $Method$(" "::grpc::ServerContext* context, " "::grpc::ServerReaderWriter< $Response$, $Request$>* stream) " "final override {\n" " abort();\n" " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" "}\n"); printer->Print( *vars, "void Request$Method$(" "::grpc::ServerContext* context, " "::grpc::ServerAsyncReaderWriter< $Response$, $Request$>* stream, " "::grpc::CompletionQueue* new_call_cq, " "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n"); printer->Print(*vars, " ::grpc::Service::RequestAsyncBidiStreaming($Idx$, " "context, stream, new_call_cq, notification_cq, tag);\n"); printer->Print("}\n"); } printer->Outdent(); printer->Print(*vars, "};\n"); } void PrintHeaderServerMethodStreamedUnary( grpc_generator::Printer *printer, const grpc_generator::Method *method, std::map *vars) { (*vars)["Method"] = method->name(); (*vars)["Request"] = method->input_type_name(); (*vars)["Response"] = method->output_type_name(); if (method->NoStreaming()) { printer->Print(*vars, "template \n"); printer->Print(*vars, "class WithStreamedUnaryMethod_$Method$ : " "public BaseClass {\n"); printer->Print( " private:\n" " void BaseClassMustBeDerivedFromService(const Service *service) " "{}\n"); printer->Print(" public:\n"); printer->Indent(); printer->Print(*vars, "WithStreamedUnaryMethod_$Method$() {\n" " ::grpc::Service::MarkMethodStreamed($Idx$,\n" " new ::grpc::StreamedUnaryHandler< $Request$, " "$Response$>(std::bind" "(&WithStreamedUnaryMethod_$Method$::" "Streamed$Method$, this, std::placeholders::_1, " "std::placeholders::_2)));\n" "}\n"); printer->Print(*vars, "~WithStreamedUnaryMethod_$Method$() override {\n" " BaseClassMustBeDerivedFromService(this);\n" "}\n"); printer->Print( *vars, "// disable regular version of this method\n" "::grpc::Status $Method$(" "::grpc::ServerContext* context, const $Request$* request, " "$Response$* response) final override {\n" " abort();\n" " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" "}\n"); printer->Print(*vars, "// replace default version of method with streamed unary\n" "virtual ::grpc::Status Streamed$Method$(" "::grpc::ServerContext* context, " "::grpc::ServerUnaryStreamer< " "$Request$,$Response$>* server_unary_streamer)" " = 0;\n"); printer->Outdent(); printer->Print(*vars, "};\n"); } } void PrintHeaderServerMethodSplitStreaming( grpc_generator::Printer *printer, const grpc_generator::Method *method, std::map *vars) { (*vars)["Method"] = method->name(); (*vars)["Request"] = method->input_type_name(); (*vars)["Response"] = method->output_type_name(); if (ServerOnlyStreaming(method)) { printer->Print(*vars, "template \n"); printer->Print(*vars, "class WithSplitStreamingMethod_$Method$ : " "public BaseClass {\n"); printer->Print( " private:\n" " void BaseClassMustBeDerivedFromService(const Service *service) " "{}\n"); printer->Print(" public:\n"); printer->Indent(); printer->Print(*vars, "WithSplitStreamingMethod_$Method$() {\n" " ::grpc::Service::MarkMethodStreamed($Idx$,\n" " new ::grpc::SplitServerStreamingHandler< $Request$, " "$Response$>(std::bind" "(&WithSplitStreamingMethod_$Method$::" "Streamed$Method$, this, std::placeholders::_1, " "std::placeholders::_2)));\n" "}\n"); printer->Print(*vars, "~WithSplitStreamingMethod_$Method$() override {\n" " BaseClassMustBeDerivedFromService(this);\n" "}\n"); printer->Print( *vars, "// disable regular version of this method\n" "::grpc::Status $Method$(" "::grpc::ServerContext* context, const $Request$* request, " "::grpc::ServerWriter< $Response$>* writer) final override " "{\n" " abort();\n" " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" "}\n"); printer->Print(*vars, "// replace default version of method with split streamed\n" "virtual ::grpc::Status Streamed$Method$(" "::grpc::ServerContext* context, " "::grpc::ServerSplitStreamer< " "$Request$,$Response$>* server_split_streamer)" " = 0;\n"); printer->Outdent(); printer->Print(*vars, "};\n"); } } void PrintHeaderServerMethodGeneric( grpc_generator::Printer *printer, const grpc_generator::Method *method, std::map *vars) { (*vars)["Method"] = method->name(); (*vars)["Request"] = method->input_type_name(); (*vars)["Response"] = method->output_type_name(); printer->Print(*vars, "template \n"); printer->Print(*vars, "class WithGenericMethod_$Method$ : public BaseClass {\n"); printer->Print( " private:\n" " void BaseClassMustBeDerivedFromService(const Service *service) {}\n"); printer->Print(" public:\n"); printer->Indent(); printer->Print(*vars, "WithGenericMethod_$Method$() {\n" " ::grpc::Service::MarkMethodGeneric($Idx$);\n" "}\n"); printer->Print(*vars, "~WithGenericMethod_$Method$() override {\n" " BaseClassMustBeDerivedFromService(this);\n" "}\n"); if (method->NoStreaming()) { printer->Print( *vars, "// disable synchronous version of this method\n" "::grpc::Status $Method$(" "::grpc::ServerContext* context, const $Request$* request, " "$Response$* response) final override {\n" " abort();\n" " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" "}\n"); } else if (ClientOnlyStreaming(method)) { printer->Print( *vars, "// disable synchronous version of this method\n" "::grpc::Status $Method$(" "::grpc::ServerContext* context, " "::grpc::ServerReader< $Request$>* reader, " "$Response$* response) final override {\n" " abort();\n" " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" "}\n"); } else if (ServerOnlyStreaming(method)) { printer->Print( *vars, "// disable synchronous version of this method\n" "::grpc::Status $Method$(" "::grpc::ServerContext* context, const $Request$* request, " "::grpc::ServerWriter< $Response$>* writer) final override " "{\n" " abort();\n" " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" "}\n"); } else if (method->BidiStreaming()) { printer->Print( *vars, "// disable synchronous version of this method\n" "::grpc::Status $Method$(" "::grpc::ServerContext* context, " "::grpc::ServerReaderWriter< $Response$, $Request$>* stream) " "final override {\n" " abort();\n" " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" "}\n"); } printer->Outdent(); printer->Print(*vars, "};\n"); } void PrintHeaderService(grpc_generator::Printer *printer, const grpc_generator::Service *service, std::map *vars) { (*vars)["Service"] = service->name(); printer->Print(service->GetLeadingComments("//").c_str()); printer->Print(*vars, "class $Service$ final {\n" " public:\n"); printer->Indent(); // Client side printer->Print( "class StubInterface {\n" " public:\n"); printer->Indent(); printer->Print("virtual ~StubInterface() {}\n"); for (int i = 0; i < service->method_count(); ++i) { printer->Print(service->method(i)->GetLeadingComments("//").c_str()); PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars, true); printer->Print(service->method(i)->GetTrailingComments("//").c_str()); } printer->Outdent(); printer->Print("private:\n"); printer->Indent(); for (int i = 0; i < service->method_count(); ++i) { PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars, false); } printer->Outdent(); printer->Print("};\n"); printer->Print( "class Stub final : public StubInterface" " {\n public:\n"); printer->Indent(); printer->Print( "Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel);\n"); for (int i = 0; i < service->method_count(); ++i) { PrintHeaderClientMethod(printer, service->method(i).get(), vars, true); } printer->Outdent(); printer->Print("\n private:\n"); printer->Indent(); printer->Print("std::shared_ptr< ::grpc::ChannelInterface> channel_;\n"); for (int i = 0; i < service->method_count(); ++i) { PrintHeaderClientMethod(printer, service->method(i).get(), vars, false); } for (int i = 0; i < service->method_count(); ++i) { PrintHeaderClientMethodData(printer, service->method(i).get(), vars); } printer->Outdent(); printer->Print("};\n"); printer->Print( "static std::unique_ptr NewStub(const std::shared_ptr< " "::grpc::ChannelInterface>& channel, " "const ::grpc::StubOptions& options = ::grpc::StubOptions());\n"); printer->Print("\n"); // Server side - base printer->Print( "class Service : public ::grpc::Service {\n" " public:\n"); printer->Indent(); printer->Print("Service();\n"); printer->Print("virtual ~Service();\n"); for (int i = 0; i < service->method_count(); ++i) { PrintHeaderServerMethodSync(printer, service->method(i).get(), vars); } printer->Outdent(); printer->Print("};\n"); // Server side - Asynchronous for (int i = 0; i < service->method_count(); ++i) { (*vars)["Idx"] = as_string(i); PrintHeaderServerMethodAsync(printer, service->method(i).get(), vars); } printer->Print("typedef "); for (int i = 0; i < service->method_count(); ++i) { (*vars)["method_name"] = service->method(i).get()->name(); printer->Print(*vars, "WithAsyncMethod_$method_name$<"); } printer->Print("Service"); for (int i = 0; i < service->method_count(); ++i) { printer->Print(" >"); } printer->Print(" AsyncService;\n"); // Server side - Generic for (int i = 0; i < service->method_count(); ++i) { (*vars)["Idx"] = as_string(i); PrintHeaderServerMethodGeneric(printer, service->method(i).get(), vars); } // Server side - Streamed Unary for (int i = 0; i < service->method_count(); ++i) { (*vars)["Idx"] = as_string(i); PrintHeaderServerMethodStreamedUnary(printer, service->method(i).get(), vars); } printer->Print("typedef "); for (int i = 0; i < service->method_count(); ++i) { (*vars)["method_name"] = service->method(i).get()->name(); if (service->method(i)->NoStreaming()) { printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<"); } } printer->Print("Service"); for (int i = 0; i < service->method_count(); ++i) { if (service->method(i)->NoStreaming()) { printer->Print(" >"); } } printer->Print(" StreamedUnaryService;\n"); // Server side - controlled server-side streaming for (int i = 0; i < service->method_count(); ++i) { (*vars)["Idx"] = as_string(i); PrintHeaderServerMethodSplitStreaming(printer, service->method(i).get(), vars); } printer->Print("typedef "); for (int i = 0; i < service->method_count(); ++i) { (*vars)["method_name"] = service->method(i).get()->name(); auto method = service->method(i); if (ServerOnlyStreaming(method.get())) { printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<"); } } printer->Print("Service"); for (int i = 0; i < service->method_count(); ++i) { auto method = service->method(i); if (ServerOnlyStreaming(method.get())) { printer->Print(" >"); } } printer->Print(" SplitStreamedService;\n"); // Server side - typedef for controlled both unary and server-side streaming printer->Print("typedef "); for (int i = 0; i < service->method_count(); ++i) { (*vars)["method_name"] = service->method(i).get()->name(); auto method = service->method(i); if (ServerOnlyStreaming(method.get())) { printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<"); } if (service->method(i)->NoStreaming()) { printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<"); } } printer->Print("Service"); for (int i = 0; i < service->method_count(); ++i) { auto method = service->method(i); if (service->method(i)->NoStreaming() || ServerOnlyStreaming(method.get())) { printer->Print(" >"); } } printer->Print(" StreamedService;\n"); printer->Outdent(); printer->Print("};\n"); printer->Print(service->GetTrailingComments("//").c_str()); } grpc::string GetHeaderServices(grpc_generator::File *file, const Parameters ¶ms) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. auto printer = file->CreatePrinter(&output); std::map vars; // Package string is empty or ends with a dot. It is used to fully qualify // method names. vars["Package"] = file->package(); if (!file->package().empty()) { vars["Package"].append("."); } if (!params.services_namespace.empty()) { vars["services_namespace"] = params.services_namespace; printer->Print(vars, "\nnamespace $services_namespace$ {\n\n"); } for (int i = 0; i < file->service_count(); ++i) { PrintHeaderService(printer.get(), file->service(i).get(), &vars); printer->Print("\n"); } if (!params.services_namespace.empty()) { printer->Print(vars, "} // namespace $services_namespace$\n\n"); } } return output; } grpc::string GetHeaderEpilogue(grpc_generator::File *file, const Parameters & /*params*/) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. auto printer = file->CreatePrinter(&output); std::map vars; vars["filename"] = file->filename(); vars["filename_identifier"] = FilenameIdentifier(file->filename()); if (!file->package().empty()) { std::vector parts = file->package_parts(); for (auto part = parts.rbegin(); part != parts.rend(); part++) { vars["part"] = *part; printer->Print(vars, "} // namespace $part$\n"); } printer->Print(vars, "\n"); } printer->Print(vars, "\n"); printer->Print(vars, "#endif // GRPC_$filename_identifier$__INCLUDED\n"); printer->Print(file->GetTrailingComments("//").c_str()); } return output; } grpc::string GetSourcePrologue(grpc_generator::File *file, const Parameters & /*params*/) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. auto printer = file->CreatePrinter(&output); std::map vars; vars["filename"] = file->filename(); vars["filename_base"] = file->filename_without_ext(); vars["message_header_ext"] = message_header_ext(); vars["service_header_ext"] = service_header_ext(); printer->Print(vars, "// Generated by the gRPC C++ plugin.\n"); printer->Print(vars, "// If you make any local change, they will be lost.\n"); printer->Print(vars, "// source: $filename$\n\n"); printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n"); printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n"); printer->Print(vars, file->additional_headers().c_str()); printer->Print(vars, "\n"); } return output; } grpc::string GetSourceIncludes(grpc_generator::File *file, const Parameters ¶ms) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. auto printer = file->CreatePrinter(&output); std::map vars; static const char *headers_strs[] = { "grpc++/impl/codegen/async_stream.h", "grpc++/impl/codegen/async_unary_call.h", "grpc++/impl/codegen/channel_interface.h", "grpc++/impl/codegen/client_unary_call.h", "grpc++/impl/codegen/method_handler_impl.h", "grpc++/impl/codegen/rpc_service_method.h", "grpc++/impl/codegen/service_type.h", "grpc++/impl/codegen/sync_stream.h"}; std::vector headers(headers_strs, array_end(headers_strs)); PrintIncludes(printer.get(), headers, params); if (!file->package().empty()) { std::vector parts = file->package_parts(); for (auto part = parts.begin(); part != parts.end(); part++) { vars["part"] = *part; printer->Print(vars, "namespace $part$ {\n"); } } printer->Print(vars, "\n"); } return output; } void PrintSourceClientMethod(grpc_generator::Printer *printer, const grpc_generator::Method *method, std::map *vars) { (*vars)["Method"] = method->name(); (*vars)["Request"] = method->input_type_name(); (*vars)["Response"] = method->output_type_name(); if (method->NoStreaming()) { printer->Print(*vars, "::grpc::Status $ns$$Service$::Stub::$Method$(" "::grpc::ClientContext* context, " "const $Request$& request, $Response$* response) {\n"); printer->Print(*vars, " return ::grpc::BlockingUnaryCall(channel_.get(), " "rpcmethod_$Method$_, " "context, request, response);\n" "}\n\n"); printer->Print( *vars, "::grpc::ClientAsyncResponseReader< $Response$>* " "$ns$$Service$::Stub::Async$Method$Raw(::grpc::ClientContext* context, " "const $Request$& request, " "::grpc::CompletionQueue* cq) {\n"); printer->Print(*vars, " return new " "::grpc::ClientAsyncResponseReader< $Response$>(" "channel_.get(), cq, " "rpcmethod_$Method$_, " "context, request);\n" "}\n\n"); } else if (ClientOnlyStreaming(method)) { printer->Print(*vars, "::grpc::ClientWriter< $Request$>* " "$ns$$Service$::Stub::$Method$Raw(" "::grpc::ClientContext* context, $Response$* response) {\n"); printer->Print(*vars, " return new ::grpc::ClientWriter< $Request$>(" "channel_.get(), " "rpcmethod_$Method$_, " "context, response);\n" "}\n\n"); printer->Print(*vars, "::grpc::ClientAsyncWriter< $Request$>* " "$ns$$Service$::Stub::Async$Method$Raw(" "::grpc::ClientContext* context, $Response$* response, " "::grpc::CompletionQueue* cq, void* tag) {\n"); printer->Print(*vars, " return new ::grpc::ClientAsyncWriter< $Request$>(" "channel_.get(), cq, " "rpcmethod_$Method$_, " "context, response, tag);\n" "}\n\n"); } else if (ServerOnlyStreaming(method)) { printer->Print( *vars, "::grpc::ClientReader< $Response$>* " "$ns$$Service$::Stub::$Method$Raw(" "::grpc::ClientContext* context, const $Request$& request) {\n"); printer->Print(*vars, " return new ::grpc::ClientReader< $Response$>(" "channel_.get(), " "rpcmethod_$Method$_, " "context, request);\n" "}\n\n"); printer->Print(*vars, "::grpc::ClientAsyncReader< $Response$>* " "$ns$$Service$::Stub::Async$Method$Raw(" "::grpc::ClientContext* context, const $Request$& request, " "::grpc::CompletionQueue* cq, void* tag) {\n"); printer->Print(*vars, " return new ::grpc::ClientAsyncReader< $Response$>(" "channel_.get(), cq, " "rpcmethod_$Method$_, " "context, request, tag);\n" "}\n\n"); } else if (method->BidiStreaming()) { printer->Print( *vars, "::grpc::ClientReaderWriter< $Request$, $Response$>* " "$ns$$Service$::Stub::$Method$Raw(::grpc::ClientContext* context) {\n"); printer->Print(*vars, " return new ::grpc::ClientReaderWriter< " "$Request$, $Response$>(" "channel_.get(), " "rpcmethod_$Method$_, " "context);\n" "}\n\n"); printer->Print( *vars, "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* " "$ns$$Service$::Stub::Async$Method$Raw(::grpc::ClientContext* context, " "::grpc::CompletionQueue* cq, void* tag) {\n"); printer->Print(*vars, " return new " "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>(" "channel_.get(), cq, " "rpcmethod_$Method$_, " "context, tag);\n" "}\n\n"); } } void PrintSourceServerMethod(grpc_generator::Printer *printer, const grpc_generator::Method *method, std::map *vars) { (*vars)["Method"] = method->name(); (*vars)["Request"] = method->input_type_name(); (*vars)["Response"] = method->output_type_name(); if (method->NoStreaming()) { printer->Print(*vars, "::grpc::Status $ns$$Service$::Service::$Method$(" "::grpc::ServerContext* context, " "const $Request$* request, $Response$* response) {\n"); printer->Print(" (void) context;\n"); printer->Print(" (void) request;\n"); printer->Print(" (void) response;\n"); printer->Print( " return ::grpc::Status(" "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"); printer->Print("}\n\n"); } else if (ClientOnlyStreaming(method)) { printer->Print(*vars, "::grpc::Status $ns$$Service$::Service::$Method$(" "::grpc::ServerContext* context, " "::grpc::ServerReader< $Request$>* reader, " "$Response$* response) {\n"); printer->Print(" (void) context;\n"); printer->Print(" (void) reader;\n"); printer->Print(" (void) response;\n"); printer->Print( " return ::grpc::Status(" "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"); printer->Print("}\n\n"); } else if (ServerOnlyStreaming(method)) { printer->Print(*vars, "::grpc::Status $ns$$Service$::Service::$Method$(" "::grpc::ServerContext* context, " "const $Request$* request, " "::grpc::ServerWriter< $Response$>* writer) {\n"); printer->Print(" (void) context;\n"); printer->Print(" (void) request;\n"); printer->Print(" (void) writer;\n"); printer->Print( " return ::grpc::Status(" "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"); printer->Print("}\n\n"); } else if (method->BidiStreaming()) { printer->Print(*vars, "::grpc::Status $ns$$Service$::Service::$Method$(" "::grpc::ServerContext* context, " "::grpc::ServerReaderWriter< $Response$, $Request$>* " "stream) {\n"); printer->Print(" (void) context;\n"); printer->Print(" (void) stream;\n"); printer->Print( " return ::grpc::Status(" "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"); printer->Print("}\n\n"); } } void PrintSourceService(grpc_generator::Printer *printer, const grpc_generator::Service *service, std::map *vars) { (*vars)["Service"] = service->name(); if (service->method_count() > 0) { printer->Print(*vars, "static const char* $prefix$$Service$_method_names[] = {\n"); for (int i = 0; i < service->method_count(); ++i) { (*vars)["Method"] = service->method(i).get()->name(); printer->Print(*vars, " \"/$Package$$Service$/$Method$\",\n"); } printer->Print(*vars, "};\n\n"); } printer->Print(*vars, "std::unique_ptr< $ns$$Service$::Stub> $ns$$Service$::NewStub(" "const std::shared_ptr< ::grpc::ChannelInterface>& channel, " "const ::grpc::StubOptions& options) {\n" " std::unique_ptr< $ns$$Service$::Stub> stub(new " "$ns$$Service$::Stub(channel));\n" " return stub;\n" "}\n\n"); printer->Print(*vars, "$ns$$Service$::Stub::Stub(const std::shared_ptr< " "::grpc::ChannelInterface>& channel)\n"); printer->Indent(); printer->Print(": channel_(channel)"); for (int i = 0; i < service->method_count(); ++i) { auto method = service->method(i); (*vars)["Method"] = method->name(); (*vars)["Idx"] = as_string(i); if (method->NoStreaming()) { (*vars)["StreamingType"] = "NORMAL_RPC"; // NOTE: There is no reason to consider streamed-unary as a separate // category here since this part is setting up the client-side stub // and this appears as a NORMAL_RPC from the client-side. } else if (ClientOnlyStreaming(method.get())) { (*vars)["StreamingType"] = "CLIENT_STREAMING"; } else if (ServerOnlyStreaming(method.get())) { (*vars)["StreamingType"] = "SERVER_STREAMING"; } else { (*vars)["StreamingType"] = "BIDI_STREAMING"; } printer->Print(*vars, ", rpcmethod_$Method$_(" "$prefix$$Service$_method_names[$Idx$], " "::grpc::RpcMethod::$StreamingType$, " "channel" ")\n"); } printer->Print("{}\n\n"); printer->Outdent(); for (int i = 0; i < service->method_count(); ++i) { (*vars)["Idx"] = as_string(i); PrintSourceClientMethod(printer, service->method(i).get(), vars); } printer->Print(*vars, "$ns$$Service$::Service::Service() {\n"); printer->Indent(); for (int i = 0; i < service->method_count(); ++i) { auto method = service->method(i); (*vars)["Idx"] = as_string(i); (*vars)["Method"] = method->name(); (*vars)["Request"] = method->input_type_name(); (*vars)["Response"] = method->output_type_name(); if (method->NoStreaming()) { printer->Print( *vars, "AddMethod(new ::grpc::RpcServiceMethod(\n" " $prefix$$Service$_method_names[$Idx$],\n" " ::grpc::RpcMethod::NORMAL_RPC,\n" " new ::grpc::RpcMethodHandler< $ns$$Service$::Service, " "$Request$, " "$Response$>(\n" " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n"); } else if (ClientOnlyStreaming(method.get())) { printer->Print( *vars, "AddMethod(new ::grpc::RpcServiceMethod(\n" " $prefix$$Service$_method_names[$Idx$],\n" " ::grpc::RpcMethod::CLIENT_STREAMING,\n" " new ::grpc::ClientStreamingHandler< " "$ns$$Service$::Service, $Request$, $Response$>(\n" " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n"); } else if (ServerOnlyStreaming(method.get())) { printer->Print( *vars, "AddMethod(new ::grpc::RpcServiceMethod(\n" " $prefix$$Service$_method_names[$Idx$],\n" " ::grpc::RpcMethod::SERVER_STREAMING,\n" " new ::grpc::ServerStreamingHandler< " "$ns$$Service$::Service, $Request$, $Response$>(\n" " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n"); } else if (method->BidiStreaming()) { printer->Print( *vars, "AddMethod(new ::grpc::RpcServiceMethod(\n" " $prefix$$Service$_method_names[$Idx$],\n" " ::grpc::RpcMethod::BIDI_STREAMING,\n" " new ::grpc::BidiStreamingHandler< " "$ns$$Service$::Service, $Request$, $Response$>(\n" " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n"); } } printer->Outdent(); printer->Print(*vars, "}\n\n"); printer->Print(*vars, "$ns$$Service$::Service::~Service() {\n" "}\n\n"); for (int i = 0; i < service->method_count(); ++i) { (*vars)["Idx"] = as_string(i); PrintSourceServerMethod(printer, service->method(i).get(), vars); } } grpc::string GetSourceServices(grpc_generator::File *file, const Parameters ¶ms) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. auto printer = file->CreatePrinter(&output); std::map vars; // Package string is empty or ends with a dot. It is used to fully qualify // method names. vars["Package"] = file->package(); if (!file->package().empty()) { vars["Package"].append("."); } if (!params.services_namespace.empty()) { vars["ns"] = params.services_namespace + "::"; vars["prefix"] = params.services_namespace; } else { vars["ns"] = ""; vars["prefix"] = ""; } for (int i = 0; i < file->service_count(); ++i) { PrintSourceService(printer.get(), file->service(i).get(), &vars); printer->Print("\n"); } } return output; } grpc::string GetSourceEpilogue(grpc_generator::File *file, const Parameters & /*params*/) { grpc::string temp; if (!file->package().empty()) { std::vector parts = file->package_parts(); for (auto part = parts.begin(); part != parts.end(); part++) { temp.append("} // namespace "); temp.append(*part); temp.append("\n"); } temp.append("\n"); } return temp; } } // namespace grpc_cpp_generator grpc-1.3.2/src/compiler/cpp_generator.h000066400000000000000000000075151310511640000200510ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_COMPILER_CPP_GENERATOR_H #define GRPC_INTERNAL_COMPILER_CPP_GENERATOR_H // cpp_generator.h/.cc do not directly depend on GRPC/ProtoBuf, such that they // can be used to generate code for other serialization systems, such as // FlatBuffers. #include #include #include "src/compiler/config.h" #include "src/compiler/schema_interface.h" #ifndef GRPC_CUSTOM_STRING #include #define GRPC_CUSTOM_STRING std::string #endif namespace grpc { typedef GRPC_CUSTOM_STRING string; } // namespace grpc namespace grpc_cpp_generator { // Contains all the parameters that are parsed from the command line. struct Parameters { // Puts the service into a namespace grpc::string services_namespace; // Use system includes (<>) or local includes ("") bool use_system_headers; // Prefix to any grpc include grpc::string grpc_search_path; }; // Return the prologue of the generated header file. grpc::string GetHeaderPrologue(grpc_generator::File *file, const Parameters ¶ms); // Return the includes needed for generated header file. grpc::string GetHeaderIncludes(grpc_generator::File *file, const Parameters ¶ms); // Return the includes needed for generated source file. grpc::string GetSourceIncludes(grpc_generator::File *file, const Parameters ¶ms); // Return the epilogue of the generated header file. grpc::string GetHeaderEpilogue(grpc_generator::File *file, const Parameters ¶ms); // Return the prologue of the generated source file. grpc::string GetSourcePrologue(grpc_generator::File *file, const Parameters ¶ms); // Return the services for generated header file. grpc::string GetHeaderServices(grpc_generator::File *file, const Parameters ¶ms); // Return the services for generated source file. grpc::string GetSourceServices(grpc_generator::File *file, const Parameters ¶ms); // Return the epilogue of the generated source file. grpc::string GetSourceEpilogue(grpc_generator::File *file, const Parameters ¶ms); } // namespace grpc_cpp_generator #endif // GRPC_INTERNAL_COMPILER_CPP_GENERATOR_H grpc-1.3.2/src/compiler/cpp_generator_helpers.h000066400000000000000000000061111310511640000215620ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_COMPILER_CPP_GENERATOR_HELPERS_H #define GRPC_INTERNAL_COMPILER_CPP_GENERATOR_HELPERS_H #include #include "src/compiler/config.h" #include "src/compiler/generator_helpers.h" namespace grpc_cpp_generator { inline grpc::string DotsToColons(const grpc::string &name) { return grpc_generator::StringReplace(name, ".", "::"); } inline grpc::string DotsToUnderscores(const grpc::string &name) { return grpc_generator::StringReplace(name, ".", "_"); } inline grpc::string ClassName(const grpc::protobuf::Descriptor *descriptor, bool qualified) { // Find "outer", the descriptor of the top-level message in which // "descriptor" is embedded. const grpc::protobuf::Descriptor *outer = descriptor; while (outer->containing_type() != NULL) outer = outer->containing_type(); const grpc::string &outer_name = outer->full_name(); grpc::string inner_name = descriptor->full_name().substr(outer_name.size()); if (qualified) { return "::" + DotsToColons(outer_name) + DotsToUnderscores(inner_name); } else { return outer->name() + DotsToUnderscores(inner_name); } } // Get leading or trailing comments in a string. Comment lines start with "// ". // Leading detached comments are put in in front of leading comments. template inline grpc::string GetCppComments(const DescriptorType *desc, bool leading) { return grpc_generator::GetPrefixedComments(desc, leading, "//"); } } // namespace grpc_cpp_generator #endif // GRPC_INTERNAL_COMPILER_CPP_GENERATOR_HELPERS_H grpc-1.3.2/src/compiler/cpp_plugin.cc000066400000000000000000000132351310511640000175130ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ // Generates cpp gRPC service interface out of Protobuf IDL. // #include #include #include "src/compiler/config.h" #include "src/compiler/cpp_generator.h" #include "src/compiler/generator_helpers.h" #include "src/compiler/protobuf_plugin.h" class CppGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { public: CppGrpcGenerator() {} virtual ~CppGrpcGenerator() {} virtual bool Generate(const grpc::protobuf::FileDescriptor *file, const grpc::string ¶meter, grpc::protobuf::compiler::GeneratorContext *context, grpc::string *error) const { if (file->options().cc_generic_services()) { *error = "cpp grpc proto compiler plugin does not work with generic " "services. To generate cpp grpc APIs, please set \"" "cc_generic_service = false\"."; return false; } grpc_cpp_generator::Parameters generator_parameters; generator_parameters.use_system_headers = true; ProtoBufFile pbfile(file); if (!parameter.empty()) { std::vector parameters_list = grpc_generator::tokenize(parameter, ","); for (auto parameter_string = parameters_list.begin(); parameter_string != parameters_list.end(); parameter_string++) { std::vector param = grpc_generator::tokenize(*parameter_string, "="); if (param[0] == "services_namespace") { generator_parameters.services_namespace = param[1]; } else if (param[0] == "use_system_headers") { if (param[1] == "true") { generator_parameters.use_system_headers = true; } else if (param[1] == "false") { generator_parameters.use_system_headers = false; } else { *error = grpc::string("Invalid parameter: ") + *parameter_string; return false; } } else if (param[0] == "grpc_search_path") { generator_parameters.grpc_search_path = param[1]; } else { *error = grpc::string("Unknown parameter: ") + *parameter_string; return false; } } } grpc::string file_name = grpc_generator::StripProto(file->name()); grpc::string header_code = grpc_cpp_generator::GetHeaderPrologue(&pbfile, generator_parameters) + grpc_cpp_generator::GetHeaderIncludes(&pbfile, generator_parameters) + grpc_cpp_generator::GetHeaderServices(&pbfile, generator_parameters) + grpc_cpp_generator::GetHeaderEpilogue(&pbfile, generator_parameters); std::unique_ptr header_output( context->Open(file_name + ".grpc.pb.h")); grpc::protobuf::io::CodedOutputStream header_coded_out(header_output.get()); header_coded_out.WriteRaw(header_code.data(), header_code.size()); grpc::string source_code = grpc_cpp_generator::GetSourcePrologue(&pbfile, generator_parameters) + grpc_cpp_generator::GetSourceIncludes(&pbfile, generator_parameters) + grpc_cpp_generator::GetSourceServices(&pbfile, generator_parameters) + grpc_cpp_generator::GetSourceEpilogue(&pbfile, generator_parameters); std::unique_ptr source_output( context->Open(file_name + ".grpc.pb.cc")); grpc::protobuf::io::CodedOutputStream source_coded_out(source_output.get()); source_coded_out.WriteRaw(source_code.data(), source_code.size()); return true; } private: // Insert the given code into the given file at the given insertion point. void Insert(grpc::protobuf::compiler::GeneratorContext *context, const grpc::string &filename, const grpc::string &insertion_point, const grpc::string &code) const { std::unique_ptr output( context->OpenForInsert(filename, insertion_point)); grpc::protobuf::io::CodedOutputStream coded_out(output.get()); coded_out.WriteRaw(code.data(), code.size()); } }; int main(int argc, char *argv[]) { CppGrpcGenerator generator; return grpc::protobuf::compiler::PluginMain(argc, argv, &generator); } grpc-1.3.2/src/compiler/csharp_generator.cc000066400000000000000000000630351310511640000207040ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include "src/compiler/config.h" #include "src/compiler/csharp_generator.h" #include "src/compiler/csharp_generator.h" #include "src/compiler/csharp_generator_helpers.h" using google::protobuf::compiler::csharp::GetFileNamespace; using google::protobuf::compiler::csharp::GetClassName; using google::protobuf::compiler::csharp::GetReflectionClassName; using grpc::protobuf::FileDescriptor; using grpc::protobuf::Descriptor; using grpc::protobuf::ServiceDescriptor; using grpc::protobuf::MethodDescriptor; using grpc::protobuf::io::Printer; using grpc::protobuf::io::StringOutputStream; using grpc_generator::MethodType; using grpc_generator::GetMethodType; using grpc_generator::METHODTYPE_NO_STREAMING; using grpc_generator::METHODTYPE_CLIENT_STREAMING; using grpc_generator::METHODTYPE_SERVER_STREAMING; using grpc_generator::METHODTYPE_BIDI_STREAMING; using grpc_generator::StringReplace; using std::map; using std::vector; namespace grpc_csharp_generator { namespace { // This function is a massaged version of // https://github.com/google/protobuf/blob/master/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc // Currently, we cannot easily reuse the functionality as // google/protobuf/compiler/csharp/csharp_doc_comment.h is not a public header. // TODO(jtattermusch): reuse the functionality from google/protobuf. bool GenerateDocCommentBodyImpl(grpc::protobuf::io::Printer *printer, grpc::protobuf::SourceLocation location) { grpc::string comments = location.leading_comments.empty() ? location.trailing_comments : location.leading_comments; if (comments.empty()) { return false; } // XML escaping... no need for apostrophes etc as the whole text is going to // be a child // node of a summary element, not part of an attribute. comments = grpc_generator::StringReplace(comments, "&", "&", true); comments = grpc_generator::StringReplace(comments, "<", "<", true); std::vector lines; grpc_generator::Split(comments, '\n', &lines); // TODO: We really should work out which part to put in the summary and which // to put in the remarks... // but that needs to be part of a bigger effort to understand the markdown // better anyway. printer->Print("/// \n"); bool last_was_empty = false; // We squash multiple blank lines down to one, and remove any trailing blank // lines. We need // to preserve the blank lines themselves, as this is relevant in the // markdown. // Note that we can't remove leading or trailing whitespace as *that's* // relevant in markdown too. // (We don't skip "just whitespace" lines, either.) for (std::vector::iterator it = lines.begin(); it != lines.end(); ++it) { grpc::string line = *it; if (line.empty()) { last_was_empty = true; } else { if (last_was_empty) { printer->Print("///\n"); } last_was_empty = false; printer->Print("///$line$\n", "line", *it); } } printer->Print("/// \n"); return true; } template bool GenerateDocCommentBody(grpc::protobuf::io::Printer *printer, const DescriptorType *descriptor) { grpc::protobuf::SourceLocation location; if (!descriptor->GetSourceLocation(&location)) { return false; } return GenerateDocCommentBodyImpl(printer, location); } void GenerateDocCommentServerMethod(grpc::protobuf::io::Printer *printer, const MethodDescriptor *method) { if (GenerateDocCommentBody(printer, method)) { if (method->client_streaming()) { printer->Print( "/// Used for reading requests from " "the client.\n"); } else { printer->Print( "/// The request received from the " "client.\n"); } if (method->server_streaming()) { printer->Print( "/// Used for sending responses back " "to the client.\n"); } printer->Print( "/// The context of the server-side call " "handler being invoked.\n"); if (method->server_streaming()) { printer->Print( "/// A task indicating completion of the " "handler.\n"); } else { printer->Print( "/// The response to send back to the client (wrapped by a " "task).\n"); } } } void GenerateDocCommentClientMethod(grpc::protobuf::io::Printer *printer, const MethodDescriptor *method, bool is_sync, bool use_call_options) { if (GenerateDocCommentBody(printer, method)) { if (!method->client_streaming()) { printer->Print( "/// The request to send to the " "server.\n"); } if (!use_call_options) { printer->Print( "/// The initial metadata to send with the " "call. This parameter is optional.\n"); printer->Print( "/// An optional deadline for the call. The " "call will be cancelled if deadline is hit.\n"); printer->Print( "/// An optional token for " "canceling the call.\n"); } else { printer->Print( "/// The options for the call.\n"); } if (is_sync) { printer->Print( "/// The response received from the server.\n"); } else { printer->Print("/// The call object.\n"); } } } std::string GetServiceClassName(const ServiceDescriptor *service) { return service->name(); } std::string GetClientClassName(const ServiceDescriptor *service) { return service->name() + "Client"; } std::string GetServerClassName(const ServiceDescriptor *service) { return service->name() + "Base"; } std::string GetCSharpMethodType(MethodType method_type) { switch (method_type) { case METHODTYPE_NO_STREAMING: return "grpc::MethodType.Unary"; case METHODTYPE_CLIENT_STREAMING: return "grpc::MethodType.ClientStreaming"; case METHODTYPE_SERVER_STREAMING: return "grpc::MethodType.ServerStreaming"; case METHODTYPE_BIDI_STREAMING: return "grpc::MethodType.DuplexStreaming"; } GOOGLE_LOG(FATAL) << "Can't get here."; return ""; } std::string GetServiceNameFieldName() { return "__ServiceName"; } std::string GetMarshallerFieldName(const Descriptor *message) { return "__Marshaller_" + message->name(); } std::string GetMethodFieldName(const MethodDescriptor *method) { return "__Method_" + method->name(); } std::string GetMethodRequestParamMaybe(const MethodDescriptor *method, bool invocation_param = false) { if (method->client_streaming()) { return ""; } if (invocation_param) { return "request, "; } return GetClassName(method->input_type()) + " request, "; } std::string GetAccessLevel(bool internal_access) { return internal_access ? "internal" : "public"; } std::string GetMethodReturnTypeClient(const MethodDescriptor *method) { switch (GetMethodType(method)) { case METHODTYPE_NO_STREAMING: return "grpc::AsyncUnaryCall<" + GetClassName(method->output_type()) + ">"; case METHODTYPE_CLIENT_STREAMING: return "grpc::AsyncClientStreamingCall<" + GetClassName(method->input_type()) + ", " + GetClassName(method->output_type()) + ">"; case METHODTYPE_SERVER_STREAMING: return "grpc::AsyncServerStreamingCall<" + GetClassName(method->output_type()) + ">"; case METHODTYPE_BIDI_STREAMING: return "grpc::AsyncDuplexStreamingCall<" + GetClassName(method->input_type()) + ", " + GetClassName(method->output_type()) + ">"; } GOOGLE_LOG(FATAL) << "Can't get here."; return ""; } std::string GetMethodRequestParamServer(const MethodDescriptor *method) { switch (GetMethodType(method)) { case METHODTYPE_NO_STREAMING: case METHODTYPE_SERVER_STREAMING: return GetClassName(method->input_type()) + " request"; case METHODTYPE_CLIENT_STREAMING: case METHODTYPE_BIDI_STREAMING: return "grpc::IAsyncStreamReader<" + GetClassName(method->input_type()) + "> requestStream"; } GOOGLE_LOG(FATAL) << "Can't get here."; return ""; } std::string GetMethodReturnTypeServer(const MethodDescriptor *method) { switch (GetMethodType(method)) { case METHODTYPE_NO_STREAMING: case METHODTYPE_CLIENT_STREAMING: return "global::System.Threading.Tasks.Task<" + GetClassName(method->output_type()) + ">"; case METHODTYPE_SERVER_STREAMING: case METHODTYPE_BIDI_STREAMING: return "global::System.Threading.Tasks.Task"; } GOOGLE_LOG(FATAL) << "Can't get here."; return ""; } std::string GetMethodResponseStreamMaybe(const MethodDescriptor *method) { switch (GetMethodType(method)) { case METHODTYPE_NO_STREAMING: case METHODTYPE_CLIENT_STREAMING: return ""; case METHODTYPE_SERVER_STREAMING: case METHODTYPE_BIDI_STREAMING: return ", grpc::IServerStreamWriter<" + GetClassName(method->output_type()) + "> responseStream"; } GOOGLE_LOG(FATAL) << "Can't get here."; return ""; } // Gets vector of all messages used as input or output types. std::vector GetUsedMessages( const ServiceDescriptor *service) { std::set descriptor_set; std::vector result; // vector is to maintain stable ordering for (int i = 0; i < service->method_count(); i++) { const MethodDescriptor *method = service->method(i); if (descriptor_set.find(method->input_type()) == descriptor_set.end()) { descriptor_set.insert(method->input_type()); result.push_back(method->input_type()); } if (descriptor_set.find(method->output_type()) == descriptor_set.end()) { descriptor_set.insert(method->output_type()); result.push_back(method->output_type()); } } return result; } void GenerateMarshallerFields(Printer *out, const ServiceDescriptor *service) { std::vector used_messages = GetUsedMessages(service); for (size_t i = 0; i < used_messages.size(); i++) { const Descriptor *message = used_messages[i]; out->Print( "static readonly grpc::Marshaller<$type$> $fieldname$ = " "grpc::Marshallers.Create((arg) => " "global::Google.Protobuf.MessageExtensions.ToByteArray(arg), " "$type$.Parser.ParseFrom);\n", "fieldname", GetMarshallerFieldName(message), "type", GetClassName(message)); } out->Print("\n"); } void GenerateStaticMethodField(Printer *out, const MethodDescriptor *method) { out->Print( "static readonly grpc::Method<$request$, $response$> $fieldname$ = new " "grpc::Method<$request$, $response$>(\n", "fieldname", GetMethodFieldName(method), "request", GetClassName(method->input_type()), "response", GetClassName(method->output_type())); out->Indent(); out->Indent(); out->Print("$methodtype$,\n", "methodtype", GetCSharpMethodType(GetMethodType(method))); out->Print("$servicenamefield$,\n", "servicenamefield", GetServiceNameFieldName()); out->Print("\"$methodname$\",\n", "methodname", method->name()); out->Print("$requestmarshaller$,\n", "requestmarshaller", GetMarshallerFieldName(method->input_type())); out->Print("$responsemarshaller$);\n", "responsemarshaller", GetMarshallerFieldName(method->output_type())); out->Print("\n"); out->Outdent(); out->Outdent(); } void GenerateServiceDescriptorProperty(Printer *out, const ServiceDescriptor *service) { std::ostringstream index; index << service->index(); out->Print("/// Service descriptor\n"); out->Print( "public static global::Google.Protobuf.Reflection.ServiceDescriptor " "Descriptor\n"); out->Print("{\n"); out->Print(" get { return $umbrella$.Descriptor.Services[$index$]; }\n", "umbrella", GetReflectionClassName(service->file()), "index", index.str()); out->Print("}\n"); out->Print("\n"); } void GenerateServerClass(Printer *out, const ServiceDescriptor *service) { out->Print( "/// Base class for server-side implementations of " "$servicename$\n", "servicename", GetServiceClassName(service)); out->Print("public abstract partial class $name$\n", "name", GetServerClassName(service)); out->Print("{\n"); out->Indent(); for (int i = 0; i < service->method_count(); i++) { const MethodDescriptor *method = service->method(i); GenerateDocCommentServerMethod(out, method); out->Print( "public virtual $returntype$ " "$methodname$($request$$response_stream_maybe$, " "grpc::ServerCallContext context)\n", "methodname", method->name(), "returntype", GetMethodReturnTypeServer(method), "request", GetMethodRequestParamServer(method), "response_stream_maybe", GetMethodResponseStreamMaybe(method)); out->Print("{\n"); out->Indent(); out->Print( "throw new grpc::RpcException(" "new grpc::Status(grpc::StatusCode.Unimplemented, \"\"));\n"); out->Outdent(); out->Print("}\n\n"); } out->Outdent(); out->Print("}\n"); out->Print("\n"); } void GenerateClientStub(Printer *out, const ServiceDescriptor *service) { out->Print("/// Client for $servicename$\n", "servicename", GetServiceClassName(service)); out->Print("public partial class $name$ : grpc::ClientBase<$name$>\n", "name", GetClientClassName(service)); out->Print("{\n"); out->Indent(); // constructors out->Print( "/// Creates a new client for $servicename$\n" "/// The channel to use to make remote " "calls.\n", "servicename", GetServiceClassName(service)); out->Print("public $name$(grpc::Channel channel) : base(channel)\n", "name", GetClientClassName(service)); out->Print("{\n"); out->Print("}\n"); out->Print( "/// Creates a new client for $servicename$ that uses a custom " "CallInvoker.\n" "/// The callInvoker to use to make remote " "calls.\n", "servicename", GetServiceClassName(service)); out->Print( "public $name$(grpc::CallInvoker callInvoker) : base(callInvoker)\n", "name", GetClientClassName(service)); out->Print("{\n"); out->Print("}\n"); out->Print( "/// Protected parameterless constructor to allow creation" " of test doubles.\n"); out->Print("protected $name$() : base()\n", "name", GetClientClassName(service)); out->Print("{\n"); out->Print("}\n"); out->Print( "/// Protected constructor to allow creation of configured " "clients.\n" "/// The client configuration.\n"); out->Print( "protected $name$(ClientBaseConfiguration configuration)" " : base(configuration)\n", "name", GetClientClassName(service)); out->Print("{\n"); out->Print("}\n\n"); for (int i = 0; i < service->method_count(); i++) { const MethodDescriptor *method = service->method(i); MethodType method_type = GetMethodType(method); if (method_type == METHODTYPE_NO_STREAMING) { // unary calls have an extra synchronous stub method GenerateDocCommentClientMethod(out, method, true, false); out->Print( "public virtual $response$ $methodname$($request$ request, " "grpc::Metadata " "headers = null, DateTime? deadline = null, CancellationToken " "cancellationToken = default(CancellationToken))\n", "methodname", method->name(), "request", GetClassName(method->input_type()), "response", GetClassName(method->output_type())); out->Print("{\n"); out->Indent(); out->Print( "return $methodname$(request, new grpc::CallOptions(headers, " "deadline, " "cancellationToken));\n", "methodname", method->name()); out->Outdent(); out->Print("}\n"); // overload taking CallOptions as a param GenerateDocCommentClientMethod(out, method, true, true); out->Print( "public virtual $response$ $methodname$($request$ request, " "grpc::CallOptions options)\n", "methodname", method->name(), "request", GetClassName(method->input_type()), "response", GetClassName(method->output_type())); out->Print("{\n"); out->Indent(); out->Print( "return CallInvoker.BlockingUnaryCall($methodfield$, null, options, " "request);\n", "methodfield", GetMethodFieldName(method)); out->Outdent(); out->Print("}\n"); } std::string method_name = method->name(); if (method_type == METHODTYPE_NO_STREAMING) { method_name += "Async"; // prevent name clash with synchronous method. } GenerateDocCommentClientMethod(out, method, false, false); out->Print( "public virtual $returntype$ " "$methodname$($request_maybe$grpc::Metadata " "headers = null, DateTime? deadline = null, CancellationToken " "cancellationToken = default(CancellationToken))\n", "methodname", method_name, "request_maybe", GetMethodRequestParamMaybe(method), "returntype", GetMethodReturnTypeClient(method)); out->Print("{\n"); out->Indent(); out->Print( "return $methodname$($request_maybe$new grpc::CallOptions(headers, " "deadline, " "cancellationToken));\n", "methodname", method_name, "request_maybe", GetMethodRequestParamMaybe(method, true)); out->Outdent(); out->Print("}\n"); // overload taking CallOptions as a param GenerateDocCommentClientMethod(out, method, false, true); out->Print( "public virtual $returntype$ " "$methodname$($request_maybe$grpc::CallOptions " "options)\n", "methodname", method_name, "request_maybe", GetMethodRequestParamMaybe(method), "returntype", GetMethodReturnTypeClient(method)); out->Print("{\n"); out->Indent(); switch (GetMethodType(method)) { case METHODTYPE_NO_STREAMING: out->Print( "return CallInvoker.AsyncUnaryCall($methodfield$, null, options, " "request);\n", "methodfield", GetMethodFieldName(method)); break; case METHODTYPE_CLIENT_STREAMING: out->Print( "return CallInvoker.AsyncClientStreamingCall($methodfield$, null, " "options);\n", "methodfield", GetMethodFieldName(method)); break; case METHODTYPE_SERVER_STREAMING: out->Print( "return CallInvoker.AsyncServerStreamingCall($methodfield$, null, " "options, request);\n", "methodfield", GetMethodFieldName(method)); break; case METHODTYPE_BIDI_STREAMING: out->Print( "return CallInvoker.AsyncDuplexStreamingCall($methodfield$, null, " "options);\n", "methodfield", GetMethodFieldName(method)); break; default: GOOGLE_LOG(FATAL) << "Can't get here."; } out->Outdent(); out->Print("}\n"); } // override NewInstance method out->Print( "/// Creates a new instance of client from given " "ClientBaseConfiguration.\n"); out->Print( "protected override $name$ NewInstance(ClientBaseConfiguration " "configuration)\n", "name", GetClientClassName(service)); out->Print("{\n"); out->Indent(); out->Print("return new $name$(configuration);\n", "name", GetClientClassName(service)); out->Outdent(); out->Print("}\n"); out->Outdent(); out->Print("}\n"); out->Print("\n"); } void GenerateBindServiceMethod(Printer *out, const ServiceDescriptor *service) { out->Print( "/// Creates service definition that can be registered with a " "server\n"); out->Print( "/// An object implementing the server-side" " handling logic.\n"); out->Print( "public static grpc::ServerServiceDefinition BindService($implclass$ " "serviceImpl)\n", "implclass", GetServerClassName(service)); out->Print("{\n"); out->Indent(); out->Print("return grpc::ServerServiceDefinition.CreateBuilder()\n"); out->Indent(); out->Indent(); for (int i = 0; i < service->method_count(); i++) { const MethodDescriptor *method = service->method(i); out->Print(".AddMethod($methodfield$, serviceImpl.$methodname$)", "methodfield", GetMethodFieldName(method), "methodname", method->name()); if (i == service->method_count() - 1) { out->Print(".Build();"); } out->Print("\n"); } out->Outdent(); out->Outdent(); out->Outdent(); out->Print("}\n"); out->Print("\n"); } void GenerateService(Printer *out, const ServiceDescriptor *service, bool generate_client, bool generate_server, bool internal_access) { GenerateDocCommentBody(out, service); out->Print("$access_level$ static partial class $classname$\n", "access_level", GetAccessLevel(internal_access), "classname", GetServiceClassName(service)); out->Print("{\n"); out->Indent(); out->Print("static readonly string $servicenamefield$ = \"$servicename$\";\n", "servicenamefield", GetServiceNameFieldName(), "servicename", service->full_name()); out->Print("\n"); GenerateMarshallerFields(out, service); for (int i = 0; i < service->method_count(); i++) { GenerateStaticMethodField(out, service->method(i)); } GenerateServiceDescriptorProperty(out, service); if (generate_server) { GenerateServerClass(out, service); } if (generate_client) { GenerateClientStub(out, service); } if (generate_server) { GenerateBindServiceMethod(out, service); } out->Outdent(); out->Print("}\n"); } } // anonymous namespace grpc::string GetServices(const FileDescriptor *file, bool generate_client, bool generate_server, bool internal_access) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. StringOutputStream output_stream(&output); Printer out(&output_stream, '$'); // Don't write out any output if there no services, to avoid empty service // files being generated for proto files that don't declare any. if (file->service_count() == 0) { return output; } // Write out a file header. out.Print("// Generated by the protocol buffer compiler. DO NOT EDIT!\n"); out.Print("// source: $filename$\n", "filename", file->name()); // use C++ style as there are no file-level XML comments in .NET grpc::string leading_comments = GetCsharpComments(file, true); if (!leading_comments.empty()) { out.Print("// Original file comments:\n"); out.Print(leading_comments.c_str()); } out.Print("#region Designer generated code\n"); out.Print("\n"); out.Print("using System;\n"); out.Print("using System.Threading;\n"); out.Print("using System.Threading.Tasks;\n"); out.Print("using grpc = global::Grpc.Core;\n"); out.Print("\n"); out.Print("namespace $namespace$ {\n", "namespace", GetFileNamespace(file)); out.Indent(); for (int i = 0; i < file->service_count(); i++) { GenerateService(&out, file->service(i), generate_client, generate_server, internal_access); } out.Outdent(); out.Print("}\n"); out.Print("#endregion\n"); } return output; } } // namespace grpc_csharp_generator grpc-1.3.2/src/compiler/csharp_generator.h000066400000000000000000000040361310511640000205420ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_H #define GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_H #include "src/compiler/config.h" #include namespace grpc_csharp_generator { grpc::string GetServices(const grpc::protobuf::FileDescriptor *file, bool generate_client, bool generate_server, bool internal_access); } // namespace grpc_csharp_generator #endif // GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_H grpc-1.3.2/src/compiler/csharp_generator_helpers.h000066400000000000000000000047351310511640000222720ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_HELPERS_H #define GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_HELPERS_H #include "src/compiler/config.h" #include "src/compiler/generator_helpers.h" namespace grpc_csharp_generator { inline bool ServicesFilename(const grpc::protobuf::FileDescriptor *file, grpc::string *file_name_or_error) { *file_name_or_error = grpc_generator::FileNameInUpperCamel(file, false) + "Grpc.cs"; return true; } // Get leading or trailing comments in a string. Comment lines start with "// ". // Leading detached comments are put in in front of leading comments. template inline grpc::string GetCsharpComments(const DescriptorType *desc, bool leading) { return grpc_generator::GetPrefixedComments(desc, leading, "//"); } } // namespace grpc_csharp_generator #endif // GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_HELPERS_H grpc-1.3.2/src/compiler/csharp_plugin.cc000066400000000000000000000067701310511640000202170ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ // Generates C# gRPC service interface out of Protobuf IDL. #include #include "src/compiler/config.h" #include "src/compiler/csharp_generator.h" #include "src/compiler/csharp_generator_helpers.h" class CSharpGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { public: CSharpGrpcGenerator() {} ~CSharpGrpcGenerator() {} bool Generate(const grpc::protobuf::FileDescriptor *file, const grpc::string ¶meter, grpc::protobuf::compiler::GeneratorContext *context, grpc::string *error) const { std::vector > options; grpc::protobuf::compiler::ParseGeneratorParameter(parameter, &options); bool generate_client = true; bool generate_server = true; bool internal_access = false; for (size_t i = 0; i < options.size(); i++) { if (options[i].first == "no_client") { generate_client = false; } else if (options[i].first == "no_server") { generate_server = false; } else if (options[i].first == "internal_access") { internal_access = true; } else { *error = "Unknown generator option: " + options[i].first; return false; } } grpc::string code = grpc_csharp_generator::GetServices( file, generate_client, generate_server, internal_access); if (code.size() == 0) { return true; // don't generate a file if there are no services } // Get output file name. grpc::string file_name; if (!grpc_csharp_generator::ServicesFilename(file, &file_name)) { return false; } std::unique_ptr output( context->Open(file_name)); grpc::protobuf::io::CodedOutputStream coded_out(output.get()); coded_out.WriteRaw(code.data(), code.size()); return true; } }; int main(int argc, char *argv[]) { CSharpGrpcGenerator generator; return grpc::protobuf::compiler::PluginMain(argc, argv, &generator); } grpc-1.3.2/src/compiler/generator_helpers.h000066400000000000000000000217341310511640000207300ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H #define GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H #include #include #include #include #include #include "src/compiler/config.h" namespace grpc_generator { inline bool StripSuffix(grpc::string *filename, const grpc::string &suffix) { if (filename->length() >= suffix.length()) { size_t suffix_pos = filename->length() - suffix.length(); if (filename->compare(suffix_pos, grpc::string::npos, suffix) == 0) { filename->resize(filename->size() - suffix.size()); return true; } } return false; } inline bool StripPrefix(grpc::string *name, const grpc::string &prefix) { if (name->length() >= prefix.length()) { if (name->substr(0, prefix.size()) == prefix) { *name = name->substr(prefix.size()); return true; } } return false; } inline grpc::string StripProto(grpc::string filename) { if (!StripSuffix(&filename, ".protodevel")) { StripSuffix(&filename, ".proto"); } return filename; } inline grpc::string StringReplace(grpc::string str, const grpc::string &from, const grpc::string &to, bool replace_all) { size_t pos = 0; do { pos = str.find(from, pos); if (pos == grpc::string::npos) { break; } str.replace(pos, from.length(), to); pos += to.length(); } while (replace_all); return str; } inline grpc::string StringReplace(grpc::string str, const grpc::string &from, const grpc::string &to) { return StringReplace(str, from, to, true); } inline std::vector tokenize(const grpc::string &input, const grpc::string &delimiters) { std::vector tokens; size_t pos, last_pos = 0; for (;;) { bool done = false; pos = input.find_first_of(delimiters, last_pos); if (pos == grpc::string::npos) { done = true; pos = input.length(); } tokens.push_back(input.substr(last_pos, pos - last_pos)); if (done) return tokens; last_pos = pos + 1; } } inline grpc::string CapitalizeFirstLetter(grpc::string s) { if (s.empty()) { return s; } s[0] = ::toupper(s[0]); return s; } inline grpc::string LowercaseFirstLetter(grpc::string s) { if (s.empty()) { return s; } s[0] = ::tolower(s[0]); return s; } inline grpc::string LowerUnderscoreToUpperCamel(grpc::string str) { std::vector tokens = tokenize(str, "_"); grpc::string result = ""; for (unsigned int i = 0; i < tokens.size(); i++) { result += CapitalizeFirstLetter(tokens[i]); } return result; } inline grpc::string FileNameInUpperCamel( const grpc::protobuf::FileDescriptor *file, bool include_package_path) { std::vector tokens = tokenize(StripProto(file->name()), "/"); grpc::string result = ""; if (include_package_path) { for (unsigned int i = 0; i < tokens.size() - 1; i++) { result += tokens[i] + "/"; } } result += LowerUnderscoreToUpperCamel(tokens.back()); return result; } inline grpc::string FileNameInUpperCamel( const grpc::protobuf::FileDescriptor *file) { return FileNameInUpperCamel(file, true); } enum MethodType { METHODTYPE_NO_STREAMING, METHODTYPE_CLIENT_STREAMING, METHODTYPE_SERVER_STREAMING, METHODTYPE_BIDI_STREAMING }; inline MethodType GetMethodType( const grpc::protobuf::MethodDescriptor *method) { if (method->client_streaming()) { if (method->server_streaming()) { return METHODTYPE_BIDI_STREAMING; } else { return METHODTYPE_CLIENT_STREAMING; } } else { if (method->server_streaming()) { return METHODTYPE_SERVER_STREAMING; } else { return METHODTYPE_NO_STREAMING; } } } inline void Split(const grpc::string &s, char delim, std::vector *append_to) { std::istringstream iss(s); grpc::string piece; while (std::getline(iss, piece)) { append_to->push_back(piece); } } enum CommentType { COMMENTTYPE_LEADING, COMMENTTYPE_TRAILING, COMMENTTYPE_LEADING_DETACHED }; // Get all the raw comments and append each line without newline to out. template inline void GetComment(const DescriptorType *desc, CommentType type, std::vector *out) { grpc::protobuf::SourceLocation location; if (!desc->GetSourceLocation(&location)) { return; } if (type == COMMENTTYPE_LEADING || type == COMMENTTYPE_TRAILING) { const grpc::string &comments = type == COMMENTTYPE_LEADING ? location.leading_comments : location.trailing_comments; Split(comments, '\n', out); } else if (type == COMMENTTYPE_LEADING_DETACHED) { for (unsigned int i = 0; i < location.leading_detached_comments.size(); i++) { Split(location.leading_detached_comments[i], '\n', out); out->push_back(""); } } else { std::cerr << "Unknown comment type " << type << std::endl; abort(); } } // Each raw comment line without newline is appended to out. // For file level leading and detached leading comments, we return comments // above syntax line. Return nothing for trailing comments. template <> inline void GetComment(const grpc::protobuf::FileDescriptor *desc, CommentType type, std::vector *out) { if (type == COMMENTTYPE_TRAILING) { return; } grpc::protobuf::SourceLocation location; std::vector path; path.push_back(grpc::protobuf::FileDescriptorProto::kSyntaxFieldNumber); if (!desc->GetSourceLocation(path, &location)) { return; } if (type == COMMENTTYPE_LEADING) { Split(location.leading_comments, '\n', out); } else if (type == COMMENTTYPE_LEADING_DETACHED) { for (unsigned int i = 0; i < location.leading_detached_comments.size(); i++) { Split(location.leading_detached_comments[i], '\n', out); out->push_back(""); } } else { std::cerr << "Unknown comment type " << type << std::endl; abort(); } } // Add prefix and newline to each comment line and concatenate them together. // Make sure there is a space after the prefix unless the line is empty. inline grpc::string GenerateCommentsWithPrefix( const std::vector &in, const grpc::string &prefix) { std::ostringstream oss; for (auto it = in.begin(); it != in.end(); it++) { const grpc::string &elem = *it; if (elem.empty()) { oss << prefix << "\n"; } else if (elem[0] == ' ') { oss << prefix << elem << "\n"; } else { oss << prefix << " " << elem << "\n"; } } return oss.str(); } template inline grpc::string GetPrefixedComments(const DescriptorType *desc, bool leading, const grpc::string &prefix) { std::vector out; if (leading) { grpc_generator::GetComment( desc, grpc_generator::COMMENTTYPE_LEADING_DETACHED, &out); std::vector leading; grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_LEADING, &leading); out.insert(out.end(), leading.begin(), leading.end()); } else { grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_TRAILING, &out); } return GenerateCommentsWithPrefix(out, prefix); } } // namespace grpc_generator #endif // GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H grpc-1.3.2/src/compiler/node_generator.cc000066400000000000000000000254321310511640000203500ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "src/compiler/config.h" #include "src/compiler/generator_helpers.h" #include "src/compiler/node_generator_helpers.h" using grpc::protobuf::FileDescriptor; using grpc::protobuf::ServiceDescriptor; using grpc::protobuf::MethodDescriptor; using grpc::protobuf::Descriptor; using grpc::protobuf::io::Printer; using grpc::protobuf::io::StringOutputStream; using std::map; namespace grpc_node_generator { namespace { // Returns the alias we assign to the module of the given .proto filename // when importing. Copied entirely from // github:google/protobuf/src/google/protobuf/compiler/js/js_generator.cc#L154 grpc::string ModuleAlias(const grpc::string filename) { // This scheme could technically cause problems if a file includes any 2 of: // foo/bar_baz.proto // foo_bar_baz.proto // foo_bar/baz.proto // // We'll worry about this problem if/when we actually see it. This name isn't // exposed to users so we can change it later if we need to. grpc::string basename = grpc_generator::StripProto(filename); basename = grpc_generator::StringReplace(basename, "-", "$"); basename = grpc_generator::StringReplace(basename, "/", "_"); return basename + "_pb"; } // Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript // message file foo/bar/baz.js grpc::string GetJSMessageFilename(const grpc::string &filename) { grpc::string name = filename; return grpc_generator::StripProto(name) + "_pb.js"; } // Given a filename like foo/bar/baz.proto, returns the root directory // path ../../ grpc::string GetRootPath(const grpc::string &from_filename, const grpc::string &to_filename) { if (to_filename.find("google/protobuf") == 0) { // Well-known types (.proto files in the google/protobuf directory) are // assumed to come from the 'google-protobuf' npm package. We may want to // generalize this exception later by letting others put generated code in // their own npm packages. return "google-protobuf/"; } size_t slashes = std::count(from_filename.begin(), from_filename.end(), '/'); if (slashes == 0) { return "./"; } grpc::string result = ""; for (size_t i = 0; i < slashes; i++) { result += "../"; } return result; } // Return the relative path to load to_file from the directory containing // from_file, assuming that both paths are relative to the same directory grpc::string GetRelativePath(const grpc::string &from_file, const grpc::string &to_file) { return GetRootPath(from_file, to_file) + to_file; } /* Finds all message types used in all services in the file, and returns them * as a map of fully qualified message type name to message descriptor */ map GetAllMessages( const FileDescriptor *file) { map message_types; for (int service_num = 0; service_num < file->service_count(); service_num++) { const ServiceDescriptor *service = file->service(service_num); for (int method_num = 0; method_num < service->method_count(); method_num++) { const MethodDescriptor *method = service->method(method_num); const Descriptor *input_type = method->input_type(); const Descriptor *output_type = method->output_type(); message_types[input_type->full_name()] = input_type; message_types[output_type->full_name()] = output_type; } } return message_types; } grpc::string MessageIdentifierName(const grpc::string &name) { return grpc_generator::StringReplace(name, ".", "_"); } grpc::string NodeObjectPath(const Descriptor *descriptor) { grpc::string module_alias = ModuleAlias(descriptor->file()->name()); grpc::string name = descriptor->full_name(); grpc_generator::StripPrefix(&name, descriptor->file()->package() + "."); return module_alias + "." + name; } // Prints out the message serializer and deserializer functions void PrintMessageTransformer(const Descriptor *descriptor, Printer *out) { map template_vars; grpc::string full_name = descriptor->full_name(); template_vars["identifier_name"] = MessageIdentifierName(full_name); template_vars["name"] = full_name; template_vars["node_name"] = NodeObjectPath(descriptor); // Print the serializer out->Print(template_vars, "function serialize_$identifier_name$(arg) {\n"); out->Indent(); out->Print(template_vars, "if (!(arg instanceof $node_name$)) {\n"); out->Indent(); out->Print(template_vars, "throw new Error('Expected argument of type $name$');\n"); out->Outdent(); out->Print("}\n"); out->Print("return new Buffer(arg.serializeBinary());\n"); out->Outdent(); out->Print("}\n\n"); // Print the deserializer out->Print(template_vars, "function deserialize_$identifier_name$(buffer_arg) {\n"); out->Indent(); out->Print( template_vars, "return $node_name$.deserializeBinary(new Uint8Array(buffer_arg));\n"); out->Outdent(); out->Print("}\n\n"); } void PrintMethod(const MethodDescriptor *method, Printer *out) { const Descriptor *input_type = method->input_type(); const Descriptor *output_type = method->output_type(); map vars; vars["service_name"] = method->service()->full_name(); vars["name"] = method->name(); vars["input_type"] = NodeObjectPath(input_type); vars["input_type_id"] = MessageIdentifierName(input_type->full_name()); vars["output_type"] = NodeObjectPath(output_type); vars["output_type_id"] = MessageIdentifierName(output_type->full_name()); vars["client_stream"] = method->client_streaming() ? "true" : "false"; vars["server_stream"] = method->server_streaming() ? "true" : "false"; out->Print("{\n"); out->Indent(); out->Print(vars, "path: '/$service_name$/$name$',\n"); out->Print(vars, "requestStream: $client_stream$,\n"); out->Print(vars, "responseStream: $server_stream$,\n"); out->Print(vars, "requestType: $input_type$,\n"); out->Print(vars, "responseType: $output_type$,\n"); out->Print(vars, "requestSerialize: serialize_$input_type_id$,\n"); out->Print(vars, "requestDeserialize: deserialize_$input_type_id$,\n"); out->Print(vars, "responseSerialize: serialize_$output_type_id$,\n"); out->Print(vars, "responseDeserialize: deserialize_$output_type_id$,\n"); out->Outdent(); out->Print("}"); } // Prints out the service descriptor object void PrintService(const ServiceDescriptor *service, Printer *out) { map template_vars; out->Print(GetNodeComments(service, true).c_str()); template_vars["name"] = service->name(); out->Print(template_vars, "var $name$Service = exports.$name$Service = {\n"); out->Indent(); for (int i = 0; i < service->method_count(); i++) { grpc::string method_name = grpc_generator::LowercaseFirstLetter(service->method(i)->name()); out->Print(GetNodeComments(service->method(i), true).c_str()); out->Print("$method_name$: ", "method_name", method_name); PrintMethod(service->method(i), out); out->Print(",\n"); out->Print(GetNodeComments(service->method(i), false).c_str()); } out->Outdent(); out->Print("};\n\n"); out->Print(template_vars, "exports.$name$Client = " "grpc.makeGenericClientConstructor($name$Service);\n"); out->Print(GetNodeComments(service, false).c_str()); } void PrintImports(const FileDescriptor *file, Printer *out) { out->Print("var grpc = require('grpc');\n"); if (file->message_type_count() > 0) { grpc::string file_path = GetRelativePath(file->name(), GetJSMessageFilename(file->name())); out->Print("var $module_alias$ = require('$file_path$');\n", "module_alias", ModuleAlias(file->name()), "file_path", file_path); } for (int i = 0; i < file->dependency_count(); i++) { grpc::string file_path = GetRelativePath( file->name(), GetJSMessageFilename(file->dependency(i)->name())); out->Print("var $module_alias$ = require('$file_path$');\n", "module_alias", ModuleAlias(file->dependency(i)->name()), "file_path", file_path); } out->Print("\n"); } void PrintTransformers(const FileDescriptor *file, Printer *out) { map messages = GetAllMessages(file); for (std::map::iterator it = messages.begin(); it != messages.end(); it++) { PrintMessageTransformer(it->second, out); } out->Print("\n"); } void PrintServices(const FileDescriptor *file, Printer *out) { for (int i = 0; i < file->service_count(); i++) { PrintService(file->service(i), out); } } } grpc::string GenerateFile(const FileDescriptor *file) { grpc::string output; { StringOutputStream output_stream(&output); Printer out(&output_stream, '$'); if (file->service_count() == 0) { return output; } out.Print("// GENERATED CODE -- DO NOT EDIT!\n\n"); grpc::string leading_comments = GetNodeComments(file, true); if (!leading_comments.empty()) { out.Print("// Original file comments:\n"); out.Print(leading_comments.c_str()); } out.Print("'use strict';\n"); PrintImports(file, &out); PrintTransformers(file, &out); PrintServices(file, &out); out.Print(GetNodeComments(file, false).c_str()); } return output; } } // namespace grpc_node_generator grpc-1.3.2/src/compiler/node_generator.h000066400000000000000000000035461310511640000202140ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_COMPILER_NODE_GENERATOR_H #define GRPC_INTERNAL_COMPILER_NODE_GENERATOR_H #include "src/compiler/config.h" namespace grpc_node_generator { grpc::string GenerateFile(const grpc::protobuf::FileDescriptor *file); } // namespace grpc_node_generator #endif // GRPC_INTERNAL_COMPILER_NODE_GENERATOR_H grpc-1.3.2/src/compiler/node_generator_helpers.h000066400000000000000000000045231310511640000217320ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_COMPILER_NODE_GENERATOR_HELPERS_H #define GRPC_INTERNAL_COMPILER_NODE_GENERATOR_HELPERS_H #include #include "src/compiler/config.h" #include "src/compiler/generator_helpers.h" namespace grpc_node_generator { inline grpc::string GetJSServiceFilename(const grpc::string& filename) { return grpc_generator::StripProto(filename) + "_grpc_pb.js"; } // Get leading or trailing comments in a string. Comment lines start with "// ". // Leading detached comments are put in in front of leading comments. template inline grpc::string GetNodeComments(const DescriptorType* desc, bool leading) { return grpc_generator::GetPrefixedComments(desc, leading, "//"); } } // namespace grpc_node_generator #endif // GRPC_INTERNAL_COMPILER_NODE_GENERATOR_HELPERS_H grpc-1.3.2/src/compiler/node_plugin.cc000066400000000000000000000053621310511640000176600ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ // Generates Node gRPC service interface out of Protobuf IDL. #include #include "src/compiler/config.h" #include "src/compiler/node_generator.h" #include "src/compiler/node_generator_helpers.h" using grpc_node_generator::GenerateFile; using grpc_node_generator::GetJSServiceFilename; class NodeGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { public: NodeGrpcGenerator() {} ~NodeGrpcGenerator() {} bool Generate(const grpc::protobuf::FileDescriptor *file, const grpc::string ¶meter, grpc::protobuf::compiler::GeneratorContext *context, grpc::string *error) const { grpc::string code = GenerateFile(file); if (code.size() == 0) { return true; } // Get output file name grpc::string file_name = GetJSServiceFilename(file->name()); std::unique_ptr output( context->Open(file_name)); grpc::protobuf::io::CodedOutputStream coded_out(output.get()); coded_out.WriteRaw(code.data(), code.size()); return true; } }; int main(int argc, char *argv[]) { NodeGrpcGenerator generator; return grpc::protobuf::compiler::PluginMain(argc, argv, &generator); } grpc-1.3.2/src/compiler/objective_c_generator.cc000066400000000000000000000245361310511640000217030ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include "src/compiler/config.h" #include "src/compiler/objective_c_generator.h" #include "src/compiler/objective_c_generator_helpers.h" #include using ::google::protobuf::compiler::objectivec::ClassName; using ::grpc::protobuf::io::Printer; using ::grpc::protobuf::MethodDescriptor; using ::grpc::protobuf::ServiceDescriptor; using ::std::map; namespace grpc_objective_c_generator { namespace { void PrintProtoRpcDeclarationAsPragma( Printer *printer, const MethodDescriptor *method, map< ::grpc::string, ::grpc::string> vars) { vars["client_stream"] = method->client_streaming() ? "stream " : ""; vars["server_stream"] = method->server_streaming() ? "stream " : ""; printer->Print(vars, "#pragma mark $method_name$($client_stream$$request_type$)" " returns ($server_stream$$response_type$)\n\n"); } template static void PrintAllComments(const DescriptorType *desc, Printer *printer) { std::vector comments; grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_LEADING_DETACHED, &comments); grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_LEADING, &comments); grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_TRAILING, &comments); if (comments.empty()) { return; } printer->Print("/**\n"); for (auto it = comments.begin(); it != comments.end(); ++it) { printer->Print(" * "); size_t start_pos = it->find_first_not_of(' '); if (start_pos != grpc::string::npos) { printer->Print(it->c_str() + start_pos); } printer->Print("\n"); } printer->Print(" */\n"); } void PrintMethodSignature(Printer *printer, const MethodDescriptor *method, const map< ::grpc::string, ::grpc::string> &vars) { // Print comment PrintAllComments(method, printer); printer->Print(vars, "- ($return_type$)$method_name$With"); if (method->client_streaming()) { printer->Print("RequestsWriter:(GRXWriter *)requestWriter"); } else { printer->Print(vars, "Request:($request_class$ *)request"); } // TODO(jcanizales): Put this on a new line and align colons. if (method->server_streaming()) { printer->Print(vars, " eventHandler:(void(^)(BOOL done, " "$response_class$ *_Nullable response, NSError *_Nullable " "error))eventHandler"); } else { printer->Print(vars, " handler:(void(^)($response_class$ *_Nullable response, " "NSError *_Nullable error))handler"); } } void PrintSimpleSignature(Printer *printer, const MethodDescriptor *method, map< ::grpc::string, ::grpc::string> vars) { vars["method_name"] = grpc_generator::LowercaseFirstLetter(vars["method_name"]); vars["return_type"] = "void"; PrintMethodSignature(printer, method, vars); } void PrintAdvancedSignature(Printer *printer, const MethodDescriptor *method, map< ::grpc::string, ::grpc::string> vars) { vars["method_name"] = "RPCTo" + vars["method_name"]; vars["return_type"] = "GRPCProtoCall *"; PrintMethodSignature(printer, method, vars); } inline map< ::grpc::string, ::grpc::string> GetMethodVars( const MethodDescriptor *method) { map< ::grpc::string, ::grpc::string> res; res["method_name"] = method->name(); res["request_type"] = method->input_type()->name(); res["response_type"] = method->output_type()->name(); res["request_class"] = ClassName(method->input_type()); res["response_class"] = ClassName(method->output_type()); return res; } void PrintMethodDeclarations(Printer *printer, const MethodDescriptor *method) { map< ::grpc::string, ::grpc::string> vars = GetMethodVars(method); PrintProtoRpcDeclarationAsPragma(printer, method, vars); PrintSimpleSignature(printer, method, vars); printer->Print(";\n\n"); PrintAdvancedSignature(printer, method, vars); printer->Print(";\n\n\n"); } void PrintSimpleImplementation(Printer *printer, const MethodDescriptor *method, map< ::grpc::string, ::grpc::string> vars) { printer->Print("{\n"); printer->Print(vars, " [[self RPCTo$method_name$With"); if (method->client_streaming()) { printer->Print("RequestsWriter:requestWriter"); } else { printer->Print("Request:request"); } if (method->server_streaming()) { printer->Print(" eventHandler:eventHandler] start];\n"); } else { printer->Print(" handler:handler] start];\n"); } printer->Print("}\n"); } void PrintAdvancedImplementation(Printer *printer, const MethodDescriptor *method, map< ::grpc::string, ::grpc::string> vars) { printer->Print("{\n"); printer->Print(vars, " return [self RPCToMethod:@\"$method_name$\"\n"); printer->Print(" requestsWriter:"); if (method->client_streaming()) { printer->Print("requestWriter\n"); } else { printer->Print("[GRXWriter writerWithValue:request]\n"); } printer->Print(vars, " responseClass:[$response_class$ class]\n"); printer->Print(" responsesWriteable:[GRXWriteable "); if (method->server_streaming()) { printer->Print("writeableWithEventHandler:eventHandler]];\n"); } else { printer->Print("writeableWithSingleHandler:handler]];\n"); } printer->Print("}\n"); } void PrintMethodImplementations(Printer *printer, const MethodDescriptor *method) { map< ::grpc::string, ::grpc::string> vars = GetMethodVars(method); PrintProtoRpcDeclarationAsPragma(printer, method, vars); // TODO(jcanizales): Print documentation from the method. PrintSimpleSignature(printer, method, vars); PrintSimpleImplementation(printer, method, vars); printer->Print("// Returns a not-yet-started RPC object.\n"); PrintAdvancedSignature(printer, method, vars); PrintAdvancedImplementation(printer, method, vars); } } // namespace ::grpc::string GetHeader(const ServiceDescriptor *service) { ::grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. grpc::protobuf::io::StringOutputStream output_stream(&output); Printer printer(&output_stream, '$'); map< ::grpc::string, ::grpc::string> vars = { {"service_class", ServiceClassName(service)}}; printer.Print(vars, "@protocol $service_class$ \n\n"); for (int i = 0; i < service->method_count(); i++) { PrintMethodDeclarations(&printer, service->method(i)); } printer.Print("@end\n\n"); printer.Print( "/**\n" " * Basic service implementation, over gRPC, that only does\n" " * marshalling and parsing.\n" " */\n"); printer.Print(vars, "@interface $service_class$ :" " GRPCProtoService<$service_class$>\n"); printer.Print( "- (instancetype)initWithHost:(NSString *)host" " NS_DESIGNATED_INITIALIZER;\n"); printer.Print("+ (instancetype)serviceWithHost:(NSString *)host;\n"); printer.Print("@end\n"); } return output; } ::grpc::string GetSource(const ServiceDescriptor *service) { ::grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. grpc::protobuf::io::StringOutputStream output_stream(&output); Printer printer(&output_stream, '$'); map< ::grpc::string, ::grpc::string> vars = { {"service_name", service->name()}, {"service_class", ServiceClassName(service)}, {"package", service->file()->package()}}; printer.Print(vars, "@implementation $service_class$\n\n"); printer.Print("// Designated initializer\n"); printer.Print("- (instancetype)initWithHost:(NSString *)host {\n"); printer.Print( vars, " return (self = [super initWithHost:host" " packageName:@\"$package$\" serviceName:@\"$service_name$\"]);\n"); printer.Print("}\n\n"); printer.Print( "// Override superclass initializer to disallow different" " package and service names.\n"); printer.Print("- (instancetype)initWithHost:(NSString *)host\n"); printer.Print(" packageName:(NSString *)packageName\n"); printer.Print(" serviceName:(NSString *)serviceName {\n"); printer.Print(" return [self initWithHost:host];\n"); printer.Print("}\n\n"); printer.Print("+ (instancetype)serviceWithHost:(NSString *)host {\n"); printer.Print(" return [[self alloc] initWithHost:host];\n"); printer.Print("}\n\n\n"); for (int i = 0; i < service->method_count(); i++) { PrintMethodImplementations(&printer, service->method(i)); } printer.Print("@end\n"); } return output; } } // namespace grpc_objective_c_generator grpc-1.3.2/src/compiler/objective_c_generator.h000066400000000000000000000043171310511640000215400ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_H #define GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_H #include "src/compiler/config.h" namespace grpc_objective_c_generator { using ::grpc::protobuf::ServiceDescriptor; using ::grpc::string; // Returns the content to be included in the "global_scope" insertion point of // the generated header file. string GetHeader(const ServiceDescriptor *service); // Returns the content to be included in the "global_scope" insertion point of // the generated implementation file. string GetSource(const ServiceDescriptor *service); } // namespace grpc_objective_c_generator #endif // GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_H grpc-1.3.2/src/compiler/objective_c_generator_helpers.h000066400000000000000000000044471310511640000232660ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_HELPERS_H #define GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_HELPERS_H #include #include "src/compiler/config.h" #include "src/compiler/generator_helpers.h" namespace grpc_objective_c_generator { using ::grpc::protobuf::FileDescriptor; using ::grpc::protobuf::ServiceDescriptor; using ::grpc::string; inline string MessageHeaderName(const FileDescriptor *file) { return grpc_generator::FileNameInUpperCamel(file) + ".pbobjc.h"; } inline string ServiceClassName(const ServiceDescriptor *service) { const FileDescriptor *file = service->file(); string prefix = file->options().objc_class_prefix(); return prefix + service->name(); } } #endif // GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_HELPERS_H grpc-1.3.2/src/compiler/objective_c_plugin.cc000066400000000000000000000136071310511640000212100ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ // Generates Objective C gRPC service interface out of Protobuf IDL. #include #include "src/compiler/config.h" #include "src/compiler/objective_c_generator.h" #include "src/compiler/objective_c_generator_helpers.h" #include using ::google::protobuf::compiler::objectivec::ProtobufLibraryFrameworkName; using ::google::protobuf::compiler::objectivec:: IsProtobufLibraryBundledProtoFile; class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { public: ObjectiveCGrpcGenerator() {} virtual ~ObjectiveCGrpcGenerator() {} virtual bool Generate(const grpc::protobuf::FileDescriptor *file, const ::grpc::string ¶meter, grpc::protobuf::compiler::GeneratorContext *context, ::grpc::string *error) const { if (file->service_count() == 0) { // No services. Do nothing. return true; } ::grpc::string file_name = grpc_generator::FileNameInUpperCamel(file); ::grpc::string prefix = file->options().objc_class_prefix(); { // Generate .pbrpc.h ::grpc::string imports = ::grpc::string("#import \"") + file_name + ".pbobjc.h\"\n\n" "#import \n" "#import \n" "#import \n"; // TODO(jcanizales): Instead forward-declare the input and output types // and import the files in the .pbrpc.m ::grpc::string proto_imports; for (int i = 0; i < file->dependency_count(); i++) { ::grpc::string header = grpc_objective_c_generator::MessageHeaderName(file->dependency(i)); const grpc::protobuf::FileDescriptor *dependency = file->dependency(i); if (IsProtobufLibraryBundledProtoFile(dependency)) { ::grpc::string base_name = header; grpc_generator::StripPrefix(&base_name, "google/protobuf/"); // create the import code snippet proto_imports += "#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS\n" " #import <" + ::grpc::string(ProtobufLibraryFrameworkName) + "/" + base_name + ">\n" "#else\n" " #import \"" + header + "\"\n" "#endif\n"; } else { proto_imports += ::grpc::string("#import \"") + header + "\"\n"; } } ::grpc::string declarations; for (int i = 0; i < file->service_count(); i++) { const grpc::protobuf::ServiceDescriptor *service = file->service(i); declarations += grpc_objective_c_generator::GetHeader(service); } static const ::grpc::string kNonNullBegin = "\nNS_ASSUME_NONNULL_BEGIN\n\n"; static const ::grpc::string kNonNullEnd = "\nNS_ASSUME_NONNULL_END\n"; Write(context, file_name + ".pbrpc.h", imports + '\n' + proto_imports + '\n' + kNonNullBegin + declarations + kNonNullEnd); } { // Generate .pbrpc.m ::grpc::string imports = ::grpc::string("#import \"") + file_name + ".pbrpc.h\"\n\n" "#import \n" "#import \n"; ::grpc::string definitions; for (int i = 0; i < file->service_count(); i++) { const grpc::protobuf::ServiceDescriptor *service = file->service(i); definitions += grpc_objective_c_generator::GetSource(service); } Write(context, file_name + ".pbrpc.m", imports + '\n' + definitions); } return true; } private: // Write the given code into the given file. void Write(grpc::protobuf::compiler::GeneratorContext *context, const ::grpc::string &filename, const ::grpc::string &code) const { std::unique_ptr output( context->Open(filename)); grpc::protobuf::io::CodedOutputStream coded_out(output.get()); coded_out.WriteRaw(code.data(), code.size()); } }; int main(int argc, char *argv[]) { ObjectiveCGrpcGenerator generator; return grpc::protobuf::compiler::PluginMain(argc, argv, &generator); } grpc-1.3.2/src/compiler/php_generator.cc000066400000000000000000000137261310511640000202150ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "src/compiler/config.h" #include "src/compiler/generator_helpers.h" #include "src/compiler/php_generator_helpers.h" using grpc::protobuf::FileDescriptor; using grpc::protobuf::ServiceDescriptor; using grpc::protobuf::MethodDescriptor; using grpc::protobuf::Descriptor; using grpc::protobuf::io::Printer; using grpc::protobuf::io::StringOutputStream; using std::map; namespace grpc_php_generator { namespace { grpc::string MessageIdentifierName(const grpc::string &name) { std::vector tokens = grpc_generator::tokenize(name, "."); std::ostringstream oss; for (unsigned int i = 0; i < tokens.size(); i++) { oss << (i == 0 ? "" : "\\") << grpc_generator::CapitalizeFirstLetter(tokens[i]); } return oss.str(); } void PrintMethod(const MethodDescriptor *method, Printer *out) { const Descriptor *input_type = method->input_type(); const Descriptor *output_type = method->output_type(); map vars; vars["service_name"] = method->service()->full_name(); vars["name"] = method->name(); vars["input_type_id"] = MessageIdentifierName(input_type->full_name()); vars["output_type_id"] = MessageIdentifierName(output_type->full_name()); out->Print("/**\n"); out->Print(GetPHPComments(method, " *").c_str()); if (method->client_streaming()) { out->Print(vars, " * @param array $$metadata metadata\n" " * @param array $$options call options\n */\n" "public function $name$($$metadata = [], " "$$options = []) {\n"); out->Indent(); if (method->server_streaming()) { out->Print("return $$this->_bidiRequest("); } else { out->Print("return $$this->_clientStreamRequest("); } out->Print(vars, "'/$service_name$/$name$',\n" "['\\$output_type_id$','decode'],\n" "$$metadata, $$options);\n"); } else { out->Print(vars, " * @param \\$input_type_id$ $$argument input argument\n" " * @param array $$metadata metadata\n" " * @param array $$options call options\n */\n" "public function $name$(\\$input_type_id$ $$argument,\n" " $$metadata = [], $$options = []) {\n"); out->Indent(); if (method->server_streaming()) { out->Print("return $$this->_serverStreamRequest("); } else { out->Print("return $$this->_simpleRequest("); } out->Print(vars, "'/$service_name$/$name$',\n" "$$argument,\n" "['\\$output_type_id$', 'decode'],\n" "$$metadata, $$options);\n"); } out->Outdent(); out->Print("}\n\n"); } // Prints out the service descriptor object void PrintService(const ServiceDescriptor *service, Printer *out) { map vars; out->Print(GetPHPComments(service, "//").c_str()); vars["name"] = service->name(); out->Print(vars, "class $name$Client extends \\Grpc\\BaseStub {\n\n"); out->Indent(); out->Print( "/**\n * @param string $$hostname hostname\n" " * @param array $$opts channel options\n" " * @param \\Grpc\\Channel $$channel (optional) re-use channel " "object\n */\n" "public function __construct($$hostname, $$opts, " "$$channel = null) {\n"); out->Indent(); out->Print("parent::__construct($$hostname, $$opts, $$channel);\n"); out->Outdent(); out->Print("}\n\n"); for (int i = 0; i < service->method_count(); i++) { grpc::string method_name = grpc_generator::LowercaseFirstLetter(service->method(i)->name()); PrintMethod(service->method(i), out); } out->Outdent(); out->Print("}\n\n"); } } grpc::string GenerateFile(const FileDescriptor *file, const ServiceDescriptor *service) { grpc::string output; { StringOutputStream output_stream(&output); Printer out(&output_stream, '$'); out.Print(" vars; vars["package"] = MessageIdentifierName(file->package()); out.Print(vars, "namespace $package$ {\n\n"); out.Indent(); PrintService(service, &out); out.Outdent(); out.Print("}\n"); } return output; } } // namespace grpc_php_generator grpc-1.3.2/src/compiler/php_generator.h000066400000000000000000000036551310511640000200570ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_COMPILER_PHP_GENERATOR_H #define GRPC_INTERNAL_COMPILER_PHP_GENERATOR_H #include "src/compiler/config.h" namespace grpc_php_generator { grpc::string GenerateFile(const grpc::protobuf::FileDescriptor *file, const grpc::protobuf::ServiceDescriptor *service); } // namespace grpc_php_generator #endif // GRPC_INTERNAL_COMPILER_PHP_GENERATOR_H grpc-1.3.2/src/compiler/php_generator_helpers.h000066400000000000000000000053061310511640000215740ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_COMPILER_PHP_GENERATOR_HELPERS_H #define GRPC_INTERNAL_COMPILER_PHP_GENERATOR_HELPERS_H #include #include "src/compiler/config.h" #include "src/compiler/generator_helpers.h" namespace grpc_php_generator { inline grpc::string GetPHPServiceFilename( const grpc::protobuf::FileDescriptor *file, const grpc::protobuf::ServiceDescriptor *service) { std::vector tokens = grpc_generator::tokenize(file->package(), "."); std::ostringstream oss; for (unsigned int i = 0; i < tokens.size(); i++) { oss << (i == 0 ? "" : "/") << grpc_generator::CapitalizeFirstLetter(tokens[i]); } return oss.str() + "/" + service->name() + "Client.php"; } // Get leading or trailing comments in a string. Comment lines start with "// ". // Leading detached comments are put in in front of leading comments. template inline grpc::string GetPHPComments(const DescriptorType *desc, grpc::string prefix) { return grpc_generator::GetPrefixedComments(desc, true, prefix); } } // namespace grpc_php_generator #endif // GRPC_INTERNAL_COMPILER_PHP_GENERATOR_HELPERS_H grpc-1.3.2/src/compiler/php_plugin.cc000066400000000000000000000055351310511640000175240ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ // Generates PHP gRPC service interface out of Protobuf IDL. #include #include "src/compiler/config.h" #include "src/compiler/php_generator.h" #include "src/compiler/php_generator_helpers.h" using grpc_php_generator::GenerateFile; using grpc_php_generator::GetPHPServiceFilename; class PHPGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { public: PHPGrpcGenerator() {} ~PHPGrpcGenerator() {} bool Generate(const grpc::protobuf::FileDescriptor *file, const grpc::string ¶meter, grpc::protobuf::compiler::GeneratorContext *context, grpc::string *error) const { if (file->service_count() == 0) { return true; } for (int i = 0; i < file->service_count(); i++) { grpc::string code = GenerateFile(file, file->service(i)); // Get output file name grpc::string file_name = GetPHPServiceFilename(file, file->service(i)); std::unique_ptr output( context->Open(file_name)); grpc::protobuf::io::CodedOutputStream coded_out(output.get()); coded_out.WriteRaw(code.data(), code.size()); } return true; } }; int main(int argc, char *argv[]) { PHPGrpcGenerator generator; return grpc::protobuf::compiler::PluginMain(argc, argv, &generator); } grpc-1.3.2/src/compiler/protobuf_plugin.h000066400000000000000000000164611310511640000204370ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_COMPILER_PROTOBUF_PLUGIN_H #define GRPC_INTERNAL_COMPILER_PROTOBUF_PLUGIN_H #include "src/compiler/config.h" #include "src/compiler/cpp_generator_helpers.h" #include "src/compiler/python_generator_helpers.h" #include "src/compiler/python_private_generator.h" #include "src/compiler/schema_interface.h" #include // Get leading or trailing comments in a string. template inline grpc::string GetCommentsHelper(const DescriptorType *desc, bool leading, const grpc::string &prefix) { return grpc_generator::GetPrefixedComments(desc, leading, prefix); } class ProtoBufMethod : public grpc_generator::Method { public: ProtoBufMethod(const grpc::protobuf::MethodDescriptor *method) : method_(method) {} grpc::string name() const { return method_->name(); } grpc::string input_type_name() const { return grpc_cpp_generator::ClassName(method_->input_type(), true); } grpc::string output_type_name() const { return grpc_cpp_generator::ClassName(method_->output_type(), true); } grpc::string get_input_type_name() const { return method_->input_type()->file()->name(); } grpc::string get_output_type_name() const { return method_->output_type()->file()->name(); } bool get_module_and_message_path_input(grpc::string *str, grpc::string generator_file_name, bool generate_in_pb2_grpc, grpc::string import_prefix) const { return grpc_python_generator::GetModuleAndMessagePath( method_->input_type(), str, generator_file_name, generate_in_pb2_grpc, import_prefix); } bool get_module_and_message_path_output(grpc::string *str, grpc::string generator_file_name, bool generate_in_pb2_grpc, grpc::string import_prefix) const { return grpc_python_generator::GetModuleAndMessagePath( method_->output_type(), str, generator_file_name, generate_in_pb2_grpc, import_prefix); } bool NoStreaming() const { return !method_->client_streaming() && !method_->server_streaming(); } bool ClientStreaming() const { return method_->client_streaming(); } bool ServerStreaming() const { return method_->server_streaming(); } bool BidiStreaming() const { return method_->client_streaming() && method_->server_streaming(); } grpc::string GetLeadingComments(const grpc::string prefix) const { return GetCommentsHelper(method_, true, prefix); } grpc::string GetTrailingComments(const grpc::string prefix) const { return GetCommentsHelper(method_, false, prefix); } vector GetAllComments() const { return grpc_python_generator::get_all_comments(method_); } private: const grpc::protobuf::MethodDescriptor *method_; }; class ProtoBufService : public grpc_generator::Service { public: ProtoBufService(const grpc::protobuf::ServiceDescriptor *service) : service_(service) {} grpc::string name() const { return service_->name(); } int method_count() const { return service_->method_count(); }; std::unique_ptr method(int i) const { return std::unique_ptr( new ProtoBufMethod(service_->method(i))); }; grpc::string GetLeadingComments(const grpc::string prefix) const { return GetCommentsHelper(service_, true, prefix); } grpc::string GetTrailingComments(const grpc::string prefix) const { return GetCommentsHelper(service_, false, prefix); } vector GetAllComments() const { return grpc_python_generator::get_all_comments(service_); } private: const grpc::protobuf::ServiceDescriptor *service_; }; class ProtoBufPrinter : public grpc_generator::Printer { public: ProtoBufPrinter(grpc::string *str) : output_stream_(str), printer_(&output_stream_, '$') {} void Print(const std::map &vars, const char *string_template) { printer_.Print(vars, string_template); } void Print(const char *string) { printer_.Print(string); } void Indent() { printer_.Indent(); } void Outdent() { printer_.Outdent(); } private: grpc::protobuf::io::StringOutputStream output_stream_; grpc::protobuf::io::Printer printer_; }; class ProtoBufFile : public grpc_generator::File { public: ProtoBufFile(const grpc::protobuf::FileDescriptor *file) : file_(file) {} grpc::string filename() const { return file_->name(); } grpc::string filename_without_ext() const { return grpc_generator::StripProto(filename()); } grpc::string package() const { return file_->package(); } std::vector package_parts() const { return grpc_generator::tokenize(package(), "."); } grpc::string additional_headers() const { return ""; } int service_count() const { return file_->service_count(); }; std::unique_ptr service(int i) const { return std::unique_ptr( new ProtoBufService(file_->service(i))); } std::unique_ptr CreatePrinter( grpc::string *str) const { return std::unique_ptr(new ProtoBufPrinter(str)); } grpc::string GetLeadingComments(const grpc::string prefix) const { return GetCommentsHelper(file_, true, prefix); } grpc::string GetTrailingComments(const grpc::string prefix) const { return GetCommentsHelper(file_, false, prefix); } vector GetAllComments() const { return grpc_python_generator::get_all_comments(file_); } private: const grpc::protobuf::FileDescriptor *file_; }; #endif // GRPC_INTERNAL_COMPILER_PROTOBUF_PLUGIN_H grpc-1.3.2/src/compiler/python_generator.cc000066400000000000000000000742171310511640000207510ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "src/compiler/config.h" #include "src/compiler/generator_helpers.h" #include "src/compiler/protobuf_plugin.h" #include "src/compiler/python_generator.h" #include "src/compiler/python_generator_helpers.h" #include "src/compiler/python_private_generator.h" using grpc::protobuf::FileDescriptor; using grpc::protobuf::compiler::GeneratorContext; using grpc::protobuf::io::CodedOutputStream; using grpc::protobuf::io::ZeroCopyOutputStream; using std::make_pair; using std::map; using std::pair; using std::replace; using std::tuple; using std::vector; using std::set; namespace grpc_python_generator { grpc::string generator_file_name; namespace { typedef map StringMap; typedef vector StringVector; typedef tuple StringPair; typedef set StringPairSet; // Provides RAII indentation handling. Use as: // { // IndentScope raii_my_indent_var_name_here(my_py_printer); // // constructor indented my_py_printer // ... // // destructor called at end of scope, un-indenting my_py_printer // } class IndentScope { public: explicit IndentScope(grpc_generator::Printer* printer) : printer_(printer) { printer_->Indent(); } ~IndentScope() { printer_->Outdent(); } private: grpc_generator::Printer* printer_; }; PrivateGenerator::PrivateGenerator(const GeneratorConfiguration& config, const grpc_generator::File* file) : config(config), file(file) {} void PrivateGenerator::PrintAllComments(StringVector comments, grpc_generator::Printer* out) { if (comments.empty()) { return; } out->Print("\"\"\""); for (StringVector::iterator it = comments.begin(); it != comments.end(); ++it) { size_t start_pos = it->find_first_not_of(' '); if (start_pos != grpc::string::npos) { out->Print(it->c_str() + start_pos); } out->Print("\n"); } out->Print("\"\"\"\n"); } bool PrivateGenerator::PrintBetaServicer(const grpc_generator::Service* service, grpc_generator::Printer* out) { StringMap service_dict; service_dict["Service"] = service->name(); out->Print("\n\n"); out->Print(service_dict, "class Beta$Service$Servicer(object):\n"); { IndentScope raii_class_indent(out); out->Print( "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n" "\nIt is recommended to use the GA API (classes and functions in this\n" "file not marked beta) for all further purposes. This class was " "generated\n" "only to ease transition from grpcio<0.15.0 to " "grpcio>=0.15.0.\"\"\"\n"); StringVector service_comments = service->GetAllComments(); PrintAllComments(service_comments, out); for (int i = 0; i < service->method_count(); ++i) { auto method = service->method(i); grpc::string arg_name = method->ClientStreaming() ? "request_iterator" : "request"; StringMap method_dict; method_dict["Method"] = method->name(); method_dict["ArgName"] = arg_name; out->Print(method_dict, "def $Method$(self, $ArgName$, context):\n"); { IndentScope raii_method_indent(out); StringVector method_comments = method->GetAllComments(); PrintAllComments(method_comments, out); out->Print("context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)\n"); } } } return true; } bool PrivateGenerator::PrintBetaStub(const grpc_generator::Service* service, grpc_generator::Printer* out) { StringMap service_dict; service_dict["Service"] = service->name(); out->Print("\n\n"); out->Print(service_dict, "class Beta$Service$Stub(object):\n"); { IndentScope raii_class_indent(out); out->Print( "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n" "\nIt is recommended to use the GA API (classes and functions in this\n" "file not marked beta) for all further purposes. This class was " "generated\n" "only to ease transition from grpcio<0.15.0 to " "grpcio>=0.15.0.\"\"\"\n"); StringVector service_comments = service->GetAllComments(); PrintAllComments(service_comments, out); for (int i = 0; i < service->method_count(); ++i) { auto method = service->method(i); grpc::string arg_name = method->ClientStreaming() ? "request_iterator" : "request"; StringMap method_dict; method_dict["Method"] = method->name(); method_dict["ArgName"] = arg_name; out->Print(method_dict, "def $Method$(self, $ArgName$, timeout, metadata=None, " "with_call=False, protocol_options=None):\n"); { IndentScope raii_method_indent(out); StringVector method_comments = method->GetAllComments(); PrintAllComments(method_comments, out); out->Print("raise NotImplementedError()\n"); } if (!method->ServerStreaming()) { out->Print(method_dict, "$Method$.future = None\n"); } } } return true; } bool PrivateGenerator::PrintBetaServerFactory( const grpc::string& package_qualified_service_name, const grpc_generator::Service* service, grpc_generator::Printer* out) { StringMap service_dict; service_dict["Service"] = service->name(); out->Print("\n\n"); out->Print(service_dict, "def beta_create_$Service$_server(servicer, pool=None, " "pool_size=None, default_timeout=None, maximum_timeout=None):\n"); { IndentScope raii_create_server_indent(out); out->Print( "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n" "\nIt is recommended to use the GA API (classes and functions in this\n" "file not marked beta) for all further purposes. This function was\n" "generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0" "\"\"\"\n"); StringMap method_implementation_constructors; StringMap input_message_modules_and_classes; StringMap output_message_modules_and_classes; for (int i = 0; i < service->method_count(); ++i) { auto method = service->method(i); const grpc::string method_implementation_constructor = grpc::string(method->ClientStreaming() ? "stream_" : "unary_") + grpc::string(method->ServerStreaming() ? "stream_" : "unary_") + "inline"; grpc::string input_message_module_and_class; if (!method->get_module_and_message_path_input( &input_message_module_and_class, generator_file_name, generate_in_pb2_grpc, config.import_prefix)) { return false; } grpc::string output_message_module_and_class; if (!method->get_module_and_message_path_output( &output_message_module_and_class, generator_file_name, generate_in_pb2_grpc, config.import_prefix)) { return false; } method_implementation_constructors.insert( make_pair(method->name(), method_implementation_constructor)); input_message_modules_and_classes.insert( make_pair(method->name(), input_message_module_and_class)); output_message_modules_and_classes.insert( make_pair(method->name(), output_message_module_and_class)); } StringMap method_dict; method_dict["PackageQualifiedServiceName"] = package_qualified_service_name; out->Print("request_deserializers = {\n"); for (StringMap::iterator name_and_input_module_class_pair = input_message_modules_and_classes.begin(); name_and_input_module_class_pair != input_message_modules_and_classes.end(); name_and_input_module_class_pair++) { method_dict["MethodName"] = name_and_input_module_class_pair->first; method_dict["InputTypeModuleAndClass"] = name_and_input_module_class_pair->second; IndentScope raii_indent(out); out->Print(method_dict, "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): " "$InputTypeModuleAndClass$.FromString,\n"); } out->Print("}\n"); out->Print("response_serializers = {\n"); for (StringMap::iterator name_and_output_module_class_pair = output_message_modules_and_classes.begin(); name_and_output_module_class_pair != output_message_modules_and_classes.end(); name_and_output_module_class_pair++) { method_dict["MethodName"] = name_and_output_module_class_pair->first; method_dict["OutputTypeModuleAndClass"] = name_and_output_module_class_pair->second; IndentScope raii_indent(out); out->Print(method_dict, "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): " "$OutputTypeModuleAndClass$.SerializeToString,\n"); } out->Print("}\n"); out->Print("method_implementations = {\n"); for (StringMap::iterator name_and_implementation_constructor = method_implementation_constructors.begin(); name_and_implementation_constructor != method_implementation_constructors.end(); name_and_implementation_constructor++) { method_dict["Method"] = name_and_implementation_constructor->first; method_dict["Constructor"] = name_and_implementation_constructor->second; IndentScope raii_descriptions_indent(out); const grpc::string method_name = name_and_implementation_constructor->first; out->Print(method_dict, "(\'$PackageQualifiedServiceName$\', \'$Method$\'): " "face_utilities.$Constructor$(servicer.$Method$),\n"); } out->Print("}\n"); out->Print( "server_options = beta_implementations.server_options(" "request_deserializers=request_deserializers, " "response_serializers=response_serializers, " "thread_pool=pool, thread_pool_size=pool_size, " "default_timeout=default_timeout, " "maximum_timeout=maximum_timeout)\n"); out->Print( "return beta_implementations.server(method_implementations, " "options=server_options)\n"); } return true; } bool PrivateGenerator::PrintBetaStubFactory( const grpc::string& package_qualified_service_name, const grpc_generator::Service* service, grpc_generator::Printer* out) { StringMap dict; dict["Service"] = service->name(); out->Print("\n\n"); out->Print(dict, "def beta_create_$Service$_stub(channel, host=None," " metadata_transformer=None, pool=None, pool_size=None):\n"); { IndentScope raii_create_server_indent(out); out->Print( "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n" "\nIt is recommended to use the GA API (classes and functions in this\n" "file not marked beta) for all further purposes. This function was\n" "generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0" "\"\"\"\n"); StringMap method_cardinalities; StringMap input_message_modules_and_classes; StringMap output_message_modules_and_classes; for (int i = 0; i < service->method_count(); ++i) { auto method = service->method(i); const grpc::string method_cardinality = grpc::string(method->ClientStreaming() ? "STREAM" : "UNARY") + "_" + grpc::string(method->ServerStreaming() ? "STREAM" : "UNARY"); grpc::string input_message_module_and_class; if (!method->get_module_and_message_path_input( &input_message_module_and_class, generator_file_name, generate_in_pb2_grpc, config.import_prefix)) { return false; } grpc::string output_message_module_and_class; if (!method->get_module_and_message_path_output( &output_message_module_and_class, generator_file_name, generate_in_pb2_grpc, config.import_prefix)) { return false; } method_cardinalities.insert( make_pair(method->name(), method_cardinality)); input_message_modules_and_classes.insert( make_pair(method->name(), input_message_module_and_class)); output_message_modules_and_classes.insert( make_pair(method->name(), output_message_module_and_class)); } StringMap method_dict; method_dict["PackageQualifiedServiceName"] = package_qualified_service_name; out->Print("request_serializers = {\n"); for (StringMap::iterator name_and_input_module_class_pair = input_message_modules_and_classes.begin(); name_and_input_module_class_pair != input_message_modules_and_classes.end(); name_and_input_module_class_pair++) { method_dict["MethodName"] = name_and_input_module_class_pair->first; method_dict["InputTypeModuleAndClass"] = name_and_input_module_class_pair->second; IndentScope raii_indent(out); out->Print(method_dict, "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): " "$InputTypeModuleAndClass$.SerializeToString,\n"); } out->Print("}\n"); out->Print("response_deserializers = {\n"); for (StringMap::iterator name_and_output_module_class_pair = output_message_modules_and_classes.begin(); name_and_output_module_class_pair != output_message_modules_and_classes.end(); name_and_output_module_class_pair++) { method_dict["MethodName"] = name_and_output_module_class_pair->first; method_dict["OutputTypeModuleAndClass"] = name_and_output_module_class_pair->second; IndentScope raii_indent(out); out->Print(method_dict, "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): " "$OutputTypeModuleAndClass$.FromString,\n"); } out->Print("}\n"); out->Print("cardinalities = {\n"); for (StringMap::iterator name_and_cardinality = method_cardinalities.begin(); name_and_cardinality != method_cardinalities.end(); name_and_cardinality++) { method_dict["Method"] = name_and_cardinality->first; method_dict["Cardinality"] = name_and_cardinality->second; IndentScope raii_descriptions_indent(out); out->Print(method_dict, "\'$Method$\': cardinality.Cardinality.$Cardinality$,\n"); } out->Print("}\n"); out->Print( "stub_options = beta_implementations.stub_options(" "host=host, metadata_transformer=metadata_transformer, " "request_serializers=request_serializers, " "response_deserializers=response_deserializers, " "thread_pool=pool, thread_pool_size=pool_size)\n"); out->Print(method_dict, "return beta_implementations.dynamic_stub(channel, " "\'$PackageQualifiedServiceName$\', " "cardinalities, options=stub_options)\n"); } return true; } bool PrivateGenerator::PrintStub( const grpc::string& package_qualified_service_name, const grpc_generator::Service* service, grpc_generator::Printer* out) { StringMap dict; dict["Service"] = service->name(); out->Print("\n\n"); out->Print(dict, "class $Service$Stub(object):\n"); { IndentScope raii_class_indent(out); StringVector service_comments = service->GetAllComments(); PrintAllComments(service_comments, out); out->Print("\n"); out->Print("def __init__(self, channel):\n"); { IndentScope raii_init_indent(out); out->Print("\"\"\"Constructor.\n"); out->Print("\n"); out->Print("Args:\n"); { IndentScope raii_args_indent(out); out->Print("channel: A grpc.Channel.\n"); } out->Print("\"\"\"\n"); for (int i = 0; i < service->method_count(); ++i) { auto method = service->method(i); grpc::string multi_callable_constructor = grpc::string(method->ClientStreaming() ? "stream" : "unary") + "_" + grpc::string(method->ServerStreaming() ? "stream" : "unary"); grpc::string request_module_and_class; if (!method->get_module_and_message_path_input( &request_module_and_class, generator_file_name, generate_in_pb2_grpc, config.import_prefix)) { return false; } grpc::string response_module_and_class; if (!method->get_module_and_message_path_output( &response_module_and_class, generator_file_name, generate_in_pb2_grpc, config.import_prefix)) { return false; } StringMap method_dict; method_dict["Method"] = method->name(); method_dict["MultiCallableConstructor"] = multi_callable_constructor; out->Print(method_dict, "self.$Method$ = channel.$MultiCallableConstructor$(\n"); { method_dict["PackageQualifiedService"] = package_qualified_service_name; method_dict["RequestModuleAndClass"] = request_module_and_class; method_dict["ResponseModuleAndClass"] = response_module_and_class; IndentScope raii_first_attribute_indent(out); IndentScope raii_second_attribute_indent(out); out->Print(method_dict, "'/$PackageQualifiedService$/$Method$',\n"); out->Print(method_dict, "request_serializer=$RequestModuleAndClass$." "SerializeToString,\n"); out->Print( method_dict, "response_deserializer=$ResponseModuleAndClass$.FromString,\n"); out->Print(")\n"); } } } } return true; } bool PrivateGenerator::PrintServicer(const grpc_generator::Service* service, grpc_generator::Printer* out) { StringMap service_dict; service_dict["Service"] = service->name(); out->Print("\n\n"); out->Print(service_dict, "class $Service$Servicer(object):\n"); { IndentScope raii_class_indent(out); StringVector service_comments = service->GetAllComments(); PrintAllComments(service_comments, out); for (int i = 0; i < service->method_count(); ++i) { auto method = service->method(i); grpc::string arg_name = method->ClientStreaming() ? "request_iterator" : "request"; StringMap method_dict; method_dict["Method"] = method->name(); method_dict["ArgName"] = arg_name; out->Print("\n"); out->Print(method_dict, "def $Method$(self, $ArgName$, context):\n"); { IndentScope raii_method_indent(out); StringVector method_comments = method->GetAllComments(); PrintAllComments(method_comments, out); out->Print("context.set_code(grpc.StatusCode.UNIMPLEMENTED)\n"); out->Print("context.set_details('Method not implemented!')\n"); out->Print("raise NotImplementedError('Method not implemented!')\n"); } } } return true; } bool PrivateGenerator::PrintAddServicerToServer( const grpc::string& package_qualified_service_name, const grpc_generator::Service* service, grpc_generator::Printer* out) { StringMap service_dict; service_dict["Service"] = service->name(); out->Print("\n\n"); out->Print(service_dict, "def add_$Service$Servicer_to_server(servicer, server):\n"); { IndentScope raii_class_indent(out); out->Print("rpc_method_handlers = {\n"); { IndentScope raii_dict_first_indent(out); IndentScope raii_dict_second_indent(out); for (int i = 0; i < service->method_count(); ++i) { auto method = service->method(i); grpc::string method_handler_constructor = grpc::string(method->ClientStreaming() ? "stream" : "unary") + "_" + grpc::string(method->ServerStreaming() ? "stream" : "unary") + "_rpc_method_handler"; grpc::string request_module_and_class; if (!method->get_module_and_message_path_input( &request_module_and_class, generator_file_name, generate_in_pb2_grpc, config.import_prefix)) { return false; } grpc::string response_module_and_class; if (!method->get_module_and_message_path_output( &response_module_and_class, generator_file_name, generate_in_pb2_grpc, config.import_prefix)) { return false; } StringMap method_dict; method_dict["Method"] = method->name(); method_dict["MethodHandlerConstructor"] = method_handler_constructor; method_dict["RequestModuleAndClass"] = request_module_and_class; method_dict["ResponseModuleAndClass"] = response_module_and_class; out->Print(method_dict, "'$Method$': grpc.$MethodHandlerConstructor$(\n"); { IndentScope raii_call_first_indent(out); IndentScope raii_call_second_indent(out); out->Print(method_dict, "servicer.$Method$,\n"); out->Print( method_dict, "request_deserializer=$RequestModuleAndClass$.FromString,\n"); out->Print( method_dict, "response_serializer=$ResponseModuleAndClass$.SerializeToString," "\n"); } out->Print("),\n"); } } StringMap method_dict; method_dict["PackageQualifiedServiceName"] = package_qualified_service_name; out->Print("}\n"); out->Print("generic_handler = grpc.method_handlers_generic_handler(\n"); { IndentScope raii_call_first_indent(out); IndentScope raii_call_second_indent(out); out->Print(method_dict, "'$PackageQualifiedServiceName$', rpc_method_handlers)\n"); } out->Print("server.add_generic_rpc_handlers((generic_handler,))\n"); } return true; } bool PrivateGenerator::PrintBetaPreamble(grpc_generator::Printer* out) { StringMap var; var["Package"] = config.beta_package_root; out->Print(var, "from $Package$ import implementations as beta_implementations\n"); out->Print(var, "from $Package$ import interfaces as beta_interfaces\n"); out->Print("from grpc.framework.common import cardinality\n"); out->Print( "from grpc.framework.interfaces.face import utilities as " "face_utilities\n"); return true; } bool PrivateGenerator::PrintPreamble(grpc_generator::Printer* out) { StringMap var; var["Package"] = config.grpc_package_root; out->Print(var, "import $Package$\n"); if (generate_in_pb2_grpc) { out->Print("\n"); StringPairSet imports_set; for (int i = 0; i < file->service_count(); ++i) { auto service = file->service(i); for (int j = 0; j < service->method_count(); ++j) { auto method = service.get()->method(j); grpc::string input_type_file_name = method->get_input_type_name(); grpc::string input_module_name = ModuleName(input_type_file_name, config.import_prefix); grpc::string input_module_alias = ModuleAlias(input_type_file_name, config.import_prefix); imports_set.insert( std::make_tuple(input_module_name, input_module_alias)); grpc::string output_type_file_name = method->get_output_type_name(); grpc::string output_module_name = ModuleName(output_type_file_name, config.import_prefix); grpc::string output_module_alias = ModuleAlias(output_type_file_name, config.import_prefix); imports_set.insert( std::make_tuple(output_module_name, output_module_alias)); } } for (StringPairSet::iterator it = imports_set.begin(); it != imports_set.end(); ++it) { var["ModuleName"] = std::get<0>(*it); var["ModuleAlias"] = std::get<1>(*it); out->Print(var, "import $ModuleName$ as $ModuleAlias$\n"); } } return true; } bool PrivateGenerator::PrintGAServices(grpc_generator::Printer* out) { grpc::string package = file->package(); if (!package.empty()) { package = package.append("."); } for (int i = 0; i < file->service_count(); ++i) { auto service = file->service(i); grpc::string package_qualified_service_name = package + service->name(); if (!(PrintStub(package_qualified_service_name, service.get(), out) && PrintServicer(service.get(), out) && PrintAddServicerToServer(package_qualified_service_name, service.get(), out))) { return false; } } return true; } bool PrivateGenerator::PrintBetaServices(grpc_generator::Printer* out) { grpc::string package = file->package(); if (!package.empty()) { package = package.append("."); } for (int i = 0; i < file->service_count(); ++i) { auto service = file->service(i); grpc::string package_qualified_service_name = package + service->name(); if (!(PrintBetaServicer(service.get(), out) && PrintBetaStub(service.get(), out) && PrintBetaServerFactory(package_qualified_service_name, service.get(), out) && PrintBetaStubFactory(package_qualified_service_name, service.get(), out))) { return false; } } return true; } pair PrivateGenerator::GetGrpcServices() { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. auto out = file->CreatePrinter(&output); if (generate_in_pb2_grpc) { out->Print( "# Generated by the gRPC Python protocol compiler plugin. " "DO NOT EDIT!\n"); if (!PrintPreamble(out.get())) { return make_pair(false, ""); } if (!PrintGAServices(out.get())) { return make_pair(false, ""); } } else { out->Print("try:\n"); { IndentScope raii_dict_try_indent(out.get()); out->Print( "# THESE ELEMENTS WILL BE DEPRECATED.\n" "# Please use the generated *_pb2_grpc.py files instead.\n"); if (!PrintPreamble(out.get())) { return make_pair(false, ""); } if (!PrintBetaPreamble(out.get())) { return make_pair(false, ""); } if (!PrintGAServices(out.get())) { return make_pair(false, ""); } if (!PrintBetaServices(out.get())) { return make_pair(false, ""); } } out->Print("except ImportError:\n"); { IndentScope raii_dict_except_indent(out.get()); out->Print("pass"); } } } return make_pair(true, std::move(output)); } } // namespace GeneratorConfiguration::GeneratorConfiguration() : grpc_package_root("grpc"), beta_package_root("grpc.beta"), import_prefix("") {} PythonGrpcGenerator::PythonGrpcGenerator(const GeneratorConfiguration& config) : config_(config) {} PythonGrpcGenerator::~PythonGrpcGenerator() {} static bool GenerateGrpc(GeneratorContext* context, PrivateGenerator& generator, grpc::string file_name, bool generate_in_pb2_grpc) { bool success; std::unique_ptr output; std::unique_ptr coded_output; grpc::string grpc_code; if (generate_in_pb2_grpc) { output.reset(context->Open(file_name)); generator.generate_in_pb2_grpc = true; } else { output.reset(context->OpenForInsert(file_name, "module_scope")); generator.generate_in_pb2_grpc = false; } coded_output.reset(new CodedOutputStream(output.get())); tie(success, grpc_code) = generator.GetGrpcServices(); if (success) { coded_output->WriteRaw(grpc_code.data(), grpc_code.size()); return true; } else { return false; } } bool PythonGrpcGenerator::Generate(const FileDescriptor* file, const grpc::string& parameter, GeneratorContext* context, grpc::string* error) const { // Get output file name. grpc::string pb2_file_name; grpc::string pb2_grpc_file_name; static const int proto_suffix_length = strlen(".proto"); if (file->name().size() > static_cast(proto_suffix_length) && file->name().find_last_of(".proto") == file->name().size() - 1) { grpc::string base = file->name().substr(0, file->name().size() - proto_suffix_length); pb2_file_name = base + "_pb2.py"; pb2_grpc_file_name = base + "_pb2_grpc.py"; } else { *error = "Invalid proto file name. Proto file must end with .proto"; return false; } generator_file_name = file->name(); ProtoBufFile pbfile(file); PrivateGenerator generator(config_, &pbfile); if (parameter == "grpc_2_0") { return GenerateGrpc(context, generator, pb2_grpc_file_name, true); } else if (parameter == "") { return GenerateGrpc(context, generator, pb2_grpc_file_name, true) && GenerateGrpc(context, generator, pb2_file_name, false); } else { *error = "Invalid parameter '" + parameter + "'."; return false; } } } // namespace grpc_python_generator grpc-1.3.2/src/compiler/python_generator.h000066400000000000000000000053011310511640000205770ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H #define GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H #include #include "src/compiler/config.h" #include "src/compiler/schema_interface.h" namespace grpc_python_generator { // Data pertaining to configuration of the generator with respect to anything // that may be used internally at Google. struct GeneratorConfiguration { GeneratorConfiguration(); grpc::string grpc_package_root; // TODO(https://github.com/grpc/grpc/issues/8622): Drop this. grpc::string beta_package_root; // TODO(https://github.com/google/protobuf/issues/888): Drop this. grpc::string import_prefix; }; class PythonGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { public: PythonGrpcGenerator(const GeneratorConfiguration& config); ~PythonGrpcGenerator(); bool Generate(const grpc::protobuf::FileDescriptor* file, const grpc::string& parameter, grpc::protobuf::compiler::GeneratorContext* context, grpc::string* error) const; private: GeneratorConfiguration config_; }; } // namespace grpc_python_generator #endif // GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H grpc-1.3.2/src/compiler/python_generator_helpers.h000066400000000000000000000127401310511640000223260ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_HELPERS_H #define GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_HELPERS_H #include #include #include #include #include "src/compiler/config.h" #include "src/compiler/generator_helpers.h" #include "src/compiler/python_generator.h" #include "src/compiler/python_private_generator.h" using std::vector; using grpc_generator::StringReplace; using grpc_generator::StripProto; using grpc::protobuf::Descriptor; using grpc::protobuf::FileDescriptor; using grpc::protobuf::MethodDescriptor; using grpc::protobuf::ServiceDescriptor; using grpc::protobuf::compiler::GeneratorContext; using grpc::protobuf::io::CodedOutputStream; using grpc::protobuf::io::Printer; using grpc::protobuf::io::StringOutputStream; using grpc::protobuf::io::ZeroCopyOutputStream; namespace grpc_python_generator { namespace { typedef vector DescriptorVector; typedef vector StringVector; // TODO(https://github.com/google/protobuf/issues/888): // Export `ModuleName` from protobuf's // `src/google/protobuf/compiler/python/python_generator.cc` file. grpc::string ModuleName(const grpc::string& filename, const grpc::string& import_prefix) { grpc::string basename = StripProto(filename); basename = StringReplace(basename, "-", "_"); basename = StringReplace(basename, "/", "."); return import_prefix + basename + "_pb2"; } // TODO(https://github.com/google/protobuf/issues/888): // Export `ModuleAlias` from protobuf's // `src/google/protobuf/compiler/python/python_generator.cc` file. grpc::string ModuleAlias(const grpc::string& filename, const grpc::string& import_prefix) { grpc::string module_name = ModuleName(filename, import_prefix); // We can't have dots in the module name, so we replace each with _dot_. // But that could lead to a collision between a.b and a_dot_b, so we also // duplicate each underscore. module_name = StringReplace(module_name, "_", "__"); module_name = StringReplace(module_name, ".", "_dot_"); return module_name; } bool GetModuleAndMessagePath(const Descriptor* type, grpc::string* out, grpc::string generator_file_name, bool generate_in_pb2_grpc, grpc::string& import_prefix) { const Descriptor* path_elem_type = type; DescriptorVector message_path; do { message_path.push_back(path_elem_type); path_elem_type = path_elem_type->containing_type(); } while (path_elem_type); // implicit nullptr comparison; don't be explicit grpc::string file_name = type->file()->name(); static const int proto_suffix_length = strlen(".proto"); if (!(file_name.size() > static_cast(proto_suffix_length) && file_name.find_last_of(".proto") == file_name.size() - 1)) { return false; } grpc::string module; if (generator_file_name != file_name || generate_in_pb2_grpc) { module = ModuleAlias(file_name, import_prefix) + "."; } else { module = ""; } grpc::string message_type; for (DescriptorVector::reverse_iterator path_iter = message_path.rbegin(); path_iter != message_path.rend(); ++path_iter) { message_type += (*path_iter)->name() + "."; } // no pop_back prior to C++11 message_type.resize(message_type.size() - 1); *out = module + message_type; return true; } template StringVector get_all_comments(const DescriptorType* descriptor) { StringVector comments; grpc_generator::GetComment( descriptor, grpc_generator::COMMENTTYPE_LEADING_DETACHED, &comments); grpc_generator::GetComment(descriptor, grpc_generator::COMMENTTYPE_LEADING, &comments); grpc_generator::GetComment(descriptor, grpc_generator::COMMENTTYPE_TRAILING, &comments); return comments; } } // namespace } // namespace grpc_python_generator #endif // GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_HELPERS_H grpc-1.3.2/src/compiler/python_plugin.cc000066400000000000000000000037001310511640000202460ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ // Generates a Python gRPC service interface out of Protobuf IDL. #include "src/compiler/config.h" #include "src/compiler/protobuf_plugin.h" #include "src/compiler/python_generator.h" int main(int argc, char* argv[]) { grpc_python_generator::GeneratorConfiguration config; grpc_python_generator::PythonGrpcGenerator generator(config); return grpc::protobuf::compiler::PluginMain(argc, argv, &generator); } grpc-1.3.2/src/compiler/python_private_generator.h000066400000000000000000000100541310511640000223320ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_COMPILER_PYTHON_PRIVATE_GENERATOR_H #define GRPC_INTERNAL_COMPILER_PYTHON_PRIVATE_GENERATOR_H #include #include #include "src/compiler/python_generator.h" #include "src/compiler/schema_interface.h" namespace grpc_python_generator { namespace { // Tucks all generator state in an anonymous namespace away from // PythonGrpcGenerator and the header file, mostly to encourage future changes // to not require updates to the grpcio-tools C++ code part. Assumes that it is // only ever used from a single thread. struct PrivateGenerator { const GeneratorConfiguration& config; const grpc_generator::File* file; bool generate_in_pb2_grpc; PrivateGenerator(const GeneratorConfiguration& config, const grpc_generator::File* file); std::pair GetGrpcServices(); private: bool PrintPreamble(grpc_generator::Printer* out); bool PrintBetaPreamble(grpc_generator::Printer* out); bool PrintGAServices(grpc_generator::Printer* out); bool PrintBetaServices(grpc_generator::Printer* out); bool PrintAddServicerToServer( const grpc::string& package_qualified_service_name, const grpc_generator::Service* service, grpc_generator::Printer* out); bool PrintServicer(const grpc_generator::Service* service, grpc_generator::Printer* out); bool PrintStub(const grpc::string& package_qualified_service_name, const grpc_generator::Service* service, grpc_generator::Printer* out); bool PrintBetaServicer(const grpc_generator::Service* service, grpc_generator::Printer* out); bool PrintBetaServerFactory( const grpc::string& package_qualified_service_name, const grpc_generator::Service* service, grpc_generator::Printer* out); bool PrintBetaStub(const grpc_generator::Service* service, grpc_generator::Printer* out); bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name, const grpc_generator::Service* service, grpc_generator::Printer* out); // Get all comments (leading, leading_detached, trailing) and print them as a // docstring. Any leading space of a line will be removed, but the line // wrapping will not be changed. void PrintAllComments(std::vector comments, grpc_generator::Printer* out); }; } // namespace } // namespace grpc_python_generator #endif // GRPC_INTERNAL_COMPILER_PYTHON_PRIVATE_GENERATOR_H grpc-1.3.2/src/compiler/ruby_generator.cc000066400000000000000000000170611310511640000204030ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include "src/compiler/config.h" #include "src/compiler/ruby_generator.h" #include "src/compiler/ruby_generator_helpers-inl.h" #include "src/compiler/ruby_generator_map-inl.h" #include "src/compiler/ruby_generator_string-inl.h" using grpc::protobuf::FileDescriptor; using grpc::protobuf::ServiceDescriptor; using grpc::protobuf::MethodDescriptor; using grpc::protobuf::io::Printer; using grpc::protobuf::io::StringOutputStream; using std::map; using std::vector; namespace grpc_ruby_generator { namespace { // Prints out the method using the ruby gRPC DSL. void PrintMethod(const MethodDescriptor *method, const grpc::string &package, Printer *out) { grpc::string input_type = RubyTypeOf(method->input_type()->full_name(), package); if (method->client_streaming()) { input_type = "stream(" + input_type + ")"; } grpc::string output_type = RubyTypeOf(method->output_type()->full_name(), package); if (method->server_streaming()) { output_type = "stream(" + output_type + ")"; } std::map method_vars = ListToDict({ "mth.name", method->name(), "input.type", input_type, "output.type", output_type, }); out->Print(GetRubyComments(method, true).c_str()); out->Print(method_vars, "rpc :$mth.name$, $input.type$, $output.type$\n"); out->Print(GetRubyComments(method, false).c_str()); } // Prints out the service using the ruby gRPC DSL. void PrintService(const ServiceDescriptor *service, const grpc::string &package, Printer *out) { if (service->method_count() == 0) { return; } // Begin the service module std::map module_vars = ListToDict({ "module.name", CapitalizeFirst(service->name()), }); out->Print(module_vars, "module $module.name$\n"); out->Indent(); out->Print(GetRubyComments(service, true).c_str()); out->Print("class Service\n"); // Write the indented class body. out->Indent(); out->Print("\n"); out->Print("include GRPC::GenericService\n"); out->Print("\n"); out->Print("self.marshal_class_method = :encode\n"); out->Print("self.unmarshal_class_method = :decode\n"); std::map pkg_vars = ListToDict({"service_full_name", service->full_name()}); out->Print(pkg_vars, "self.service_name = '$service_full_name$'\n"); out->Print("\n"); for (int i = 0; i < service->method_count(); ++i) { PrintMethod(service->method(i), package, out); } out->Outdent(); out->Print("end\n"); out->Print("\n"); out->Print("Stub = Service.rpc_stub_class\n"); // End the service module out->Outdent(); out->Print("end\n"); out->Print(GetRubyComments(service, false).c_str()); } } // namespace // The following functions are copied directly from the source for the protoc // ruby generator // to ensure compatibility (with the exception of int and string type changes). // See // https://github.com/google/protobuf/blob/master/src/google/protobuf/compiler/ruby/ruby_generator.cc#L250 // TODO: keep up to date with protoc code generation, though this behavior isn't // expected to change bool IsLower(char ch) { return ch >= 'a' && ch <= 'z'; } char ToUpper(char ch) { return IsLower(ch) ? (ch - 'a' + 'A') : ch; } // Package names in protobuf are snake_case by convention, but Ruby module // names must be PascalCased. // // foo_bar_baz -> FooBarBaz grpc::string PackageToModule(const grpc::string &name) { bool next_upper = true; grpc::string result; result.reserve(name.size()); for (grpc::string::size_type i = 0; i < name.size(); i++) { if (name[i] == '_') { next_upper = true; } else { if (next_upper) { result.push_back(ToUpper(name[i])); } else { result.push_back(name[i]); } next_upper = false; } } return result; } // end copying of protoc generator for ruby code grpc::string GetServices(const FileDescriptor *file) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. StringOutputStream output_stream(&output); Printer out(&output_stream, '$'); // Don't write out any output if there no services, to avoid empty service // files being generated for proto files that don't declare any. if (file->service_count() == 0) { return output; } // Write out a file header. std::map header_comment_vars = ListToDict({ "file.name", file->name(), "file.package", file->package(), }); out.Print("# Generated by the protocol buffer compiler. DO NOT EDIT!\n"); out.Print(header_comment_vars, "# Source: $file.name$ for package '$file.package$'\n"); grpc::string leading_comments = GetRubyComments(file, true); if (!leading_comments.empty()) { out.Print("# Original file comments:\n"); out.Print(leading_comments.c_str()); } out.Print("\n"); out.Print("require 'grpc'\n"); // Write out require statemment to import the separately generated file // that defines the messages used by the service. This is generated by the // main ruby plugin. std::map dep_vars = ListToDict({ "dep.name", MessagesRequireName(file), }); out.Print(dep_vars, "require '$dep.name$'\n"); // Write out services within the modules out.Print("\n"); std::vector modules = Split(file->package(), '.'); for (size_t i = 0; i < modules.size(); ++i) { std::map module_vars = ListToDict({ "module.name", PackageToModule(modules[i]), }); out.Print(module_vars, "module $module.name$\n"); out.Indent(); } for (int i = 0; i < file->service_count(); ++i) { auto service = file->service(i); PrintService(service, file->package(), &out); } for (size_t i = 0; i < modules.size(); ++i) { out.Outdent(); out.Print("end\n"); } out.Print(GetRubyComments(file, false).c_str()); } return output; } } // namespace grpc_ruby_generator grpc-1.3.2/src/compiler/ruby_generator.h000066400000000000000000000035451310511640000202470ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_COMPILER_RUBY_GENERATOR_H #define GRPC_INTERNAL_COMPILER_RUBY_GENERATOR_H #include "src/compiler/config.h" namespace grpc_ruby_generator { grpc::string GetServices(const grpc::protobuf::FileDescriptor *file); } // namespace grpc_ruby_generator #endif // GRPC_INTERNAL_COMPILER_RUBY_GENERATOR_H grpc-1.3.2/src/compiler/ruby_generator_helpers-inl.h000066400000000000000000000057511310511640000225520ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_COMPILER_RUBY_GENERATOR_HELPERS_INL_H #define GRPC_INTERNAL_COMPILER_RUBY_GENERATOR_HELPERS_INL_H #include "src/compiler/config.h" #include "src/compiler/generator_helpers.h" #include "src/compiler/ruby_generator_string-inl.h" namespace grpc_ruby_generator { inline bool ServicesFilename(const grpc::protobuf::FileDescriptor *file, grpc::string *file_name_or_error) { // Get output file name. static const unsigned proto_suffix_length = 6; // length of ".proto" if (file->name().size() > proto_suffix_length && file->name().find_last_of(".proto") == file->name().size() - 1) { *file_name_or_error = file->name().substr(0, file->name().size() - proto_suffix_length) + "_services_pb.rb"; return true; } else { *file_name_or_error = "Invalid proto file name: must end with .proto"; return false; } } inline grpc::string MessagesRequireName( const grpc::protobuf::FileDescriptor *file) { return Replace(file->name(), ".proto", "_pb"); } // Get leading or trailing comments in a string. Comment lines start with "# ". // Leading detached comments are put in in front of leading comments. template inline grpc::string GetRubyComments(const DescriptorType *desc, bool leading) { return grpc_generator::GetPrefixedComments(desc, leading, "#"); } } // namespace grpc_ruby_generator #endif // GRPC_INTERNAL_COMPILER_RUBY_GENERATOR_HELPERS_INL_H grpc-1.3.2/src/compiler/ruby_generator_map-inl.h000066400000000000000000000052211310511640000216550ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_COMPILER_RUBY_GENERATOR_MAP_INL_H #define GRPC_INTERNAL_COMPILER_RUBY_GENERATOR_MAP_INL_H #include "src/compiler/config.h" #include #include #include #include // NOLINT #include using std::initializer_list; using std::map; using std::vector; namespace grpc_ruby_generator { // Converts an initializer list of the form { key0, value0, key1, value1, ... } // into a map of key* to value*. Is merely a readability helper for later code. inline std::map ListToDict( const initializer_list &values) { if (values.size() % 2 != 0) { std::cerr << "Not every 'key' has a value in `values`." << std::endl; } std::map value_map; auto value_iter = values.begin(); for (unsigned i = 0; i < values.size() / 2; ++i) { grpc::string key = *value_iter; ++value_iter; grpc::string value = *value_iter; value_map[key] = value; ++value_iter; } return value_map; } } // namespace grpc_ruby_generator #endif // GRPC_INTERNAL_COMPILER_RUBY_GENERATOR_MAP_INL_H grpc-1.3.2/src/compiler/ruby_generator_string-inl.h000066400000000000000000000110711310511640000224060ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_COMPILER_RUBY_GENERATOR_STRING_INL_H #define GRPC_INTERNAL_COMPILER_RUBY_GENERATOR_STRING_INL_H #include "src/compiler/config.h" #include #include #include using std::getline; using std::transform; namespace grpc_ruby_generator { // Split splits a string using char into elems. inline std::vector &Split(const grpc::string &s, char delim, std::vector *elems) { std::stringstream ss(s); grpc::string item; while (getline(ss, item, delim)) { elems->push_back(item); } return *elems; } // Split splits a string using char, returning the result in a vector. inline std::vector Split(const grpc::string &s, char delim) { std::vector elems; Split(s, delim, &elems); return elems; } // Replace replaces from with to in s. inline grpc::string Replace(grpc::string s, const grpc::string &from, const grpc::string &to) { size_t start_pos = s.find(from); if (start_pos == grpc::string::npos) { return s; } s.replace(start_pos, from.length(), to); return s; } // ReplaceAll replaces all instances of search with replace in s. inline grpc::string ReplaceAll(grpc::string s, const grpc::string &search, const grpc::string &replace) { size_t pos = 0; while ((pos = s.find(search, pos)) != grpc::string::npos) { s.replace(pos, search.length(), replace); pos += replace.length(); } return s; } // ReplacePrefix replaces from with to in s if search is a prefix of s. inline bool ReplacePrefix(grpc::string *s, const grpc::string &from, const grpc::string &to) { size_t start_pos = s->find(from); if (start_pos == grpc::string::npos || start_pos != 0) { return false; } s->replace(start_pos, from.length(), to); return true; } // CapitalizeFirst capitalizes the first char in a string. inline grpc::string CapitalizeFirst(grpc::string s) { if (s.empty()) { return s; } s[0] = ::toupper(s[0]); return s; } // RubyTypeOf updates a proto type to the required ruby equivalent. inline grpc::string RubyTypeOf(const grpc::string &a_type, const grpc::string &package) { grpc::string res(a_type); ReplacePrefix(&res, package, ""); // remove the leading package if present ReplacePrefix(&res, ".", ""); // remove the leading . (no package) if (res.find('.') == grpc::string::npos) { return res; } else { std::vector prefixes_and_type = Split(res, '.'); res.clear(); for (unsigned int i = 0; i < prefixes_and_type.size(); ++i) { if (i != 0) { res += "::"; // switch '.' to the ruby module delim } if (i < prefixes_and_type.size() - 1) { res += CapitalizeFirst(prefixes_and_type[i]); // capitalize pkgs } else { res += prefixes_and_type[i]; } } return res; } } } // namespace grpc_ruby_generator #endif // GRPC_INTERNAL_COMPILER_RUBY_GENERATOR_STRING_INL_H grpc-1.3.2/src/compiler/ruby_plugin.cc000066400000000000000000000054331310511640000177130ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ // Generates Ruby gRPC service interface out of Protobuf IDL. #include #include "src/compiler/config.h" #include "src/compiler/ruby_generator.h" #include "src/compiler/ruby_generator_helpers-inl.h" class RubyGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { public: RubyGrpcGenerator() {} ~RubyGrpcGenerator() {} bool Generate(const grpc::protobuf::FileDescriptor *file, const grpc::string ¶meter, grpc::protobuf::compiler::GeneratorContext *context, grpc::string *error) const { grpc::string code = grpc_ruby_generator::GetServices(file); if (code.size() == 0) { return true; // don't generate a file if there are no services } // Get output file name. grpc::string file_name; if (!grpc_ruby_generator::ServicesFilename(file, &file_name)) { return false; } std::unique_ptr output( context->Open(file_name)); grpc::protobuf::io::CodedOutputStream coded_out(output.get()); coded_out.WriteRaw(code.data(), code.size()); return true; } }; int main(int argc, char *argv[]) { RubyGrpcGenerator generator; return grpc::protobuf::compiler::PluginMain(argc, argv, &generator); } grpc-1.3.2/src/compiler/schema_interface.h000066400000000000000000000106331310511640000204740ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H #define GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H #include "src/compiler/config.h" #include #include #ifndef GRPC_CUSTOM_STRING #include #define GRPC_CUSTOM_STRING std::string #endif namespace grpc { typedef GRPC_CUSTOM_STRING string; } // namespace grpc namespace grpc_generator { // A common interface for objects having comments in the source. // Return formatted comments to be inserted in generated code. struct CommentHolder { virtual ~CommentHolder() {} virtual grpc::string GetLeadingComments(const grpc::string prefix) const = 0; virtual grpc::string GetTrailingComments(const grpc::string prefix) const = 0; virtual std::vector GetAllComments() const = 0; }; // An abstract interface representing a method. struct Method : public CommentHolder { virtual ~Method() {} virtual grpc::string name() const = 0; virtual grpc::string input_type_name() const = 0; virtual grpc::string output_type_name() const = 0; virtual bool get_module_and_message_path_input( grpc::string *str, grpc::string generator_file_name, bool generate_in_pb2_grpc, grpc::string import_prefix) const = 0; virtual bool get_module_and_message_path_output( grpc::string *str, grpc::string generator_file_name, bool generate_in_pb2_grpc, grpc::string import_prefix) const = 0; virtual grpc::string get_input_type_name() const = 0; virtual grpc::string get_output_type_name() const = 0; virtual bool NoStreaming() const = 0; virtual bool ClientStreaming() const = 0; virtual bool ServerStreaming() const = 0; virtual bool BidiStreaming() const = 0; }; // An abstract interface representing a service. struct Service : public CommentHolder { virtual ~Service() {} virtual grpc::string name() const = 0; virtual int method_count() const = 0; virtual std::unique_ptr method(int i) const = 0; }; struct Printer { virtual ~Printer() {} virtual void Print(const std::map &vars, const char *template_string) = 0; virtual void Print(const char *string) = 0; virtual void Indent() = 0; virtual void Outdent() = 0; }; // An interface that allows the source generated to be output using various // libraries/idls/serializers. struct File : public CommentHolder { virtual ~File() {} virtual grpc::string filename() const = 0; virtual grpc::string filename_without_ext() const = 0; virtual grpc::string package() const = 0; virtual std::vector package_parts() const = 0; virtual grpc::string additional_headers() const = 0; virtual int service_count() const = 0; virtual std::unique_ptr service(int i) const = 0; virtual std::unique_ptr CreatePrinter(grpc::string *str) const = 0; }; } // namespace grpc_generator #endif // GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H grpc-1.3.2/src/core/000077500000000000000000000000001310511640000141565ustar00rootroot00000000000000grpc-1.3.2/src/core/README.md000066400000000000000000000004371310511640000154410ustar00rootroot00000000000000# Overview This directory contains source code for C library (a.k.a the *gRPC C core*) that provides all gRPC's core functionality through a low level API. Libraries in other languages in this repository (C++, Ruby, Python, PHP, NodeJS, Objective-C) are layered on top of this library. grpc-1.3.2/src/core/ext/000077500000000000000000000000001310511640000147565ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/README.md000066400000000000000000000004041310511640000162330ustar00rootroot00000000000000Optional plugins for gRPC Core: Modules in this directory extend gRPC Core in useful ways. All optional code belongs here. NOTE: The movement of code between lib and ext is an ongoing effort, so this directory currently contains too much of the core library. grpc-1.3.2/src/core/ext/census/000077500000000000000000000000001310511640000162565ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/census/README.md000066400000000000000000000057461310511640000175510ustar00rootroot00000000000000 # Census - a resource measurement and tracing system This directory contains code for Census, which will ultimately provide the following features for any gRPC-using system: * A [dapper](http://research.google.com/pubs/pub36356.html)-like tracing system, enabling tracing across a distributed infrastructure. * RPC statistics and measurements for key metrics, such as latency, bytes transferred, number of errors etc. * Resource measurement framework which can be used for measuring custom metrics. Through the use of [tags](#Tags), these can be broken down across the entire distributed stack. * Easy integration of the above with [Google Cloud Trace](https://cloud.google.com/tools/cloud-trace) and [Google Cloud Monitoring](https://cloud.google.com/monitoring/). ## Concepts ### Context ### Operations ### Tags ### Metrics ## API ### Internal/RPC API ### External/Client API ### RPC API ## Files in this directory Note that files and functions in this directory can be split into two categories: * Files that define core census library functions. Functions etc. in these files are named census\_\*, and constitute the core census library functionality. At some time in the future, these will become a standalone library. * Files that define functions etc. that provide a convenient interface between grpc and the core census functionality. These files are all named grpc\_\*.{c,h}, and define function names beginning with grpc\_census\_\*. grpc-1.3.2/src/core/ext/census/aggregation.h000066400000000000000000000060071310511640000207210ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifndef GRPC_CORE_EXT_CENSUS_AGGREGATION_H #define GRPC_CORE_EXT_CENSUS_AGGREGATION_H /** Structure used to describe an aggregation type. */ struct census_aggregation_ops { /* Create a new aggregation. The pointer returned can be used in future calls to clone(), free(), record(), data() and reset(). */ void *(*create)(const void *create_arg); /* Make a copy of an aggregation created by create() */ void *(*clone)(const void *aggregation); /* Destroy an aggregation created by create() */ void (*free)(void *aggregation); /* Record a new value against aggregation. */ void (*record)(void *aggregation, double value); /* Return current aggregation data. The caller must cast this object into the correct type for the aggregation result. The object returned can be freed by using free_data(). */ void *(*data)(const void *aggregation); /* free data returned by data() */ void (*free_data)(void *data); /* Reset an aggregation to default (zero) values. */ void (*reset)(void *aggregation); /* Merge 'from' aggregation into 'to'. Both aggregations must be compatible */ void (*merge)(void *to, const void *from); /* Fill buffer with printable string version of aggregation contents. For debugging only. Returns the number of bytes added to buffer (a value == n implies the buffer was of insufficient size). */ size_t (*print)(const void *aggregation, char *buffer, size_t n); }; #endif /* GRPC_CORE_EXT_CENSUS_AGGREGATION_H */ grpc-1.3.2/src/core/ext/census/base_resources.c000066400000000000000000000063371310511640000214370ustar00rootroot00000000000000/* * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/census/base_resources.h" #include #include #include #include #include "src/core/ext/census/resource.h" // Add base RPC resource definitions for use by RPC runtime. // // TODO(aveitch): All of these are currently hardwired definitions encoded in // the code in this file. These should be converted to use an external // configuration mechanism, in which these resources are defined in a text // file, which is compiled to .pb format and read by still-to-be-written // configuration functions. // Define all base resources. This should be called by census initialization. void define_base_resources() { google_census_Resource_BasicUnit numerator = google_census_Resource_BasicUnit_SECS; resource r = {"client_rpc_latency", // name "Client RPC latency in seconds", // description 0, // prefix 1, // n_numerators &numerator, // numerators 0, // n_denominators NULL}; // denominators define_resource(&r); r = (resource){"server_rpc_latency", // name "Server RPC latency in seconds", // description 0, // prefix 1, // n_numerators &numerator, // numerators 0, // n_denominators NULL}; // denominators define_resource(&r); } grpc-1.3.2/src/core/ext/census/base_resources.h000066400000000000000000000034371310511640000214420ustar00rootroot00000000000000/* * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_CENSUS_BASE_RESOURCES_H #define GRPC_CORE_EXT_CENSUS_BASE_RESOURCES_H /* Define all base resources. This should be called by census initialization. */ void define_base_resources(); #endif /* GRPC_CORE_EXT_CENSUS_BASE_RESOURCES_H */ grpc-1.3.2/src/core/ext/census/census_init.c000066400000000000000000000036051310511640000207510ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/census/census_interface.h" #include #include "src/core/ext/census/census_rpc_stats.h" #include "src/core/ext/census/census_tracing.h" void census_init(void) { census_tracing_init(); census_stats_store_init(); } void census_shutdown(void) { census_stats_store_shutdown(); census_tracing_shutdown(); } grpc-1.3.2/src/core/ext/census/census_interface.h000066400000000000000000000061551310511640000217560ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_CENSUS_CENSUS_INTERFACE_H #define GRPC_CORE_EXT_CENSUS_CENSUS_INTERFACE_H #include /* Maximum length of an individual census trace annotation. */ #define CENSUS_MAX_ANNOTATION_LENGTH 200 /* Structure of a census op id. Define as structure because 64bit integer is not available on every platform for C89. */ typedef struct census_op_id { uint32_t upper; uint32_t lower; } census_op_id; typedef struct census_rpc_stats census_rpc_stats; /* Initializes Census library. No-op if Census is already initialized. */ void census_init(void); /* Shutdown Census Library. */ void census_shutdown(void); /* Annotates grpc method name on a census_op_id. The method name has the format of /. Returns 0 iff op_id and method_name are all valid. op_id is valid after its creation and before calling census_tracing_end_op(). TODO(hongyu): Figure out valid characters set for service name and command name and document requirements here.*/ int census_add_method_tag(census_op_id op_id, const char *method_name); /* Annotates tracing information to a specific op_id. Up to CENSUS_MAX_ANNOTATION_LENGTH bytes are recorded. */ void census_tracing_print(census_op_id op_id, const char *annotation); /* Starts tracing for an RPC. Returns a locally unique census_op_id */ census_op_id census_tracing_start_op(void); /* Ends tracing. Calling this function will invalidate the input op_id. */ void census_tracing_end_op(census_op_id op_id); #endif /* GRPC_CORE_EXT_CENSUS_CENSUS_INTERFACE_H */ grpc-1.3.2/src/core/ext/census/census_log.c000066400000000000000000000530601310511640000205670ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* Available log space is divided up in blocks of CENSUS_LOG_2_MAX_RECORD_SIZE bytes. A block can be in one of the following three data structures: - Free blocks (free_block_list) - Blocks with unread data (dirty_block_list) - Blocks currently attached to cores (core_local_blocks[]) census_log_start_write() moves a block from core_local_blocks[] to the end of dirty_block_list when block: - is out-of-space OR - has an incomplete record (an incomplete record occurs when a thread calls census_log_start_write() and is context-switched before calling census_log_end_write() So, blocks in dirty_block_list are ordered, from oldest to newest, by time when block is detached from the core. census_log_read_next() first iterates over dirty_block_list and then core_local_blocks[]. It moves completely read blocks from dirty_block_list to free_block_list. Blocks in core_local_blocks[] are not freed, even when completely read. If log is configured to discard old records and free_block_list is empty, census_log_start_write() iterates over dirty_block_list to allocate a new block. It moves the oldest available block (no pending read/write) to core_local_blocks[]. core_local_block_struct is used to implement a map from core id to the block associated with that core. This mapping is advisory. It is possible that the block returned by this mapping is no longer associated with that core. This mapping is updated, lazily, by census_log_start_write(). Locking in block struct: Exclusive g_log.lock must be held before calling any functions operatong on block structs except census_log_start_write() and census_log_end_write(). Writes to a block are serialized via writer_lock. census_log_start_write() acquires this lock and census_log_end_write() releases it. On failure to acquire the lock, writer allocates a new block for the current core and updates core_local_block accordingly. Simultaneous read and write access is allowed. Reader can safely read up to committed bytes (bytes_committed). reader_lock protects the block, currently being read, from getting recycled. start_read() acquires reader_lock and end_read() releases the lock. Read/write access to a block is disabled via try_disable_access(). It returns with both writer_lock and reader_lock held. These locks are subsequently released by enable_access() to enable access to the block. A note on naming: Most function/struct names are prepended by cl_ (shorthand for census_log). Further, functions that manipulate structures include the name of the structure, which will be passed as the first argument. E.g. cl_block_initialize() will initialize a cl_block. */ #include "src/core/ext/census/census_log.h" #include #include #include #include #include #include #include #include /* End of platform specific code */ typedef struct census_log_block_list_struct { struct census_log_block_list_struct *next; struct census_log_block_list_struct *prev; struct census_log_block *block; } cl_block_list_struct; typedef struct census_log_block { /* Pointer to underlying buffer */ char *buffer; gpr_atm writer_lock; gpr_atm reader_lock; /* Keeps completely written bytes. Declared atomic because accessed simultaneously by reader and writer. */ gpr_atm bytes_committed; /* Bytes already read */ int32_t bytes_read; /* Links for list */ cl_block_list_struct link; /* We want this structure to be cacheline aligned. We assume the following sizes for the various parts on 32/64bit systems: type 32b size 64b size char* 4 8 3x gpr_atm 12 24 int32_t 4 8 (assumes padding) cl_block_list_struct 12 24 TOTAL 32 64 Depending on the size of our cacheline and the architecture, we selectively add char buffering to this structure. The size is checked via assert in census_log_initialize(). */ #if defined(GPR_ARCH_64) #define CL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 64) #else #if defined(GPR_ARCH_32) #define CL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 32) #else #error "Unknown architecture" #endif #endif #if CL_BLOCK_PAD_SIZE > 0 char padding[CL_BLOCK_PAD_SIZE]; #endif } cl_block; /* A list of cl_blocks, doubly-linked through cl_block::link. */ typedef struct census_log_block_list { int32_t count; /* Number of items in list. */ cl_block_list_struct ht; /* head/tail of linked list. */ } cl_block_list; /* Cacheline aligned block pointers to avoid false sharing. Block pointer must be initialized via set_block(), before calling other functions */ typedef struct census_log_core_local_block { gpr_atm block; /* Ensure cachline alignment: we assume sizeof(gpr_atm) == 4 or 8 */ #if defined(GPR_ARCH_64) #define CL_CORE_LOCAL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 8) #else #if defined(GPR_ARCH_32) #define CL_CORE_LOCAL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 4) #else #error "Unknown architecture" #endif #endif #if CL_CORE_LOCAL_BLOCK_PAD_SIZE > 0 char padding[CL_CORE_LOCAL_BLOCK_PAD_SIZE]; #endif } cl_core_local_block; struct census_log { int discard_old_records; /* Number of cores (aka hardware-contexts) */ unsigned num_cores; /* number of CENSUS_LOG_2_MAX_RECORD_SIZE blocks in log */ int32_t num_blocks; cl_block *blocks; /* Block metadata. */ cl_core_local_block *core_local_blocks; /* Keeps core to block mappings. */ gpr_mu lock; int initialized; /* has log been initialized? */ /* Keeps the state of the reader iterator. A value of 0 indicates that iterator has reached the end. census_log_init_reader() resets the value to num_core to restart iteration. */ uint32_t read_iterator_state; /* Points to the block being read. If non-NULL, the block is locked for reading (block_being_read_->reader_lock is held). */ cl_block *block_being_read; /* A non-zero value indicates that log is full. */ gpr_atm is_full; char *buffer; cl_block_list free_block_list; cl_block_list dirty_block_list; gpr_atm out_of_space_count; }; /* Single internal log */ static struct census_log g_log; /* Functions that operate on an atomic memory location used as a lock */ /* Returns non-zero if lock is acquired */ static int cl_try_lock(gpr_atm *lock) { return gpr_atm_acq_cas(lock, 0, 1); } static void cl_unlock(gpr_atm *lock) { gpr_atm_rel_store(lock, 0); } /* Functions that operate on cl_core_local_block's */ static void cl_core_local_block_set_block(cl_core_local_block *clb, cl_block *block) { gpr_atm_rel_store(&clb->block, (gpr_atm)block); } static cl_block *cl_core_local_block_get_block(cl_core_local_block *clb) { return (cl_block *)gpr_atm_acq_load(&clb->block); } /* Functions that operate on cl_block_list_struct's */ static void cl_block_list_struct_initialize(cl_block_list_struct *bls, cl_block *block) { bls->next = bls->prev = bls; bls->block = block; } /* Functions that operate on cl_block_list's */ static void cl_block_list_initialize(cl_block_list *list) { list->count = 0; cl_block_list_struct_initialize(&list->ht, NULL); } /* Returns head of *this, or NULL if empty. */ static cl_block *cl_block_list_head(cl_block_list *list) { return list->ht.next->block; } /* Insert element *e after *pos. */ static void cl_block_list_insert(cl_block_list *list, cl_block_list_struct *pos, cl_block_list_struct *e) { list->count++; e->next = pos->next; e->prev = pos; e->next->prev = e; e->prev->next = e; } /* Insert block at the head of the list */ static void cl_block_list_insert_at_head(cl_block_list *list, cl_block *block) { cl_block_list_insert(list, &list->ht, &block->link); } /* Insert block at the tail of the list */ static void cl_block_list_insert_at_tail(cl_block_list *list, cl_block *block) { cl_block_list_insert(list, list->ht.prev, &block->link); } /* Removes block *b. Requires *b be in the list. */ static void cl_block_list_remove(cl_block_list *list, cl_block *b) { list->count--; b->link.next->prev = b->link.prev; b->link.prev->next = b->link.next; } /* Functions that operate on cl_block's */ static void cl_block_initialize(cl_block *block, char *buffer) { block->buffer = buffer; gpr_atm_rel_store(&block->writer_lock, 0); gpr_atm_rel_store(&block->reader_lock, 0); gpr_atm_rel_store(&block->bytes_committed, 0); block->bytes_read = 0; cl_block_list_struct_initialize(&block->link, block); } /* Guards against exposing partially written buffer to the reader. */ static void cl_block_set_bytes_committed(cl_block *block, int32_t bytes_committed) { gpr_atm_rel_store(&block->bytes_committed, bytes_committed); } static int32_t cl_block_get_bytes_committed(cl_block *block) { return gpr_atm_acq_load(&block->bytes_committed); } /* Tries to disable future read/write access to this block. Succeeds if: - no in-progress write AND - no in-progress read AND - 'discard_data' set to true OR no unread data On success, clears the block state and returns with writer_lock_ and reader_lock_ held. These locks are released by a subsequent cl_block_access_enable() call. */ static int cl_block_try_disable_access(cl_block *block, int discard_data) { if (!cl_try_lock(&block->writer_lock)) { return 0; } if (!cl_try_lock(&block->reader_lock)) { cl_unlock(&block->writer_lock); return 0; } if (!discard_data && (block->bytes_read != cl_block_get_bytes_committed(block))) { cl_unlock(&block->reader_lock); cl_unlock(&block->writer_lock); return 0; } cl_block_set_bytes_committed(block, 0); block->bytes_read = 0; return 1; } static void cl_block_enable_access(cl_block *block) { cl_unlock(&block->reader_lock); cl_unlock(&block->writer_lock); } /* Returns with writer_lock held. */ static void *cl_block_start_write(cl_block *block, size_t size) { int32_t bytes_committed; if (!cl_try_lock(&block->writer_lock)) { return NULL; } bytes_committed = cl_block_get_bytes_committed(block); if (bytes_committed + size > CENSUS_LOG_MAX_RECORD_SIZE) { cl_unlock(&block->writer_lock); return NULL; } return block->buffer + bytes_committed; } /* Releases writer_lock and increments committed bytes by 'bytes_written'. 'bytes_written' must be <= 'size' specified in the corresponding StartWrite() call. This function is thread-safe. */ static void cl_block_end_write(cl_block *block, size_t bytes_written) { cl_block_set_bytes_committed( block, cl_block_get_bytes_committed(block) + bytes_written); cl_unlock(&block->writer_lock); } /* Returns a pointer to the first unread byte in buffer. The number of bytes available are returned in 'bytes_available'. Acquires reader lock that is released by a subsequent cl_block_end_read() call. Returns NULL if: - read in progress - no data available */ static void *cl_block_start_read(cl_block *block, size_t *bytes_available) { void *record; if (!cl_try_lock(&block->reader_lock)) { return NULL; } /* bytes_committed may change from under us. Use bytes_available to update bytes_read below. */ *bytes_available = cl_block_get_bytes_committed(block) - block->bytes_read; if (*bytes_available == 0) { cl_unlock(&block->reader_lock); return NULL; } record = block->buffer + block->bytes_read; block->bytes_read += *bytes_available; return record; } static void cl_block_end_read(cl_block *block) { cl_unlock(&block->reader_lock); } /* Internal functions operating on g_log */ /* Allocates a new free block (or recycles an available dirty block if log is configured to discard old records). Returns NULL if out-of-space. */ static cl_block *cl_allocate_block(void) { cl_block *block = cl_block_list_head(&g_log.free_block_list); if (block != NULL) { cl_block_list_remove(&g_log.free_block_list, block); return block; } if (!g_log.discard_old_records) { /* No free block and log is configured to keep old records. */ return NULL; } /* Recycle dirty block. Start from the oldest. */ for (block = cl_block_list_head(&g_log.dirty_block_list); block != NULL; block = block->link.next->block) { if (cl_block_try_disable_access(block, 1 /* discard data */)) { cl_block_list_remove(&g_log.dirty_block_list, block); return block; } } return NULL; } /* Allocates a new block and updates core id => block mapping. 'old_block' points to the block that the caller thinks is attached to 'core_id'. 'old_block' may be NULL. Returns non-zero if: - allocated a new block OR - 'core_id' => 'old_block' mapping changed (another thread allocated a block before lock was acquired). */ static int cl_allocate_core_local_block(int32_t core_id, cl_block *old_block) { /* Now that we have the lock, check if core-local mapping has changed. */ cl_core_local_block *core_local_block = &g_log.core_local_blocks[core_id]; cl_block *block = cl_core_local_block_get_block(core_local_block); if ((block != NULL) && (block != old_block)) { return 1; } if (block != NULL) { cl_core_local_block_set_block(core_local_block, NULL); cl_block_list_insert_at_tail(&g_log.dirty_block_list, block); } block = cl_allocate_block(); if (block == NULL) { gpr_atm_rel_store(&g_log.is_full, 1); return 0; } cl_core_local_block_set_block(core_local_block, block); cl_block_enable_access(block); return 1; } static cl_block *cl_get_block(void *record) { uintptr_t p = (uintptr_t)((char *)record - g_log.buffer); uintptr_t index = p >> CENSUS_LOG_2_MAX_RECORD_SIZE; return &g_log.blocks[index]; } /* Gets the next block to read and tries to free 'prev' block (if not NULL). Returns NULL if reached the end. */ static cl_block *cl_next_block_to_read(cl_block *prev) { cl_block *block = NULL; if (g_log.read_iterator_state == g_log.num_cores) { /* We are traversing dirty list; find the next dirty block. */ if (prev != NULL) { /* Try to free the previous block if there is no unread data. This block may have unread data if previously incomplete record completed between read_next() calls. */ block = prev->link.next->block; if (cl_block_try_disable_access(prev, 0 /* do not discard data */)) { cl_block_list_remove(&g_log.dirty_block_list, prev); cl_block_list_insert_at_head(&g_log.free_block_list, prev); gpr_atm_rel_store(&g_log.is_full, 0); } } else { block = cl_block_list_head(&g_log.dirty_block_list); } if (block != NULL) { return block; } /* We are done with the dirty list; moving on to core-local blocks. */ } while (g_log.read_iterator_state > 0) { g_log.read_iterator_state--; block = cl_core_local_block_get_block( &g_log.core_local_blocks[g_log.read_iterator_state]); if (block != NULL) { return block; } } return NULL; } /* External functions: primary stats_log interface */ void census_log_initialize(size_t size_in_mb, int discard_old_records) { int32_t ix; /* Check cacheline alignment. */ GPR_ASSERT(sizeof(cl_block) % GPR_CACHELINE_SIZE == 0); GPR_ASSERT(sizeof(cl_core_local_block) % GPR_CACHELINE_SIZE == 0); GPR_ASSERT(!g_log.initialized); g_log.discard_old_records = discard_old_records; g_log.num_cores = gpr_cpu_num_cores(); /* Ensure at least as many blocks as there are cores. */ g_log.num_blocks = GPR_MAX( g_log.num_cores, (size_in_mb << 20) >> CENSUS_LOG_2_MAX_RECORD_SIZE); gpr_mu_init(&g_log.lock); g_log.read_iterator_state = 0; g_log.block_being_read = NULL; gpr_atm_rel_store(&g_log.is_full, 0); g_log.core_local_blocks = (cl_core_local_block *)gpr_malloc_aligned( g_log.num_cores * sizeof(cl_core_local_block), GPR_CACHELINE_SIZE_LOG); memset(g_log.core_local_blocks, 0, g_log.num_cores * sizeof(cl_core_local_block)); g_log.blocks = (cl_block *)gpr_malloc_aligned( g_log.num_blocks * sizeof(cl_block), GPR_CACHELINE_SIZE_LOG); memset(g_log.blocks, 0, g_log.num_blocks * sizeof(cl_block)); g_log.buffer = gpr_malloc(g_log.num_blocks * CENSUS_LOG_MAX_RECORD_SIZE); memset(g_log.buffer, 0, g_log.num_blocks * CENSUS_LOG_MAX_RECORD_SIZE); cl_block_list_initialize(&g_log.free_block_list); cl_block_list_initialize(&g_log.dirty_block_list); for (ix = 0; ix < g_log.num_blocks; ++ix) { cl_block *block = g_log.blocks + ix; cl_block_initialize(block, g_log.buffer + (CENSUS_LOG_MAX_RECORD_SIZE * ix)); cl_block_try_disable_access(block, 1 /* discard data */); cl_block_list_insert_at_tail(&g_log.free_block_list, block); } gpr_atm_rel_store(&g_log.out_of_space_count, 0); g_log.initialized = 1; } void census_log_shutdown(void) { GPR_ASSERT(g_log.initialized); gpr_mu_destroy(&g_log.lock); gpr_free_aligned(g_log.core_local_blocks); g_log.core_local_blocks = NULL; gpr_free_aligned(g_log.blocks); g_log.blocks = NULL; gpr_free(g_log.buffer); g_log.buffer = NULL; g_log.initialized = 0; } void *census_log_start_write(size_t size) { /* Used to bound number of times block allocation is attempted. */ int32_t attempts_remaining = g_log.num_blocks; /* TODO(aveitch): move this inside the do loop when current_cpu is fixed */ int32_t core_id = gpr_cpu_current_cpu(); GPR_ASSERT(g_log.initialized); if (size > CENSUS_LOG_MAX_RECORD_SIZE) { return NULL; } do { int allocated; void *record = NULL; cl_block *block = cl_core_local_block_get_block(&g_log.core_local_blocks[core_id]); if (block && (record = cl_block_start_write(block, size))) { return record; } /* Need to allocate a new block. We are here if: - No block associated with the core OR - Write in-progress on the block OR - block is out of space */ if (gpr_atm_acq_load(&g_log.is_full)) { gpr_atm_no_barrier_fetch_add(&g_log.out_of_space_count, 1); return NULL; } gpr_mu_lock(&g_log.lock); allocated = cl_allocate_core_local_block(core_id, block); gpr_mu_unlock(&g_log.lock); if (!allocated) { gpr_atm_no_barrier_fetch_add(&g_log.out_of_space_count, 1); return NULL; } } while (attempts_remaining--); /* Give up. */ gpr_atm_no_barrier_fetch_add(&g_log.out_of_space_count, 1); return NULL; } void census_log_end_write(void *record, size_t bytes_written) { GPR_ASSERT(g_log.initialized); cl_block_end_write(cl_get_block(record), bytes_written); } void census_log_init_reader(void) { GPR_ASSERT(g_log.initialized); gpr_mu_lock(&g_log.lock); /* If a block is locked for reading unlock it. */ if (g_log.block_being_read != NULL) { cl_block_end_read(g_log.block_being_read); g_log.block_being_read = NULL; } g_log.read_iterator_state = g_log.num_cores; gpr_mu_unlock(&g_log.lock); } const void *census_log_read_next(size_t *bytes_available) { GPR_ASSERT(g_log.initialized); gpr_mu_lock(&g_log.lock); if (g_log.block_being_read != NULL) { cl_block_end_read(g_log.block_being_read); } do { g_log.block_being_read = cl_next_block_to_read(g_log.block_being_read); if (g_log.block_being_read != NULL) { void *record = cl_block_start_read(g_log.block_being_read, bytes_available); if (record != NULL) { gpr_mu_unlock(&g_log.lock); return record; } } } while (g_log.block_being_read != NULL); gpr_mu_unlock(&g_log.lock); return NULL; } size_t census_log_remaining_space(void) { size_t space; GPR_ASSERT(g_log.initialized); gpr_mu_lock(&g_log.lock); if (g_log.discard_old_records) { /* Remaining space is not meaningful; just return the entire log space. */ space = g_log.num_blocks << CENSUS_LOG_2_MAX_RECORD_SIZE; } else { space = g_log.free_block_list.count * CENSUS_LOG_MAX_RECORD_SIZE; } gpr_mu_unlock(&g_log.lock); return space; } int census_log_out_of_space_count(void) { GPR_ASSERT(g_log.initialized); return gpr_atm_acq_load(&g_log.out_of_space_count); } grpc-1.3.2/src/core/ext/census/census_log.h000066400000000000000000000076461310511640000206050ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_CENSUS_CENSUS_LOG_H #define GRPC_CORE_EXT_CENSUS_CENSUS_LOG_H #include /* Maximum record size, in bytes. */ #define CENSUS_LOG_2_MAX_RECORD_SIZE 14 /* 2^14 = 16KB */ #define CENSUS_LOG_MAX_RECORD_SIZE (1 << CENSUS_LOG_2_MAX_RECORD_SIZE) /* Initialize the statistics logging subsystem with the given log size. A log size of 0 will result in the smallest possible log for the platform (approximately CENSUS_LOG_MAX_RECORD_SIZE * gpr_cpu_num_cores()). If discard_old_records is non-zero, then new records will displace older ones when the log is full. This function must be called before any other census_log functions. */ void census_log_initialize(size_t size_in_mb, int discard_old_records); /* Shutdown the logging subsystem. Caller must ensure that: - no in progress or future call to any census_log functions - no incomplete records */ void census_log_shutdown(void); /* Allocates and returns a 'size' bytes record and marks it in use. A subsequent census_log_end_write() marks the record complete. The 'bytes_written' census_log_end_write() argument must be <= 'size'. Returns NULL if out-of-space AND: - log is configured to keep old records OR - all blocks are pinned by incomplete records. */ void *census_log_start_write(size_t size); void census_log_end_write(void *record, size_t bytes_written); /* census_log_read_next() iterates over blocks with data and for each block returns a pointer to the first unread byte. The number of bytes that can be read are returned in 'bytes_available'. Reader is expected to read all available data. Reading the data consumes it i.e. it cannot be read again. census_log_read_next() returns NULL if the end is reached i.e last block is read. census_log_init_reader() starts the iteration or aborts the current iteration. */ void census_log_init_reader(void); const void *census_log_read_next(size_t *bytes_available); /* Returns estimated remaining space across all blocks, in bytes. If log is configured to discard old records, returns total log space. Otherwise, returns space available in empty blocks (partially filled blocks are treated as full). */ size_t census_log_remaining_space(void); /* Returns the number of times grpc_stats_log_start_write() failed due to out-of-space. */ int census_log_out_of_space_count(void); #endif /* GRPC_CORE_EXT_CENSUS_CENSUS_LOG_H */ grpc-1.3.2/src/core/ext/census/census_rpc_stats.c000066400000000000000000000211531310511640000220060ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include "src/core/ext/census/census_interface.h" #include "src/core/ext/census/census_rpc_stats.h" #include "src/core/ext/census/census_tracing.h" #include "src/core/ext/census/hash_table.h" #include "src/core/ext/census/window_stats.h" #include "src/core/lib/support/murmur_hash.h" #include "src/core/lib/support/string.h" #define NUM_INTERVALS 3 #define MINUTE_INTERVAL 0 #define HOUR_INTERVAL 1 #define TOTAL_INTERVAL 2 /* for easier typing */ typedef census_per_method_rpc_stats per_method_stats; /* Ensure mu is only initialized once. */ static gpr_once g_stats_store_mu_init = GPR_ONCE_INIT; /* Guards two stats stores. */ static gpr_mu g_mu; static census_ht *g_client_stats_store = NULL; static census_ht *g_server_stats_store = NULL; static void init_mutex(void) { gpr_mu_init(&g_mu); } static void init_mutex_once(void) { gpr_once_init(&g_stats_store_mu_init, init_mutex); } static int cmp_str_keys(const void *k1, const void *k2) { return strcmp((const char *)k1, (const char *)k2); } /* TODO(hongyu): replace it with cityhash64 */ static uint64_t simple_hash(const void *k) { size_t len = strlen(k); uint64_t higher = gpr_murmur_hash3((const char *)k, len / 2, 0); return higher << 32 | gpr_murmur_hash3((const char *)k + len / 2, len - len / 2, 0); } static void delete_stats(void *stats) { census_window_stats_destroy((struct census_window_stats *)stats); } static void delete_key(void *key) { gpr_free(key); } static const census_ht_option ht_opt = { CENSUS_HT_POINTER /* key type */, 1999 /* n_of_buckets */, simple_hash /* hash function */, cmp_str_keys /* key comparator */, delete_stats /* data deleter */, delete_key /* key deleter */ }; static void init_rpc_stats(void *stats) { memset(stats, 0, sizeof(census_rpc_stats)); } static void stat_add_proportion(double p, void *base, const void *addme) { census_rpc_stats *b = (census_rpc_stats *)base; census_rpc_stats *a = (census_rpc_stats *)addme; b->cnt += p * a->cnt; b->rpc_error_cnt += p * a->rpc_error_cnt; b->app_error_cnt += p * a->app_error_cnt; b->elapsed_time_ms += p * a->elapsed_time_ms; b->api_request_bytes += p * a->api_request_bytes; b->wire_request_bytes += p * a->wire_request_bytes; b->api_response_bytes += p * a->api_response_bytes; b->wire_response_bytes += p * a->wire_response_bytes; } static void stat_add(void *base, const void *addme) { stat_add_proportion(1.0, base, addme); } static gpr_timespec min_hour_total_intervals[3] = { {60, 0}, {3600, 0}, {36000000, 0}}; static const census_window_stats_stat_info window_stats_settings = { sizeof(census_rpc_stats), init_rpc_stats, stat_add, stat_add_proportion}; census_rpc_stats *census_rpc_stats_create_empty(void) { census_rpc_stats *ret = (census_rpc_stats *)gpr_malloc(sizeof(census_rpc_stats)); memset(ret, 0, sizeof(census_rpc_stats)); return ret; } void census_aggregated_rpc_stats_set_empty(census_aggregated_rpc_stats *data) { int i = 0; for (i = 0; i < data->num_entries; i++) { if (data->stats[i].method != NULL) { gpr_free((void *)data->stats[i].method); } } if (data->stats != NULL) { gpr_free(data->stats); } data->num_entries = 0; data->stats = NULL; } static void record_stats(census_ht *store, census_op_id op_id, const census_rpc_stats *stats) { gpr_mu_lock(&g_mu); if (store != NULL) { census_trace_obj *trace = NULL; census_internal_lock_trace_store(); trace = census_get_trace_obj_locked(op_id); if (trace != NULL) { const char *method_name = census_get_trace_method_name(trace); struct census_window_stats *window_stats = NULL; census_ht_key key; key.ptr = (void *)method_name; window_stats = census_ht_find(store, key); census_internal_unlock_trace_store(); if (window_stats == NULL) { window_stats = census_window_stats_create(3, min_hour_total_intervals, 30, &window_stats_settings); key.ptr = gpr_strdup(key.ptr); census_ht_insert(store, key, (void *)window_stats); } census_window_stats_add(window_stats, gpr_now(GPR_CLOCK_REALTIME), stats); } else { census_internal_unlock_trace_store(); } } gpr_mu_unlock(&g_mu); } void census_record_rpc_client_stats(census_op_id op_id, const census_rpc_stats *stats) { record_stats(g_client_stats_store, op_id, stats); } void census_record_rpc_server_stats(census_op_id op_id, const census_rpc_stats *stats) { record_stats(g_server_stats_store, op_id, stats); } /* Get stats from input stats store */ static void get_stats(census_ht *store, census_aggregated_rpc_stats *data) { GPR_ASSERT(data != NULL); if (data->num_entries != 0) { census_aggregated_rpc_stats_set_empty(data); } gpr_mu_lock(&g_mu); if (store != NULL) { size_t n; unsigned i, j; gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); census_ht_kv *kv = census_ht_get_all_elements(store, &n); if (kv != NULL) { data->num_entries = n; data->stats = (per_method_stats *)gpr_malloc(sizeof(per_method_stats) * n); for (i = 0; i < n; i++) { census_window_stats_sums sums[NUM_INTERVALS]; for (j = 0; j < NUM_INTERVALS; j++) { sums[j].statistic = (void *)census_rpc_stats_create_empty(); } data->stats[i].method = gpr_strdup(kv[i].k.ptr); census_window_stats_get_sums(kv[i].v, now, sums); data->stats[i].minute_stats = *(census_rpc_stats *)sums[MINUTE_INTERVAL].statistic; data->stats[i].hour_stats = *(census_rpc_stats *)sums[HOUR_INTERVAL].statistic; data->stats[i].total_stats = *(census_rpc_stats *)sums[TOTAL_INTERVAL].statistic; for (j = 0; j < NUM_INTERVALS; j++) { gpr_free(sums[j].statistic); } } gpr_free(kv); } } gpr_mu_unlock(&g_mu); } void census_get_client_stats(census_aggregated_rpc_stats *data) { get_stats(g_client_stats_store, data); } void census_get_server_stats(census_aggregated_rpc_stats *data) { get_stats(g_server_stats_store, data); } void census_stats_store_init(void) { init_mutex_once(); gpr_mu_lock(&g_mu); if (g_client_stats_store == NULL && g_server_stats_store == NULL) { g_client_stats_store = census_ht_create(&ht_opt); g_server_stats_store = census_ht_create(&ht_opt); } else { gpr_log(GPR_ERROR, "Census stats store already initialized."); } gpr_mu_unlock(&g_mu); } void census_stats_store_shutdown(void) { init_mutex_once(); gpr_mu_lock(&g_mu); if (g_client_stats_store != NULL) { census_ht_destroy(g_client_stats_store); g_client_stats_store = NULL; } else { gpr_log(GPR_ERROR, "Census server stats store not initialized."); } if (g_server_stats_store != NULL) { census_ht_destroy(g_server_stats_store); g_server_stats_store = NULL; } else { gpr_log(GPR_ERROR, "Census client stats store not initialized."); } gpr_mu_unlock(&g_mu); } grpc-1.3.2/src/core/ext/census/census_rpc_stats.h000066400000000000000000000072621310511640000220200ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_CENSUS_CENSUS_RPC_STATS_H #define GRPC_CORE_EXT_CENSUS_CENSUS_RPC_STATS_H #include #include "src/core/ext/census/census_interface.h" #ifdef __cplusplus extern "C" { #endif struct census_rpc_stats { uint64_t cnt; uint64_t rpc_error_cnt; uint64_t app_error_cnt; double elapsed_time_ms; double api_request_bytes; double wire_request_bytes; double api_response_bytes; double wire_response_bytes; }; /* Creates an empty rpc stats object on heap. */ census_rpc_stats *census_rpc_stats_create_empty(void); typedef struct census_per_method_rpc_stats { const char *method; census_rpc_stats minute_stats; /* cumulative stats in the past minute */ census_rpc_stats hour_stats; /* cumulative stats in the past hour */ census_rpc_stats total_stats; /* cumulative stats from last gc */ } census_per_method_rpc_stats; typedef struct census_aggregated_rpc_stats { int num_entries; census_per_method_rpc_stats *stats; } census_aggregated_rpc_stats; /* Initializes an aggregated rpc stats object to an empty state. */ void census_aggregated_rpc_stats_set_empty(census_aggregated_rpc_stats *data); /* Records client side stats of a rpc. */ void census_record_rpc_client_stats(census_op_id op_id, const census_rpc_stats *stats); /* Records server side stats of a rpc. */ void census_record_rpc_server_stats(census_op_id op_id, const census_rpc_stats *stats); /* The following two functions are intended for inprocess query of per-service per-method stats from grpc implementations. */ /* Populates *data_map with server side aggregated per-service per-method stats. DO NOT CALL from outside of grpc code. */ void census_get_server_stats(census_aggregated_rpc_stats *data_map); /* Populates *data_map with client side aggregated per-service per-method stats. DO NOT CALL from outside of grpc code. */ void census_get_client_stats(census_aggregated_rpc_stats *data_map); void census_stats_store_init(void); void census_stats_store_shutdown(void); #ifdef __cplusplus } #endif #endif /* GRPC_CORE_EXT_CENSUS_CENSUS_RPC_STATS_H */ grpc-1.3.2/src/core/ext/census/census_tracing.c000066400000000000000000000164561310511640000214450ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/census/census_tracing.h" #include "src/core/ext/census/census_interface.h" #include #include #include #include #include #include #include "src/core/ext/census/hash_table.h" #include "src/core/lib/support/string.h" void census_trace_obj_destroy(census_trace_obj *obj) { census_trace_annotation *p = obj->annotations; while (p != NULL) { census_trace_annotation *next = p->next; gpr_free(p); p = next; } gpr_free(obj->method); gpr_free(obj); } static void delete_trace_obj(void *obj) { census_trace_obj_destroy((census_trace_obj *)obj); } static const census_ht_option ht_opt = { CENSUS_HT_UINT64 /* key type */, 571 /* n_of_buckets */, NULL /* hash */, NULL /* compare_keys */, delete_trace_obj /* delete data */, NULL /* delete key */ }; static gpr_once g_init_mutex_once = GPR_ONCE_INIT; static gpr_mu g_mu; /* Guards following two static variables. */ static census_ht *g_trace_store = NULL; static uint64_t g_id = 0; static census_ht_key op_id_as_key(census_op_id *id) { return *(census_ht_key *)id; } static uint64_t op_id_2_uint64(census_op_id *id) { uint64_t ret; memcpy(&ret, id, sizeof(census_op_id)); return ret; } static void init_mutex(void) { gpr_mu_init(&g_mu); } static void init_mutex_once(void) { gpr_once_init(&g_init_mutex_once, init_mutex); } census_op_id census_tracing_start_op(void) { gpr_mu_lock(&g_mu); { census_trace_obj *ret = gpr_malloc(sizeof(census_trace_obj)); memset(ret, 0, sizeof(census_trace_obj)); g_id++; memcpy(&ret->id, &g_id, sizeof(census_op_id)); ret->rpc_stats.cnt = 1; ret->ts = gpr_now(GPR_CLOCK_REALTIME); census_ht_insert(g_trace_store, op_id_as_key(&ret->id), (void *)ret); gpr_log(GPR_DEBUG, "Start tracing for id %lu", g_id); gpr_mu_unlock(&g_mu); return ret->id; } } int census_add_method_tag(census_op_id op_id, const char *method) { int ret = 0; census_trace_obj *trace = NULL; gpr_mu_lock(&g_mu); trace = census_ht_find(g_trace_store, op_id_as_key(&op_id)); if (trace == NULL) { ret = 1; } else { trace->method = gpr_strdup(method); } gpr_mu_unlock(&g_mu); return ret; } void census_tracing_print(census_op_id op_id, const char *anno_txt) { census_trace_obj *trace = NULL; gpr_mu_lock(&g_mu); trace = census_ht_find(g_trace_store, op_id_as_key(&op_id)); if (trace != NULL) { census_trace_annotation *anno = gpr_malloc(sizeof(census_trace_annotation)); anno->ts = gpr_now(GPR_CLOCK_REALTIME); { char *d = anno->txt; const char *s = anno_txt; int n = 0; for (; n < CENSUS_MAX_ANNOTATION_LENGTH && *s != '\0'; ++n) { *d++ = *s++; } *d = '\0'; } anno->next = trace->annotations; trace->annotations = anno; } gpr_mu_unlock(&g_mu); } void census_tracing_end_op(census_op_id op_id) { census_trace_obj *trace = NULL; gpr_mu_lock(&g_mu); trace = census_ht_find(g_trace_store, op_id_as_key(&op_id)); if (trace != NULL) { trace->rpc_stats.elapsed_time_ms = gpr_timespec_to_micros( gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), trace->ts)); gpr_log(GPR_DEBUG, "End tracing for id %lu, method %s, latency %f us", op_id_2_uint64(&op_id), trace->method, trace->rpc_stats.elapsed_time_ms); census_ht_erase(g_trace_store, op_id_as_key(&op_id)); } gpr_mu_unlock(&g_mu); } void census_tracing_init(void) { init_mutex_once(); gpr_mu_lock(&g_mu); if (g_trace_store == NULL) { g_id = 1; g_trace_store = census_ht_create(&ht_opt); } else { gpr_log(GPR_ERROR, "Census trace store already initialized."); } gpr_mu_unlock(&g_mu); } void census_tracing_shutdown(void) { gpr_mu_lock(&g_mu); if (g_trace_store != NULL) { census_ht_destroy(g_trace_store); g_trace_store = NULL; } else { gpr_log(GPR_ERROR, "Census trace store is not initialized."); } gpr_mu_unlock(&g_mu); } void census_internal_lock_trace_store(void) { gpr_mu_lock(&g_mu); } void census_internal_unlock_trace_store(void) { gpr_mu_unlock(&g_mu); } census_trace_obj *census_get_trace_obj_locked(census_op_id op_id) { if (g_trace_store == NULL) { gpr_log(GPR_ERROR, "Census trace store is not initialized."); return NULL; } return (census_trace_obj *)census_ht_find(g_trace_store, op_id_as_key(&op_id)); } const char *census_get_trace_method_name(const census_trace_obj *trace) { return trace->method; } static census_trace_annotation *dup_annotation_chain( census_trace_annotation *from) { census_trace_annotation *ret = NULL; census_trace_annotation **to = &ret; for (; from != NULL; from = from->next) { *to = gpr_malloc(sizeof(census_trace_annotation)); memcpy(*to, from, sizeof(census_trace_annotation)); to = &(*to)->next; } return ret; } static census_trace_obj *trace_obj_dup(census_trace_obj *from) { census_trace_obj *to = NULL; GPR_ASSERT(from != NULL); to = gpr_malloc(sizeof(census_trace_obj)); to->id = from->id; to->ts = from->ts; to->rpc_stats = from->rpc_stats; to->method = gpr_strdup(from->method); to->annotations = dup_annotation_chain(from->annotations); return to; } census_trace_obj **census_get_active_ops(int *num_active_ops) { census_trace_obj **ret = NULL; gpr_mu_lock(&g_mu); if (g_trace_store != NULL) { size_t n = 0; census_ht_kv *all_kvs = census_ht_get_all_elements(g_trace_store, &n); *num_active_ops = (int)n; if (n != 0) { size_t i = 0; ret = gpr_malloc(sizeof(census_trace_obj *) * n); for (i = 0; i < n; i++) { ret[i] = trace_obj_dup((census_trace_obj *)all_kvs[i].v); } } gpr_free(all_kvs); } gpr_mu_unlock(&g_mu); return ret; } grpc-1.3.2/src/core/ext/census/census_tracing.h000066400000000000000000000073031310511640000214410ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_CENSUS_CENSUS_TRACING_H #define GRPC_CORE_EXT_CENSUS_CENSUS_TRACING_H #include #include "src/core/ext/census/census_rpc_stats.h" /* WARNING: The data structures and APIs provided by this file are for GRPC library's internal use ONLY. They might be changed in backward-incompatible ways and are not subject to any deprecation policy. They are not recommended for external use. */ #ifdef __cplusplus extern "C" { #endif /* Struct for a trace annotation. */ typedef struct census_trace_annotation { gpr_timespec ts; /* timestamp of the annotation */ char txt[CENSUS_MAX_ANNOTATION_LENGTH + 1]; /* actual txt annotation */ struct census_trace_annotation *next; } census_trace_annotation; typedef struct census_trace_obj { census_op_id id; gpr_timespec ts; census_rpc_stats rpc_stats; char *method; census_trace_annotation *annotations; } census_trace_obj; /* Deletes trace object. */ void census_trace_obj_destroy(census_trace_obj *obj); /* Initializes trace store. This function is thread safe. */ void census_tracing_init(void); /* Shutsdown trace store. This function is thread safe. */ void census_tracing_shutdown(void); /* Gets trace obj corresponding to the input op_id. Returns NULL if trace store is not initialized or trace obj is not found. Requires trace store being locked before calling this function. */ census_trace_obj *census_get_trace_obj_locked(census_op_id op_id); /* The following two functions acquire and release the trace store global lock. They are for census internal use only. */ void census_internal_lock_trace_store(void); void census_internal_unlock_trace_store(void); /* Gets method name associated with the input trace object. */ const char *census_get_trace_method_name(const census_trace_obj *trace); /* Returns an array of pointers to trace objects of currently active operations and fills in number of active operations. Returns NULL if there are no active operations. Caller owns the returned objects. */ census_trace_obj **census_get_active_ops(int *num_active_ops); #ifdef __cplusplus } #endif #endif /* GRPC_CORE_EXT_CENSUS_CENSUS_TRACING_H */ grpc-1.3.2/src/core/ext/census/context.c000066400000000000000000000443561310511640000201220ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include "src/core/lib/support/string.h" // Functions in this file support the public context API, including // encoding/decoding as part of context propagation across RPC's. The overall // requirements (in approximate priority order) for the // context representation: // 1. Efficient conversion to/from wire format // 2. Minimal bytes used on-wire // 3. Efficient context creation // 4. Efficient lookup of tag value for a key // 5. Efficient iteration over tags // 6. Minimal memory footprint // // Notes on tradeoffs/decisions: // * tag includes 1 byte length of key, as well as nil-terminating byte. These // are to aid in efficient parsing and the ability to directly return key // strings. This is more important than saving a single byte/tag on the wire. // * The wire encoding uses only single byte values. This eliminates the need // to handle endian-ness conversions. It also means there is a hard upper // limit of 255 for both CENSUS_MAX_TAG_KV_LEN and CENSUS_MAX_PROPAGATED_TAGS. // * Keep all tag information (keys/values/flags) in a single memory buffer, // that can be directly copied to the wire. // min and max valid chars in tag keys and values. All printable ASCII is OK. #define MIN_VALID_TAG_CHAR 32 // ' ' #define MAX_VALID_TAG_CHAR 126 // '~' // Structure representing a set of tags. Essentially a count of number of tags // present, and pointer to a chunk of memory that contains the per-tag details. struct tag_set { int ntags; // number of tags. int ntags_alloc; // ntags + number of deleted tags (total number of tags // in all of kvm). This will always be == ntags, except during the process // of building a new tag set. size_t kvm_size; // number of bytes allocated for key/value storage. size_t kvm_used; // number of bytes of used key/value memory char *kvm; // key/value memory. Consists of repeated entries of: // Offset Size Description // 0 1 Key length, including trailing 0. (K) // 1 1 Value length, including trailing 0 (V) // 2 1 Flags // 3 K Key bytes // 3 + K V Value bytes // // We refer to the first 3 entries as the 'tag header'. If extra values are // introduced in the header, you will need to modify the TAG_HEADER_SIZE // constant, the raw_tag structure (and everything that uses it) and the // encode/decode functions appropriately. }; // Number of bytes in tag header. #define TAG_HEADER_SIZE 3 // key length (1) + value length (1) + flags (1) // Offsets to tag header entries. #define KEY_LEN_OFFSET 0 #define VALUE_LEN_OFFSET 1 #define FLAG_OFFSET 2 // raw_tag represents the raw-storage form of a tag in the kvm of a tag_set. struct raw_tag { uint8_t key_len; uint8_t value_len; uint8_t flags; char *key; char *value; }; // Use a reserved flag bit for indication of deleted tag. #define CENSUS_TAG_DELETED CENSUS_TAG_RESERVED #define CENSUS_TAG_IS_DELETED(flags) (flags & CENSUS_TAG_DELETED) // Primary representation of a context. Composed of 2 underlying tag_set // structs, one each for propagated and local (non-propagated) tags. This is // to efficiently support tag encoding/decoding. // TODO(aveitch): need to add tracing id's/structure. struct census_context { struct tag_set tags[2]; census_context_status status; }; // Indices into the tags member of census_context #define PROPAGATED_TAGS 0 #define LOCAL_TAGS 1 // Validate (check all characters are in range and size is less than limit) a // key or value string. Returns 0 if the string is invalid, or the length // (including terminator) if valid. static size_t validate_tag(const char *kv) { size_t len = 1; char ch; while ((ch = *kv++) != 0) { if (ch < MIN_VALID_TAG_CHAR || ch > MAX_VALID_TAG_CHAR) { return 0; } len++; } if (len > CENSUS_MAX_TAG_KV_LEN) { return 0; } return len; } // Extract a raw tag given a pointer (raw) to the tag header. Allow for some // extra bytes in the tag header (see encode/decode functions for usage: this // allows for future expansion of the tag header). static char *decode_tag(struct raw_tag *tag, char *header, int offset) { tag->key_len = (uint8_t)(*header++); tag->value_len = (uint8_t)(*header++); tag->flags = (uint8_t)(*header++); header += offset; tag->key = header; header += tag->key_len; tag->value = header; return header + tag->value_len; } // Make a copy (in 'to') of an existing tag_set. static void tag_set_copy(struct tag_set *to, const struct tag_set *from) { memcpy(to, from, sizeof(struct tag_set)); to->kvm = gpr_malloc(to->kvm_size); memcpy(to->kvm, from->kvm, from->kvm_used); } // Delete a tag from a tag_set, if it exists (returns true if it did). static bool tag_set_delete_tag(struct tag_set *tags, const char *key, size_t key_len) { char *kvp = tags->kvm; for (int i = 0; i < tags->ntags_alloc; i++) { uint8_t *flags = (uint8_t *)(kvp + FLAG_OFFSET); struct raw_tag tag; kvp = decode_tag(&tag, kvp, 0); if (CENSUS_TAG_IS_DELETED(tag.flags)) continue; if ((key_len == tag.key_len) && (memcmp(key, tag.key, key_len) == 0)) { *flags |= CENSUS_TAG_DELETED; tags->ntags--; return true; } } return false; } // Delete a tag from a context, return true if it existed. static bool context_delete_tag(census_context *context, const census_tag *tag, size_t key_len) { return ( tag_set_delete_tag(&context->tags[LOCAL_TAGS], tag->key, key_len) || tag_set_delete_tag(&context->tags[PROPAGATED_TAGS], tag->key, key_len)); } // Add a tag to a tag_set. Return true on success, false if the tag could // not be added because of constraints on tag set size. This function should // not be called if the tag may already exist (in a non-deleted state) in // the tag_set, as that would result in two tags with the same key. static bool tag_set_add_tag(struct tag_set *tags, const census_tag *tag, size_t key_len, size_t value_len) { if (tags->ntags == CENSUS_MAX_PROPAGATED_TAGS) { return false; } const size_t tag_size = key_len + value_len + TAG_HEADER_SIZE; if (tags->kvm_used + tag_size > tags->kvm_size) { // allocate new memory if needed tags->kvm_size += 2 * CENSUS_MAX_TAG_KV_LEN + TAG_HEADER_SIZE; char *new_kvm = gpr_malloc(tags->kvm_size); memcpy(new_kvm, tags->kvm, tags->kvm_used); gpr_free(tags->kvm); tags->kvm = new_kvm; } char *kvp = tags->kvm + tags->kvm_used; *kvp++ = (char)key_len; *kvp++ = (char)value_len; // ensure reserved flags are not used. *kvp++ = (char)(tag->flags & (CENSUS_TAG_PROPAGATE | CENSUS_TAG_STATS)); memcpy(kvp, tag->key, key_len); kvp += key_len; memcpy(kvp, tag->value, value_len); tags->kvm_used += tag_size; tags->ntags++; tags->ntags_alloc++; return true; } // Add/modify/delete a tag to/in a context. Caller must validate that tag key // etc. are valid. static void context_modify_tag(census_context *context, const census_tag *tag, size_t key_len, size_t value_len) { // First delete the tag if it is already present. bool deleted = context_delete_tag(context, tag, key_len); bool added = false; if (CENSUS_TAG_IS_PROPAGATED(tag->flags)) { added = tag_set_add_tag(&context->tags[PROPAGATED_TAGS], tag, key_len, value_len); } else { added = tag_set_add_tag(&context->tags[LOCAL_TAGS], tag, key_len, value_len); } if (deleted) { context->status.n_modified_tags++; } else { if (added) { context->status.n_added_tags++; } else { context->status.n_ignored_tags++; } } } // Remove memory used for deleted tags from a tag set. Basic algorithm: // 1) Walk through tag set to find first deleted tag. Record where it is. // 2) Find the next not-deleted tag. Copy all of kvm from there to the end // "over" the deleted tags // 3) repeat #1 and #2 until we have seen all tags // 4) if we are still looking for a not-deleted tag, then all the end portion // of the kvm is deleted. Just reduce the used amount of memory by the // appropriate amount. static void tag_set_flatten(struct tag_set *tags) { if (tags->ntags == tags->ntags_alloc) return; bool found_deleted = false; // found a deleted tag. char *kvp = tags->kvm; char *dbase = NULL; // record location of deleted tag for (int i = 0; i < tags->ntags_alloc; i++) { struct raw_tag tag; char *next_kvp = decode_tag(&tag, kvp, 0); if (found_deleted) { if (!CENSUS_TAG_IS_DELETED(tag.flags)) { ptrdiff_t reduce = kvp - dbase; // #bytes in deleted tags GPR_ASSERT(reduce > 0); ptrdiff_t copy_size = tags->kvm + tags->kvm_used - kvp; GPR_ASSERT(copy_size > 0); memmove(dbase, kvp, (size_t)copy_size); tags->kvm_used -= (size_t)reduce; next_kvp -= reduce; found_deleted = false; } } else { if (CENSUS_TAG_IS_DELETED(tag.flags)) { dbase = kvp; found_deleted = true; } } kvp = next_kvp; } if (found_deleted) { GPR_ASSERT(dbase > tags->kvm); tags->kvm_used = (size_t)(dbase - tags->kvm); } tags->ntags_alloc = tags->ntags; } census_context *census_context_create(const census_context *base, const census_tag *tags, int ntags, census_context_status const **status) { census_context *context = gpr_malloc(sizeof(census_context)); // If we are given a base, copy it into our new tag set. Otherwise set it // to zero/NULL everything. if (base == NULL) { memset(context, 0, sizeof(census_context)); } else { tag_set_copy(&context->tags[PROPAGATED_TAGS], &base->tags[PROPAGATED_TAGS]); tag_set_copy(&context->tags[LOCAL_TAGS], &base->tags[LOCAL_TAGS]); memset(&context->status, 0, sizeof(context->status)); } // Walk over the additional tags and, for those that aren't invalid, modify // the context to add/replace/delete as required. for (int i = 0; i < ntags; i++) { const census_tag *tag = &tags[i]; size_t key_len = validate_tag(tag->key); // ignore the tag if it is invalid or too short. if (key_len <= 1) { context->status.n_invalid_tags++; } else { if (tag->value != NULL) { size_t value_len = validate_tag(tag->value); if (value_len != 0) { context_modify_tag(context, tag, key_len, value_len); } else { context->status.n_invalid_tags++; } } else { if (context_delete_tag(context, tag, key_len)) { context->status.n_deleted_tags++; } } } } // Remove any deleted tags, update status if needed, and return. tag_set_flatten(&context->tags[PROPAGATED_TAGS]); tag_set_flatten(&context->tags[LOCAL_TAGS]); context->status.n_propagated_tags = context->tags[PROPAGATED_TAGS].ntags; context->status.n_local_tags = context->tags[LOCAL_TAGS].ntags; if (status) { *status = &context->status; } return context; } const census_context_status *census_context_get_status( const census_context *context) { return &context->status; } void census_context_destroy(census_context *context) { gpr_free(context->tags[PROPAGATED_TAGS].kvm); gpr_free(context->tags[LOCAL_TAGS].kvm); gpr_free(context); } void census_context_initialize_iterator(const census_context *context, census_context_iterator *iterator) { iterator->context = context; iterator->index = 0; if (context->tags[PROPAGATED_TAGS].ntags != 0) { iterator->base = PROPAGATED_TAGS; iterator->kvm = context->tags[PROPAGATED_TAGS].kvm; } else if (context->tags[LOCAL_TAGS].ntags != 0) { iterator->base = LOCAL_TAGS; iterator->kvm = context->tags[LOCAL_TAGS].kvm; } else { iterator->base = -1; } } int census_context_next_tag(census_context_iterator *iterator, census_tag *tag) { if (iterator->base < 0) { return 0; } struct raw_tag raw; iterator->kvm = decode_tag(&raw, iterator->kvm, 0); tag->key = raw.key; tag->value = raw.value; tag->flags = raw.flags; if (++iterator->index == iterator->context->tags[iterator->base].ntags) { do { if (iterator->base == LOCAL_TAGS) { iterator->base = -1; return 1; } } while (iterator->context->tags[++iterator->base].ntags == 0); iterator->index = 0; iterator->kvm = iterator->context->tags[iterator->base].kvm; } return 1; } // Find a tag in a tag_set by key. Return true if found, false otherwise. static bool tag_set_get_tag(const struct tag_set *tags, const char *key, size_t key_len, census_tag *tag) { char *kvp = tags->kvm; for (int i = 0; i < tags->ntags; i++) { struct raw_tag raw; kvp = decode_tag(&raw, kvp, 0); if (key_len == raw.key_len && memcmp(raw.key, key, key_len) == 0) { tag->key = raw.key; tag->value = raw.value; tag->flags = raw.flags; return true; } } return false; } int census_context_get_tag(const census_context *context, const char *key, census_tag *tag) { size_t key_len = strlen(key) + 1; if (key_len == 1) { return 0; } if (tag_set_get_tag(&context->tags[PROPAGATED_TAGS], key, key_len, tag) || tag_set_get_tag(&context->tags[LOCAL_TAGS], key, key_len, tag)) { return 1; } return 0; } // Context encoding and decoding functions. // // Wire format for tag_set's on the wire: // // First, a tag set header: // // offset bytes description // 0 1 version number // 1 1 number of bytes in this header. This allows for future // expansion. // 2 1 number of bytes in each tag header. // 3 1 ntags value from tag set. // // This is followed by the key/value memory from struct tag_set. #define ENCODED_VERSION 0 // Version number #define ENCODED_HEADER_SIZE 4 // size of tag set header // Encode a tag set. Returns 0 if buffer is too small. static size_t tag_set_encode(const struct tag_set *tags, char *buffer, size_t buf_size) { if (buf_size < ENCODED_HEADER_SIZE + tags->kvm_used) { return 0; } buf_size -= ENCODED_HEADER_SIZE; *buffer++ = (char)ENCODED_VERSION; *buffer++ = (char)ENCODED_HEADER_SIZE; *buffer++ = (char)TAG_HEADER_SIZE; *buffer++ = (char)tags->ntags; if (tags->ntags == 0) { return ENCODED_HEADER_SIZE; } memcpy(buffer, tags->kvm, tags->kvm_used); return ENCODED_HEADER_SIZE + tags->kvm_used; } size_t census_context_encode(const census_context *context, char *buffer, size_t buf_size) { return tag_set_encode(&context->tags[PROPAGATED_TAGS], buffer, buf_size); } // Decode a tag set. static void tag_set_decode(struct tag_set *tags, const char *buffer, size_t size) { uint8_t version = (uint8_t)(*buffer++); uint8_t header_size = (uint8_t)(*buffer++); uint8_t tag_header_size = (uint8_t)(*buffer++); tags->ntags = tags->ntags_alloc = (int)(*buffer++); if (tags->ntags == 0) { tags->ntags_alloc = 0; tags->kvm_size = 0; tags->kvm_used = 0; tags->kvm = NULL; return; } if (header_size != ENCODED_HEADER_SIZE) { GPR_ASSERT(version != ENCODED_VERSION); GPR_ASSERT(ENCODED_HEADER_SIZE < header_size); buffer += (header_size - ENCODED_HEADER_SIZE); } tags->kvm_used = size - header_size; tags->kvm_size = tags->kvm_used + CENSUS_MAX_TAG_KV_LEN; tags->kvm = gpr_malloc(tags->kvm_size); if (tag_header_size != TAG_HEADER_SIZE) { // something new in the tag information. I don't understand it, so // don't copy it over. GPR_ASSERT(version != ENCODED_VERSION); GPR_ASSERT(tag_header_size > TAG_HEADER_SIZE); char *kvp = tags->kvm; for (int i = 0; i < tags->ntags; i++) { memcpy(kvp, buffer, TAG_HEADER_SIZE); kvp += header_size; struct raw_tag raw; buffer = decode_tag(&raw, (char *)buffer, tag_header_size - TAG_HEADER_SIZE); memcpy(kvp, raw.key, (size_t)raw.key_len + raw.value_len); kvp += raw.key_len + raw.value_len; } } else { memcpy(tags->kvm, buffer, tags->kvm_used); } } census_context *census_context_decode(const char *buffer, size_t size) { census_context *context = gpr_malloc(sizeof(census_context)); memset(&context->tags[LOCAL_TAGS], 0, sizeof(struct tag_set)); if (buffer == NULL) { memset(&context->tags[PROPAGATED_TAGS], 0, sizeof(struct tag_set)); } else { tag_set_decode(&context->tags[PROPAGATED_TAGS], buffer, size); } memset(&context->status, 0, sizeof(context->status)); context->status.n_propagated_tags = context->tags[PROPAGATED_TAGS].ntags; return context; } grpc-1.3.2/src/core/ext/census/gen/000077500000000000000000000000001310511640000170275ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/census/gen/README.md000066400000000000000000000010171310511640000203050ustar00rootroot00000000000000Files generated for use by Census stats and trace recording subsystem. # Files * census.pb.{h,c} - Generated from src/core/ext/census/census.proto, using the script `tools/codegen/core/gen_nano_proto.sh src/proto/census/census.proto $PWD/src/core/ext/census/gen src/core/ext/census/gen` * trace_context.pb.{h,c} - Generated from src/core/ext/census/trace_context.proto, using the script `tools/codegen/core/gen_nano_proto.sh src/proto/census/trace_context.proto $PWD/src/core/ext/census/gen src/core/ext/census/gen` grpc-1.3.2/src/core/ext/census/gen/census.pb.c000066400000000000000000000334461310511640000211050ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* Automatically generated nanopb constant definitions */ /* Generated by nanopb-0.3.5-dev */ #include "src/core/ext/census/gen/census.pb.h" #if PB_PROTO_HEADER_VERSION != 30 #error Regenerate this file with the current version of nanopb generator. #endif const pb_field_t google_census_Duration_fields[3] = { PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, google_census_Duration, seconds, seconds, 0), PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, google_census_Duration, nanos, seconds, 0), PB_LAST_FIELD }; const pb_field_t google_census_Timestamp_fields[3] = { PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, google_census_Timestamp, seconds, seconds, 0), PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, google_census_Timestamp, nanos, seconds, 0), PB_LAST_FIELD }; const pb_field_t google_census_Resource_fields[4] = { PB_FIELD( 1, STRING , OPTIONAL, CALLBACK, FIRST, google_census_Resource, name, name, 0), PB_FIELD( 2, STRING , OPTIONAL, CALLBACK, OTHER, google_census_Resource, description, name, 0), PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, google_census_Resource, unit, description, &google_census_Resource_MeasurementUnit_fields), PB_LAST_FIELD }; const pb_field_t google_census_Resource_MeasurementUnit_fields[4] = { PB_FIELD( 1, INT32 , OPTIONAL, STATIC , FIRST, google_census_Resource_MeasurementUnit, prefix, prefix, 0), PB_FIELD( 2, UENUM , REPEATED, CALLBACK, OTHER, google_census_Resource_MeasurementUnit, numerator, prefix, 0), PB_FIELD( 3, UENUM , REPEATED, CALLBACK, OTHER, google_census_Resource_MeasurementUnit, denominator, numerator, 0), PB_LAST_FIELD }; const pb_field_t google_census_AggregationDescriptor_fields[4] = { PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, google_census_AggregationDescriptor, type, type, 0), PB_ONEOF_FIELD(options, 2, MESSAGE , ONEOF, STATIC , OTHER, google_census_AggregationDescriptor, bucket_boundaries, type, &google_census_AggregationDescriptor_BucketBoundaries_fields), PB_ONEOF_FIELD(options, 3, MESSAGE , ONEOF, STATIC , OTHER, google_census_AggregationDescriptor, interval_boundaries, type, &google_census_AggregationDescriptor_IntervalBoundaries_fields), PB_LAST_FIELD }; const pb_field_t google_census_AggregationDescriptor_BucketBoundaries_fields[2] = { PB_FIELD( 1, DOUBLE , REPEATED, CALLBACK, FIRST, google_census_AggregationDescriptor_BucketBoundaries, bounds, bounds, 0), PB_LAST_FIELD }; const pb_field_t google_census_AggregationDescriptor_IntervalBoundaries_fields[2] = { PB_FIELD( 1, DOUBLE , REPEATED, CALLBACK, FIRST, google_census_AggregationDescriptor_IntervalBoundaries, window_size, window_size, 0), PB_LAST_FIELD }; const pb_field_t google_census_Distribution_fields[5] = { PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, google_census_Distribution, count, count, 0), PB_FIELD( 2, DOUBLE , OPTIONAL, STATIC , OTHER, google_census_Distribution, mean, count, 0), PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, google_census_Distribution, range, mean, &google_census_Distribution_Range_fields), PB_FIELD( 4, INT64 , REPEATED, CALLBACK, OTHER, google_census_Distribution, bucket_count, range, 0), PB_LAST_FIELD }; const pb_field_t google_census_Distribution_Range_fields[3] = { PB_FIELD( 1, DOUBLE , OPTIONAL, STATIC , FIRST, google_census_Distribution_Range, min, min, 0), PB_FIELD( 2, DOUBLE , OPTIONAL, STATIC , OTHER, google_census_Distribution_Range, max, min, 0), PB_LAST_FIELD }; const pb_field_t google_census_IntervalStats_fields[2] = { PB_FIELD( 1, MESSAGE , REPEATED, CALLBACK, FIRST, google_census_IntervalStats, window, window, &google_census_IntervalStats_Window_fields), PB_LAST_FIELD }; const pb_field_t google_census_IntervalStats_Window_fields[4] = { PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, google_census_IntervalStats_Window, window_size, window_size, &google_census_Duration_fields), PB_FIELD( 2, INT64 , OPTIONAL, STATIC , OTHER, google_census_IntervalStats_Window, count, window_size, 0), PB_FIELD( 3, DOUBLE , OPTIONAL, STATIC , OTHER, google_census_IntervalStats_Window, mean, count, 0), PB_LAST_FIELD }; const pb_field_t google_census_Tag_fields[3] = { PB_FIELD( 1, STRING , OPTIONAL, STATIC , FIRST, google_census_Tag, key, key, 0), PB_FIELD( 2, STRING , OPTIONAL, STATIC , OTHER, google_census_Tag, value, key, 0), PB_LAST_FIELD }; const pb_field_t google_census_View_fields[6] = { PB_FIELD( 1, STRING , OPTIONAL, CALLBACK, FIRST, google_census_View, name, name, 0), PB_FIELD( 2, STRING , OPTIONAL, CALLBACK, OTHER, google_census_View, description, name, 0), PB_FIELD( 3, STRING , OPTIONAL, CALLBACK, OTHER, google_census_View, resource_name, description, 0), PB_FIELD( 4, MESSAGE , OPTIONAL, STATIC , OTHER, google_census_View, aggregation, resource_name, &google_census_AggregationDescriptor_fields), PB_FIELD( 5, STRING , REPEATED, CALLBACK, OTHER, google_census_View, tag_key, aggregation, 0), PB_LAST_FIELD }; const pb_field_t google_census_Aggregation_fields[7] = { PB_FIELD( 1, STRING , OPTIONAL, CALLBACK, FIRST, google_census_Aggregation, name, name, 0), PB_FIELD( 2, STRING , OPTIONAL, CALLBACK, OTHER, google_census_Aggregation, description, name, 0), PB_ONEOF_FIELD(data, 3, UINT64 , ONEOF, STATIC , OTHER, google_census_Aggregation, count, description, 0), PB_ONEOF_FIELD(data, 4, MESSAGE , ONEOF, STATIC , OTHER, google_census_Aggregation, distribution, description, &google_census_Distribution_fields), PB_ONEOF_FIELD(data, 5, MESSAGE , ONEOF, STATIC , OTHER, google_census_Aggregation, interval_stats, description, &google_census_IntervalStats_fields), PB_FIELD( 6, MESSAGE , REPEATED, CALLBACK, OTHER, google_census_Aggregation, tag, data.interval_stats, &google_census_Tag_fields), PB_LAST_FIELD }; const pb_field_t google_census_Metric_fields[5] = { PB_FIELD( 1, STRING , OPTIONAL, CALLBACK, FIRST, google_census_Metric, view_name, view_name, 0), PB_FIELD( 2, MESSAGE , REPEATED, CALLBACK, OTHER, google_census_Metric, aggregation, view_name, &google_census_Aggregation_fields), PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, google_census_Metric, start, aggregation, &google_census_Timestamp_fields), PB_FIELD( 4, MESSAGE , OPTIONAL, STATIC , OTHER, google_census_Metric, end, start, &google_census_Timestamp_fields), PB_LAST_FIELD }; /* Check that field information fits in pb_field_t */ #if !defined(PB_FIELD_32BIT) /* If you get an error here, it means that you need to define PB_FIELD_32BIT * compile-time option. You can do that in pb.h or on compiler command line. * * The reason you need to do this is that some of your messages contain tag * numbers or field sizes that are larger than what can fit in 8 or 16 bit * field descriptors. */ PB_STATIC_ASSERT((pb_membersize(google_census_Resource, unit) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Resource, unit) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Distribution, range) < 65536 && pb_membersize(google_census_IntervalStats, window) < 65536 && pb_membersize(google_census_IntervalStats_Window, window_size) < 65536 && pb_membersize(google_census_View, aggregation) < 65536 && pb_membersize(google_census_Aggregation, data.distribution) < 65536 && pb_membersize(google_census_Aggregation, data.interval_stats) < 65536 && pb_membersize(google_census_Resource, unit) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Resource, unit) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Distribution, range) < 65536 && pb_membersize(google_census_IntervalStats, window) < 65536 && pb_membersize(google_census_IntervalStats_Window, window_size) < 65536 && pb_membersize(google_census_View, aggregation) < 65536 && pb_membersize(google_census_Aggregation, data.distribution) < 65536 && pb_membersize(google_census_Aggregation, data.interval_stats) < 65536 && pb_membersize(google_census_Aggregation, tag) < 65536 && pb_membersize(google_census_Metric, aggregation) < 65536 && pb_membersize(google_census_Metric, start) < 65536 && pb_membersize(google_census_Metric, end) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_google_census_Duration_google_census_Timestamp_google_census_Resource_google_census_Resource_MeasurementUnit_google_census_AggregationDescriptor_google_census_AggregationDescriptor_BucketBoundaries_google_census_AggregationDescriptor_IntervalBoundaries_google_census_Distribution_google_census_Distribution_Range_google_census_IntervalStats_google_census_IntervalStats_Window_google_census_Tag_google_census_View_google_census_Aggregation_google_census_Metric) #endif #if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) /* If you get an error here, it means that you need to define PB_FIELD_16BIT * compile-time option. You can do that in pb.h or on compiler command line. * * The reason you need to do this is that some of your messages contain tag * numbers or field sizes that are larger than what can fit in the default * 8 bit descriptors. */ PB_STATIC_ASSERT((pb_membersize(google_census_Resource, unit) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Resource, unit) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Distribution, range) < 256 && pb_membersize(google_census_IntervalStats, window) < 256 && pb_membersize(google_census_IntervalStats_Window, window_size) < 256 && pb_membersize(google_census_View, aggregation) < 256 && pb_membersize(google_census_Aggregation, data.distribution) < 256 && pb_membersize(google_census_Aggregation, data.interval_stats) < 256 && pb_membersize(google_census_Resource, unit) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Resource, unit) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Distribution, range) < 256 && pb_membersize(google_census_IntervalStats, window) < 256 && pb_membersize(google_census_IntervalStats_Window, window_size) < 256 && pb_membersize(google_census_View, aggregation) < 256 && pb_membersize(google_census_Aggregation, data.distribution) < 256 && pb_membersize(google_census_Aggregation, data.interval_stats) < 256 && pb_membersize(google_census_Aggregation, tag) < 256 && pb_membersize(google_census_Metric, aggregation) < 256 && pb_membersize(google_census_Metric, start) < 256 && pb_membersize(google_census_Metric, end) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_google_census_Duration_google_census_Timestamp_google_census_Resource_google_census_Resource_MeasurementUnit_google_census_AggregationDescriptor_google_census_AggregationDescriptor_BucketBoundaries_google_census_AggregationDescriptor_IntervalBoundaries_google_census_Distribution_google_census_Distribution_Range_google_census_IntervalStats_google_census_IntervalStats_Window_google_census_Tag_google_census_View_google_census_Aggregation_google_census_Metric) #endif /* On some platforms (such as AVR), double is really float. * These are not directly supported by nanopb, but see example_avr_double. * To get rid of this error, remove any double fields from your .proto. */ PB_STATIC_ASSERT(sizeof(double) == 8, DOUBLE_MUST_BE_8_BYTES) grpc-1.3.2/src/core/ext/census/gen/census.pb.h000066400000000000000000000315721310511640000211100ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* Automatically generated nanopb header */ /* Generated by nanopb-0.3.5-dev */ #ifndef GRPC_CORE_EXT_CENSUS_GEN_CENSUS_PB_H #define GRPC_CORE_EXT_CENSUS_GEN_CENSUS_PB_H #include "third_party/nanopb/pb.h" #if PB_PROTO_HEADER_VERSION != 30 #error Regenerate this file with the current version of nanopb generator. #endif #ifdef __cplusplus extern "C" { #endif /* Enum definitions */ typedef enum _google_census_Resource_BasicUnit { google_census_Resource_BasicUnit_UNKNOWN = 0, google_census_Resource_BasicUnit_BITS = 1, google_census_Resource_BasicUnit_BYTES = 2, google_census_Resource_BasicUnit_SECS = 3, google_census_Resource_BasicUnit_CORES = 4, google_census_Resource_BasicUnit_MAX_UNITS = 5 } google_census_Resource_BasicUnit; typedef enum _google_census_AggregationDescriptor_AggregationType { google_census_AggregationDescriptor_AggregationType_UNKNOWN = 0, google_census_AggregationDescriptor_AggregationType_COUNT = 1, google_census_AggregationDescriptor_AggregationType_DISTRIBUTION = 2, google_census_AggregationDescriptor_AggregationType_INTERVAL = 3 } google_census_AggregationDescriptor_AggregationType; /* Struct definitions */ typedef struct _google_census_AggregationDescriptor_BucketBoundaries { pb_callback_t bounds; } google_census_AggregationDescriptor_BucketBoundaries; typedef struct _google_census_AggregationDescriptor_IntervalBoundaries { pb_callback_t window_size; } google_census_AggregationDescriptor_IntervalBoundaries; typedef struct _google_census_IntervalStats { pb_callback_t window; } google_census_IntervalStats; typedef struct _google_census_AggregationDescriptor { bool has_type; google_census_AggregationDescriptor_AggregationType type; pb_size_t which_options; union { google_census_AggregationDescriptor_BucketBoundaries bucket_boundaries; google_census_AggregationDescriptor_IntervalBoundaries interval_boundaries; } options; } google_census_AggregationDescriptor; typedef struct _google_census_Distribution_Range { bool has_min; double min; bool has_max; double max; } google_census_Distribution_Range; typedef struct _google_census_Duration { bool has_seconds; int64_t seconds; bool has_nanos; int32_t nanos; } google_census_Duration; typedef struct _google_census_Resource_MeasurementUnit { bool has_prefix; int32_t prefix; pb_callback_t numerator; pb_callback_t denominator; } google_census_Resource_MeasurementUnit; typedef struct _google_census_Tag { bool has_key; char key[255]; bool has_value; char value[255]; } google_census_Tag; typedef struct _google_census_Timestamp { bool has_seconds; int64_t seconds; bool has_nanos; int32_t nanos; } google_census_Timestamp; typedef struct _google_census_Distribution { bool has_count; int64_t count; bool has_mean; double mean; bool has_range; google_census_Distribution_Range range; pb_callback_t bucket_count; } google_census_Distribution; typedef struct _google_census_IntervalStats_Window { bool has_window_size; google_census_Duration window_size; bool has_count; int64_t count; bool has_mean; double mean; } google_census_IntervalStats_Window; typedef struct _google_census_Metric { pb_callback_t view_name; pb_callback_t aggregation; bool has_start; google_census_Timestamp start; bool has_end; google_census_Timestamp end; } google_census_Metric; typedef struct _google_census_Resource { pb_callback_t name; pb_callback_t description; bool has_unit; google_census_Resource_MeasurementUnit unit; } google_census_Resource; typedef struct _google_census_View { pb_callback_t name; pb_callback_t description; pb_callback_t resource_name; bool has_aggregation; google_census_AggregationDescriptor aggregation; pb_callback_t tag_key; } google_census_View; typedef struct _google_census_Aggregation { pb_callback_t name; pb_callback_t description; pb_size_t which_data; union { uint64_t count; google_census_Distribution distribution; google_census_IntervalStats interval_stats; } data; pb_callback_t tag; } google_census_Aggregation; /* Default values for struct fields */ /* Initializer values for message structs */ #define google_census_Duration_init_default {false, 0, false, 0} #define google_census_Timestamp_init_default {false, 0, false, 0} #define google_census_Resource_init_default {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Resource_MeasurementUnit_init_default} #define google_census_Resource_MeasurementUnit_init_default {false, 0, {{NULL}, NULL}, {{NULL}, NULL}} #define google_census_AggregationDescriptor_init_default {false, (google_census_AggregationDescriptor_AggregationType)0, 0, {google_census_AggregationDescriptor_BucketBoundaries_init_default}} #define google_census_AggregationDescriptor_BucketBoundaries_init_default {{{NULL}, NULL}} #define google_census_AggregationDescriptor_IntervalBoundaries_init_default {{{NULL}, NULL}} #define google_census_Distribution_init_default {false, 0, false, 0, false, google_census_Distribution_Range_init_default, {{NULL}, NULL}} #define google_census_Distribution_Range_init_default {false, 0, false, 0} #define google_census_IntervalStats_init_default {{{NULL}, NULL}} #define google_census_IntervalStats_Window_init_default {false, google_census_Duration_init_default, false, 0, false, 0} #define google_census_Tag_init_default {false, "", false, ""} #define google_census_View_init_default {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, false, google_census_AggregationDescriptor_init_default, {{NULL}, NULL}} #define google_census_Aggregation_init_default {{{NULL}, NULL}, {{NULL}, NULL}, 0, {0}, {{NULL}, NULL}} #define google_census_Metric_init_default {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Timestamp_init_default, false, google_census_Timestamp_init_default} #define google_census_Duration_init_zero {false, 0, false, 0} #define google_census_Timestamp_init_zero {false, 0, false, 0} #define google_census_Resource_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Resource_MeasurementUnit_init_zero} #define google_census_Resource_MeasurementUnit_init_zero {false, 0, {{NULL}, NULL}, {{NULL}, NULL}} #define google_census_AggregationDescriptor_init_zero {false, (google_census_AggregationDescriptor_AggregationType)0, 0, {google_census_AggregationDescriptor_BucketBoundaries_init_zero}} #define google_census_AggregationDescriptor_BucketBoundaries_init_zero {{{NULL}, NULL}} #define google_census_AggregationDescriptor_IntervalBoundaries_init_zero {{{NULL}, NULL}} #define google_census_Distribution_init_zero {false, 0, false, 0, false, google_census_Distribution_Range_init_zero, {{NULL}, NULL}} #define google_census_Distribution_Range_init_zero {false, 0, false, 0} #define google_census_IntervalStats_init_zero {{{NULL}, NULL}} #define google_census_IntervalStats_Window_init_zero {false, google_census_Duration_init_zero, false, 0, false, 0} #define google_census_Tag_init_zero {false, "", false, ""} #define google_census_View_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, false, google_census_AggregationDescriptor_init_zero, {{NULL}, NULL}} #define google_census_Aggregation_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, 0, {0}, {{NULL}, NULL}} #define google_census_Metric_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Timestamp_init_zero, false, google_census_Timestamp_init_zero} /* Field tags (for use in manual encoding/decoding) */ #define google_census_AggregationDescriptor_BucketBoundaries_bounds_tag 1 #define google_census_AggregationDescriptor_IntervalBoundaries_window_size_tag 1 #define google_census_IntervalStats_window_tag 1 #define google_census_AggregationDescriptor_bucket_boundaries_tag 2 #define google_census_AggregationDescriptor_interval_boundaries_tag 3 #define google_census_AggregationDescriptor_type_tag 1 #define google_census_Distribution_Range_min_tag 1 #define google_census_Distribution_Range_max_tag 2 #define google_census_Duration_seconds_tag 1 #define google_census_Duration_nanos_tag 2 #define google_census_Resource_MeasurementUnit_prefix_tag 1 #define google_census_Resource_MeasurementUnit_numerator_tag 2 #define google_census_Resource_MeasurementUnit_denominator_tag 3 #define google_census_Tag_key_tag 1 #define google_census_Tag_value_tag 2 #define google_census_Timestamp_seconds_tag 1 #define google_census_Timestamp_nanos_tag 2 #define google_census_Distribution_count_tag 1 #define google_census_Distribution_mean_tag 2 #define google_census_Distribution_range_tag 3 #define google_census_Distribution_bucket_count_tag 4 #define google_census_IntervalStats_Window_window_size_tag 1 #define google_census_IntervalStats_Window_count_tag 2 #define google_census_IntervalStats_Window_mean_tag 3 #define google_census_Metric_view_name_tag 1 #define google_census_Metric_aggregation_tag 2 #define google_census_Metric_start_tag 3 #define google_census_Metric_end_tag 4 #define google_census_Resource_name_tag 1 #define google_census_Resource_description_tag 2 #define google_census_Resource_unit_tag 3 #define google_census_View_name_tag 1 #define google_census_View_description_tag 2 #define google_census_View_resource_name_tag 3 #define google_census_View_aggregation_tag 4 #define google_census_View_tag_key_tag 5 #define google_census_Aggregation_count_tag 3 #define google_census_Aggregation_distribution_tag 4 #define google_census_Aggregation_interval_stats_tag 5 #define google_census_Aggregation_name_tag 1 #define google_census_Aggregation_description_tag 2 #define google_census_Aggregation_tag_tag 6 /* Struct field encoding specification for nanopb */ extern const pb_field_t google_census_Duration_fields[3]; extern const pb_field_t google_census_Timestamp_fields[3]; extern const pb_field_t google_census_Resource_fields[4]; extern const pb_field_t google_census_Resource_MeasurementUnit_fields[4]; extern const pb_field_t google_census_AggregationDescriptor_fields[4]; extern const pb_field_t google_census_AggregationDescriptor_BucketBoundaries_fields[2]; extern const pb_field_t google_census_AggregationDescriptor_IntervalBoundaries_fields[2]; extern const pb_field_t google_census_Distribution_fields[5]; extern const pb_field_t google_census_Distribution_Range_fields[3]; extern const pb_field_t google_census_IntervalStats_fields[2]; extern const pb_field_t google_census_IntervalStats_Window_fields[4]; extern const pb_field_t google_census_Tag_fields[3]; extern const pb_field_t google_census_View_fields[6]; extern const pb_field_t google_census_Aggregation_fields[7]; extern const pb_field_t google_census_Metric_fields[5]; /* Maximum encoded size of messages (where known) */ #define google_census_Duration_size 22 #define google_census_Timestamp_size 22 #define google_census_Distribution_Range_size 18 #define google_census_IntervalStats_Window_size 44 #define google_census_Tag_size 516 /* Message IDs (where set with "msgid" option) */ #ifdef PB_MSGID #define CENSUS_MESSAGES \ #endif #ifdef __cplusplus } /* extern "C" */ #endif #endif /* GRPC_CORE_EXT_CENSUS_GEN_CENSUS_PB_H */ grpc-1.3.2/src/core/ext/census/gen/trace_context.pb.c000066400000000000000000000046401310511640000224410ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* Automatically generated nanopb constant definitions */ /* Generated by nanopb-0.3.7-dev at Fri Jan 20 16:14:22 2017. */ #include "src/core/ext/census/gen/trace_context.pb.h" /* @@protoc_insertion_point(includes) */ #if PB_PROTO_HEADER_VERSION != 30 #error Regenerate this file with the current version of nanopb generator. #endif const pb_field_t google_trace_TraceContext_fields[5] = { PB_FIELD( 1, FIXED64 , OPTIONAL, STATIC , FIRST, google_trace_TraceContext, trace_id_hi, trace_id_hi, 0), PB_FIELD( 2, FIXED64 , OPTIONAL, STATIC , OTHER, google_trace_TraceContext, trace_id_lo, trace_id_hi, 0), PB_FIELD( 3, FIXED64 , OPTIONAL, STATIC , OTHER, google_trace_TraceContext, span_id, trace_id_lo, 0), PB_FIELD( 4, FIXED32 , OPTIONAL, STATIC , OTHER, google_trace_TraceContext, span_options, span_id, 0), PB_LAST_FIELD }; /* @@protoc_insertion_point(eof) */ grpc-1.3.2/src/core/ext/census/gen/trace_context.pb.h000066400000000000000000000064661310511640000224560ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* Automatically generated nanopb header */ /* Generated by nanopb-0.3.7-dev at Fri Jan 20 16:14:22 2017. */ #ifndef GRPC_CORE_EXT_CENSUS_GEN_TRACE_CONTEXT_PB_H #define GRPC_CORE_EXT_CENSUS_GEN_TRACE_CONTEXT_PB_H #include "third_party/nanopb/pb.h" /* @@protoc_insertion_point(includes) */ #if PB_PROTO_HEADER_VERSION != 30 #error Regenerate this file with the current version of nanopb generator. #endif #ifdef __cplusplus extern "C" { #endif /* Struct definitions */ typedef struct _google_trace_TraceContext { bool has_trace_id_hi; uint64_t trace_id_hi; bool has_trace_id_lo; uint64_t trace_id_lo; bool has_span_id; uint64_t span_id; bool has_span_options; uint32_t span_options; /* @@protoc_insertion_point(struct:google_trace_TraceContext) */ } google_trace_TraceContext; /* Default values for struct fields */ /* Initializer values for message structs */ #define google_trace_TraceContext_init_default {false, 0, false, 0, false, 0, false, 0} #define google_trace_TraceContext_init_zero {false, 0, false, 0, false, 0, false, 0} /* Field tags (for use in manual encoding/decoding) */ #define google_trace_TraceContext_trace_id_hi_tag 1 #define google_trace_TraceContext_trace_id_lo_tag 2 #define google_trace_TraceContext_span_id_tag 3 #define google_trace_TraceContext_span_options_tag 4 /* Struct field encoding specification for nanopb */ extern const pb_field_t google_trace_TraceContext_fields[5]; /* Maximum encoded size of messages (where known) */ #define google_trace_TraceContext_size 32 /* Message IDs (where set with "msgid" option) */ #ifdef PB_MSGID #define TRACE_CONTEXT_MESSAGES \ #endif #ifdef __cplusplus } /* extern "C" */ #endif /* @@protoc_insertion_point(eof) */ #endif /* GRPC_CORE_EXT_CENSUS_GEN_TRACE_CONTEXT_PB_H */ grpc-1.3.2/src/core/ext/census/grpc_context.c000066400000000000000000000043441310511640000211260ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/call.h" void grpc_census_call_set_context(grpc_call *call, census_context *context) { GRPC_API_TRACE("grpc_census_call_set_context(call=%p, census_context=%p)", 2, (call, context)); if (census_enabled() == CENSUS_FEATURE_NONE) { return; } if (context != NULL) { grpc_call_context_set(call, GRPC_CONTEXT_TRACING, context, NULL); } } census_context *grpc_census_call_get_context(grpc_call *call) { GRPC_API_TRACE("grpc_census_call_get_context(call=%p)", 1, (call)); return (census_context *)grpc_call_context_get(call, GRPC_CONTEXT_TRACING); } grpc-1.3.2/src/core/ext/census/grpc_filter.c000066400000000000000000000175041310511640000207310ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/census/grpc_filter.h" #include #include #include #include #include #include #include #include "src/core/ext/census/census_interface.h" #include "src/core/ext/census/census_rpc_stats.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/transport/static_metadata.h" typedef struct call_data { census_op_id op_id; census_context *ctxt; gpr_timespec start_ts; int error; /* recv callback */ grpc_metadata_batch *recv_initial_metadata; grpc_closure *on_done_recv; grpc_closure finish_recv; } call_data; typedef struct channel_data { uint8_t unused; } channel_data; static void extract_and_annotate_method_tag(grpc_metadata_batch *md, call_data *calld, channel_data *chand) { grpc_linked_mdelem *m; for (m = md->list.head; m != NULL; m = m->next) { if (grpc_slice_eq(GRPC_MDKEY(m->md), GRPC_MDSTR_PATH)) { /* Add method tag here */ } } } static void client_mutate_op(grpc_call_element *elem, grpc_transport_stream_op_batch *op) { call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; if (op->send_initial_metadata) { extract_and_annotate_method_tag( op->payload->send_initial_metadata.send_initial_metadata, calld, chand); } } static void client_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op_batch *op) { client_mutate_op(elem, op); grpc_call_next_op(exec_ctx, elem, op); } static void server_on_done_recv(grpc_exec_ctx *exec_ctx, void *ptr, grpc_error *error) { GPR_TIMER_BEGIN("census-server:server_on_done_recv", 0); grpc_call_element *elem = ptr; call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; if (error == GRPC_ERROR_NONE) { extract_and_annotate_method_tag(calld->recv_initial_metadata, calld, chand); } calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, error); GPR_TIMER_END("census-server:server_on_done_recv", 0); } static void server_mutate_op(grpc_call_element *elem, grpc_transport_stream_op_batch *op) { call_data *calld = elem->call_data; if (op->recv_initial_metadata) { /* substitute our callback for the op callback */ calld->recv_initial_metadata = op->payload->recv_initial_metadata.recv_initial_metadata; calld->on_done_recv = op->payload->recv_initial_metadata.recv_initial_metadata_ready; op->payload->recv_initial_metadata.recv_initial_metadata_ready = &calld->finish_recv; } } static void server_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op_batch *op) { /* TODO(ctiller): this code fails. I don't know why. I expect it's incomplete, and someone should look at it soon. call_data *calld = elem->call_data; GPR_ASSERT((calld->op_id.upper != 0) || (calld->op_id.lower != 0)); */ server_mutate_op(elem, op); grpc_call_next_op(exec_ctx, elem, op); } static grpc_error *client_init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_element_args *args) { call_data *d = elem->call_data; GPR_ASSERT(d != NULL); memset(d, 0, sizeof(*d)); d->start_ts = args->start_time; return GRPC_ERROR_NONE; } static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, grpc_closure *ignored) { call_data *d = elem->call_data; GPR_ASSERT(d != NULL); /* TODO(hongyu): record rpc client stats and census_rpc_end_op here */ } static grpc_error *server_init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_element_args *args) { call_data *d = elem->call_data; GPR_ASSERT(d != NULL); memset(d, 0, sizeof(*d)); d->start_ts = args->start_time; /* TODO(hongyu): call census_tracing_start_op here. */ grpc_closure_init(&d->finish_recv, server_on_done_recv, elem, grpc_schedule_on_exec_ctx); return GRPC_ERROR_NONE; } static void server_destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, grpc_closure *ignored) { call_data *d = elem->call_data; GPR_ASSERT(d != NULL); /* TODO(hongyu): record rpc server stats and census_tracing_end_op here */ } static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_channel_element_args *args) { channel_data *chand = elem->channel_data; GPR_ASSERT(chand != NULL); return GRPC_ERROR_NONE; } static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) { channel_data *chand = elem->channel_data; GPR_ASSERT(chand != NULL); } const grpc_channel_filter grpc_client_census_filter = { client_start_transport_op, grpc_channel_next_op, sizeof(call_data), client_init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, client_destroy_call_elem, sizeof(channel_data), init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer, grpc_channel_next_get_info, "census-client"}; const grpc_channel_filter grpc_server_census_filter = { server_start_transport_op, grpc_channel_next_op, sizeof(call_data), server_init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, server_destroy_call_elem, sizeof(channel_data), init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer, grpc_channel_next_get_info, "census-server"}; grpc-1.3.2/src/core/ext/census/grpc_filter.h000066400000000000000000000037531310511640000207370ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_CENSUS_GRPC_FILTER_H #define GRPC_CORE_EXT_CENSUS_GRPC_FILTER_H #include "src/core/lib/channel/channel_stack.h" /* Census filters: provides tracing and stats collection functionalities. It needs to reside right below the surface filter in the channel stack. */ extern const grpc_channel_filter grpc_client_census_filter; extern const grpc_channel_filter grpc_server_census_filter; #endif /* GRPC_CORE_EXT_CENSUS_GRPC_FILTER_H */ grpc-1.3.2/src/core/ext/census/grpc_plugin.c000066400000000000000000000066021310511640000207370ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include "src/core/ext/census/grpc_filter.h" #include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/surface/channel_init.h" static bool is_census_enabled(const grpc_channel_args *a) { size_t i; if (a == NULL) return 0; for (i = 0; i < a->num_args; i++) { if (0 == strcmp(a->args[i].key, GRPC_ARG_ENABLE_CENSUS)) { return a->args[i].value.integer != 0 && census_enabled(); } } return census_enabled() && !grpc_channel_args_want_minimal_stack(a); } static bool maybe_add_census_filter(grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, void *arg) { const grpc_channel_args *args = grpc_channel_stack_builder_get_channel_arguments(builder); if (is_census_enabled(args)) { return grpc_channel_stack_builder_prepend_filter( builder, (const grpc_channel_filter *)arg, NULL, NULL); } return true; } void census_grpc_plugin_init(void) { /* Only initialize census if no one else has and some features are * available. */ if (census_enabled() == CENSUS_FEATURE_NONE && census_supported() != CENSUS_FEATURE_NONE) { if (census_initialize(census_supported())) { /* enable all features. */ gpr_log(GPR_ERROR, "Could not initialize census."); } } grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, maybe_add_census_filter, (void *)&grpc_client_census_filter); grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, maybe_add_census_filter, (void *)&grpc_server_census_filter); } void census_grpc_plugin_shutdown(void) { census_shutdown(); } grpc-1.3.2/src/core/ext/census/hash_table.c000066400000000000000000000221631310511640000205200ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/census/hash_table.h" #include #include #include #include #include #define CENSUS_HT_NUM_BUCKETS 1999 /* A single hash table data entry */ typedef struct ht_entry { census_ht_key key; void *data; struct ht_entry *next; } ht_entry; /* hash table bucket */ typedef struct bucket { /* NULL if bucket is empty */ ht_entry *next; /* -1 if all buckets are empty. */ int32_t prev_non_empty_bucket; /* -1 if all buckets are empty. */ int32_t next_non_empty_bucket; } bucket; struct unresizable_hash_table { /* Number of entries in the table */ size_t size; /* Number of buckets */ uint32_t num_buckets; /* Array of buckets initialized at creation time. Memory consumption is 16 bytes per bucket on a 64-bit platform. */ bucket *buckets; /* Index of the first non-empty bucket. -1 iff size == 0. */ int32_t first_non_empty_bucket; /* Index of the last non_empty bucket. -1 iff size == 0. */ int32_t last_non_empty_bucket; /* Immutable options of this hash table, initialized at creation time. */ census_ht_option options; }; typedef struct entry_locator { int32_t bucket_idx; int is_first_in_chain; int found; ht_entry *prev_entry; } entry_locator; /* Asserts if option is not valid. */ void check_options(const census_ht_option *option) { GPR_ASSERT(option != NULL); GPR_ASSERT(option->num_buckets > 0); GPR_ASSERT(option->key_type == CENSUS_HT_UINT64 || option->key_type == CENSUS_HT_POINTER); if (option->key_type == CENSUS_HT_UINT64) { GPR_ASSERT(option->hash == NULL); } else if (option->key_type == CENSUS_HT_POINTER) { GPR_ASSERT(option->hash != NULL); GPR_ASSERT(option->compare_keys != NULL); } } #define REMOVE_NEXT(options, ptr) \ do { \ ht_entry *tmp = (ptr)->next; \ (ptr)->next = tmp->next; \ delete_entry(options, tmp); \ } while (0) static void delete_entry(const census_ht_option *opt, ht_entry *p) { if (opt->delete_data != NULL) { opt->delete_data(p->data); } if (opt->delete_key != NULL) { opt->delete_key(p->key.ptr); } gpr_free(p); } static uint64_t hash(const census_ht_option *opt, census_ht_key key) { return opt->key_type == CENSUS_HT_UINT64 ? key.val : opt->hash(key.ptr); } census_ht *census_ht_create(const census_ht_option *option) { int i; census_ht *ret = NULL; check_options(option); ret = (census_ht *)gpr_malloc(sizeof(census_ht)); ret->size = 0; ret->num_buckets = option->num_buckets; ret->buckets = (bucket *)gpr_malloc(sizeof(bucket) * ret->num_buckets); ret->options = *option; /* initialize each bucket */ for (i = 0; i < ret->options.num_buckets; i++) { ret->buckets[i].prev_non_empty_bucket = -1; ret->buckets[i].next_non_empty_bucket = -1; ret->buckets[i].next = NULL; } return ret; } static int32_t find_bucket_idx(const census_ht *ht, census_ht_key key) { return hash(&ht->options, key) % ht->num_buckets; } static int keys_match(const census_ht_option *opt, const ht_entry *p, const census_ht_key key) { GPR_ASSERT(opt->key_type == CENSUS_HT_UINT64 || opt->key_type == CENSUS_HT_POINTER); if (opt->key_type == CENSUS_HT_UINT64) return p->key.val == key.val; return !opt->compare_keys((p->key).ptr, key.ptr); } static entry_locator ht_find(const census_ht *ht, census_ht_key key) { entry_locator loc = {0, 0, 0, NULL}; int32_t idx = 0; ht_entry *ptr = NULL; GPR_ASSERT(ht != NULL); idx = find_bucket_idx(ht, key); ptr = ht->buckets[idx].next; if (ptr == NULL) { /* bucket is empty */ return loc; } if (keys_match(&ht->options, ptr, key)) { loc.bucket_idx = idx; loc.is_first_in_chain = 1; loc.found = 1; return loc; } else { for (; ptr->next != NULL; ptr = ptr->next) { if (keys_match(&ht->options, ptr->next, key)) { loc.bucket_idx = idx; loc.is_first_in_chain = 0; loc.found = 1; loc.prev_entry = ptr; return loc; } } } /* Could not find the key */ return loc; } void *census_ht_find(const census_ht *ht, census_ht_key key) { entry_locator loc = ht_find(ht, key); if (loc.found == 0) { return NULL; } return loc.is_first_in_chain ? ht->buckets[loc.bucket_idx].next->data : loc.prev_entry->next->data; } void census_ht_insert(census_ht *ht, census_ht_key key, void *data) { int32_t idx = find_bucket_idx(ht, key); ht_entry *ptr = NULL; entry_locator loc = ht_find(ht, key); if (loc.found) { /* Replace old value with new value. */ ptr = loc.is_first_in_chain ? ht->buckets[loc.bucket_idx].next : loc.prev_entry->next; if (ht->options.delete_data != NULL) { ht->options.delete_data(ptr->data); } ptr->data = data; return; } /* first entry in the table. */ if (ht->size == 0) { ht->buckets[idx].next_non_empty_bucket = -1; ht->buckets[idx].prev_non_empty_bucket = -1; ht->first_non_empty_bucket = idx; ht->last_non_empty_bucket = idx; } else if (ht->buckets[idx].next == NULL) { /* first entry in the bucket. */ ht->buckets[ht->last_non_empty_bucket].next_non_empty_bucket = idx; ht->buckets[idx].prev_non_empty_bucket = ht->last_non_empty_bucket; ht->buckets[idx].next_non_empty_bucket = -1; ht->last_non_empty_bucket = idx; } ptr = (ht_entry *)gpr_malloc(sizeof(ht_entry)); ptr->key = key; ptr->data = data; ptr->next = ht->buckets[idx].next; ht->buckets[idx].next = ptr; ht->size++; } void census_ht_erase(census_ht *ht, census_ht_key key) { entry_locator loc = ht_find(ht, key); if (loc.found == 0) { /* noop if not found */ return; } ht->size--; if (loc.is_first_in_chain) { bucket *b = &ht->buckets[loc.bucket_idx]; GPR_ASSERT(b->next != NULL); /* The only entry in the bucket */ if (b->next->next == NULL) { int prev = b->prev_non_empty_bucket; int next = b->next_non_empty_bucket; if (prev != -1) { ht->buckets[prev].next_non_empty_bucket = next; } else { ht->first_non_empty_bucket = next; } if (next != -1) { ht->buckets[next].prev_non_empty_bucket = prev; } else { ht->last_non_empty_bucket = prev; } } REMOVE_NEXT(&ht->options, b); } else { GPR_ASSERT(loc.prev_entry->next != NULL); REMOVE_NEXT(&ht->options, loc.prev_entry); } } /* Returns NULL if input table is empty. */ census_ht_kv *census_ht_get_all_elements(const census_ht *ht, size_t *num) { census_ht_kv *ret = NULL; int i = 0; int32_t idx = -1; GPR_ASSERT(ht != NULL && num != NULL); *num = ht->size; if (*num == 0) { return NULL; } ret = (census_ht_kv *)gpr_malloc(sizeof(census_ht_kv) * ht->size); idx = ht->first_non_empty_bucket; while (idx >= 0) { ht_entry *ptr = ht->buckets[idx].next; for (; ptr != NULL; ptr = ptr->next) { ret[i].k = ptr->key; ret[i].v = ptr->data; i++; } idx = ht->buckets[idx].next_non_empty_bucket; } return ret; } static void ht_delete_entry_chain(const census_ht_option *options, ht_entry *first) { if (first == NULL) { return; } if (first->next != NULL) { ht_delete_entry_chain(options, first->next); } delete_entry(options, first); } void census_ht_destroy(census_ht *ht) { unsigned i; for (i = 0; i < ht->num_buckets; ++i) { ht_delete_entry_chain(&ht->options, ht->buckets[i].next); } gpr_free(ht->buckets); gpr_free(ht); } size_t census_ht_get_size(const census_ht *ht) { return ht->size; } grpc-1.3.2/src/core/ext/census/hash_table.h000066400000000000000000000125551310511640000205310ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_CENSUS_HASH_TABLE_H #define GRPC_CORE_EXT_CENSUS_HASH_TABLE_H #include #include /* A chain based hash table with fixed number of buckets. Your probably shouldn't use this code directly. It is implemented for the use case in census trace store and stats store, where number of entries in the table is in the scale of upto several thousands, entries are added and removed from the table very frequently (~100k/s), the frequency of find() operations is roughly several times of the frequency of insert() and erase() Comparing to find(), the insert(), erase() and get_all_entries() operations are much less freqent (<1/s). Per bucket memory overhead is about (8 + sizeof(intptr_t) bytes. Per entry memory overhead is about (8 + 2 * sizeof(intptr_t) bytes. All functions are not thread-safe. Synchronization will be provided in the upper layer (in trace store and stats store). */ /* Opaque hash table struct */ typedef struct unresizable_hash_table census_ht; /* Currently, the hash_table can take two types of keys. (uint64 for trace store and const char* for stats store). */ typedef union { uint64_t val; void *ptr; } census_ht_key; typedef enum census_ht_key_type { CENSUS_HT_UINT64 = 0, CENSUS_HT_POINTER = 1 } census_ht_key_type; typedef struct census_ht_option { /* Type of hash key */ census_ht_key_type key_type; /* Desired number of buckets, preferably a prime number */ int32_t num_buckets; /* Fucntion to calculate uint64 hash value of the key. Only takes effect if key_type is POINTER. */ uint64_t (*hash)(const void *); /* Function to compare two keys, returns 0 iff equal. Only takes effect if key_type is POINTER */ int (*compare_keys)(const void *k1, const void *k2); /* Value deleter. NULL if no specialized delete function is needed. */ void (*delete_data)(void *); /* Key deleter. NULL if table does not own the key. (e.g. key is part of the value or key is not owned by the table.) */ void (*delete_key)(void *); } census_ht_option; /* Creates a hashtable with fixed number of buckets according to the settings specified in 'options' arg. Function pointers "hash" and "compare_keys" must be provided if key_type is POINTER. Asserts if fail to create. */ census_ht *census_ht_create(const census_ht_option *options); /* Deletes hash table instance. Frees all dynamic memory owned by ht.*/ void census_ht_destroy(census_ht *ht); /* Inserts the input key-val pair into hash_table. If an entry with the same key exists in the table, the corresponding value will be overwritten by the input val. */ void census_ht_insert(census_ht *ht, census_ht_key key, void *val); /* Returns pointer to data, returns NULL if not found. */ void *census_ht_find(const census_ht *ht, census_ht_key key); /* Erase hash table entry with input key. Noop if key is not found. */ void census_ht_erase(census_ht *ht, census_ht_key key); typedef struct census_ht_kv { census_ht_key k; void *v; } census_ht_kv; /* Returns an array of pointers to all values in the hash table. Order of the elements can be arbitrary. Sets 'num' to the size of returned array. Caller owns returned array. */ census_ht_kv *census_ht_get_all_elements(const census_ht *ht, size_t *num); /* Returns number of elements kept. */ size_t census_ht_get_size(const census_ht *ht); /* Functor applied on each key-value pair while iterating through entries in the table. The functor should not mutate data. */ typedef void (*census_ht_itr_cb)(census_ht_key key, const void *val_ptr, void *state); /* Iterates through all key-value pairs in the hash_table. The callback function should not invalidate data entries. */ uint64_t census_ht_for_all(const census_ht *ht, census_ht_itr_cb); #endif /* GRPC_CORE_EXT_CENSUS_HASH_TABLE_H */ grpc-1.3.2/src/core/ext/census/initialize.c000066400000000000000000000046031310511640000205660ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "src/core/ext/census/base_resources.h" #include "src/core/ext/census/resource.h" static int features_enabled = CENSUS_FEATURE_NONE; int census_initialize(int features) { if (features_enabled != CENSUS_FEATURE_NONE) { // Must have been a previous call to census_initialize; return error return -1; } features_enabled = features & CENSUS_FEATURE_ALL; if (features & CENSUS_FEATURE_STATS) { initialize_resources(); define_base_resources(); } return features_enabled; } void census_shutdown(void) { if (features_enabled & CENSUS_FEATURE_STATS) { shutdown_resources(); } features_enabled = CENSUS_FEATURE_NONE; } int census_supported(void) { /* TODO(aveitch): improve this as we implement features... */ return CENSUS_FEATURE_NONE; } int census_enabled(void) { return features_enabled; } grpc-1.3.2/src/core/ext/census/mlog.c000066400000000000000000000530611310511640000173650ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ // Implements an efficient in-memory log, optimized for multiple writers and // a single reader. Available log space is divided up in blocks of // CENSUS_LOG_2_MAX_RECORD_SIZE bytes. A block can be in one of the following // three data structures: // - Free blocks (free_block_list) // - Blocks with unread data (dirty_block_list) // - Blocks currently attached to cores (core_local_blocks[]) // // census_log_start_write() moves a block from core_local_blocks[] to the end of // dirty_block_list when block: // - is out-of-space OR // - has an incomplete record (an incomplete record occurs when a thread calls // census_log_start_write() and is context-switched before calling // census_log_end_write() // So, blocks in dirty_block_list are ordered, from oldest to newest, by the // time when block is detached from the core. // // census_log_read_next() first iterates over dirty_block_list and then // core_local_blocks[]. It moves completely read blocks from dirty_block_list // to free_block_list. Blocks in core_local_blocks[] are not freed, even when // completely read. // // If the log is configured to discard old records and free_block_list is empty, // census_log_start_write() iterates over dirty_block_list to allocate a // new block. It moves the oldest available block (no pending read/write) to // core_local_blocks[]. // // core_local_block_struct is used to implement a map from core id to the block // associated with that core. This mapping is advisory. It is possible that the // block returned by this mapping is no longer associated with that core. This // mapping is updated, lazily, by census_log_start_write(). // // Locking in block struct: // // Exclusive g_log.lock must be held before calling any functions operating on // block structs except census_log_start_write() and census_log_end_write(). // // Writes to a block are serialized via writer_lock. census_log_start_write() // acquires this lock and census_log_end_write() releases it. On failure to // acquire the lock, writer allocates a new block for the current core and // updates core_local_block accordingly. // // Simultaneous read and write access is allowed. Readers can safely read up to // committed bytes (bytes_committed). // // reader_lock protects the block, currently being read, from getting recycled. // start_read() acquires reader_lock and end_read() releases the lock. // // Read/write access to a block is disabled via try_disable_access(). It returns // with both writer_lock and reader_lock held. These locks are subsequently // released by enable_access() to enable access to the block. // // A note on naming: Most function/struct names are prepended by cl_ // (shorthand for census_log). Further, functions that manipulate structures // include the name of the structure, which will be passed as the first // argument. E.g. cl_block_initialize() will initialize a cl_block. #include "src/core/ext/census/mlog.h" #include #include #include #include #include #include #include #include // End of platform specific code typedef struct census_log_block_list_struct { struct census_log_block_list_struct* next; struct census_log_block_list_struct* prev; struct census_log_block* block; } cl_block_list_struct; typedef struct census_log_block { // Pointer to underlying buffer. char* buffer; gpr_atm writer_lock; gpr_atm reader_lock; // Keeps completely written bytes. Declared atomic because accessed // simultaneously by reader and writer. gpr_atm bytes_committed; // Bytes already read. size_t bytes_read; // Links for list. cl_block_list_struct link; // We want this structure to be cacheline aligned. We assume the following // sizes for the various parts on 32/64bit systems: // type 32b size 64b size // char* 4 8 // 3x gpr_atm 12 24 // size_t 4 8 // cl_block_list_struct 12 24 // TOTAL 32 64 // // Depending on the size of our cacheline and the architecture, we // selectively add char buffering to this structure. The size is checked // via assert in census_log_initialize(). #if defined(GPR_ARCH_64) #define CL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 64) #else #if defined(GPR_ARCH_32) #define CL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 32) #else #error "Unknown architecture" #endif #endif #if CL_BLOCK_PAD_SIZE > 0 char padding[CL_BLOCK_PAD_SIZE]; #endif } cl_block; // A list of cl_blocks, doubly-linked through cl_block::link. typedef struct census_log_block_list { int32_t count; // Number of items in list. cl_block_list_struct ht; // head/tail of linked list. } cl_block_list; // Cacheline aligned block pointers to avoid false sharing. Block pointer must // be initialized via set_block(), before calling other functions typedef struct census_log_core_local_block { gpr_atm block; // Ensure cachline alignment: we assume sizeof(gpr_atm) == 4 or 8 #if defined(GPR_ARCH_64) #define CL_CORE_LOCAL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 8) #else #if defined(GPR_ARCH_32) #define CL_CORE_LOCAL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 4) #else #error "Unknown architecture" #endif #endif #if CL_CORE_LOCAL_BLOCK_PAD_SIZE > 0 char padding[CL_CORE_LOCAL_BLOCK_PAD_SIZE]; #endif } cl_core_local_block; struct census_log { int discard_old_records; // Number of cores (aka hardware-contexts) unsigned num_cores; // number of CENSUS_LOG_2_MAX_RECORD_SIZE blocks in log uint32_t num_blocks; cl_block* blocks; // Block metadata. cl_core_local_block* core_local_blocks; // Keeps core to block mappings. gpr_mu lock; int initialized; // has log been initialized? // Keeps the state of the reader iterator. A value of 0 indicates that // iterator has reached the end. census_log_init_reader() resets the value // to num_core to restart iteration. uint32_t read_iterator_state; // Points to the block being read. If non-NULL, the block is locked for // reading(block_being_read_->reader_lock is held). cl_block* block_being_read; char* buffer; cl_block_list free_block_list; cl_block_list dirty_block_list; gpr_atm out_of_space_count; }; // Single internal log. static struct census_log g_log; // Functions that operate on an atomic memory location used as a lock. // Returns non-zero if lock is acquired. static int cl_try_lock(gpr_atm* lock) { return gpr_atm_acq_cas(lock, 0, 1); } static void cl_unlock(gpr_atm* lock) { gpr_atm_rel_store(lock, 0); } // Functions that operate on cl_core_local_block's. static void cl_core_local_block_set_block(cl_core_local_block* clb, cl_block* block) { gpr_atm_rel_store(&clb->block, (gpr_atm)block); } static cl_block* cl_core_local_block_get_block(cl_core_local_block* clb) { return (cl_block*)gpr_atm_acq_load(&clb->block); } // Functions that operate on cl_block_list_struct's. static void cl_block_list_struct_initialize(cl_block_list_struct* bls, cl_block* block) { bls->next = bls->prev = bls; bls->block = block; } // Functions that operate on cl_block_list's. static void cl_block_list_initialize(cl_block_list* list) { list->count = 0; cl_block_list_struct_initialize(&list->ht, NULL); } // Returns head of *this, or NULL if empty. static cl_block* cl_block_list_head(cl_block_list* list) { return list->ht.next->block; } // Insert element *e after *pos. static void cl_block_list_insert(cl_block_list* list, cl_block_list_struct* pos, cl_block_list_struct* e) { list->count++; e->next = pos->next; e->prev = pos; e->next->prev = e; e->prev->next = e; } // Insert block at the head of the list static void cl_block_list_insert_at_head(cl_block_list* list, cl_block* block) { cl_block_list_insert(list, &list->ht, &block->link); } // Insert block at the tail of the list. static void cl_block_list_insert_at_tail(cl_block_list* list, cl_block* block) { cl_block_list_insert(list, list->ht.prev, &block->link); } // Removes block *b. Requires *b be in the list. static void cl_block_list_remove(cl_block_list* list, cl_block* b) { list->count--; b->link.next->prev = b->link.prev; b->link.prev->next = b->link.next; } // Functions that operate on cl_block's static void cl_block_initialize(cl_block* block, char* buffer) { block->buffer = buffer; gpr_atm_rel_store(&block->writer_lock, 0); gpr_atm_rel_store(&block->reader_lock, 0); gpr_atm_rel_store(&block->bytes_committed, 0); block->bytes_read = 0; cl_block_list_struct_initialize(&block->link, block); } // Guards against exposing partially written buffer to the reader. static void cl_block_set_bytes_committed(cl_block* block, size_t bytes_committed) { gpr_atm_rel_store(&block->bytes_committed, (gpr_atm)bytes_committed); } static size_t cl_block_get_bytes_committed(cl_block* block) { return (size_t)gpr_atm_acq_load(&block->bytes_committed); } // Tries to disable future read/write access to this block. Succeeds if: // - no in-progress write AND // - no in-progress read AND // - 'discard_data' set to true OR no unread data // On success, clears the block state and returns with writer_lock_ and // reader_lock_ held. These locks are released by a subsequent // cl_block_access_enable() call. static bool cl_block_try_disable_access(cl_block* block, int discard_data) { if (!cl_try_lock(&block->writer_lock)) { return false; } if (!cl_try_lock(&block->reader_lock)) { cl_unlock(&block->writer_lock); return false; } if (!discard_data && (block->bytes_read != cl_block_get_bytes_committed(block))) { cl_unlock(&block->reader_lock); cl_unlock(&block->writer_lock); return false; } cl_block_set_bytes_committed(block, 0); block->bytes_read = 0; return true; } static void cl_block_enable_access(cl_block* block) { cl_unlock(&block->reader_lock); cl_unlock(&block->writer_lock); } // Returns with writer_lock held. static void* cl_block_start_write(cl_block* block, size_t size) { if (!cl_try_lock(&block->writer_lock)) { return NULL; } size_t bytes_committed = cl_block_get_bytes_committed(block); if (bytes_committed + size > CENSUS_LOG_MAX_RECORD_SIZE) { cl_unlock(&block->writer_lock); return NULL; } return block->buffer + bytes_committed; } // Releases writer_lock and increments committed bytes by 'bytes_written'. // 'bytes_written' must be <= 'size' specified in the corresponding // StartWrite() call. This function is thread-safe. static void cl_block_end_write(cl_block* block, size_t bytes_written) { cl_block_set_bytes_committed( block, cl_block_get_bytes_committed(block) + bytes_written); cl_unlock(&block->writer_lock); } // Returns a pointer to the first unread byte in buffer. The number of bytes // available are returned in 'bytes_available'. Acquires reader lock that is // released by a subsequent cl_block_end_read() call. Returns NULL if: // - read in progress // - no data available static void* cl_block_start_read(cl_block* block, size_t* bytes_available) { if (!cl_try_lock(&block->reader_lock)) { return NULL; } // bytes_committed may change from under us. Use bytes_available to update // bytes_read below. size_t bytes_committed = cl_block_get_bytes_committed(block); GPR_ASSERT(bytes_committed >= block->bytes_read); *bytes_available = bytes_committed - block->bytes_read; if (*bytes_available == 0) { cl_unlock(&block->reader_lock); return NULL; } void* record = block->buffer + block->bytes_read; block->bytes_read += *bytes_available; return record; } static void cl_block_end_read(cl_block* block) { cl_unlock(&block->reader_lock); } // Internal functions operating on g_log // Allocates a new free block (or recycles an available dirty block if log is // configured to discard old records). Returns NULL if out-of-space. static cl_block* cl_allocate_block(void) { cl_block* block = cl_block_list_head(&g_log.free_block_list); if (block != NULL) { cl_block_list_remove(&g_log.free_block_list, block); return block; } if (!g_log.discard_old_records) { // No free block and log is configured to keep old records. return NULL; } // Recycle dirty block. Start from the oldest. for (block = cl_block_list_head(&g_log.dirty_block_list); block != NULL; block = block->link.next->block) { if (cl_block_try_disable_access(block, 1 /* discard data */)) { cl_block_list_remove(&g_log.dirty_block_list, block); return block; } } return NULL; } // Allocates a new block and updates core id => block mapping. 'old_block' // points to the block that the caller thinks is attached to // 'core_id'. 'old_block' may be NULL. Returns true if: // - allocated a new block OR // - 'core_id' => 'old_block' mapping changed (another thread allocated a // block before lock was acquired). static bool cl_allocate_core_local_block(uint32_t core_id, cl_block* old_block) { // Now that we have the lock, check if core-local mapping has changed. cl_core_local_block* core_local_block = &g_log.core_local_blocks[core_id]; cl_block* block = cl_core_local_block_get_block(core_local_block); if ((block != NULL) && (block != old_block)) { return true; } if (block != NULL) { cl_core_local_block_set_block(core_local_block, NULL); cl_block_list_insert_at_tail(&g_log.dirty_block_list, block); } block = cl_allocate_block(); if (block == NULL) { return false; } cl_core_local_block_set_block(core_local_block, block); cl_block_enable_access(block); return true; } static cl_block* cl_get_block(void* record) { uintptr_t p = (uintptr_t)((char*)record - g_log.buffer); uintptr_t index = p >> CENSUS_LOG_2_MAX_RECORD_SIZE; return &g_log.blocks[index]; } // Gets the next block to read and tries to free 'prev' block (if not NULL). // Returns NULL if reached the end. static cl_block* cl_next_block_to_read(cl_block* prev) { cl_block* block = NULL; if (g_log.read_iterator_state == g_log.num_cores) { // We are traversing dirty list; find the next dirty block. if (prev != NULL) { // Try to free the previous block if there is no unread data. This // block // may have unread data if previously incomplete record completed // between // read_next() calls. block = prev->link.next->block; if (cl_block_try_disable_access(prev, 0 /* do not discard data */)) { cl_block_list_remove(&g_log.dirty_block_list, prev); cl_block_list_insert_at_head(&g_log.free_block_list, prev); } } else { block = cl_block_list_head(&g_log.dirty_block_list); } if (block != NULL) { return block; } // We are done with the dirty list; moving on to core-local blocks. } while (g_log.read_iterator_state > 0) { g_log.read_iterator_state--; block = cl_core_local_block_get_block( &g_log.core_local_blocks[g_log.read_iterator_state]); if (block != NULL) { return block; } } return NULL; } #define CL_LOG_2_MB 20 // 2^20 = 1MB // External functions: primary stats_log interface void census_log_initialize(size_t size_in_mb, int discard_old_records) { // Check cacheline alignment. GPR_ASSERT(sizeof(cl_block) % GPR_CACHELINE_SIZE == 0); GPR_ASSERT(sizeof(cl_core_local_block) % GPR_CACHELINE_SIZE == 0); GPR_ASSERT(!g_log.initialized); g_log.discard_old_records = discard_old_records; g_log.num_cores = gpr_cpu_num_cores(); // Ensure that we will not get any overflow in calaculating num_blocks GPR_ASSERT(CL_LOG_2_MB >= CENSUS_LOG_2_MAX_RECORD_SIZE); GPR_ASSERT(size_in_mb < 1000); // Ensure at least 2x as many blocks as there are cores. g_log.num_blocks = (uint32_t)GPR_MAX(2 * g_log.num_cores, (size_in_mb << CL_LOG_2_MB) >> CENSUS_LOG_2_MAX_RECORD_SIZE); gpr_mu_init(&g_log.lock); g_log.read_iterator_state = 0; g_log.block_being_read = NULL; g_log.core_local_blocks = (cl_core_local_block*)gpr_malloc_aligned( g_log.num_cores * sizeof(cl_core_local_block), GPR_CACHELINE_SIZE_LOG); memset(g_log.core_local_blocks, 0, g_log.num_cores * sizeof(cl_core_local_block)); g_log.blocks = (cl_block*)gpr_malloc_aligned( g_log.num_blocks * sizeof(cl_block), GPR_CACHELINE_SIZE_LOG); memset(g_log.blocks, 0, g_log.num_blocks * sizeof(cl_block)); g_log.buffer = gpr_malloc(g_log.num_blocks * CENSUS_LOG_MAX_RECORD_SIZE); memset(g_log.buffer, 0, g_log.num_blocks * CENSUS_LOG_MAX_RECORD_SIZE); cl_block_list_initialize(&g_log.free_block_list); cl_block_list_initialize(&g_log.dirty_block_list); for (uint32_t i = 0; i < g_log.num_blocks; ++i) { cl_block* block = g_log.blocks + i; cl_block_initialize(block, g_log.buffer + (CENSUS_LOG_MAX_RECORD_SIZE * i)); cl_block_try_disable_access(block, 1 /* discard data */); cl_block_list_insert_at_tail(&g_log.free_block_list, block); } gpr_atm_rel_store(&g_log.out_of_space_count, 0); g_log.initialized = 1; } void census_log_shutdown(void) { GPR_ASSERT(g_log.initialized); gpr_mu_destroy(&g_log.lock); gpr_free_aligned(g_log.core_local_blocks); g_log.core_local_blocks = NULL; gpr_free_aligned(g_log.blocks); g_log.blocks = NULL; gpr_free(g_log.buffer); g_log.buffer = NULL; g_log.initialized = 0; } void* census_log_start_write(size_t size) { // Used to bound number of times block allocation is attempted. GPR_ASSERT(size > 0); GPR_ASSERT(g_log.initialized); if (size > CENSUS_LOG_MAX_RECORD_SIZE) { return NULL; } uint32_t attempts_remaining = g_log.num_blocks; uint32_t core_id = gpr_cpu_current_cpu(); do { void* record = NULL; cl_block* block = cl_core_local_block_get_block(&g_log.core_local_blocks[core_id]); if (block && (record = cl_block_start_write(block, size))) { return record; } // Need to allocate a new block. We are here if: // - No block associated with the core OR // - Write in-progress on the block OR // - block is out of space gpr_mu_lock(&g_log.lock); bool allocated = cl_allocate_core_local_block(core_id, block); gpr_mu_unlock(&g_log.lock); if (!allocated) { gpr_atm_no_barrier_fetch_add(&g_log.out_of_space_count, 1); return NULL; } } while (attempts_remaining--); // Give up. gpr_atm_no_barrier_fetch_add(&g_log.out_of_space_count, 1); return NULL; } void census_log_end_write(void* record, size_t bytes_written) { GPR_ASSERT(g_log.initialized); cl_block_end_write(cl_get_block(record), bytes_written); } void census_log_init_reader(void) { GPR_ASSERT(g_log.initialized); gpr_mu_lock(&g_log.lock); // If a block is locked for reading unlock it. if (g_log.block_being_read != NULL) { cl_block_end_read(g_log.block_being_read); g_log.block_being_read = NULL; } g_log.read_iterator_state = g_log.num_cores; gpr_mu_unlock(&g_log.lock); } const void* census_log_read_next(size_t* bytes_available) { GPR_ASSERT(g_log.initialized); gpr_mu_lock(&g_log.lock); if (g_log.block_being_read != NULL) { cl_block_end_read(g_log.block_being_read); } do { g_log.block_being_read = cl_next_block_to_read(g_log.block_being_read); if (g_log.block_being_read != NULL) { void* record = cl_block_start_read(g_log.block_being_read, bytes_available); if (record != NULL) { gpr_mu_unlock(&g_log.lock); return record; } } } while (g_log.block_being_read != NULL); gpr_mu_unlock(&g_log.lock); return NULL; } size_t census_log_remaining_space(void) { GPR_ASSERT(g_log.initialized); size_t space = 0; gpr_mu_lock(&g_log.lock); if (g_log.discard_old_records) { // Remaining space is not meaningful; just return the entire log space. space = g_log.num_blocks << CENSUS_LOG_2_MAX_RECORD_SIZE; } else { GPR_ASSERT(g_log.free_block_list.count >= 0); space = (size_t)g_log.free_block_list.count * CENSUS_LOG_MAX_RECORD_SIZE; } gpr_mu_unlock(&g_log.lock); return space; } int64_t census_log_out_of_space_count(void) { GPR_ASSERT(g_log.initialized); return gpr_atm_acq_load(&g_log.out_of_space_count); } grpc-1.3.2/src/core/ext/census/mlog.h000066400000000000000000000100031310511640000173570ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* A very fast in-memory log, optimized for multiple writers. */ #ifndef GRPC_CORE_EXT_CENSUS_MLOG_H #define GRPC_CORE_EXT_CENSUS_MLOG_H #include #include /* Maximum record size, in bytes. */ #define CENSUS_LOG_2_MAX_RECORD_SIZE 14 /* 2^14 = 16KB */ #define CENSUS_LOG_MAX_RECORD_SIZE (1 << CENSUS_LOG_2_MAX_RECORD_SIZE) /* Initialize the statistics logging subsystem with the given log size. A log size of 0 will result in the smallest possible log for the platform (approximately CENSUS_LOG_MAX_RECORD_SIZE * gpr_cpu_num_cores()). If discard_old_records is non-zero, then new records will displace older ones when the log is full. This function must be called before any other census_log functions. */ void census_log_initialize(size_t size_in_mb, int discard_old_records); /* Shutdown the logging subsystem. Caller must ensure that: - no in progress or future call to any census_log functions - no incomplete records */ void census_log_shutdown(void); /* Allocates and returns a 'size' bytes record and marks it in use. A subsequent census_log_end_write() marks the record complete. The 'bytes_written' census_log_end_write() argument must be <= 'size'. Returns NULL if out-of-space AND: - log is configured to keep old records OR - all blocks are pinned by incomplete records. */ void* census_log_start_write(size_t size); void census_log_end_write(void* record, size_t bytes_written); void census_log_init_reader(void); /* census_log_read_next() iterates over blocks with data and for each block returns a pointer to the first unread byte. The number of bytes that can be read are returned in 'bytes_available'. Reader is expected to read all available data. Reading the data consumes it i.e. it cannot be read again. census_log_read_next() returns NULL if the end is reached i.e last block is read. census_log_init_reader() starts the iteration or aborts the current iteration. */ const void* census_log_read_next(size_t* bytes_available); /* Returns estimated remaining space across all blocks, in bytes. If log is configured to discard old records, returns total log space. Otherwise, returns space available in empty blocks (partially filled blocks are treated as full). */ size_t census_log_remaining_space(void); /* Returns the number of times grpc_stats_log_start_write() failed due to out-of-space. */ int64_t census_log_out_of_space_count(void); #endif /* GRPC_CORE_EXT_CENSUS_MLOG_H */ grpc-1.3.2/src/core/ext/census/operation.c000066400000000000000000000047771310511640000204410ustar00rootroot00000000000000/* * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include /* TODO(aveitch): These are all placeholder implementations. */ census_timestamp census_start_rpc_op_timestamp(void) { census_timestamp ct; /* TODO(aveitch): assumes gpr_timespec implementation of census_timestamp. */ ct.ts = gpr_now(GPR_CLOCK_MONOTONIC); return ct; } census_context *census_start_client_rpc_op( const census_context *context, int64_t rpc_name_id, const census_rpc_name_info *rpc_name_info, const char *peer, int trace_mask, const census_timestamp *start_time) { return NULL; } census_context *census_start_server_rpc_op( const char *buffer, int64_t rpc_name_id, const census_rpc_name_info *rpc_name_info, const char *peer, int trace_mask, census_timestamp *start_time) { return NULL; } census_context *census_start_op(census_context *context, const char *family, const char *name, int trace_mask) { return NULL; } void census_end_op(census_context *context, int status) {} grpc-1.3.2/src/core/ext/census/placeholders.c000066400000000000000000000042141310511640000210700ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include /* Placeholders for the pending APIs */ int census_get_trace_record(census_trace_record *trace_record) { (void)trace_record; abort(); } void census_record_values(census_context *context, census_value *values, size_t nvalues) { (void)context; (void)values; (void)nvalues; abort(); } void census_set_rpc_client_peer(census_context *context, const char *peer) { (void)context; (void)peer; abort(); } void census_trace_scan_end() { abort(); } int census_trace_scan_start(int consume) { (void)consume; abort(); } grpc-1.3.2/src/core/ext/census/resource.c000066400000000000000000000261211310511640000202530ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/census/resource.h" #include "third_party/nanopb/pb_decode.h" #include #include #include #include #include #include // Protect local resource data structures. static gpr_mu resource_lock; // Deleteing and creating resources are relatively rare events, and should not // be done in the critical path of performance sensitive code. We record // current resource id's used in a simple array, and just search it each time // we need to assign a new id, or look up a resource. static resource **resources = NULL; // Number of entries in *resources static size_t n_resources = 0; // Number of defined resources static size_t n_defined_resources = 0; void initialize_resources(void) { gpr_mu_init(&resource_lock); gpr_mu_lock(&resource_lock); GPR_ASSERT(resources == NULL && n_resources == 0 && n_defined_resources == 0); gpr_mu_unlock(&resource_lock); } // Delete a resource given it's ID. The ID must be a valid resource ID. Must be // called with resource_lock held. static void delete_resource_locked(size_t rid) { GPR_ASSERT(resources[rid] != NULL); gpr_free(resources[rid]->name); gpr_free(resources[rid]->description); gpr_free(resources[rid]->numerators); gpr_free(resources[rid]->denominators); gpr_free(resources[rid]); resources[rid] = NULL; n_defined_resources--; } void shutdown_resources(void) { gpr_mu_lock(&resource_lock); for (size_t i = 0; i < n_resources; i++) { if (resources[i] != NULL) { delete_resource_locked(i); } } GPR_ASSERT(n_defined_resources == 0); gpr_free(resources); resources = NULL; n_resources = 0; gpr_mu_unlock(&resource_lock); } // Check the contents of string fields in a resource proto. static bool validate_string(pb_istream_t *stream, const pb_field_t *field, void **arg) { resource *vresource = (resource *)*arg; switch (field->tag) { case google_census_Resource_name_tag: // Name must have at least one character if (stream->bytes_left == 0) { gpr_log(GPR_INFO, "Zero-length Resource name."); return false; } vresource->name = gpr_malloc(stream->bytes_left + 1); vresource->name[stream->bytes_left] = '\0'; if (!pb_read(stream, (uint8_t *)vresource->name, stream->bytes_left)) { return false; } // Can't have same name as an existing resource. for (size_t i = 0; i < n_resources; i++) { resource *compare = resources[i]; if (compare == vresource || compare == NULL) continue; if (strcmp(compare->name, vresource->name) == 0) { gpr_log(GPR_INFO, "Duplicate Resource name %s.", vresource->name); return false; } } break; case google_census_Resource_description_tag: if (stream->bytes_left == 0) { return true; } vresource->description = gpr_malloc(stream->bytes_left + 1); vresource->description[stream->bytes_left] = '\0'; if (!pb_read(stream, (uint8_t *)vresource->description, stream->bytes_left)) { return false; } break; default: // No other string fields in Resource. Print warning and skip. gpr_log(GPR_INFO, "Unknown string field type in Resource protobuf."); if (!pb_read(stream, NULL, stream->bytes_left)) { return false; } break; } return true; } // Decode numerators/denominators in a stream. The `count` and `bup` // (BasicUnit pointer) are pointers to the approriate fields in a resource // struct. static bool validate_units_helper(pb_istream_t *stream, int *count, google_census_Resource_BasicUnit **bup) { while (stream->bytes_left) { (*count)++; // Have to allocate a new array of values. Normal case is 0 or 1, so // this should normally not be an issue. google_census_Resource_BasicUnit *new_bup = gpr_malloc((size_t)*count * sizeof(google_census_Resource_BasicUnit)); if (*count != 1) { memcpy(new_bup, *bup, (size_t)(*count - 1) * sizeof(google_census_Resource_BasicUnit)); gpr_free(*bup); } *bup = new_bup; uint64_t value; if (!pb_decode_varint(stream, &value)) { return false; } *(*bup + *count - 1) = (google_census_Resource_BasicUnit)value; } return true; } // Validate units field of a Resource proto. static bool validate_units(pb_istream_t *stream, const pb_field_t *field, void **arg) { resource *vresource = (resource *)(*arg); switch (field->tag) { case google_census_Resource_MeasurementUnit_numerator_tag: return validate_units_helper(stream, &vresource->n_numerators, &vresource->numerators); break; case google_census_Resource_MeasurementUnit_denominator_tag: return validate_units_helper(stream, &vresource->n_denominators, &vresource->denominators); break; default: gpr_log(GPR_ERROR, "Unknown field type."); return false; break; } return true; } // Validate the contents of a Resource proto. `id` is the intended resource id. static bool validate_resource_pb(const uint8_t *resource_pb, size_t resource_pb_size, size_t id) { GPR_ASSERT(id < n_resources); if (resource_pb == NULL) { return false; } google_census_Resource vresource; vresource.name.funcs.decode = &validate_string; vresource.name.arg = resources[id]; vresource.description.funcs.decode = &validate_string; vresource.description.arg = resources[id]; vresource.unit.numerator.funcs.decode = &validate_units; vresource.unit.numerator.arg = resources[id]; vresource.unit.denominator.funcs.decode = &validate_units; vresource.unit.denominator.arg = resources[id]; pb_istream_t stream = pb_istream_from_buffer((uint8_t *)resource_pb, resource_pb_size); if (!pb_decode(&stream, google_census_Resource_fields, &vresource)) { return false; } // A Resource must have a name, a unit, with at least one numerator. return (resources[id]->name != NULL && vresource.has_unit && resources[id]->n_numerators > 0); } // Allocate a blank resource, and return associated ID. Must be called with // resource_lock held. size_t allocate_resource(void) { // use next_id to optimize expected placement of next new resource. static size_t next_id = 0; size_t id = n_resources; // resource ID - initialize to invalid value. // Expand resources if needed. if (n_resources == n_defined_resources) { size_t new_n_resources = n_resources ? n_resources * 2 : 2; resource **new_resources = gpr_malloc(new_n_resources * sizeof(resource *)); memcpy(new_resources, resources, n_resources * sizeof(resource *)); memset(new_resources + n_resources, 0, (new_n_resources - n_resources) * sizeof(resource *)); gpr_free(resources); resources = new_resources; n_resources = new_n_resources; id = n_defined_resources; } else { GPR_ASSERT(n_defined_resources < n_resources); // Find a free id. for (size_t base = 0; base < n_resources; base++) { id = (next_id + base) % n_resources; if (resources[id] == NULL) break; } } GPR_ASSERT(id < n_resources && resources[id] == NULL); resources[id] = gpr_malloc(sizeof(resource)); memset(resources[id], 0, sizeof(resource)); n_defined_resources++; next_id = (id + 1) % n_resources; return id; } int32_t census_define_resource(const uint8_t *resource_pb, size_t resource_pb_size) { if (resource_pb == NULL) { return -1; } gpr_mu_lock(&resource_lock); size_t id = allocate_resource(); // Validate pb, extract name. if (!validate_resource_pb(resource_pb, resource_pb_size, id)) { delete_resource_locked(id); gpr_mu_unlock(&resource_lock); return -1; } gpr_mu_unlock(&resource_lock); return (int32_t)id; } void census_delete_resource(int32_t rid) { gpr_mu_lock(&resource_lock); if (rid >= 0 && (size_t)rid < n_resources && resources[rid] != NULL) { delete_resource_locked((size_t)rid); } gpr_mu_unlock(&resource_lock); } int32_t census_resource_id(const char *name) { gpr_mu_lock(&resource_lock); for (int32_t id = 0; (size_t)id < n_resources; id++) { if (resources[id] != NULL && strcmp(resources[id]->name, name) == 0) { gpr_mu_unlock(&resource_lock); return id; } } gpr_mu_unlock(&resource_lock); return -1; } int32_t define_resource(const resource *base) { GPR_ASSERT(base != NULL && base->name != NULL && base->n_numerators > 0 && base->numerators != NULL); gpr_mu_lock(&resource_lock); size_t id = allocate_resource(); size_t len = strlen(base->name) + 1; resources[id]->name = gpr_malloc(len); memcpy(resources[id]->name, base->name, len); if (base->description) { len = strlen(base->description) + 1; resources[id]->description = gpr_malloc(len); memcpy(resources[id]->description, base->description, len); } resources[id]->prefix = base->prefix; resources[id]->n_numerators = base->n_numerators; len = (size_t)base->n_numerators * sizeof(*base->numerators); resources[id]->numerators = gpr_malloc(len); memcpy(resources[id]->numerators, base->numerators, len); resources[id]->n_denominators = base->n_denominators; if (base->n_denominators != 0) { len = (size_t)base->n_denominators * sizeof(*base->denominators); resources[id]->denominators = gpr_malloc(len); memcpy(resources[id]->denominators, base->denominators, len); } gpr_mu_unlock(&resource_lock); return (int32_t)id; } grpc-1.3.2/src/core/ext/census/resource.h000066400000000000000000000050001310511640000202510ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* Census-internal resource definition and manipluation functions. */ #ifndef GRPC_CORE_EXT_CENSUS_RESOURCE_H #define GRPC_CORE_EXT_CENSUS_RESOURCE_H #include #include "src/core/ext/census/gen/census.pb.h" /* Internal representation of a resource. */ typedef struct { char *name; char *description; int32_t prefix; int n_numerators; google_census_Resource_BasicUnit *numerators; int n_denominators; google_census_Resource_BasicUnit *denominators; } resource; /* Initialize and shutdown the resources subsystem. */ void initialize_resources(void); void shutdown_resources(void); /* Add a new resource, given a proposed resource structure. Returns the resource ID, or -ve on failure. TODO(aveitch): this function exists to support addition of the base resources. It should be removed when we have the ability to add resources from configuration files. */ int32_t define_resource(const resource *base); #endif /* GRPC_CORE_EXT_CENSUS_RESOURCE_H */ grpc-1.3.2/src/core/ext/census/rpc_metric_id.h000066400000000000000000000043551310511640000212410ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_CENSUS_RPC_METRIC_ID_H #define GRPC_CORE_EXT_CENSUS_RPC_METRIC_ID_H /* Metric ID's used for RPC measurements. */ /* Count of client requests sent. */ #define CENSUS_METRIC_RPC_CLIENT_REQUESTS ((uint32_t)0) /* Count of server requests sent. */ #define CENSUS_METRIC_RPC_SERVER_REQUESTS ((uint32_t)1) /* Client error counts. */ #define CENSUS_METRIC_RPC_CLIENT_ERRORS ((uint32_t)2) /* Server error counts. */ #define CENSUS_METRIC_RPC_SERVER_ERRORS ((uint32_t)3) /* Client side request latency. */ #define CENSUS_METRIC_RPC_CLIENT_LATENCY ((uint32_t)4) /* Server side request latency. */ #define CENSUS_METRIC_RPC_SERVER_LATENCY ((uint32_t)5) #endif /* GRPC_CORE_EXT_CENSUS_RPC_METRIC_ID_H */ grpc-1.3.2/src/core/ext/census/trace_context.c000066400000000000000000000060571310511640000212740ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/census/trace_context.h" #include #include #include #include "third_party/nanopb/pb_decode.h" #include "third_party/nanopb/pb_encode.h" // This function assumes the TraceContext is valid. size_t encode_trace_context(google_trace_TraceContext *ctxt, uint8_t *buffer, const size_t buf_size) { // Create a stream that will write to our buffer. pb_ostream_t stream = pb_ostream_from_buffer(buffer, buf_size); // encode message bool status = pb_encode(&stream, google_trace_TraceContext_fields, ctxt); if (!status) { gpr_log(GPR_DEBUG, "TraceContext encoding failed: %s", PB_GET_ERROR(&stream)); return 0; } return stream.bytes_written; } bool decode_trace_context(google_trace_TraceContext *ctxt, uint8_t *buffer, const size_t nbytes) { // Create a stream that reads nbytes from the buffer. pb_istream_t stream = pb_istream_from_buffer(buffer, nbytes); // decode message bool status = pb_decode(&stream, google_trace_TraceContext_fields, ctxt); if (!status) { gpr_log(GPR_DEBUG, "TraceContext decoding failed: %s", PB_GET_ERROR(&stream)); return false; } // check fields if (!ctxt->has_trace_id_hi || !ctxt->has_trace_id_lo) { gpr_log(GPR_DEBUG, "Invalid TraceContext: missing trace_id"); return false; } if (!ctxt->has_span_id) { gpr_log(GPR_DEBUG, "Invalid TraceContext: missing span_id"); return false; } return true; } grpc-1.3.2/src/core/ext/census/trace_context.h000066400000000000000000000061771310511640000213040ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* Functions for manipulating trace contexts as defined in src/proto/census/trace.proto */ #ifndef GRPC_CORE_EXT_CENSUS_TRACE_CONTEXT_H #define GRPC_CORE_EXT_CENSUS_TRACE_CONTEXT_H #include "src/core/ext/census/gen/trace_context.pb.h" /* Span option flags. */ #define SPAN_OPTIONS_IS_SAMPLED 0x01 /* Maximum number of bytes required to encode a TraceContext (31) 1 byte for trace_id field 1 byte for trace_id length 1 byte for trace_id.hi field 8 bytes for trace_id.hi (uint64_t) 1 byte for trace_id.lo field 8 bytes for trace_id.lo (uint64_t) 1 byte for span_id field 8 bytes for span_id (uint64_t) 1 byte for is_sampled field 1 byte for is_sampled (bool) */ #define TRACE_MAX_CONTEXT_SIZE 31 /* Encode a trace context (ctxt) into proto format to the buffer provided. The size of buffer must be at least TRACE_MAX_CONTEXT_SIZE. On success, returns the number of bytes successfully encoded into buffer. On failure, returns 0. */ size_t encode_trace_context(google_trace_TraceContext *ctxt, uint8_t *buffer, const size_t buf_size); /* Decode a proto-encoded TraceContext from the provided buffer into the TraceContext structure (ctxt). The function expects to be supplied the number of bytes to be read from buffer (nbytes). This function will also validate that the TraceContext has a span_id and a trace_id, and will return false if either of these do not exist. On success, returns true and false otherwise. */ bool decode_trace_context(google_trace_TraceContext *ctxt, uint8_t *buffer, const size_t nbytes); #endif /* GRPC_CORE_EXT_CENSUS_TRACE_CONTEXT_H */ grpc-1.3.2/src/core/ext/census/trace_label.h000066400000000000000000000043741310511640000206740ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_CENSUS_TRACE_LABEL_H #define GRPC_CORE_EXT_CENSUS_TRACE_LABEL_H #include "src/core/ext/census/trace_string.h" /* Trace label (key/value pair) stores a label name and the label value. The value can be one of trace_string/int64_t/bool. */ typedef struct trace_label { trace_string key; enum label_type { /* Unknown value for debugging/error purposes */ LABEL_UNKNOWN = 0, /* A string value */ LABEL_STRING = 1, /* An integer value. */ LABEL_INT = 2, /* A boolean value. */ LABEL_BOOL = 3, } value_type; union value { trace_string label_str; int64_t label_int; bool label_bool; } value; } trace_label; #endif /* GRPC_CORE_EXT_CENSUS_TRACE_LABEL_H */ grpc-1.3.2/src/core/ext/census/trace_propagation.h000066400000000000000000000057401310511640000221360ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_CENSUS_TRACE_PROPAGATION_H #define GRPC_CORE_EXT_CENSUS_TRACE_PROPAGATION_H #include "src/core/ext/census/tracing.h" /* Encoding and decoding functions for receiving and sending trace contexts over the wire. Only RPC libraries should be calling these functions. These functions return the number of bytes encoded/decoded (0 if a failure has occurred). buf_size indicates the size of the input/output buffer. trace_span_context is a struct that includes the trace ID, span ID, and a set of option flags (is_sampled, etc.). */ /* Converts a span context to a binary byte buffer. */ size_t trace_span_context_to_binary(const trace_span_context *ctxt, uint8_t *buf, size_t buf_size); /* Reads a binary byte buffer and populates a span context structure. */ size_t binary_to_trace_span_context(const uint8_t *buf, size_t buf_size, trace_span_context *ctxt); /* Converts a span context to an http metadata compatible string. */ size_t trace_span_context_to_http_format(const trace_span_context *ctxt, char *buf, size_t buf_size); /* Reads an http metadata compatible string and populates a span context structure. */ size_t http_format_to_trace_span_context(const char *buf, size_t buf_size, trace_span_context *ctxt); #endif /* GRPC_CORE_EXT_CENSUS_TRACE_PROPAGATION_H */ grpc-1.3.2/src/core/ext/census/trace_status.h000066400000000000000000000035671310511640000211430ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_CENSUS_TRACE_STATUS_H #define GRPC_CORE_EXT_CENSUS_TRACE_STATUS_H #include "src/core/ext/census/trace_string.h" /* Stores a status code and status message for a trace. */ typedef struct trace_status { int64_t errorCode; trace_string errorMessage; } trace_status; #endif /* GRPC_CORE_EXT_CENSUS_TRACE_STATUS_H */ grpc-1.3.2/src/core/ext/census/trace_string.h000066400000000000000000000042431310511640000211160ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_CENSUS_TRACE_STRING_H #define GRPC_CORE_EXT_CENSUS_TRACE_STRING_H #include /* String struct for tracing messages. Since this is a C API, we do not have access to a string class. This is intended for use by higher level languages which wrap around the C API, as most of them have a string class. This will also be more efficient when copying, as we have an explicitly specified length. Also, grpc_slice has reference counting which allows for interning. */ typedef struct trace_string { char *string; size_t length; } trace_string; #endif /* GRPC_CORE_EXT_CENSUS_TRACE_STRING_H */ grpc-1.3.2/src/core/ext/census/tracing.c000066400000000000000000000057101310511640000200540ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/census/tracing.h" #include #include #include #include #include "src/core/ext/census/mlog.h" void trace_start_span(const trace_span_context *span_ctxt, const trace_string name, const start_span_options *opts, trace_span_context *new_span_ctxt, bool has_remote_parent) { // Noop implementation. } void trace_add_span_annotation(const trace_string description, const trace_label *labels, const size_t n_labels, trace_span_context *span_ctxt) { // Noop implementation. } void trace_add_span_network_event_annotation(const trace_string description, const trace_label *labels, const size_t n_labels, const gpr_timespec timestamp, bool sent, uint64_t id, trace_span_context *span_ctxt) { // Noop implementation. } void trace_add_span_labels(const trace_label *labels, const size_t n_labels, trace_span_context *span_ctxt) { // Noop implementation. } void trace_end_span(const trace_status *status, trace_span_context *span_ctxt) { // Noop implementation. } grpc-1.3.2/src/core/ext/census/tracing.h000066400000000000000000000134221310511640000200600ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_CENSUS_TRACING_H #define GRPC_CORE_EXT_CENSUS_TRACING_H #include #include #include "src/core/ext/census/trace_context.h" #include "src/core/ext/census/trace_label.h" #include "src/core/ext/census/trace_status.h" /* This is the low level tracing API that other languages will interface with. This is not intended to be accessed by the end-user, therefore it has been designed with performance in mind rather than ease of use. */ /* The tracing level. */ enum TraceLevel { /* Annotations on this context will be silently discarded. */ NO_TRACING = 0, /* Annotations will not be saved to a persistent store. They will be available via local APIs only. This setting is not propagated to child spans. */ TRANSIENT_TRACING = 1, /* Annotations are recorded for the entire distributed trace and they are saved to a persistent store. This setting is propagated to child spans. */ PERSISTENT_TRACING = 2, }; typedef struct trace_span_context { /* Trace span context stores Span ID, Trace ID, and option flags. */ /* Trace ID is 128 bits split into 2 64-bit chunks (hi and lo). */ uint64_t trace_id_hi; uint64_t trace_id_lo; /* Span ID is 64 bits. */ uint64_t span_id; /* Span-options is 32-bit value which contains flag options. */ uint32_t span_options; } trace_span_context; typedef struct start_span_options { /* If set, this will override the Span.local_start_time for the Span. */ gpr_timespec local_start_timestamp; /* Linked spans can be used to identify spans that are linked to this span in a different trace. This can be used (for example) in batching operations, where a single batch handler processes multiple requests from different traces. If set, points to a list of Spans are linked to the created Span.*/ trace_span_context *linked_spans; /* The number of linked spans. */ size_t n_linked_spans; } start_span_options; /* Create a new child Span (or root if parent is NULL), with parent being the designated Span. The child span will have the provided name and starting span options (optional). The bool has_remote_parent marks whether the context refers to a remote parent span or not. */ void trace_start_span(const trace_span_context *span_ctxt, const trace_string name, const start_span_options *opts, trace_span_context *new_span_ctxt, bool has_remote_parent); /* Add a new Annotation to the Span. Annotations consist of a description (trace_string) and a set of n labels (trace_label). This can be populated with arbitrary user data. */ void trace_add_span_annotation(const trace_string description, const trace_label *labels, const size_t n_labels, trace_span_context *span_ctxt); /* Add a new NetworkEvent annotation to a Span. This function is only intended to be used by RPC systems (either client or server), not by higher level applications. The timestamp type will be system-defined, the sent argument designates whether this is a network send event (client request, server reply)or receive (server request, client reply). The id argument corresponds to Span.Annotation.NetworkEvent.id from the data model, and serves to uniquely identify each network message. */ void trace_add_span_network_event(const trace_string description, const trace_label *labels, const size_t n_labels, const gpr_timespec timestamp, bool sent, uint64_t id, trace_span_context *span_ctxt); /* Add a set of labels to the Span. These will correspond to the field Span.labels in the data model. */ void trace_add_span_labels(const trace_label *labels, const size_t n_labels, trace_span_context *span_ctxt); /* Mark the end of Span Execution with the given status. Only the timing of the first EndSpan call for a given Span will be recorded, and implementations are free to ignore all further calls using the Span. EndSpanOptions can optionally be NULL. */ void trace_end_span(const trace_status *status, trace_span_context *span_ctxt); #endif /* GRPC_CORE_EXT_CENSUS_TRACING_H */ grpc-1.3.2/src/core/ext/census/window_stats.c000066400000000000000000000301361310511640000211520ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/census/window_stats.h" #include #include #include #include #include #include #include /* typedefs make typing long names easier. Use cws (for census_window_stats) */ typedef census_window_stats_stat_info cws_stat_info; typedef struct census_window_stats_sum cws_sum; /* Each interval is composed of a number of buckets, which hold a count of entries and a single statistic */ typedef struct census_window_stats_bucket { int64_t count; void *statistic; } cws_bucket; /* Each interval has a set of buckets, and the variables needed to keep track of their current state */ typedef struct census_window_stats_interval_stats { /* The buckets. There will be 'granularity' + 1 of these. */ cws_bucket *buckets; /* Index of the bucket containing the smallest time interval. */ int bottom_bucket; /* The smallest time storable in the current window. */ int64_t bottom; /* The largest time storable in the current window + 1ns */ int64_t top; /* The width of each bucket in ns. */ int64_t width; } cws_interval_stats; typedef struct census_window_stats { /* Number of intervals. */ int nintervals; /* Number of buckets in each interval. 'granularity' + 1. */ int nbuckets; /* Record of stat_info. */ cws_stat_info stat_info; /* Stats for each interval. */ cws_interval_stats *interval_stats; /* The time the newset stat was recorded. */ int64_t newest_time; } window_stats; /* Calculate an actual bucket index from a logical index 'IDX'. Other parameters supply information on the interval struct and overall stats. */ #define BUCKET_IDX(IS, IDX, WSTATS) \ ((IS->bottom_bucket + (IDX)) % WSTATS->nbuckets) /* The maximum seconds value we can have in a valid timespec. More than this will result in overflow in timespec_to_ns(). This works out to ~292 years. TODO: consider using doubles instead of int64. */ static int64_t max_seconds = (GPR_INT64_MAX - GPR_NS_PER_SEC) / GPR_NS_PER_SEC; static int64_t timespec_to_ns(const gpr_timespec ts) { if (ts.tv_sec > max_seconds) { return GPR_INT64_MAX - 1; } return ts.tv_sec * GPR_NS_PER_SEC + ts.tv_nsec; } static void cws_initialize_statistic(void *statistic, const cws_stat_info *stat_info) { if (stat_info->stat_initialize == NULL) { memset(statistic, 0, stat_info->stat_size); } else { stat_info->stat_initialize(statistic); } } /* Create and initialize a statistic */ static void *cws_create_statistic(const cws_stat_info *stat_info) { void *stat = gpr_malloc(stat_info->stat_size); cws_initialize_statistic(stat, stat_info); return stat; } window_stats *census_window_stats_create(int nintervals, const gpr_timespec intervals[], int granularity, const cws_stat_info *stat_info) { window_stats *ret; int i; /* validate inputs */ GPR_ASSERT(nintervals > 0 && granularity > 2 && intervals != NULL && stat_info != NULL); for (i = 0; i < nintervals; i++) { int64_t ns = timespec_to_ns(intervals[i]); GPR_ASSERT(intervals[i].tv_sec >= 0 && intervals[i].tv_nsec >= 0 && intervals[i].tv_nsec < GPR_NS_PER_SEC && ns >= 100 && granularity * 10 <= ns); } /* Allocate and initialize relevant data structures */ ret = (window_stats *)gpr_malloc(sizeof(window_stats)); ret->nintervals = nintervals; ret->nbuckets = granularity + 1; ret->stat_info = *stat_info; ret->interval_stats = (cws_interval_stats *)gpr_malloc(nintervals * sizeof(cws_interval_stats)); for (i = 0; i < nintervals; i++) { int64_t size_ns = timespec_to_ns(intervals[i]); cws_interval_stats *is = ret->interval_stats + i; cws_bucket *buckets = is->buckets = (cws_bucket *)gpr_malloc(ret->nbuckets * sizeof(cws_bucket)); int b; for (b = 0; b < ret->nbuckets; b++) { buckets[b].statistic = cws_create_statistic(stat_info); buckets[b].count = 0; } is->bottom_bucket = 0; is->bottom = 0; is->width = size_ns / granularity; /* Check for possible overflow issues, and maximize interval size if the user requested something large enough. */ if ((GPR_INT64_MAX - is->width) > size_ns) { is->top = size_ns + is->width; } else { is->top = GPR_INT64_MAX; is->width = GPR_INT64_MAX / (granularity + 1); } /* If size doesn't divide evenly, we can have a width slightly too small; better to have it slightly large. */ if ((size_ns - (granularity + 1) * is->width) > 0) { is->width += 1; } } ret->newest_time = 0; return ret; } /* When we try adding a measurement above the current interval range, we need to "shift" the buckets sufficiently to cover the new range. */ static void cws_shift_buckets(const window_stats *wstats, cws_interval_stats *is, int64_t when_ns) { int i; /* number of bucket time widths to "shift" */ int shift; /* number of buckets to clear */ int nclear; GPR_ASSERT(when_ns >= is->top); /* number of bucket time widths to "shift" */ shift = ((when_ns - is->top) / is->width) + 1; /* number of buckets to clear - limited by actual number of buckets */ nclear = GPR_MIN(shift, wstats->nbuckets); for (i = 0; i < nclear; i++) { int b = BUCKET_IDX(is, i, wstats); is->buckets[b].count = 0; cws_initialize_statistic(is->buckets[b].statistic, &wstats->stat_info); } /* adjust top/bottom times and current bottom bucket */ is->bottom_bucket = BUCKET_IDX(is, shift, wstats); is->top += shift * is->width; is->bottom += shift * is->width; } void census_window_stats_add(window_stats *wstats, const gpr_timespec when, const void *stat_value) { int i; int64_t when_ns = timespec_to_ns(when); GPR_ASSERT(wstats->interval_stats != NULL); for (i = 0; i < wstats->nintervals; i++) { cws_interval_stats *is = wstats->interval_stats + i; cws_bucket *bucket; if (when_ns < is->bottom) { /* Below smallest time in interval: drop */ continue; } if (when_ns >= is->top) { /* above limit: shift buckets */ cws_shift_buckets(wstats, is, when_ns); } /* Add the stat. */ GPR_ASSERT(is->bottom <= when_ns && when_ns < is->top); bucket = is->buckets + BUCKET_IDX(is, (when_ns - is->bottom) / is->width, wstats); bucket->count++; wstats->stat_info.stat_add(bucket->statistic, stat_value); } if (when_ns > wstats->newest_time) { wstats->newest_time = when_ns; } } /* Add a specific bucket contents to an accumulating total. */ static void cws_add_bucket_to_sum(cws_sum *sum, const cws_bucket *bucket, const cws_stat_info *stat_info) { sum->count += bucket->count; stat_info->stat_add(sum->statistic, bucket->statistic); } /* Add a proportion to an accumulating sum. */ static void cws_add_proportion_to_sum(double p, cws_sum *sum, const cws_bucket *bucket, const cws_stat_info *stat_info) { sum->count += p * bucket->count; stat_info->stat_add_proportion(p, sum->statistic, bucket->statistic); } void census_window_stats_get_sums(const window_stats *wstats, const gpr_timespec when, cws_sum sums[]) { int i; int64_t when_ns = timespec_to_ns(when); GPR_ASSERT(wstats->interval_stats != NULL); for (i = 0; i < wstats->nintervals; i++) { int when_bucket; int new_bucket; double last_proportion = 1.0; double bottom_proportion; cws_interval_stats *is = wstats->interval_stats + i; cws_sum *sum = sums + i; sum->count = 0; cws_initialize_statistic(sum->statistic, &wstats->stat_info); if (when_ns < is->bottom) { continue; } if (when_ns >= is->top) { cws_shift_buckets(wstats, is, when_ns); } /* Calculating the appropriate amount of which buckets to use can get complicated. Essentially there are two cases: 1) if the "top" bucket (new_bucket, where the newest additions to the stats recorded are entered) corresponds to 'when', then we need to take a proportion of it - (if when < newest_time) or the full thing. We also (possibly) need to take a corresponding proportion of the bottom bucket. 2) Other cases, we just take a straight proportion. */ when_bucket = (when_ns - is->bottom) / is->width; new_bucket = (wstats->newest_time - is->bottom) / is->width; if (new_bucket == when_bucket) { int64_t bottom_bucket_time = is->bottom + when_bucket * is->width; if (when_ns < wstats->newest_time) { last_proportion = (double)(when_ns - bottom_bucket_time) / (double)(wstats->newest_time - bottom_bucket_time); bottom_proportion = (double)(is->width - (when_ns - bottom_bucket_time)) / is->width; } else { bottom_proportion = (double)(is->width - (wstats->newest_time - bottom_bucket_time)) / is->width; } } else { last_proportion = (double)(when_ns + 1 - is->bottom - when_bucket * is->width) / is->width; bottom_proportion = 1.0 - last_proportion; } cws_add_proportion_to_sum(last_proportion, sum, is->buckets + BUCKET_IDX(is, when_bucket, wstats), &wstats->stat_info); if (when_bucket != 0) { /* last bucket isn't also bottom bucket */ int b; /* Add all of "bottom" bucket if we are looking at a subset of the full interval, or a proportion if we are adding full interval. */ cws_add_proportion_to_sum( (when_bucket == wstats->nbuckets - 1 ? bottom_proportion : 1.0), sum, is->buckets + is->bottom_bucket, &wstats->stat_info); /* Add all the remaining buckets (everything but top and bottom). */ for (b = 1; b < when_bucket; b++) { cws_add_bucket_to_sum(sum, is->buckets + BUCKET_IDX(is, b, wstats), &wstats->stat_info); } } } } void census_window_stats_destroy(window_stats *wstats) { int i; GPR_ASSERT(wstats->interval_stats != NULL); for (i = 0; i < wstats->nintervals; i++) { int b; for (b = 0; b < wstats->nbuckets; b++) { gpr_free(wstats->interval_stats[i].buckets[b].statistic); } gpr_free(wstats->interval_stats[i].buckets); } gpr_free(wstats->interval_stats); /* Ensure any use-after free triggers assert. */ wstats->interval_stats = NULL; gpr_free(wstats); } grpc-1.3.2/src/core/ext/census/window_stats.h000066400000000000000000000176771310511640000211760ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_CENSUS_WINDOW_STATS_H #define GRPC_CORE_EXT_CENSUS_WINDOW_STATS_H #include /* Keep rolling sums of a user-defined statistic (containing a number of measurements) over a a number of time intervals ("windows"). For example, you can use a window_stats object to answer questions such as "Approximately how many RPCs/s did I receive over the past minute, and approximately how many bytes did I send out over that period?". The type of data to record, and the time intervals to keep are specified when creating the object via a call to census_window_stats_create(). A window's interval is divided into one or more "buckets"; the interval must be divisible by the number of buckets. Internally, these buckets control the granularity of window_stats' measurements. Increasing the number of buckets lets the object respond more quickly to changes in the overall rate of data added into the object, at the cost of additional memory usage. Here's some code which keeps one minute/hour measurements for two values (latency in seconds and bytes transferred), with each interval divided into 4 buckets. typedef struct my_stat { double latency; int bytes; } my_stat; void add_my_stat(void* base, const void* addme) { my_stat* b = (my_stat*)base; const my_stat* a = (const my_stat*)addme; b->latency += a->latency; b->bytes += a->bytes; } void add_proportion_my_stat(double p, void* base, const void* addme) { (my_stat*)result->latency += p * (const my_stat*)base->latency; (my_stat*)result->bytes += p * (const my_stat*)base->bytes; } #define kNumIntervals 2 #define kMinInterval 0 #define kHourInterval 1 #define kNumBuckets 4 const struct census_window_stats_stat_info kMyStatInfo = { sizeof(my_stat), NULL, add_my_stat, add_proportion_my_stat }; gpr_timespec intervals[kNumIntervals] = {{60, 0}, {3600, 0}}; my_stat stat; my_stat sums[kNumIntervals]; census_window_stats_sums result[kNumIntervals]; struct census_window_stats* stats = census_window_stats_create(kNumIntervals, intervals, kNumBuckets, &kMyStatInfo); // Record a new event, taking 15.3ms, transferring 1784 bytes. stat.latency = 0.153; stat.bytes = 1784; census_window_stats_add(stats, gpr_now(GPR_CLOCK_REALTIME), &stat); // Get sums and print them out result[kMinInterval].statistic = &sums[kMinInterval]; result[kHourInterval].statistic = &sums[kHourInterval]; census_window_stats_get_sums(stats, gpr_now(GPR_CLOCK_REALTIME), result); printf("%d events/min, average time %gs, average bytes %g\n", result[kMinInterval].count, (my_stat*)result[kMinInterval].statistic->latency / result[kMinInterval].count, (my_stat*)result[kMinInterval].statistic->bytes / result[kMinInterval].count ); printf("%d events/hr, average time %gs, average bytes %g\n", result[kHourInterval].count, (my_stat*)result[kHourInterval].statistic->latency / result[kHourInterval].count, (my_stat*)result[kHourInterval].statistic->bytes / result[kHourInterval].count ); */ /* Opaque structure for representing window_stats object */ struct census_window_stats; /* Information provided by API user on the information they want to record */ typedef struct census_window_stats_stat_info { /* Number of bytes in user-defined object. */ size_t stat_size; /* Function to initialize a user-defined statistics object. If this is set * to NULL, then the object will be zero-initialized. */ void (*stat_initialize)(void *stat); /* Function to add one user-defined statistics object ('addme') to 'base' */ void (*stat_add)(void *base, const void *addme); /* As for previous function, but only add a proportion 'p'. This API will currently only use 'p' values in the range [0,1], but other values are possible in the future, and should be supported. */ void (*stat_add_proportion)(double p, void *base, const void *addme); } census_window_stats_stat_info; /* Create a new window_stats object. 'nintervals' is the number of 'intervals', and must be >=1. 'granularity' is the number of buckets, with a larger number using more memory, but providing greater accuracy of results. 'granularity should be > 2. We also require that each interval be at least 10 * 'granularity' nanoseconds in size. 'stat_info' contains information about the statistic to be gathered. Intervals greater than ~192 years will be treated as essentially infinite in size. This function will GPR_ASSERT() if the object cannot be created or any of the parameters have invalid values. This function is thread-safe. */ struct census_window_stats *census_window_stats_create( int nintervals, const gpr_timespec intervals[], int granularity, const census_window_stats_stat_info *stat_info); /* Add a new measurement (in 'stat_value'), as of a given time ('when'). This function is thread-compatible. */ void census_window_stats_add(struct census_window_stats *wstats, const gpr_timespec when, const void *stat_value); /* Structure used to record a single intervals sum for a given statistic */ typedef struct census_window_stats_sum { /* Total count of samples. Note that because some internal interpolation is performed, the count of samples returned for each interval may not be an integral value. */ double count; /* Sum for statistic */ void *statistic; } census_window_stats_sums; /* Retrieve a set of all values stored in a window_stats object 'wstats'. The number of 'sums' MUST be the same as the number 'nintervals' used in census_window_stats_create(). This function is thread-compatible. */ void census_window_stats_get_sums(const struct census_window_stats *wstats, const gpr_timespec when, struct census_window_stats_sum sums[]); /* Destroy a window_stats object. Once this function has been called, the object will no longer be usable from any of the above functions (and calling them will most likely result in a NULL-pointer dereference or assertion failure). This function is thread-compatible. */ void census_window_stats_destroy(struct census_window_stats *wstats); #endif /* GRPC_CORE_EXT_CENSUS_WINDOW_STATS_H */ grpc-1.3.2/src/core/ext/filters/000077500000000000000000000000001310511640000164265ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/filters/client_channel/000077500000000000000000000000001310511640000213745ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/filters/client_channel/README.md000066400000000000000000000050311310511640000226520ustar00rootroot00000000000000Client Configuration Support for GRPC ===================================== This library provides high level configuration machinery to construct client channels and load balance between them. Each grpc_channel is created with a grpc_resolver. It is the resolver's duty to resolve a name into a set of arguments for the channel. Such arguments might include: - a list of (ip, port) addresses to connect to - a load balancing policy to decide which server to send a request to - a set of filters to mutate outgoing requests (say, by adding metadata) The resolver provides this data as a stream of grpc_channel_args objects to the channel. We represent arguments as a stream so that they can be changed by the resolver during execution, by reacting to external events (such as new service configuration data being pushed to some store). Load Balancing -------------- Load balancing configuration is provided by a grpc_lb_policy object. The primary job of the load balancing policies is to pick a target server given only the initial metadata for a request. It does this by providing a grpc_subchannel object to the owning channel. Sub-Channels ------------ A sub-channel provides a connection to a server for a client channel. It has a connectivity state like a regular channel, and so can be connected or disconnected. This connectivity state can be used to inform load balancing decisions (for example, by avoiding disconnected backends). Configured sub-channels are fully setup to participate in the grpc data plane. Their behavior is specified by a set of grpc channel filters defined at their construction. To customize this behavior, resolvers build grpc_client_channel_factory objects, which use the decorator pattern to customize construction arguments for concrete grpc_subchannel instances. Naming for GRPC =============== Names in GRPC are represented by a URI (as defined in [RFC 3986](https://tools.ietf.org/html/rfc3986)). The following schemes are currently supported: dns:///host:port - dns schemes are currently supported so long as authority is empty (authority based dns resolution is expected in a future release) unix:path - the unix scheme is used to create and connect to unix domain sockets - the authority must be empty, and the path represents the absolute or relative path to the desired socket ipv4:host:port - a pre-resolved ipv4 dotted decimal address/port combination ipv6:[host]:port - a pre-resolved ipv6 address/port combination grpc-1.3.2/src/core/ext/filters/client_channel/channel_connectivity.c000066400000000000000000000166661310511640000257650ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/surface/channel.h" #include #include #include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/completion_queue.h" grpc_connectivity_state grpc_channel_check_connectivity_state( grpc_channel *channel, int try_to_connect) { /* forward through to the underlying client channel */ grpc_channel_element *client_channel_elem = grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel)); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_connectivity_state state; GRPC_API_TRACE( "grpc_channel_check_connectivity_state(channel=%p, try_to_connect=%d)", 2, (channel, try_to_connect)); if (client_channel_elem->filter == &grpc_client_channel_filter) { state = grpc_client_channel_check_connectivity_state( &exec_ctx, client_channel_elem, try_to_connect); grpc_exec_ctx_finish(&exec_ctx); return state; } gpr_log(GPR_ERROR, "grpc_channel_check_connectivity_state called on something that is " "not a client channel, but '%s'", client_channel_elem->filter->name); grpc_exec_ctx_finish(&exec_ctx); return GRPC_CHANNEL_SHUTDOWN; } typedef enum { WAITING, CALLING_BACK, CALLING_BACK_AND_FINISHED, CALLED_BACK } callback_phase; typedef struct { gpr_mu mu; callback_phase phase; grpc_closure on_complete; grpc_closure on_timeout; grpc_timer alarm; grpc_connectivity_state state; grpc_completion_queue *cq; grpc_cq_completion completion_storage; grpc_channel *channel; void *tag; } state_watcher; static void delete_state_watcher(grpc_exec_ctx *exec_ctx, state_watcher *w) { grpc_channel_element *client_channel_elem = grpc_channel_stack_last_element( grpc_channel_get_channel_stack(w->channel)); if (client_channel_elem->filter == &grpc_client_channel_filter) { GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, w->channel, "watch_channel_connectivity"); } else { abort(); } gpr_mu_destroy(&w->mu); gpr_free(w); } static void finished_completion(grpc_exec_ctx *exec_ctx, void *pw, grpc_cq_completion *ignored) { int delete = 0; state_watcher *w = pw; gpr_mu_lock(&w->mu); switch (w->phase) { case WAITING: case CALLED_BACK: GPR_UNREACHABLE_CODE(return ); case CALLING_BACK: w->phase = CALLED_BACK; break; case CALLING_BACK_AND_FINISHED: delete = 1; break; } gpr_mu_unlock(&w->mu); if (delete) { delete_state_watcher(exec_ctx, w); } } static void partly_done(grpc_exec_ctx *exec_ctx, state_watcher *w, bool due_to_completion, grpc_error *error) { int delete = 0; if (due_to_completion) { grpc_timer_cancel(exec_ctx, &w->alarm); } gpr_mu_lock(&w->mu); if (due_to_completion) { if (grpc_trace_operation_failures) { GRPC_LOG_IF_ERROR("watch_completion_error", GRPC_ERROR_REF(error)); } GRPC_ERROR_UNREF(error); error = GRPC_ERROR_NONE; } else { if (error == GRPC_ERROR_NONE) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Timed out waiting for connection state change"); } else if (error == GRPC_ERROR_CANCELLED) { error = GRPC_ERROR_NONE; } } switch (w->phase) { case WAITING: w->phase = CALLING_BACK; grpc_cq_end_op(exec_ctx, w->cq, w->tag, GRPC_ERROR_REF(error), finished_completion, w, &w->completion_storage); break; case CALLING_BACK: w->phase = CALLING_BACK_AND_FINISHED; break; case CALLING_BACK_AND_FINISHED: GPR_UNREACHABLE_CODE(return ); case CALLED_BACK: delete = 1; break; } gpr_mu_unlock(&w->mu); if (delete) { delete_state_watcher(exec_ctx, w); } GRPC_ERROR_UNREF(error); } static void watch_complete(grpc_exec_ctx *exec_ctx, void *pw, grpc_error *error) { partly_done(exec_ctx, pw, true, GRPC_ERROR_REF(error)); } static void timeout_complete(grpc_exec_ctx *exec_ctx, void *pw, grpc_error *error) { partly_done(exec_ctx, pw, false, GRPC_ERROR_REF(error)); } void grpc_channel_watch_connectivity_state( grpc_channel *channel, grpc_connectivity_state last_observed_state, gpr_timespec deadline, grpc_completion_queue *cq, void *tag) { grpc_channel_element *client_channel_elem = grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel)); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; state_watcher *w = gpr_malloc(sizeof(*w)); GRPC_API_TRACE( "grpc_channel_watch_connectivity_state(" "channel=%p, last_observed_state=%d, " "deadline=gpr_timespec { tv_sec: %" PRId64 ", tv_nsec: %d, clock_type: %d }, " "cq=%p, tag=%p)", 7, (channel, (int)last_observed_state, deadline.tv_sec, deadline.tv_nsec, (int)deadline.clock_type, cq, tag)); grpc_cq_begin_op(cq, tag); gpr_mu_init(&w->mu); grpc_closure_init(&w->on_complete, watch_complete, w, grpc_schedule_on_exec_ctx); grpc_closure_init(&w->on_timeout, timeout_complete, w, grpc_schedule_on_exec_ctx); w->phase = WAITING; w->state = last_observed_state; w->cq = cq; w->tag = tag; w->channel = channel; grpc_timer_init(&exec_ctx, &w->alarm, gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC), &w->on_timeout, gpr_now(GPR_CLOCK_MONOTONIC)); if (client_channel_elem->filter == &grpc_client_channel_filter) { GRPC_CHANNEL_INTERNAL_REF(channel, "watch_channel_connectivity"); grpc_client_channel_watch_connectivity_state(&exec_ctx, client_channel_elem, grpc_cq_pollset(cq), &w->state, &w->on_complete); } else { abort(); } grpc_exec_ctx_finish(&exec_ctx); } grpc-1.3.2/src/core/ext/filters/client_channel/client_channel.c000066400000000000000000001577671310511640000245350ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/filters/client_channel/client_channel.h" #include #include #include #include #include #include #include #include #include "src/core/ext/filters/client_channel/http_connect_handshaker.h" #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/proxy_mapper_registry.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/ext/filters/client_channel/retry_throttle.h" #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/channel/deadline_filter.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/support/string.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata_batch.h" #include "src/core/lib/transport/service_config.h" #include "src/core/lib/transport/static_metadata.h" /* Client channel implementation */ /************************************************************************* * METHOD-CONFIG TABLE */ typedef enum { /* zero so it can be default initialized */ WAIT_FOR_READY_UNSET = 0, WAIT_FOR_READY_FALSE, WAIT_FOR_READY_TRUE } wait_for_ready_value; typedef struct { gpr_refcount refs; gpr_timespec timeout; wait_for_ready_value wait_for_ready; } method_parameters; static method_parameters *method_parameters_ref( method_parameters *method_params) { gpr_ref(&method_params->refs); return method_params; } static void method_parameters_unref(method_parameters *method_params) { if (gpr_unref(&method_params->refs)) { gpr_free(method_params); } } static void *method_parameters_copy(void *value) { return method_parameters_ref(value); } static void method_parameters_free(grpc_exec_ctx *exec_ctx, void *value) { method_parameters_unref(value); } static const grpc_slice_hash_table_vtable method_parameters_vtable = { method_parameters_free, method_parameters_copy}; static bool parse_wait_for_ready(grpc_json *field, wait_for_ready_value *wait_for_ready) { if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) { return false; } *wait_for_ready = field->type == GRPC_JSON_TRUE ? WAIT_FOR_READY_TRUE : WAIT_FOR_READY_FALSE; return true; } static bool parse_timeout(grpc_json *field, gpr_timespec *timeout) { if (field->type != GRPC_JSON_STRING) return false; size_t len = strlen(field->value); if (field->value[len - 1] != 's') return false; char *buf = gpr_strdup(field->value); buf[len - 1] = '\0'; // Remove trailing 's'. char *decimal_point = strchr(buf, '.'); if (decimal_point != NULL) { *decimal_point = '\0'; timeout->tv_nsec = gpr_parse_nonnegative_int(decimal_point + 1); if (timeout->tv_nsec == -1) { gpr_free(buf); return false; } // There should always be exactly 3, 6, or 9 fractional digits. int multiplier = 1; switch (strlen(decimal_point + 1)) { case 9: break; case 6: multiplier *= 1000; break; case 3: multiplier *= 1000000; break; default: // Unsupported number of digits. gpr_free(buf); return false; } timeout->tv_nsec *= multiplier; } timeout->tv_sec = gpr_parse_nonnegative_int(buf); gpr_free(buf); if (timeout->tv_sec == -1) return false; return true; } static void *method_parameters_create_from_json(const grpc_json *json) { wait_for_ready_value wait_for_ready = WAIT_FOR_READY_UNSET; gpr_timespec timeout = {0, 0, GPR_TIMESPAN}; for (grpc_json *field = json->child; field != NULL; field = field->next) { if (field->key == NULL) continue; if (strcmp(field->key, "waitForReady") == 0) { if (wait_for_ready != WAIT_FOR_READY_UNSET) return NULL; // Duplicate. if (!parse_wait_for_ready(field, &wait_for_ready)) return NULL; } else if (strcmp(field->key, "timeout") == 0) { if (timeout.tv_sec > 0 || timeout.tv_nsec > 0) return NULL; // Duplicate. if (!parse_timeout(field, &timeout)) return NULL; } } method_parameters *value = gpr_malloc(sizeof(method_parameters)); gpr_ref_init(&value->refs, 1); value->timeout = timeout; value->wait_for_ready = wait_for_ready; return value; } /************************************************************************* * CHANNEL-WIDE FUNCTIONS */ typedef struct client_channel_channel_data { /** resolver for this channel */ grpc_resolver *resolver; /** have we started resolving this channel */ bool started_resolving; /** client channel factory */ grpc_client_channel_factory *client_channel_factory; /** combiner protecting all variables below in this data structure */ grpc_combiner *combiner; /** currently active load balancer */ grpc_lb_policy *lb_policy; /** retry throttle data */ grpc_server_retry_throttle_data *retry_throttle_data; /** maps method names to method_parameters structs */ grpc_slice_hash_table *method_params_table; /** incoming resolver result - set by resolver.next() */ grpc_channel_args *resolver_result; /** a list of closures that are all waiting for config to come in */ grpc_closure_list waiting_for_config_closures; /** resolver callback */ grpc_closure on_resolver_result_changed; /** connectivity state being tracked */ grpc_connectivity_state_tracker state_tracker; /** when an lb_policy arrives, should we try to exit idle */ bool exit_idle_when_lb_policy_arrives; /** owning stack */ grpc_channel_stack *owning_stack; /** interested parties (owned) */ grpc_pollset_set *interested_parties; /* the following properties are guarded by a mutex since API's require them to be instantaneously available */ gpr_mu info_mu; char *info_lb_policy_name; /** service config in JSON form */ char *info_service_config_json; } channel_data; /** We create one watcher for each new lb_policy that is returned from a resolver, to watch for state changes from the lb_policy. When a state change is seen, we update the channel, and create a new watcher. */ typedef struct { channel_data *chand; grpc_closure on_changed; grpc_connectivity_state state; grpc_lb_policy *lb_policy; } lb_policy_connectivity_watcher; static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand, grpc_lb_policy *lb_policy, grpc_connectivity_state current_state); static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx, channel_data *chand, grpc_connectivity_state state, grpc_error *error, const char *reason) { if ((state == GRPC_CHANNEL_TRANSIENT_FAILURE || state == GRPC_CHANNEL_SHUTDOWN) && chand->lb_policy != NULL) { /* cancel picks with wait_for_ready=false */ grpc_lb_policy_cancel_picks_locked( exec_ctx, chand->lb_policy, /* mask= */ GRPC_INITIAL_METADATA_WAIT_FOR_READY, /* check= */ 0, GRPC_ERROR_REF(error)); } grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, error, reason); } static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { lb_policy_connectivity_watcher *w = arg; grpc_connectivity_state publish_state = w->state; /* check if the notification is for the latest policy */ if (w->lb_policy == w->chand->lb_policy) { if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) { publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE; grpc_resolver_channel_saw_error_locked(exec_ctx, w->chand->resolver); GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel"); w->chand->lb_policy = NULL; } set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state, GRPC_ERROR_REF(error), "lb_changed"); if (w->state != GRPC_CHANNEL_SHUTDOWN) { watch_lb_policy_locked(exec_ctx, w->chand, w->lb_policy, w->state); } } GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy"); gpr_free(w); } static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand, grpc_lb_policy *lb_policy, grpc_connectivity_state current_state) { lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w)); GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy"); w->chand = chand; grpc_closure_init(&w->on_changed, on_lb_policy_state_changed_locked, w, grpc_combiner_scheduler(chand->combiner, false)); w->state = current_state; w->lb_policy = lb_policy; grpc_lb_policy_notify_on_state_change_locked(exec_ctx, lb_policy, &w->state, &w->on_changed); } typedef struct { char *server_name; grpc_server_retry_throttle_data *retry_throttle_data; } service_config_parsing_state; static void parse_retry_throttle_params(const grpc_json *field, void *arg) { service_config_parsing_state *parsing_state = arg; if (strcmp(field->key, "retryThrottling") == 0) { if (parsing_state->retry_throttle_data != NULL) return; // Duplicate. if (field->type != GRPC_JSON_OBJECT) return; int max_milli_tokens = 0; int milli_token_ratio = 0; for (grpc_json *sub_field = field->child; sub_field != NULL; sub_field = sub_field->next) { if (sub_field->key == NULL) return; if (strcmp(sub_field->key, "maxTokens") == 0) { if (max_milli_tokens != 0) return; // Duplicate. if (sub_field->type != GRPC_JSON_NUMBER) return; max_milli_tokens = gpr_parse_nonnegative_int(sub_field->value); if (max_milli_tokens == -1) return; max_milli_tokens *= 1000; } else if (strcmp(sub_field->key, "tokenRatio") == 0) { if (milli_token_ratio != 0) return; // Duplicate. if (sub_field->type != GRPC_JSON_NUMBER) return; // We support up to 3 decimal digits. size_t whole_len = strlen(sub_field->value); uint32_t multiplier = 1; uint32_t decimal_value = 0; const char *decimal_point = strchr(sub_field->value, '.'); if (decimal_point != NULL) { whole_len = (size_t)(decimal_point - sub_field->value); multiplier = 1000; size_t decimal_len = strlen(decimal_point + 1); if (decimal_len > 3) decimal_len = 3; if (!gpr_parse_bytes_to_uint32(decimal_point + 1, decimal_len, &decimal_value)) { return; } uint32_t decimal_multiplier = 1; for (size_t i = 0; i < (3 - decimal_len); ++i) { decimal_multiplier *= 10; } decimal_value *= decimal_multiplier; } uint32_t whole_value; if (!gpr_parse_bytes_to_uint32(sub_field->value, whole_len, &whole_value)) { return; } milli_token_ratio = (int)((whole_value * multiplier) + decimal_value); if (milli_token_ratio <= 0) return; } } parsing_state->retry_throttle_data = grpc_retry_throttle_map_get_data_for_server( parsing_state->server_name, max_milli_tokens, milli_token_ratio); } } static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { channel_data *chand = arg; char *lb_policy_name = NULL; grpc_lb_policy *lb_policy = NULL; grpc_lb_policy *old_lb_policy; grpc_slice_hash_table *method_params_table = NULL; grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE; bool exit_idle = false; grpc_error *state_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("No load balancing policy"); char *service_config_json = NULL; service_config_parsing_state parsing_state; memset(&parsing_state, 0, sizeof(parsing_state)); if (chand->resolver_result != NULL) { // Find LB policy name. const grpc_arg *channel_arg = grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_POLICY_NAME); if (channel_arg != NULL) { GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING); lb_policy_name = channel_arg->value.string; } // Special case: If all of the addresses are balancer addresses, // assume that we should use the grpclb policy, regardless of what the // resolver actually specified. channel_arg = grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_ADDRESSES); if (channel_arg != NULL && channel_arg->type == GRPC_ARG_POINTER) { grpc_lb_addresses *addresses = channel_arg->value.pointer.p; bool found_backend_address = false; for (size_t i = 0; i < addresses->num_addresses; ++i) { if (!addresses->addresses[i].is_balancer) { found_backend_address = true; break; } } if (!found_backend_address) { if (lb_policy_name != NULL && strcmp(lb_policy_name, "grpclb") != 0) { gpr_log(GPR_INFO, "resolver requested LB policy %s but provided only balancer " "addresses, no backend addresses -- forcing use of grpclb LB " "policy", lb_policy_name); } lb_policy_name = "grpclb"; } } // Use pick_first if nothing was specified and we didn't select grpclb // above. if (lb_policy_name == NULL) lb_policy_name = "pick_first"; // Instantiate LB policy. grpc_lb_policy_args lb_policy_args; lb_policy_args.args = chand->resolver_result; lb_policy_args.client_channel_factory = chand->client_channel_factory; lb_policy_args.combiner = chand->combiner; lb_policy = grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args); if (lb_policy != NULL) { GRPC_LB_POLICY_REF(lb_policy, "config_change"); GRPC_ERROR_UNREF(state_error); state = grpc_lb_policy_check_connectivity_locked(exec_ctx, lb_policy, &state_error); } // Find service config. channel_arg = grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVICE_CONFIG); if (channel_arg != NULL) { GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING); service_config_json = gpr_strdup(channel_arg->value.string); grpc_service_config *service_config = grpc_service_config_create(service_config_json); if (service_config != NULL) { channel_arg = grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVER_URI); GPR_ASSERT(channel_arg != NULL); GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING); grpc_uri *uri = grpc_uri_parse(exec_ctx, channel_arg->value.string, true); GPR_ASSERT(uri->path[0] != '\0'); parsing_state.server_name = uri->path[0] == '/' ? uri->path + 1 : uri->path; grpc_service_config_parse_global_params( service_config, parse_retry_throttle_params, &parsing_state); parsing_state.server_name = NULL; grpc_uri_destroy(uri); method_params_table = grpc_service_config_create_method_config_table( exec_ctx, service_config, method_parameters_create_from_json, &method_parameters_vtable); grpc_service_config_destroy(service_config); } } // Before we clean up, save a copy of lb_policy_name, since it might // be pointing to data inside chand->resolver_result. // The copy will be saved in chand->lb_policy_name below. lb_policy_name = gpr_strdup(lb_policy_name); grpc_channel_args_destroy(exec_ctx, chand->resolver_result); chand->resolver_result = NULL; } if (lb_policy != NULL) { grpc_pollset_set_add_pollset_set(exec_ctx, lb_policy->interested_parties, chand->interested_parties); } gpr_mu_lock(&chand->info_mu); if (lb_policy_name != NULL) { gpr_free(chand->info_lb_policy_name); chand->info_lb_policy_name = lb_policy_name; } old_lb_policy = chand->lb_policy; chand->lb_policy = lb_policy; if (service_config_json != NULL) { gpr_free(chand->info_service_config_json); chand->info_service_config_json = service_config_json; } gpr_mu_unlock(&chand->info_mu); if (chand->retry_throttle_data != NULL) { grpc_server_retry_throttle_data_unref(chand->retry_throttle_data); } chand->retry_throttle_data = parsing_state.retry_throttle_data; if (chand->method_params_table != NULL) { grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table); } chand->method_params_table = method_params_table; if (lb_policy != NULL) { grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures); } else if (chand->resolver == NULL /* disconnected */) { grpc_closure_list_fail_all(&chand->waiting_for_config_closures, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Channel disconnected", &error, 1)); grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures); } if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) { GRPC_LB_POLICY_REF(lb_policy, "exit_idle"); exit_idle = true; chand->exit_idle_when_lb_policy_arrives = false; } if (error == GRPC_ERROR_NONE && chand->resolver) { set_channel_connectivity_state_locked( exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver"); if (lb_policy != NULL) { watch_lb_policy_locked(exec_ctx, chand, lb_policy, state); } GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver"); grpc_resolver_next_locked(exec_ctx, chand->resolver, &chand->resolver_result, &chand->on_resolver_result_changed); } else { if (chand->resolver != NULL) { grpc_resolver_shutdown_locked(exec_ctx, chand->resolver); GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel"); chand->resolver = NULL; } grpc_error *refs[] = {error, state_error}; set_channel_connectivity_state_locked( exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Got config after disconnection", refs, GPR_ARRAY_SIZE(refs)), "resolver_gone"); } if (exit_idle) { grpc_lb_policy_exit_idle_locked(exec_ctx, lb_policy); GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle"); } if (old_lb_policy != NULL) { grpc_pollset_set_del_pollset_set( exec_ctx, old_lb_policy->interested_parties, chand->interested_parties); GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel"); } if (lb_policy != NULL) { GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change"); } GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver"); GRPC_ERROR_UNREF(state_error); } static void start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error_ignored) { grpc_transport_op *op = arg; grpc_channel_element *elem = op->handler_private.extra_arg; channel_data *chand = elem->channel_data; if (op->on_connectivity_state_change != NULL) { grpc_connectivity_state_notify_on_state_change( exec_ctx, &chand->state_tracker, op->connectivity_state, op->on_connectivity_state_change); op->on_connectivity_state_change = NULL; op->connectivity_state = NULL; } if (op->send_ping != NULL) { if (chand->lb_policy == NULL) { grpc_closure_sched( exec_ctx, op->send_ping, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Ping with no load balancing")); } else { grpc_lb_policy_ping_one_locked(exec_ctx, chand->lb_policy, op->send_ping); op->bind_pollset = NULL; } op->send_ping = NULL; } if (op->disconnect_with_error != GRPC_ERROR_NONE) { if (chand->resolver != NULL) { set_channel_connectivity_state_locked( exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_REF(op->disconnect_with_error), "disconnect"); grpc_resolver_shutdown_locked(exec_ctx, chand->resolver); GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel"); chand->resolver = NULL; if (!chand->started_resolving) { grpc_closure_list_fail_all(&chand->waiting_for_config_closures, GRPC_ERROR_REF(op->disconnect_with_error)); grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures); } if (chand->lb_policy != NULL) { grpc_pollset_set_del_pollset_set(exec_ctx, chand->lb_policy->interested_parties, chand->interested_parties); GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel"); chand->lb_policy = NULL; } } GRPC_ERROR_UNREF(op->disconnect_with_error); } GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "start_transport_op"); grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE); } static void cc_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_transport_op *op) { channel_data *chand = elem->channel_data; GPR_ASSERT(op->set_accept_stream == false); if (op->bind_pollset != NULL) { grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, op->bind_pollset); } op->handler_private.extra_arg = elem; GRPC_CHANNEL_STACK_REF(chand->owning_stack, "start_transport_op"); grpc_closure_sched( exec_ctx, grpc_closure_init(&op->handler_private.closure, start_transport_op_locked, op, grpc_combiner_scheduler(chand->combiner, false)), GRPC_ERROR_NONE); } static void cc_get_channel_info(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, const grpc_channel_info *info) { channel_data *chand = elem->channel_data; gpr_mu_lock(&chand->info_mu); if (info->lb_policy_name != NULL) { *info->lb_policy_name = chand->info_lb_policy_name == NULL ? NULL : gpr_strdup(chand->info_lb_policy_name); } if (info->service_config_json != NULL) { *info->service_config_json = chand->info_service_config_json == NULL ? NULL : gpr_strdup(chand->info_service_config_json); } gpr_mu_unlock(&chand->info_mu); } /* Constructor for channel_data */ static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_channel_element_args *args) { channel_data *chand = elem->channel_data; GPR_ASSERT(args->is_last); GPR_ASSERT(elem->filter == &grpc_client_channel_filter); // Initialize data members. chand->combiner = grpc_combiner_create(NULL); gpr_mu_init(&chand->info_mu); chand->owning_stack = args->channel_stack; grpc_closure_init(&chand->on_resolver_result_changed, on_resolver_result_changed_locked, chand, grpc_combiner_scheduler(chand->combiner, false)); chand->interested_parties = grpc_pollset_set_create(); grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE, "client_channel"); // Record client channel factory. const grpc_arg *arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_CLIENT_CHANNEL_FACTORY); if (arg == NULL) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Missing client channel factory in args for client channel filter"); } if (arg->type != GRPC_ARG_POINTER) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "client channel factory arg must be a pointer"); } grpc_client_channel_factory_ref(arg->value.pointer.p); chand->client_channel_factory = arg->value.pointer.p; // Get server name to resolve, using proxy mapper if needed. arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI); if (arg == NULL) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Missing server uri in args for client channel filter"); } if (arg->type != GRPC_ARG_STRING) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "server uri arg must be a string"); } char *proxy_name = NULL; grpc_channel_args *new_args = NULL; grpc_proxy_mappers_map_name(exec_ctx, arg->value.string, args->channel_args, &proxy_name, &new_args); // Instantiate resolver. chand->resolver = grpc_resolver_create( exec_ctx, proxy_name != NULL ? proxy_name : arg->value.string, new_args != NULL ? new_args : args->channel_args, chand->interested_parties, chand->combiner); if (proxy_name != NULL) gpr_free(proxy_name); if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args); if (chand->resolver == NULL) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("resolver creation failed"); } return GRPC_ERROR_NONE; } static void shutdown_resolver_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_resolver *resolver = arg; grpc_resolver_shutdown_locked(exec_ctx, resolver); GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel"); } /* Destructor for channel_data */ static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) { channel_data *chand = elem->channel_data; if (chand->resolver != NULL) { grpc_closure_sched( exec_ctx, grpc_closure_create(shutdown_resolver_locked, chand->resolver, grpc_combiner_scheduler(chand->combiner, false)), GRPC_ERROR_NONE); } if (chand->client_channel_factory != NULL) { grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory); } if (chand->lb_policy != NULL) { grpc_pollset_set_del_pollset_set(exec_ctx, chand->lb_policy->interested_parties, chand->interested_parties); GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel"); } gpr_free(chand->info_lb_policy_name); gpr_free(chand->info_service_config_json); if (chand->retry_throttle_data != NULL) { grpc_server_retry_throttle_data_unref(chand->retry_throttle_data); } if (chand->method_params_table != NULL) { grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table); } grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker); grpc_pollset_set_destroy(exec_ctx, chand->interested_parties); GRPC_COMBINER_UNREF(exec_ctx, chand->combiner, "client_channel"); gpr_mu_destroy(&chand->info_mu); } /************************************************************************* * PER-CALL FUNCTIONS */ #define GET_CALL(call_data) \ ((grpc_subchannel_call *)(gpr_atm_acq_load(&(call_data)->subchannel_call))) #define CANCELLED_CALL ((grpc_subchannel_call *)1) typedef enum { /* zero so that it can be default-initialized */ GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING = 0, GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL } subchannel_creation_phase; /** Call data. Holds a pointer to grpc_subchannel_call and the associated machinery to create such a pointer. Handles queueing of stream ops until a call object is ready, waiting for initial metadata before trying to create a call object, and handling cancellation gracefully. */ typedef struct client_channel_call_data { // State for handling deadlines. // The code in deadline_filter.c requires this to be the first field. // TODO(roth): This is slightly sub-optimal in that grpc_deadline_state // and this struct both independently store a pointer to the call // stack and each has its own mutex. If/when we have time, find a way // to avoid this without breaking the grpc_deadline_state abstraction. grpc_deadline_state deadline_state; grpc_slice path; // Request path. gpr_timespec call_start_time; gpr_timespec deadline; grpc_server_retry_throttle_data *retry_throttle_data; method_parameters *method_params; grpc_error *cancel_error; /** either 0 for no call, 1 for cancelled, or a pointer to a grpc_subchannel_call */ gpr_atm subchannel_call; gpr_arena *arena; subchannel_creation_phase creation_phase; grpc_connected_subchannel *connected_subchannel; grpc_polling_entity *pollent; grpc_transport_stream_op_batch **waiting_ops; size_t waiting_ops_count; size_t waiting_ops_capacity; grpc_closure next_step; grpc_call_stack *owning_call; grpc_linked_mdelem lb_token_mdelem; grpc_closure on_complete; grpc_closure *original_on_complete; } call_data; grpc_subchannel_call *grpc_client_channel_get_subchannel_call( grpc_call_element *call_elem) { grpc_subchannel_call *scc = GET_CALL((call_data *)call_elem->call_data); return scc == CANCELLED_CALL ? NULL : scc; } static void add_waiting_locked(call_data *calld, grpc_transport_stream_op_batch *op) { GPR_TIMER_BEGIN("add_waiting_locked", 0); if (calld->waiting_ops_count == calld->waiting_ops_capacity) { calld->waiting_ops_capacity = GPR_MAX(3, 2 * calld->waiting_ops_capacity); calld->waiting_ops = gpr_realloc(calld->waiting_ops, calld->waiting_ops_capacity * sizeof(*calld->waiting_ops)); } calld->waiting_ops[calld->waiting_ops_count++] = op; GPR_TIMER_END("add_waiting_locked", 0); } static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld, grpc_error *error) { size_t i; for (i = 0; i < calld->waiting_ops_count; i++) { grpc_transport_stream_op_batch_finish_with_failure( exec_ctx, calld->waiting_ops[i], GRPC_ERROR_REF(error)); } calld->waiting_ops_count = 0; GRPC_ERROR_UNREF(error); } static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) { if (calld->waiting_ops_count == 0) { return; } grpc_subchannel_call *call = GET_CALL(calld); grpc_transport_stream_op_batch **ops = calld->waiting_ops; size_t nops = calld->waiting_ops_count; if (call == CANCELLED_CALL) { fail_locked(exec_ctx, calld, GRPC_ERROR_CANCELLED); return; } calld->waiting_ops = NULL; calld->waiting_ops_count = 0; calld->waiting_ops_capacity = 0; for (size_t i = 0; i < nops; i++) { grpc_subchannel_call_process_op(exec_ctx, call, ops[i]); } gpr_free(ops); } // Sets calld->method_params and calld->retry_throttle_data. // If the method params specify a timeout, populates // *per_method_deadline and returns true. static bool set_call_method_params_from_service_config_locked( grpc_exec_ctx *exec_ctx, grpc_call_element *elem, gpr_timespec *per_method_deadline) { channel_data *chand = elem->channel_data; call_data *calld = elem->call_data; if (chand->retry_throttle_data != NULL) { calld->retry_throttle_data = grpc_server_retry_throttle_data_ref(chand->retry_throttle_data); } if (chand->method_params_table != NULL) { calld->method_params = grpc_method_config_table_get( exec_ctx, chand->method_params_table, calld->path); if (calld->method_params != NULL) { method_parameters_ref(calld->method_params); if (gpr_time_cmp(calld->method_params->timeout, gpr_time_0(GPR_TIMESPAN)) != 0) { *per_method_deadline = gpr_time_add(calld->call_start_time, calld->method_params->timeout); return true; } } } return false; } static void apply_final_configuration_locked(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { /* apply service-config level configuration to the call (now that we're * certain it exists) */ call_data *calld = elem->call_data; gpr_timespec per_method_deadline; if (set_call_method_params_from_service_config_locked(exec_ctx, elem, &per_method_deadline)) { // If the deadline from the service config is shorter than the one // from the client API, reset the deadline timer. if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) { calld->deadline = per_method_deadline; grpc_deadline_state_reset(exec_ctx, elem, calld->deadline); } } } static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_call_element *elem = arg; call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL); grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent, chand->interested_parties); calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING; if (calld->connected_subchannel == NULL) { gpr_atm_no_barrier_store(&calld->subchannel_call, 1); fail_locked(exec_ctx, calld, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Failed to create subchannel", &error, 1)); } else if (GET_CALL(calld) == CANCELLED_CALL) { /* already cancelled before subchannel became ready */ grpc_error *cancellation_error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Cancelled before creating subchannel", &error, 1); /* if due to deadline, attach the deadline exceeded status to the error */ if (gpr_time_cmp(calld->deadline, gpr_now(GPR_CLOCK_MONOTONIC)) < 0) { cancellation_error = grpc_error_set_int(cancellation_error, GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_DEADLINE_EXCEEDED); } fail_locked(exec_ctx, calld, cancellation_error); } else { /* Create call on subchannel. */ grpc_subchannel_call *subchannel_call = NULL; const grpc_connected_subchannel_call_args call_args = { .pollent = calld->pollent, .path = calld->path, .start_time = calld->call_start_time, .deadline = calld->deadline, .arena = calld->arena}; grpc_error *new_error = grpc_connected_subchannel_create_call( exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call); gpr_atm_rel_store(&calld->subchannel_call, (gpr_atm)(uintptr_t)subchannel_call); if (new_error != GRPC_ERROR_NONE) { new_error = grpc_error_add_child(new_error, error); fail_locked(exec_ctx, calld, new_error); } else { retry_waiting_locked(exec_ctx, calld); } } GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel"); } static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { call_data *calld = elem->call_data; grpc_subchannel_call *subchannel_call = GET_CALL(calld); if (subchannel_call == NULL || subchannel_call == CANCELLED_CALL) { return NULL; } else { return grpc_subchannel_call_get_peer(exec_ctx, subchannel_call); } } typedef struct { grpc_metadata_batch *initial_metadata; uint32_t initial_metadata_flags; grpc_connected_subchannel **connected_subchannel; grpc_closure *on_ready; grpc_call_element *elem; grpc_closure closure; } continue_picking_args; /** Return true if subchannel is available immediately (in which case on_ready should not be called), or false otherwise (in which case on_ready should be called when the subchannel is available). */ static bool pick_subchannel_locked( grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags, grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready, grpc_error *error); static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { continue_picking_args *cpa = arg; if (cpa->connected_subchannel == NULL) { /* cancelled, do nothing */ } else if (error != GRPC_ERROR_NONE) { grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error)); } else { if (pick_subchannel_locked(exec_ctx, cpa->elem, cpa->initial_metadata, cpa->initial_metadata_flags, cpa->connected_subchannel, cpa->on_ready, GRPC_ERROR_NONE)) { grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE); } } gpr_free(cpa); } static bool pick_subchannel_locked( grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags, grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready, grpc_error *error) { GPR_TIMER_BEGIN("pick_subchannel", 0); channel_data *chand = elem->channel_data; call_data *calld = elem->call_data; continue_picking_args *cpa; grpc_closure *closure; GPR_ASSERT(connected_subchannel); if (initial_metadata == NULL) { if (chand->lb_policy != NULL) { grpc_lb_policy_cancel_pick_locked(exec_ctx, chand->lb_policy, connected_subchannel, GRPC_ERROR_REF(error)); } for (closure = chand->waiting_for_config_closures.head; closure != NULL; closure = closure->next_data.next) { cpa = closure->cb_arg; if (cpa->connected_subchannel == connected_subchannel) { cpa->connected_subchannel = NULL; grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Pick cancelled", &error, 1)); } } GPR_TIMER_END("pick_subchannel", 0); GRPC_ERROR_UNREF(error); return true; } GPR_ASSERT(error == GRPC_ERROR_NONE); if (chand->lb_policy != NULL) { apply_final_configuration_locked(exec_ctx, elem); grpc_lb_policy *lb_policy = chand->lb_policy; GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel"); // If the application explicitly set wait_for_ready, use that. // Otherwise, if the service config specified a value for this // method, use that. const bool wait_for_ready_set_from_api = initial_metadata_flags & GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET; const bool wait_for_ready_set_from_service_config = calld->method_params != NULL && calld->method_params->wait_for_ready != WAIT_FOR_READY_UNSET; if (!wait_for_ready_set_from_api && wait_for_ready_set_from_service_config) { if (calld->method_params->wait_for_ready == WAIT_FOR_READY_TRUE) { initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY; } else { initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY; } } const grpc_lb_policy_pick_args inputs = { initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem, gpr_inf_future(GPR_CLOCK_MONOTONIC)}; const bool result = grpc_lb_policy_pick_locked( exec_ctx, lb_policy, &inputs, connected_subchannel, NULL, on_ready); GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick_subchannel"); GPR_TIMER_END("pick_subchannel", 0); return result; } if (chand->resolver != NULL && !chand->started_resolving) { chand->started_resolving = true; GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver"); grpc_resolver_next_locked(exec_ctx, chand->resolver, &chand->resolver_result, &chand->on_resolver_result_changed); } if (chand->resolver != NULL) { cpa = gpr_malloc(sizeof(*cpa)); cpa->initial_metadata = initial_metadata; cpa->initial_metadata_flags = initial_metadata_flags; cpa->connected_subchannel = connected_subchannel; cpa->on_ready = on_ready; cpa->elem = elem; grpc_closure_init(&cpa->closure, continue_picking_locked, cpa, grpc_combiner_scheduler(chand->combiner, true)); grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure, GRPC_ERROR_NONE); } else { grpc_closure_sched(exec_ctx, on_ready, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected")); } GPR_TIMER_END("pick_subchannel", 0); return false; } static void start_transport_stream_op_batch_locked_inner( grpc_exec_ctx *exec_ctx, grpc_transport_stream_op_batch *op, grpc_call_element *elem) { channel_data *chand = elem->channel_data; call_data *calld = elem->call_data; grpc_subchannel_call *call; /* need to recheck that another thread hasn't set the call */ call = GET_CALL(calld); if (call == CANCELLED_CALL) { grpc_transport_stream_op_batch_finish_with_failure( exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error)); /* early out */ return; } if (call != NULL) { grpc_subchannel_call_process_op(exec_ctx, call, op); /* early out */ return; } /* if this is a cancellation, then we can raise our cancelled flag */ if (op->cancel_stream) { if (!gpr_atm_rel_cas(&calld->subchannel_call, 0, (gpr_atm)(uintptr_t)CANCELLED_CALL)) { /* recurse to retry */ start_transport_stream_op_batch_locked_inner(exec_ctx, op, elem); /* early out */ return; } else { /* Stash a copy of cancel_error in our call data, so that we can use it for subsequent operations. This ensures that if the call is cancelled before any ops are passed down (e.g., if the deadline is in the past when the call starts), we can return the right error to the caller when the first op does get passed down. */ calld->cancel_error = GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error); switch (calld->creation_phase) { case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING: fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error)); break; case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL: pick_subchannel_locked( exec_ctx, elem, NULL, 0, &calld->connected_subchannel, NULL, GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error)); break; } grpc_transport_stream_op_batch_finish_with_failure( exec_ctx, op, GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error)); /* early out */ return; } } /* if we don't have a subchannel, try to get one */ if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING && calld->connected_subchannel == NULL && op->send_initial_metadata) { calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL; grpc_closure_init(&calld->next_step, subchannel_ready_locked, elem, grpc_combiner_scheduler(chand->combiner, true)); GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel"); /* If a subchannel is not available immediately, the polling entity from call_data should be provided to channel_data's interested_parties, so that IO of the lb_policy and resolver could be done under it. */ if (pick_subchannel_locked( exec_ctx, elem, op->payload->send_initial_metadata.send_initial_metadata, op->payload->send_initial_metadata.send_initial_metadata_flags, &calld->connected_subchannel, &calld->next_step, GRPC_ERROR_NONE)) { calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING; GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel"); } else { grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent, chand->interested_parties); } } /* if we've got a subchannel, then let's ask it to create a call */ if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING && calld->connected_subchannel != NULL) { grpc_subchannel_call *subchannel_call = NULL; const grpc_connected_subchannel_call_args call_args = { .pollent = calld->pollent, .path = calld->path, .start_time = calld->call_start_time, .deadline = calld->deadline, .arena = calld->arena}; grpc_error *error = grpc_connected_subchannel_create_call( exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call); gpr_atm_rel_store(&calld->subchannel_call, (gpr_atm)(uintptr_t)subchannel_call); if (error != GRPC_ERROR_NONE) { fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error)); grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, op, error); } else { retry_waiting_locked(exec_ctx, calld); /* recurse to retry */ start_transport_stream_op_batch_locked_inner(exec_ctx, op, elem); } /* early out */ return; } /* nothing to be done but wait */ add_waiting_locked(calld, op); } static void on_complete(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_call_element *elem = arg; call_data *calld = elem->call_data; if (calld->retry_throttle_data != NULL) { if (error == GRPC_ERROR_NONE) { grpc_server_retry_throttle_data_record_success( calld->retry_throttle_data); } else { // TODO(roth): In a subsequent PR, check the return value here and // decide whether or not to retry. Note that we should only // record failures whose statuses match the configured retryable // or non-fatal status codes. grpc_server_retry_throttle_data_record_failure( calld->retry_throttle_data); } } grpc_closure_run(exec_ctx, calld->original_on_complete, GRPC_ERROR_REF(error)); } static void start_transport_stream_op_batch_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error_ignored) { GPR_TIMER_BEGIN("start_transport_stream_op_batch_locked", 0); grpc_transport_stream_op_batch *op = arg; grpc_call_element *elem = op->handler_private.extra_arg; call_data *calld = elem->call_data; if (op->recv_trailing_metadata) { GPR_ASSERT(op->on_complete != NULL); calld->original_on_complete = op->on_complete; grpc_closure_init(&calld->on_complete, on_complete, elem, grpc_schedule_on_exec_ctx); op->on_complete = &calld->on_complete; } start_transport_stream_op_batch_locked_inner(exec_ctx, op, elem); GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "start_transport_stream_op_batch"); GPR_TIMER_END("start_transport_stream_op_batch_locked", 0); } /* The logic here is fairly complicated, due to (a) the fact that we need to handle the case where we receive the send op before the initial metadata op, and (b) the need for efficiency, especially in the streaming case. We use double-checked locking to initially see if initialization has been performed. If it has not, we acquire the combiner and perform initialization. If it has, we proceed on the fast path. */ static void cc_start_transport_stream_op_batch( grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op_batch *op) { call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; GRPC_CALL_LOG_OP(GPR_INFO, elem, op); grpc_deadline_state_client_start_transport_stream_op_batch(exec_ctx, elem, op); /* try to (atomically) get the call */ grpc_subchannel_call *call = GET_CALL(calld); GPR_TIMER_BEGIN("cc_start_transport_stream_op_batch", 0); if (call == CANCELLED_CALL) { grpc_transport_stream_op_batch_finish_with_failure( exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error)); GPR_TIMER_END("cc_start_transport_stream_op_batch", 0); /* early out */ return; } if (call != NULL) { grpc_subchannel_call_process_op(exec_ctx, call, op); GPR_TIMER_END("cc_start_transport_stream_op_batch", 0); /* early out */ return; } /* we failed; lock and figure out what to do */ GRPC_CALL_STACK_REF(calld->owning_call, "start_transport_stream_op_batch"); op->handler_private.extra_arg = elem; grpc_closure_sched( exec_ctx, grpc_closure_init(&op->handler_private.closure, start_transport_stream_op_batch_locked, op, grpc_combiner_scheduler(chand->combiner, false)), GRPC_ERROR_NONE); GPR_TIMER_END("cc_start_transport_stream_op_batch", 0); } /* Constructor for call_data */ static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_element_args *args) { call_data *calld = elem->call_data; // Initialize data members. grpc_deadline_state_init(exec_ctx, elem, args->call_stack); calld->path = grpc_slice_ref_internal(args->path); calld->call_start_time = args->start_time; calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC); calld->owning_call = args->call_stack; calld->arena = args->arena; grpc_deadline_state_start(exec_ctx, elem, calld->deadline); return GRPC_ERROR_NONE; } /* Destructor for call_data */ static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, grpc_closure *then_schedule_closure) { call_data *calld = elem->call_data; grpc_deadline_state_destroy(exec_ctx, elem); grpc_slice_unref_internal(exec_ctx, calld->path); if (calld->method_params != NULL) { method_parameters_unref(calld->method_params); } GRPC_ERROR_UNREF(calld->cancel_error); grpc_subchannel_call *call = GET_CALL(calld); if (call != NULL && call != CANCELLED_CALL) { grpc_subchannel_call_set_cleanup_closure(call, then_schedule_closure); then_schedule_closure = NULL; GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call"); } GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING); GPR_ASSERT(calld->waiting_ops_count == 0); if (calld->connected_subchannel != NULL) { GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel, "picked"); } gpr_free(calld->waiting_ops); grpc_closure_sched(exec_ctx, then_schedule_closure, GRPC_ERROR_NONE); } static void cc_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_polling_entity *pollent) { call_data *calld = elem->call_data; calld->pollent = pollent; } /************************************************************************* * EXPORTED SYMBOLS */ const grpc_channel_filter grpc_client_channel_filter = { cc_start_transport_stream_op_batch, cc_start_transport_op, sizeof(call_data), cc_init_call_elem, cc_set_pollset_or_pollset_set, cc_destroy_call_elem, sizeof(channel_data), cc_init_channel_elem, cc_destroy_channel_elem, cc_get_peer, cc_get_channel_info, "client-channel", }; static void try_to_connect_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error_ignored) { channel_data *chand = arg; if (chand->lb_policy != NULL) { grpc_lb_policy_exit_idle_locked(exec_ctx, chand->lb_policy); } else { chand->exit_idle_when_lb_policy_arrives = true; if (!chand->started_resolving && chand->resolver != NULL) { GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver"); chand->started_resolving = true; grpc_resolver_next_locked(exec_ctx, chand->resolver, &chand->resolver_result, &chand->on_resolver_result_changed); } } GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "try_to_connect"); } grpc_connectivity_state grpc_client_channel_check_connectivity_state( grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) { channel_data *chand = elem->channel_data; grpc_connectivity_state out = grpc_connectivity_state_check(&chand->state_tracker); if (out == GRPC_CHANNEL_IDLE && try_to_connect) { GRPC_CHANNEL_STACK_REF(chand->owning_stack, "try_to_connect"); grpc_closure_sched( exec_ctx, grpc_closure_create(try_to_connect_locked, chand, grpc_combiner_scheduler(chand->combiner, false)), GRPC_ERROR_NONE); } return out; } typedef struct { channel_data *chand; grpc_pollset *pollset; grpc_closure *on_complete; grpc_connectivity_state *state; grpc_closure my_closure; } external_connectivity_watcher; static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { external_connectivity_watcher *w = arg; grpc_closure *follow_up = w->on_complete; grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties, w->pollset); GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "external_connectivity_watcher"); gpr_free(w); grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error)); } static void watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error_ignored) { external_connectivity_watcher *w = arg; grpc_closure_init(&w->my_closure, on_external_watch_complete, w, grpc_schedule_on_exec_ctx); grpc_connectivity_state_notify_on_state_change( exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure); } void grpc_client_channel_watch_connectivity_state( grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset, grpc_connectivity_state *state, grpc_closure *on_complete) { channel_data *chand = elem->channel_data; external_connectivity_watcher *w = gpr_malloc(sizeof(*w)); w->chand = chand; w->pollset = pollset; w->on_complete = on_complete; w->state = state; grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset); GRPC_CHANNEL_STACK_REF(w->chand->owning_stack, "external_connectivity_watcher"); grpc_closure_sched( exec_ctx, grpc_closure_init(&w->my_closure, watch_connectivity_state_locked, w, grpc_combiner_scheduler(chand->combiner, true)), GRPC_ERROR_NONE); } grpc-1.3.2/src/core/ext/filters/client_channel/client_channel.h000066400000000000000000000054721310511640000245230ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_H #include "src/core/ext/filters/client_channel/client_channel_factory.h" #include "src/core/ext/filters/client_channel/resolver.h" #include "src/core/lib/channel/channel_stack.h" // Channel arg key for server URI string. #define GRPC_ARG_SERVER_URI "grpc.server_uri" /* A client channel is a channel that begins disconnected, and can connect to some endpoint on demand. If that endpoint disconnects, it will be connected to again later. Calls on a disconnected client channel are queued until a connection is established. */ extern const grpc_channel_filter grpc_client_channel_filter; grpc_connectivity_state grpc_client_channel_check_connectivity_state( grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect); void grpc_client_channel_watch_connectivity_state( grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset, grpc_connectivity_state *state, grpc_closure *on_complete); /* Debug helper: pull the subchannel call from a call stack element */ grpc_subchannel_call *grpc_client_channel_get_subchannel_call( grpc_call_element *elem); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_H */ grpc-1.3.2/src/core/ext/filters/client_channel/client_channel_factory.c000066400000000000000000000066001310511640000262370ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/filters/client_channel/client_channel_factory.h" void grpc_client_channel_factory_ref(grpc_client_channel_factory* factory) { factory->vtable->ref(factory); } void grpc_client_channel_factory_unref(grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory) { factory->vtable->unref(exec_ctx, factory); } grpc_subchannel* grpc_client_channel_factory_create_subchannel( grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory, const grpc_subchannel_args* args) { return factory->vtable->create_subchannel(exec_ctx, factory, args); } grpc_channel* grpc_client_channel_factory_create_channel( grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory, const char* target, grpc_client_channel_type type, const grpc_channel_args* args) { return factory->vtable->create_client_channel(exec_ctx, factory, target, type, args); } static void* factory_arg_copy(void* factory) { grpc_client_channel_factory_ref(factory); return factory; } static void factory_arg_destroy(grpc_exec_ctx* exec_ctx, void* factory) { // TODO(roth): Remove local exec_ctx when // https://github.com/grpc/grpc/pull/8705 is merged. grpc_client_channel_factory_unref(exec_ctx, factory); } static int factory_arg_cmp(void* factory1, void* factory2) { if (factory1 < factory2) return -1; if (factory1 > factory2) return 1; return 0; } static const grpc_arg_pointer_vtable factory_arg_vtable = { factory_arg_copy, factory_arg_destroy, factory_arg_cmp}; grpc_arg grpc_client_channel_factory_create_channel_arg( grpc_client_channel_factory* factory) { grpc_arg arg; arg.type = GRPC_ARG_POINTER; arg.key = GRPC_ARG_CLIENT_CHANNEL_FACTORY; arg.value.pointer.p = factory; arg.value.pointer.vtable = &factory_arg_vtable; return arg; } grpc-1.3.2/src/core/ext/filters/client_channel/client_channel_factory.h000066400000000000000000000102011310511640000262340ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_FACTORY_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_FACTORY_H #include #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/channel/channel_stack.h" // Channel arg key for client channel factory. #define GRPC_ARG_CLIENT_CHANNEL_FACTORY "grpc.client_channel_factory" typedef struct grpc_client_channel_factory grpc_client_channel_factory; typedef struct grpc_client_channel_factory_vtable grpc_client_channel_factory_vtable; typedef enum { GRPC_CLIENT_CHANNEL_TYPE_REGULAR, /** for the user-level regular calls */ GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, /** for communication with a load balancing service */ } grpc_client_channel_type; /** Constructor for new configured channels. Creating decorators around this type is encouraged to adapt behavior. */ struct grpc_client_channel_factory { const grpc_client_channel_factory_vtable *vtable; }; struct grpc_client_channel_factory_vtable { void (*ref)(grpc_client_channel_factory *factory); void (*unref)(grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory); grpc_subchannel *(*create_subchannel)(grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory, const grpc_subchannel_args *args); grpc_channel *(*create_client_channel)(grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory, const char *target, grpc_client_channel_type type, const grpc_channel_args *args); }; void grpc_client_channel_factory_ref(grpc_client_channel_factory *factory); void grpc_client_channel_factory_unref(grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory); /** Create a new grpc_subchannel */ grpc_subchannel *grpc_client_channel_factory_create_subchannel( grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory, const grpc_subchannel_args *args); /** Create a new grpc_channel */ grpc_channel *grpc_client_channel_factory_create_channel( grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory, const char *target, grpc_client_channel_type type, const grpc_channel_args *args); grpc_arg grpc_client_channel_factory_create_channel_arg( grpc_client_channel_factory *factory); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_FACTORY_H */ grpc-1.3.2/src/core/ext/filters/client_channel/client_channel_plugin.c000066400000000000000000000106361310511640000260720ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/filters/client_channel/http_connect_handshaker.h" #include "src/core/ext/filters/client_channel/http_proxy.h" #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/proxy_mapper_registry.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/ext/filters/client_channel/retry_throttle.h" #include "src/core/ext/filters/client_channel/subchannel_index.h" #include "src/core/lib/surface/channel_init.h" static bool append_filter(grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, void *arg) { return grpc_channel_stack_builder_append_filter( builder, (const grpc_channel_filter *)arg, NULL, NULL); } static bool set_default_host_if_unset(grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, void *unused) { const grpc_channel_args *args = grpc_channel_stack_builder_get_channel_arguments(builder); for (size_t i = 0; i < args->num_args; i++) { if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY) || 0 == strcmp(args->args[i].key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) { return true; } } char *default_authority = grpc_get_default_authority( exec_ctx, grpc_channel_stack_builder_get_target(builder)); if (default_authority != NULL) { grpc_arg arg; arg.type = GRPC_ARG_STRING; arg.key = GRPC_ARG_DEFAULT_AUTHORITY; arg.value.string = default_authority; grpc_channel_args *new_args = grpc_channel_args_copy_and_add(args, &arg, 1); grpc_channel_stack_builder_set_channel_arguments(exec_ctx, builder, new_args); gpr_free(default_authority); grpc_channel_args_destroy(exec_ctx, new_args); } return true; } void grpc_client_channel_init(void) { grpc_lb_policy_registry_init(); grpc_resolver_registry_init(); grpc_retry_throttle_map_init(); grpc_proxy_mapper_registry_init(); grpc_register_http_proxy_mapper(); grpc_subchannel_index_init(); grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MIN, set_default_host_if_unset, NULL); grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, append_filter, (void *)&grpc_client_channel_filter); grpc_http_connect_register_handshaker_factory(); } void grpc_client_channel_shutdown(void) { grpc_subchannel_index_shutdown(); grpc_channel_init_shutdown(); grpc_proxy_mapper_registry_shutdown(); grpc_retry_throttle_map_shutdown(); grpc_resolver_registry_shutdown(); grpc_lb_policy_registry_shutdown(); } grpc-1.3.2/src/core/ext/filters/client_channel/connector.c000066400000000000000000000045551310511640000235430ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/filters/client_channel/connector.h" grpc_connector* grpc_connector_ref(grpc_connector* connector) { connector->vtable->ref(connector); return connector; } void grpc_connector_unref(grpc_exec_ctx* exec_ctx, grpc_connector* connector) { connector->vtable->unref(exec_ctx, connector); } void grpc_connector_connect(grpc_exec_ctx* exec_ctx, grpc_connector* connector, const grpc_connect_in_args* in_args, grpc_connect_out_args* out_args, grpc_closure* notify) { connector->vtable->connect(exec_ctx, connector, in_args, out_args, notify); } void grpc_connector_shutdown(grpc_exec_ctx* exec_ctx, grpc_connector* connector, grpc_error* why) { connector->vtable->shutdown(exec_ctx, connector, why); } grpc-1.3.2/src/core/ext/filters/client_channel/connector.h000066400000000000000000000072371310511640000235500ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CONNECTOR_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CONNECTOR_H #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/transport/transport.h" typedef struct grpc_connector grpc_connector; typedef struct grpc_connector_vtable grpc_connector_vtable; struct grpc_connector { const grpc_connector_vtable *vtable; }; typedef struct { /** set of pollsets interested in this connection */ grpc_pollset_set *interested_parties; /** deadline for connection */ gpr_timespec deadline; /** channel arguments (to be passed to transport) */ const grpc_channel_args *channel_args; } grpc_connect_in_args; typedef struct { /** the connected transport */ grpc_transport *transport; /** channel arguments (to be passed to the filters) */ grpc_channel_args *channel_args; } grpc_connect_out_args; struct grpc_connector_vtable { void (*ref)(grpc_connector *connector); void (*unref)(grpc_exec_ctx *exec_ctx, grpc_connector *connector); /** Implementation of grpc_connector_shutdown */ void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_connector *connector, grpc_error *why); /** Implementation of grpc_connector_connect */ void (*connect)(grpc_exec_ctx *exec_ctx, grpc_connector *connector, const grpc_connect_in_args *in_args, grpc_connect_out_args *out_args, grpc_closure *notify); }; grpc_connector *grpc_connector_ref(grpc_connector *connector); void grpc_connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *connector); /** Connect using the connector: max one outstanding call at a time */ void grpc_connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *connector, const grpc_connect_in_args *in_args, grpc_connect_out_args *out_args, grpc_closure *notify); /** Cancel any pending connection */ void grpc_connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *connector, grpc_error *why); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CONNECTOR_H */ grpc-1.3.2/src/core/ext/filters/client_channel/http_connect_handshaker.c000066400000000000000000000400051310511640000264170ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/filters/client_channel/http_connect_handshaker.h" #include #include #include #include #include #include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/ext/filters/client_channel/uri_parser.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/handshaker_registry.h" #include "src/core/lib/http/format_request.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" typedef struct http_connect_handshaker { // Base class. Must be first. grpc_handshaker base; gpr_refcount refcount; gpr_mu mu; bool shutdown; // Endpoint and read buffer to destroy after a shutdown. grpc_endpoint* endpoint_to_destroy; grpc_slice_buffer* read_buffer_to_destroy; // State saved while performing the handshake. grpc_handshaker_args* args; grpc_closure* on_handshake_done; // Objects for processing the HTTP CONNECT request and response. grpc_slice_buffer write_buffer; grpc_closure request_done_closure; grpc_closure response_read_closure; grpc_http_parser http_parser; grpc_http_response http_response; } http_connect_handshaker; // Unref and clean up handshaker. static void http_connect_handshaker_unref(grpc_exec_ctx* exec_ctx, http_connect_handshaker* handshaker) { if (gpr_unref(&handshaker->refcount)) { gpr_mu_destroy(&handshaker->mu); if (handshaker->endpoint_to_destroy != NULL) { grpc_endpoint_destroy(exec_ctx, handshaker->endpoint_to_destroy); } if (handshaker->read_buffer_to_destroy != NULL) { grpc_slice_buffer_destroy_internal(exec_ctx, handshaker->read_buffer_to_destroy); gpr_free(handshaker->read_buffer_to_destroy); } grpc_slice_buffer_destroy_internal(exec_ctx, &handshaker->write_buffer); grpc_http_parser_destroy(&handshaker->http_parser); grpc_http_response_destroy(&handshaker->http_response); gpr_free(handshaker); } } // Set args fields to NULL, saving the endpoint and read buffer for // later destruction. static void cleanup_args_for_failure_locked( grpc_exec_ctx* exec_ctx, http_connect_handshaker* handshaker) { handshaker->endpoint_to_destroy = handshaker->args->endpoint; handshaker->args->endpoint = NULL; handshaker->read_buffer_to_destroy = handshaker->args->read_buffer; handshaker->args->read_buffer = NULL; grpc_channel_args_destroy(exec_ctx, handshaker->args->args); handshaker->args->args = NULL; } // If the handshake failed or we're shutting down, clean up and invoke the // callback with the error. static void handshake_failed_locked(grpc_exec_ctx* exec_ctx, http_connect_handshaker* handshaker, grpc_error* error) { if (error == GRPC_ERROR_NONE) { // If we were shut down after an endpoint operation succeeded but // before the endpoint callback was invoked, we need to generate our // own error. error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshaker shutdown"); } if (!handshaker->shutdown) { // TODO(ctiller): It is currently necessary to shutdown endpoints // before destroying them, even if we know that there are no // pending read/write callbacks. This should be fixed, at which // point this can be removed. grpc_endpoint_shutdown(exec_ctx, handshaker->args->endpoint, GRPC_ERROR_REF(error)); // Not shutting down, so the handshake failed. Clean up before // invoking the callback. cleanup_args_for_failure_locked(exec_ctx, handshaker); // Set shutdown to true so that subsequent calls to // http_connect_handshaker_shutdown() do nothing. handshaker->shutdown = true; } // Invoke callback. grpc_closure_sched(exec_ctx, handshaker->on_handshake_done, error); } // Callback invoked when finished writing HTTP CONNECT request. static void on_write_done(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { http_connect_handshaker* handshaker = arg; gpr_mu_lock(&handshaker->mu); if (error != GRPC_ERROR_NONE || handshaker->shutdown) { // If the write failed or we're shutting down, clean up and invoke the // callback with the error. handshake_failed_locked(exec_ctx, handshaker, GRPC_ERROR_REF(error)); gpr_mu_unlock(&handshaker->mu); http_connect_handshaker_unref(exec_ctx, handshaker); } else { // Otherwise, read the response. // The read callback inherits our ref to the handshaker. grpc_endpoint_read(exec_ctx, handshaker->args->endpoint, handshaker->args->read_buffer, &handshaker->response_read_closure); gpr_mu_unlock(&handshaker->mu); } } // Callback invoked for reading HTTP CONNECT response. static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { http_connect_handshaker* handshaker = arg; gpr_mu_lock(&handshaker->mu); if (error != GRPC_ERROR_NONE || handshaker->shutdown) { // If the read failed or we're shutting down, clean up and invoke the // callback with the error. handshake_failed_locked(exec_ctx, handshaker, GRPC_ERROR_REF(error)); goto done; } // Add buffer to parser. for (size_t i = 0; i < handshaker->args->read_buffer->count; ++i) { if (GRPC_SLICE_LENGTH(handshaker->args->read_buffer->slices[i]) > 0) { size_t body_start_offset = 0; error = grpc_http_parser_parse(&handshaker->http_parser, handshaker->args->read_buffer->slices[i], &body_start_offset); if (error != GRPC_ERROR_NONE) { handshake_failed_locked(exec_ctx, handshaker, error); goto done; } if (handshaker->http_parser.state == GRPC_HTTP_BODY) { // Remove the data we've already read from the read buffer, // leaving only the leftover bytes (if any). grpc_slice_buffer tmp_buffer; grpc_slice_buffer_init(&tmp_buffer); if (body_start_offset < GRPC_SLICE_LENGTH(handshaker->args->read_buffer->slices[i])) { grpc_slice_buffer_add( &tmp_buffer, grpc_slice_split_tail(&handshaker->args->read_buffer->slices[i], body_start_offset)); } grpc_slice_buffer_addn(&tmp_buffer, &handshaker->args->read_buffer->slices[i + 1], handshaker->args->read_buffer->count - i - 1); grpc_slice_buffer_swap(handshaker->args->read_buffer, &tmp_buffer); grpc_slice_buffer_destroy_internal(exec_ctx, &tmp_buffer); break; } } } // If we're not done reading the response, read more data. // TODO(roth): In practice, I suspect that the response to a CONNECT // request will never include a body, in which case this check is // sufficient. However, the language of RFC-2817 doesn't explicitly // forbid the response from including a body. If there is a body, // it's possible that we might have parsed part but not all of the // body, in which case this check will cause us to fail to parse the // remainder of the body. If that ever becomes an issue, we may // need to fix the HTTP parser to understand when the body is // complete (e.g., handling chunked transfer encoding or looking // at the Content-Length: header). if (handshaker->http_parser.state != GRPC_HTTP_BODY) { grpc_slice_buffer_reset_and_unref_internal(exec_ctx, handshaker->args->read_buffer); grpc_endpoint_read(exec_ctx, handshaker->args->endpoint, handshaker->args->read_buffer, &handshaker->response_read_closure); gpr_mu_unlock(&handshaker->mu); return; } // Make sure we got a 2xx response. if (handshaker->http_response.status < 200 || handshaker->http_response.status >= 300) { char* msg; gpr_asprintf(&msg, "HTTP proxy returned response code %d", handshaker->http_response.status); error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); handshake_failed_locked(exec_ctx, handshaker, error); goto done; } // Success. Invoke handshake-done callback. grpc_closure_sched(exec_ctx, handshaker->on_handshake_done, error); done: // Set shutdown to true so that subsequent calls to // http_connect_handshaker_shutdown() do nothing. handshaker->shutdown = true; gpr_mu_unlock(&handshaker->mu); http_connect_handshaker_unref(exec_ctx, handshaker); } // // Public handshaker methods // static void http_connect_handshaker_destroy(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker_in) { http_connect_handshaker* handshaker = (http_connect_handshaker*)handshaker_in; http_connect_handshaker_unref(exec_ctx, handshaker); } static void http_connect_handshaker_shutdown(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker_in, grpc_error* why) { http_connect_handshaker* handshaker = (http_connect_handshaker*)handshaker_in; gpr_mu_lock(&handshaker->mu); if (!handshaker->shutdown) { handshaker->shutdown = true; grpc_endpoint_shutdown(exec_ctx, handshaker->args->endpoint, GRPC_ERROR_REF(why)); cleanup_args_for_failure_locked(exec_ctx, handshaker); } gpr_mu_unlock(&handshaker->mu); GRPC_ERROR_UNREF(why); } static void http_connect_handshaker_do_handshake( grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker_in, grpc_tcp_server_acceptor* acceptor, grpc_closure* on_handshake_done, grpc_handshaker_args* args) { http_connect_handshaker* handshaker = (http_connect_handshaker*)handshaker_in; // Check for HTTP CONNECT channel arg. // If not found, invoke on_handshake_done without doing anything. const grpc_arg* arg = grpc_channel_args_find(args->args, GRPC_ARG_HTTP_CONNECT_SERVER); if (arg == NULL) { // Set shutdown to true so that subsequent calls to // http_connect_handshaker_shutdown() do nothing. gpr_mu_lock(&handshaker->mu); handshaker->shutdown = true; gpr_mu_unlock(&handshaker->mu); grpc_closure_sched(exec_ctx, on_handshake_done, GRPC_ERROR_NONE); return; } GPR_ASSERT(arg->type == GRPC_ARG_STRING); char* server_name = arg->value.string; // Get headers from channel args. arg = grpc_channel_args_find(args->args, GRPC_ARG_HTTP_CONNECT_HEADERS); grpc_http_header* headers = NULL; size_t num_headers = 0; char** header_strings = NULL; size_t num_header_strings = 0; if (arg != NULL) { GPR_ASSERT(arg->type == GRPC_ARG_STRING); gpr_string_split(arg->value.string, "\n", &header_strings, &num_header_strings); headers = gpr_malloc(sizeof(grpc_http_header) * num_header_strings); for (size_t i = 0; i < num_header_strings; ++i) { char* sep = strchr(header_strings[i], ':'); if (sep == NULL) { gpr_log(GPR_ERROR, "skipping unparseable HTTP CONNECT header: %s", header_strings[i]); continue; } *sep = '\0'; headers[num_headers].key = header_strings[i]; headers[num_headers].value = sep + 1; ++num_headers; } } // Save state in the handshaker object. gpr_mu_lock(&handshaker->mu); handshaker->args = args; handshaker->on_handshake_done = on_handshake_done; // Log connection via proxy. char* proxy_name = grpc_endpoint_get_peer(args->endpoint); gpr_log(GPR_INFO, "Connecting to server %s via HTTP proxy %s", server_name, proxy_name); gpr_free(proxy_name); // Construct HTTP CONNECT request. grpc_httpcli_request request; memset(&request, 0, sizeof(request)); request.host = server_name; request.http.method = "CONNECT"; request.http.path = server_name; request.http.hdrs = headers; request.http.hdr_count = num_headers; request.handshaker = &grpc_httpcli_plaintext; grpc_slice request_slice = grpc_httpcli_format_connect_request(&request); grpc_slice_buffer_add(&handshaker->write_buffer, request_slice); // Clean up. gpr_free(headers); for (size_t i = 0; i < num_header_strings; ++i) { gpr_free(header_strings[i]); } gpr_free(header_strings); // Take a new ref to be held by the write callback. gpr_ref(&handshaker->refcount); grpc_endpoint_write(exec_ctx, args->endpoint, &handshaker->write_buffer, &handshaker->request_done_closure); gpr_mu_unlock(&handshaker->mu); } static const grpc_handshaker_vtable http_connect_handshaker_vtable = { http_connect_handshaker_destroy, http_connect_handshaker_shutdown, http_connect_handshaker_do_handshake}; static grpc_handshaker* grpc_http_connect_handshaker_create() { http_connect_handshaker* handshaker = gpr_malloc(sizeof(*handshaker)); memset(handshaker, 0, sizeof(*handshaker)); grpc_handshaker_init(&http_connect_handshaker_vtable, &handshaker->base); gpr_mu_init(&handshaker->mu); gpr_ref_init(&handshaker->refcount, 1); grpc_slice_buffer_init(&handshaker->write_buffer); grpc_closure_init(&handshaker->request_done_closure, on_write_done, handshaker, grpc_schedule_on_exec_ctx); grpc_closure_init(&handshaker->response_read_closure, on_read_done, handshaker, grpc_schedule_on_exec_ctx); grpc_http_parser_init(&handshaker->http_parser, GRPC_HTTP_RESPONSE, &handshaker->http_response); return &handshaker->base; } // // handshaker factory // static void handshaker_factory_add_handshakers( grpc_exec_ctx* exec_ctx, grpc_handshaker_factory* factory, const grpc_channel_args* args, grpc_handshake_manager* handshake_mgr) { grpc_handshake_manager_add(handshake_mgr, grpc_http_connect_handshaker_create()); } static void handshaker_factory_destroy(grpc_exec_ctx* exec_ctx, grpc_handshaker_factory* factory) {} static const grpc_handshaker_factory_vtable handshaker_factory_vtable = { handshaker_factory_add_handshakers, handshaker_factory_destroy}; static grpc_handshaker_factory handshaker_factory = { &handshaker_factory_vtable}; void grpc_http_connect_register_handshaker_factory() { grpc_handshaker_factory_register(true /* at_start */, HANDSHAKER_CLIENT, &handshaker_factory); } grpc-1.3.2/src/core/ext/filters/client_channel/http_connect_handshaker.h000066400000000000000000000043711310511640000264320ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_HTTP_CONNECT_HANDSHAKER_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_HTTP_CONNECT_HANDSHAKER_H /// Channel arg indicating the server in HTTP CONNECT request (string). /// The presence of this arg triggers the use of HTTP CONNECT. #define GRPC_ARG_HTTP_CONNECT_SERVER "grpc.http_connect_server" /// Channel arg indicating HTTP CONNECT headers (string). /// Multiple headers are separated by newlines. Key/value pairs are /// seperated by colons. #define GRPC_ARG_HTTP_CONNECT_HEADERS "grpc.http_connect_headers" /// Registers handshaker factory. void grpc_http_connect_register_handshaker_factory(); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_HTTP_CONNECT_HANDSHAKER_H */ grpc-1.3.2/src/core/ext/filters/client_channel/http_proxy.c000066400000000000000000000115461310511640000237670ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/filters/client_channel/http_proxy.h" #include #include #include #include #include #include "src/core/ext/filters/client_channel/http_connect_handshaker.h" #include "src/core/ext/filters/client_channel/proxy_mapper_registry.h" #include "src/core/ext/filters/client_channel/uri_parser.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/support/env.h" static char* grpc_get_http_proxy_server(grpc_exec_ctx* exec_ctx) { char* uri_str = gpr_getenv("http_proxy"); if (uri_str == NULL) return NULL; grpc_uri* uri = grpc_uri_parse(exec_ctx, uri_str, false /* suppress_errors */); char* proxy_name = NULL; if (uri == NULL || uri->authority == NULL) { gpr_log(GPR_ERROR, "cannot parse value of 'http_proxy' env var"); goto done; } if (strcmp(uri->scheme, "http") != 0) { gpr_log(GPR_ERROR, "'%s' scheme not supported in proxy URI", uri->scheme); goto done; } if (strchr(uri->authority, '@') != NULL) { gpr_log(GPR_ERROR, "userinfo not supported in proxy URI"); goto done; } proxy_name = gpr_strdup(uri->authority); done: gpr_free(uri_str); grpc_uri_destroy(uri); return proxy_name; } static bool proxy_mapper_map_name(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper, const char* server_uri, const grpc_channel_args* args, char** name_to_resolve, grpc_channel_args** new_args) { *name_to_resolve = grpc_get_http_proxy_server(exec_ctx); if (*name_to_resolve == NULL) return false; grpc_uri* uri = grpc_uri_parse(exec_ctx, server_uri, false /* suppress_errors */); if (uri == NULL || uri->path[0] == '\0') { gpr_log(GPR_ERROR, "'http_proxy' environment variable set, but cannot " "parse server URI '%s' -- not using proxy", server_uri); if (uri != NULL) grpc_uri_destroy(uri); return false; } if (strcmp(uri->scheme, "unix") == 0) { gpr_log(GPR_INFO, "not using proxy for Unix domain socket '%s'", server_uri); grpc_uri_destroy(uri); return false; } grpc_arg new_arg; new_arg.key = GRPC_ARG_HTTP_CONNECT_SERVER; new_arg.type = GRPC_ARG_STRING; new_arg.value.string = uri->path[0] == '/' ? uri->path + 1 : uri->path; *new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1); grpc_uri_destroy(uri); return true; } static bool proxy_mapper_map_address(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper, const grpc_resolved_address* address, const grpc_channel_args* args, grpc_resolved_address** new_address, grpc_channel_args** new_args) { return false; } static void proxy_mapper_destroy(grpc_proxy_mapper* mapper) {} static const grpc_proxy_mapper_vtable proxy_mapper_vtable = { proxy_mapper_map_name, proxy_mapper_map_address, proxy_mapper_destroy}; static grpc_proxy_mapper proxy_mapper = {&proxy_mapper_vtable}; void grpc_register_http_proxy_mapper() { grpc_proxy_mapper_register(true /* at_start */, &proxy_mapper); } grpc-1.3.2/src/core/ext/filters/client_channel/http_proxy.h000066400000000000000000000033771310511640000237770ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_HTTP_PROXY_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_HTTP_PROXY_H void grpc_register_http_proxy_mapper(); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_HTTP_PROXY_H */ grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy.c000066400000000000000000000160361310511640000235220ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/filters/client_channel/lb_policy.h" #include "src/core/lib/iomgr/combiner.h" #define WEAK_REF_BITS 16 void grpc_lb_policy_init(grpc_lb_policy *policy, const grpc_lb_policy_vtable *vtable, grpc_combiner *combiner) { policy->vtable = vtable; gpr_atm_no_barrier_store(&policy->ref_pair, 1 << WEAK_REF_BITS); policy->interested_parties = grpc_pollset_set_create(); policy->combiner = GRPC_COMBINER_REF(combiner, "lb_policy"); } #ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG #define REF_FUNC_EXTRA_ARGS , const char *file, int line, const char *reason #define REF_MUTATE_EXTRA_ARGS REF_FUNC_EXTRA_ARGS, const char *purpose #define REF_FUNC_PASS_ARGS(new_reason) , file, line, new_reason #define REF_MUTATE_PASS_ARGS(purpose) , file, line, reason, purpose #else #define REF_FUNC_EXTRA_ARGS #define REF_MUTATE_EXTRA_ARGS #define REF_FUNC_PASS_ARGS(new_reason) #define REF_MUTATE_PASS_ARGS(x) #endif static gpr_atm ref_mutate(grpc_lb_policy *c, gpr_atm delta, int barrier REF_MUTATE_EXTRA_ARGS) { gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&c->ref_pair, delta) : gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta); #ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "LB_POLICY: 0x%" PRIxPTR " %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR " [%s]", (intptr_t)c, purpose, old_val, old_val + delta, reason); #endif return old_val; } void grpc_lb_policy_ref(grpc_lb_policy *policy REF_FUNC_EXTRA_ARGS) { ref_mutate(policy, 1 << WEAK_REF_BITS, 0 REF_MUTATE_PASS_ARGS("STRONG_REF")); } static void shutdown_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_lb_policy *policy = arg; policy->vtable->shutdown_locked(exec_ctx, policy); GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, policy, "strong-unref"); } void grpc_lb_policy_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy REF_FUNC_EXTRA_ARGS) { gpr_atm old_val = ref_mutate(policy, (gpr_atm)1 - (gpr_atm)(1 << WEAK_REF_BITS), 1 REF_MUTATE_PASS_ARGS("STRONG_UNREF")); gpr_atm mask = ~(gpr_atm)((1 << WEAK_REF_BITS) - 1); gpr_atm check = 1 << WEAK_REF_BITS; if ((old_val & mask) == check) { grpc_closure_sched( exec_ctx, grpc_closure_create(shutdown_locked, policy, grpc_combiner_scheduler(policy->combiner, false)), GRPC_ERROR_NONE); } else { grpc_lb_policy_weak_unref(exec_ctx, policy REF_FUNC_PASS_ARGS("strong-unref")); } } void grpc_lb_policy_weak_ref(grpc_lb_policy *policy REF_FUNC_EXTRA_ARGS) { ref_mutate(policy, 1, 0 REF_MUTATE_PASS_ARGS("WEAK_REF")); } void grpc_lb_policy_weak_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy REF_FUNC_EXTRA_ARGS) { gpr_atm old_val = ref_mutate(policy, -(gpr_atm)1, 1 REF_MUTATE_PASS_ARGS("WEAK_UNREF")); if (old_val == 1) { grpc_pollset_set_destroy(exec_ctx, policy->interested_parties); grpc_combiner *combiner = policy->combiner; policy->vtable->destroy(exec_ctx, policy); GRPC_COMBINER_UNREF(exec_ctx, combiner, "lb_policy"); } } int grpc_lb_policy_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, const grpc_lb_policy_pick_args *pick_args, grpc_connected_subchannel **target, void **user_data, grpc_closure *on_complete) { return policy->vtable->pick_locked(exec_ctx, policy, pick_args, target, user_data, on_complete); } void grpc_lb_policy_cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_connected_subchannel **target, grpc_error *error) { policy->vtable->cancel_pick_locked(exec_ctx, policy, target, error); } void grpc_lb_policy_cancel_picks_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, uint32_t initial_metadata_flags_mask, uint32_t initial_metadata_flags_eq, grpc_error *error) { policy->vtable->cancel_picks_locked(exec_ctx, policy, initial_metadata_flags_mask, initial_metadata_flags_eq, error); } void grpc_lb_policy_exit_idle_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy) { policy->vtable->exit_idle_locked(exec_ctx, policy); } void grpc_lb_policy_ping_one_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_closure *closure) { policy->vtable->ping_one_locked(exec_ctx, policy, closure); } void grpc_lb_policy_notify_on_state_change_locked( grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_connectivity_state *state, grpc_closure *closure) { policy->vtable->notify_on_state_change_locked(exec_ctx, policy, state, closure); } grpc_connectivity_state grpc_lb_policy_check_connectivity_locked( grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_error **connectivity_error) { return policy->vtable->check_connectivity_locked(exec_ctx, policy, connectivity_error); } grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy.h000066400000000000000000000236761310511640000235370ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_H #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/transport/connectivity_state.h" /** A load balancing policy: specified by a vtable and a struct (which is expected to be extended to contain some parameters) */ typedef struct grpc_lb_policy grpc_lb_policy; typedef struct grpc_lb_policy_vtable grpc_lb_policy_vtable; typedef void (*grpc_lb_completion)(void *cb_arg, grpc_subchannel *subchannel, grpc_status_code status, const char *errmsg); struct grpc_lb_policy { const grpc_lb_policy_vtable *vtable; gpr_atm ref_pair; /* owned pointer to interested parties in load balancing decisions */ grpc_pollset_set *interested_parties; /* combiner under which lb_policy actions take place */ grpc_combiner *combiner; }; /** Extra arguments for an LB pick */ typedef struct grpc_lb_policy_pick_args { /** Initial metadata associated with the picking call. */ grpc_metadata_batch *initial_metadata; /** Bitmask used for selective cancelling. See \a * grpc_lb_policy_cancel_picks() and \a GRPC_INITIAL_METADATA_* in * grpc_types.h */ uint32_t initial_metadata_flags; /** Storage for LB token in \a initial_metadata, or NULL if not used */ grpc_linked_mdelem *lb_token_mdelem_storage; /** Deadline for the call to the LB server */ gpr_timespec deadline; } grpc_lb_policy_pick_args; struct grpc_lb_policy_vtable { void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy); void (*shutdown_locked)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy); /** \see grpc_lb_policy_pick */ int (*pick_locked)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, const grpc_lb_policy_pick_args *pick_args, grpc_connected_subchannel **target, void **user_data, grpc_closure *on_complete); /** \see grpc_lb_policy_cancel_pick */ void (*cancel_pick_locked)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_connected_subchannel **target, grpc_error *error); /** \see grpc_lb_policy_cancel_picks */ void (*cancel_picks_locked)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, uint32_t initial_metadata_flags_mask, uint32_t initial_metadata_flags_eq, grpc_error *error); /** \see grpc_lb_policy_ping_one */ void (*ping_one_locked)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_closure *closure); /** Try to enter a READY connectivity state */ void (*exit_idle_locked)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy); /** check the current connectivity of the lb_policy */ grpc_connectivity_state (*check_connectivity_locked)( grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_error **connectivity_error); /** call notify when the connectivity state of a channel changes from *state. Updates *state with the new state of the policy. Calling with a NULL \a state cancels the subscription. */ void (*notify_on_state_change_locked)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_connectivity_state *state, grpc_closure *closure); }; /*#define GRPC_LB_POLICY_REFCOUNT_DEBUG*/ #ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG /* Strong references: the policy will shutdown when they reach zero */ #define GRPC_LB_POLICY_REF(p, r) \ grpc_lb_policy_ref((p), __FILE__, __LINE__, (r)) #define GRPC_LB_POLICY_UNREF(exec_ctx, p, r) \ grpc_lb_policy_unref((exec_ctx), (p), __FILE__, __LINE__, (r)) /* Weak references: they don't prevent the shutdown of the LB policy. When no * strong references are left but there are still weak ones, shutdown is called. * Once the weak reference also reaches zero, the LB policy is destroyed. */ #define GRPC_LB_POLICY_WEAK_REF(p, r) \ grpc_lb_policy_weak_ref((p), __FILE__, __LINE__, (r)) #define GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, p, r) \ grpc_lb_policy_weak_unref((exec_ctx), (p), __FILE__, __LINE__, (r)) void grpc_lb_policy_ref(grpc_lb_policy *policy, const char *file, int line, const char *reason); void grpc_lb_policy_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, const char *file, int line, const char *reason); void grpc_lb_policy_weak_ref(grpc_lb_policy *policy, const char *file, int line, const char *reason); void grpc_lb_policy_weak_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, const char *file, int line, const char *reason); #else #define GRPC_LB_POLICY_REF(p, r) grpc_lb_policy_ref((p)) #define GRPC_LB_POLICY_UNREF(cl, p, r) grpc_lb_policy_unref((cl), (p)) #define GRPC_LB_POLICY_WEAK_REF(p, r) grpc_lb_policy_weak_ref((p)) #define GRPC_LB_POLICY_WEAK_UNREF(cl, p, r) grpc_lb_policy_weak_unref((cl), (p)) void grpc_lb_policy_ref(grpc_lb_policy *policy); void grpc_lb_policy_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy); void grpc_lb_policy_weak_ref(grpc_lb_policy *policy); void grpc_lb_policy_weak_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy); #endif /** called by concrete implementations to initialize the base struct */ void grpc_lb_policy_init(grpc_lb_policy *policy, const grpc_lb_policy_vtable *vtable, grpc_combiner *combiner); /** Finds an appropriate subchannel for a call, based on \a pick_args. \a target will be set to the selected subchannel, or NULL on failure. Upon success, \a user_data will be set to whatever opaque information may need to be propagated from the LB policy, or NULL if not needed. If the pick succeeds and a result is known immediately, a non-zero value will be returned. Otherwise, \a on_complete will be invoked once the pick is complete with its error argument set to indicate success or failure. Any IO should be done under the \a interested_parties \a grpc_pollset_set in the \a grpc_lb_policy struct. */ int grpc_lb_policy_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, const grpc_lb_policy_pick_args *pick_args, grpc_connected_subchannel **target, void **user_data, grpc_closure *on_complete); /** Perform a connected subchannel ping (see \a grpc_connected_subchannel_ping) against one of the connected subchannels managed by \a policy. */ void grpc_lb_policy_ping_one_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_closure *closure); /** Cancel picks for \a target. The \a on_complete callback of the pending picks will be invoked with \a *target set to NULL. */ void grpc_lb_policy_cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_connected_subchannel **target, grpc_error *error); /** Cancel all pending picks for which their \a initial_metadata_flags (as given in the call to \a grpc_lb_policy_pick) matches \a initial_metadata_flags_eq when AND'd with \a initial_metadata_flags_mask */ void grpc_lb_policy_cancel_picks_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, uint32_t initial_metadata_flags_mask, uint32_t initial_metadata_flags_eq, grpc_error *error); /** Try to enter a READY connectivity state */ void grpc_lb_policy_exit_idle_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy); /* Call notify when the connectivity state of a channel changes from \a *state. * Updates \a *state with the new state of the policy */ void grpc_lb_policy_notify_on_state_change_locked( grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_connectivity_state *state, grpc_closure *closure); grpc_connectivity_state grpc_lb_policy_check_connectivity_locked( grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_error **connectivity_error); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_H */ grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy/000077500000000000000000000000001310511640000233505ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy/grpclb/000077500000000000000000000000001310511640000246215ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c000066400000000000000000001623671310511640000262550ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** Implementation of the gRPC LB policy. * * This policy takes as input a set of resolved addresses {a1..an} for which the * LB set was set (it's the resolver's responsibility to ensure this). That is * to say, {a1..an} represent a collection of LB servers. * * An internal channel (\a glb_lb_policy.lb_channel) is created over {a1..an}. * This channel behaves just like a regular channel. In particular, the * constructed URI over the addresses a1..an will use the default pick first * policy to select from this list of LB server backends. * * The first time the policy gets a request for a pick, a ping, or to exit the * idle state, \a query_for_backends_locked() is called. This function sets up * and initiates the internal communication with the LB server. In particular, * it's responsible for instantiating the internal *streaming* call to the LB * server (whichever address from {a1..an} pick-first chose). This call is * serviced by two callbacks, \a lb_on_server_status_received and \a * lb_on_response_received. The former will be called when the call to the LB * server completes. This can happen if the LB server closes the connection or * if this policy itself cancels the call (for example because it's shutting * down). If the internal call times out, the usual behavior of pick-first * applies, continuing to pick from the list {a1..an}. * * Upon sucesss, the incoming \a LoadBalancingResponse is processed by \a * res_recv. An invalid one results in the termination of the streaming call. A * new streaming call should be created if possible, failing the original call * otherwise. For a valid \a LoadBalancingResponse, the server list of actual * backends is extracted. A Round Robin policy will be created from this list. * There are two possible scenarios: * * 1. This is the first server list received. There was no previous instance of * the Round Robin policy. \a rr_handover_locked() will instantiate the RR * policy and perform all the pending operations over it. * 2. There's already a RR policy instance active. We need to introduce the new * one build from the new serverlist, but taking care not to disrupt the * operations in progress over the old RR instance. This is done by * decreasing the reference count on the old policy. The moment no more * references are held on the old RR policy, it'll be destroyed and \a * glb_rr_connectivity_changed notified with a \a GRPC_CHANNEL_SHUTDOWN * state. At this point we can transition to a new RR instance safely, which * is done once again via \a rr_handover_locked(). * * * Once a RR policy instance is in place (and getting updated as described), * calls to for a pick, a ping or a cancellation will be serviced right away by * forwarding them to the RR instance. Any time there's no RR policy available * (ie, right after the creation of the gRPCLB policy, if an empty serverlist is * received, etc), pick/ping requests are added to a list of pending picks/pings * to be flushed and serviced as part of \a rr_handover_locked() the moment the * RR policy instance becomes available. * * \see https://github.com/grpc/grpc/blob/master/doc/load-balancing.md for the * high level design and details. */ /* TODO(dgq): * - Implement LB service forwarding (point 2c. in the doc's diagram). */ /* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when using that endpoint. Because of various transitive includes in uv.h, including windows.h on Windows, uv.h must be included before other system headers. Therefore, sockaddr.h must always be included first */ #include "src/core/lib/iomgr/sockaddr.h" #include #include #include #include #include #include #include #include #include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/filters/client_channel/client_channel_factory.h" #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h" #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h" #include "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h" #include "src/core/ext/filters/client_channel/lb_policy_factory.h" #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/parse_address.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/slice/slice_hash_table.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/backoff.h" #include "src/core/lib/support/string.h" #include "src/core/lib/surface/call.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/transport/static_metadata.h" #define GRPC_GRPCLB_MIN_CONNECT_TIMEOUT_SECONDS 20 #define GRPC_GRPCLB_INITIAL_CONNECT_BACKOFF_SECONDS 1 #define GRPC_GRPCLB_RECONNECT_BACKOFF_MULTIPLIER 1.6 #define GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS 120 #define GRPC_GRPCLB_RECONNECT_JITTER 0.2 int grpc_lb_glb_trace = 0; /* add lb_token of selected subchannel (address) to the call's initial * metadata */ static grpc_error *initial_metadata_add_lb_token( grpc_exec_ctx *exec_ctx, grpc_metadata_batch *initial_metadata, grpc_linked_mdelem *lb_token_mdelem_storage, grpc_mdelem lb_token) { GPR_ASSERT(lb_token_mdelem_storage != NULL); GPR_ASSERT(!GRPC_MDISNULL(lb_token)); return grpc_metadata_batch_add_tail(exec_ctx, initial_metadata, lb_token_mdelem_storage, lb_token); } typedef struct wrapped_rr_closure_arg { /* the closure instance using this struct as argument */ grpc_closure wrapper_closure; /* the original closure. Usually a on_complete/notify cb for pick() and ping() * calls against the internal RR instance, respectively. */ grpc_closure *wrapped_closure; /* the pick's initial metadata, kept in order to append the LB token for the * pick */ grpc_metadata_batch *initial_metadata; /* the picked target, used to determine which LB token to add to the pick's * initial metadata */ grpc_connected_subchannel **target; /* the LB token associated with the pick */ grpc_mdelem lb_token; /* storage for the lb token initial metadata mdelem */ grpc_linked_mdelem *lb_token_mdelem_storage; /* The RR instance related to the closure */ grpc_lb_policy *rr_policy; /* heap memory to be freed upon closure execution. */ void *free_when_done; } wrapped_rr_closure_arg; /* The \a on_complete closure passed as part of the pick requires keeping a * reference to its associated round robin instance. We wrap this closure in * order to unref the round robin instance upon its invocation */ static void wrapped_rr_closure(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { wrapped_rr_closure_arg *wc_arg = arg; GPR_ASSERT(wc_arg->wrapped_closure != NULL); grpc_closure_sched(exec_ctx, wc_arg->wrapped_closure, GRPC_ERROR_REF(error)); if (wc_arg->rr_policy != NULL) { /* if *target is NULL, no pick has been made by the RR policy (eg, all * addresses failed to connect). There won't be any user_data/token * available */ if (*wc_arg->target != NULL) { if (!GRPC_MDISNULL(wc_arg->lb_token)) { initial_metadata_add_lb_token(exec_ctx, wc_arg->initial_metadata, wc_arg->lb_token_mdelem_storage, GRPC_MDELEM_REF(wc_arg->lb_token)); } else { gpr_log(GPR_ERROR, "No LB token for connected subchannel pick %p (from RR " "instance %p).", (void *)*wc_arg->target, (void *)wc_arg->rr_policy); abort(); } } if (grpc_lb_glb_trace) { gpr_log(GPR_INFO, "Unreffing RR %p", (void *)wc_arg->rr_policy); } GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "wrapped_rr_closure"); } GPR_ASSERT(wc_arg->free_when_done != NULL); gpr_free(wc_arg->free_when_done); } /* Linked list of pending pick requests. It stores all information needed to * eventually call (Round Robin's) pick() on them. They mainly stay pending * waiting for the RR policy to be created/updated. * * One particularity is the wrapping of the user-provided \a on_complete closure * (in \a wrapped_on_complete and \a wrapped_on_complete_arg). This is needed in * order to correctly unref the RR policy instance upon completion of the pick. * See \a wrapped_rr_closure for details. */ typedef struct pending_pick { struct pending_pick *next; /* original pick()'s arguments */ grpc_lb_policy_pick_args pick_args; /* output argument where to store the pick()ed connected subchannel, or NULL * upon error. */ grpc_connected_subchannel **target; /* args for wrapped_on_complete */ wrapped_rr_closure_arg wrapped_on_complete_arg; } pending_pick; static void add_pending_pick(pending_pick **root, const grpc_lb_policy_pick_args *pick_args, grpc_connected_subchannel **target, grpc_closure *on_complete) { pending_pick *pp = gpr_zalloc(sizeof(*pp)); pp->next = *root; pp->pick_args = *pick_args; pp->target = target; pp->wrapped_on_complete_arg.wrapped_closure = on_complete; pp->wrapped_on_complete_arg.target = target; pp->wrapped_on_complete_arg.initial_metadata = pick_args->initial_metadata; pp->wrapped_on_complete_arg.lb_token_mdelem_storage = pick_args->lb_token_mdelem_storage; pp->wrapped_on_complete_arg.free_when_done = pp; grpc_closure_init(&pp->wrapped_on_complete_arg.wrapper_closure, wrapped_rr_closure, &pp->wrapped_on_complete_arg, grpc_schedule_on_exec_ctx); *root = pp; } /* Same as the \a pending_pick struct but for ping operations */ typedef struct pending_ping { struct pending_ping *next; /* args for wrapped_notify */ wrapped_rr_closure_arg wrapped_notify_arg; } pending_ping; static void add_pending_ping(pending_ping **root, grpc_closure *notify) { pending_ping *pping = gpr_zalloc(sizeof(*pping)); pping->wrapped_notify_arg.wrapped_closure = notify; pping->wrapped_notify_arg.free_when_done = pping; pping->next = *root; grpc_closure_init(&pping->wrapped_notify_arg.wrapper_closure, wrapped_rr_closure, &pping->wrapped_notify_arg, grpc_schedule_on_exec_ctx); *root = pping; } /* * glb_lb_policy */ typedef struct rr_connectivity_data rr_connectivity_data; static const grpc_lb_policy_vtable glb_lb_policy_vtable; typedef struct glb_lb_policy { /** base policy: must be first */ grpc_lb_policy base; /** who the client is trying to communicate with */ const char *server_name; grpc_client_channel_factory *cc_factory; grpc_channel_args *args; /** deadline for the LB's call */ gpr_timespec deadline; /** for communicating with the LB server */ grpc_channel *lb_channel; /** the RR policy to use of the backend servers returned by the LB server */ grpc_lb_policy *rr_policy; bool started_picking; /** our connectivity state tracker */ grpc_connectivity_state_tracker state_tracker; /** stores the deserialized response from the LB. May be NULL until one such * response has arrived. */ grpc_grpclb_serverlist *serverlist; /** list of picks that are waiting on RR's policy connectivity */ pending_pick *pending_picks; /** list of pings that are waiting on RR's policy connectivity */ pending_ping *pending_pings; bool shutting_down; /************************************************************/ /* client data associated with the LB server communication */ /************************************************************/ /* Status from the LB server has been received. This signals the end of the LB * call. */ grpc_closure lb_on_server_status_received; /* A response from the LB server has been received. Process it */ grpc_closure lb_on_response_received; /* LB call retry timer callback. */ grpc_closure lb_on_call_retry; grpc_call *lb_call; /* streaming call to the LB server, */ grpc_metadata_array lb_initial_metadata_recv; /* initial MD from LB server */ grpc_metadata_array lb_trailing_metadata_recv; /* trailing MD from LB server */ /* what's being sent to the LB server. Note that its value may vary if the LB * server indicates a redirect. */ grpc_byte_buffer *lb_request_payload; /* response the LB server, if any. Processed in lb_on_response_received() */ grpc_byte_buffer *lb_response_payload; /* call status code and details, set in lb_on_server_status_received() */ grpc_status_code lb_call_status; grpc_slice lb_call_status_details; /** LB call retry backoff state */ gpr_backoff lb_call_backoff_state; /** LB call retry timer */ grpc_timer lb_call_retry_timer; } glb_lb_policy; /* Keeps track and reacts to changes in connectivity of the RR instance */ struct rr_connectivity_data { grpc_closure on_change; grpc_connectivity_state state; glb_lb_policy *glb_policy; }; static bool is_server_valid(const grpc_grpclb_server *server, size_t idx, bool log) { const grpc_grpclb_ip_address *ip = &server->ip_address; if (server->port >> 16 != 0) { if (log) { gpr_log(GPR_ERROR, "Invalid port '%d' at index %lu of serverlist. Ignoring.", server->port, (unsigned long)idx); } return false; } if (ip->size != 4 && ip->size != 16) { if (log) { gpr_log(GPR_ERROR, "Expected IP to be 4 or 16 bytes, got %d at index %lu of " "serverlist. Ignoring", ip->size, (unsigned long)idx); } return false; } return true; } /* vtable for LB tokens in grpc_lb_addresses. */ static void *lb_token_copy(void *token) { return token == NULL ? NULL : (void *)GRPC_MDELEM_REF((grpc_mdelem){(uintptr_t)token}).payload; } static void lb_token_destroy(grpc_exec_ctx *exec_ctx, void *token) { if (token != NULL) { GRPC_MDELEM_UNREF(exec_ctx, (grpc_mdelem){(uintptr_t)token}); } } static int lb_token_cmp(void *token1, void *token2) { if (token1 > token2) return 1; if (token1 < token2) return -1; return 0; } static const grpc_lb_user_data_vtable lb_token_vtable = { lb_token_copy, lb_token_destroy, lb_token_cmp}; static void parse_server(const grpc_grpclb_server *server, grpc_resolved_address *addr) { const uint16_t netorder_port = htons((uint16_t)server->port); /* the addresses are given in binary format (a in(6)_addr struct) in * server->ip_address.bytes. */ const grpc_grpclb_ip_address *ip = &server->ip_address; memset(addr, 0, sizeof(*addr)); if (ip->size == 4) { addr->len = sizeof(struct sockaddr_in); struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr->addr; addr4->sin_family = AF_INET; memcpy(&addr4->sin_addr, ip->bytes, ip->size); addr4->sin_port = netorder_port; } else if (ip->size == 16) { addr->len = sizeof(struct sockaddr_in6); struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr->addr; addr6->sin6_family = AF_INET6; memcpy(&addr6->sin6_addr, ip->bytes, ip->size); addr6->sin6_port = netorder_port; } } /* Returns addresses extracted from \a serverlist. */ static grpc_lb_addresses *process_serverlist_locked( grpc_exec_ctx *exec_ctx, const grpc_grpclb_serverlist *serverlist) { size_t num_valid = 0; /* first pass: count how many are valid in order to allocate the necessary * memory in a single block */ for (size_t i = 0; i < serverlist->num_servers; ++i) { if (is_server_valid(serverlist->servers[i], i, true)) ++num_valid; } if (num_valid == 0) return NULL; grpc_lb_addresses *lb_addresses = grpc_lb_addresses_create(num_valid, &lb_token_vtable); /* second pass: actually populate the addresses and LB tokens (aka user data * to the outside world) to be read by the RR policy during its creation. * Given that the validity tests are very cheap, they are performed again * instead of marking the valid ones during the first pass, as this would * incurr in an allocation due to the arbitrary number of server */ size_t addr_idx = 0; for (size_t sl_idx = 0; sl_idx < serverlist->num_servers; ++sl_idx) { GPR_ASSERT(addr_idx < num_valid); const grpc_grpclb_server *server = serverlist->servers[sl_idx]; if (!is_server_valid(serverlist->servers[sl_idx], sl_idx, false)) continue; /* address processing */ grpc_resolved_address addr; parse_server(server, &addr); /* lb token processing */ void *user_data; if (server->has_load_balance_token) { const size_t lb_token_max_length = GPR_ARRAY_SIZE(server->load_balance_token); const size_t lb_token_length = strnlen(server->load_balance_token, lb_token_max_length); grpc_slice lb_token_mdstr = grpc_slice_from_copied_buffer( server->load_balance_token, lb_token_length); user_data = (void *)grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_LB_TOKEN, lb_token_mdstr) .payload; } else { char *uri = grpc_sockaddr_to_uri(&addr); gpr_log(GPR_INFO, "Missing LB token for backend address '%s'. The empty token will " "be used instead", uri); gpr_free(uri); user_data = (void *)GRPC_MDELEM_LB_TOKEN_EMPTY.payload; } grpc_lb_addresses_set_address(lb_addresses, addr_idx, &addr.addr, addr.len, false /* is_balancer */, NULL /* balancer_name */, user_data); ++addr_idx; } GPR_ASSERT(addr_idx == num_valid); return lb_addresses; } /* returns true if the new RR policy should replace the current one, if any */ static bool update_lb_connectivity_status_locked( grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy, grpc_connectivity_state new_rr_state, grpc_error *new_rr_state_error) { const grpc_connectivity_state curr_glb_state = grpc_connectivity_state_check(&glb_policy->state_tracker); /* The new connectivity status is a function of the previous one and the new * input coming from the status of the RR policy. * * current state (grpclb's) * | * v || I | C | R | TF | SD | <- new state (RR's) * ===++====+=====+=====+======+======+ * I || I | C | R | [I] | [I] | * ---++----+-----+-----+------+------+ * C || I | C | R | [C] | [C] | * ---++----+-----+-----+------+------+ * R || I | C | R | [R] | [R] | * ---++----+-----+-----+------+------+ * TF || I | C | R | [TF] | [TF] | * ---++----+-----+-----+------+------+ * SD || NA | NA | NA | NA | NA | (*) * ---++----+-----+-----+------+------+ * * A [STATE] indicates that the old RR policy is kept. In those cases, STATE * is the current state of grpclb, which is left untouched. * * In summary, if the new state is TRANSIENT_FAILURE or SHUTDOWN, stick to * the previous RR instance. * * Note that the status is never updated to SHUTDOWN as a result of calling * this function. Only glb_shutdown() has the power to set that state. * * (*) This function mustn't be called during shutting down. */ GPR_ASSERT(curr_glb_state != GRPC_CHANNEL_SHUTDOWN); switch (new_rr_state) { case GRPC_CHANNEL_TRANSIENT_FAILURE: case GRPC_CHANNEL_SHUTDOWN: GPR_ASSERT(new_rr_state_error != GRPC_ERROR_NONE); return false; /* don't replace the RR policy */ case GRPC_CHANNEL_INIT: case GRPC_CHANNEL_IDLE: case GRPC_CHANNEL_CONNECTING: case GRPC_CHANNEL_READY: GPR_ASSERT(new_rr_state_error == GRPC_ERROR_NONE); } if (grpc_lb_glb_trace) { gpr_log(GPR_INFO, "Setting grpclb's state to %s from new RR policy %p state.", grpc_connectivity_state_name(new_rr_state), (void *)glb_policy->rr_policy); } grpc_connectivity_state_set(exec_ctx, &glb_policy->state_tracker, new_rr_state, GRPC_ERROR_REF(new_rr_state_error), "update_lb_connectivity_status_locked"); return true; } /* perform a pick over \a rr_policy. Given that a pick can return immediately * (ignoring its completion callback) we need to perform the cleanups this * callback would be otherwise resposible for */ static bool pick_from_internal_rr_locked( grpc_exec_ctx *exec_ctx, grpc_lb_policy *rr_policy, const grpc_lb_policy_pick_args *pick_args, grpc_connected_subchannel **target, wrapped_rr_closure_arg *wc_arg) { GPR_ASSERT(rr_policy != NULL); const bool pick_done = grpc_lb_policy_pick_locked( exec_ctx, rr_policy, pick_args, target, (void **)&wc_arg->lb_token, &wc_arg->wrapper_closure); if (pick_done) { /* synchronous grpc_lb_policy_pick call. Unref the RR policy. */ if (grpc_lb_glb_trace) { gpr_log(GPR_INFO, "Unreffing RR (0x%" PRIxPTR ")", (intptr_t)wc_arg->rr_policy); } GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "glb_pick_sync"); /* add the load reporting initial metadata */ initial_metadata_add_lb_token(exec_ctx, pick_args->initial_metadata, pick_args->lb_token_mdelem_storage, GRPC_MDELEM_REF(wc_arg->lb_token)); gpr_free(wc_arg); } /* else, the pending pick will be registered and taken care of by the * pending pick list inside the RR policy (glb_policy->rr_policy). * Eventually, wrapped_on_complete will be called, which will -among other * things- add the LB token to the call's initial metadata */ return pick_done; } static grpc_lb_policy *create_rr_locked( grpc_exec_ctx *exec_ctx, const grpc_grpclb_serverlist *serverlist, glb_lb_policy *glb_policy) { GPR_ASSERT(serverlist != NULL && serverlist->num_servers > 0); grpc_lb_policy_args args; memset(&args, 0, sizeof(args)); args.client_channel_factory = glb_policy->cc_factory; args.combiner = glb_policy->base.combiner; grpc_lb_addresses *addresses = process_serverlist_locked(exec_ctx, serverlist); // Replace the LB addresses in the channel args that we pass down to // the subchannel. static const char *keys_to_remove[] = {GRPC_ARG_LB_ADDRESSES}; const grpc_arg arg = grpc_lb_addresses_create_channel_arg(addresses); args.args = grpc_channel_args_copy_and_add_and_remove( glb_policy->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &arg, 1); grpc_lb_policy *rr = grpc_lb_policy_create(exec_ctx, "round_robin", &args); GPR_ASSERT(rr != NULL); grpc_lb_addresses_destroy(exec_ctx, addresses); grpc_channel_args_destroy(exec_ctx, args.args); return rr; } static void glb_rr_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); /* glb_policy->rr_policy may be NULL (initial handover) */ static void rr_handover_locked(grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy) { GPR_ASSERT(glb_policy->serverlist != NULL && glb_policy->serverlist->num_servers > 0); if (glb_policy->shutting_down) return; grpc_lb_policy *new_rr_policy = create_rr_locked(exec_ctx, glb_policy->serverlist, glb_policy); if (new_rr_policy == NULL) { gpr_log(GPR_ERROR, "Failure creating a RoundRobin policy for serverlist update with " "%lu entries. The previous RR instance (%p), if any, will continue " "to be used. Future updates from the LB will attempt to create new " "instances.", (unsigned long)glb_policy->serverlist->num_servers, (void *)glb_policy->rr_policy); return; } grpc_error *new_rr_state_error = NULL; const grpc_connectivity_state new_rr_state = grpc_lb_policy_check_connectivity_locked(exec_ctx, new_rr_policy, &new_rr_state_error); /* Connectivity state is a function of the new RR policy just created */ const bool replace_old_rr = update_lb_connectivity_status_locked( exec_ctx, glb_policy, new_rr_state, new_rr_state_error); if (!replace_old_rr) { /* dispose of the new RR policy that won't be used after all */ GRPC_LB_POLICY_UNREF(exec_ctx, new_rr_policy, "rr_handover_no_replace"); if (grpc_lb_glb_trace) { gpr_log(GPR_INFO, "Keeping old RR policy (%p) despite new serverlist: new RR " "policy was in %s connectivity state.", (void *)glb_policy->rr_policy, grpc_connectivity_state_name(new_rr_state)); } return; } if (grpc_lb_glb_trace) { gpr_log(GPR_INFO, "Created RR policy (%p) to replace old RR (%p)", (void *)new_rr_policy, (void *)glb_policy->rr_policy); } if (glb_policy->rr_policy != NULL) { /* if we are phasing out an existing RR instance, unref it. */ GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy, "rr_handover"); } /* Finally update the RR policy to the newly created one */ glb_policy->rr_policy = new_rr_policy; /* Add the gRPC LB's interested_parties pollset_set to that of the newly * created RR policy. This will make the RR policy progress upon activity on * gRPC LB, which in turn is tied to the application's call */ grpc_pollset_set_add_pollset_set(exec_ctx, glb_policy->rr_policy->interested_parties, glb_policy->base.interested_parties); /* Allocate the data for the tracking of the new RR policy's connectivity. * It'll be deallocated in glb_rr_connectivity_changed() */ rr_connectivity_data *rr_connectivity = gpr_zalloc(sizeof(rr_connectivity_data)); grpc_closure_init(&rr_connectivity->on_change, glb_rr_connectivity_changed_locked, rr_connectivity, grpc_combiner_scheduler(glb_policy->base.combiner, false)); rr_connectivity->glb_policy = glb_policy; rr_connectivity->state = new_rr_state; /* Subscribe to changes to the connectivity of the new RR */ GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "rr_connectivity_cb"); grpc_lb_policy_notify_on_state_change_locked(exec_ctx, glb_policy->rr_policy, &rr_connectivity->state, &rr_connectivity->on_change); grpc_lb_policy_exit_idle_locked(exec_ctx, glb_policy->rr_policy); /* Update picks and pings in wait */ pending_pick *pp; while ((pp = glb_policy->pending_picks)) { glb_policy->pending_picks = pp->next; GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_pick"); pp->wrapped_on_complete_arg.rr_policy = glb_policy->rr_policy; if (grpc_lb_glb_trace) { gpr_log(GPR_INFO, "Pending pick about to PICK from 0x%" PRIxPTR "", (intptr_t)glb_policy->rr_policy); } pick_from_internal_rr_locked(exec_ctx, glb_policy->rr_policy, &pp->pick_args, pp->target, &pp->wrapped_on_complete_arg); } pending_ping *pping; while ((pping = glb_policy->pending_pings)) { glb_policy->pending_pings = pping->next; GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_ping"); pping->wrapped_notify_arg.rr_policy = glb_policy->rr_policy; if (grpc_lb_glb_trace) { gpr_log(GPR_INFO, "Pending ping about to PING from 0x%" PRIxPTR "", (intptr_t)glb_policy->rr_policy); } grpc_lb_policy_ping_one_locked(exec_ctx, glb_policy->rr_policy, &pping->wrapped_notify_arg.wrapper_closure); } } static void glb_rr_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { rr_connectivity_data *rr_connectivity = arg; glb_lb_policy *glb_policy = rr_connectivity->glb_policy; const bool shutting_down = glb_policy->shutting_down; bool unref_needed = false; GRPC_ERROR_REF(error); if (rr_connectivity->state == GRPC_CHANNEL_SHUTDOWN || shutting_down) { /* RR policy shutting down. Don't renew subscription and free the arg of * this callback. In addition we need to stash away the current policy to * be UNREF'd after releasing the lock. Otherwise, if the UNREF is the last * one, the policy would be destroyed, alongside the lock, which would * result in a use-after-free */ unref_needed = true; gpr_free(rr_connectivity); } else { /* rr state != SHUTDOWN && !shutting down: biz as usual */ update_lb_connectivity_status_locked(exec_ctx, glb_policy, rr_connectivity->state, error); /* Resubscribe. Reuse the "rr_connectivity_cb" weak ref. */ grpc_lb_policy_notify_on_state_change_locked( exec_ctx, glb_policy->rr_policy, &rr_connectivity->state, &rr_connectivity->on_change); } if (unref_needed) { GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base, "rr_connectivity_cb"); } GRPC_ERROR_UNREF(error); } static void destroy_balancer_name(grpc_exec_ctx *exec_ctx, void *balancer_name) { gpr_free(balancer_name); } static void *copy_balancer_name(void *balancer_name) { return gpr_strdup(balancer_name); } static grpc_slice_hash_table_entry targets_info_entry_create( const char *address, const char *balancer_name) { static const grpc_slice_hash_table_vtable vtable = {destroy_balancer_name, copy_balancer_name}; grpc_slice_hash_table_entry entry; entry.key = grpc_slice_from_copied_string(address); entry.value = (void *)balancer_name; entry.vtable = &vtable; return entry; } /* Returns the target URI for the LB service whose addresses are in \a * addresses. Using this URI, a bidirectional streaming channel will be created * for the reception of load balancing updates. * * The output argument \a targets_info will be updated to contain a mapping of * "LB server address" to "balancer name", as reported by the naming system. * This mapping will be propagated via the channel arguments of the * aforementioned LB streaming channel, to be used by the security connector for * secure naming checks. The user is responsible for freeing \a targets_info. */ static char *get_lb_uri_target_addresses(grpc_exec_ctx *exec_ctx, const grpc_lb_addresses *addresses, grpc_slice_hash_table **targets_info) { size_t num_grpclb_addrs = 0; for (size_t i = 0; i < addresses->num_addresses; ++i) { if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs; } /* All input addresses come from a resolver that claims they are LB services. * It's the resolver's responsibility to make sure this policy is only * instantiated and used in that case. Otherwise, something has gone wrong. */ GPR_ASSERT(num_grpclb_addrs > 0); grpc_slice_hash_table_entry *targets_info_entries = gpr_malloc(sizeof(*targets_info_entries) * num_grpclb_addrs); /* construct a target ipvX://ip1:port1,ip2:port2,... from the addresses in \a * addresses */ /* TODO(dgq): support mixed ip version */ char **addr_strs = gpr_malloc(sizeof(char *) * num_grpclb_addrs); size_t addr_index = 0; for (size_t i = 0; i < addresses->num_addresses; i++) { if (addresses->addresses[i].user_data != NULL) { gpr_log(GPR_ERROR, "This LB policy doesn't support user data. It will be ignored"); } if (addresses->addresses[i].is_balancer) { char *addr_str; GPR_ASSERT(grpc_sockaddr_to_string( &addr_str, &addresses->addresses[i].address, true) > 0); targets_info_entries[addr_index] = targets_info_entry_create( addr_str, addresses->addresses[i].balancer_name); addr_strs[addr_index++] = addr_str; } } GPR_ASSERT(addr_index == num_grpclb_addrs); size_t uri_path_len; char *uri_path = gpr_strjoin_sep((const char **)addr_strs, num_grpclb_addrs, ",", &uri_path_len); for (size_t i = 0; i < num_grpclb_addrs; i++) gpr_free(addr_strs[i]); gpr_free(addr_strs); char *target_uri_str = NULL; /* TODO(dgq): Don't assume all addresses will share the scheme of the first * one */ gpr_asprintf(&target_uri_str, "%s:%s", grpc_sockaddr_get_uri_scheme(&addresses->addresses[0].address), uri_path); gpr_free(uri_path); *targets_info = grpc_slice_hash_table_create(num_grpclb_addrs, targets_info_entries); for (size_t i = 0; i < num_grpclb_addrs; i++) { grpc_slice_unref_internal(exec_ctx, targets_info_entries[i].key); } gpr_free(targets_info_entries); return target_uri_str; } static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx, grpc_lb_policy_factory *factory, grpc_lb_policy_args *args) { /* Count the number of gRPC-LB addresses. There must be at least one. * TODO(roth): For now, we ignore non-balancer addresses, but in the * future, we may change the behavior such that we fall back to using * the non-balancer addresses if we cannot reach any balancers. At that * time, this should be changed to allow a list with no balancer addresses, * since the resolver might fail to return a balancer address even when * this is the right LB policy to use. */ const grpc_arg *arg = grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES); if (arg == NULL || arg->type != GRPC_ARG_POINTER) { return NULL; } grpc_lb_addresses *addresses = arg->value.pointer.p; size_t num_grpclb_addrs = 0; for (size_t i = 0; i < addresses->num_addresses; ++i) { if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs; } if (num_grpclb_addrs == 0) return NULL; glb_lb_policy *glb_policy = gpr_zalloc(sizeof(*glb_policy)); /* Get server name. */ arg = grpc_channel_args_find(args->args, GRPC_ARG_SERVER_URI); GPR_ASSERT(arg != NULL); GPR_ASSERT(arg->type == GRPC_ARG_STRING); grpc_uri *uri = grpc_uri_parse(exec_ctx, arg->value.string, true); GPR_ASSERT(uri->path[0] != '\0'); glb_policy->server_name = gpr_strdup(uri->path[0] == '/' ? uri->path + 1 : uri->path); if (grpc_lb_glb_trace) { gpr_log(GPR_INFO, "Will use '%s' as the server name for LB request.", glb_policy->server_name); } grpc_uri_destroy(uri); glb_policy->cc_factory = args->client_channel_factory; glb_policy->args = grpc_channel_args_copy(args->args); GPR_ASSERT(glb_policy->cc_factory != NULL); grpc_slice_hash_table *targets_info = NULL; /* Create a client channel over them to communicate with a LB service */ char *lb_service_target_addresses = get_lb_uri_target_addresses(exec_ctx, addresses, &targets_info); grpc_channel_args *lb_channel_args = get_lb_channel_args(exec_ctx, targets_info, args->args); glb_policy->lb_channel = grpc_lb_policy_grpclb_create_lb_channel( exec_ctx, lb_service_target_addresses, args->client_channel_factory, lb_channel_args); grpc_slice_hash_table_unref(exec_ctx, targets_info); grpc_channel_args_destroy(exec_ctx, lb_channel_args); gpr_free(lb_service_target_addresses); if (glb_policy->lb_channel == NULL) { gpr_free(glb_policy); return NULL; } grpc_lb_policy_init(&glb_policy->base, &glb_lb_policy_vtable, args->combiner); grpc_connectivity_state_init(&glb_policy->state_tracker, GRPC_CHANNEL_IDLE, "grpclb"); return &glb_policy->base; } static void glb_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { glb_lb_policy *glb_policy = (glb_lb_policy *)pol; GPR_ASSERT(glb_policy->pending_picks == NULL); GPR_ASSERT(glb_policy->pending_pings == NULL); gpr_free((void *)glb_policy->server_name); grpc_channel_args_destroy(exec_ctx, glb_policy->args); grpc_channel_destroy(glb_policy->lb_channel); glb_policy->lb_channel = NULL; grpc_connectivity_state_destroy(exec_ctx, &glb_policy->state_tracker); if (glb_policy->serverlist != NULL) { grpc_grpclb_destroy_serverlist(glb_policy->serverlist); } gpr_free(glb_policy); } static void glb_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { glb_lb_policy *glb_policy = (glb_lb_policy *)pol; glb_policy->shutting_down = true; pending_pick *pp = glb_policy->pending_picks; glb_policy->pending_picks = NULL; pending_ping *pping = glb_policy->pending_pings; glb_policy->pending_pings = NULL; if (glb_policy->rr_policy) { GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy, "glb_shutdown"); } grpc_connectivity_state_set( exec_ctx, &glb_policy->state_tracker, GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel Shutdown"), "glb_shutdown"); /* We need a copy of the lb_call pointer because we can't cancell the call * while holding glb_policy->mu: lb_on_server_status_received, invoked due to * the cancel, needs to acquire that same lock */ grpc_call *lb_call = glb_policy->lb_call; /* glb_policy->lb_call and this local lb_call must be consistent at this point * because glb_policy->lb_call is only assigned in lb_call_init_locked as part * of query_for_backends_locked, which can only be invoked while * glb_policy->shutting_down is false. */ if (lb_call != NULL) { grpc_call_cancel(lb_call, NULL); /* lb_on_server_status_received will pick up the cancel and clean up */ } while (pp != NULL) { pending_pick *next = pp->next; *pp->target = NULL; grpc_closure_sched(exec_ctx, &pp->wrapped_on_complete_arg.wrapper_closure, GRPC_ERROR_NONE); pp = next; } while (pping != NULL) { pending_ping *next = pping->next; grpc_closure_sched(exec_ctx, &pping->wrapped_notify_arg.wrapper_closure, GRPC_ERROR_NONE); pping = next; } } static void glb_cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_connected_subchannel **target, grpc_error *error) { glb_lb_policy *glb_policy = (glb_lb_policy *)pol; pending_pick *pp = glb_policy->pending_picks; glb_policy->pending_picks = NULL; while (pp != NULL) { pending_pick *next = pp->next; if (pp->target == target) { *target = NULL; grpc_closure_sched(exec_ctx, &pp->wrapped_on_complete_arg.wrapper_closure, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Pick Cancelled", &error, 1)); } else { pp->next = glb_policy->pending_picks; glb_policy->pending_picks = pp; } pp = next; } GRPC_ERROR_UNREF(error); } static void glb_cancel_picks_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, uint32_t initial_metadata_flags_mask, uint32_t initial_metadata_flags_eq, grpc_error *error) { glb_lb_policy *glb_policy = (glb_lb_policy *)pol; pending_pick *pp = glb_policy->pending_picks; glb_policy->pending_picks = NULL; while (pp != NULL) { pending_pick *next = pp->next; if ((pp->pick_args.initial_metadata_flags & initial_metadata_flags_mask) == initial_metadata_flags_eq) { grpc_closure_sched(exec_ctx, &pp->wrapped_on_complete_arg.wrapper_closure, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Pick Cancelled", &error, 1)); } else { pp->next = glb_policy->pending_picks; glb_policy->pending_picks = pp; } pp = next; } GRPC_ERROR_UNREF(error); } static void query_for_backends_locked(grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy); static void start_picking_locked(grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy) { glb_policy->started_picking = true; gpr_backoff_reset(&glb_policy->lb_call_backoff_state); query_for_backends_locked(exec_ctx, glb_policy); } static void glb_exit_idle_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { glb_lb_policy *glb_policy = (glb_lb_policy *)pol; if (!glb_policy->started_picking) { start_picking_locked(exec_ctx, glb_policy); } } static int glb_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, const grpc_lb_policy_pick_args *pick_args, grpc_connected_subchannel **target, void **user_data, grpc_closure *on_complete) { if (pick_args->lb_token_mdelem_storage == NULL) { *target = NULL; grpc_closure_sched(exec_ctx, on_complete, GRPC_ERROR_CREATE_FROM_STATIC_STRING( "No mdelem storage for the LB token. Load reporting " "won't work without it. Failing")); return 0; } glb_lb_policy *glb_policy = (glb_lb_policy *)pol; glb_policy->deadline = pick_args->deadline; bool pick_done; if (glb_policy->rr_policy != NULL) { if (grpc_lb_glb_trace) { gpr_log(GPR_INFO, "grpclb %p about to PICK from RR %p", (void *)glb_policy, (void *)glb_policy->rr_policy); } GRPC_LB_POLICY_REF(glb_policy->rr_policy, "glb_pick"); wrapped_rr_closure_arg *wc_arg = gpr_zalloc(sizeof(wrapped_rr_closure_arg)); grpc_closure_init(&wc_arg->wrapper_closure, wrapped_rr_closure, wc_arg, grpc_schedule_on_exec_ctx); wc_arg->rr_policy = glb_policy->rr_policy; wc_arg->target = target; wc_arg->wrapped_closure = on_complete; wc_arg->lb_token_mdelem_storage = pick_args->lb_token_mdelem_storage; wc_arg->initial_metadata = pick_args->initial_metadata; wc_arg->free_when_done = wc_arg; pick_done = pick_from_internal_rr_locked(exec_ctx, glb_policy->rr_policy, pick_args, target, wc_arg); } else { if (grpc_lb_glb_trace) { gpr_log(GPR_DEBUG, "No RR policy in grpclb instance %p. Adding to grpclb's pending " "picks", (void *)(glb_policy)); } add_pending_pick(&glb_policy->pending_picks, pick_args, target, on_complete); if (!glb_policy->started_picking) { start_picking_locked(exec_ctx, glb_policy); } pick_done = false; } return pick_done; } static grpc_connectivity_state glb_check_connectivity_locked( grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_error **connectivity_error) { glb_lb_policy *glb_policy = (glb_lb_policy *)pol; return grpc_connectivity_state_get(&glb_policy->state_tracker, connectivity_error); } static void glb_ping_one_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_closure *closure) { glb_lb_policy *glb_policy = (glb_lb_policy *)pol; if (glb_policy->rr_policy) { grpc_lb_policy_ping_one_locked(exec_ctx, glb_policy->rr_policy, closure); } else { add_pending_ping(&glb_policy->pending_pings, closure); if (!glb_policy->started_picking) { start_picking_locked(exec_ctx, glb_policy); } } } static void glb_notify_on_state_change_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_connectivity_state *current, grpc_closure *notify) { glb_lb_policy *glb_policy = (glb_lb_policy *)pol; grpc_connectivity_state_notify_on_state_change( exec_ctx, &glb_policy->state_tracker, current, notify); } static void lb_on_server_status_received_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); static void lb_on_response_received_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); static void lb_call_init_locked(grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy) { GPR_ASSERT(glb_policy->server_name != NULL); GPR_ASSERT(glb_policy->server_name[0] != '\0'); GPR_ASSERT(!glb_policy->shutting_down); /* Note the following LB call progresses every time there's activity in \a * glb_policy->base.interested_parties, which is comprised of the polling * entities from \a client_channel. */ grpc_slice host = grpc_slice_from_copied_string(glb_policy->server_name); glb_policy->lb_call = grpc_channel_create_pollset_set_call( exec_ctx, glb_policy->lb_channel, NULL, GRPC_PROPAGATE_DEFAULTS, glb_policy->base.interested_parties, GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD, &host, glb_policy->deadline, NULL); grpc_metadata_array_init(&glb_policy->lb_initial_metadata_recv); grpc_metadata_array_init(&glb_policy->lb_trailing_metadata_recv); grpc_grpclb_request *request = grpc_grpclb_request_create(glb_policy->server_name); grpc_slice request_payload_slice = grpc_grpclb_request_encode(request); glb_policy->lb_request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); grpc_slice_unref_internal(exec_ctx, request_payload_slice); grpc_grpclb_request_destroy(request); grpc_closure_init(&glb_policy->lb_on_server_status_received, lb_on_server_status_received_locked, glb_policy, grpc_combiner_scheduler(glb_policy->base.combiner, false)); grpc_closure_init(&glb_policy->lb_on_response_received, lb_on_response_received_locked, glb_policy, grpc_combiner_scheduler(glb_policy->base.combiner, false)); gpr_backoff_init(&glb_policy->lb_call_backoff_state, GRPC_GRPCLB_INITIAL_CONNECT_BACKOFF_SECONDS, GRPC_GRPCLB_RECONNECT_BACKOFF_MULTIPLIER, GRPC_GRPCLB_RECONNECT_JITTER, GRPC_GRPCLB_MIN_CONNECT_TIMEOUT_SECONDS * 1000, GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS * 1000); } static void lb_call_destroy_locked(grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy) { GPR_ASSERT(glb_policy->lb_call != NULL); grpc_call_destroy(glb_policy->lb_call); glb_policy->lb_call = NULL; grpc_metadata_array_destroy(&glb_policy->lb_initial_metadata_recv); grpc_metadata_array_destroy(&glb_policy->lb_trailing_metadata_recv); grpc_byte_buffer_destroy(glb_policy->lb_request_payload); grpc_slice_unref_internal(exec_ctx, glb_policy->lb_call_status_details); } /* * Auxiliary functions and LB client callbacks. */ static void query_for_backends_locked(grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy) { GPR_ASSERT(glb_policy->lb_channel != NULL); if (glb_policy->shutting_down) return; lb_call_init_locked(exec_ctx, glb_policy); if (grpc_lb_glb_trace) { gpr_log(GPR_INFO, "Query for backends (grpclb: %p, lb_call: %p)", (void *)glb_policy, (void *)glb_policy->lb_call); } GPR_ASSERT(glb_policy->lb_call != NULL); grpc_call_error call_error; grpc_op ops[4]; memset(ops, 0, sizeof(ops)); grpc_op *op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_INITIAL_METADATA; op->data.recv_initial_metadata.recv_initial_metadata = &glb_policy->lb_initial_metadata_recv; op->flags = 0; op->reserved = NULL; op++; GPR_ASSERT(glb_policy->lb_request_payload != NULL); op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message.send_message = glb_policy->lb_request_payload; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.trailing_metadata = &glb_policy->lb_trailing_metadata_recv; op->data.recv_status_on_client.status = &glb_policy->lb_call_status; op->data.recv_status_on_client.status_details = &glb_policy->lb_call_status_details; op->flags = 0; op->reserved = NULL; op++; /* take a weak ref (won't prevent calling of \a glb_shutdown if the strong ref * count goes to zero) to be unref'd in lb_on_server_status_received */ GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "lb_on_server_status_received"); call_error = grpc_call_start_batch_and_execute( exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops), &glb_policy->lb_on_server_status_received); GPR_ASSERT(GRPC_CALL_OK == call_error); op = ops; op->op = GRPC_OP_RECV_MESSAGE; op->data.recv_message.recv_message = &glb_policy->lb_response_payload; op->flags = 0; op->reserved = NULL; op++; /* take another weak ref to be unref'd in lb_on_response_received */ GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "lb_on_response_received"); call_error = grpc_call_start_batch_and_execute( exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops), &glb_policy->lb_on_response_received); GPR_ASSERT(GRPC_CALL_OK == call_error); } static void lb_on_response_received_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { glb_lb_policy *glb_policy = arg; grpc_op ops[2]; memset(ops, 0, sizeof(ops)); grpc_op *op = ops; if (glb_policy->lb_response_payload != NULL) { gpr_backoff_reset(&glb_policy->lb_call_backoff_state); /* Received data from the LB server. Look inside * glb_policy->lb_response_payload, for a serverlist. */ grpc_byte_buffer_reader bbr; grpc_byte_buffer_reader_init(&bbr, glb_policy->lb_response_payload); grpc_slice response_slice = grpc_byte_buffer_reader_readall(&bbr); grpc_byte_buffer_destroy(glb_policy->lb_response_payload); grpc_grpclb_serverlist *serverlist = grpc_grpclb_response_parse_serverlist(response_slice); if (serverlist != NULL) { GPR_ASSERT(glb_policy->lb_call != NULL); grpc_slice_unref_internal(exec_ctx, response_slice); if (grpc_lb_glb_trace) { gpr_log(GPR_INFO, "Serverlist with %lu servers received", (unsigned long)serverlist->num_servers); for (size_t i = 0; i < serverlist->num_servers; ++i) { grpc_resolved_address addr; parse_server(serverlist->servers[i], &addr); char *ipport; grpc_sockaddr_to_string(&ipport, &addr, false); gpr_log(GPR_INFO, "Serverlist[%lu]: %s", (unsigned long)i, ipport); gpr_free(ipport); } } /* update serverlist */ if (serverlist->num_servers > 0) { if (grpc_grpclb_serverlist_equals(glb_policy->serverlist, serverlist)) { if (grpc_lb_glb_trace) { gpr_log(GPR_INFO, "Incoming server list identical to current, ignoring."); } grpc_grpclb_destroy_serverlist(serverlist); } else { /* new serverlist */ if (glb_policy->serverlist != NULL) { /* dispose of the old serverlist */ grpc_grpclb_destroy_serverlist(glb_policy->serverlist); } /* and update the copy in the glb_lb_policy instance. This serverlist * instance will be destroyed either upon the next update or in * glb_destroy() */ glb_policy->serverlist = serverlist; rr_handover_locked(exec_ctx, glb_policy); } } else { if (grpc_lb_glb_trace) { gpr_log(GPR_INFO, "Received empty server list. Picks will stay pending until a " "response with > 0 servers is received"); } } } else { /* serverlist == NULL */ gpr_log(GPR_ERROR, "Invalid LB response received: '%s'. Ignoring.", grpc_dump_slice(response_slice, GPR_DUMP_ASCII | GPR_DUMP_HEX)); grpc_slice_unref_internal(exec_ctx, response_slice); } if (!glb_policy->shutting_down) { /* keep listening for serverlist updates */ op->op = GRPC_OP_RECV_MESSAGE; op->data.recv_message.recv_message = &glb_policy->lb_response_payload; op->flags = 0; op->reserved = NULL; op++; /* reuse the "lb_on_response_received" weak ref taken in * query_for_backends_locked() */ const grpc_call_error call_error = grpc_call_start_batch_and_execute( exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops), &glb_policy->lb_on_response_received); /* loop */ GPR_ASSERT(GRPC_CALL_OK == call_error); } } else { /* empty payload: call cancelled. */ /* dispose of the "lb_on_response_received" weak ref taken in * query_for_backends_locked() and reused in every reception loop */ GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base, "lb_on_response_received_empty_payload"); } } static void lb_call_on_retry_timer_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { glb_lb_policy *glb_policy = arg; if (!glb_policy->shutting_down) { if (grpc_lb_glb_trace) { gpr_log(GPR_INFO, "Restaring call to LB server (grpclb %p)", (void *)glb_policy); } GPR_ASSERT(glb_policy->lb_call == NULL); query_for_backends_locked(exec_ctx, glb_policy); } GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base, "grpclb_on_retry_timer"); } static void lb_on_server_status_received_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { glb_lb_policy *glb_policy = arg; GPR_ASSERT(glb_policy->lb_call != NULL); if (grpc_lb_glb_trace) { char *status_details = grpc_slice_to_c_string(glb_policy->lb_call_status_details); gpr_log(GPR_DEBUG, "Status from LB server received. Status = %d, Details = '%s', " "(call: %p)", glb_policy->lb_call_status, status_details, (void *)glb_policy->lb_call); gpr_free(status_details); } /* We need to perform cleanups no matter what. */ lb_call_destroy_locked(exec_ctx, glb_policy); if (!glb_policy->shutting_down) { /* if we aren't shutting down, restart the LB client call after some time */ gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); gpr_timespec next_try = gpr_backoff_step(&glb_policy->lb_call_backoff_state, now); if (grpc_lb_glb_trace) { gpr_log(GPR_DEBUG, "Connection to LB server lost (grpclb: %p)...", (void *)glb_policy); gpr_timespec timeout = gpr_time_sub(next_try, now); if (gpr_time_cmp(timeout, gpr_time_0(timeout.clock_type)) > 0) { gpr_log(GPR_DEBUG, "... retrying in %" PRId64 ".%09d seconds.", timeout.tv_sec, timeout.tv_nsec); } else { gpr_log(GPR_DEBUG, "... retrying immediately."); } } GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "grpclb_retry_timer"); grpc_closure_init( &glb_policy->lb_on_call_retry, lb_call_on_retry_timer_locked, glb_policy, grpc_combiner_scheduler(glb_policy->base.combiner, false)); grpc_timer_init(exec_ctx, &glb_policy->lb_call_retry_timer, next_try, &glb_policy->lb_on_call_retry, now); } GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base, "lb_on_server_status_received"); } /* Code wiring the policy with the rest of the core */ static const grpc_lb_policy_vtable glb_lb_policy_vtable = { glb_destroy, glb_shutdown_locked, glb_pick_locked, glb_cancel_pick_locked, glb_cancel_picks_locked, glb_ping_one_locked, glb_exit_idle_locked, glb_check_connectivity_locked, glb_notify_on_state_change_locked}; static void glb_factory_ref(grpc_lb_policy_factory *factory) {} static void glb_factory_unref(grpc_lb_policy_factory *factory) {} static const grpc_lb_policy_factory_vtable glb_factory_vtable = { glb_factory_ref, glb_factory_unref, glb_create, "grpclb"}; static grpc_lb_policy_factory glb_lb_policy_factory = {&glb_factory_vtable}; grpc_lb_policy_factory *grpc_glb_lb_factory_create() { return &glb_lb_policy_factory; } /* Plugin registration */ void grpc_lb_policy_grpclb_init() { grpc_register_lb_policy(grpc_glb_lb_factory_create()); grpc_register_tracer("glb", &grpc_lb_glb_trace); } void grpc_lb_policy_grpclb_shutdown() {} grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h000066400000000000000000000040521310511640000262440ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_H #include "src/core/ext/filters/client_channel/lb_policy_factory.h" /** Returns a load balancing factory for the glb policy, which tries to connect * to a load balancing server to decide the next successfully connected * subchannel to pick. */ grpc_lb_policy_factory *grpc_glb_lb_factory_create(); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_H */ grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.c000066400000000000000000000073651310511640000277410ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/support/string.h" grpc_channel *grpc_lb_policy_grpclb_create_lb_channel( grpc_exec_ctx *exec_ctx, const char *lb_service_target_addresses, grpc_client_channel_factory *client_channel_factory, grpc_channel_args *args) { grpc_channel *lb_channel = grpc_client_channel_factory_create_channel( exec_ctx, client_channel_factory, lb_service_target_addresses, GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, args); return lb_channel; } grpc_channel_args *get_lb_channel_args(grpc_exec_ctx *exec_ctx, grpc_slice_hash_table *targets_info, const grpc_channel_args *args) { /* We strip out the channel arg for the LB policy name, since we want * to use the default (pick_first) in this case. * * We also strip out the channel arg for the resolved addresses, since * that will be generated by the name resolver used in the LB channel. * Note that the LB channel will use the sockaddr resolver, so this * won't actually generate a query to DNS (or some other name service). * However, the addresses returned by the sockaddr resolver will have * is_balancer=false, whereas our own addresses have is_balancer=true. * We need the LB channel to return addresses with is_balancer=false * so that it does not wind up recursively using the grpclb LB policy, * as per the special case logic in client_channel.c. * * Lastly, we also strip out the channel arg for the server URI, * since that will be different for the LB channel than for the parent * channel (the client channel factory will re-add this arg with * the right value). */ static const char *keys_to_remove[] = { GRPC_ARG_LB_POLICY_NAME, GRPC_ARG_LB_ADDRESSES, GRPC_ARG_SERVER_URI}; return grpc_channel_args_copy_and_remove(args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove)); } grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h000066400000000000000000000053521310511640000277400ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_CHANNEL_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_CHANNEL_H #include "src/core/ext/filters/client_channel/lb_policy_factory.h" #include "src/core/lib/slice/slice_hash_table.h" /** Create the channel used for communicating with an LB service. * Note that an LB *service* may be comprised of several LB *servers*. * * \a lb_service_target_addresses is the target URI containing the addresses * from resolving the LB service's name (eg, ipv4:10.0.0.1:1234,10.2.3.4:9876). * \a client_channel_factory will be used for the creation of the LB channel, * alongside the channel args passed in \a args. */ grpc_channel *grpc_lb_policy_grpclb_create_lb_channel( grpc_exec_ctx *exec_ctx, const char *lb_service_target_addresses, grpc_client_channel_factory *client_channel_factory, grpc_channel_args *args); grpc_channel_args *get_lb_channel_args(grpc_exec_ctx *exec_ctx, grpc_slice_hash_table *targets_info, const grpc_channel_args *args); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_CHANNEL_H \ */ grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c000066400000000000000000000122301310511640000312720ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/transport/lb_targets_info.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/support/string.h" grpc_channel *grpc_lb_policy_grpclb_create_lb_channel( grpc_exec_ctx *exec_ctx, const char *lb_service_target_addresses, grpc_client_channel_factory *client_channel_factory, grpc_channel_args *args) { grpc_channel_args *new_args = args; grpc_channel_credentials *channel_credentials = grpc_channel_credentials_find_in_args(args); if (channel_credentials != NULL) { /* Substitute the channel credentials with a version without call * credentials: the load balancer is not necessarily trusted to handle * bearer token credentials */ static const char *keys_to_remove[] = {GRPC_ARG_CHANNEL_CREDENTIALS}; grpc_channel_credentials *creds_sans_call_creds = grpc_channel_credentials_duplicate_without_call_credentials( channel_credentials); GPR_ASSERT(creds_sans_call_creds != NULL); grpc_arg args_to_add[] = { grpc_channel_credentials_to_arg(creds_sans_call_creds)}; /* Create the new set of channel args */ new_args = grpc_channel_args_copy_and_add_and_remove( args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), args_to_add, GPR_ARRAY_SIZE(args_to_add)); grpc_channel_credentials_unref(exec_ctx, creds_sans_call_creds); } grpc_channel *lb_channel = grpc_client_channel_factory_create_channel( exec_ctx, client_channel_factory, lb_service_target_addresses, GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, new_args); if (channel_credentials != NULL) { grpc_channel_args_destroy(exec_ctx, new_args); } return lb_channel; } grpc_channel_args *get_lb_channel_args(grpc_exec_ctx *exec_ctx, grpc_slice_hash_table *targets_info, const grpc_channel_args *args) { const grpc_arg targets_info_arg = grpc_lb_targets_info_create_channel_arg(targets_info); /* We strip out the channel arg for the LB policy name, since we want * to use the default (pick_first) in this case. * * We also strip out the channel arg for the resolved addresses, since * that will be generated by the name resolver used in the LB channel. * Note that the LB channel will use the sockaddr resolver, so this * won't actually generate a query to DNS (or some other name service). * However, the addresses returned by the sockaddr resolver will have * is_balancer=false, whereas our own addresses have is_balancer=true. * We need the LB channel to return addresses with is_balancer=false * so that it does not wind up recursively using the grpclb LB policy, * as per the special case logic in client_channel.c. * * Lastly, we also strip out the channel arg for the server URI, * since that will be different for the LB channel than for the parent * channel (the client channel factory will re-add this arg with * the right value). */ static const char *keys_to_remove[] = { GRPC_ARG_LB_POLICY_NAME, GRPC_ARG_LB_ADDRESSES, GRPC_ARG_SERVER_URI}; /* Add the targets info table to be used for secure naming */ return grpc_channel_args_copy_and_add_and_remove( args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &targets_info_arg, 1); } grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c000066400000000000000000000216031310511640000303660ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h" #include "third_party/nanopb/pb_decode.h" #include "third_party/nanopb/pb_encode.h" #include typedef struct decode_serverlist_arg { /* The first pass counts the number of servers in the server list. The second * one allocates and decodes. */ bool first_pass; /* The decoding callback is invoked once per server in serverlist. Remember * which index of the serverlist are we currently decoding */ size_t decoding_idx; /* Populated after the first pass. Number of server in the input serverlist */ size_t num_servers; /* The decoded serverlist */ grpc_grpclb_server **servers; } decode_serverlist_arg; /* invoked once for every Server in ServerList */ static bool decode_serverlist(pb_istream_t *stream, const pb_field_t *field, void **arg) { decode_serverlist_arg *dec_arg = *arg; if (dec_arg->first_pass) { /* count how many server do we have */ grpc_grpclb_server server; if (!pb_decode(stream, grpc_lb_v1_Server_fields, &server)) { gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(stream)); return false; } dec_arg->num_servers++; } else { /* second pass. Actually decode. */ grpc_grpclb_server *server = gpr_zalloc(sizeof(grpc_grpclb_server)); GPR_ASSERT(dec_arg->num_servers > 0); if (dec_arg->decoding_idx == 0) { /* first iteration of second pass */ dec_arg->servers = gpr_malloc(sizeof(grpc_grpclb_server *) * dec_arg->num_servers); } if (!pb_decode(stream, grpc_lb_v1_Server_fields, server)) { gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(stream)); return false; } dec_arg->servers[dec_arg->decoding_idx++] = server; } return true; } grpc_grpclb_request *grpc_grpclb_request_create(const char *lb_service_name) { grpc_grpclb_request *req = gpr_malloc(sizeof(grpc_grpclb_request)); req->has_client_stats = 0; /* TODO(dgq): add support for stats once defined */ req->has_initial_request = 1; req->initial_request.has_name = 1; strncpy(req->initial_request.name, lb_service_name, GRPC_GRPCLB_SERVICE_NAME_MAX_LENGTH); return req; } grpc_slice grpc_grpclb_request_encode(const grpc_grpclb_request *request) { size_t encoded_length; pb_ostream_t sizestream; pb_ostream_t outputstream; grpc_slice slice; memset(&sizestream, 0, sizeof(pb_ostream_t)); pb_encode(&sizestream, grpc_lb_v1_LoadBalanceRequest_fields, request); encoded_length = sizestream.bytes_written; slice = grpc_slice_malloc(encoded_length); outputstream = pb_ostream_from_buffer(GRPC_SLICE_START_PTR(slice), encoded_length); GPR_ASSERT(pb_encode(&outputstream, grpc_lb_v1_LoadBalanceRequest_fields, request) != 0); return slice; } void grpc_grpclb_request_destroy(grpc_grpclb_request *request) { gpr_free(request); } typedef grpc_lb_v1_LoadBalanceResponse grpc_grpclb_response; grpc_grpclb_initial_response *grpc_grpclb_initial_response_parse( grpc_slice encoded_grpc_grpclb_response) { pb_istream_t stream = pb_istream_from_buffer(GRPC_SLICE_START_PTR(encoded_grpc_grpclb_response), GRPC_SLICE_LENGTH(encoded_grpc_grpclb_response)); grpc_grpclb_response res; memset(&res, 0, sizeof(grpc_grpclb_response)); if (!pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, &res)) { gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream)); return NULL; } grpc_grpclb_initial_response *initial_res = gpr_malloc(sizeof(grpc_grpclb_initial_response)); memcpy(initial_res, &res.initial_response, sizeof(grpc_grpclb_initial_response)); return initial_res; } grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist( grpc_slice encoded_grpc_grpclb_response) { bool status; decode_serverlist_arg arg; pb_istream_t stream = pb_istream_from_buffer(GRPC_SLICE_START_PTR(encoded_grpc_grpclb_response), GRPC_SLICE_LENGTH(encoded_grpc_grpclb_response)); pb_istream_t stream_at_start = stream; grpc_grpclb_response res; memset(&res, 0, sizeof(grpc_grpclb_response)); memset(&arg, 0, sizeof(decode_serverlist_arg)); res.server_list.servers.funcs.decode = decode_serverlist; res.server_list.servers.arg = &arg; arg.first_pass = true; status = pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, &res); if (!status) { gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream)); return NULL; } arg.first_pass = false; status = pb_decode(&stream_at_start, grpc_lb_v1_LoadBalanceResponse_fields, &res); if (!status) { gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream)); return NULL; } grpc_grpclb_serverlist *sl = gpr_zalloc(sizeof(grpc_grpclb_serverlist)); sl->num_servers = arg.num_servers; sl->servers = arg.servers; if (res.server_list.has_expiration_interval) { sl->expiration_interval = res.server_list.expiration_interval; } return sl; } void grpc_grpclb_destroy_serverlist(grpc_grpclb_serverlist *serverlist) { if (serverlist == NULL) { return; } for (size_t i = 0; i < serverlist->num_servers; i++) { gpr_free(serverlist->servers[i]); } gpr_free(serverlist->servers); gpr_free(serverlist); } grpc_grpclb_serverlist *grpc_grpclb_serverlist_copy( const grpc_grpclb_serverlist *sl) { grpc_grpclb_serverlist *copy = gpr_zalloc(sizeof(grpc_grpclb_serverlist)); copy->num_servers = sl->num_servers; memcpy(©->expiration_interval, &sl->expiration_interval, sizeof(grpc_grpclb_duration)); copy->servers = gpr_malloc(sizeof(grpc_grpclb_server *) * sl->num_servers); for (size_t i = 0; i < sl->num_servers; i++) { copy->servers[i] = gpr_malloc(sizeof(grpc_grpclb_server)); memcpy(copy->servers[i], sl->servers[i], sizeof(grpc_grpclb_server)); } return copy; } bool grpc_grpclb_serverlist_equals(const grpc_grpclb_serverlist *lhs, const grpc_grpclb_serverlist *rhs) { if ((lhs == NULL) || (rhs == NULL)) { return false; } if (lhs->num_servers != rhs->num_servers) { return false; } if (grpc_grpclb_duration_compare(&lhs->expiration_interval, &rhs->expiration_interval) != 0) { return false; } for (size_t i = 0; i < lhs->num_servers; i++) { if (!grpc_grpclb_server_equals(lhs->servers[i], rhs->servers[i])) { return false; } } return true; } bool grpc_grpclb_server_equals(const grpc_grpclb_server *lhs, const grpc_grpclb_server *rhs) { return memcmp(lhs, rhs, sizeof(grpc_grpclb_server)) == 0; } int grpc_grpclb_duration_compare(const grpc_grpclb_duration *lhs, const grpc_grpclb_duration *rhs) { GPR_ASSERT(lhs && rhs); if (lhs->has_seconds && rhs->has_seconds) { if (lhs->seconds < rhs->seconds) return -1; if (lhs->seconds > rhs->seconds) return 1; } else if (lhs->has_seconds) { return 1; } else if (rhs->has_seconds) { return -1; } GPR_ASSERT(lhs->seconds == rhs->seconds); if (lhs->has_nanos && rhs->has_nanos) { if (lhs->nanos < rhs->nanos) return -1; if (lhs->nanos > rhs->nanos) return 1; } else if (lhs->has_nanos) { return 1; } else if (rhs->has_nanos) { return -1; } return 0; } void grpc_grpclb_initial_response_destroy( grpc_grpclb_initial_response *response) { gpr_free(response); } grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h000066400000000000000000000104451310511640000303750ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_LOAD_BALANCER_API_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_LOAD_BALANCER_API_H #include #include "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" #include "src/core/ext/filters/client_channel/lb_policy_factory.h" #ifdef __cplusplus extern "C" { #endif #define GRPC_GRPCLB_SERVICE_NAME_MAX_LENGTH 128 typedef grpc_lb_v1_Server_ip_address_t grpc_grpclb_ip_address; typedef grpc_lb_v1_LoadBalanceRequest grpc_grpclb_request; typedef grpc_lb_v1_InitialLoadBalanceResponse grpc_grpclb_initial_response; typedef grpc_lb_v1_Server grpc_grpclb_server; typedef grpc_lb_v1_Duration grpc_grpclb_duration; typedef struct grpc_grpclb_serverlist { grpc_grpclb_server **servers; size_t num_servers; grpc_grpclb_duration expiration_interval; } grpc_grpclb_serverlist; /** Create a request for a gRPC LB service under \a lb_service_name */ grpc_grpclb_request *grpc_grpclb_request_create(const char *lb_service_name); /** Protocol Buffers v3-encode \a request */ grpc_slice grpc_grpclb_request_encode(const grpc_grpclb_request *request); /** Destroy \a request */ void grpc_grpclb_request_destroy(grpc_grpclb_request *request); /** Parse (ie, decode) the bytes in \a encoded_grpc_grpclb_response as a \a * grpc_grpclb_initial_response */ grpc_grpclb_initial_response *grpc_grpclb_initial_response_parse( grpc_slice encoded_grpc_grpclb_response); /** Parse the list of servers from an encoded \a grpc_grpclb_response */ grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist( grpc_slice encoded_grpc_grpclb_response); /** Return a copy of \a sl. The caller is responsible for calling \a * grpc_grpclb_destroy_serverlist on the returned copy. */ grpc_grpclb_serverlist *grpc_grpclb_serverlist_copy( const grpc_grpclb_serverlist *sl); bool grpc_grpclb_serverlist_equals(const grpc_grpclb_serverlist *lhs, const grpc_grpclb_serverlist *rhs); bool grpc_grpclb_server_equals(const grpc_grpclb_server *lhs, const grpc_grpclb_server *rhs); /** Destroy \a serverlist */ void grpc_grpclb_destroy_serverlist(grpc_grpclb_serverlist *serverlist); /** Compare \a lhs against \a rhs and return 0 if \a lhs and \a rhs are equal, * < 0 if \a lhs represents a duration shorter than \a rhs and > 0 otherwise */ int grpc_grpclb_duration_compare(const grpc_grpclb_duration *lhs, const grpc_grpclb_duration *rhs); /** Destroy \a initial_response */ void grpc_grpclb_initial_response_destroy( grpc_grpclb_initial_response *response); #ifdef __cplusplus } #endif #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_LOAD_BALANCER_API_H \ */ grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/000077500000000000000000000000001310511640000257645ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/000077500000000000000000000000001310511640000267175ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/000077500000000000000000000000001310511640000273145ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/000077500000000000000000000000001310511640000276425ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c000066400000000000000000000131301310511640000331520ustar00rootroot00000000000000/* Automatically generated nanopb constant definitions */ /* Generated by nanopb-0.3.7-dev */ #include "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" /* @@protoc_insertion_point(includes) */ #if PB_PROTO_HEADER_VERSION != 30 #error Regenerate this file with the current version of nanopb generator. #endif const pb_field_t grpc_lb_v1_Duration_fields[3] = { PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, grpc_lb_v1_Duration, seconds, seconds, 0), PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_Duration, nanos, seconds, 0), PB_LAST_FIELD }; const pb_field_t grpc_lb_v1_LoadBalanceRequest_fields[3] = { PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, grpc_lb_v1_LoadBalanceRequest, initial_request, initial_request, &grpc_lb_v1_InitialLoadBalanceRequest_fields), PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v1_LoadBalanceRequest, client_stats, initial_request, &grpc_lb_v1_ClientStats_fields), PB_LAST_FIELD }; const pb_field_t grpc_lb_v1_InitialLoadBalanceRequest_fields[2] = { PB_FIELD( 1, STRING , OPTIONAL, STATIC , FIRST, grpc_lb_v1_InitialLoadBalanceRequest, name, name, 0), PB_LAST_FIELD }; const pb_field_t grpc_lb_v1_ClientStats_fields[4] = { PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, grpc_lb_v1_ClientStats, total_requests, total_requests, 0), PB_FIELD( 2, INT64 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_ClientStats, client_rpc_errors, total_requests, 0), PB_FIELD( 3, INT64 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_ClientStats, dropped_requests, client_rpc_errors, 0), PB_LAST_FIELD }; const pb_field_t grpc_lb_v1_LoadBalanceResponse_fields[3] = { PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, grpc_lb_v1_LoadBalanceResponse, initial_response, initial_response, &grpc_lb_v1_InitialLoadBalanceResponse_fields), PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v1_LoadBalanceResponse, server_list, initial_response, &grpc_lb_v1_ServerList_fields), PB_LAST_FIELD }; const pb_field_t grpc_lb_v1_InitialLoadBalanceResponse_fields[3] = { PB_FIELD( 1, STRING , OPTIONAL, STATIC , FIRST, grpc_lb_v1_InitialLoadBalanceResponse, load_balancer_delegate, load_balancer_delegate, 0), PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval, load_balancer_delegate, &grpc_lb_v1_Duration_fields), PB_LAST_FIELD }; const pb_field_t grpc_lb_v1_ServerList_fields[3] = { PB_FIELD( 1, MESSAGE , REPEATED, CALLBACK, FIRST, grpc_lb_v1_ServerList, servers, servers, &grpc_lb_v1_Server_fields), PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v1_ServerList, expiration_interval, servers, &grpc_lb_v1_Duration_fields), PB_LAST_FIELD }; const pb_field_t grpc_lb_v1_Server_fields[5] = { PB_FIELD( 1, BYTES , OPTIONAL, STATIC , FIRST, grpc_lb_v1_Server, ip_address, ip_address, 0), PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_Server, port, ip_address, 0), PB_FIELD( 3, STRING , OPTIONAL, STATIC , OTHER, grpc_lb_v1_Server, load_balance_token, port, 0), PB_FIELD( 4, BOOL , OPTIONAL, STATIC , OTHER, grpc_lb_v1_Server, drop_request, load_balance_token, 0), PB_LAST_FIELD }; /* Check that field information fits in pb_field_t */ #if !defined(PB_FIELD_32BIT) /* If you get an error here, it means that you need to define PB_FIELD_32BIT * compile-time option. You can do that in pb.h or on compiler command line. * * The reason you need to do this is that some of your messages contain tag * numbers or field sizes that are larger than what can fit in 8 or 16 bit * field descriptors. */ PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 65536 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 65536 && pb_membersize(grpc_lb_v1_ServerList, servers) < 65536 && pb_membersize(grpc_lb_v1_ServerList, expiration_interval) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_lb_v1_Duration_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server) #endif #if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) /* If you get an error here, it means that you need to define PB_FIELD_16BIT * compile-time option. You can do that in pb.h or on compiler command line. * * The reason you need to do this is that some of your messages contain tag * numbers or field sizes that are larger than what can fit in the default * 8 bit descriptors. */ PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 256 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 256 && pb_membersize(grpc_lb_v1_ServerList, servers) < 256 && pb_membersize(grpc_lb_v1_ServerList, expiration_interval) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_lb_v1_Duration_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server) #endif /* @@protoc_insertion_point(eof) */ grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h000066400000000000000000000153101310511640000331610ustar00rootroot00000000000000/* Automatically generated nanopb header */ /* Generated by nanopb-0.3.7-dev */ #ifndef PB_GRPC_LB_V1_LOAD_BALANCER_PB_H_INCLUDED #define PB_GRPC_LB_V1_LOAD_BALANCER_PB_H_INCLUDED #include "third_party/nanopb/pb.h" /* @@protoc_insertion_point(includes) */ #if PB_PROTO_HEADER_VERSION != 30 #error Regenerate this file with the current version of nanopb generator. #endif #ifdef __cplusplus extern "C" { #endif /* Struct definitions */ typedef struct _grpc_lb_v1_ClientStats { bool has_total_requests; int64_t total_requests; bool has_client_rpc_errors; int64_t client_rpc_errors; bool has_dropped_requests; int64_t dropped_requests; /* @@protoc_insertion_point(struct:grpc_lb_v1_ClientStats) */ } grpc_lb_v1_ClientStats; typedef struct _grpc_lb_v1_Duration { bool has_seconds; int64_t seconds; bool has_nanos; int32_t nanos; /* @@protoc_insertion_point(struct:grpc_lb_v1_Duration) */ } grpc_lb_v1_Duration; typedef struct _grpc_lb_v1_InitialLoadBalanceRequest { bool has_name; char name[128]; /* @@protoc_insertion_point(struct:grpc_lb_v1_InitialLoadBalanceRequest) */ } grpc_lb_v1_InitialLoadBalanceRequest; typedef PB_BYTES_ARRAY_T(16) grpc_lb_v1_Server_ip_address_t; typedef struct _grpc_lb_v1_Server { bool has_ip_address; grpc_lb_v1_Server_ip_address_t ip_address; bool has_port; int32_t port; bool has_load_balance_token; char load_balance_token[50]; bool has_drop_request; bool drop_request; /* @@protoc_insertion_point(struct:grpc_lb_v1_Server) */ } grpc_lb_v1_Server; typedef struct _grpc_lb_v1_InitialLoadBalanceResponse { bool has_load_balancer_delegate; char load_balancer_delegate[64]; bool has_client_stats_report_interval; grpc_lb_v1_Duration client_stats_report_interval; /* @@protoc_insertion_point(struct:grpc_lb_v1_InitialLoadBalanceResponse) */ } grpc_lb_v1_InitialLoadBalanceResponse; typedef struct _grpc_lb_v1_LoadBalanceRequest { bool has_initial_request; grpc_lb_v1_InitialLoadBalanceRequest initial_request; bool has_client_stats; grpc_lb_v1_ClientStats client_stats; /* @@protoc_insertion_point(struct:grpc_lb_v1_LoadBalanceRequest) */ } grpc_lb_v1_LoadBalanceRequest; typedef struct _grpc_lb_v1_ServerList { pb_callback_t servers; bool has_expiration_interval; grpc_lb_v1_Duration expiration_interval; /* @@protoc_insertion_point(struct:grpc_lb_v1_ServerList) */ } grpc_lb_v1_ServerList; typedef struct _grpc_lb_v1_LoadBalanceResponse { bool has_initial_response; grpc_lb_v1_InitialLoadBalanceResponse initial_response; bool has_server_list; grpc_lb_v1_ServerList server_list; /* @@protoc_insertion_point(struct:grpc_lb_v1_LoadBalanceResponse) */ } grpc_lb_v1_LoadBalanceResponse; /* Default values for struct fields */ /* Initializer values for message structs */ #define grpc_lb_v1_Duration_init_default {false, 0, false, 0} #define grpc_lb_v1_LoadBalanceRequest_init_default {false, grpc_lb_v1_InitialLoadBalanceRequest_init_default, false, grpc_lb_v1_ClientStats_init_default} #define grpc_lb_v1_InitialLoadBalanceRequest_init_default {false, ""} #define grpc_lb_v1_ClientStats_init_default {false, 0, false, 0, false, 0} #define grpc_lb_v1_LoadBalanceResponse_init_default {false, grpc_lb_v1_InitialLoadBalanceResponse_init_default, false, grpc_lb_v1_ServerList_init_default} #define grpc_lb_v1_InitialLoadBalanceResponse_init_default {false, "", false, grpc_lb_v1_Duration_init_default} #define grpc_lb_v1_ServerList_init_default {{{NULL}, NULL}, false, grpc_lb_v1_Duration_init_default} #define grpc_lb_v1_Server_init_default {false, {0, {0}}, false, 0, false, "", false, 0} #define grpc_lb_v1_Duration_init_zero {false, 0, false, 0} #define grpc_lb_v1_LoadBalanceRequest_init_zero {false, grpc_lb_v1_InitialLoadBalanceRequest_init_zero, false, grpc_lb_v1_ClientStats_init_zero} #define grpc_lb_v1_InitialLoadBalanceRequest_init_zero {false, ""} #define grpc_lb_v1_ClientStats_init_zero {false, 0, false, 0, false, 0} #define grpc_lb_v1_LoadBalanceResponse_init_zero {false, grpc_lb_v1_InitialLoadBalanceResponse_init_zero, false, grpc_lb_v1_ServerList_init_zero} #define grpc_lb_v1_InitialLoadBalanceResponse_init_zero {false, "", false, grpc_lb_v1_Duration_init_zero} #define grpc_lb_v1_ServerList_init_zero {{{NULL}, NULL}, false, grpc_lb_v1_Duration_init_zero} #define grpc_lb_v1_Server_init_zero {false, {0, {0}}, false, 0, false, "", false, 0} /* Field tags (for use in manual encoding/decoding) */ #define grpc_lb_v1_ClientStats_total_requests_tag 1 #define grpc_lb_v1_ClientStats_client_rpc_errors_tag 2 #define grpc_lb_v1_ClientStats_dropped_requests_tag 3 #define grpc_lb_v1_Duration_seconds_tag 1 #define grpc_lb_v1_Duration_nanos_tag 2 #define grpc_lb_v1_InitialLoadBalanceRequest_name_tag 1 #define grpc_lb_v1_Server_ip_address_tag 1 #define grpc_lb_v1_Server_port_tag 2 #define grpc_lb_v1_Server_load_balance_token_tag 3 #define grpc_lb_v1_Server_drop_request_tag 4 #define grpc_lb_v1_InitialLoadBalanceResponse_load_balancer_delegate_tag 1 #define grpc_lb_v1_InitialLoadBalanceResponse_client_stats_report_interval_tag 2 #define grpc_lb_v1_LoadBalanceRequest_initial_request_tag 1 #define grpc_lb_v1_LoadBalanceRequest_client_stats_tag 2 #define grpc_lb_v1_ServerList_servers_tag 1 #define grpc_lb_v1_ServerList_expiration_interval_tag 3 #define grpc_lb_v1_LoadBalanceResponse_initial_response_tag 1 #define grpc_lb_v1_LoadBalanceResponse_server_list_tag 2 /* Struct field encoding specification for nanopb */ extern const pb_field_t grpc_lb_v1_Duration_fields[3]; extern const pb_field_t grpc_lb_v1_LoadBalanceRequest_fields[3]; extern const pb_field_t grpc_lb_v1_InitialLoadBalanceRequest_fields[2]; extern const pb_field_t grpc_lb_v1_ClientStats_fields[4]; extern const pb_field_t grpc_lb_v1_LoadBalanceResponse_fields[3]; extern const pb_field_t grpc_lb_v1_InitialLoadBalanceResponse_fields[3]; extern const pb_field_t grpc_lb_v1_ServerList_fields[3]; extern const pb_field_t grpc_lb_v1_Server_fields[5]; /* Maximum encoded size of messages (where known) */ #define grpc_lb_v1_Duration_size 22 #define grpc_lb_v1_LoadBalanceRequest_size 169 #define grpc_lb_v1_InitialLoadBalanceRequest_size 131 #define grpc_lb_v1_ClientStats_size 33 #define grpc_lb_v1_LoadBalanceResponse_size (98 + grpc_lb_v1_ServerList_size) #define grpc_lb_v1_InitialLoadBalanceResponse_size 90 /* grpc_lb_v1_ServerList_size depends on runtime parameters */ #define grpc_lb_v1_Server_size 83 /* Message IDs (where set with "msgid" option) */ #ifdef PB_MSGID #define LOAD_BALANCER_MESSAGES \ #endif #ifdef __cplusplus } /* extern "C" */ #endif /* @@protoc_insertion_point(eof) */ #endif grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy/pick_first/000077500000000000000000000000001310511640000255055ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c000066400000000000000000000432521310511640000300140ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/transport/connectivity_state.h" typedef struct pending_pick { struct pending_pick *next; uint32_t initial_metadata_flags; grpc_connected_subchannel **target; grpc_closure *on_complete; } pending_pick; typedef struct { /** base policy: must be first */ grpc_lb_policy base; /** all our subchannels */ grpc_subchannel **subchannels; size_t num_subchannels; grpc_closure connectivity_changed; /** remaining members are protected by the combiner */ /** the selected channel */ grpc_connected_subchannel *selected; /** have we started picking? */ int started_picking; /** are we shut down? */ int shutdown; /** which subchannel are we watching? */ size_t checking_subchannel; /** what is the connectivity of that channel? */ grpc_connectivity_state checking_connectivity; /** list of picks that are waiting on connectivity */ pending_pick *pending_picks; /** our connectivity state tracker */ grpc_connectivity_state_tracker state_tracker; } pick_first_lb_policy; static void pf_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { pick_first_lb_policy *p = (pick_first_lb_policy *)pol; size_t i; GPR_ASSERT(p->pending_picks == NULL); for (i = 0; i < p->num_subchannels; i++) { GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[i], "pick_first"); } if (p->selected != NULL) { GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, p->selected, "picked_first"); } grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker); gpr_free(p->subchannels); gpr_free(p); } static void pf_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { pick_first_lb_policy *p = (pick_first_lb_policy *)pol; pending_pick *pp; p->shutdown = 1; pp = p->pending_picks; p->pending_picks = NULL; grpc_connectivity_state_set( exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel shutdown"), "shutdown"); /* cancel subscription */ if (p->selected != NULL) { grpc_connected_subchannel_notify_on_state_change( exec_ctx, p->selected, NULL, NULL, &p->connectivity_changed); } else if (p->num_subchannels > 0) { grpc_subchannel_notify_on_state_change( exec_ctx, p->subchannels[p->checking_subchannel], NULL, NULL, &p->connectivity_changed); } while (pp != NULL) { pending_pick *next = pp->next; *pp->target = NULL; grpc_closure_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE); gpr_free(pp); pp = next; } } static void pf_cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_connected_subchannel **target, grpc_error *error) { pick_first_lb_policy *p = (pick_first_lb_policy *)pol; pending_pick *pp; pp = p->pending_picks; p->pending_picks = NULL; while (pp != NULL) { pending_pick *next = pp->next; if (pp->target == target) { *target = NULL; grpc_closure_sched(exec_ctx, pp->on_complete, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Pick Cancelled", &error, 1)); gpr_free(pp); } else { pp->next = p->pending_picks; p->pending_picks = pp; } pp = next; } GRPC_ERROR_UNREF(error); } static void pf_cancel_picks_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, uint32_t initial_metadata_flags_mask, uint32_t initial_metadata_flags_eq, grpc_error *error) { pick_first_lb_policy *p = (pick_first_lb_policy *)pol; pending_pick *pp; pp = p->pending_picks; p->pending_picks = NULL; while (pp != NULL) { pending_pick *next = pp->next; if ((pp->initial_metadata_flags & initial_metadata_flags_mask) == initial_metadata_flags_eq) { grpc_closure_sched(exec_ctx, pp->on_complete, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Pick Cancelled", &error, 1)); gpr_free(pp); } else { pp->next = p->pending_picks; p->pending_picks = pp; } pp = next; } GRPC_ERROR_UNREF(error); } static void start_picking(grpc_exec_ctx *exec_ctx, pick_first_lb_policy *p) { p->started_picking = 1; p->checking_subchannel = 0; p->checking_connectivity = GRPC_CHANNEL_IDLE; GRPC_LB_POLICY_WEAK_REF(&p->base, "pick_first_connectivity"); grpc_subchannel_notify_on_state_change( exec_ctx, p->subchannels[p->checking_subchannel], p->base.interested_parties, &p->checking_connectivity, &p->connectivity_changed); } static void pf_exit_idle_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { pick_first_lb_policy *p = (pick_first_lb_policy *)pol; if (!p->started_picking) { start_picking(exec_ctx, p); } } static int pf_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, const grpc_lb_policy_pick_args *pick_args, grpc_connected_subchannel **target, void **user_data, grpc_closure *on_complete) { pick_first_lb_policy *p = (pick_first_lb_policy *)pol; pending_pick *pp; /* Check atomically for a selected channel */ if (p->selected != NULL) { *target = GRPC_CONNECTED_SUBCHANNEL_REF(p->selected, "picked"); return 1; } /* No subchannel selected yet, so try again */ if (!p->started_picking) { start_picking(exec_ctx, p); } pp = gpr_malloc(sizeof(*pp)); pp->next = p->pending_picks; pp->target = target; pp->initial_metadata_flags = pick_args->initial_metadata_flags; pp->on_complete = on_complete; p->pending_picks = pp; return 0; } static void destroy_subchannels_locked(grpc_exec_ctx *exec_ctx, pick_first_lb_policy *p) { size_t i; size_t num_subchannels = p->num_subchannels; grpc_subchannel **subchannels; subchannels = p->subchannels; p->num_subchannels = 0; p->subchannels = NULL; GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "destroy_subchannels"); for (i = 0; i < num_subchannels; i++) { GRPC_SUBCHANNEL_UNREF(exec_ctx, subchannels[i], "pick_first"); } gpr_free(subchannels); } static void pf_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { pick_first_lb_policy *p = arg; grpc_subchannel *selected_subchannel; pending_pick *pp; GRPC_ERROR_REF(error); if (p->shutdown) { GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity"); GRPC_ERROR_UNREF(error); return; } else if (p->selected != NULL) { if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) { /* if the selected channel goes bad, we're done */ p->checking_connectivity = GRPC_CHANNEL_SHUTDOWN; } grpc_connectivity_state_set(exec_ctx, &p->state_tracker, p->checking_connectivity, GRPC_ERROR_REF(error), "selected_changed"); if (p->checking_connectivity != GRPC_CHANNEL_SHUTDOWN) { grpc_connected_subchannel_notify_on_state_change( exec_ctx, p->selected, p->base.interested_parties, &p->checking_connectivity, &p->connectivity_changed); } else { GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity"); } } else { loop: switch (p->checking_connectivity) { case GRPC_CHANNEL_INIT: GPR_UNREACHABLE_CODE(return ); case GRPC_CHANNEL_READY: grpc_connectivity_state_set(exec_ctx, &p->state_tracker, GRPC_CHANNEL_READY, GRPC_ERROR_NONE, "connecting_ready"); selected_subchannel = p->subchannels[p->checking_subchannel]; p->selected = GRPC_CONNECTED_SUBCHANNEL_REF( grpc_subchannel_get_connected_subchannel(selected_subchannel), "picked_first"); /* drop the pick list: we are connected now */ GRPC_LB_POLICY_WEAK_REF(&p->base, "destroy_subchannels"); destroy_subchannels_locked(exec_ctx, p); /* update any calls that were waiting for a pick */ while ((pp = p->pending_picks)) { p->pending_picks = pp->next; *pp->target = GRPC_CONNECTED_SUBCHANNEL_REF(p->selected, "picked"); grpc_closure_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE); gpr_free(pp); } grpc_connected_subchannel_notify_on_state_change( exec_ctx, p->selected, p->base.interested_parties, &p->checking_connectivity, &p->connectivity_changed); break; case GRPC_CHANNEL_TRANSIENT_FAILURE: p->checking_subchannel = (p->checking_subchannel + 1) % p->num_subchannels; if (p->checking_subchannel == 0) { /* only trigger transient failure when we've tried all alternatives */ grpc_connectivity_state_set( exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error), "connecting_transient_failure"); } GRPC_ERROR_UNREF(error); p->checking_connectivity = grpc_subchannel_check_connectivity( p->subchannels[p->checking_subchannel], &error); if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) { grpc_subchannel_notify_on_state_change( exec_ctx, p->subchannels[p->checking_subchannel], p->base.interested_parties, &p->checking_connectivity, &p->connectivity_changed); } else { goto loop; } break; case GRPC_CHANNEL_CONNECTING: case GRPC_CHANNEL_IDLE: grpc_connectivity_state_set( exec_ctx, &p->state_tracker, GRPC_CHANNEL_CONNECTING, GRPC_ERROR_REF(error), "connecting_changed"); grpc_subchannel_notify_on_state_change( exec_ctx, p->subchannels[p->checking_subchannel], p->base.interested_parties, &p->checking_connectivity, &p->connectivity_changed); break; case GRPC_CHANNEL_SHUTDOWN: p->num_subchannels--; GPR_SWAP(grpc_subchannel *, p->subchannels[p->checking_subchannel], p->subchannels[p->num_subchannels]); GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[p->num_subchannels], "pick_first"); if (p->num_subchannels == 0) { grpc_connectivity_state_set( exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Pick first exhausted channels", &error, 1), "no_more_channels"); while ((pp = p->pending_picks)) { p->pending_picks = pp->next; *pp->target = NULL; grpc_closure_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE); gpr_free(pp); } GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity"); } else { grpc_connectivity_state_set( exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error), "subchannel_failed"); p->checking_subchannel %= p->num_subchannels; GRPC_ERROR_UNREF(error); p->checking_connectivity = grpc_subchannel_check_connectivity( p->subchannels[p->checking_subchannel], &error); goto loop; } } } GRPC_ERROR_UNREF(error); } static grpc_connectivity_state pf_check_connectivity_locked( grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_error **error) { pick_first_lb_policy *p = (pick_first_lb_policy *)pol; return grpc_connectivity_state_get(&p->state_tracker, error); } static void pf_notify_on_state_change_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_connectivity_state *current, grpc_closure *notify) { pick_first_lb_policy *p = (pick_first_lb_policy *)pol; grpc_connectivity_state_notify_on_state_change(exec_ctx, &p->state_tracker, current, notify); } static void pf_ping_one_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_closure *closure) { pick_first_lb_policy *p = (pick_first_lb_policy *)pol; if (p->selected) { grpc_connected_subchannel_ping(exec_ctx, p->selected, closure); } else { grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Not connected")); } } static const grpc_lb_policy_vtable pick_first_lb_policy_vtable = { pf_destroy, pf_shutdown_locked, pf_pick_locked, pf_cancel_pick_locked, pf_cancel_picks_locked, pf_ping_one_locked, pf_exit_idle_locked, pf_check_connectivity_locked, pf_notify_on_state_change_locked}; static void pick_first_factory_ref(grpc_lb_policy_factory *factory) {} static void pick_first_factory_unref(grpc_lb_policy_factory *factory) {} static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx, grpc_lb_policy_factory *factory, grpc_lb_policy_args *args) { GPR_ASSERT(args->client_channel_factory != NULL); /* Find the number of backend addresses. We ignore balancer * addresses, since we don't know how to handle them. */ const grpc_arg *arg = grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES); if (arg == NULL || arg->type != GRPC_ARG_POINTER) { return NULL; } grpc_lb_addresses *addresses = arg->value.pointer.p; size_t num_addrs = 0; for (size_t i = 0; i < addresses->num_addresses; i++) { if (!addresses->addresses[i].is_balancer) ++num_addrs; } if (num_addrs == 0) return NULL; pick_first_lb_policy *p = gpr_zalloc(sizeof(*p)); p->subchannels = gpr_zalloc(sizeof(grpc_subchannel *) * num_addrs); grpc_subchannel_args sc_args; size_t subchannel_idx = 0; for (size_t i = 0; i < addresses->num_addresses; i++) { /* Skip balancer addresses, since we only know how to handle backends. */ if (addresses->addresses[i].is_balancer) continue; if (addresses->addresses[i].user_data != NULL) { gpr_log(GPR_ERROR, "This LB policy doesn't support user data. It will be ignored"); } static const char *keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS}; memset(&sc_args, 0, sizeof(grpc_subchannel_args)); grpc_arg addr_arg = grpc_create_subchannel_address_arg(&addresses->addresses[i].address); grpc_channel_args *new_args = grpc_channel_args_copy_and_add_and_remove( args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &addr_arg, 1); gpr_free(addr_arg.value.string); sc_args.args = new_args; grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel( exec_ctx, args->client_channel_factory, &sc_args); grpc_channel_args_destroy(exec_ctx, new_args); if (subchannel != NULL) { p->subchannels[subchannel_idx++] = subchannel; } } if (subchannel_idx == 0) { gpr_free(p->subchannels); gpr_free(p); return NULL; } p->num_subchannels = subchannel_idx; grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable, args->combiner); grpc_closure_init(&p->connectivity_changed, pf_connectivity_changed_locked, p, grpc_combiner_scheduler(args->combiner, false)); return &p->base; } static const grpc_lb_policy_factory_vtable pick_first_factory_vtable = { pick_first_factory_ref, pick_first_factory_unref, create_pick_first, "pick_first"}; static grpc_lb_policy_factory pick_first_lb_policy_factory = { &pick_first_factory_vtable}; static grpc_lb_policy_factory *pick_first_lb_factory_create() { return &pick_first_lb_policy_factory; } /* Plugin registration */ void grpc_lb_policy_pick_first_init() { grpc_register_lb_policy(pick_first_lb_factory_create()); } void grpc_lb_policy_pick_first_shutdown() {} grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy/round_robin/000077500000000000000000000000001310511640000256705ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c000066400000000000000000000727461310511640000303740ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** Round Robin Policy. * * This policy keeps: * - A circular list of ready (connected) subchannels, the *readylist*. An empty * readylist consists solely of its root (dummy) node. * - A pointer to the last element picked from the readylist, the *lastpick*. * Initially set to point to the readylist's root. * * Behavior: * - When a subchannel connects, it's *prepended* to the readylist's root node. * Ie, if readylist = A <-> B <-> ROOT <-> C * ^ ^ * |____________________| * and subchannel D becomes connected, the addition of D to the readylist * results in readylist = A <-> B <-> D <-> ROOT <-> C * ^ ^ * |__________________________| * - When a subchannel disconnects, it's removed from the readylist. If the * subchannel being removed was the most recently picked, the *lastpick* * pointer moves to the removed node's previous element. Note that if the * readylist only had one element, this is still legal, as the lastpick would * point to the dummy root node, for an empty readylist. * - Upon picking, *lastpick* is updated to point to the returned (connected) * subchannel. Note that it's possible that the selected subchannel becomes * disconnected in the interim between the selection and the actual usage of * the subchannel by the caller. */ #include #include #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/static_metadata.h" typedef struct round_robin_lb_policy round_robin_lb_policy; int grpc_lb_round_robin_trace = 0; /** List of entities waiting for a pick. * * Once a pick is available, \a target is updated and \a on_complete called. */ typedef struct pending_pick { struct pending_pick *next; /* output argument where to store the pick()ed user_data. It'll be NULL if no * such data is present or there's an error (the definite test for errors is * \a target being NULL). */ void **user_data; /* bitmask passed to pick() and used for selective cancelling. See * grpc_lb_policy_cancel_picks() */ uint32_t initial_metadata_flags; /* output argument where to store the pick()ed connected subchannel, or NULL * upon error. */ grpc_connected_subchannel **target; /* to be invoked once the pick() has completed (regardless of success) */ grpc_closure *on_complete; } pending_pick; /** List of subchannels in a connectivity READY state */ typedef struct ready_list { grpc_subchannel *subchannel; /* references namesake entry in subchannel_data */ void *user_data; struct ready_list *next; struct ready_list *prev; } ready_list; typedef struct { /** index within policy->subchannels */ size_t index; /** backpointer to owning policy */ round_robin_lb_policy *policy; /** subchannel itself */ grpc_subchannel *subchannel; /** notification that connectivity has changed on subchannel */ grpc_closure connectivity_changed_closure; /** this subchannels current position in subchannel->ready_list */ ready_list *ready_list_node; /** last observed connectivity. Not updated by * \a grpc_subchannel_notify_on_state_change. Used to determine the previous * state while processing the new state in \a rr_connectivity_changed */ grpc_connectivity_state prev_connectivity_state; /** current connectivity state. Updated by \a * grpc_subchannel_notify_on_state_change */ grpc_connectivity_state curr_connectivity_state; /** the subchannel's target user data */ void *user_data; /** vtable to operate over \a user_data */ const grpc_lb_user_data_vtable *user_data_vtable; } subchannel_data; struct round_robin_lb_policy { /** base policy: must be first */ grpc_lb_policy base; /** total number of addresses received at creation time */ size_t num_addresses; /** all our subchannels */ size_t num_subchannels; subchannel_data **subchannels; /** how many subchannels are in TRANSIENT_FAILURE */ size_t num_transient_failures; /** how many subchannels are IDLE */ size_t num_idle; /** have we started picking? */ int started_picking; /** are we shutting down? */ int shutdown; /** List of picks that are waiting on connectivity */ pending_pick *pending_picks; /** our connectivity state tracker */ grpc_connectivity_state_tracker state_tracker; /** (Dummy) root of the doubly linked list containing READY subchannels */ ready_list ready_list; /** Last pick from the ready list. */ ready_list *ready_list_last_pick; }; /** Returns the next subchannel from the connected list or NULL if the list is * empty. * * Note that this function does *not* advance p->ready_list_last_pick. Use \a * advance_last_picked_locked() for that. */ static ready_list *peek_next_connected_locked(const round_robin_lb_policy *p) { ready_list *selected; selected = p->ready_list_last_pick->next; while (selected != NULL) { if (selected == &p->ready_list) { GPR_ASSERT(selected->subchannel == NULL); /* skip dummy root */ selected = selected->next; } else { GPR_ASSERT(selected->subchannel != NULL); return selected; } } return NULL; } /** Advance the \a ready_list picking head. */ static void advance_last_picked_locked(round_robin_lb_policy *p) { if (p->ready_list_last_pick->next != NULL) { /* non-empty list */ p->ready_list_last_pick = p->ready_list_last_pick->next; if (p->ready_list_last_pick == &p->ready_list) { /* skip dummy root */ p->ready_list_last_pick = p->ready_list_last_pick->next; } } else { /* should be an empty list */ GPR_ASSERT(p->ready_list_last_pick == &p->ready_list); } if (grpc_lb_round_robin_trace) { gpr_log(GPR_DEBUG, "[READYLIST, RR: %p] ADVANCED LAST PICK. NOW AT NODE %p (SC %p, " "CSC %p)", (void *)p, (void *)p->ready_list_last_pick, (void *)p->ready_list_last_pick->subchannel, (void *)grpc_subchannel_get_connected_subchannel( p->ready_list_last_pick->subchannel)); } } /** Prepends (relative to the root at p->ready_list) the connected subchannel \a * csc to the list of ready subchannels. */ static ready_list *add_connected_sc_locked(round_robin_lb_policy *p, subchannel_data *sd) { ready_list *new_elem = gpr_zalloc(sizeof(ready_list)); new_elem->subchannel = sd->subchannel; new_elem->user_data = sd->user_data; if (p->ready_list.prev == NULL) { /* first element */ new_elem->next = &p->ready_list; new_elem->prev = &p->ready_list; p->ready_list.next = new_elem; p->ready_list.prev = new_elem; } else { new_elem->next = &p->ready_list; new_elem->prev = p->ready_list.prev; p->ready_list.prev->next = new_elem; p->ready_list.prev = new_elem; } if (grpc_lb_round_robin_trace) { gpr_log(GPR_DEBUG, "[READYLIST] ADDING NODE %p (Conn. SC %p)", (void *)new_elem, (void *)sd->subchannel); } return new_elem; } /** Removes \a node from the list of connected subchannels */ static void remove_disconnected_sc_locked(round_robin_lb_policy *p, ready_list *node) { if (node == NULL) { return; } if (node == p->ready_list_last_pick) { p->ready_list_last_pick = p->ready_list_last_pick->prev; } /* removing last item */ if (node->next == &p->ready_list && node->prev == &p->ready_list) { GPR_ASSERT(p->ready_list.next == node); GPR_ASSERT(p->ready_list.prev == node); p->ready_list.next = NULL; p->ready_list.prev = NULL; } else { node->prev->next = node->next; node->next->prev = node->prev; } if (grpc_lb_round_robin_trace) { gpr_log(GPR_DEBUG, "[READYLIST] REMOVED NODE %p (SC %p)", (void *)node, (void *)node->subchannel); } node->next = NULL; node->prev = NULL; node->subchannel = NULL; gpr_free(node); } static bool is_ready_list_empty(round_robin_lb_policy *p) { return p->ready_list.prev == NULL; } static void rr_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { round_robin_lb_policy *p = (round_robin_lb_policy *)pol; ready_list *elem; if (grpc_lb_round_robin_trace) { gpr_log(GPR_DEBUG, "Destroying Round Robin policy at %p", (void *)pol); } for (size_t i = 0; i < p->num_subchannels; i++) { subchannel_data *sd = p->subchannels[i]; GRPC_SUBCHANNEL_UNREF(exec_ctx, sd->subchannel, "rr_destroy"); if (sd->user_data != NULL) { GPR_ASSERT(sd->user_data_vtable != NULL); sd->user_data_vtable->destroy(exec_ctx, sd->user_data); } gpr_free(sd); } grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker); gpr_free(p->subchannels); elem = p->ready_list.next; while (elem != NULL && elem != &p->ready_list) { ready_list *tmp; tmp = elem->next; elem->next = NULL; elem->prev = NULL; elem->subchannel = NULL; gpr_free(elem); elem = tmp; } gpr_free(p); } static void rr_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { round_robin_lb_policy *p = (round_robin_lb_policy *)pol; pending_pick *pp; size_t i; if (grpc_lb_round_robin_trace) { gpr_log(GPR_DEBUG, "Shutting down Round Robin policy at %p", (void *)pol); } p->shutdown = 1; while ((pp = p->pending_picks)) { p->pending_picks = pp->next; *pp->target = NULL; grpc_closure_sched( exec_ctx, pp->on_complete, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel Shutdown")); gpr_free(pp); } grpc_connectivity_state_set( exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel Shutdown"), "rr_shutdown"); for (i = 0; i < p->num_subchannels; i++) { subchannel_data *sd = p->subchannels[i]; grpc_subchannel_notify_on_state_change(exec_ctx, sd->subchannel, NULL, NULL, &sd->connectivity_changed_closure); } } static void rr_cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_connected_subchannel **target, grpc_error *error) { round_robin_lb_policy *p = (round_robin_lb_policy *)pol; pending_pick *pp; pp = p->pending_picks; p->pending_picks = NULL; while (pp != NULL) { pending_pick *next = pp->next; if (pp->target == target) { *target = NULL; grpc_closure_sched(exec_ctx, pp->on_complete, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Pick cancelled", &error, 1)); gpr_free(pp); } else { pp->next = p->pending_picks; p->pending_picks = pp; } pp = next; } GRPC_ERROR_UNREF(error); } static void rr_cancel_picks_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, uint32_t initial_metadata_flags_mask, uint32_t initial_metadata_flags_eq, grpc_error *error) { round_robin_lb_policy *p = (round_robin_lb_policy *)pol; pending_pick *pp; pp = p->pending_picks; p->pending_picks = NULL; while (pp != NULL) { pending_pick *next = pp->next; if ((pp->initial_metadata_flags & initial_metadata_flags_mask) == initial_metadata_flags_eq) { *pp->target = NULL; grpc_closure_sched(exec_ctx, pp->on_complete, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Pick cancelled", &error, 1)); gpr_free(pp); } else { pp->next = p->pending_picks; p->pending_picks = pp; } pp = next; } GRPC_ERROR_UNREF(error); } static void start_picking_locked(grpc_exec_ctx *exec_ctx, round_robin_lb_policy *p) { size_t i; p->started_picking = 1; for (i = 0; i < p->num_subchannels; i++) { subchannel_data *sd = p->subchannels[i]; /* use some sentinel value outside of the range of grpc_connectivity_state * to signal an undefined previous state. We won't be referring to this * value again and it'll be overwritten after the first call to * rr_connectivity_changed */ sd->prev_connectivity_state = GRPC_CHANNEL_INIT; sd->curr_connectivity_state = GRPC_CHANNEL_IDLE; GRPC_LB_POLICY_WEAK_REF(&p->base, "rr_connectivity"); grpc_subchannel_notify_on_state_change( exec_ctx, sd->subchannel, p->base.interested_parties, &sd->curr_connectivity_state, &sd->connectivity_changed_closure); } } static void rr_exit_idle_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { round_robin_lb_policy *p = (round_robin_lb_policy *)pol; if (!p->started_picking) { start_picking_locked(exec_ctx, p); } } static int rr_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, const grpc_lb_policy_pick_args *pick_args, grpc_connected_subchannel **target, void **user_data, grpc_closure *on_complete) { round_robin_lb_policy *p = (round_robin_lb_policy *)pol; pending_pick *pp; ready_list *selected; if (grpc_lb_round_robin_trace) { gpr_log(GPR_INFO, "Round Robin %p trying to pick", (void *)pol); } if ((selected = peek_next_connected_locked(p))) { /* readily available, report right away */ *target = GRPC_CONNECTED_SUBCHANNEL_REF( grpc_subchannel_get_connected_subchannel(selected->subchannel), "rr_picked"); if (user_data != NULL) { *user_data = selected->user_data; } if (grpc_lb_round_robin_trace) { gpr_log(GPR_DEBUG, "[RR PICK] TARGET <-- CONNECTED SUBCHANNEL %p (NODE %p)", (void *)*target, (void *)selected); } /* only advance the last picked pointer if the selection was used */ advance_last_picked_locked(p); return 1; } else { /* no pick currently available. Save for later in list of pending picks */ if (!p->started_picking) { start_picking_locked(exec_ctx, p); } pp = gpr_malloc(sizeof(*pp)); pp->next = p->pending_picks; pp->target = target; pp->on_complete = on_complete; pp->initial_metadata_flags = pick_args->initial_metadata_flags; pp->user_data = user_data; p->pending_picks = pp; return 0; } } static void update_state_counters(subchannel_data *sd) { round_robin_lb_policy *p = sd->policy; /* update p->num_transient_failures (resp. p->num_idle): if the previous * state was TRANSIENT_FAILURE (resp. IDLE), decrement * p->num_transient_failures (resp. p->num_idle). */ if (sd->prev_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) { GPR_ASSERT(p->num_transient_failures > 0); --p->num_transient_failures; } else if (sd->prev_connectivity_state == GRPC_CHANNEL_IDLE) { GPR_ASSERT(p->num_idle > 0); --p->num_idle; } } /* sd is the subchannel_data associted with the updated subchannel. * shutdown_error will only be used upon policy transition to TRANSIENT_FAILURE * or SHUTDOWN */ static grpc_connectivity_state update_lb_connectivity_status( grpc_exec_ctx *exec_ctx, subchannel_data *sd, grpc_error *error) { /* In priority order. The first rule to match terminates the search (ie, if we * are on rule n, all previous rules were unfulfilled). * * 1) RULE: ANY subchannel is READY => policy is READY. * CHECK: At least one subchannel is ready iff p->ready_list is NOT empty. * * 2) RULE: ANY subchannel is CONNECTING => policy is CONNECTING. * CHECK: sd->curr_connectivity_state == CONNECTING. * * 3) RULE: ALL subchannels are SHUTDOWN => policy is SHUTDOWN. * CHECK: p->num_subchannels = 0. * * 4) RULE: ALL subchannels are TRANSIENT_FAILURE => policy is * TRANSIENT_FAILURE. * CHECK: p->num_transient_failures == p->num_subchannels. * * 5) RULE: ALL subchannels are IDLE => policy is IDLE. * CHECK: p->num_idle == p->num_subchannels. */ round_robin_lb_policy *p = sd->policy; if (!is_ready_list_empty(p)) { /* 1) READY */ grpc_connectivity_state_set(exec_ctx, &p->state_tracker, GRPC_CHANNEL_READY, GRPC_ERROR_NONE, "rr_ready"); return GRPC_CHANNEL_READY; } else if (sd->curr_connectivity_state == GRPC_CHANNEL_CONNECTING) { /* 2) CONNECTING */ grpc_connectivity_state_set(exec_ctx, &p->state_tracker, GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE, "rr_connecting"); return GRPC_CHANNEL_CONNECTING; } else if (p->num_subchannels == 0) { /* 3) SHUTDOWN */ grpc_connectivity_state_set(exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_REF(error), "rr_shutdown"); return GRPC_CHANNEL_SHUTDOWN; } else if (p->num_transient_failures == p->num_subchannels) { /* 4) TRANSIENT_FAILURE */ grpc_connectivity_state_set(exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error), "rr_transient_failure"); return GRPC_CHANNEL_TRANSIENT_FAILURE; } else if (p->num_idle == p->num_subchannels) { /* 5) IDLE */ grpc_connectivity_state_set(exec_ctx, &p->state_tracker, GRPC_CHANNEL_IDLE, GRPC_ERROR_NONE, "rr_idle"); return GRPC_CHANNEL_IDLE; } /* no change */ return sd->curr_connectivity_state; } static void rr_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { subchannel_data *sd = arg; round_robin_lb_policy *p = sd->policy; pending_pick *pp; GRPC_ERROR_REF(error); if (p->shutdown) { GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "rr_connectivity"); GRPC_ERROR_UNREF(error); return; } switch (sd->curr_connectivity_state) { case GRPC_CHANNEL_INIT: GPR_UNREACHABLE_CODE(return ); case GRPC_CHANNEL_READY: /* add the newly connected subchannel to the list of connected ones. * Note that it goes to the "end of the line". */ sd->ready_list_node = add_connected_sc_locked(p, sd); /* at this point we know there's at least one suitable subchannel. Go * ahead and pick one and notify the pending suitors in * p->pending_picks. This preemtively replicates rr_pick()'s actions. */ ready_list *selected = peek_next_connected_locked(p); GPR_ASSERT(selected != NULL); if (p->pending_picks != NULL) { /* if the selected subchannel is going to be used for the pending * picks, update the last picked pointer */ advance_last_picked_locked(p); } while ((pp = p->pending_picks)) { p->pending_picks = pp->next; *pp->target = GRPC_CONNECTED_SUBCHANNEL_REF( grpc_subchannel_get_connected_subchannel(selected->subchannel), "rr_picked"); if (pp->user_data != NULL) { *pp->user_data = selected->user_data; } if (grpc_lb_round_robin_trace) { gpr_log(GPR_DEBUG, "[RR CONN CHANGED] TARGET <-- SUBCHANNEL %p (NODE %p)", (void *)selected->subchannel, (void *)selected); } grpc_closure_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE); gpr_free(pp); } update_lb_connectivity_status(exec_ctx, sd, error); sd->prev_connectivity_state = sd->curr_connectivity_state; /* renew notification: reuses the "rr_connectivity" weak ref */ grpc_subchannel_notify_on_state_change( exec_ctx, sd->subchannel, p->base.interested_parties, &sd->curr_connectivity_state, &sd->connectivity_changed_closure); break; case GRPC_CHANNEL_IDLE: ++p->num_idle; /* fallthrough */ case GRPC_CHANNEL_CONNECTING: update_state_counters(sd); update_lb_connectivity_status(exec_ctx, sd, error); sd->prev_connectivity_state = sd->curr_connectivity_state; /* renew notification: reuses the "rr_connectivity" weak ref */ grpc_subchannel_notify_on_state_change( exec_ctx, sd->subchannel, p->base.interested_parties, &sd->curr_connectivity_state, &sd->connectivity_changed_closure); break; case GRPC_CHANNEL_TRANSIENT_FAILURE: ++p->num_transient_failures; /* remove from ready list if still present */ if (sd->ready_list_node != NULL) { remove_disconnected_sc_locked(p, sd->ready_list_node); sd->ready_list_node = NULL; } update_lb_connectivity_status(exec_ctx, sd, error); sd->prev_connectivity_state = sd->curr_connectivity_state; /* renew notification: reuses the "rr_connectivity" weak ref */ grpc_subchannel_notify_on_state_change( exec_ctx, sd->subchannel, p->base.interested_parties, &sd->curr_connectivity_state, &sd->connectivity_changed_closure); break; case GRPC_CHANNEL_SHUTDOWN: update_state_counters(sd); if (sd->ready_list_node != NULL) { remove_disconnected_sc_locked(p, sd->ready_list_node); sd->ready_list_node = NULL; } --p->num_subchannels; GPR_SWAP(subchannel_data *, p->subchannels[sd->index], p->subchannels[p->num_subchannels]); GRPC_SUBCHANNEL_UNREF(exec_ctx, sd->subchannel, "rr_subchannel_shutdown"); p->subchannels[sd->index]->index = sd->index; if (update_lb_connectivity_status(exec_ctx, sd, error) == GRPC_CHANNEL_SHUTDOWN) { /* the policy is shutting down. Flush all the pending picks... */ while ((pp = p->pending_picks)) { p->pending_picks = pp->next; *pp->target = NULL; grpc_closure_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE); gpr_free(pp); } } gpr_free(sd); /* unref the "rr_connectivity" weak ref from start_picking */ GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "rr_connectivity"); break; } GRPC_ERROR_UNREF(error); } static grpc_connectivity_state rr_check_connectivity_locked( grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_error **error) { round_robin_lb_policy *p = (round_robin_lb_policy *)pol; return grpc_connectivity_state_get(&p->state_tracker, error); } static void rr_notify_on_state_change_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_connectivity_state *current, grpc_closure *notify) { round_robin_lb_policy *p = (round_robin_lb_policy *)pol; grpc_connectivity_state_notify_on_state_change(exec_ctx, &p->state_tracker, current, notify); } static void rr_ping_one_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_closure *closure) { round_robin_lb_policy *p = (round_robin_lb_policy *)pol; ready_list *selected; grpc_connected_subchannel *target; if ((selected = peek_next_connected_locked(p))) { target = GRPC_CONNECTED_SUBCHANNEL_REF( grpc_subchannel_get_connected_subchannel(selected->subchannel), "rr_picked"); grpc_connected_subchannel_ping(exec_ctx, target, closure); GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, target, "rr_picked"); } else { grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Round Robin not connected")); } } static const grpc_lb_policy_vtable round_robin_lb_policy_vtable = { rr_destroy, rr_shutdown_locked, rr_pick_locked, rr_cancel_pick_locked, rr_cancel_picks_locked, rr_ping_one_locked, rr_exit_idle_locked, rr_check_connectivity_locked, rr_notify_on_state_change_locked}; static void round_robin_factory_ref(grpc_lb_policy_factory *factory) {} static void round_robin_factory_unref(grpc_lb_policy_factory *factory) {} static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx, grpc_lb_policy_factory *factory, grpc_lb_policy_args *args) { GPR_ASSERT(args->client_channel_factory != NULL); /* Find the number of backend addresses. We ignore balancer * addresses, since we don't know how to handle them. */ const grpc_arg *arg = grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES); if (arg == NULL || arg->type != GRPC_ARG_POINTER) { return NULL; } grpc_lb_addresses *addresses = arg->value.pointer.p; size_t num_addrs = 0; for (size_t i = 0; i < addresses->num_addresses; i++) { if (!addresses->addresses[i].is_balancer) ++num_addrs; } if (num_addrs == 0) return NULL; round_robin_lb_policy *p = gpr_zalloc(sizeof(*p)); p->num_addresses = num_addrs; p->subchannels = gpr_zalloc(sizeof(*p->subchannels) * num_addrs); grpc_subchannel_args sc_args; size_t subchannel_idx = 0; for (size_t i = 0; i < addresses->num_addresses; i++) { /* Skip balancer addresses, since we only know how to handle backends. */ if (addresses->addresses[i].is_balancer) continue; static const char *keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS}; memset(&sc_args, 0, sizeof(grpc_subchannel_args)); grpc_arg addr_arg = grpc_create_subchannel_address_arg(&addresses->addresses[i].address); grpc_channel_args *new_args = grpc_channel_args_copy_and_add_and_remove( args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &addr_arg, 1); gpr_free(addr_arg.value.string); sc_args.args = new_args; grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel( exec_ctx, args->client_channel_factory, &sc_args); if (grpc_lb_round_robin_trace) { char *address_uri = grpc_sockaddr_to_uri(&addresses->addresses[i].address); gpr_log(GPR_DEBUG, "Created subchannel %p for address uri %s", (void *)subchannel, address_uri); gpr_free(address_uri); } grpc_channel_args_destroy(exec_ctx, new_args); if (subchannel != NULL) { subchannel_data *sd = gpr_zalloc(sizeof(*sd)); p->subchannels[subchannel_idx] = sd; sd->policy = p; sd->index = subchannel_idx; sd->subchannel = subchannel; sd->user_data_vtable = addresses->user_data_vtable; if (sd->user_data_vtable != NULL) { sd->user_data = sd->user_data_vtable->copy(addresses->addresses[i].user_data); } ++subchannel_idx; grpc_closure_init(&sd->connectivity_changed_closure, rr_connectivity_changed_locked, sd, grpc_combiner_scheduler(args->combiner, false)); } } if (subchannel_idx == 0) { /* couldn't create any subchannel. Bail out */ gpr_free(p->subchannels); gpr_free(p); return NULL; } p->num_subchannels = subchannel_idx; /* The (dummy node) root of the ready list */ p->ready_list.subchannel = NULL; p->ready_list.prev = NULL; p->ready_list.next = NULL; p->ready_list_last_pick = &p->ready_list; grpc_lb_policy_init(&p->base, &round_robin_lb_policy_vtable, args->combiner); grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE, "round_robin"); if (grpc_lb_round_robin_trace) { gpr_log(GPR_DEBUG, "Created RR policy at %p with %lu subchannels", (void *)p, (unsigned long)p->num_subchannels); } return &p->base; } static const grpc_lb_policy_factory_vtable round_robin_factory_vtable = { round_robin_factory_ref, round_robin_factory_unref, round_robin_create, "round_robin"}; static grpc_lb_policy_factory round_robin_lb_policy_factory = { &round_robin_factory_vtable}; static grpc_lb_policy_factory *round_robin_lb_factory_create() { return &round_robin_lb_policy_factory; } /* Plugin registration */ void grpc_lb_policy_round_robin_init() { grpc_register_lb_policy(round_robin_lb_factory_create()); grpc_register_tracer("round_robin", &grpc_lb_round_robin_trace); } void grpc_lb_policy_round_robin_shutdown() {} grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy_factory.c000066400000000000000000000154511310511640000252510ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include "src/core/ext/filters/client_channel/lb_policy_factory.h" grpc_lb_addresses* grpc_lb_addresses_create( size_t num_addresses, const grpc_lb_user_data_vtable* user_data_vtable) { grpc_lb_addresses* addresses = gpr_malloc(sizeof(grpc_lb_addresses)); addresses->num_addresses = num_addresses; addresses->user_data_vtable = user_data_vtable; const size_t addresses_size = sizeof(grpc_lb_address) * num_addresses; addresses->addresses = gpr_malloc(addresses_size); memset(addresses->addresses, 0, addresses_size); return addresses; } grpc_lb_addresses* grpc_lb_addresses_copy(const grpc_lb_addresses* addresses) { grpc_lb_addresses* new_addresses = grpc_lb_addresses_create( addresses->num_addresses, addresses->user_data_vtable); memcpy(new_addresses->addresses, addresses->addresses, sizeof(grpc_lb_address) * addresses->num_addresses); for (size_t i = 0; i < addresses->num_addresses; ++i) { if (new_addresses->addresses[i].balancer_name != NULL) { new_addresses->addresses[i].balancer_name = gpr_strdup(new_addresses->addresses[i].balancer_name); } if (new_addresses->addresses[i].user_data != NULL) { new_addresses->addresses[i].user_data = addresses->user_data_vtable->copy( new_addresses->addresses[i].user_data); } } return new_addresses; } void grpc_lb_addresses_set_address(grpc_lb_addresses* addresses, size_t index, void* address, size_t address_len, bool is_balancer, char* balancer_name, void* user_data) { GPR_ASSERT(index < addresses->num_addresses); if (user_data != NULL) GPR_ASSERT(addresses->user_data_vtable != NULL); grpc_lb_address* target = &addresses->addresses[index]; memcpy(target->address.addr, address, address_len); target->address.len = address_len; target->is_balancer = is_balancer; target->balancer_name = balancer_name; target->user_data = user_data; } int grpc_lb_addresses_cmp(const grpc_lb_addresses* addresses1, const grpc_lb_addresses* addresses2) { if (addresses1->num_addresses > addresses2->num_addresses) return 1; if (addresses1->num_addresses < addresses2->num_addresses) return -1; if (addresses1->user_data_vtable > addresses2->user_data_vtable) return 1; if (addresses1->user_data_vtable < addresses2->user_data_vtable) return -1; for (size_t i = 0; i < addresses1->num_addresses; ++i) { const grpc_lb_address* target1 = &addresses1->addresses[i]; const grpc_lb_address* target2 = &addresses2->addresses[i]; if (target1->address.len > target2->address.len) return 1; if (target1->address.len < target2->address.len) return -1; int retval = memcmp(target1->address.addr, target2->address.addr, target1->address.len); if (retval != 0) return retval; if (target1->is_balancer > target2->is_balancer) return 1; if (target1->is_balancer < target2->is_balancer) return -1; const char* balancer_name1 = target1->balancer_name != NULL ? target1->balancer_name : ""; const char* balancer_name2 = target2->balancer_name != NULL ? target2->balancer_name : ""; retval = strcmp(balancer_name1, balancer_name2); if (retval != 0) return retval; if (addresses1->user_data_vtable != NULL) { retval = addresses1->user_data_vtable->cmp(target1->user_data, target2->user_data); if (retval != 0) return retval; } } return 0; } void grpc_lb_addresses_destroy(grpc_exec_ctx* exec_ctx, grpc_lb_addresses* addresses) { for (size_t i = 0; i < addresses->num_addresses; ++i) { gpr_free(addresses->addresses[i].balancer_name); if (addresses->addresses[i].user_data != NULL) { addresses->user_data_vtable->destroy(exec_ctx, addresses->addresses[i].user_data); } } gpr_free(addresses->addresses); gpr_free(addresses); } static void* lb_addresses_copy(void* addresses) { return grpc_lb_addresses_copy(addresses); } static void lb_addresses_destroy(grpc_exec_ctx* exec_ctx, void* addresses) { grpc_lb_addresses_destroy(exec_ctx, addresses); } static int lb_addresses_cmp(void* addresses1, void* addresses2) { return grpc_lb_addresses_cmp(addresses1, addresses2); } static const grpc_arg_pointer_vtable lb_addresses_arg_vtable = { lb_addresses_copy, lb_addresses_destroy, lb_addresses_cmp}; grpc_arg grpc_lb_addresses_create_channel_arg( const grpc_lb_addresses* addresses) { grpc_arg arg; arg.type = GRPC_ARG_POINTER; arg.key = GRPC_ARG_LB_ADDRESSES; arg.value.pointer.p = (void*)addresses; arg.value.pointer.vtable = &lb_addresses_arg_vtable; return arg; } void grpc_lb_policy_factory_ref(grpc_lb_policy_factory* factory) { factory->vtable->ref(factory); } void grpc_lb_policy_factory_unref(grpc_lb_policy_factory* factory) { factory->vtable->unref(factory); } grpc_lb_policy* grpc_lb_policy_factory_create_lb_policy( grpc_exec_ctx* exec_ctx, grpc_lb_policy_factory* factory, grpc_lb_policy_args* args) { if (factory == NULL) return NULL; return factory->vtable->create_lb_policy(exec_ctx, factory, args); } grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy_factory.h000066400000000000000000000126431310511640000252560ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_FACTORY_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_FACTORY_H #include "src/core/ext/filters/client_channel/client_channel_factory.h" #include "src/core/ext/filters/client_channel/lb_policy.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/resolve_address.h" // Channel arg key for grpc_lb_addresses. #define GRPC_ARG_LB_ADDRESSES "grpc.lb_addresses" typedef struct grpc_lb_policy_factory grpc_lb_policy_factory; typedef struct grpc_lb_policy_factory_vtable grpc_lb_policy_factory_vtable; struct grpc_lb_policy_factory { const grpc_lb_policy_factory_vtable *vtable; }; /** A resolved address alongside any LB related information associated with it. * \a user_data, if not NULL, contains opaque data meant to be consumed by the * gRPC LB policy. Note that no all LB policies support \a user_data as input. * Those who don't will simply ignore it and will correspondingly return NULL in * their namesake pick() output argument. */ typedef struct grpc_lb_address { grpc_resolved_address address; bool is_balancer; char *balancer_name; /* For secure naming. */ void *user_data; } grpc_lb_address; typedef struct grpc_lb_user_data_vtable { void *(*copy)(void *); void (*destroy)(grpc_exec_ctx *exec_ctx, void *); int (*cmp)(void *, void *); } grpc_lb_user_data_vtable; typedef struct grpc_lb_addresses { size_t num_addresses; grpc_lb_address *addresses; const grpc_lb_user_data_vtable *user_data_vtable; } grpc_lb_addresses; /** Returns a grpc_addresses struct with enough space for \a num_addresses addresses. The \a user_data_vtable argument may be NULL if no user data will be added. */ grpc_lb_addresses *grpc_lb_addresses_create( size_t num_addresses, const grpc_lb_user_data_vtable *user_data_vtable); /** Creates a copy of \a addresses. */ grpc_lb_addresses *grpc_lb_addresses_copy(const grpc_lb_addresses *addresses); /** Sets the value of the address at index \a index of \a addresses. * \a address is a socket address of length \a address_len. * Takes ownership of \a balancer_name. */ void grpc_lb_addresses_set_address(grpc_lb_addresses *addresses, size_t index, void *address, size_t address_len, bool is_balancer, char *balancer_name, void *user_data); /** Compares \a addresses1 and \a addresses2. */ int grpc_lb_addresses_cmp(const grpc_lb_addresses *addresses1, const grpc_lb_addresses *addresses2); /** Destroys \a addresses. */ void grpc_lb_addresses_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_addresses *addresses); /** Returns a channel arg containing \a addresses. */ grpc_arg grpc_lb_addresses_create_channel_arg( const grpc_lb_addresses *addresses); /** Arguments passed to LB policies. */ typedef struct grpc_lb_policy_args { grpc_client_channel_factory *client_channel_factory; grpc_channel_args *args; grpc_combiner *combiner; } grpc_lb_policy_args; struct grpc_lb_policy_factory_vtable { void (*ref)(grpc_lb_policy_factory *factory); void (*unref)(grpc_lb_policy_factory *factory); /** Implementation of grpc_lb_policy_factory_create_lb_policy */ grpc_lb_policy *(*create_lb_policy)(grpc_exec_ctx *exec_ctx, grpc_lb_policy_factory *factory, grpc_lb_policy_args *args); /** Name for the LB policy this factory implements */ const char *name; }; void grpc_lb_policy_factory_ref(grpc_lb_policy_factory *factory); void grpc_lb_policy_factory_unref(grpc_lb_policy_factory *factory); /** Create a lb_policy instance. */ grpc_lb_policy *grpc_lb_policy_factory_create_lb_policy( grpc_exec_ctx *exec_ctx, grpc_lb_policy_factory *factory, grpc_lb_policy_args *args); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_FACTORY_H */ grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy_registry.c000066400000000000000000000061131310511640000254450ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include #include "src/core/lib/support/string.h" #define MAX_POLICIES 10 static grpc_lb_policy_factory *g_all_of_the_lb_policies[MAX_POLICIES]; static int g_number_of_lb_policies = 0; void grpc_lb_policy_registry_init(void) { g_number_of_lb_policies = 0; } void grpc_lb_policy_registry_shutdown(void) { int i; for (i = 0; i < g_number_of_lb_policies; i++) { grpc_lb_policy_factory_unref(g_all_of_the_lb_policies[i]); } } void grpc_register_lb_policy(grpc_lb_policy_factory *factory) { int i; for (i = 0; i < g_number_of_lb_policies; i++) { GPR_ASSERT(0 != gpr_stricmp(factory->vtable->name, g_all_of_the_lb_policies[i]->vtable->name)); } GPR_ASSERT(g_number_of_lb_policies != MAX_POLICIES); grpc_lb_policy_factory_ref(factory); g_all_of_the_lb_policies[g_number_of_lb_policies++] = factory; } static grpc_lb_policy_factory *lookup_factory(const char *name) { int i; if (name == NULL) return NULL; for (i = 0; i < g_number_of_lb_policies; i++) { if (0 == gpr_stricmp(name, g_all_of_the_lb_policies[i]->vtable->name)) { return g_all_of_the_lb_policies[i]; } } return NULL; } grpc_lb_policy *grpc_lb_policy_create(grpc_exec_ctx *exec_ctx, const char *name, grpc_lb_policy_args *args) { grpc_lb_policy_factory *factory = lookup_factory(name); grpc_lb_policy *lb_policy = grpc_lb_policy_factory_create_lb_policy(exec_ctx, factory, args); return lb_policy; } grpc-1.3.2/src/core/ext/filters/client_channel/lb_policy_registry.h000066400000000000000000000046771310511640000254670ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_REGISTRY_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_REGISTRY_H #include "src/core/ext/filters/client_channel/lb_policy_factory.h" #include "src/core/lib/iomgr/exec_ctx.h" /** Initialize the registry and set \a default_factory as the factory to be * returned when no name is provided in a lookup */ void grpc_lb_policy_registry_init(void); void grpc_lb_policy_registry_shutdown(void); /** Register a LB policy factory. */ void grpc_register_lb_policy(grpc_lb_policy_factory *factory); /** Create a \a grpc_lb_policy instance. * * If \a name is NULL, the default factory from \a grpc_lb_policy_registry_init * will be returned. */ grpc_lb_policy *grpc_lb_policy_create(grpc_exec_ctx *exec_ctx, const char *name, grpc_lb_policy_args *args); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_REGISTRY_H */ grpc-1.3.2/src/core/ext/filters/client_channel/parse_address.c000066400000000000000000000127151310511640000243650ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/filters/client_channel/parse_address.h" #include "src/core/lib/iomgr/sockaddr.h" #include #include #ifdef GRPC_HAVE_UNIX_SOCKET #include #endif #include #include #include #include #include "src/core/lib/support/string.h" #ifdef GRPC_HAVE_UNIX_SOCKET int parse_unix(grpc_uri *uri, grpc_resolved_address *resolved_addr) { struct sockaddr_un *un = (struct sockaddr_un *)resolved_addr->addr; const size_t maxlen = sizeof(un->sun_path); const size_t path_len = strnlen(uri->path, maxlen); if (path_len == maxlen) return 0; un->sun_family = AF_UNIX; strcpy(un->sun_path, uri->path); resolved_addr->len = sizeof(*un); return 1; } #else /* GRPC_HAVE_UNIX_SOCKET */ int parse_unix(grpc_uri *uri, grpc_resolved_address *resolved_addr) { abort(); } #endif /* GRPC_HAVE_UNIX_SOCKET */ int parse_ipv4(grpc_uri *uri, grpc_resolved_address *resolved_addr) { const char *host_port = uri->path; char *host; char *port; int port_num; int result = 0; struct sockaddr_in *in = (struct sockaddr_in *)resolved_addr->addr; if (*host_port == '/') ++host_port; if (!gpr_split_host_port(host_port, &host, &port)) { return 0; } memset(resolved_addr, 0, sizeof(grpc_resolved_address)); resolved_addr->len = sizeof(struct sockaddr_in); in->sin_family = AF_INET; if (inet_pton(AF_INET, host, &in->sin_addr) == 0) { gpr_log(GPR_ERROR, "invalid ipv4 address: '%s'", host); goto done; } if (port != NULL) { if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 || port_num > 65535) { gpr_log(GPR_ERROR, "invalid ipv4 port: '%s'", port); goto done; } in->sin_port = htons((uint16_t)port_num); } else { gpr_log(GPR_ERROR, "no port given for ipv4 scheme"); goto done; } result = 1; done: gpr_free(host); gpr_free(port); return result; } int parse_ipv6(grpc_uri *uri, grpc_resolved_address *resolved_addr) { const char *host_port = uri->path; char *host; char *port; int port_num; int result = 0; struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)resolved_addr->addr; if (*host_port == '/') ++host_port; if (!gpr_split_host_port(host_port, &host, &port)) { return 0; } memset(in6, 0, sizeof(*in6)); resolved_addr->len = sizeof(*in6); in6->sin6_family = AF_INET6; /* Handle the RFC6874 syntax for IPv6 zone identifiers. */ char *host_end = (char *)gpr_memrchr(host, '%', strlen(host)); if (host_end != NULL) { GPR_ASSERT(host_end >= host); char host_without_scope[INET6_ADDRSTRLEN]; size_t host_without_scope_len = (size_t)(host_end - host); uint32_t sin6_scope_id = 0; strncpy(host_without_scope, host, host_without_scope_len); host_without_scope[host_without_scope_len] = '\0'; if (inet_pton(AF_INET6, host_without_scope, &in6->sin6_addr) == 0) { gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host_without_scope); goto done; } if (gpr_parse_bytes_to_uint32(host_end + 1, strlen(host) - host_without_scope_len - 1, &sin6_scope_id) == 0) { gpr_log(GPR_ERROR, "invalid ipv6 scope id: '%s'", host_end + 1); goto done; } // Handle "sin6_scope_id" being type "u_long". See grpc issue ##10027. in6->sin6_scope_id = sin6_scope_id; } else { if (inet_pton(AF_INET6, host, &in6->sin6_addr) == 0) { gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host); goto done; } } if (port != NULL) { if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 || port_num > 65535) { gpr_log(GPR_ERROR, "invalid ipv6 port: '%s'", port); goto done; } in6->sin6_port = htons((uint16_t)port_num); } else { gpr_log(GPR_ERROR, "no port given for ipv6 scheme"); goto done; } result = 1; done: gpr_free(host); gpr_free(port); return result; } grpc-1.3.2/src/core/ext/filters/client_channel/parse_address.h000066400000000000000000000046731310511640000243760ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PARSE_ADDRESS_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PARSE_ADDRESS_H #include #include "src/core/ext/filters/client_channel/uri_parser.h" #include "src/core/lib/iomgr/resolve_address.h" /** Populate \a addr and \a len from \a uri, whose path is expected to contain a * unix socket path. Returns true upon success. */ int parse_unix(grpc_uri *uri, grpc_resolved_address *resolved_addr); /** Populate /a addr and \a len from \a uri, whose path is expected to contain a * host:port pair. Returns true upon success. */ int parse_ipv4(grpc_uri *uri, grpc_resolved_address *resolved_addr); /** Populate /a addr and \a len from \a uri, whose path is expected to contain a * host:port pair. Returns true upon success. */ int parse_ipv6(grpc_uri *uri, grpc_resolved_address *resolved_addr); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PARSE_ADDRESS_H */ grpc-1.3.2/src/core/ext/filters/client_channel/proxy_mapper.c000066400000000000000000000055351310511640000242750ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/filters/client_channel/proxy_mapper.h" void grpc_proxy_mapper_init(const grpc_proxy_mapper_vtable* vtable, grpc_proxy_mapper* mapper) { mapper->vtable = vtable; } bool grpc_proxy_mapper_map_name(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper, const char* server_uri, const grpc_channel_args* args, char** name_to_resolve, grpc_channel_args** new_args) { return mapper->vtable->map_name(exec_ctx, mapper, server_uri, args, name_to_resolve, new_args); } bool grpc_proxy_mapper_map_address(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper, const grpc_resolved_address* address, const grpc_channel_args* args, grpc_resolved_address** new_address, grpc_channel_args** new_args) { return mapper->vtable->map_address(exec_ctx, mapper, address, args, new_address, new_args); } void grpc_proxy_mapper_destroy(grpc_proxy_mapper* mapper) { mapper->vtable->destroy(mapper); } grpc-1.3.2/src/core/ext/filters/client_channel/proxy_mapper.h000066400000000000000000000076051310511640000243020ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PROXY_MAPPER_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PROXY_MAPPER_H #include #include #include "src/core/lib/iomgr/resolve_address.h" typedef struct grpc_proxy_mapper grpc_proxy_mapper; typedef struct { /// Determines the proxy name to resolve for \a server_uri. /// If no proxy is needed, returns false. /// Otherwise, sets \a name_to_resolve, optionally sets \a new_args, /// and returns true. bool (*map_name)(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper, const char* server_uri, const grpc_channel_args* args, char** name_to_resolve, grpc_channel_args** new_args); /// Determines the proxy address to use to contact \a address. /// If no proxy is needed, returns false. /// Otherwise, sets \a new_address, optionally sets \a new_args, and /// returns true. bool (*map_address)(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper, const grpc_resolved_address* address, const grpc_channel_args* args, grpc_resolved_address** new_address, grpc_channel_args** new_args); /// Destroys \a mapper. void (*destroy)(grpc_proxy_mapper* mapper); } grpc_proxy_mapper_vtable; struct grpc_proxy_mapper { const grpc_proxy_mapper_vtable* vtable; }; void grpc_proxy_mapper_init(const grpc_proxy_mapper_vtable* vtable, grpc_proxy_mapper* mapper); bool grpc_proxy_mapper_map_name(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper, const char* server_uri, const grpc_channel_args* args, char** name_to_resolve, grpc_channel_args** new_args); bool grpc_proxy_mapper_map_address(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper, const grpc_resolved_address* address, const grpc_channel_args* args, grpc_resolved_address** new_address, grpc_channel_args** new_args); void grpc_proxy_mapper_destroy(grpc_proxy_mapper* mapper); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PROXY_MAPPER_H */ grpc-1.3.2/src/core/ext/filters/client_channel/proxy_mapper_registry.c000066400000000000000000000125741310511640000262260ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/filters/client_channel/proxy_mapper_registry.h" #include #include // // grpc_proxy_mapper_list // typedef struct { grpc_proxy_mapper** list; size_t num_mappers; } grpc_proxy_mapper_list; static void grpc_proxy_mapper_list_register(grpc_proxy_mapper_list* list, bool at_start, grpc_proxy_mapper* mapper) { list->list = gpr_realloc( list->list, (list->num_mappers + 1) * sizeof(grpc_proxy_mapper*)); if (at_start) { memmove(list->list + 1, list->list, sizeof(grpc_proxy_mapper*) * list->num_mappers); list->list[0] = mapper; } else { list->list[list->num_mappers] = mapper; } ++list->num_mappers; } static bool grpc_proxy_mapper_list_map_name(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper_list* list, const char* server_uri, const grpc_channel_args* args, char** name_to_resolve, grpc_channel_args** new_args) { for (size_t i = 0; i < list->num_mappers; ++i) { if (grpc_proxy_mapper_map_name(exec_ctx, list->list[i], server_uri, args, name_to_resolve, new_args)) { return true; } } return false; } static bool grpc_proxy_mapper_list_map_address( grpc_exec_ctx* exec_ctx, grpc_proxy_mapper_list* list, const grpc_resolved_address* address, const grpc_channel_args* args, grpc_resolved_address** new_address, grpc_channel_args** new_args) { for (size_t i = 0; i < list->num_mappers; ++i) { if (grpc_proxy_mapper_map_address(exec_ctx, list->list[i], address, args, new_address, new_args)) { return true; } } return false; } static void grpc_proxy_mapper_list_destroy(grpc_proxy_mapper_list* list) { for (size_t i = 0; i < list->num_mappers; ++i) { grpc_proxy_mapper_destroy(list->list[i]); } gpr_free(list->list); // Clean up in case we re-initialze later. // TODO(ctiller): This should ideally live in // grpc_proxy_mapper_registry_init(). However, if we did this there, // then we would do it AFTER we start registering proxy mappers from // third-party plugins, so they'd never show up (and would leak memory). // We probably need some sort of dependency system for plugins to fix // this. memset(list, 0, sizeof(*list)); } // // plugin // static grpc_proxy_mapper_list g_proxy_mapper_list; void grpc_proxy_mapper_registry_init() {} void grpc_proxy_mapper_registry_shutdown() { grpc_proxy_mapper_list_destroy(&g_proxy_mapper_list); } void grpc_proxy_mapper_register(bool at_start, grpc_proxy_mapper* mapper) { grpc_proxy_mapper_list_register(&g_proxy_mapper_list, at_start, mapper); } bool grpc_proxy_mappers_map_name(grpc_exec_ctx* exec_ctx, const char* server_uri, const grpc_channel_args* args, char** name_to_resolve, grpc_channel_args** new_args) { return grpc_proxy_mapper_list_map_name(exec_ctx, &g_proxy_mapper_list, server_uri, args, name_to_resolve, new_args); } bool grpc_proxy_mappers_map_address(grpc_exec_ctx* exec_ctx, const grpc_resolved_address* address, const grpc_channel_args* args, grpc_resolved_address** new_address, grpc_channel_args** new_args) { return grpc_proxy_mapper_list_map_address( exec_ctx, &g_proxy_mapper_list, address, args, new_address, new_args); } grpc-1.3.2/src/core/ext/filters/client_channel/proxy_mapper_registry.h000066400000000000000000000054151310511640000262270ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PROXY_MAPPER_REGISTRY_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PROXY_MAPPER_REGISTRY_H #include "src/core/ext/filters/client_channel/proxy_mapper.h" void grpc_proxy_mapper_registry_init(); void grpc_proxy_mapper_registry_shutdown(); /// Registers a new proxy mapper. Takes ownership. /// If \a at_start is true, the new mapper will be at the beginning of /// the list. Otherwise, it will be added to the end. void grpc_proxy_mapper_register(bool at_start, grpc_proxy_mapper* mapper); bool grpc_proxy_mappers_map_name(grpc_exec_ctx* exec_ctx, const char* server_uri, const grpc_channel_args* args, char** name_to_resolve, grpc_channel_args** new_args); bool grpc_proxy_mappers_map_address(grpc_exec_ctx* exec_ctx, const grpc_resolved_address* address, const grpc_channel_args* args, grpc_resolved_address** new_address, grpc_channel_args** new_args); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PROXY_MAPPER_REGISTRY_H */ grpc-1.3.2/src/core/ext/filters/client_channel/resolver.c000066400000000000000000000072771310511640000234160ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/filters/client_channel/resolver.h" #include "src/core/lib/iomgr/combiner.h" void grpc_resolver_init(grpc_resolver *resolver, const grpc_resolver_vtable *vtable, grpc_combiner *combiner) { resolver->vtable = vtable; resolver->combiner = GRPC_COMBINER_REF(combiner, "resolver"); gpr_ref_init(&resolver->refs, 1); } #ifdef GRPC_RESOLVER_REFCOUNT_DEBUG void grpc_resolver_ref(grpc_resolver *resolver, grpc_closure_list *closure_list, const char *file, int line, const char *reason) { gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "RESOLVER:%p ref %d -> %d %s", resolver, (int)resolver->refs.count, (int)resolver->refs.count + 1, reason); #else void grpc_resolver_ref(grpc_resolver *resolver) { #endif gpr_ref(&resolver->refs); } #ifdef GRPC_RESOLVER_REFCOUNT_DEBUG void grpc_resolver_unref(grpc_resolver *resolver, grpc_closure_list *closure_list, const char *file, int line, const char *reason) { gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "RESOLVER:%p unref %d -> %d %s", resolver, (int)resolver->refs.count, (int)resolver->refs.count - 1, reason); #else void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) { #endif if (gpr_unref(&resolver->refs)) { grpc_combiner *combiner = resolver->combiner; resolver->vtable->destroy(exec_ctx, resolver); GRPC_COMBINER_UNREF(exec_ctx, combiner, "resolver"); } } void grpc_resolver_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) { resolver->vtable->shutdown_locked(exec_ctx, resolver); } void grpc_resolver_channel_saw_error_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) { resolver->vtable->channel_saw_error_locked(exec_ctx, resolver); } void grpc_resolver_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver, grpc_channel_args **result, grpc_closure *on_complete) { resolver->vtable->next_locked(exec_ctx, resolver, result, on_complete); } grpc-1.3.2/src/core/ext/filters/client_channel/resolver.h000066400000000000000000000106341310511640000234120ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_H #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/iomgr/iomgr.h" typedef struct grpc_resolver grpc_resolver; typedef struct grpc_resolver_vtable grpc_resolver_vtable; /** \a grpc_resolver provides \a grpc_channel_args objects to its caller */ struct grpc_resolver { const grpc_resolver_vtable *vtable; gpr_refcount refs; grpc_combiner *combiner; }; struct grpc_resolver_vtable { void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver); void (*shutdown_locked)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver); void (*channel_saw_error_locked)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver); void (*next_locked)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver, grpc_channel_args **result, grpc_closure *on_complete); }; #ifdef GRPC_RESOLVER_REFCOUNT_DEBUG #define GRPC_RESOLVER_REF(p, r) grpc_resolver_ref((p), __FILE__, __LINE__, (r)) #define GRPC_RESOLVER_UNREF(cl, p, r) \ grpc_resolver_unref((cl), (p), __FILE__, __LINE__, (r)) void grpc_resolver_ref(grpc_resolver *policy, const char *file, int line, const char *reason); void grpc_resolver_unref(grpc_resolver *policy, grpc_closure_list *closure_list, const char *file, int line, const char *reason); #else #define GRPC_RESOLVER_REF(p, r) grpc_resolver_ref((p)) #define GRPC_RESOLVER_UNREF(cl, p, r) grpc_resolver_unref((cl), (p)) void grpc_resolver_ref(grpc_resolver *policy); void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *policy); #endif void grpc_resolver_init(grpc_resolver *resolver, const grpc_resolver_vtable *vtable, grpc_combiner *combiner); void grpc_resolver_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver); /** Notification that the channel has seen an error on some address. Can be used as a hint that re-resolution is desirable soon. Must be called from the combiner passed as a resolver_arg at construction time.*/ void grpc_resolver_channel_saw_error_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver); /** Get the next result from the resolver. Expected to set \a *result with new channel args and then schedule \a on_complete for execution. If resolution is fatally broken, set \a *result to NULL and schedule \a on_complete. Must be called from the combiner passed as a resolver_arg at construction time.*/ void grpc_resolver_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver, grpc_channel_args **result, grpc_closure *on_complete); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_H */ grpc-1.3.2/src/core/ext/filters/client_channel/resolver/000077500000000000000000000000001310511640000232355ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/filters/client_channel/resolver/README.md000066400000000000000000000001471310511640000245160ustar00rootroot00000000000000# Resolver Implementations of various name resolution schemes. See the [naming spec](/doc/naming.md). grpc-1.3.2/src/core/ext/filters/client_channel/resolver/dns/000077500000000000000000000000001310511640000240215ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/filters/client_channel/resolver/dns/c_ares/000077500000000000000000000000001310511640000252555ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c000066400000000000000000000326161310511640000311500ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #if GRPC_ARES == 1 && !defined(GRPC_UV) #include #include #include #include #include "src/core/ext/filters/client_channel/http_connect_handshaker.h" #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/support/backoff.h" #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" #define GRPC_DNS_MIN_CONNECT_TIMEOUT_SECONDS 1 #define GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS 1 #define GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER 1.6 #define GRPC_DNS_RECONNECT_MAX_BACKOFF_SECONDS 120 #define GRPC_DNS_RECONNECT_JITTER 0.2 typedef struct { /** base class: must be first */ grpc_resolver base; /** name to resolve (usually the same as target_name) */ char *name_to_resolve; /** default port to use */ char *default_port; /** channel args. */ grpc_channel_args *channel_args; /** pollset_set to drive the name resolution process */ grpc_pollset_set *interested_parties; /** Closures used by the combiner */ grpc_closure dns_ares_on_retry_timer_locked; grpc_closure dns_ares_on_resolved_locked; /** Combiner guarding the rest of the state */ grpc_combiner *combiner; /** are we currently resolving? */ bool resolving; /** which version of the result have we published? */ int published_version; /** which version of the result is current? */ int resolved_version; /** pending next completion, or NULL */ grpc_closure *next_completion; /** target result address for next completion */ grpc_channel_args **target_result; /** current (fully resolved) result */ grpc_channel_args *resolved_result; /** retry timer */ bool have_retry_timer; grpc_timer retry_timer; /** retry backoff state */ gpr_backoff backoff_state; /** currently resolving addresses */ grpc_resolved_addresses *addresses; } ares_dns_resolver; static void dns_ares_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r); static void dns_ares_start_resolving_locked(grpc_exec_ctx *exec_ctx, ares_dns_resolver *r); static void dns_ares_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx, ares_dns_resolver *r); static void dns_ares_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r); static void dns_ares_channel_saw_error_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r); static void dns_ares_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r, grpc_channel_args **target_result, grpc_closure *on_complete); static const grpc_resolver_vtable dns_ares_resolver_vtable = { dns_ares_destroy, dns_ares_shutdown_locked, dns_ares_channel_saw_error_locked, dns_ares_next_locked}; static void dns_ares_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) { ares_dns_resolver *r = (ares_dns_resolver *)resolver; if (r->have_retry_timer) { grpc_timer_cancel(exec_ctx, &r->retry_timer); } if (r->next_completion != NULL) { *r->target_result = NULL; grpc_closure_sched( exec_ctx, r->next_completion, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resolver Shutdown")); r->next_completion = NULL; } } static void dns_ares_channel_saw_error_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) { ares_dns_resolver *r = (ares_dns_resolver *)resolver; if (!r->resolving) { gpr_backoff_reset(&r->backoff_state); dns_ares_start_resolving_locked(exec_ctx, r); } } static void dns_ares_on_retry_timer_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { ares_dns_resolver *r = arg; r->have_retry_timer = false; if (error == GRPC_ERROR_NONE) { if (!r->resolving) { dns_ares_start_resolving_locked(exec_ctx, r); } } GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "retry-timer"); } static void dns_ares_on_resolved_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { ares_dns_resolver *r = arg; grpc_channel_args *result = NULL; GPR_ASSERT(r->resolving); r->resolving = false; if (r->addresses != NULL) { grpc_lb_addresses *addresses = grpc_lb_addresses_create( r->addresses->naddrs, NULL /* user_data_vtable */); for (size_t i = 0; i < r->addresses->naddrs; ++i) { grpc_lb_addresses_set_address( addresses, i, &r->addresses->addrs[i].addr, r->addresses->addrs[i].len, false /* is_balancer */, NULL /* balancer_name */, NULL /* user_data */); } grpc_arg new_arg = grpc_lb_addresses_create_channel_arg(addresses); result = grpc_channel_args_copy_and_add(r->channel_args, &new_arg, 1); grpc_resolved_addresses_destroy(r->addresses); grpc_lb_addresses_destroy(exec_ctx, addresses); } else { gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now); gpr_timespec timeout = gpr_time_sub(next_try, now); gpr_log(GPR_INFO, "dns resolution failed (will retry): %s", grpc_error_string(error)); GPR_ASSERT(!r->have_retry_timer); r->have_retry_timer = true; GRPC_RESOLVER_REF(&r->base, "retry-timer"); if (gpr_time_cmp(timeout, gpr_time_0(timeout.clock_type)) > 0) { gpr_log(GPR_DEBUG, "retrying in %" PRId64 ".%09d seconds", timeout.tv_sec, timeout.tv_nsec); } else { gpr_log(GPR_DEBUG, "retrying immediately"); } grpc_timer_init(exec_ctx, &r->retry_timer, next_try, &r->dns_ares_on_retry_timer_locked, now); } if (r->resolved_result != NULL) { grpc_channel_args_destroy(exec_ctx, r->resolved_result); } r->resolved_result = result; r->resolved_version++; dns_ares_maybe_finish_next_locked(exec_ctx, r); GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "dns-resolving"); } static void dns_ares_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver, grpc_channel_args **target_result, grpc_closure *on_complete) { gpr_log(GPR_DEBUG, "dns_ares_next is called."); ares_dns_resolver *r = (ares_dns_resolver *)resolver; GPR_ASSERT(!r->next_completion); r->next_completion = on_complete; r->target_result = target_result; if (r->resolved_version == 0 && !r->resolving) { gpr_backoff_reset(&r->backoff_state); dns_ares_start_resolving_locked(exec_ctx, r); } else { dns_ares_maybe_finish_next_locked(exec_ctx, r); } } static void dns_ares_start_resolving_locked(grpc_exec_ctx *exec_ctx, ares_dns_resolver *r) { GRPC_RESOLVER_REF(&r->base, "dns-resolving"); GPR_ASSERT(!r->resolving); r->resolving = true; r->addresses = NULL; grpc_resolve_address(exec_ctx, r->name_to_resolve, r->default_port, r->interested_parties, &r->dns_ares_on_resolved_locked, &r->addresses); } static void dns_ares_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx, ares_dns_resolver *r) { if (r->next_completion != NULL && r->resolved_version != r->published_version) { *r->target_result = r->resolved_result == NULL ? NULL : grpc_channel_args_copy(r->resolved_result); grpc_closure_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE); r->next_completion = NULL; r->published_version = r->resolved_version; } } static void dns_ares_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) { gpr_log(GPR_DEBUG, "dns_ares_destroy"); ares_dns_resolver *r = (ares_dns_resolver *)gr; if (r->resolved_result != NULL) { grpc_channel_args_destroy(exec_ctx, r->resolved_result); } grpc_pollset_set_destroy(exec_ctx, r->interested_parties); gpr_free(r->name_to_resolve); gpr_free(r->default_port); grpc_channel_args_destroy(exec_ctx, r->channel_args); gpr_free(r); } static grpc_resolver *dns_ares_create(grpc_exec_ctx *exec_ctx, grpc_resolver_args *args, const char *default_port) { // Get name from args. const char *path = args->uri->path; if (0 != strcmp(args->uri->authority, "")) { gpr_log(GPR_ERROR, "authority based dns uri's not supported"); return NULL; } if (path[0] == '/') ++path; // Create resolver. ares_dns_resolver *r = gpr_zalloc(sizeof(ares_dns_resolver)); grpc_resolver_init(&r->base, &dns_ares_resolver_vtable, args->combiner); r->name_to_resolve = gpr_strdup(path); r->default_port = gpr_strdup(default_port); r->channel_args = grpc_channel_args_copy(args->args); r->interested_parties = grpc_pollset_set_create(); if (args->pollset_set != NULL) { grpc_pollset_set_add_pollset_set(exec_ctx, r->interested_parties, args->pollset_set); } gpr_backoff_init(&r->backoff_state, GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS, GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER, GRPC_DNS_RECONNECT_JITTER, GRPC_DNS_MIN_CONNECT_TIMEOUT_SECONDS * 1000, GRPC_DNS_RECONNECT_MAX_BACKOFF_SECONDS * 1000); grpc_closure_init(&r->dns_ares_on_retry_timer_locked, dns_ares_on_retry_timer_locked, r, grpc_combiner_scheduler(r->base.combiner, false)); grpc_closure_init(&r->dns_ares_on_resolved_locked, dns_ares_on_resolved_locked, r, grpc_combiner_scheduler(r->base.combiner, false)); return &r->base; } /* * FACTORY */ static void dns_ares_factory_ref(grpc_resolver_factory *factory) {} static void dns_ares_factory_unref(grpc_resolver_factory *factory) {} static grpc_resolver *dns_factory_create_resolver( grpc_exec_ctx *exec_ctx, grpc_resolver_factory *factory, grpc_resolver_args *args) { return dns_ares_create(exec_ctx, args, "https"); } static char *dns_ares_factory_get_default_host_name( grpc_resolver_factory *factory, grpc_uri *uri) { const char *path = uri->path; if (path[0] == '/') ++path; return gpr_strdup(path); } static const grpc_resolver_factory_vtable dns_ares_factory_vtable = { dns_ares_factory_ref, dns_ares_factory_unref, dns_factory_create_resolver, dns_ares_factory_get_default_host_name, "dns"}; static grpc_resolver_factory dns_resolver_factory = {&dns_ares_factory_vtable}; static grpc_resolver_factory *dns_ares_resolver_factory_create() { return &dns_resolver_factory; } void grpc_resolver_dns_ares_init(void) { char *resolver = gpr_getenv("GRPC_DNS_RESOLVER"); /* TODO(zyc): Turn on c-ares based resolver by default after the address sorter and the CNAME support are added. */ if (resolver != NULL && gpr_stricmp(resolver, "ares") == 0) { grpc_error *error = grpc_ares_init(); if (error != GRPC_ERROR_NONE) { GRPC_LOG_IF_ERROR("ares_library_init() failed", error); return; } grpc_resolve_address = grpc_resolve_address_ares; grpc_register_resolver_type(dns_ares_resolver_factory_create()); } gpr_free(resolver); } void grpc_resolver_dns_ares_shutdown(void) { char *resolver = gpr_getenv("GRPC_DNS_RESOLVER"); if (resolver != NULL && gpr_stricmp(resolver, "ares") == 0) { grpc_ares_cleanup(); } gpr_free(resolver); } #else /* GRPC_ARES == 1 && !defined(GRPC_UV) */ void grpc_resolver_dns_ares_init(void) {} void grpc_resolver_dns_ares_shutdown(void) {} #endif /* GRPC_ARES == 1 && !defined(GRPC_UV) */ grpc-1.3.2/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h000066400000000000000000000060241310511640000314420ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_EV_DRIVER_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_EV_DRIVER_H #include #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/pollset_set.h" typedef struct grpc_ares_ev_driver grpc_ares_ev_driver; /* Start \a ev_driver. It will keep working until all IO on its ares_channel is done, or grpc_ares_ev_driver_destroy() is called. It may notify the callbacks bound to its ares_channel when necessary. */ void grpc_ares_ev_driver_start(grpc_exec_ctx *exec_ctx, grpc_ares_ev_driver *ev_driver); /* Returns the ares_channel owned by \a ev_driver. To bind a c-ares query to \a ev_driver, use the ares_channel owned by \a ev_driver as the arg of the query. */ ares_channel *grpc_ares_ev_driver_get_channel(grpc_ares_ev_driver *ev_driver); /* Creates a new grpc_ares_ev_driver. Returns GRPC_ERROR_NONE if \a ev_driver is created successfully. */ grpc_error *grpc_ares_ev_driver_create(grpc_ares_ev_driver **ev_driver, grpc_pollset_set *pollset_set); /* Destroys \a ev_driver asynchronously. Pending lookups made on \a ev_driver will be cancelled and their on_done callbacks will be invoked with a status of ARES_ECANCELLED. */ void grpc_ares_ev_driver_destroy(grpc_ares_ev_driver *ev_driver); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_EV_DRIVER_H \ */ grpc-1.3.2/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c000066400000000000000000000307661310511640000326710ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "src/core/lib/iomgr/port.h" #if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET) #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" #include #include #include #include #include #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/support/string.h" typedef struct fd_node { /** the owner of this fd node */ grpc_ares_ev_driver *ev_driver; /** the grpc_fd owned by this fd node */ grpc_fd *grpc_fd; /** a closure wrapping on_readable_cb, which should be invoked when the grpc_fd in this node becomes readable. */ grpc_closure read_closure; /** a closure wrapping on_writable_cb, which should be invoked when the grpc_fd in this node becomes writable. */ grpc_closure write_closure; /** next fd node in the list */ struct fd_node *next; /** mutex guarding the rest of the state */ gpr_mu mu; /** if the readable closure has been registered */ bool readable_registered; /** if the writable closure has been registered */ bool writable_registered; } fd_node; struct grpc_ares_ev_driver { /** the ares_channel owned by this event driver */ ares_channel channel; /** pollset set for driving the IO events of the channel */ grpc_pollset_set *pollset_set; /** refcount of the event driver */ gpr_refcount refs; /** mutex guarding the rest of the state */ gpr_mu mu; /** a list of grpc_fd that this event driver is currently using. */ fd_node *fds; /** is this event driver currently working? */ bool working; /** is this event driver being shut down */ bool shutting_down; }; static void grpc_ares_notify_on_event_locked(grpc_exec_ctx *exec_ctx, grpc_ares_ev_driver *ev_driver); static grpc_ares_ev_driver *grpc_ares_ev_driver_ref( grpc_ares_ev_driver *ev_driver) { gpr_log(GPR_DEBUG, "Ref ev_driver %" PRIuPTR, (uintptr_t)ev_driver); gpr_ref(&ev_driver->refs); return ev_driver; } static void grpc_ares_ev_driver_unref(grpc_ares_ev_driver *ev_driver) { gpr_log(GPR_DEBUG, "Unref ev_driver %" PRIuPTR, (uintptr_t)ev_driver); if (gpr_unref(&ev_driver->refs)) { gpr_log(GPR_DEBUG, "destroy ev_driver %" PRIuPTR, (uintptr_t)ev_driver); GPR_ASSERT(ev_driver->fds == NULL); gpr_mu_destroy(&ev_driver->mu); ares_destroy(ev_driver->channel); gpr_free(ev_driver); } } static void fd_node_destroy(grpc_exec_ctx *exec_ctx, fd_node *fdn) { gpr_log(GPR_DEBUG, "delete fd: %d", grpc_fd_wrapped_fd(fdn->grpc_fd)); GPR_ASSERT(!fdn->readable_registered); GPR_ASSERT(!fdn->writable_registered); gpr_mu_destroy(&fdn->mu); grpc_pollset_set_del_fd(exec_ctx, fdn->ev_driver->pollset_set, fdn->grpc_fd); grpc_fd_shutdown(exec_ctx, fdn->grpc_fd, GRPC_ERROR_CREATE_FROM_STATIC_STRING("fd node destroyed")); grpc_fd_orphan(exec_ctx, fdn->grpc_fd, NULL, NULL, "c-ares query finished"); gpr_free(fdn); } grpc_error *grpc_ares_ev_driver_create(grpc_ares_ev_driver **ev_driver, grpc_pollset_set *pollset_set) { *ev_driver = gpr_malloc(sizeof(grpc_ares_ev_driver)); int status = ares_init(&(*ev_driver)->channel); gpr_log(GPR_DEBUG, "grpc_ares_ev_driver_create"); if (status != ARES_SUCCESS) { char *err_msg; gpr_asprintf(&err_msg, "Failed to init ares channel. C-ares error: %s", ares_strerror(status)); grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(err_msg); gpr_free(err_msg); gpr_free(*ev_driver); return err; } gpr_mu_init(&(*ev_driver)->mu); gpr_ref_init(&(*ev_driver)->refs, 1); (*ev_driver)->pollset_set = pollset_set; (*ev_driver)->fds = NULL; (*ev_driver)->working = false; (*ev_driver)->shutting_down = false; return GRPC_ERROR_NONE; } void grpc_ares_ev_driver_destroy(grpc_ares_ev_driver *ev_driver) { // It's not safe to shut down remaining fds here directly, becauses // ares_host_callback does not provide an exec_ctx. We mark the event driver // as being shut down. If the event driver is working, // grpc_ares_notify_on_event_locked will shut down the fds; if it's not // working, there are no fds to shut down. gpr_mu_lock(&ev_driver->mu); ev_driver->shutting_down = true; gpr_mu_unlock(&ev_driver->mu); grpc_ares_ev_driver_unref(ev_driver); } // Search fd in the fd_node list head. This is an O(n) search, the max possible // value of n is ARES_GETSOCK_MAXNUM (16). n is typically 1 - 2 in our tests. static fd_node *pop_fd_node(fd_node **head, int fd) { fd_node dummy_head; dummy_head.next = *head; fd_node *node = &dummy_head; while (node->next != NULL) { if (grpc_fd_wrapped_fd(node->next->grpc_fd) == fd) { fd_node *ret = node->next; node->next = node->next->next; *head = dummy_head.next; return ret; } node = node->next; } return NULL; } static void on_readable_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { fd_node *fdn = arg; grpc_ares_ev_driver *ev_driver = fdn->ev_driver; gpr_mu_lock(&fdn->mu); fdn->readable_registered = false; gpr_mu_unlock(&fdn->mu); gpr_log(GPR_DEBUG, "readable on %d", grpc_fd_wrapped_fd(fdn->grpc_fd)); if (error == GRPC_ERROR_NONE) { ares_process_fd(ev_driver->channel, grpc_fd_wrapped_fd(fdn->grpc_fd), ARES_SOCKET_BAD); } else { // If error is not GRPC_ERROR_NONE, it means the fd has been shutdown or // timed out. The pending lookups made on this ev_driver will be cancelled // by the following ares_cancel() and the on_done callbacks will be invoked // with a status of ARES_ECANCELLED. The remaining file descriptors in this // ev_driver will be cleaned up in the follwing // grpc_ares_notify_on_event_locked(). ares_cancel(ev_driver->channel); } gpr_mu_lock(&ev_driver->mu); grpc_ares_notify_on_event_locked(exec_ctx, ev_driver); gpr_mu_unlock(&ev_driver->mu); grpc_ares_ev_driver_unref(ev_driver); } static void on_writable_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { fd_node *fdn = arg; grpc_ares_ev_driver *ev_driver = fdn->ev_driver; gpr_mu_lock(&fdn->mu); fdn->writable_registered = false; gpr_mu_unlock(&fdn->mu); gpr_log(GPR_DEBUG, "writable on %d", grpc_fd_wrapped_fd(fdn->grpc_fd)); if (error == GRPC_ERROR_NONE) { ares_process_fd(ev_driver->channel, ARES_SOCKET_BAD, grpc_fd_wrapped_fd(fdn->grpc_fd)); } else { // If error is not GRPC_ERROR_NONE, it means the fd has been shutdown or // timed out. The pending lookups made on this ev_driver will be cancelled // by the following ares_cancel() and the on_done callbacks will be invoked // with a status of ARES_ECANCELLED. The remaining file descriptors in this // ev_driver will be cleaned up in the follwing // grpc_ares_notify_on_event_locked(). ares_cancel(ev_driver->channel); } gpr_mu_lock(&ev_driver->mu); grpc_ares_notify_on_event_locked(exec_ctx, ev_driver); gpr_mu_unlock(&ev_driver->mu); grpc_ares_ev_driver_unref(ev_driver); } ares_channel *grpc_ares_ev_driver_get_channel(grpc_ares_ev_driver *ev_driver) { return &ev_driver->channel; } // Get the file descriptors used by the ev_driver's ares channel, register // driver_closure with these filedescriptors. static void grpc_ares_notify_on_event_locked(grpc_exec_ctx *exec_ctx, grpc_ares_ev_driver *ev_driver) { fd_node *new_list = NULL; if (!ev_driver->shutting_down) { ares_socket_t socks[ARES_GETSOCK_MAXNUM]; int socks_bitmask = ares_getsock(ev_driver->channel, socks, ARES_GETSOCK_MAXNUM); for (size_t i = 0; i < ARES_GETSOCK_MAXNUM; i++) { if (ARES_GETSOCK_READABLE(socks_bitmask, i) || ARES_GETSOCK_WRITABLE(socks_bitmask, i)) { fd_node *fdn = pop_fd_node(&ev_driver->fds, socks[i]); // Create a new fd_node if sock[i] is not in the fd_node list. if (fdn == NULL) { char *fd_name; gpr_asprintf(&fd_name, "ares_ev_driver-%" PRIuPTR, i); fdn = gpr_malloc(sizeof(fd_node)); gpr_log(GPR_DEBUG, "new fd: %d", socks[i]); fdn->grpc_fd = grpc_fd_create(socks[i], fd_name); fdn->ev_driver = ev_driver; fdn->readable_registered = false; fdn->writable_registered = false; gpr_mu_init(&fdn->mu); grpc_closure_init(&fdn->read_closure, on_readable_cb, fdn, grpc_schedule_on_exec_ctx); grpc_closure_init(&fdn->write_closure, on_writable_cb, fdn, grpc_schedule_on_exec_ctx); grpc_pollset_set_add_fd(exec_ctx, ev_driver->pollset_set, fdn->grpc_fd); gpr_free(fd_name); } fdn->next = new_list; new_list = fdn; gpr_mu_lock(&fdn->mu); // Register read_closure if the socket is readable and read_closure has // not been registered with this socket. if (ARES_GETSOCK_READABLE(socks_bitmask, i) && !fdn->readable_registered) { grpc_ares_ev_driver_ref(ev_driver); gpr_log(GPR_DEBUG, "notify read on: %d", grpc_fd_wrapped_fd(fdn->grpc_fd)); grpc_fd_notify_on_read(exec_ctx, fdn->grpc_fd, &fdn->read_closure); fdn->readable_registered = true; } // Register write_closure if the socket is writable and write_closure // has not been registered with this socket. if (ARES_GETSOCK_WRITABLE(socks_bitmask, i) && !fdn->writable_registered) { gpr_log(GPR_DEBUG, "notify write on: %d", grpc_fd_wrapped_fd(fdn->grpc_fd)); grpc_ares_ev_driver_ref(ev_driver); grpc_fd_notify_on_write(exec_ctx, fdn->grpc_fd, &fdn->write_closure); fdn->writable_registered = true; } gpr_mu_unlock(&fdn->mu); } } } // Any remaining fds in ev_driver->fds were not returned by ares_getsock() and // are therefore no longer in use, so they can be shut down and removed from // the list. while (ev_driver->fds != NULL) { fd_node *cur = ev_driver->fds; ev_driver->fds = ev_driver->fds->next; fd_node_destroy(exec_ctx, cur); } ev_driver->fds = new_list; // If the ev driver has no working fd, all the tasks are done. if (new_list == NULL) { ev_driver->working = false; gpr_log(GPR_DEBUG, "ev driver stop working"); } } void grpc_ares_ev_driver_start(grpc_exec_ctx *exec_ctx, grpc_ares_ev_driver *ev_driver) { gpr_mu_lock(&ev_driver->mu); if (!ev_driver->working) { ev_driver->working = true; grpc_ares_notify_on_event_locked(exec_ctx, ev_driver); } gpr_mu_unlock(&ev_driver->mu); } #endif /* GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET) */ grpc-1.3.2/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c000066400000000000000000000252241310511640000311330ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #if GRPC_ARES == 1 && !defined(GRPC_UV) #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/socket_utils_posix.h" #include #include #include #include #include #include #include #include #include #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/support/string.h" static gpr_once g_basic_init = GPR_ONCE_INIT; static gpr_mu g_init_mu; typedef struct grpc_ares_request { /** following members are set in grpc_resolve_address_ares_impl */ /** host to resolve, parsed from the name to resolve */ char *host; /** port to fill in sockaddr_in, parsed from the name to resolve */ char *port; /** default port to use */ char *default_port; /** closure to call when the request completes */ grpc_closure *on_done; /** the pointer to receive the resolved addresses */ grpc_resolved_addresses **addrs_out; /** the evernt driver used by this request */ grpc_ares_ev_driver *ev_driver; /** number of ongoing queries */ gpr_refcount pending_queries; /** mutex guarding the rest of the state */ gpr_mu mu; /** is there at least one successful query, set in on_done_cb */ bool success; /** the errors explaining the request failure, set in on_done_cb */ grpc_error *error; } grpc_ares_request; static void do_basic_init(void) { gpr_mu_init(&g_init_mu); } static uint16_t strhtons(const char *port) { if (strcmp(port, "http") == 0) { return htons(80); } else if (strcmp(port, "https") == 0) { return htons(443); } return htons((unsigned short)atoi(port)); } static void grpc_ares_request_unref(grpc_exec_ctx *exec_ctx, grpc_ares_request *r) { /* If there are no pending queries, invoke on_done callback and destroy the request */ if (gpr_unref(&r->pending_queries)) { /* TODO(zyc): Sort results with RFC6724 before invoking on_done. */ if (exec_ctx == NULL) { /* A new exec_ctx is created here, as the c-ares interface does not provide one in ares_host_callback. It's safe to schedule on_done with the newly created exec_ctx, since the caller has been warned not to acquire locks in on_done. ares_dns_resolver is using combiner to protect resources needed by on_done. */ grpc_exec_ctx new_exec_ctx = GRPC_EXEC_CTX_INIT; grpc_closure_sched(&new_exec_ctx, r->on_done, r->error); grpc_exec_ctx_finish(&new_exec_ctx); } else { grpc_closure_sched(exec_ctx, r->on_done, r->error); } gpr_mu_destroy(&r->mu); grpc_ares_ev_driver_destroy(r->ev_driver); gpr_free(r->host); gpr_free(r->port); gpr_free(r->default_port); gpr_free(r); } } static void on_done_cb(void *arg, int status, int timeouts, struct hostent *hostent) { grpc_ares_request *r = (grpc_ares_request *)arg; gpr_mu_lock(&r->mu); if (status == ARES_SUCCESS) { GRPC_ERROR_UNREF(r->error); r->error = GRPC_ERROR_NONE; r->success = true; grpc_resolved_addresses **addresses = r->addrs_out; if (*addresses == NULL) { *addresses = gpr_malloc(sizeof(grpc_resolved_addresses)); (*addresses)->naddrs = 0; (*addresses)->addrs = NULL; } size_t prev_naddr = (*addresses)->naddrs; size_t i; for (i = 0; hostent->h_addr_list[i] != NULL; i++) { } (*addresses)->naddrs += i; (*addresses)->addrs = gpr_realloc((*addresses)->addrs, sizeof(grpc_resolved_address) * (*addresses)->naddrs); for (i = prev_naddr; i < (*addresses)->naddrs; i++) { memset(&(*addresses)->addrs[i], 0, sizeof(grpc_resolved_address)); if (hostent->h_addrtype == AF_INET6) { (*addresses)->addrs[i].len = sizeof(struct sockaddr_in6); struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&(*addresses)->addrs[i].addr; addr->sin6_family = (sa_family_t)hostent->h_addrtype; addr->sin6_port = strhtons(r->port); char output[INET6_ADDRSTRLEN]; memcpy(&addr->sin6_addr, hostent->h_addr_list[i - prev_naddr], sizeof(struct in6_addr)); ares_inet_ntop(AF_INET6, &addr->sin6_addr, output, INET6_ADDRSTRLEN); gpr_log(GPR_DEBUG, "c-ares resolver gets a AF_INET6 result: \n" " addr: %s\n port: %s\n sin6_scope_id: %d\n", output, r->port, addr->sin6_scope_id); } else { (*addresses)->addrs[i].len = sizeof(struct sockaddr_in); struct sockaddr_in *addr = (struct sockaddr_in *)&(*addresses)->addrs[i].addr; memcpy(&addr->sin_addr, hostent->h_addr_list[i - prev_naddr], sizeof(struct in_addr)); addr->sin_family = (sa_family_t)hostent->h_addrtype; addr->sin_port = strhtons(r->port); char output[INET_ADDRSTRLEN]; ares_inet_ntop(AF_INET, &addr->sin_addr, output, INET_ADDRSTRLEN); gpr_log(GPR_DEBUG, "c-ares resolver gets a AF_INET result: \n" " addr: %s\n port: %s\n", output, r->port); } } } else if (!r->success) { char *error_msg; gpr_asprintf(&error_msg, "C-ares status is not ARES_SUCCESS: %s", ares_strerror(status)); grpc_error *error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg); gpr_free(error_msg); if (r->error == GRPC_ERROR_NONE) { r->error = error; } else { r->error = grpc_error_add_child(error, r->error); } } gpr_mu_unlock(&r->mu); grpc_ares_request_unref(NULL, r); } void grpc_resolve_address_ares_impl(grpc_exec_ctx *exec_ctx, const char *name, const char *default_port, grpc_pollset_set *interested_parties, grpc_closure *on_done, grpc_resolved_addresses **addrs) { /* TODO(zyc): Enable tracing after #9603 is checked in */ /* if (grpc_dns_trace) { gpr_log(GPR_DEBUG, "resolve_address (blocking): name=%s, default_port=%s", name, default_port); } */ /* parse name, splitting it into host and port parts */ char *host; char *port; gpr_split_host_port(name, &host, &port); if (host == NULL) { grpc_error *err = grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("unparseable host:port"), GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name)); grpc_closure_sched(exec_ctx, on_done, err); goto error_cleanup; } else if (port == NULL) { if (default_port == NULL) { grpc_error *err = grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("no port in name"), GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name)); grpc_closure_sched(exec_ctx, on_done, err); goto error_cleanup; } port = gpr_strdup(default_port); } grpc_ares_ev_driver *ev_driver; grpc_error *err = grpc_ares_ev_driver_create(&ev_driver, interested_parties); if (err != GRPC_ERROR_NONE) { GRPC_LOG_IF_ERROR("grpc_ares_ev_driver_create() failed", err); goto error_cleanup; } grpc_ares_request *r = gpr_malloc(sizeof(grpc_ares_request)); gpr_mu_init(&r->mu); r->ev_driver = ev_driver; r->on_done = on_done; r->addrs_out = addrs; r->default_port = gpr_strdup(default_port); r->port = port; r->host = host; r->success = false; r->error = GRPC_ERROR_NONE; ares_channel *channel = grpc_ares_ev_driver_get_channel(r->ev_driver); gpr_ref_init(&r->pending_queries, 2); if (grpc_ipv6_loopback_available()) { gpr_ref(&r->pending_queries); ares_gethostbyname(*channel, r->host, AF_INET6, on_done_cb, r); } ares_gethostbyname(*channel, r->host, AF_INET, on_done_cb, r); /* TODO(zyc): Handle CNAME records here. */ grpc_ares_ev_driver_start(exec_ctx, r->ev_driver); grpc_ares_request_unref(exec_ctx, r); return; error_cleanup: gpr_free(host); gpr_free(port); } void (*grpc_resolve_address_ares)( grpc_exec_ctx *exec_ctx, const char *name, const char *default_port, grpc_pollset_set *interested_parties, grpc_closure *on_done, grpc_resolved_addresses **addrs) = grpc_resolve_address_ares_impl; grpc_error *grpc_ares_init(void) { gpr_once_init(&g_basic_init, do_basic_init); gpr_mu_lock(&g_init_mu); int status = ares_library_init(ARES_LIB_INIT_ALL); gpr_mu_unlock(&g_init_mu); if (status != ARES_SUCCESS) { char *error_msg; gpr_asprintf(&error_msg, "ares_library_init failed: %s", ares_strerror(status)); grpc_error *error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg); gpr_free(error_msg); return error; } return GRPC_ERROR_NONE; } void grpc_ares_cleanup(void) { gpr_mu_lock(&g_init_mu); ares_library_cleanup(); gpr_mu_unlock(&g_init_mu); } #endif /* GRPC_ARES == 1 && !defined(GRPC_UV) */ grpc-1.3.2/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h000066400000000000000000000061751310511640000311440ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_WRAPPER_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_WRAPPER_H #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/resolve_address.h" /* Asynchronously resolve addr. Use \a default_port if a port isn't designated in addr, otherwise use the port in addr. grpc_ares_init() must be called at least once before this function. \a on_done may be called directly in this function without being scheduled with \a exec_ctx, it must not try to acquire locks that are being held by the caller. */ extern void (*grpc_resolve_address_ares)(grpc_exec_ctx *exec_ctx, const char *addr, const char *default_port, grpc_pollset_set *interested_parties, grpc_closure *on_done, grpc_resolved_addresses **addresses); /* Initialize gRPC ares wrapper. Must be called at least once before grpc_resolve_address_ares(). */ grpc_error *grpc_ares_init(void); /* Uninitialized gRPC ares wrapper. If there was more than one previous call to grpc_ares_init(), this function uninitializes the gRPC ares wrapper only if it has been called the same number of times as grpc_ares_init(). */ void grpc_ares_cleanup(void); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_WRAPPER_H \ */ grpc-1.3.2/src/core/ext/filters/client_channel/resolver/dns/native/000077500000000000000000000000001310511640000253075ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/filters/client_channel/resolver/dns/native/README.md000066400000000000000000000001271310511640000265660ustar00rootroot00000000000000dns: scheme name resolution, using getaddrbyname (or other OS specific implementation) grpc-1.3.2/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.c000066400000000000000000000300411310511640000301560ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/support/backoff.h" #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" #define GRPC_DNS_MIN_CONNECT_TIMEOUT_SECONDS 1 #define GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS 1 #define GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER 1.6 #define GRPC_DNS_RECONNECT_MAX_BACKOFF_SECONDS 120 #define GRPC_DNS_RECONNECT_JITTER 0.2 typedef struct { /** base class: must be first */ grpc_resolver base; /** name to resolve */ char *name_to_resolve; /** default port to use */ char *default_port; /** channel args. */ grpc_channel_args *channel_args; /** pollset_set to drive the name resolution process */ grpc_pollset_set *interested_parties; /** are we currently resolving? */ bool resolving; /** which version of the result have we published? */ int published_version; /** which version of the result is current? */ int resolved_version; /** pending next completion, or NULL */ grpc_closure *next_completion; /** target result address for next completion */ grpc_channel_args **target_result; /** current (fully resolved) result */ grpc_channel_args *resolved_result; /** retry timer */ bool have_retry_timer; grpc_timer retry_timer; grpc_closure on_retry; /** retry backoff state */ gpr_backoff backoff_state; /** currently resolving addresses */ grpc_resolved_addresses *addresses; } dns_resolver; static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r); static void dns_start_resolving_locked(grpc_exec_ctx *exec_ctx, dns_resolver *r); static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx, dns_resolver *r); static void dns_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r); static void dns_channel_saw_error_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r); static void dns_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r, grpc_channel_args **target_result, grpc_closure *on_complete); static const grpc_resolver_vtable dns_resolver_vtable = { dns_destroy, dns_shutdown_locked, dns_channel_saw_error_locked, dns_next_locked}; static void dns_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) { dns_resolver *r = (dns_resolver *)resolver; if (r->have_retry_timer) { grpc_timer_cancel(exec_ctx, &r->retry_timer); } if (r->next_completion != NULL) { *r->target_result = NULL; grpc_closure_sched( exec_ctx, r->next_completion, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resolver Shutdown")); r->next_completion = NULL; } } static void dns_channel_saw_error_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) { dns_resolver *r = (dns_resolver *)resolver; if (!r->resolving) { gpr_backoff_reset(&r->backoff_state); dns_start_resolving_locked(exec_ctx, r); } } static void dns_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver, grpc_channel_args **target_result, grpc_closure *on_complete) { dns_resolver *r = (dns_resolver *)resolver; GPR_ASSERT(!r->next_completion); r->next_completion = on_complete; r->target_result = target_result; if (r->resolved_version == 0 && !r->resolving) { gpr_backoff_reset(&r->backoff_state); dns_start_resolving_locked(exec_ctx, r); } else { dns_maybe_finish_next_locked(exec_ctx, r); } } static void dns_on_retry_timer_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { dns_resolver *r = arg; r->have_retry_timer = false; if (error == GRPC_ERROR_NONE) { if (!r->resolving) { dns_start_resolving_locked(exec_ctx, r); } } GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "retry-timer"); } static void dns_on_resolved_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { dns_resolver *r = arg; grpc_channel_args *result = NULL; GPR_ASSERT(r->resolving); r->resolving = false; if (r->addresses != NULL) { grpc_lb_addresses *addresses = grpc_lb_addresses_create( r->addresses->naddrs, NULL /* user_data_vtable */); for (size_t i = 0; i < r->addresses->naddrs; ++i) { grpc_lb_addresses_set_address( addresses, i, &r->addresses->addrs[i].addr, r->addresses->addrs[i].len, false /* is_balancer */, NULL /* balancer_name */, NULL /* user_data */); } grpc_arg new_arg = grpc_lb_addresses_create_channel_arg(addresses); result = grpc_channel_args_copy_and_add(r->channel_args, &new_arg, 1); grpc_resolved_addresses_destroy(r->addresses); grpc_lb_addresses_destroy(exec_ctx, addresses); } else { gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now); gpr_timespec timeout = gpr_time_sub(next_try, now); gpr_log(GPR_INFO, "dns resolution failed (will retry): %s", grpc_error_string(error)); GPR_ASSERT(!r->have_retry_timer); r->have_retry_timer = true; GRPC_RESOLVER_REF(&r->base, "retry-timer"); if (gpr_time_cmp(timeout, gpr_time_0(timeout.clock_type)) > 0) { gpr_log(GPR_DEBUG, "retrying in %" PRId64 ".%09d seconds", timeout.tv_sec, timeout.tv_nsec); } else { gpr_log(GPR_DEBUG, "retrying immediately"); } grpc_closure_init(&r->on_retry, dns_on_retry_timer_locked, r, grpc_combiner_scheduler(r->base.combiner, false)); grpc_timer_init(exec_ctx, &r->retry_timer, next_try, &r->on_retry, now); } if (r->resolved_result != NULL) { grpc_channel_args_destroy(exec_ctx, r->resolved_result); } r->resolved_result = result; r->resolved_version++; dns_maybe_finish_next_locked(exec_ctx, r); GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "dns-resolving"); } static void dns_start_resolving_locked(grpc_exec_ctx *exec_ctx, dns_resolver *r) { GRPC_RESOLVER_REF(&r->base, "dns-resolving"); GPR_ASSERT(!r->resolving); r->resolving = true; r->addresses = NULL; grpc_resolve_address( exec_ctx, r->name_to_resolve, r->default_port, r->interested_parties, grpc_closure_create(dns_on_resolved_locked, r, grpc_combiner_scheduler(r->base.combiner, false)), &r->addresses); } static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx, dns_resolver *r) { if (r->next_completion != NULL && r->resolved_version != r->published_version) { *r->target_result = r->resolved_result == NULL ? NULL : grpc_channel_args_copy(r->resolved_result); grpc_closure_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE); r->next_completion = NULL; r->published_version = r->resolved_version; } } static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) { dns_resolver *r = (dns_resolver *)gr; if (r->resolved_result != NULL) { grpc_channel_args_destroy(exec_ctx, r->resolved_result); } grpc_pollset_set_destroy(exec_ctx, r->interested_parties); gpr_free(r->name_to_resolve); gpr_free(r->default_port); grpc_channel_args_destroy(exec_ctx, r->channel_args); gpr_free(r); } static grpc_resolver *dns_create(grpc_exec_ctx *exec_ctx, grpc_resolver_args *args, const char *default_port) { if (0 != strcmp(args->uri->authority, "")) { gpr_log(GPR_ERROR, "authority based dns uri's not supported"); return NULL; } // Get name from args. char *path = args->uri->path; if (path[0] == '/') ++path; // Create resolver. dns_resolver *r = gpr_zalloc(sizeof(dns_resolver)); grpc_resolver_init(&r->base, &dns_resolver_vtable, args->combiner); r->name_to_resolve = gpr_strdup(path); r->default_port = gpr_strdup(default_port); r->channel_args = grpc_channel_args_copy(args->args); r->interested_parties = grpc_pollset_set_create(); if (args->pollset_set != NULL) { grpc_pollset_set_add_pollset_set(exec_ctx, r->interested_parties, args->pollset_set); } gpr_backoff_init(&r->backoff_state, GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS, GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER, GRPC_DNS_RECONNECT_JITTER, GRPC_DNS_MIN_CONNECT_TIMEOUT_SECONDS * 1000, GRPC_DNS_RECONNECT_MAX_BACKOFF_SECONDS * 1000); return &r->base; } /* * FACTORY */ static void dns_factory_ref(grpc_resolver_factory *factory) {} static void dns_factory_unref(grpc_resolver_factory *factory) {} static grpc_resolver *dns_factory_create_resolver( grpc_exec_ctx *exec_ctx, grpc_resolver_factory *factory, grpc_resolver_args *args) { return dns_create(exec_ctx, args, "https"); } static char *dns_factory_get_default_host_name(grpc_resolver_factory *factory, grpc_uri *uri) { const char *path = uri->path; if (path[0] == '/') ++path; return gpr_strdup(path); } static const grpc_resolver_factory_vtable dns_factory_vtable = { dns_factory_ref, dns_factory_unref, dns_factory_create_resolver, dns_factory_get_default_host_name, "dns"}; static grpc_resolver_factory dns_resolver_factory = {&dns_factory_vtable}; static grpc_resolver_factory *dns_resolver_factory_create() { return &dns_resolver_factory; } void grpc_resolver_dns_native_init(void) { char *resolver = gpr_getenv("GRPC_DNS_RESOLVER"); if (resolver != NULL && gpr_stricmp(resolver, "native") == 0) { gpr_log(GPR_DEBUG, "Using native dns resolver"); grpc_register_resolver_type(dns_resolver_factory_create()); } else { grpc_resolver_factory *existing_factory = grpc_resolver_factory_lookup("dns"); if (existing_factory == NULL) { gpr_log(GPR_DEBUG, "Using native dns resolver"); grpc_register_resolver_type(dns_resolver_factory_create()); } else { grpc_resolver_factory_unref(existing_factory); } } gpr_free(resolver); } void grpc_resolver_dns_native_shutdown(void) {} grpc-1.3.2/src/core/ext/filters/client_channel/resolver/sockaddr/000077500000000000000000000000001310511640000250275ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/filters/client_channel/resolver/sockaddr/README.md000066400000000000000000000000621310511640000263040ustar00rootroot00000000000000Support for resolving ipv4:, ipv6:, unix: schemes grpc-1.3.2/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c000066400000000000000000000217271310511640000307170ustar00rootroot00000000000000/* * * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include "src/core/ext/filters/client_channel/lb_policy_factory.h" #include "src/core/ext/filters/client_channel/parse_address.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/string.h" typedef struct { /** base class: must be first */ grpc_resolver base; /** the addresses that we've 'resolved' */ grpc_lb_addresses *addresses; /** channel args */ grpc_channel_args *channel_args; /** have we published? */ bool published; /** pending next completion, or NULL */ grpc_closure *next_completion; /** target result address for next completion */ grpc_channel_args **target_result; } sockaddr_resolver; static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r); static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx, sockaddr_resolver *r); static void sockaddr_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r); static void sockaddr_channel_saw_error_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r); static void sockaddr_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r, grpc_channel_args **target_result, grpc_closure *on_complete); static const grpc_resolver_vtable sockaddr_resolver_vtable = { sockaddr_destroy, sockaddr_shutdown_locked, sockaddr_channel_saw_error_locked, sockaddr_next_locked}; static void sockaddr_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) { sockaddr_resolver *r = (sockaddr_resolver *)resolver; if (r->next_completion != NULL) { *r->target_result = NULL; grpc_closure_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE); r->next_completion = NULL; } } static void sockaddr_channel_saw_error_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) { sockaddr_resolver *r = (sockaddr_resolver *)resolver; r->published = false; sockaddr_maybe_finish_next_locked(exec_ctx, r); } static void sockaddr_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver, grpc_channel_args **target_result, grpc_closure *on_complete) { sockaddr_resolver *r = (sockaddr_resolver *)resolver; GPR_ASSERT(!r->next_completion); r->next_completion = on_complete; r->target_result = target_result; sockaddr_maybe_finish_next_locked(exec_ctx, r); } static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx, sockaddr_resolver *r) { if (r->next_completion != NULL && !r->published) { r->published = true; grpc_arg arg = grpc_lb_addresses_create_channel_arg(r->addresses); *r->target_result = grpc_channel_args_copy_and_add(r->channel_args, &arg, 1); grpc_closure_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE); r->next_completion = NULL; } } static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) { sockaddr_resolver *r = (sockaddr_resolver *)gr; grpc_lb_addresses_destroy(exec_ctx, r->addresses); grpc_channel_args_destroy(exec_ctx, r->channel_args); gpr_free(r); } static char *ip_get_default_authority(grpc_uri *uri) { const char *path = uri->path; if (path[0] == '/') ++path; return gpr_strdup(path); } static char *ipv4_get_default_authority(grpc_resolver_factory *factory, grpc_uri *uri) { return ip_get_default_authority(uri); } static char *ipv6_get_default_authority(grpc_resolver_factory *factory, grpc_uri *uri) { return ip_get_default_authority(uri); } #ifdef GRPC_HAVE_UNIX_SOCKET char *unix_get_default_authority(grpc_resolver_factory *factory, grpc_uri *uri) { return gpr_strdup("localhost"); } #endif static void do_nothing(void *ignored) {} static grpc_resolver *sockaddr_create(grpc_exec_ctx *exec_ctx, grpc_resolver_args *args, int parse(grpc_uri *uri, grpc_resolved_address *dst)) { if (0 != strcmp(args->uri->authority, "")) { gpr_log(GPR_ERROR, "authority based uri's not supported by the %s scheme", args->uri->scheme); return NULL; } /* Construct addresses. */ grpc_slice path_slice = grpc_slice_new(args->uri->path, strlen(args->uri->path), do_nothing); grpc_slice_buffer path_parts; grpc_slice_buffer_init(&path_parts); grpc_slice_split(path_slice, ",", &path_parts); grpc_lb_addresses *addresses = grpc_lb_addresses_create(path_parts.count, NULL /* user_data_vtable */); bool errors_found = false; for (size_t i = 0; i < addresses->num_addresses; i++) { grpc_uri ith_uri = *args->uri; char *part_str = grpc_slice_to_c_string(path_parts.slices[i]); ith_uri.path = part_str; if (!parse(&ith_uri, &addresses->addresses[i].address)) { errors_found = true; /* GPR_TRUE */ } gpr_free(part_str); if (errors_found) break; } grpc_slice_buffer_destroy_internal(exec_ctx, &path_parts); grpc_slice_unref_internal(exec_ctx, path_slice); if (errors_found) { grpc_lb_addresses_destroy(exec_ctx, addresses); return NULL; } /* Instantiate resolver. */ sockaddr_resolver *r = gpr_zalloc(sizeof(sockaddr_resolver)); r->addresses = addresses; r->channel_args = grpc_channel_args_copy(args->args); grpc_resolver_init(&r->base, &sockaddr_resolver_vtable, args->combiner); return &r->base; } /* * FACTORY */ static void sockaddr_factory_ref(grpc_resolver_factory *factory) {} static void sockaddr_factory_unref(grpc_resolver_factory *factory) {} #define DECL_FACTORY(name) \ static grpc_resolver *name##_factory_create_resolver( \ grpc_exec_ctx *exec_ctx, grpc_resolver_factory *factory, \ grpc_resolver_args *args) { \ return sockaddr_create(exec_ctx, args, parse_##name); \ } \ static const grpc_resolver_factory_vtable name##_factory_vtable = { \ sockaddr_factory_ref, sockaddr_factory_unref, \ name##_factory_create_resolver, name##_get_default_authority, #name}; \ static grpc_resolver_factory name##_resolver_factory = { \ &name##_factory_vtable} #ifdef GRPC_HAVE_UNIX_SOCKET DECL_FACTORY(unix); #endif DECL_FACTORY(ipv4); DECL_FACTORY(ipv6); void grpc_resolver_sockaddr_init(void) { grpc_register_resolver_type(&ipv4_resolver_factory); grpc_register_resolver_type(&ipv6_resolver_factory); #ifdef GRPC_HAVE_UNIX_SOCKET grpc_register_resolver_type(&unix_resolver_factory); #endif } void grpc_resolver_sockaddr_shutdown(void) {} grpc-1.3.2/src/core/ext/filters/client_channel/resolver_factory.c000066400000000000000000000044531310511640000251360ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/filters/client_channel/resolver_factory.h" void grpc_resolver_factory_ref(grpc_resolver_factory* factory) { factory->vtable->ref(factory); } void grpc_resolver_factory_unref(grpc_resolver_factory* factory) { factory->vtable->unref(factory); } /** Create a resolver instance for a name */ grpc_resolver* grpc_resolver_factory_create_resolver( grpc_exec_ctx* exec_ctx, grpc_resolver_factory* factory, grpc_resolver_args* args) { if (factory == NULL) return NULL; return factory->vtable->create_resolver(exec_ctx, factory, args); } char* grpc_resolver_factory_get_default_authority( grpc_resolver_factory* factory, grpc_uri* uri) { if (factory == NULL) return NULL; return factory->vtable->get_default_authority(factory, uri); } grpc-1.3.2/src/core/ext/filters/client_channel/resolver_factory.h000066400000000000000000000067501310511640000251450ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_FACTORY_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_FACTORY_H #include "src/core/ext/filters/client_channel/client_channel_factory.h" #include "src/core/ext/filters/client_channel/resolver.h" #include "src/core/ext/filters/client_channel/uri_parser.h" #include "src/core/lib/iomgr/pollset_set.h" typedef struct grpc_resolver_factory grpc_resolver_factory; typedef struct grpc_resolver_factory_vtable grpc_resolver_factory_vtable; struct grpc_resolver_factory { const grpc_resolver_factory_vtable *vtable; }; typedef struct grpc_resolver_args { grpc_uri *uri; const grpc_channel_args *args; grpc_pollset_set *pollset_set; grpc_combiner *combiner; } grpc_resolver_args; struct grpc_resolver_factory_vtable { void (*ref)(grpc_resolver_factory *factory); void (*unref)(grpc_resolver_factory *factory); /** Implementation of grpc_resolver_factory_create_resolver */ grpc_resolver *(*create_resolver)(grpc_exec_ctx *exec_ctx, grpc_resolver_factory *factory, grpc_resolver_args *args); /** Implementation of grpc_resolver_factory_get_default_authority */ char *(*get_default_authority)(grpc_resolver_factory *factory, grpc_uri *uri); /** URI scheme that this factory implements */ const char *scheme; }; void grpc_resolver_factory_ref(grpc_resolver_factory *resolver); void grpc_resolver_factory_unref(grpc_resolver_factory *resolver); /** Create a resolver instance for a name */ grpc_resolver *grpc_resolver_factory_create_resolver( grpc_exec_ctx *exec_ctx, grpc_resolver_factory *factory, grpc_resolver_args *args); /** Return a (freshly allocated with gpr_malloc) string representing the default authority to use for this scheme. */ char *grpc_resolver_factory_get_default_authority( grpc_resolver_factory *factory, grpc_uri *uri); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_FACTORY_H */ grpc-1.3.2/src/core/ext/filters/client_channel/resolver_registry.c000066400000000000000000000147251310511640000253420ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/filters/client_channel/resolver_registry.h" #include #include #include #include #define MAX_RESOLVERS 10 #define DEFAULT_RESOLVER_PREFIX_MAX_LENGTH 32 static grpc_resolver_factory *g_all_of_the_resolvers[MAX_RESOLVERS]; static int g_number_of_resolvers = 0; static char g_default_resolver_prefix[DEFAULT_RESOLVER_PREFIX_MAX_LENGTH] = "dns:///"; void grpc_resolver_registry_init() {} void grpc_resolver_registry_shutdown(void) { for (int i = 0; i < g_number_of_resolvers; i++) { grpc_resolver_factory_unref(g_all_of_the_resolvers[i]); } // FIXME(ctiller): this should live in grpc_resolver_registry_init, // however that would have the client_channel plugin call this AFTER we start // registering resolvers from third party plugins, and so they'd never show // up. // We likely need some kind of dependency system for plugins.... what form // that takes is TBD. g_number_of_resolvers = 0; } void grpc_resolver_registry_set_default_prefix( const char *default_resolver_prefix) { const size_t len = strlen(default_resolver_prefix); GPR_ASSERT(len < DEFAULT_RESOLVER_PREFIX_MAX_LENGTH && "default resolver prefix too long"); GPR_ASSERT(len > 0 && "default resolver prefix can't be empty"); // By the previous assert, default_resolver_prefix is safe to be copied with a // plain strcpy. strcpy(g_default_resolver_prefix, default_resolver_prefix); } void grpc_register_resolver_type(grpc_resolver_factory *factory) { int i; for (i = 0; i < g_number_of_resolvers; i++) { GPR_ASSERT(0 != strcmp(factory->vtable->scheme, g_all_of_the_resolvers[i]->vtable->scheme)); } GPR_ASSERT(g_number_of_resolvers != MAX_RESOLVERS); grpc_resolver_factory_ref(factory); g_all_of_the_resolvers[g_number_of_resolvers++] = factory; } static grpc_resolver_factory *lookup_factory(const char *name) { int i; for (i = 0; i < g_number_of_resolvers; i++) { if (0 == strcmp(name, g_all_of_the_resolvers[i]->vtable->scheme)) { return g_all_of_the_resolvers[i]; } } return NULL; } grpc_resolver_factory *grpc_resolver_factory_lookup(const char *name) { grpc_resolver_factory *f = lookup_factory(name); if (f) grpc_resolver_factory_ref(f); return f; } static grpc_resolver_factory *lookup_factory_by_uri(grpc_uri *uri) { if (!uri) return NULL; return lookup_factory(uri->scheme); } static grpc_resolver_factory *resolve_factory(grpc_exec_ctx *exec_ctx, const char *target, grpc_uri **uri, char **canonical_target) { grpc_resolver_factory *factory = NULL; GPR_ASSERT(uri != NULL); *uri = grpc_uri_parse(exec_ctx, target, 1); factory = lookup_factory_by_uri(*uri); if (factory == NULL) { grpc_uri_destroy(*uri); gpr_asprintf(canonical_target, "%s%s", g_default_resolver_prefix, target); *uri = grpc_uri_parse(exec_ctx, *canonical_target, 1); factory = lookup_factory_by_uri(*uri); if (factory == NULL) { grpc_uri_destroy(grpc_uri_parse(exec_ctx, target, 0)); grpc_uri_destroy(grpc_uri_parse(exec_ctx, *canonical_target, 0)); gpr_log(GPR_ERROR, "don't know how to resolve '%s' or '%s'", target, *canonical_target); } } return factory; } grpc_resolver *grpc_resolver_create(grpc_exec_ctx *exec_ctx, const char *target, const grpc_channel_args *args, grpc_pollset_set *pollset_set, grpc_combiner *combiner) { grpc_uri *uri = NULL; char *canonical_target = NULL; grpc_resolver_factory *factory = resolve_factory(exec_ctx, target, &uri, &canonical_target); grpc_resolver *resolver; grpc_resolver_args resolver_args; memset(&resolver_args, 0, sizeof(resolver_args)); resolver_args.uri = uri; resolver_args.args = args; resolver_args.pollset_set = pollset_set; resolver_args.combiner = combiner; resolver = grpc_resolver_factory_create_resolver(exec_ctx, factory, &resolver_args); grpc_uri_destroy(uri); gpr_free(canonical_target); return resolver; } char *grpc_get_default_authority(grpc_exec_ctx *exec_ctx, const char *target) { grpc_uri *uri = NULL; char *canonical_target = NULL; grpc_resolver_factory *factory = resolve_factory(exec_ctx, target, &uri, &canonical_target); char *authority = grpc_resolver_factory_get_default_authority(factory, uri); grpc_uri_destroy(uri); gpr_free(canonical_target); return authority; } char *grpc_resolver_factory_add_default_prefix_if_needed( grpc_exec_ctx *exec_ctx, const char *target) { grpc_uri *uri = NULL; char *canonical_target = NULL; resolve_factory(exec_ctx, target, &uri, &canonical_target); grpc_uri_destroy(uri); return canonical_target == NULL ? gpr_strdup(target) : canonical_target; } grpc-1.3.2/src/core/ext/filters/client_channel/resolver_registry.h000066400000000000000000000077431310511640000253510ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_REGISTRY_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_REGISTRY_H #include "src/core/ext/filters/client_channel/resolver_factory.h" #include "src/core/lib/iomgr/pollset_set.h" void grpc_resolver_registry_init(); void grpc_resolver_registry_shutdown(void); /** Set the default URI prefix to \a default_prefix. */ void grpc_resolver_registry_set_default_prefix(const char *default_prefix); /** Register a resolver type. URI's of \a scheme will be resolved with the given resolver. If \a priority is greater than zero, then the resolver will be eligible to resolve names that are passed in with no scheme. Higher priority resolvers will be tried before lower priority schemes. */ void grpc_register_resolver_type(grpc_resolver_factory *factory); /** Create a resolver given \a target. First tries to parse \a target as a URI. If this succeeds, tries to locate a registered resolver factory based on the URI scheme. If parsing or location fails, prefixes default_prefix from grpc_resolver_registry_init to target, and tries again (if default_prefix was not NULL). If a resolver factory was found, use it to instantiate a resolver and return it. If a resolver factory was not found, return NULL. \a args is a set of channel arguments to be included in the result (typically the set of arguments passed in from the client API). \a pollset_set is used to drive IO in the name resolution process, it should not be NULL. */ grpc_resolver *grpc_resolver_create(grpc_exec_ctx *exec_ctx, const char *target, const grpc_channel_args *args, grpc_pollset_set *pollset_set, grpc_combiner *combiner); /** Find a resolver factory given a name and return an (owned-by-the-caller) * reference to it */ grpc_resolver_factory *grpc_resolver_factory_lookup(const char *name); /** Given a target, return a (freshly allocated with gpr_malloc) string representing the default authority to pass from a client. */ char *grpc_get_default_authority(grpc_exec_ctx *exec_ctx, const char *target); /** Returns a newly allocated string containing \a target, adding the default prefix if needed. */ char *grpc_resolver_factory_add_default_prefix_if_needed( grpc_exec_ctx *exec_ctx, const char *target); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_REGISTRY_H */ grpc-1.3.2/src/core/ext/filters/client_channel/retry_throttle.c000066400000000000000000000174661310511640000246500ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/filters/client_channel/retry_throttle.h" #include #include #include #include #include #include #include // // server_retry_throttle_data // struct grpc_server_retry_throttle_data { gpr_refcount refs; int max_milli_tokens; int milli_token_ratio; gpr_atm milli_tokens; // A pointer to the replacement for this grpc_server_retry_throttle_data // entry. If non-NULL, then this entry is stale and must not be used. // We hold a reference to the replacement. gpr_atm replacement; }; static void get_replacement_throttle_data_if_needed( grpc_server_retry_throttle_data** throttle_data) { while (true) { grpc_server_retry_throttle_data* new_throttle_data = (grpc_server_retry_throttle_data*)gpr_atm_acq_load( &(*throttle_data)->replacement); if (new_throttle_data == NULL) return; *throttle_data = new_throttle_data; } } bool grpc_server_retry_throttle_data_record_failure( grpc_server_retry_throttle_data* throttle_data) { // First, check if we are stale and need to be replaced. get_replacement_throttle_data_if_needed(&throttle_data); // We decrement milli_tokens by 1000 (1 token) for each failure. const int new_value = (int)gpr_atm_no_barrier_clamped_add( &throttle_data->milli_tokens, (gpr_atm)-1000, (gpr_atm)0, (gpr_atm)throttle_data->max_milli_tokens); // Retries are allowed as long as the new value is above the threshold // (max_milli_tokens / 2). return new_value > throttle_data->max_milli_tokens / 2; } void grpc_server_retry_throttle_data_record_success( grpc_server_retry_throttle_data* throttle_data) { // First, check if we are stale and need to be replaced. get_replacement_throttle_data_if_needed(&throttle_data); // We increment milli_tokens by milli_token_ratio for each success. gpr_atm_no_barrier_clamped_add( &throttle_data->milli_tokens, (gpr_atm)throttle_data->milli_token_ratio, (gpr_atm)0, (gpr_atm)throttle_data->max_milli_tokens); } grpc_server_retry_throttle_data* grpc_server_retry_throttle_data_ref( grpc_server_retry_throttle_data* throttle_data) { gpr_ref(&throttle_data->refs); return throttle_data; } void grpc_server_retry_throttle_data_unref( grpc_server_retry_throttle_data* throttle_data) { if (gpr_unref(&throttle_data->refs)) { grpc_server_retry_throttle_data* replacement = (grpc_server_retry_throttle_data*)gpr_atm_acq_load( &throttle_data->replacement); if (replacement != NULL) { grpc_server_retry_throttle_data_unref(replacement); } gpr_free(throttle_data); } } static grpc_server_retry_throttle_data* grpc_server_retry_throttle_data_create( int max_milli_tokens, int milli_token_ratio, grpc_server_retry_throttle_data* old_throttle_data) { grpc_server_retry_throttle_data* throttle_data = gpr_malloc(sizeof(*throttle_data)); memset(throttle_data, 0, sizeof(*throttle_data)); gpr_ref_init(&throttle_data->refs, 1); throttle_data->max_milli_tokens = max_milli_tokens; throttle_data->milli_token_ratio = milli_token_ratio; int initial_milli_tokens = max_milli_tokens; // If there was a pre-existing entry for this server name, initialize // the token count by scaling proportionately to the old data. This // ensures that if we're already throttling retries on the old scale, // we will start out doing the same thing on the new one. if (old_throttle_data != NULL) { double token_fraction = (int)gpr_atm_acq_load(&old_throttle_data->milli_tokens) / (double)old_throttle_data->max_milli_tokens; initial_milli_tokens = (int)(token_fraction * max_milli_tokens); } gpr_atm_rel_store(&throttle_data->milli_tokens, (gpr_atm)initial_milli_tokens); // If there was a pre-existing entry, mark it as stale and give it a // pointer to the new entry, which is its replacement. if (old_throttle_data != NULL) { grpc_server_retry_throttle_data_ref(throttle_data); gpr_atm_rel_store(&old_throttle_data->replacement, (gpr_atm)throttle_data); } return throttle_data; } // // avl vtable for string -> server_retry_throttle_data map // static void* copy_server_name(void* key) { return gpr_strdup(key); } static long compare_server_name(void* key1, void* key2) { return strcmp(key1, key2); } static void destroy_server_retry_throttle_data(void* value) { grpc_server_retry_throttle_data* throttle_data = value; grpc_server_retry_throttle_data_unref(throttle_data); } static void* copy_server_retry_throttle_data(void* value) { grpc_server_retry_throttle_data* throttle_data = value; return grpc_server_retry_throttle_data_ref(throttle_data); } static const gpr_avl_vtable avl_vtable = { gpr_free /* destroy_key */, copy_server_name, compare_server_name, destroy_server_retry_throttle_data, copy_server_retry_throttle_data}; // // server_retry_throttle_map // static gpr_mu g_mu; static gpr_avl g_avl; void grpc_retry_throttle_map_init() { gpr_mu_init(&g_mu); g_avl = gpr_avl_create(&avl_vtable); } void grpc_retry_throttle_map_shutdown() { gpr_mu_destroy(&g_mu); gpr_avl_unref(g_avl); } grpc_server_retry_throttle_data* grpc_retry_throttle_map_get_data_for_server( const char* server_name, int max_milli_tokens, int milli_token_ratio) { gpr_mu_lock(&g_mu); grpc_server_retry_throttle_data* throttle_data = gpr_avl_get(g_avl, (char*)server_name); if (throttle_data == NULL) { // Entry not found. Create a new one. throttle_data = grpc_server_retry_throttle_data_create( max_milli_tokens, milli_token_ratio, NULL); g_avl = gpr_avl_add(g_avl, (char*)server_name, throttle_data); } else { if (throttle_data->max_milli_tokens != max_milli_tokens || throttle_data->milli_token_ratio != milli_token_ratio) { // Entry found but with old parameters. Create a new one based on // the original one. throttle_data = grpc_server_retry_throttle_data_create( max_milli_tokens, milli_token_ratio, throttle_data); g_avl = gpr_avl_add(g_avl, (char*)server_name, throttle_data); } else { // Entry found. Increase refcount. grpc_server_retry_throttle_data_ref(throttle_data); } } gpr_mu_unlock(&g_mu); return throttle_data; } grpc-1.3.2/src/core/ext/filters/client_channel/retry_throttle.h000066400000000000000000000056641310511640000246520ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RETRY_THROTTLE_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RETRY_THROTTLE_H #include /// Tracks retry throttling data for an individual server name. typedef struct grpc_server_retry_throttle_data grpc_server_retry_throttle_data; /// Records a failure. Returns true if it's okay to send a retry. bool grpc_server_retry_throttle_data_record_failure( grpc_server_retry_throttle_data* throttle_data); /// Records a success. void grpc_server_retry_throttle_data_record_success( grpc_server_retry_throttle_data* throttle_data); grpc_server_retry_throttle_data* grpc_server_retry_throttle_data_ref( grpc_server_retry_throttle_data* throttle_data); void grpc_server_retry_throttle_data_unref( grpc_server_retry_throttle_data* throttle_data); /// Initializes global map of failure data for each server name. void grpc_retry_throttle_map_init(); /// Shuts down global map of failure data for each server name. void grpc_retry_throttle_map_shutdown(); /// Returns a reference to the failure data for \a server_name, creating /// a new entry if needed. /// Caller must eventually unref via \a grpc_server_retry_throttle_data_unref(). grpc_server_retry_throttle_data* grpc_retry_throttle_map_get_data_for_server( const char* server_name, int max_milli_tokens, int milli_token_ratio); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RETRY_THROTTLE_H */ grpc-1.3.2/src/core/ext/filters/client_channel/subchannel.c000066400000000000000000000766261310511640000237030ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/filters/client_channel/subchannel.h" #include #include #include #include #include #include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/filters/client_channel/parse_address.h" #include "src/core/ext/filters/client_channel/proxy_mapper_registry.h" #include "src/core/ext/filters/client_channel/subchannel_index.h" #include "src/core/ext/filters/client_channel/uri_parser.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/support/backoff.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/channel_init.h" #include "src/core/lib/transport/connectivity_state.h" #define INTERNAL_REF_BITS 16 #define STRONG_REF_MASK (~(gpr_atm)((1 << INTERNAL_REF_BITS) - 1)) #define GRPC_SUBCHANNEL_MIN_CONNECT_TIMEOUT_SECONDS 20 #define GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS 1 #define GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER 1.6 #define GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS 120 #define GRPC_SUBCHANNEL_RECONNECT_JITTER 0.2 #define GET_CONNECTED_SUBCHANNEL(subchannel, barrier) \ ((grpc_connected_subchannel *)(gpr_atm_##barrier##_load( \ &(subchannel)->connected_subchannel))) typedef struct { grpc_closure closure; grpc_subchannel *subchannel; grpc_connectivity_state connectivity_state; } state_watcher; typedef struct external_state_watcher { grpc_subchannel *subchannel; grpc_pollset_set *pollset_set; grpc_closure *notify; grpc_closure closure; struct external_state_watcher *next; struct external_state_watcher *prev; } external_state_watcher; struct grpc_subchannel { grpc_connector *connector; /** refcount - lower INTERNAL_REF_BITS bits are for internal references: these do not keep the subchannel open. - upper remaining bits are for public references: these do keep the subchannel open */ gpr_atm ref_pair; /** non-transport related channel filters */ const grpc_channel_filter **filters; size_t num_filters; /** channel arguments */ grpc_channel_args *args; grpc_subchannel_key *key; /** set during connection */ grpc_connect_out_args connecting_result; /** callback for connection finishing */ grpc_closure connected; /** callback for our alarm */ grpc_closure on_alarm; /** pollset_set tracking who's interested in a connection being setup */ grpc_pollset_set *pollset_set; /** active connection, or null; of type grpc_connected_subchannel */ gpr_atm connected_subchannel; /** mutex protecting remaining elements */ gpr_mu mu; /** have we seen a disconnection? */ bool disconnected; /** are we connecting */ bool connecting; /** connectivity state tracking */ grpc_connectivity_state_tracker state_tracker; external_state_watcher root_external_state_watcher; /** next connect attempt time */ gpr_timespec next_attempt; /** backoff state */ gpr_backoff backoff_state; /** do we have an active alarm? */ bool have_alarm; /** have we started the backoff loop */ bool backoff_begun; /** our alarm */ grpc_timer alarm; }; struct grpc_subchannel_call { grpc_connected_subchannel *connection; grpc_closure *schedule_closure_after_destroy; }; #define SUBCHANNEL_CALL_TO_CALL_STACK(call) ((grpc_call_stack *)((call) + 1)) #define CHANNEL_STACK_FROM_CONNECTION(con) ((grpc_channel_stack *)(con)) #define CALLSTACK_TO_SUBCHANNEL_CALL(callstack) \ (((grpc_subchannel_call *)(callstack)) - 1) static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *subchannel, grpc_error *error); #ifdef GRPC_STREAM_REFCOUNT_DEBUG #define REF_REASON reason #define REF_LOG(name, p) \ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "%s: %p ref %d -> %d %s", \ (name), (p), (p)->refs.count, (p)->refs.count + 1, reason) #define UNREF_LOG(name, p) \ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "%s: %p unref %d -> %d %s", \ (name), (p), (p)->refs.count, (p)->refs.count - 1, reason) #define REF_MUTATE_EXTRA_ARGS \ GRPC_SUBCHANNEL_REF_EXTRA_ARGS, const char *purpose #define REF_MUTATE_PURPOSE(x) , file, line, reason, x #else #define REF_REASON "" #define REF_LOG(name, p) \ do { \ } while (0) #define UNREF_LOG(name, p) \ do { \ } while (0) #define REF_MUTATE_EXTRA_ARGS #define REF_MUTATE_PURPOSE(x) #endif /* * connection implementation */ static void connection_destroy(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_connected_subchannel *c = arg; grpc_channel_stack_destroy(exec_ctx, CHANNEL_STACK_FROM_CONNECTION(c)); gpr_free(c); } grpc_connected_subchannel *grpc_connected_subchannel_ref( grpc_connected_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { GRPC_CHANNEL_STACK_REF(CHANNEL_STACK_FROM_CONNECTION(c), REF_REASON); return c; } void grpc_connected_subchannel_unref(grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { GRPC_CHANNEL_STACK_UNREF(exec_ctx, CHANNEL_STACK_FROM_CONNECTION(c), REF_REASON); } /* * grpc_subchannel implementation */ static void subchannel_destroy(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_subchannel *c = arg; gpr_free((void *)c->filters); grpc_channel_args_destroy(exec_ctx, c->args); grpc_connectivity_state_destroy(exec_ctx, &c->state_tracker); grpc_connector_unref(exec_ctx, c->connector); grpc_pollset_set_destroy(exec_ctx, c->pollset_set); grpc_subchannel_key_destroy(exec_ctx, c->key); gpr_free(c); } static gpr_atm ref_mutate(grpc_subchannel *c, gpr_atm delta, int barrier REF_MUTATE_EXTRA_ARGS) { gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&c->ref_pair, delta) : gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta); #ifdef GRPC_STREAM_REFCOUNT_DEBUG gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SUBCHANNEL: %p %s 0x%08" PRIxPTR " -> 0x%08" PRIxPTR " [%s]", c, purpose, old_val, old_val + delta, reason); #endif return old_val; } grpc_subchannel *grpc_subchannel_ref( grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { gpr_atm old_refs; old_refs = ref_mutate(c, (1 << INTERNAL_REF_BITS), 0 REF_MUTATE_PURPOSE("STRONG_REF")); GPR_ASSERT((old_refs & STRONG_REF_MASK) != 0); return c; } grpc_subchannel *grpc_subchannel_weak_ref( grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { gpr_atm old_refs; old_refs = ref_mutate(c, 1, 0 REF_MUTATE_PURPOSE("WEAK_REF")); GPR_ASSERT(old_refs != 0); return c; } grpc_subchannel *grpc_subchannel_ref_from_weak_ref( grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { if (!c) return NULL; for (;;) { gpr_atm old_refs = gpr_atm_acq_load(&c->ref_pair); if (old_refs >= (1 << INTERNAL_REF_BITS)) { gpr_atm new_refs = old_refs + (1 << INTERNAL_REF_BITS); if (gpr_atm_rel_cas(&c->ref_pair, old_refs, new_refs)) { return c; } } else { return NULL; } } } static void disconnect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) { grpc_connected_subchannel *con; grpc_subchannel_index_unregister(exec_ctx, c->key, c); gpr_mu_lock(&c->mu); GPR_ASSERT(!c->disconnected); c->disconnected = true; grpc_connector_shutdown( exec_ctx, c->connector, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Subchannel disconnected")); con = GET_CONNECTED_SUBCHANNEL(c, no_barrier); if (con != NULL) { GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, con, "connection"); gpr_atm_no_barrier_store(&c->connected_subchannel, (gpr_atm)0xdeadbeef); } gpr_mu_unlock(&c->mu); } void grpc_subchannel_unref(grpc_exec_ctx *exec_ctx, grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { gpr_atm old_refs; old_refs = ref_mutate(c, (gpr_atm)1 - (gpr_atm)(1 << INTERNAL_REF_BITS), 1 REF_MUTATE_PURPOSE("STRONG_UNREF")); if ((old_refs & STRONG_REF_MASK) == (1 << INTERNAL_REF_BITS)) { disconnect(exec_ctx, c); } GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "strong-unref"); } void grpc_subchannel_weak_unref(grpc_exec_ctx *exec_ctx, grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { gpr_atm old_refs; old_refs = ref_mutate(c, -(gpr_atm)1, 1 REF_MUTATE_PURPOSE("WEAK_UNREF")); if (old_refs == 1) { grpc_closure_sched(exec_ctx, grpc_closure_create(subchannel_destroy, c, grpc_schedule_on_exec_ctx), GRPC_ERROR_NONE); } } grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx, grpc_connector *connector, const grpc_subchannel_args *args) { grpc_subchannel_key *key = grpc_subchannel_key_create(connector, args); grpc_subchannel *c = grpc_subchannel_index_find(exec_ctx, key); if (c) { grpc_subchannel_key_destroy(exec_ctx, key); return c; } c = gpr_zalloc(sizeof(*c)); c->key = key; gpr_atm_no_barrier_store(&c->ref_pair, 1 << INTERNAL_REF_BITS); c->connector = connector; grpc_connector_ref(c->connector); c->num_filters = args->filter_count; if (c->num_filters > 0) { c->filters = gpr_malloc(sizeof(grpc_channel_filter *) * c->num_filters); memcpy((void *)c->filters, args->filters, sizeof(grpc_channel_filter *) * c->num_filters); } else { c->filters = NULL; } c->pollset_set = grpc_pollset_set_create(); grpc_resolved_address *addr = gpr_malloc(sizeof(*addr)); grpc_get_subchannel_address_arg(exec_ctx, args->args, addr); grpc_resolved_address *new_address = NULL; grpc_channel_args *new_args = NULL; if (grpc_proxy_mappers_map_address(exec_ctx, addr, args->args, &new_address, &new_args)) { GPR_ASSERT(new_address != NULL); gpr_free(addr); addr = new_address; } static const char *keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS}; grpc_arg new_arg = grpc_create_subchannel_address_arg(addr); gpr_free(addr); c->args = grpc_channel_args_copy_and_add_and_remove( new_args != NULL ? new_args : args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &new_arg, 1); gpr_free(new_arg.value.string); if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args); c->root_external_state_watcher.next = c->root_external_state_watcher.prev = &c->root_external_state_watcher; grpc_closure_init(&c->connected, subchannel_connected, c, grpc_schedule_on_exec_ctx); grpc_connectivity_state_init(&c->state_tracker, GRPC_CHANNEL_IDLE, "subchannel"); int initial_backoff_ms = GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000; int max_backoff_ms = GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS * 1000; int min_backoff_ms = GRPC_SUBCHANNEL_MIN_CONNECT_TIMEOUT_SECONDS * 1000; bool fixed_reconnect_backoff = false; if (c->args) { for (size_t i = 0; i < c->args->num_args; i++) { if (0 == strcmp(c->args->args[i].key, "grpc.testing.fixed_reconnect_backoff_ms")) { fixed_reconnect_backoff = true; initial_backoff_ms = min_backoff_ms = max_backoff_ms = grpc_channel_arg_get_integer( &c->args->args[i], (grpc_integer_options){initial_backoff_ms, 100, INT_MAX}); } else if (0 == strcmp(c->args->args[i].key, GRPC_ARG_MAX_RECONNECT_BACKOFF_MS)) { fixed_reconnect_backoff = false; max_backoff_ms = grpc_channel_arg_get_integer( &c->args->args[i], (grpc_integer_options){max_backoff_ms, 100, INT_MAX}); } else if (0 == strcmp(c->args->args[i].key, GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS)) { fixed_reconnect_backoff = false; initial_backoff_ms = grpc_channel_arg_get_integer( &c->args->args[i], (grpc_integer_options){initial_backoff_ms, 100, INT_MAX}); } } } gpr_backoff_init( &c->backoff_state, initial_backoff_ms, fixed_reconnect_backoff ? 1.0 : GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER, fixed_reconnect_backoff ? 0.0 : GRPC_SUBCHANNEL_RECONNECT_JITTER, min_backoff_ms, max_backoff_ms); gpr_mu_init(&c->mu); return grpc_subchannel_index_register(exec_ctx, key, c); } static void continue_connect_locked(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) { grpc_connect_in_args args; args.interested_parties = c->pollset_set; args.deadline = c->next_attempt; args.channel_args = c->args; grpc_connectivity_state_set(exec_ctx, &c->state_tracker, GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE, "state_change"); grpc_connector_connect(exec_ctx, c->connector, &args, &c->connecting_result, &c->connected); } grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel *c, grpc_error **error) { grpc_connectivity_state state; gpr_mu_lock(&c->mu); state = grpc_connectivity_state_get(&c->state_tracker, error); gpr_mu_unlock(&c->mu); return state; } static void on_external_state_watcher_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { external_state_watcher *w = arg; grpc_closure *follow_up = w->notify; if (w->pollset_set != NULL) { grpc_pollset_set_del_pollset_set(exec_ctx, w->subchannel->pollset_set, w->pollset_set); } gpr_mu_lock(&w->subchannel->mu); w->next->prev = w->prev; w->prev->next = w->next; gpr_mu_unlock(&w->subchannel->mu); GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, w->subchannel, "external_state_watcher"); gpr_free(w); grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error)); } static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_subchannel *c = arg; gpr_mu_lock(&c->mu); c->have_alarm = false; if (c->disconnected) { error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Disconnected", &error, 1); } else { GRPC_ERROR_REF(error); } if (error == GRPC_ERROR_NONE) { gpr_log(GPR_INFO, "Failed to connect to channel, retrying"); c->next_attempt = gpr_backoff_step(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC)); continue_connect_locked(exec_ctx, c); gpr_mu_unlock(&c->mu); } else { gpr_mu_unlock(&c->mu); GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting"); } GRPC_ERROR_UNREF(error); } static void maybe_start_connecting_locked(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) { if (c->disconnected) { /* Don't try to connect if we're already disconnected */ return; } if (c->connecting) { /* Already connecting: don't restart */ return; } if (GET_CONNECTED_SUBCHANNEL(c, no_barrier) != NULL) { /* Already connected: don't restart */ return; } if (!grpc_connectivity_state_has_watchers(&c->state_tracker)) { /* Nobody is interested in connecting: so don't just yet */ return; } c->connecting = true; GRPC_SUBCHANNEL_WEAK_REF(c, "connecting"); gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); if (!c->backoff_begun) { c->backoff_begun = true; c->next_attempt = gpr_backoff_begin(&c->backoff_state, now); continue_connect_locked(exec_ctx, c); } else { GPR_ASSERT(!c->have_alarm); c->have_alarm = true; gpr_timespec time_til_next = gpr_time_sub(c->next_attempt, now); if (gpr_time_cmp(time_til_next, gpr_time_0(time_til_next.clock_type)) <= 0) { gpr_log(GPR_INFO, "Retry immediately"); } else { gpr_log(GPR_INFO, "Retry in %" PRId64 ".%09d seconds", time_til_next.tv_sec, time_til_next.tv_nsec); } grpc_closure_init(&c->on_alarm, on_alarm, c, grpc_schedule_on_exec_ctx); grpc_timer_init(exec_ctx, &c->alarm, c->next_attempt, &c->on_alarm, now); } } void grpc_subchannel_notify_on_state_change( grpc_exec_ctx *exec_ctx, grpc_subchannel *c, grpc_pollset_set *interested_parties, grpc_connectivity_state *state, grpc_closure *notify) { external_state_watcher *w; if (state == NULL) { gpr_mu_lock(&c->mu); for (w = c->root_external_state_watcher.next; w != &c->root_external_state_watcher; w = w->next) { if (w->notify == notify) { grpc_connectivity_state_notify_on_state_change( exec_ctx, &c->state_tracker, NULL, &w->closure); } } gpr_mu_unlock(&c->mu); } else { w = gpr_malloc(sizeof(*w)); w->subchannel = c; w->pollset_set = interested_parties; w->notify = notify; grpc_closure_init(&w->closure, on_external_state_watcher_done, w, grpc_schedule_on_exec_ctx); if (interested_parties != NULL) { grpc_pollset_set_add_pollset_set(exec_ctx, c->pollset_set, interested_parties); } GRPC_SUBCHANNEL_WEAK_REF(c, "external_state_watcher"); gpr_mu_lock(&c->mu); w->next = &c->root_external_state_watcher; w->prev = w->next->prev; w->next->prev = w->prev->next = w; grpc_connectivity_state_notify_on_state_change(exec_ctx, &c->state_tracker, state, &w->closure); maybe_start_connecting_locked(exec_ctx, c); gpr_mu_unlock(&c->mu); } } void grpc_connected_subchannel_process_transport_op( grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con, grpc_transport_op *op) { grpc_channel_stack *channel_stack = CHANNEL_STACK_FROM_CONNECTION(con); grpc_channel_element *top_elem = grpc_channel_stack_element(channel_stack, 0); top_elem->filter->start_transport_op(exec_ctx, top_elem, op); } static void subchannel_on_child_state_changed(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) { state_watcher *sw = p; grpc_subchannel *c = sw->subchannel; gpr_mu *mu = &c->mu; gpr_mu_lock(mu); /* if we failed just leave this closure */ if (sw->connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) { /* any errors on a subchannel ==> we're done, create a new one */ sw->connectivity_state = GRPC_CHANNEL_SHUTDOWN; } grpc_connectivity_state_set(exec_ctx, &c->state_tracker, sw->connectivity_state, GRPC_ERROR_REF(error), "reflect_child"); if (sw->connectivity_state != GRPC_CHANNEL_SHUTDOWN) { grpc_connected_subchannel_notify_on_state_change( exec_ctx, GET_CONNECTED_SUBCHANNEL(c, no_barrier), NULL, &sw->connectivity_state, &sw->closure); GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher"); sw = NULL; } gpr_mu_unlock(mu); GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "state_watcher"); gpr_free(sw); } static void connected_subchannel_state_op(grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con, grpc_pollset_set *interested_parties, grpc_connectivity_state *state, grpc_closure *closure) { grpc_transport_op *op = grpc_make_transport_op(NULL); grpc_channel_element *elem; op->connectivity_state = state; op->on_connectivity_state_change = closure; op->bind_pollset_set = interested_parties; elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0); elem->filter->start_transport_op(exec_ctx, elem, op); } void grpc_connected_subchannel_notify_on_state_change( grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con, grpc_pollset_set *interested_parties, grpc_connectivity_state *state, grpc_closure *closure) { connected_subchannel_state_op(exec_ctx, con, interested_parties, state, closure); } void grpc_connected_subchannel_ping(grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con, grpc_closure *closure) { grpc_transport_op *op = grpc_make_transport_op(NULL); grpc_channel_element *elem; op->send_ping = closure; elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0); elem->filter->start_transport_op(exec_ctx, elem, op); } static void publish_transport_locked(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) { grpc_connected_subchannel *con; grpc_channel_stack *stk; state_watcher *sw_subchannel; /* construct channel stack */ grpc_channel_stack_builder *builder = grpc_channel_stack_builder_create(); grpc_channel_stack_builder_set_channel_arguments( exec_ctx, builder, c->connecting_result.channel_args); grpc_channel_stack_builder_set_transport(builder, c->connecting_result.transport); if (!grpc_channel_init_create_stack(exec_ctx, builder, GRPC_CLIENT_SUBCHANNEL)) { grpc_channel_stack_builder_destroy(exec_ctx, builder); abort(); /* TODO(ctiller): what to do here (previously we just crashed) */ } grpc_error *error = grpc_channel_stack_builder_finish( exec_ctx, builder, 0, 1, connection_destroy, NULL, (void **)&con); if (error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "error initializing subchannel stack: %s", grpc_error_string(error)); GRPC_ERROR_UNREF(error); abort(); /* TODO(ctiller): what to do here? */ } stk = CHANNEL_STACK_FROM_CONNECTION(con); memset(&c->connecting_result, 0, sizeof(c->connecting_result)); /* initialize state watcher */ sw_subchannel = gpr_malloc(sizeof(*sw_subchannel)); sw_subchannel->subchannel = c; sw_subchannel->connectivity_state = GRPC_CHANNEL_READY; grpc_closure_init(&sw_subchannel->closure, subchannel_on_child_state_changed, sw_subchannel, grpc_schedule_on_exec_ctx); if (c->disconnected) { gpr_free(sw_subchannel); grpc_channel_stack_destroy(exec_ctx, stk); gpr_free(con); GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting"); return; } /* publish */ /* TODO(ctiller): this full barrier seems to clear up a TSAN failure. I'd have expected the rel_cas below to be enough, but seemingly it's not. Re-evaluate if we really need this. */ gpr_atm_full_barrier(); GPR_ASSERT(gpr_atm_rel_cas(&c->connected_subchannel, 0, (gpr_atm)con)); /* setup subchannel watching connected subchannel for changes; subchannel ref for connecting is donated to the state watcher */ GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher"); GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting"); grpc_connected_subchannel_notify_on_state_change( exec_ctx, con, c->pollset_set, &sw_subchannel->connectivity_state, &sw_subchannel->closure); /* signal completion */ grpc_connectivity_state_set(exec_ctx, &c->state_tracker, GRPC_CHANNEL_READY, GRPC_ERROR_NONE, "connected"); } static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_subchannel *c = arg; grpc_channel_args *delete_channel_args = c->connecting_result.channel_args; GRPC_SUBCHANNEL_WEAK_REF(c, "connected"); gpr_mu_lock(&c->mu); c->connecting = false; if (c->connecting_result.transport != NULL) { publish_transport_locked(exec_ctx, c); } else if (c->disconnected) { GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting"); } else { grpc_connectivity_state_set( exec_ctx, &c->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Connect Failed", &error, 1), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), "connect_failed"); const char *errmsg = grpc_error_string(error); gpr_log(GPR_INFO, "Connect failed: %s", errmsg); maybe_start_connecting_locked(exec_ctx, c); GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting"); } gpr_mu_unlock(&c->mu); GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connected"); grpc_channel_args_destroy(exec_ctx, delete_channel_args); } /* * grpc_subchannel_call implementation */ static void subchannel_call_destroy(grpc_exec_ctx *exec_ctx, void *call, grpc_error *error) { grpc_subchannel_call *c = call; GPR_ASSERT(c->schedule_closure_after_destroy != NULL); GPR_TIMER_BEGIN("grpc_subchannel_call_unref.destroy", 0); grpc_connected_subchannel *connection = c->connection; grpc_call_stack_destroy(exec_ctx, SUBCHANNEL_CALL_TO_CALL_STACK(c), NULL, c->schedule_closure_after_destroy); GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, connection, "subchannel_call"); GPR_TIMER_END("grpc_subchannel_call_unref.destroy", 0); } void grpc_subchannel_call_set_cleanup_closure(grpc_subchannel_call *call, grpc_closure *closure) { GPR_ASSERT(call->schedule_closure_after_destroy == NULL); GPR_ASSERT(closure != NULL); call->schedule_closure_after_destroy = closure; } void grpc_subchannel_call_ref( grpc_subchannel_call *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON); } void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx, grpc_subchannel_call *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { GRPC_CALL_STACK_UNREF(exec_ctx, SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON); } char *grpc_subchannel_call_get_peer(grpc_exec_ctx *exec_ctx, grpc_subchannel_call *call) { grpc_call_stack *call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call); grpc_call_element *top_elem = grpc_call_stack_element(call_stack, 0); return top_elem->filter->get_peer(exec_ctx, top_elem); } void grpc_subchannel_call_process_op(grpc_exec_ctx *exec_ctx, grpc_subchannel_call *call, grpc_transport_stream_op_batch *op) { GPR_TIMER_BEGIN("grpc_subchannel_call_process_op", 0); grpc_call_stack *call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call); grpc_call_element *top_elem = grpc_call_stack_element(call_stack, 0); top_elem->filter->start_transport_stream_op_batch(exec_ctx, top_elem, op); GPR_TIMER_END("grpc_subchannel_call_process_op", 0); } grpc_connected_subchannel *grpc_subchannel_get_connected_subchannel( grpc_subchannel *c) { return GET_CONNECTED_SUBCHANNEL(c, acq); } grpc_error *grpc_connected_subchannel_create_call( grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con, const grpc_connected_subchannel_call_args *args, grpc_subchannel_call **call) { grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con); *call = gpr_arena_alloc( args->arena, sizeof(grpc_subchannel_call) + chanstk->call_stack_size); grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call); (*call)->connection = GRPC_CONNECTED_SUBCHANNEL_REF(con, "subchannel_call"); const grpc_call_element_args call_args = {.call_stack = callstk, .server_transport_data = NULL, .context = NULL, .path = args->path, .start_time = args->start_time, .deadline = args->deadline, .arena = args->arena}; grpc_error *error = grpc_call_stack_init( exec_ctx, chanstk, 1, subchannel_call_destroy, *call, &call_args); if (error != GRPC_ERROR_NONE) { const char *error_string = grpc_error_string(error); gpr_log(GPR_ERROR, "error: %s", error_string); return error; } grpc_call_stack_set_pollset_or_pollset_set(exec_ctx, callstk, args->pollent); return GRPC_ERROR_NONE; } grpc_call_stack *grpc_subchannel_call_get_call_stack( grpc_subchannel_call *subchannel_call) { return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call); } static void grpc_uri_to_sockaddr(grpc_exec_ctx *exec_ctx, const char *uri_str, grpc_resolved_address *addr) { grpc_uri *uri = grpc_uri_parse(exec_ctx, uri_str, 0 /* suppress_errors */); GPR_ASSERT(uri != NULL); if (strcmp(uri->scheme, "ipv4") == 0) { GPR_ASSERT(parse_ipv4(uri, addr)); } else if (strcmp(uri->scheme, "ipv6") == 0) { GPR_ASSERT(parse_ipv6(uri, addr)); } else { GPR_ASSERT(parse_unix(uri, addr)); } grpc_uri_destroy(uri); } void grpc_get_subchannel_address_arg(grpc_exec_ctx *exec_ctx, const grpc_channel_args *args, grpc_resolved_address *addr) { const char *addr_uri_str = grpc_get_subchannel_address_uri_arg(args); memset(addr, 0, sizeof(*addr)); if (*addr_uri_str != '\0') { grpc_uri_to_sockaddr(exec_ctx, addr_uri_str, addr); } } const char *grpc_get_subchannel_address_uri_arg(const grpc_channel_args *args) { const grpc_arg *addr_arg = grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_ADDRESS); GPR_ASSERT(addr_arg != NULL); // Should have been set by LB policy. GPR_ASSERT(addr_arg->type == GRPC_ARG_STRING); return addr_arg->value.string; } grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address *addr) { grpc_arg new_arg; new_arg.key = GRPC_ARG_SUBCHANNEL_ADDRESS; new_arg.type = GRPC_ARG_STRING; new_arg.value.string = addr->len > 0 ? grpc_sockaddr_to_uri(addr) : gpr_strdup(""); return new_arg; } grpc-1.3.2/src/core/ext/filters/client_channel/subchannel.h000066400000000000000000000223131310511640000236700ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_H #include "src/core/ext/filters/client_channel/connector.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/support/arena.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/metadata.h" // Channel arg containing a grpc_resolved_address to connect to. #define GRPC_ARG_SUBCHANNEL_ADDRESS "grpc.subchannel_address" /** A (sub-)channel that knows how to connect to exactly one target address. Provides a target for load balancing. */ typedef struct grpc_subchannel grpc_subchannel; typedef struct grpc_connected_subchannel grpc_connected_subchannel; typedef struct grpc_subchannel_call grpc_subchannel_call; typedef struct grpc_subchannel_args grpc_subchannel_args; #ifdef GRPC_STREAM_REFCOUNT_DEBUG #define GRPC_SUBCHANNEL_REF(p, r) \ grpc_subchannel_ref((p), __FILE__, __LINE__, (r)) #define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \ grpc_subchannel_ref_from_weak_ref((p), __FILE__, __LINE__, (r)) #define GRPC_SUBCHANNEL_UNREF(cl, p, r) \ grpc_subchannel_unref((cl), (p), __FILE__, __LINE__, (r)) #define GRPC_SUBCHANNEL_WEAK_REF(p, r) \ grpc_subchannel_weak_ref((p), __FILE__, __LINE__, (r)) #define GRPC_SUBCHANNEL_WEAK_UNREF(cl, p, r) \ grpc_subchannel_weak_unref((cl), (p), __FILE__, __LINE__, (r)) #define GRPC_CONNECTED_SUBCHANNEL_REF(p, r) \ grpc_connected_subchannel_ref((p), __FILE__, __LINE__, (r)) #define GRPC_CONNECTED_SUBCHANNEL_UNREF(cl, p, r) \ grpc_connected_subchannel_unref((cl), (p), __FILE__, __LINE__, (r)) #define GRPC_SUBCHANNEL_CALL_REF(p, r) \ grpc_subchannel_call_ref((p), __FILE__, __LINE__, (r)) #define GRPC_SUBCHANNEL_CALL_UNREF(cl, p, r) \ grpc_subchannel_call_unref((cl), (p), __FILE__, __LINE__, (r)) #define GRPC_SUBCHANNEL_REF_EXTRA_ARGS \ , const char *file, int line, const char *reason #else #define GRPC_SUBCHANNEL_REF(p, r) grpc_subchannel_ref((p)) #define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \ grpc_subchannel_ref_from_weak_ref((p)) #define GRPC_SUBCHANNEL_UNREF(cl, p, r) grpc_subchannel_unref((cl), (p)) #define GRPC_SUBCHANNEL_WEAK_REF(p, r) grpc_subchannel_weak_ref((p)) #define GRPC_SUBCHANNEL_WEAK_UNREF(cl, p, r) \ grpc_subchannel_weak_unref((cl), (p)) #define GRPC_CONNECTED_SUBCHANNEL_REF(p, r) grpc_connected_subchannel_ref((p)) #define GRPC_CONNECTED_SUBCHANNEL_UNREF(cl, p, r) \ grpc_connected_subchannel_unref((cl), (p)) #define GRPC_SUBCHANNEL_CALL_REF(p, r) grpc_subchannel_call_ref((p)) #define GRPC_SUBCHANNEL_CALL_UNREF(cl, p, r) \ grpc_subchannel_call_unref((cl), (p)) #define GRPC_SUBCHANNEL_REF_EXTRA_ARGS #endif grpc_subchannel *grpc_subchannel_ref( grpc_subchannel *channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); grpc_subchannel *grpc_subchannel_ref_from_weak_ref( grpc_subchannel *channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); void grpc_subchannel_unref(grpc_exec_ctx *exec_ctx, grpc_subchannel *channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); grpc_subchannel *grpc_subchannel_weak_ref( grpc_subchannel *channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); void grpc_subchannel_weak_unref(grpc_exec_ctx *exec_ctx, grpc_subchannel *channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); grpc_connected_subchannel *grpc_connected_subchannel_ref( grpc_connected_subchannel *channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); void grpc_connected_subchannel_unref(grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); void grpc_subchannel_call_ref( grpc_subchannel_call *call GRPC_SUBCHANNEL_REF_EXTRA_ARGS); void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx, grpc_subchannel_call *call GRPC_SUBCHANNEL_REF_EXTRA_ARGS); /** construct a subchannel call */ typedef struct { grpc_polling_entity *pollent; grpc_slice path; gpr_timespec start_time; gpr_timespec deadline; gpr_arena *arena; } grpc_connected_subchannel_call_args; grpc_error *grpc_connected_subchannel_create_call( grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *connected_subchannel, const grpc_connected_subchannel_call_args *args, grpc_subchannel_call **subchannel_call); /** process a transport level op */ void grpc_connected_subchannel_process_transport_op( grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *subchannel, grpc_transport_op *op); /** poll the current connectivity state of a channel */ grpc_connectivity_state grpc_subchannel_check_connectivity( grpc_subchannel *channel, grpc_error **error); /** call notify when the connectivity state of a channel changes from *state. Updates *state with the new state of the channel */ void grpc_subchannel_notify_on_state_change( grpc_exec_ctx *exec_ctx, grpc_subchannel *channel, grpc_pollset_set *interested_parties, grpc_connectivity_state *state, grpc_closure *notify); void grpc_connected_subchannel_notify_on_state_change( grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *channel, grpc_pollset_set *interested_parties, grpc_connectivity_state *state, grpc_closure *notify); void grpc_connected_subchannel_ping(grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *channel, grpc_closure *notify); /** retrieve the grpc_connected_subchannel - or NULL if called before the subchannel becomes connected */ grpc_connected_subchannel *grpc_subchannel_get_connected_subchannel( grpc_subchannel *subchannel); /** continue processing a transport op */ void grpc_subchannel_call_process_op(grpc_exec_ctx *exec_ctx, grpc_subchannel_call *subchannel_call, grpc_transport_stream_op_batch *op); /** continue querying for peer */ char *grpc_subchannel_call_get_peer(grpc_exec_ctx *exec_ctx, grpc_subchannel_call *subchannel_call); /** Must be called once per call. Sets the 'then_schedule_closure' argument for call stack destruction. */ void grpc_subchannel_call_set_cleanup_closure( grpc_subchannel_call *subchannel_call, grpc_closure *closure); grpc_call_stack *grpc_subchannel_call_get_call_stack( grpc_subchannel_call *subchannel_call); struct grpc_subchannel_args { /* When updating this struct, also update subchannel_index.c */ /** Channel filters for this channel - wrapped factories will likely want to mutate this */ const grpc_channel_filter **filters; /** The number of filters in the above array */ size_t filter_count; /** Channel arguments to be supplied to the newly created channel */ const grpc_channel_args *args; }; /** create a subchannel given a connector */ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx, grpc_connector *connector, const grpc_subchannel_args *args); /// Sets \a addr from \a args. void grpc_get_subchannel_address_arg(grpc_exec_ctx *exec_ctx, const grpc_channel_args *args, grpc_resolved_address *addr); /// Returns the URI string for the address to connect to. const char *grpc_get_subchannel_address_uri_arg(const grpc_channel_args *args); /// Returns a new channel arg encoding the subchannel address as a string. /// Caller is responsible for freeing the string. grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address *addr); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_H */ grpc-1.3.2/src/core/ext/filters/client_channel/subchannel_index.c000066400000000000000000000206201310511640000250510ustar00rootroot00000000000000// // // Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // #include "src/core/ext/filters/client_channel/subchannel_index.h" #include #include #include #include #include #include #include "src/core/lib/channel/channel_args.h" // a map of subchannel_key --> subchannel, used for detecting connections // to the same destination in order to share them static gpr_avl g_subchannel_index; static gpr_mu g_mu; struct grpc_subchannel_key { grpc_connector *connector; grpc_subchannel_args args; }; GPR_TLS_DECL(subchannel_index_exec_ctx); static void enter_ctx(grpc_exec_ctx *exec_ctx) { GPR_ASSERT(gpr_tls_get(&subchannel_index_exec_ctx) == 0); gpr_tls_set(&subchannel_index_exec_ctx, (intptr_t)exec_ctx); } static void leave_ctx(grpc_exec_ctx *exec_ctx) { GPR_ASSERT(gpr_tls_get(&subchannel_index_exec_ctx) == (intptr_t)exec_ctx); gpr_tls_set(&subchannel_index_exec_ctx, 0); } static grpc_exec_ctx *current_ctx() { grpc_exec_ctx *c = (grpc_exec_ctx *)gpr_tls_get(&subchannel_index_exec_ctx); GPR_ASSERT(c != NULL); return c; } static grpc_subchannel_key *create_key( grpc_connector *connector, const grpc_subchannel_args *args, grpc_channel_args *(*copy_channel_args)(const grpc_channel_args *args)) { grpc_subchannel_key *k = gpr_malloc(sizeof(*k)); k->connector = grpc_connector_ref(connector); k->args.filter_count = args->filter_count; if (k->args.filter_count > 0) { k->args.filters = gpr_malloc(sizeof(*k->args.filters) * k->args.filter_count); memcpy((grpc_channel_filter *)k->args.filters, args->filters, sizeof(*k->args.filters) * k->args.filter_count); } else { k->args.filters = NULL; } k->args.args = copy_channel_args(args->args); return k; } grpc_subchannel_key *grpc_subchannel_key_create( grpc_connector *connector, const grpc_subchannel_args *args) { return create_key(connector, args, grpc_channel_args_normalize); } static grpc_subchannel_key *subchannel_key_copy(grpc_subchannel_key *k) { return create_key(k->connector, &k->args, grpc_channel_args_copy); } static int subchannel_key_compare(grpc_subchannel_key *a, grpc_subchannel_key *b) { int c = GPR_ICMP(a->connector, b->connector); if (c != 0) return c; c = GPR_ICMP(a->args.filter_count, b->args.filter_count); if (c != 0) return c; if (a->args.filter_count > 0) { c = memcmp(a->args.filters, b->args.filters, a->args.filter_count * sizeof(*a->args.filters)); if (c != 0) return c; } return grpc_channel_args_compare(a->args.args, b->args.args); } void grpc_subchannel_key_destroy(grpc_exec_ctx *exec_ctx, grpc_subchannel_key *k) { grpc_connector_unref(exec_ctx, k->connector); gpr_free((grpc_channel_args *)k->args.filters); grpc_channel_args_destroy(exec_ctx, (grpc_channel_args *)k->args.args); gpr_free(k); } static void sck_avl_destroy(void *p) { grpc_subchannel_key_destroy(current_ctx(), p); } static void *sck_avl_copy(void *p) { return subchannel_key_copy(p); } static long sck_avl_compare(void *a, void *b) { return subchannel_key_compare(a, b); } static void scv_avl_destroy(void *p) { GRPC_SUBCHANNEL_WEAK_UNREF(current_ctx(), p, "subchannel_index"); } static void *scv_avl_copy(void *p) { GRPC_SUBCHANNEL_WEAK_REF(p, "subchannel_index"); return p; } static const gpr_avl_vtable subchannel_avl_vtable = { .destroy_key = sck_avl_destroy, .copy_key = sck_avl_copy, .compare_keys = sck_avl_compare, .destroy_value = scv_avl_destroy, .copy_value = scv_avl_copy}; void grpc_subchannel_index_init(void) { g_subchannel_index = gpr_avl_create(&subchannel_avl_vtable); gpr_mu_init(&g_mu); gpr_tls_init(&subchannel_index_exec_ctx); } void grpc_subchannel_index_shutdown(void) { gpr_mu_destroy(&g_mu); gpr_avl_unref(g_subchannel_index); gpr_tls_destroy(&subchannel_index_exec_ctx); } grpc_subchannel *grpc_subchannel_index_find(grpc_exec_ctx *exec_ctx, grpc_subchannel_key *key) { enter_ctx(exec_ctx); // Lock, and take a reference to the subchannel index. // We don't need to do the search under a lock as avl's are immutable. gpr_mu_lock(&g_mu); gpr_avl index = gpr_avl_ref(g_subchannel_index); gpr_mu_unlock(&g_mu); grpc_subchannel *c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(gpr_avl_get(index, key), "index_find"); gpr_avl_unref(index); leave_ctx(exec_ctx); return c; } grpc_subchannel *grpc_subchannel_index_register(grpc_exec_ctx *exec_ctx, grpc_subchannel_key *key, grpc_subchannel *constructed) { enter_ctx(exec_ctx); grpc_subchannel *c = NULL; while (c == NULL) { // Compare and swap loop: // - take a reference to the current index gpr_mu_lock(&g_mu); gpr_avl index = gpr_avl_ref(g_subchannel_index); gpr_mu_unlock(&g_mu); // - Check to see if a subchannel already exists c = gpr_avl_get(index, key); if (c != NULL) { // yes -> we're done GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, constructed, "index_register"); } else { // no -> update the avl and compare/swap gpr_avl updated = gpr_avl_add(gpr_avl_ref(index), subchannel_key_copy(key), GRPC_SUBCHANNEL_WEAK_REF(constructed, "index_register")); // it may happen (but it's expected to be unlikely) // that some other thread has changed the index: // compare/swap here to check that, and retry as necessary gpr_mu_lock(&g_mu); if (index.root == g_subchannel_index.root) { GPR_SWAP(gpr_avl, updated, g_subchannel_index); c = constructed; } gpr_mu_unlock(&g_mu); gpr_avl_unref(updated); } gpr_avl_unref(index); } leave_ctx(exec_ctx); return c; } void grpc_subchannel_index_unregister(grpc_exec_ctx *exec_ctx, grpc_subchannel_key *key, grpc_subchannel *constructed) { enter_ctx(exec_ctx); bool done = false; while (!done) { // Compare and swap loop: // - take a reference to the current index gpr_mu_lock(&g_mu); gpr_avl index = gpr_avl_ref(g_subchannel_index); gpr_mu_unlock(&g_mu); // Check to see if this key still refers to the previously // registered subchannel grpc_subchannel *c = gpr_avl_get(index, key); if (c != constructed) { gpr_avl_unref(index); break; } // compare and swap the update (some other thread may have // mutated the index behind us) gpr_avl updated = gpr_avl_remove(gpr_avl_ref(index), key); gpr_mu_lock(&g_mu); if (index.root == g_subchannel_index.root) { GPR_SWAP(gpr_avl, updated, g_subchannel_index); done = true; } gpr_mu_unlock(&g_mu); gpr_avl_unref(updated); gpr_avl_unref(index); } leave_ctx(exec_ctx); } grpc-1.3.2/src/core/ext/filters/client_channel/subchannel_index.h000066400000000000000000000067061310511640000250670ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_INDEX_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_INDEX_H #include "src/core/ext/filters/client_channel/connector.h" #include "src/core/ext/filters/client_channel/subchannel.h" /** \file Provides an index of active subchannels so that they can be shared amongst channels */ typedef struct grpc_subchannel_key grpc_subchannel_key; /** Create a key that can be used to uniquely identify a subchannel */ grpc_subchannel_key *grpc_subchannel_key_create( grpc_connector *con, const grpc_subchannel_args *args); /** Destroy a subchannel key */ void grpc_subchannel_key_destroy(grpc_exec_ctx *exec_ctx, grpc_subchannel_key *key); /** Given a subchannel key, find the subchannel registered for it. Returns NULL if no such channel exists. Thread-safe. */ grpc_subchannel *grpc_subchannel_index_find(grpc_exec_ctx *exec_ctx, grpc_subchannel_key *key); /** Register a subchannel against a key. Takes ownership of \a constructed. Returns the registered subchannel. This may be different from \a constructed in the case of a registration race. */ grpc_subchannel *grpc_subchannel_index_register(grpc_exec_ctx *exec_ctx, grpc_subchannel_key *key, grpc_subchannel *constructed); /** Remove \a constructed as the registered subchannel for \a key. */ void grpc_subchannel_index_unregister(grpc_exec_ctx *exec_ctx, grpc_subchannel_key *key, grpc_subchannel *constructed); /** Initialize the subchannel index (global) */ void grpc_subchannel_index_init(void); /** Shutdown the subchannel index (global) */ void grpc_subchannel_index_shutdown(void); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_INDEX_H */ grpc-1.3.2/src/core/ext/filters/client_channel/uri_parser.c000066400000000000000000000250761310511640000237250ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/filters/client_channel/uri_parser.h" #include #include #include #include #include #include #include "src/core/lib/slice/percent_encoding.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/string.h" /** a size_t default value... maps to all 1's */ #define NOT_SET (~(size_t)0) static grpc_uri *bad_uri(const char *uri_text, size_t pos, const char *section, int suppress_errors) { char *line_prefix; size_t pfx_len; if (!suppress_errors) { gpr_asprintf(&line_prefix, "bad uri.%s: '", section); pfx_len = strlen(line_prefix) + pos; gpr_log(GPR_ERROR, "%s%s'", line_prefix, uri_text); gpr_free(line_prefix); line_prefix = gpr_malloc(pfx_len + 1); memset(line_prefix, ' ', pfx_len); line_prefix[pfx_len] = 0; gpr_log(GPR_ERROR, "%s^ here", line_prefix); gpr_free(line_prefix); } return NULL; } /** Returns a copy of percent decoded \a src[begin, end) */ static char *decode_and_copy_component(grpc_exec_ctx *exec_ctx, const char *src, size_t begin, size_t end) { grpc_slice component = grpc_slice_from_copied_buffer(src + begin, end - begin); grpc_slice decoded_component = grpc_permissive_percent_decode_slice(component); char *out = grpc_dump_slice(decoded_component, GPR_DUMP_ASCII); grpc_slice_unref_internal(exec_ctx, component); grpc_slice_unref_internal(exec_ctx, decoded_component); return out; } /** Returns how many chars to advance if \a uri_text[i] begins a valid \a pchar * production. If \a uri_text[i] introduces an invalid \a pchar (such as percent * sign not followed by two hex digits), NOT_SET is returned. */ static size_t parse_pchar(const char *uri_text, size_t i) { /* pchar = unreserved / pct-encoded / sub-delims / ":" / "@" * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" * pct-encoded = "%" HEXDIG HEXDIG * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" */ char c = uri_text[i]; if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9')) || (c == '-' || c == '.' || c == '_' || c == '~') || /* unreserved */ (c == '!' || c == '$' || c == '&' || c == '\'' || c == '$' || c == '&' || c == '(' || c == ')' || c == '*' || c == '+' || c == ',' || c == ';' || c == '=') /* sub-delims */) { return 1; } if (c == '%') { /* pct-encoded */ size_t j; if (uri_text[i + 1] == 0 || uri_text[i + 2] == 0) { return NOT_SET; } for (j = i + 1; j < 2; j++) { c = uri_text[j]; if (!(((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'f')) || ((c >= 'A') && (c <= 'F')))) { return NOT_SET; } } return 2; } return 0; } /* *( pchar / "?" / "/" ) */ static int parse_fragment_or_query(const char *uri_text, size_t *i) { char c; while ((c = uri_text[*i]) != 0) { const size_t advance = parse_pchar(uri_text, *i); /* pchar */ switch (advance) { case 0: /* uri_text[i] isn't in pchar */ /* maybe it's ? or / */ if (uri_text[*i] == '?' || uri_text[*i] == '/') { (*i)++; break; } else { return 1; } GPR_UNREACHABLE_CODE(return 0); default: (*i) += advance; break; case NOT_SET: /* uri_text[i] introduces an invalid URI */ return 0; } } /* *i is the first uri_text position past the \a query production, maybe \0 */ return 1; } static void parse_query_parts(grpc_uri *uri) { static const char *QUERY_PARTS_SEPARATOR = "&"; static const char *QUERY_PARTS_VALUE_SEPARATOR = "="; GPR_ASSERT(uri->query != NULL); if (uri->query[0] == '\0') { uri->query_parts = NULL; uri->query_parts_values = NULL; uri->num_query_parts = 0; return; } gpr_string_split(uri->query, QUERY_PARTS_SEPARATOR, &uri->query_parts, &uri->num_query_parts); uri->query_parts_values = gpr_malloc(uri->num_query_parts * sizeof(char **)); for (size_t i = 0; i < uri->num_query_parts; i++) { char **query_param_parts; size_t num_query_param_parts; char *full = uri->query_parts[i]; gpr_string_split(full, QUERY_PARTS_VALUE_SEPARATOR, &query_param_parts, &num_query_param_parts); GPR_ASSERT(num_query_param_parts > 0); uri->query_parts[i] = query_param_parts[0]; if (num_query_param_parts > 1) { /* TODO(dgq): only the first value after the separator is considered. * Perhaps all chars after the first separator for the query part should * be included, even if they include the separator. */ uri->query_parts_values[i] = query_param_parts[1]; } else { uri->query_parts_values[i] = NULL; } for (size_t j = 2; j < num_query_param_parts; j++) { gpr_free(query_param_parts[j]); } gpr_free(query_param_parts); gpr_free(full); } } grpc_uri *grpc_uri_parse(grpc_exec_ctx *exec_ctx, const char *uri_text, int suppress_errors) { grpc_uri *uri; size_t scheme_begin = 0; size_t scheme_end = NOT_SET; size_t authority_begin = NOT_SET; size_t authority_end = NOT_SET; size_t path_begin = NOT_SET; size_t path_end = NOT_SET; size_t query_begin = NOT_SET; size_t query_end = NOT_SET; size_t fragment_begin = NOT_SET; size_t fragment_end = NOT_SET; size_t i; for (i = scheme_begin; uri_text[i] != 0; i++) { if (uri_text[i] == ':') { scheme_end = i; break; } if (uri_text[i] >= 'a' && uri_text[i] <= 'z') continue; if (uri_text[i] >= 'A' && uri_text[i] <= 'Z') continue; if (i != scheme_begin) { if (uri_text[i] >= '0' && uri_text[i] <= '9') continue; if (uri_text[i] == '+') continue; if (uri_text[i] == '-') continue; if (uri_text[i] == '.') continue; } break; } if (scheme_end == NOT_SET) { return bad_uri(uri_text, i, "scheme", suppress_errors); } if (uri_text[scheme_end + 1] == '/' && uri_text[scheme_end + 2] == '/') { authority_begin = scheme_end + 3; for (i = authority_begin; uri_text[i] != 0 && authority_end == NOT_SET; i++) { if (uri_text[i] == '/' || uri_text[i] == '?' || uri_text[i] == '#') { authority_end = i; } } if (authority_end == NOT_SET && uri_text[i] == 0) { authority_end = i; } if (authority_end == NOT_SET) { return bad_uri(uri_text, i, "authority", suppress_errors); } /* TODO(ctiller): parse the authority correctly */ path_begin = authority_end; } else { path_begin = scheme_end + 1; } for (i = path_begin; uri_text[i] != 0; i++) { if (uri_text[i] == '?' || uri_text[i] == '#') { path_end = i; break; } } if (path_end == NOT_SET && uri_text[i] == 0) { path_end = i; } if (path_end == NOT_SET) { return bad_uri(uri_text, i, "path", suppress_errors); } if (uri_text[i] == '?') { query_begin = ++i; if (!parse_fragment_or_query(uri_text, &i)) { return bad_uri(uri_text, i, "query", suppress_errors); } else if (uri_text[i] != 0 && uri_text[i] != '#') { /* We must be at the end or at the beginning of a fragment */ return bad_uri(uri_text, i, "query", suppress_errors); } query_end = i; } if (uri_text[i] == '#') { fragment_begin = ++i; if (!parse_fragment_or_query(uri_text, &i)) { return bad_uri(uri_text, i - fragment_end, "fragment", suppress_errors); } else if (uri_text[i] != 0) { /* We must be at the end */ return bad_uri(uri_text, i, "fragment", suppress_errors); } fragment_end = i; } uri = gpr_zalloc(sizeof(*uri)); uri->scheme = decode_and_copy_component(exec_ctx, uri_text, scheme_begin, scheme_end); uri->authority = decode_and_copy_component(exec_ctx, uri_text, authority_begin, authority_end); uri->path = decode_and_copy_component(exec_ctx, uri_text, path_begin, path_end); uri->query = decode_and_copy_component(exec_ctx, uri_text, query_begin, query_end); uri->fragment = decode_and_copy_component(exec_ctx, uri_text, fragment_begin, fragment_end); parse_query_parts(uri); return uri; } const char *grpc_uri_get_query_arg(const grpc_uri *uri, const char *key) { GPR_ASSERT(key != NULL); if (key[0] == '\0') return NULL; for (size_t i = 0; i < uri->num_query_parts; ++i) { if (0 == strcmp(key, uri->query_parts[i])) { return uri->query_parts_values[i]; } } return NULL; } void grpc_uri_destroy(grpc_uri *uri) { if (!uri) return; gpr_free(uri->scheme); gpr_free(uri->authority); gpr_free(uri->path); gpr_free(uri->query); for (size_t i = 0; i < uri->num_query_parts; ++i) { gpr_free(uri->query_parts[i]); gpr_free(uri->query_parts_values[i]); } gpr_free(uri->query_parts); gpr_free(uri->query_parts_values); gpr_free(uri->fragment); gpr_free(uri); } grpc-1.3.2/src/core/ext/filters/client_channel/uri_parser.h000066400000000000000000000050251310511640000237220ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_URI_PARSER_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_URI_PARSER_H #include #include "src/core/lib/iomgr/exec_ctx.h" typedef struct { char *scheme; char *authority; char *path; char *query; /** Query substrings separated by '&' */ char **query_parts; /** Number of elements in \a query_parts and \a query_parts_values */ size_t num_query_parts; /** Split each query part by '='. NULL if not present. */ char **query_parts_values; char *fragment; } grpc_uri; /** parse a uri, return NULL on failure */ grpc_uri *grpc_uri_parse(grpc_exec_ctx *exec_ctx, const char *uri_text, int suppress_errors); /** return the part of a query string after the '=' in "?key=xxx&...", or NULL * if key is not present */ const char *grpc_uri_get_query_arg(const grpc_uri *uri, const char *key); /** destroy a uri */ void grpc_uri_destroy(grpc_uri *uri); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_URI_PARSER_H */ grpc-1.3.2/src/core/ext/filters/load_reporting/000077500000000000000000000000001310511640000214365ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/filters/load_reporting/load_reporting.c000066400000000000000000000076161310511640000246240ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include "src/core/ext/filters/load_reporting/load_reporting.h" #include "src/core/ext/filters/load_reporting/load_reporting_filter.h" #include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/surface/call.h" #include "src/core/lib/surface/channel_init.h" static void destroy_lr_cost_context(void *c) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_load_reporting_cost_context *cost_ctx = c; for (size_t i = 0; i < cost_ctx->values_count; ++i) { grpc_slice_unref_internal(&exec_ctx, cost_ctx->values[i]); } grpc_exec_ctx_finish(&exec_ctx); gpr_free(cost_ctx->values); gpr_free(cost_ctx); } void grpc_call_set_load_reporting_cost_context( grpc_call *call, grpc_load_reporting_cost_context *ctx) { grpc_call_context_set(call, GRPC_CONTEXT_LR_COST, ctx, destroy_lr_cost_context); } static bool is_load_reporting_enabled(const grpc_channel_args *a) { if (a == NULL) return false; for (size_t i = 0; i < a->num_args; i++) { if (0 == strcmp(a->args[i].key, GRPC_ARG_ENABLE_LOAD_REPORTING)) { return a->args[i].type == GRPC_ARG_INTEGER && a->args[i].value.integer != 0; } } return false; } static bool maybe_add_load_reporting_filter(grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, void *arg) { const grpc_channel_args *args = grpc_channel_stack_builder_get_channel_arguments(builder); if (is_load_reporting_enabled(args)) { return grpc_channel_stack_builder_prepend_filter( builder, (const grpc_channel_filter *)arg, NULL, NULL); } return true; } grpc_arg grpc_load_reporting_enable_arg() { grpc_arg arg; arg.type = GRPC_ARG_INTEGER; arg.key = GRPC_ARG_ENABLE_LOAD_REPORTING; arg.value.integer = 1; return arg; } /* Plugin registration */ void grpc_load_reporting_plugin_init(void) { grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, maybe_add_load_reporting_filter, (void *)&grpc_load_reporting_filter); } void grpc_load_reporting_plugin_shutdown() {} grpc-1.3.2/src/core/ext/filters/load_reporting/load_reporting.h000066400000000000000000000060561310511640000246260ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_LOAD_REPORTING_LOAD_REPORTING_H #define GRPC_CORE_EXT_FILTERS_LOAD_REPORTING_LOAD_REPORTING_H #include #include "src/core/lib/channel/channel_stack.h" /** Identifiers for the invocation point of the users LR callback */ typedef enum grpc_load_reporting_source { GRPC_LR_POINT_UNKNOWN = 0, GRPC_LR_POINT_CHANNEL_CREATION, GRPC_LR_POINT_CHANNEL_DESTRUCTION, GRPC_LR_POINT_CALL_CREATION, GRPC_LR_POINT_CALL_DESTRUCTION } grpc_load_reporting_source; /** Call information to be passed to the provided LR callback. */ typedef struct grpc_load_reporting_call_data { const grpc_load_reporting_source source; /**< point of last data update. */ /** Unique identifier for the channel associated with the data */ intptr_t channel_id; /** Unique identifier for the call associated with the data. If the call * hasn't been created yet, it'll have a value of zero. */ intptr_t call_id; /** Only valid when \a source is \a GRPC_LR_POINT_CALL_DESTRUCTION, that is, * once the call has completed */ const grpc_call_final_info *final_info; const char *initial_md_string; /**< value string for LR's initial md key */ const char *trailing_md_string; /**< value string for LR's trailing md key */ const char *method_name; /**< Corresponds to :path header */ } grpc_load_reporting_call_data; /** Return a \a grpc_arg enabling load reporting */ grpc_arg grpc_load_reporting_enable_arg(); #endif /* GRPC_CORE_EXT_FILTERS_LOAD_REPORTING_LOAD_REPORTING_H */ grpc-1.3.2/src/core/ext/filters/load_reporting/load_reporting_filter.c000066400000000000000000000204721310511640000261640ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include "src/core/ext/filters/load_reporting/load_reporting.h" #include "src/core/ext/filters/load_reporting/load_reporting_filter.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/transport/static_metadata.h" typedef struct call_data { intptr_t id; /**< an id unique to the call */ bool have_initial_md_string; grpc_slice initial_md_string; bool have_service_method; grpc_slice service_method; /* stores the recv_initial_metadata op's ready closure, which we wrap with our * own (on_initial_md_ready) in order to capture the incoming initial metadata * */ grpc_closure *ops_recv_initial_metadata_ready; /* to get notified of the availability of the incoming initial metadata. */ grpc_closure on_initial_md_ready; grpc_metadata_batch *recv_initial_metadata; } call_data; typedef struct channel_data { intptr_t id; /**< an id unique to the channel */ } channel_data; static void on_initial_md_ready(grpc_exec_ctx *exec_ctx, void *user_data, grpc_error *err) { grpc_call_element *elem = user_data; call_data *calld = elem->call_data; if (err == GRPC_ERROR_NONE) { if (calld->recv_initial_metadata->idx.named.path != NULL) { calld->service_method = grpc_slice_ref_internal( GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.path->md)); calld->have_service_method = true; } else { err = grpc_error_add_child( err, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing :path header")); } if (calld->recv_initial_metadata->idx.named.lb_token != NULL) { calld->initial_md_string = grpc_slice_ref_internal( GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.lb_token->md)); calld->have_initial_md_string = true; grpc_metadata_batch_remove( exec_ctx, calld->recv_initial_metadata, calld->recv_initial_metadata->idx.named.lb_token); } } else { GRPC_ERROR_REF(err); } calld->ops_recv_initial_metadata_ready->cb( exec_ctx, calld->ops_recv_initial_metadata_ready->cb_arg, err); GRPC_ERROR_UNREF(err); } /* Constructor for call_data */ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_element_args *args) { call_data *calld = elem->call_data; calld->id = (intptr_t)args->call_stack; grpc_closure_init(&calld->on_initial_md_ready, on_initial_md_ready, elem, grpc_schedule_on_exec_ctx); /* TODO(dgq): do something with the data channel_data *chand = elem->channel_data; grpc_load_reporting_call_data lr_call_data = {GRPC_LR_POINT_CALL_CREATION, (intptr_t)chand->id, (intptr_t)calld->id, NULL, NULL, NULL, NULL}; */ return GRPC_ERROR_NONE; } /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, grpc_closure *ignored) { call_data *calld = elem->call_data; /* TODO(dgq): do something with the data channel_data *chand = elem->channel_data; grpc_load_reporting_call_data lr_call_data = {GRPC_LR_POINT_CALL_DESTRUCTION, (intptr_t)chand->id, (intptr_t)calld->id, final_info, calld->initial_md_string, calld->trailing_md_string, calld->service_method}; */ if (calld->have_initial_md_string) { grpc_slice_unref_internal(exec_ctx, calld->initial_md_string); } if (calld->have_service_method) { grpc_slice_unref_internal(exec_ctx, calld->service_method); } } /* Constructor for channel_data */ static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_channel_element_args *args) { GPR_ASSERT(!args->is_last); channel_data *chand = elem->channel_data; chand->id = (intptr_t)args->channel_stack; /* TODO(dgq): do something with the data grpc_load_reporting_call_data lr_call_data = {GRPC_LR_POINT_CHANNEL_CREATION, (intptr_t)chand, 0, NULL, NULL, NULL, NULL}; */ return GRPC_ERROR_NONE; } /* Destructor for channel data */ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) { /* TODO(dgq): do something with the data channel_data *chand = elem->channel_data; grpc_load_reporting_call_data lr_call_data = { GRPC_LR_POINT_CHANNEL_DESTRUCTION, (intptr_t)chand->id, 0, NULL, NULL, NULL, NULL}; */ } static void lr_start_transport_stream_op_batch( grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op_batch *op) { GPR_TIMER_BEGIN("lr_start_transport_stream_op_batch", 0); call_data *calld = elem->call_data; if (op->recv_initial_metadata) { calld->recv_initial_metadata = op->payload->recv_initial_metadata.recv_initial_metadata; /* substitute our callback for the higher callback */ calld->ops_recv_initial_metadata_ready = op->payload->recv_initial_metadata.recv_initial_metadata_ready; op->payload->recv_initial_metadata.recv_initial_metadata_ready = &calld->on_initial_md_ready; } grpc_call_next_op(exec_ctx, elem, op); GPR_TIMER_END("lr_start_transport_stream_op_batch", 0); } const grpc_channel_filter grpc_load_reporting_filter = { lr_start_transport_stream_op_batch, grpc_channel_next_op, sizeof(call_data), init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, destroy_call_elem, sizeof(channel_data), init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer, grpc_channel_next_get_info, "load_reporting"}; grpc-1.3.2/src/core/ext/filters/load_reporting/load_reporting_filter.h000066400000000000000000000036461310511640000261750ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_FILTERS_LOAD_REPORTING_LOAD_REPORTING_FILTER_H #define GRPC_CORE_EXT_FILTERS_LOAD_REPORTING_LOAD_REPORTING_FILTER_H #include "src/core/ext/filters/load_reporting/load_reporting.h" #include "src/core/lib/channel/channel_stack.h" extern const grpc_channel_filter grpc_load_reporting_filter; #endif /* GRPC_CORE_EXT_FILTERS_LOAD_REPORTING_LOAD_REPORTING_FILTER_H */ grpc-1.3.2/src/core/ext/filters/max_age/000077500000000000000000000000001310511640000200275ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/filters/max_age/max_age_filter.c000066400000000000000000000472671310511640000231610ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/filters/max_age/max_age_filter.h" #include #include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/surface/channel_init.h" #include "src/core/lib/transport/http2_errors.h" #define DEFAULT_MAX_CONNECTION_AGE_MS INT_MAX #define DEFAULT_MAX_CONNECTION_AGE_GRACE_MS INT_MAX #define DEFAULT_MAX_CONNECTION_IDLE_MS INT_MAX #define MAX_CONNECTION_AGE_JITTER 0.1 typedef struct channel_data { /* We take a reference to the channel stack for the timer callback */ grpc_channel_stack* channel_stack; /* Guards access to max_age_timer, max_age_timer_pending, max_age_grace_timer and max_age_grace_timer_pending */ gpr_mu max_age_timer_mu; /* True if the max_age timer callback is currently pending */ bool max_age_timer_pending; /* True if the max_age_grace timer callback is currently pending */ bool max_age_grace_timer_pending; /* The timer for checking if the channel has reached its max age */ grpc_timer max_age_timer; /* The timer for checking if the max-aged channel has uesed up the grace period */ grpc_timer max_age_grace_timer; /* The timer for checking if the channel's idle duration reaches max_connection_idle */ grpc_timer max_idle_timer; /* Allowed max time a channel may have no outstanding rpcs */ gpr_timespec max_connection_idle; /* Allowed max time a channel may exist */ gpr_timespec max_connection_age; /* Allowed grace period after the channel reaches its max age */ gpr_timespec max_connection_age_grace; /* Closure to run when the channel's idle duration reaches max_connection_idle and should be closed gracefully */ grpc_closure close_max_idle_channel; /* Closure to run when the channel reaches its max age and should be closed gracefully */ grpc_closure close_max_age_channel; /* Closure to run the channel uses up its max age grace time and should be closed forcibly */ grpc_closure force_close_max_age_channel; /* Closure to run when the init fo channel stack is done and the max_idle timer should be started */ grpc_closure start_max_idle_timer_after_init; /* Closure to run when the init fo channel stack is done and the max_age timer should be started */ grpc_closure start_max_age_timer_after_init; /* Closure to run when the goaway op is finished and the max_age_timer */ grpc_closure start_max_age_grace_timer_after_goaway_op; /* Closure to run when the channel connectivity state changes */ grpc_closure channel_connectivity_changed; /* Records the current connectivity state */ grpc_connectivity_state connectivity_state; /* Number of active calls */ gpr_atm call_count; } channel_data; /* Increase the nubmer of active calls. Before the increasement, if there are no calls, the max_idle_timer should be cancelled. */ static void increase_call_count(grpc_exec_ctx* exec_ctx, channel_data* chand) { if (gpr_atm_full_fetch_add(&chand->call_count, 1) == 0) { grpc_timer_cancel(exec_ctx, &chand->max_idle_timer); } } /* Decrease the nubmer of active calls. After the decrement, if there are no calls, the max_idle_timer should be started. */ static void decrease_call_count(grpc_exec_ctx* exec_ctx, channel_data* chand) { if (gpr_atm_full_fetch_add(&chand->call_count, -1) == 1) { GRPC_CHANNEL_STACK_REF(chand->channel_stack, "max_age max_idle_timer"); grpc_timer_init( exec_ctx, &chand->max_idle_timer, gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), chand->max_connection_idle), &chand->close_max_idle_channel, gpr_now(GPR_CLOCK_MONOTONIC)); } } static void start_max_idle_timer_after_init(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { channel_data* chand = arg; /* Decrease call_count. If there are no active calls at this time, max_idle_timer will start here. If the number of active calls is not 0, max_idle_timer will start after all the active calls end. */ decrease_call_count(exec_ctx, chand); GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack, "max_age start_max_idle_timer_after_init"); } static void start_max_age_timer_after_init(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { channel_data* chand = arg; gpr_mu_lock(&chand->max_age_timer_mu); chand->max_age_timer_pending = true; GRPC_CHANNEL_STACK_REF(chand->channel_stack, "max_age max_age_timer"); grpc_timer_init( exec_ctx, &chand->max_age_timer, gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), chand->max_connection_age), &chand->close_max_age_channel, gpr_now(GPR_CLOCK_MONOTONIC)); gpr_mu_unlock(&chand->max_age_timer_mu); grpc_transport_op* op = grpc_make_transport_op(NULL); op->on_connectivity_state_change = &chand->channel_connectivity_changed, op->connectivity_state = &chand->connectivity_state; grpc_channel_next_op(exec_ctx, grpc_channel_stack_element(chand->channel_stack, 0), op); GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack, "max_age start_max_age_timer_after_init"); } static void start_max_age_grace_timer_after_goaway_op(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { channel_data* chand = arg; gpr_mu_lock(&chand->max_age_timer_mu); chand->max_age_grace_timer_pending = true; GRPC_CHANNEL_STACK_REF(chand->channel_stack, "max_age max_age_grace_timer"); grpc_timer_init(exec_ctx, &chand->max_age_grace_timer, gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), chand->max_connection_age_grace), &chand->force_close_max_age_channel, gpr_now(GPR_CLOCK_MONOTONIC)); gpr_mu_unlock(&chand->max_age_timer_mu); GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack, "max_age start_max_age_grace_timer_after_goaway_op"); } static void close_max_idle_channel(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { channel_data* chand = arg; if (error == GRPC_ERROR_NONE) { /* Prevent the max idle timer from being set again */ gpr_atm_no_barrier_fetch_add(&chand->call_count, 1); grpc_transport_op* op = grpc_make_transport_op(NULL); op->goaway_error = grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("max_idle"), GRPC_ERROR_INT_HTTP2_ERROR, GRPC_HTTP2_NO_ERROR); grpc_channel_element* elem = grpc_channel_stack_element(chand->channel_stack, 0); elem->filter->start_transport_op(exec_ctx, elem, op); } else if (error != GRPC_ERROR_CANCELLED) { GRPC_LOG_IF_ERROR("close_max_idle_channel", error); } GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack, "max_age max_idle_timer"); } static void close_max_age_channel(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { channel_data* chand = arg; gpr_mu_lock(&chand->max_age_timer_mu); chand->max_age_timer_pending = false; gpr_mu_unlock(&chand->max_age_timer_mu); if (error == GRPC_ERROR_NONE) { GRPC_CHANNEL_STACK_REF(chand->channel_stack, "max_age start_max_age_grace_timer_after_goaway_op"); grpc_transport_op* op = grpc_make_transport_op( &chand->start_max_age_grace_timer_after_goaway_op); op->goaway_error = grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("max_age"), GRPC_ERROR_INT_HTTP2_ERROR, GRPC_HTTP2_NO_ERROR); grpc_channel_element* elem = grpc_channel_stack_element(chand->channel_stack, 0); elem->filter->start_transport_op(exec_ctx, elem, op); } else if (error != GRPC_ERROR_CANCELLED) { GRPC_LOG_IF_ERROR("close_max_age_channel", error); } GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack, "max_age max_age_timer"); } static void force_close_max_age_channel(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { channel_data* chand = arg; gpr_mu_lock(&chand->max_age_timer_mu); chand->max_age_grace_timer_pending = false; gpr_mu_unlock(&chand->max_age_timer_mu); if (error == GRPC_ERROR_NONE) { grpc_transport_op* op = grpc_make_transport_op(NULL); op->disconnect_with_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel reaches max age"); grpc_channel_element* elem = grpc_channel_stack_element(chand->channel_stack, 0); elem->filter->start_transport_op(exec_ctx, elem, op); } else if (error != GRPC_ERROR_CANCELLED) { GRPC_LOG_IF_ERROR("force_close_max_age_channel", error); } GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack, "max_age max_age_grace_timer"); } static void channel_connectivity_changed(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { channel_data* chand = arg; if (chand->connectivity_state != GRPC_CHANNEL_SHUTDOWN) { grpc_transport_op* op = grpc_make_transport_op(NULL); op->on_connectivity_state_change = &chand->channel_connectivity_changed, op->connectivity_state = &chand->connectivity_state; grpc_channel_next_op( exec_ctx, grpc_channel_stack_element(chand->channel_stack, 0), op); } else { gpr_mu_lock(&chand->max_age_timer_mu); if (chand->max_age_timer_pending) { grpc_timer_cancel(exec_ctx, &chand->max_age_timer); chand->max_age_timer_pending = false; } if (chand->max_age_grace_timer_pending) { grpc_timer_cancel(exec_ctx, &chand->max_age_grace_timer); chand->max_age_grace_timer_pending = false; } gpr_mu_unlock(&chand->max_age_timer_mu); /* If there are no active calls, this increasement will cancel max_idle_timer, and prevent max_idle_timer from being started in the future. */ increase_call_count(exec_ctx, chand); } } /* A random jitter of +/-10% will be added to MAX_CONNECTION_AGE to spread out connection storms. Note that the MAX_CONNECTION_AGE option without jitter would not create connection storms by itself, but if there happened to be a connection storm it could cause it to repeat at a fixed period. */ static int add_random_max_connection_age_jitter(int value) { /* generate a random number between 1 - MAX_CONNECTION_AGE_JITTER and 1 + MAX_CONNECTION_AGE_JITTER */ double multiplier = rand() * MAX_CONNECTION_AGE_JITTER * 2.0 / RAND_MAX + 1.0 - MAX_CONNECTION_AGE_JITTER; double result = multiplier * value; /* INT_MAX - 0.5 converts the value to float, so that result will not be cast to int implicitly before the comparison. */ return result > INT_MAX - 0.5 ? INT_MAX : (int)result; } /* Constructor for call_data. */ static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, const grpc_call_element_args* args) { channel_data* chand = elem->channel_data; increase_call_count(exec_ctx, chand); return GRPC_ERROR_NONE; } /* Destructor for call_data. */ static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, const grpc_call_final_info* final_info, grpc_closure* ignored) { channel_data* chand = elem->channel_data; decrease_call_count(exec_ctx, chand); } /* Constructor for channel_data. */ static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx, grpc_channel_element* elem, grpc_channel_element_args* args) { channel_data* chand = elem->channel_data; gpr_mu_init(&chand->max_age_timer_mu); chand->max_age_timer_pending = false; chand->max_age_grace_timer_pending = false; chand->channel_stack = args->channel_stack; chand->max_connection_age = DEFAULT_MAX_CONNECTION_AGE_MS == INT_MAX ? gpr_inf_future(GPR_TIMESPAN) : gpr_time_from_millis(add_random_max_connection_age_jitter( DEFAULT_MAX_CONNECTION_AGE_MS), GPR_TIMESPAN); chand->max_connection_age_grace = DEFAULT_MAX_CONNECTION_AGE_GRACE_MS == INT_MAX ? gpr_inf_future(GPR_TIMESPAN) : gpr_time_from_millis(DEFAULT_MAX_CONNECTION_AGE_GRACE_MS, GPR_TIMESPAN); chand->max_connection_idle = DEFAULT_MAX_CONNECTION_IDLE_MS == INT_MAX ? gpr_inf_future(GPR_TIMESPAN) : gpr_time_from_millis(DEFAULT_MAX_CONNECTION_IDLE_MS, GPR_TIMESPAN); for (size_t i = 0; i < args->channel_args->num_args; ++i) { if (0 == strcmp(args->channel_args->args[i].key, GRPC_ARG_MAX_CONNECTION_AGE_MS)) { const int value = grpc_channel_arg_get_integer( &args->channel_args->args[i], (grpc_integer_options){DEFAULT_MAX_CONNECTION_AGE_MS, 1, INT_MAX}); chand->max_connection_age = value == INT_MAX ? gpr_inf_future(GPR_TIMESPAN) : gpr_time_from_millis( add_random_max_connection_age_jitter(value), GPR_TIMESPAN); } else if (0 == strcmp(args->channel_args->args[i].key, GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS)) { const int value = grpc_channel_arg_get_integer( &args->channel_args->args[i], (grpc_integer_options){DEFAULT_MAX_CONNECTION_AGE_GRACE_MS, 0, INT_MAX}); chand->max_connection_age_grace = value == INT_MAX ? gpr_inf_future(GPR_TIMESPAN) : gpr_time_from_millis(value, GPR_TIMESPAN); } else if (0 == strcmp(args->channel_args->args[i].key, GRPC_ARG_MAX_CONNECTION_IDLE_MS)) { const int value = grpc_channel_arg_get_integer( &args->channel_args->args[i], (grpc_integer_options){DEFAULT_MAX_CONNECTION_IDLE_MS, 1, INT_MAX}); chand->max_connection_idle = value == INT_MAX ? gpr_inf_future(GPR_TIMESPAN) : gpr_time_from_millis(value, GPR_TIMESPAN); } } grpc_closure_init(&chand->close_max_idle_channel, close_max_idle_channel, chand, grpc_schedule_on_exec_ctx); grpc_closure_init(&chand->close_max_age_channel, close_max_age_channel, chand, grpc_schedule_on_exec_ctx); grpc_closure_init(&chand->force_close_max_age_channel, force_close_max_age_channel, chand, grpc_schedule_on_exec_ctx); grpc_closure_init(&chand->start_max_idle_timer_after_init, start_max_idle_timer_after_init, chand, grpc_schedule_on_exec_ctx); grpc_closure_init(&chand->start_max_age_timer_after_init, start_max_age_timer_after_init, chand, grpc_schedule_on_exec_ctx); grpc_closure_init(&chand->start_max_age_grace_timer_after_goaway_op, start_max_age_grace_timer_after_goaway_op, chand, grpc_schedule_on_exec_ctx); grpc_closure_init(&chand->channel_connectivity_changed, channel_connectivity_changed, chand, grpc_schedule_on_exec_ctx); if (gpr_time_cmp(chand->max_connection_age, gpr_inf_future(GPR_TIMESPAN)) != 0) { /* When the channel reaches its max age, we send down an op with goaway_error set. However, we can't send down any ops until after the channel stack is fully initialized. If we start the timer here, we have no guarantee that the timer won't pop before channel stack initialization is finished. To avoid that problem, we create a closure to start the timer, and we schedule that closure to be run after call stack initialization is done. */ GRPC_CHANNEL_STACK_REF(chand->channel_stack, "max_age start_max_age_timer_after_init"); grpc_closure_sched(exec_ctx, &chand->start_max_age_timer_after_init, GRPC_ERROR_NONE); } /* Initialize the number of calls as 1, so that the max_idle_timer will not start until start_max_idle_timer_after_init is invoked. */ gpr_atm_rel_store(&chand->call_count, 1); if (gpr_time_cmp(chand->max_connection_idle, gpr_inf_future(GPR_TIMESPAN)) != 0) { GRPC_CHANNEL_STACK_REF(chand->channel_stack, "max_age start_max_idle_timer_after_init"); grpc_closure_sched(exec_ctx, &chand->start_max_idle_timer_after_init, GRPC_ERROR_NONE); } return GRPC_ERROR_NONE; } /* Destructor for channel_data. */ static void destroy_channel_elem(grpc_exec_ctx* exec_ctx, grpc_channel_element* elem) {} const grpc_channel_filter grpc_max_age_filter = { grpc_call_next_op, grpc_channel_next_op, 0, /* sizeof_call_data */ init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, destroy_call_elem, sizeof(channel_data), init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer, grpc_channel_next_get_info, "max_age"}; static bool maybe_add_max_age_filter(grpc_exec_ctx* exec_ctx, grpc_channel_stack_builder* builder, void* arg) { const grpc_channel_args* channel_args = grpc_channel_stack_builder_get_channel_arguments(builder); const grpc_arg* a = grpc_channel_args_find(channel_args, GRPC_ARG_MAX_CONNECTION_AGE_MS); bool enable = false; if (a != NULL && a->type == GRPC_ARG_INTEGER && a->value.integer != INT_MAX) { enable = true; } a = grpc_channel_args_find(channel_args, GRPC_ARG_MAX_CONNECTION_IDLE_MS); if (a != NULL && a->type == GRPC_ARG_INTEGER && a->value.integer != INT_MAX) { enable = true; } if (enable) { return grpc_channel_stack_builder_prepend_filter( builder, &grpc_max_age_filter, NULL, NULL); } else { return true; } } void grpc_max_age_filter_init(void) { grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, maybe_add_max_age_filter, NULL); } void grpc_max_age_filter_shutdown(void) {} grpc-1.3.2/src/core/ext/filters/max_age/max_age_filter.h000066400000000000000000000034561310511640000231560ustar00rootroot00000000000000// // Copyright 2017, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #ifndef GRPC_CORE_EXT_FILTERS_MAX_AGE_MAX_AGE_FILTER_H #define GRPC_CORE_EXT_FILTERS_MAX_AGE_MAX_AGE_FILTER_H #include "src/core/lib/channel/channel_stack.h" extern const grpc_channel_filter grpc_max_age_filter; #endif /* GRPC_CORE_EXT_FILTERS_MAX_AGE_MAX_AGE_FILTER_H */ grpc-1.3.2/src/core/ext/transport/000077500000000000000000000000001310511640000170125ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/transport/README.md000066400000000000000000000000241310511640000202650ustar00rootroot00000000000000Transports for gRPC grpc-1.3.2/src/core/ext/transport/chttp2/000077500000000000000000000000001310511640000202165ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/transport/chttp2/README.md000066400000000000000000000000721310511640000214740ustar00rootroot00000000000000CHTTP2 - gRPC's implementation of a HTTP2 based transport grpc-1.3.2/src/core/ext/transport/chttp2/alpn/000077500000000000000000000000001310511640000211505ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/transport/chttp2/alpn/alpn.c000066400000000000000000000043251310511640000222520ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/alpn/alpn.h" #include #include /* in order of preference */ static const char *const supported_versions[] = {"grpc-exp", "h2"}; int grpc_chttp2_is_alpn_version_supported(const char *version, size_t size) { size_t i; for (i = 0; i < GPR_ARRAY_SIZE(supported_versions); i++) { if (!strncmp(version, supported_versions[i], size)) return 1; } return 0; } size_t grpc_chttp2_num_alpn_versions(void) { return GPR_ARRAY_SIZE(supported_versions); } const char *grpc_chttp2_get_alpn_version_index(size_t i) { GPR_ASSERT(i < GPR_ARRAY_SIZE(supported_versions)); return supported_versions[i]; } grpc-1.3.2/src/core/ext/transport/chttp2/alpn/alpn.h000066400000000000000000000041341310511640000222550ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_ALPN_ALPN_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_ALPN_ALPN_H #include /* Retuns 1 if the version is supported, 0 otherwise. */ int grpc_chttp2_is_alpn_version_supported(const char *version, size_t size); /* Returns the number of protocol versions to advertise */ size_t grpc_chttp2_num_alpn_versions(void); /* Returns the protocol version at index i (0 <= i < * grpc_chttp2_num_alpn_versions()) */ const char *grpc_chttp2_get_alpn_version_index(size_t i); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_ALPN_ALPN_H */ grpc-1.3.2/src/core/ext/transport/chttp2/client/000077500000000000000000000000001310511640000214745ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/transport/chttp2/client/chttp2_connector.c000066400000000000000000000204041310511640000251160ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/client/chttp2_connector.h" #include #include #include #include #include #include "src/core/ext/filters/client_channel/connector.h" #include "src/core/ext/filters/client_channel/http_connect_handshaker.h" #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/handshaker.h" #include "src/core/lib/channel/handshaker_registry.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/slice/slice_internal.h" typedef struct { grpc_connector base; gpr_mu mu; gpr_refcount refs; bool shutdown; bool connecting; grpc_closure *notify; grpc_connect_in_args args; grpc_connect_out_args *result; grpc_endpoint *endpoint; // Non-NULL until handshaking starts. grpc_closure connected; grpc_handshake_manager *handshake_mgr; } chttp2_connector; static void chttp2_connector_ref(grpc_connector *con) { chttp2_connector *c = (chttp2_connector *)con; gpr_ref(&c->refs); } static void chttp2_connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) { chttp2_connector *c = (chttp2_connector *)con; if (gpr_unref(&c->refs)) { gpr_mu_destroy(&c->mu); // If handshaking is not yet in progress, destroy the endpoint. // Otherwise, the handshaker will do this for us. if (c->endpoint != NULL) grpc_endpoint_destroy(exec_ctx, c->endpoint); gpr_free(c); } } static void chttp2_connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *con, grpc_error *why) { chttp2_connector *c = (chttp2_connector *)con; gpr_mu_lock(&c->mu); c->shutdown = true; if (c->handshake_mgr != NULL) { grpc_handshake_manager_shutdown(exec_ctx, c->handshake_mgr, GRPC_ERROR_REF(why)); } // If handshaking is not yet in progress, shutdown the endpoint. // Otherwise, the handshaker will do this for us. if (!c->connecting && c->endpoint != NULL) { grpc_endpoint_shutdown(exec_ctx, c->endpoint, GRPC_ERROR_REF(why)); } gpr_mu_unlock(&c->mu); GRPC_ERROR_UNREF(why); } static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_handshaker_args *args = arg; chttp2_connector *c = args->user_data; gpr_mu_lock(&c->mu); if (error != GRPC_ERROR_NONE || c->shutdown) { if (error == GRPC_ERROR_NONE) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("connector shutdown"); // We were shut down after handshaking completed successfully, so // destroy the endpoint here. // TODO(ctiller): It is currently necessary to shutdown endpoints // before destroying them, even if we know that there are no // pending read/write callbacks. This should be fixed, at which // point this can be removed. grpc_endpoint_shutdown(exec_ctx, args->endpoint, GRPC_ERROR_REF(error)); grpc_endpoint_destroy(exec_ctx, args->endpoint); grpc_channel_args_destroy(exec_ctx, args->args); grpc_slice_buffer_destroy_internal(exec_ctx, args->read_buffer); gpr_free(args->read_buffer); } else { error = GRPC_ERROR_REF(error); } memset(c->result, 0, sizeof(*c->result)); } else { c->result->transport = grpc_create_chttp2_transport(exec_ctx, args->args, args->endpoint, 1); GPR_ASSERT(c->result->transport); grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, args->read_buffer); c->result->channel_args = args->args; } grpc_closure *notify = c->notify; c->notify = NULL; grpc_closure_sched(exec_ctx, notify, error); grpc_handshake_manager_destroy(exec_ctx, c->handshake_mgr); c->handshake_mgr = NULL; gpr_mu_unlock(&c->mu); chttp2_connector_unref(exec_ctx, (grpc_connector *)c); } static void start_handshake_locked(grpc_exec_ctx *exec_ctx, chttp2_connector *c) { c->handshake_mgr = grpc_handshake_manager_create(); grpc_handshakers_add(exec_ctx, HANDSHAKER_CLIENT, c->args.channel_args, c->handshake_mgr); grpc_handshake_manager_do_handshake( exec_ctx, c->handshake_mgr, c->endpoint, c->args.channel_args, c->args.deadline, NULL /* acceptor */, on_handshake_done, c); c->endpoint = NULL; // Endpoint handed off to handshake manager. } static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { chttp2_connector *c = arg; gpr_mu_lock(&c->mu); GPR_ASSERT(c->connecting); c->connecting = false; if (error != GRPC_ERROR_NONE || c->shutdown) { if (error == GRPC_ERROR_NONE) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("connector shutdown"); } else { error = GRPC_ERROR_REF(error); } memset(c->result, 0, sizeof(*c->result)); grpc_closure *notify = c->notify; c->notify = NULL; grpc_closure_sched(exec_ctx, notify, error); if (c->endpoint != NULL) { grpc_endpoint_shutdown(exec_ctx, c->endpoint, GRPC_ERROR_REF(error)); } gpr_mu_unlock(&c->mu); chttp2_connector_unref(exec_ctx, arg); } else { GPR_ASSERT(c->endpoint != NULL); start_handshake_locked(exec_ctx, c); gpr_mu_unlock(&c->mu); } } static void chttp2_connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con, const grpc_connect_in_args *args, grpc_connect_out_args *result, grpc_closure *notify) { chttp2_connector *c = (chttp2_connector *)con; grpc_resolved_address addr; grpc_get_subchannel_address_arg(exec_ctx, args->channel_args, &addr); gpr_mu_lock(&c->mu); GPR_ASSERT(c->notify == NULL); c->notify = notify; c->args = *args; c->result = result; GPR_ASSERT(c->endpoint == NULL); chttp2_connector_ref(con); // Ref taken for callback. grpc_closure_init(&c->connected, connected, c, grpc_schedule_on_exec_ctx); GPR_ASSERT(!c->connecting); c->connecting = true; grpc_tcp_client_connect(exec_ctx, &c->connected, &c->endpoint, args->interested_parties, args->channel_args, &addr, args->deadline); gpr_mu_unlock(&c->mu); } static const grpc_connector_vtable chttp2_connector_vtable = { chttp2_connector_ref, chttp2_connector_unref, chttp2_connector_shutdown, chttp2_connector_connect}; grpc_connector *grpc_chttp2_connector_create() { chttp2_connector *c = gpr_zalloc(sizeof(*c)); c->base.vtable = &chttp2_connector_vtable; gpr_mu_init(&c->mu); gpr_ref_init(&c->refs, 1); return &c->base; } grpc-1.3.2/src/core/ext/transport/chttp2/client/chttp2_connector.h000066400000000000000000000035301310511640000251240ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_CLIENT_CHTTP2_CONNECTOR_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_CLIENT_CHTTP2_CONNECTOR_H #include "src/core/ext/filters/client_channel/connector.h" grpc_connector* grpc_chttp2_connector_create(); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_CLIENT_CHTTP2_CONNECTOR_H */ grpc-1.3.2/src/core/ext/transport/chttp2/client/insecure/000077500000000000000000000000001310511640000233115ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/transport/chttp2/client/insecure/README.md000066400000000000000000000000631310511640000245670ustar00rootroot00000000000000Plugin for creating insecure channels using chttp2 grpc-1.3.2/src/core/ext/transport/chttp2/client/insecure/channel_create.c000066400000000000000000000121471310511640000264150ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/ext/transport/chttp2/client/chttp2_connector.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/channel.h" static void client_channel_factory_ref( grpc_client_channel_factory *cc_factory) {} static void client_channel_factory_unref( grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) {} static grpc_subchannel *client_channel_factory_create_subchannel( grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, const grpc_subchannel_args *args) { grpc_connector *connector = grpc_chttp2_connector_create(); grpc_subchannel *s = grpc_subchannel_create(exec_ctx, connector, args); grpc_connector_unref(exec_ctx, connector); return s; } static grpc_channel *client_channel_factory_create_channel( grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, const char *target, grpc_client_channel_type type, const grpc_channel_args *args) { if (target == NULL) { gpr_log(GPR_ERROR, "cannot create channel with NULL target name"); return NULL; } // Add channel arg containing the server URI. grpc_arg arg; arg.type = GRPC_ARG_STRING; arg.key = GRPC_ARG_SERVER_URI; arg.value.string = grpc_resolver_factory_add_default_prefix_if_needed(exec_ctx, target); const char *to_remove[] = {GRPC_ARG_SERVER_URI}; grpc_channel_args *new_args = grpc_channel_args_copy_and_add_and_remove(args, to_remove, 1, &arg, 1); gpr_free(arg.value.string); grpc_channel *channel = grpc_channel_create(exec_ctx, target, new_args, GRPC_CLIENT_CHANNEL, NULL); grpc_channel_args_destroy(exec_ctx, new_args); return channel; } static const grpc_client_channel_factory_vtable client_channel_factory_vtable = {client_channel_factory_ref, client_channel_factory_unref, client_channel_factory_create_subchannel, client_channel_factory_create_channel}; static grpc_client_channel_factory client_channel_factory = { &client_channel_factory_vtable}; /* Create a client channel: Asynchronously: - resolve target - connect to it (trying alternatives as presented) - perform handshakes */ grpc_channel *grpc_insecure_channel_create(const char *target, const grpc_channel_args *args, void *reserved) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE( "grpc_insecure_channel_create(target=%p, args=%p, reserved=%p)", 3, (target, args, reserved)); GPR_ASSERT(reserved == NULL); // Add channel arg containing the client channel factory. grpc_arg arg = grpc_client_channel_factory_create_channel_arg(&client_channel_factory); grpc_channel_args *new_args = grpc_channel_args_copy_and_add(args, &arg, 1); // Create channel. grpc_channel *channel = client_channel_factory_create_channel( &exec_ctx, &client_channel_factory, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, new_args); // Clean up. grpc_channel_args_destroy(&exec_ctx, new_args); grpc_exec_ctx_finish(&exec_ctx); return channel != NULL ? channel : grpc_lame_client_channel_create( target, GRPC_STATUS_INTERNAL, "Failed to create client channel"); } grpc-1.3.2/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c000066400000000000000000000074001310511640000276330ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #ifdef GPR_SUPPORT_CHANNELS_FROM_FD #include #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/tcp_client_posix.h" #include "src/core/lib/iomgr/tcp_posix.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/transport/transport.h" grpc_channel *grpc_insecure_channel_create_from_fd( const char *target, int fd, const grpc_channel_args *args) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE("grpc_insecure_channel_create(target=%p, fd=%d, args=%p)", 3, (target, fd, args)); grpc_arg default_authority_arg; default_authority_arg.type = GRPC_ARG_STRING; default_authority_arg.key = GRPC_ARG_DEFAULT_AUTHORITY; default_authority_arg.value.string = "test.authority"; grpc_channel_args *final_args = grpc_channel_args_copy_and_add(args, &default_authority_arg, 1); int flags = fcntl(fd, F_GETFL, 0); GPR_ASSERT(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0); grpc_endpoint *client = grpc_tcp_client_create_from_fd( &exec_ctx, grpc_fd_create(fd, "client"), args, "fd-client"); grpc_transport *transport = grpc_create_chttp2_transport(&exec_ctx, final_args, client, 1); GPR_ASSERT(transport); grpc_channel *channel = grpc_channel_create( &exec_ctx, target, final_args, GRPC_CLIENT_DIRECT_CHANNEL, transport); grpc_channel_args_destroy(&exec_ctx, final_args); grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL); grpc_exec_ctx_finish(&exec_ctx); return channel != NULL ? channel : grpc_lame_client_channel_create( target, GRPC_STATUS_INTERNAL, "Failed to create client channel"); } #else // !GPR_SUPPORT_CHANNELS_FROM_FD grpc_channel *grpc_insecure_channel_create_from_fd( const char *target, int fd, const grpc_channel_args *args) { GPR_ASSERT(0); return NULL; } #endif // GPR_SUPPORT_CHANNELS_FROM_FD grpc-1.3.2/src/core/ext/transport/chttp2/client/secure/000077500000000000000000000000001310511640000227625ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/transport/chttp2/client/secure/README.md000066400000000000000000000000611310511640000242360ustar00rootroot00000000000000Plugin for creating secure channels using chttp2 grpc-1.3.2/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c000066400000000000000000000243161310511640000274350ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/ext/filters/client_channel/uri_parser.h" #include "src/core/ext/transport/chttp2/client/chttp2_connector.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/transport/lb_targets_info.h" #include "src/core/lib/security/transport/security_connector.h" #include "src/core/lib/slice/slice_hash_table.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/channel.h" static void client_channel_factory_ref( grpc_client_channel_factory *cc_factory) {} static void client_channel_factory_unref( grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) {} static grpc_subchannel_args *get_secure_naming_subchannel_args( grpc_exec_ctx *exec_ctx, const grpc_subchannel_args *args) { grpc_channel_credentials *channel_credentials = grpc_channel_credentials_find_in_args(args->args); if (channel_credentials == NULL) { gpr_log(GPR_ERROR, "Can't create subchannel: channel credentials missing for secure " "channel."); return NULL; } // Make sure security connector does not already exist in args. if (grpc_security_connector_find_in_args(args->args) != NULL) { gpr_log(GPR_ERROR, "Can't create subchannel: security connector already present in " "channel args."); return NULL; } // To which address are we connecting? By default, use the server URI. const grpc_arg *server_uri_arg = grpc_channel_args_find(args->args, GRPC_ARG_SERVER_URI); GPR_ASSERT(server_uri_arg != NULL); GPR_ASSERT(server_uri_arg->type == GRPC_ARG_STRING); const char *server_uri_str = server_uri_arg->value.string; GPR_ASSERT(server_uri_str != NULL); grpc_uri *server_uri = grpc_uri_parse(exec_ctx, server_uri_str, true /* supress errors */); GPR_ASSERT(server_uri != NULL); const char *server_uri_path; server_uri_path = server_uri->path[0] == '/' ? server_uri->path + 1 : server_uri->path; const grpc_slice_hash_table *targets_info = grpc_lb_targets_info_find_in_args(args->args); char *target_name_to_check = NULL; if (targets_info != NULL) { // LB channel // Find the balancer name for the target. const char *target_uri_str = grpc_get_subchannel_address_uri_arg(args->args); grpc_uri *target_uri = grpc_uri_parse(exec_ctx, target_uri_str, false /* suppress errors */); GPR_ASSERT(target_uri != NULL); if (target_uri->path[0] != '\0') { // "path" may be empty const grpc_slice key = grpc_slice_from_static_string( target_uri->path[0] == '/' ? target_uri->path + 1 : target_uri->path); const char *value = grpc_slice_hash_table_get(targets_info, key); if (value != NULL) target_name_to_check = gpr_strdup(value); grpc_slice_unref_internal(exec_ctx, key); } if (target_name_to_check == NULL) { // If the target name to check hasn't already been set, fall back to using // SERVER_URI target_name_to_check = gpr_strdup(server_uri_path); } grpc_uri_destroy(target_uri); } else { // regular channel: the secure name is the original server URI. target_name_to_check = gpr_strdup(server_uri_path); } grpc_uri_destroy(server_uri); GPR_ASSERT(target_name_to_check != NULL); grpc_channel_security_connector *subchannel_security_connector = NULL; // Create the security connector using the credentials and target name. grpc_channel_args *new_args_from_connector = NULL; const grpc_security_status security_status = grpc_channel_credentials_create_security_connector( exec_ctx, channel_credentials, target_name_to_check, args->args, &subchannel_security_connector, &new_args_from_connector); if (security_status != GRPC_SECURITY_OK) { gpr_log(GPR_ERROR, "Failed to create secure subchannel for secure name '%s'", target_name_to_check); gpr_free(target_name_to_check); return NULL; } gpr_free(target_name_to_check); grpc_arg new_security_connector_arg = grpc_security_connector_to_arg(&subchannel_security_connector->base); grpc_channel_args *new_args = grpc_channel_args_copy_and_add( new_args_from_connector != NULL ? new_args_from_connector : args->args, &new_security_connector_arg, 1); GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, &subchannel_security_connector->base, "lb_channel_create"); if (new_args_from_connector != NULL) { grpc_channel_args_destroy(exec_ctx, new_args_from_connector); } grpc_subchannel_args *final_sc_args = gpr_malloc(sizeof(*final_sc_args)); memcpy(final_sc_args, args, sizeof(*args)); final_sc_args->args = new_args; return final_sc_args; } static grpc_subchannel *client_channel_factory_create_subchannel( grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, const grpc_subchannel_args *args) { grpc_subchannel_args *subchannel_args = get_secure_naming_subchannel_args(exec_ctx, args); if (subchannel_args == NULL) { gpr_log( GPR_ERROR, "Failed to create subchannel arguments during subchannel creation."); return NULL; } grpc_connector *connector = grpc_chttp2_connector_create(); grpc_subchannel *s = grpc_subchannel_create(exec_ctx, connector, subchannel_args); grpc_connector_unref(exec_ctx, connector); grpc_channel_args_destroy(exec_ctx, (grpc_channel_args *)subchannel_args->args); gpr_free(subchannel_args); return s; } static grpc_channel *client_channel_factory_create_channel( grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, const char *target, grpc_client_channel_type type, const grpc_channel_args *args) { if (target == NULL) { gpr_log(GPR_ERROR, "cannot create channel with NULL target name"); return NULL; } // Add channel arg containing the server URI. grpc_arg arg; arg.type = GRPC_ARG_STRING; arg.key = GRPC_ARG_SERVER_URI; arg.value.string = grpc_resolver_factory_add_default_prefix_if_needed(exec_ctx, target); const char *to_remove[] = {GRPC_ARG_SERVER_URI}; grpc_channel_args *new_args = grpc_channel_args_copy_and_add_and_remove(args, to_remove, 1, &arg, 1); gpr_free(arg.value.string); grpc_channel *channel = grpc_channel_create(exec_ctx, target, new_args, GRPC_CLIENT_CHANNEL, NULL); grpc_channel_args_destroy(exec_ctx, new_args); return channel; } static const grpc_client_channel_factory_vtable client_channel_factory_vtable = {client_channel_factory_ref, client_channel_factory_unref, client_channel_factory_create_subchannel, client_channel_factory_create_channel}; static grpc_client_channel_factory client_channel_factory = { &client_channel_factory_vtable}; // Create a secure client channel: // Asynchronously: - resolve target // - connect to it (trying alternatives as presented) // - perform handshakes grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds, const char *target, const grpc_channel_args *args, void *reserved) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE( "grpc_secure_channel_create(creds=%p, target=%s, args=%p, " "reserved=%p)", 4, ((void *)creds, target, (void *)args, (void *)reserved)); GPR_ASSERT(reserved == NULL); grpc_channel *channel = NULL; if (creds != NULL) { // Add channel args containing the client channel factory and channel // credentials. grpc_arg args_to_add[] = { grpc_client_channel_factory_create_channel_arg(&client_channel_factory), grpc_channel_credentials_to_arg(creds)}; grpc_channel_args *new_args = grpc_channel_args_copy_and_add( args, args_to_add, GPR_ARRAY_SIZE(args_to_add)); // Create channel. channel = client_channel_factory_create_channel( &exec_ctx, &client_channel_factory, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, new_args); // Clean up. grpc_channel_args_destroy(&exec_ctx, new_args); grpc_exec_ctx_finish(&exec_ctx); } return channel != NULL ? channel : grpc_lame_client_channel_create( target, GRPC_STATUS_INTERNAL, "Failed to create secure client channel"); } grpc-1.3.2/src/core/ext/transport/chttp2/server/000077500000000000000000000000001310511640000215245ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/transport/chttp2/server/chttp2_server.c000066400000000000000000000267231310511640000244740ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/server/chttp2_server.h" #include #include #include #include #include #include #include #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/handshaker.h" #include "src/core/lib/channel/handshaker_registry.h" #include "src/core/lib/channel/http_server_filter.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/tcp_server.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/server.h" typedef struct { grpc_server *server; grpc_tcp_server *tcp_server; grpc_channel_args *args; gpr_mu mu; bool shutdown; grpc_closure tcp_server_shutdown_complete; grpc_closure *server_destroy_listener_done; grpc_handshake_manager *pending_handshake_mgrs; } server_state; typedef struct { server_state *server_state; grpc_pollset *accepting_pollset; grpc_tcp_server_acceptor *acceptor; grpc_handshake_manager *handshake_mgr; } server_connection_state; static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_handshaker_args *args = arg; server_connection_state *connection_state = args->user_data; gpr_mu_lock(&connection_state->server_state->mu); if (error != GRPC_ERROR_NONE || connection_state->server_state->shutdown) { const char *error_str = grpc_error_string(error); gpr_log(GPR_ERROR, "Handshaking failed: %s", error_str); if (error == GRPC_ERROR_NONE && args->endpoint != NULL) { // We were shut down after handshaking completed successfully, so // destroy the endpoint here. // TODO(ctiller): It is currently necessary to shutdown endpoints // before destroying them, even if we know that there are no // pending read/write callbacks. This should be fixed, at which // point this can be removed. grpc_endpoint_shutdown(exec_ctx, args->endpoint, GRPC_ERROR_NONE); grpc_endpoint_destroy(exec_ctx, args->endpoint); grpc_channel_args_destroy(exec_ctx, args->args); grpc_slice_buffer_destroy_internal(exec_ctx, args->read_buffer); gpr_free(args->read_buffer); } } else { // If the handshaking succeeded but there is no endpoint, then the // handshaker may have handed off the connection to some external // code, so we can just clean up here without creating a transport. if (args->endpoint != NULL) { grpc_transport *transport = grpc_create_chttp2_transport(exec_ctx, args->args, args->endpoint, 0); grpc_server_setup_transport( exec_ctx, connection_state->server_state->server, transport, connection_state->accepting_pollset, args->args); grpc_chttp2_transport_start_reading(exec_ctx, transport, args->read_buffer); grpc_channel_args_destroy(exec_ctx, args->args); } } grpc_handshake_manager_pending_list_remove( &connection_state->server_state->pending_handshake_mgrs, connection_state->handshake_mgr); gpr_mu_unlock(&connection_state->server_state->mu); grpc_handshake_manager_destroy(exec_ctx, connection_state->handshake_mgr); grpc_tcp_server_unref(exec_ctx, connection_state->server_state->tcp_server); gpr_free(connection_state->acceptor); gpr_free(connection_state); } static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp, grpc_pollset *accepting_pollset, grpc_tcp_server_acceptor *acceptor) { server_state *state = arg; gpr_mu_lock(&state->mu); if (state->shutdown) { gpr_mu_unlock(&state->mu); grpc_endpoint_destroy(exec_ctx, tcp); gpr_free(acceptor); return; } grpc_handshake_manager *handshake_mgr = grpc_handshake_manager_create(); grpc_handshake_manager_pending_list_add(&state->pending_handshake_mgrs, handshake_mgr); gpr_mu_unlock(&state->mu); grpc_tcp_server_ref(state->tcp_server); server_connection_state *connection_state = gpr_malloc(sizeof(*connection_state)); connection_state->server_state = state; connection_state->accepting_pollset = accepting_pollset; connection_state->acceptor = acceptor; connection_state->handshake_mgr = handshake_mgr; grpc_handshakers_add(exec_ctx, HANDSHAKER_SERVER, state->args, connection_state->handshake_mgr); // TODO(roth): We should really get this timeout value from channel // args instead of hard-coding it. const gpr_timespec deadline = gpr_time_add( gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_seconds(120, GPR_TIMESPAN)); grpc_handshake_manager_do_handshake(exec_ctx, connection_state->handshake_mgr, tcp, state->args, deadline, acceptor, on_handshake_done, connection_state); } /* Server callback: start listening on our ports */ static void server_start_listener(grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg, grpc_pollset **pollsets, size_t pollset_count) { server_state *state = arg; gpr_mu_lock(&state->mu); state->shutdown = false; gpr_mu_unlock(&state->mu); grpc_tcp_server_start(exec_ctx, state->tcp_server, pollsets, pollset_count, on_accept, state); } static void tcp_server_shutdown_complete(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { server_state *state = arg; /* ensure all threads have unlocked */ gpr_mu_lock(&state->mu); grpc_closure *destroy_done = state->server_destroy_listener_done; GPR_ASSERT(state->shutdown); grpc_handshake_manager_pending_list_shutdown_all( exec_ctx, state->pending_handshake_mgrs, GRPC_ERROR_REF(error)); gpr_mu_unlock(&state->mu); // Flush queued work before destroying handshaker factory, since that // may do a synchronous unref. grpc_exec_ctx_flush(exec_ctx); if (destroy_done != NULL) { destroy_done->cb(exec_ctx, destroy_done->cb_arg, GRPC_ERROR_REF(error)); grpc_exec_ctx_flush(exec_ctx); } grpc_channel_args_destroy(exec_ctx, state->args); gpr_mu_destroy(&state->mu); gpr_free(state); } /* Server callback: destroy the tcp listener (so we don't generate further callbacks) */ static void server_destroy_listener(grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg, grpc_closure *destroy_done) { server_state *state = arg; gpr_mu_lock(&state->mu); state->shutdown = true; state->server_destroy_listener_done = destroy_done; grpc_tcp_server *tcp_server = state->tcp_server; gpr_mu_unlock(&state->mu); grpc_tcp_server_shutdown_listeners(exec_ctx, tcp_server); grpc_tcp_server_unref(exec_ctx, tcp_server); } grpc_error *grpc_chttp2_server_add_port(grpc_exec_ctx *exec_ctx, grpc_server *server, const char *addr, grpc_channel_args *args, int *port_num) { grpc_resolved_addresses *resolved = NULL; grpc_tcp_server *tcp_server = NULL; size_t i; size_t count = 0; int port_temp; grpc_error *err = GRPC_ERROR_NONE; server_state *state = NULL; grpc_error **errors = NULL; *port_num = -1; /* resolve address */ err = grpc_blocking_resolve_address(addr, "https", &resolved); if (err != GRPC_ERROR_NONE) { goto error; } state = gpr_zalloc(sizeof(*state)); grpc_closure_init(&state->tcp_server_shutdown_complete, tcp_server_shutdown_complete, state, grpc_schedule_on_exec_ctx); err = grpc_tcp_server_create(exec_ctx, &state->tcp_server_shutdown_complete, args, &tcp_server); if (err != GRPC_ERROR_NONE) { goto error; } state->server = server; state->tcp_server = tcp_server; state->args = args; state->shutdown = true; gpr_mu_init(&state->mu); const size_t naddrs = resolved->naddrs; errors = gpr_malloc(sizeof(*errors) * naddrs); for (i = 0; i < naddrs; i++) { errors[i] = grpc_tcp_server_add_port(tcp_server, &resolved->addrs[i], &port_temp); if (errors[i] == GRPC_ERROR_NONE) { if (*port_num == -1) { *port_num = port_temp; } else { GPR_ASSERT(*port_num == port_temp); } count++; } } if (count == 0) { char *msg; gpr_asprintf(&msg, "No address added out of total %" PRIuPTR " resolved", naddrs); err = GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING(msg, errors, naddrs); gpr_free(msg); goto error; } else if (count != naddrs) { char *msg; gpr_asprintf(&msg, "Only %" PRIuPTR " addresses added out of total %" PRIuPTR " resolved", count, naddrs); err = GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING(msg, errors, naddrs); gpr_free(msg); const char *warning_message = grpc_error_string(err); gpr_log(GPR_INFO, "WARNING: %s", warning_message); /* we managed to bind some addresses: continue */ } grpc_resolved_addresses_destroy(resolved); /* Register with the server only upon success */ grpc_server_add_listener(exec_ctx, server, state, server_start_listener, server_destroy_listener); goto done; /* Error path: cleanup and return */ error: GPR_ASSERT(err != GRPC_ERROR_NONE); if (resolved) { grpc_resolved_addresses_destroy(resolved); } if (tcp_server) { grpc_tcp_server_unref(exec_ctx, tcp_server); } else { grpc_channel_args_destroy(exec_ctx, args); gpr_free(state); } *port_num = 0; done: if (errors != NULL) { for (i = 0; i < naddrs; i++) { GRPC_ERROR_UNREF(errors[i]); } gpr_free(errors); } return err; } grpc-1.3.2/src/core/ext/transport/chttp2/server/chttp2_server.h000066400000000000000000000041751310511640000244760ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_SERVER_CHTTP2_SERVER_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_SERVER_CHTTP2_SERVER_H #include #include "src/core/lib/iomgr/exec_ctx.h" /// Adds a port to \a server. Sets \a port_num to the port number. /// Takes ownership of \a args. grpc_error *grpc_chttp2_server_add_port(grpc_exec_ctx *exec_ctx, grpc_server *server, const char *addr, grpc_channel_args *args, int *port_num); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_SERVER_CHTTP2_SERVER_H */ grpc-1.3.2/src/core/ext/transport/chttp2/server/insecure/000077500000000000000000000000001310511640000233415ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/transport/chttp2/server/insecure/README.md000066400000000000000000000000621310511640000246160ustar00rootroot00000000000000Plugin for creating insecure servers using chttp2 grpc-1.3.2/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c000066400000000000000000000046141310511640000263040ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include "src/core/ext/transport/chttp2/server/chttp2_server.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/server.h" int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; int port_num = 0; GRPC_API_TRACE("grpc_server_add_insecure_http2_port(server=%p, addr=%s)", 2, (server, addr)); grpc_error *err = grpc_chttp2_server_add_port( &exec_ctx, server, addr, grpc_channel_args_copy(grpc_server_get_channel_args(server)), &port_num); if (err != GRPC_ERROR_NONE) { const char *msg = grpc_error_string(err); gpr_log(GPR_ERROR, "%s", msg); GRPC_ERROR_UNREF(err); } grpc_exec_ctx_finish(&exec_ctx); return port_num; } grpc-1.3.2/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c000066400000000000000000000066051310511640000275300ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #ifdef GPR_SUPPORT_CHANNELS_FROM_FD #include #include #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/tcp_posix.h" #include "src/core/lib/surface/completion_queue.h" #include "src/core/lib/surface/server.h" void grpc_server_add_insecure_channel_from_fd(grpc_server *server, void *reserved, int fd) { GPR_ASSERT(reserved == NULL); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; char *name; gpr_asprintf(&name, "fd:%d", fd); grpc_endpoint *server_endpoint = grpc_tcp_create(&exec_ctx, grpc_fd_create(fd, name), grpc_server_get_channel_args(server), name); gpr_free(name); const grpc_channel_args *server_args = grpc_server_get_channel_args(server); grpc_transport *transport = grpc_create_chttp2_transport( &exec_ctx, server_args, server_endpoint, 0 /* is_client */); grpc_pollset **pollsets; size_t num_pollsets = 0; grpc_server_get_pollsets(server, &pollsets, &num_pollsets); for (size_t i = 0; i < num_pollsets; i++) { grpc_endpoint_add_to_pollset(&exec_ctx, server_endpoint, pollsets[i]); } grpc_server_setup_transport(&exec_ctx, server, transport, NULL, server_args); grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL); grpc_exec_ctx_finish(&exec_ctx); } #else // !GPR_SUPPORT_CHANNELS_FROM_FD void grpc_server_add_insecure_channel_from_fd(grpc_server *server, void *reserved, int fd) { GPR_ASSERT(0); } #endif // GPR_SUPPORT_CHANNELS_FROM_FD grpc-1.3.2/src/core/ext/transport/chttp2/server/secure/000077500000000000000000000000001310511640000230125ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/transport/chttp2/server/secure/README.md000066400000000000000000000000601310511640000242650ustar00rootroot00000000000000Plugin for creating secure servers using chttp2 grpc-1.3.2/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c000066400000000000000000000076451310511640000273320ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include "src/core/ext/transport/chttp2/server/chttp2_server.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/handshaker.h" #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/server.h" int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, grpc_server_credentials *creds) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_error *err = GRPC_ERROR_NONE; grpc_server_security_connector *sc = NULL; int port_num = 0; GRPC_API_TRACE( "grpc_server_add_secure_http2_port(" "server=%p, addr=%s, creds=%p)", 3, (server, addr, creds)); // Create security context. if (creds == NULL) { err = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "No credentials specified for secure server port (creds==NULL)"); goto done; } grpc_security_status status = grpc_server_credentials_create_security_connector(&exec_ctx, creds, &sc); if (status != GRPC_SECURITY_OK) { char *msg; gpr_asprintf(&msg, "Unable to create secure server with credentials of type %s.", creds->type); err = grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg), GRPC_ERROR_INT_SECURITY_STATUS, status); gpr_free(msg); goto done; } // Create channel args. grpc_arg args_to_add[2]; args_to_add[0] = grpc_server_credentials_to_arg(creds); args_to_add[1] = grpc_security_connector_to_arg(&sc->base); grpc_channel_args *args = grpc_channel_args_copy_and_add(grpc_server_get_channel_args(server), args_to_add, GPR_ARRAY_SIZE(args_to_add)); // Add server port. err = grpc_chttp2_server_add_port(&exec_ctx, server, addr, args, &port_num); done: if (sc != NULL) { GRPC_SECURITY_CONNECTOR_UNREF(&exec_ctx, &sc->base, "server"); } grpc_exec_ctx_finish(&exec_ctx); if (err != GRPC_ERROR_NONE) { const char *msg = grpc_error_string(err); gpr_log(GPR_ERROR, "%s", msg); GRPC_ERROR_UNREF(err); } return port_num; } grpc-1.3.2/src/core/ext/transport/chttp2/transport/000077500000000000000000000000001310511640000222525ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/transport/chttp2/transport/README.md000066400000000000000000000002301310511640000235240ustar00rootroot00000000000000chttp2 transport plugin - implements grpc over http2 Used by chttp2/{client,server}/{insecure,secure} plugins to implement most of their functionality grpc-1.3.2/src/core/ext/transport/chttp2/transport/bin_decoder.c000066400000000000000000000225161310511640000246610ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/transport/bin_decoder.h" #include #include #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/string.h" static uint8_t decode_table[] = { 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 62, 0x40, 0x40, 0x40, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}; static const uint8_t tail_xtra[4] = {0, 0, 1, 2}; static bool input_is_valid(uint8_t *input_ptr, size_t length) { size_t i; for (i = 0; i < length; ++i) { if ((decode_table[input_ptr[i]] & 0xC0) != 0) { gpr_log(GPR_ERROR, "Base64 decoding failed, invalid character '%c' in base64 " "input.\n", (char)(*input_ptr)); return false; } } return true; } #define COMPOSE_OUTPUT_BYTE_0(input_ptr) \ (uint8_t)((decode_table[input_ptr[0]] << 2) | \ (decode_table[input_ptr[1]] >> 4)) #define COMPOSE_OUTPUT_BYTE_1(input_ptr) \ (uint8_t)((decode_table[input_ptr[1]] << 4) | \ (decode_table[input_ptr[2]] >> 2)) #define COMPOSE_OUTPUT_BYTE_2(input_ptr) \ (uint8_t)((decode_table[input_ptr[2]] << 6) | decode_table[input_ptr[3]]) bool grpc_base64_decode_partial(struct grpc_base64_decode_context *ctx) { size_t input_tail; if (ctx->input_cur > ctx->input_end || ctx->output_cur > ctx->output_end) { return false; } // Process a block of 4 input characters and 3 output bytes while (ctx->input_end >= ctx->input_cur + 4 && ctx->output_end >= ctx->output_cur + 3) { if (!input_is_valid(ctx->input_cur, 4)) return false; ctx->output_cur[0] = COMPOSE_OUTPUT_BYTE_0(ctx->input_cur); ctx->output_cur[1] = COMPOSE_OUTPUT_BYTE_1(ctx->input_cur); ctx->output_cur[2] = COMPOSE_OUTPUT_BYTE_2(ctx->input_cur); ctx->output_cur += 3; ctx->input_cur += 4; } // Process the tail of input data input_tail = (size_t)(ctx->input_end - ctx->input_cur); if (input_tail == 4) { // Process the input data with pad chars if (ctx->input_cur[3] == '=') { if (ctx->input_cur[2] == '=' && ctx->output_end >= ctx->output_cur + 1) { if (!input_is_valid(ctx->input_cur, 2)) return false; *(ctx->output_cur++) = COMPOSE_OUTPUT_BYTE_0(ctx->input_cur); ctx->input_cur += 4; } else if (ctx->output_end >= ctx->output_cur + 2) { if (!input_is_valid(ctx->input_cur, 3)) return false; *(ctx->output_cur++) = COMPOSE_OUTPUT_BYTE_0(ctx->input_cur); *(ctx->output_cur++) = COMPOSE_OUTPUT_BYTE_1(ctx->input_cur); ; ctx->input_cur += 4; } } } else if (ctx->contains_tail && input_tail > 1) { // Process the input data without pad chars, but constains_tail is set if (ctx->output_end >= ctx->output_cur + tail_xtra[input_tail]) { if (!input_is_valid(ctx->input_cur, input_tail)) return false; switch (input_tail) { case 3: ctx->output_cur[1] = COMPOSE_OUTPUT_BYTE_1(ctx->input_cur); case 2: ctx->output_cur[0] = COMPOSE_OUTPUT_BYTE_0(ctx->input_cur); } ctx->output_cur += tail_xtra[input_tail]; ctx->input_cur += input_tail; } } return true; } grpc_slice grpc_chttp2_base64_decode(grpc_exec_ctx *exec_ctx, grpc_slice input) { size_t input_length = GRPC_SLICE_LENGTH(input); size_t output_length = input_length / 4 * 3; struct grpc_base64_decode_context ctx; grpc_slice output; if (input_length % 4 != 0) { gpr_log(GPR_ERROR, "Base64 decoding failed, input of " "grpc_chttp2_base64_decode has a length of %d, which is not a " "multiple of 4.\n", (int)input_length); return grpc_empty_slice(); } if (input_length > 0) { uint8_t *input_end = GRPC_SLICE_END_PTR(input); if (*(--input_end) == '=') { output_length--; if (*(--input_end) == '=') { output_length--; } } } output = grpc_slice_malloc(output_length); ctx.input_cur = GRPC_SLICE_START_PTR(input); ctx.input_end = GRPC_SLICE_END_PTR(input); ctx.output_cur = GRPC_SLICE_START_PTR(output); ctx.output_end = GRPC_SLICE_END_PTR(output); ctx.contains_tail = false; if (!grpc_base64_decode_partial(&ctx)) { char *s = grpc_slice_to_c_string(input); gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s); gpr_free(s); grpc_slice_unref_internal(exec_ctx, output); return grpc_empty_slice(); } GPR_ASSERT(ctx.output_cur == GRPC_SLICE_END_PTR(output)); GPR_ASSERT(ctx.input_cur == GRPC_SLICE_END_PTR(input)); return output; } grpc_slice grpc_chttp2_base64_decode_with_length(grpc_exec_ctx *exec_ctx, grpc_slice input, size_t output_length) { size_t input_length = GRPC_SLICE_LENGTH(input); grpc_slice output = grpc_slice_malloc(output_length); struct grpc_base64_decode_context ctx; // The length of a base64 string cannot be 4 * n + 1 if (input_length % 4 == 1) { gpr_log(GPR_ERROR, "Base64 decoding failed, input of " "grpc_chttp2_base64_decode_with_length has a length of %d, which " "has a tail of 1 byte.\n", (int)input_length); grpc_slice_unref_internal(exec_ctx, output); return grpc_empty_slice(); } if (output_length > input_length / 4 * 3 + tail_xtra[input_length % 4]) { gpr_log(GPR_ERROR, "Base64 decoding failed, output_length %d is longer " "than the max possible output length %d.\n", (int)output_length, (int)(input_length / 4 * 3 + tail_xtra[input_length % 4])); grpc_slice_unref_internal(exec_ctx, output); return grpc_empty_slice(); } ctx.input_cur = GRPC_SLICE_START_PTR(input); ctx.input_end = GRPC_SLICE_END_PTR(input); ctx.output_cur = GRPC_SLICE_START_PTR(output); ctx.output_end = GRPC_SLICE_END_PTR(output); ctx.contains_tail = true; if (!grpc_base64_decode_partial(&ctx)) { char *s = grpc_slice_to_c_string(input); gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s); gpr_free(s); grpc_slice_unref_internal(exec_ctx, output); return grpc_empty_slice(); } GPR_ASSERT(ctx.output_cur == GRPC_SLICE_END_PTR(output)); GPR_ASSERT(ctx.input_cur <= GRPC_SLICE_END_PTR(input)); return output; } grpc-1.3.2/src/core/ext/transport/chttp2/transport/bin_decoder.h000066400000000000000000000057471310511640000246750ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_DECODER_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_DECODER_H #include #include struct grpc_base64_decode_context { /* input/output: */ uint8_t *input_cur; uint8_t *input_end; uint8_t *output_cur; uint8_t *output_end; /* Indicate if the decoder should handle the tail of input data*/ bool contains_tail; }; /* base64 decode a grpc_base64_decode_context util either input_end is reached or output_end is reached. When input_end is reached, (input_end - input_cur) is less than 4. When output_end is reached, (output_end - output_cur) is less than 3. Returns false if decoding is failed. */ bool grpc_base64_decode_partial(struct grpc_base64_decode_context *ctx); /* base64 decode a slice with pad chars. Returns a new slice, does not take ownership of the input. Returns an empty slice if decoding is failed. */ grpc_slice grpc_chttp2_base64_decode(grpc_exec_ctx *exec_ctx, grpc_slice input); /* base64 decode a slice without pad chars, data length is needed. Returns a new slice, does not take ownership of the input. Returns an empty slice if decoding is failed. */ grpc_slice grpc_chttp2_base64_decode_with_length(grpc_exec_ctx *exec_ctx, grpc_slice input, size_t output_length); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_DECODER_H */ grpc-1.3.2/src/core/ext/transport/chttp2/transport/bin_encoder.c000066400000000000000000000201311310511640000246620ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/transport/bin_encoder.h" #include #include #include "src/core/ext/transport/chttp2/transport/huffsyms.h" static const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; typedef struct { uint16_t bits; uint8_t length; } b64_huff_sym; static const b64_huff_sym huff_alphabet[64] = { {0x21, 6}, {0x5d, 7}, {0x5e, 7}, {0x5f, 7}, {0x60, 7}, {0x61, 7}, {0x62, 7}, {0x63, 7}, {0x64, 7}, {0x65, 7}, {0x66, 7}, {0x67, 7}, {0x68, 7}, {0x69, 7}, {0x6a, 7}, {0x6b, 7}, {0x6c, 7}, {0x6d, 7}, {0x6e, 7}, {0x6f, 7}, {0x70, 7}, {0x71, 7}, {0x72, 7}, {0xfc, 8}, {0x73, 7}, {0xfd, 8}, {0x3, 5}, {0x23, 6}, {0x4, 5}, {0x24, 6}, {0x5, 5}, {0x25, 6}, {0x26, 6}, {0x27, 6}, {0x6, 5}, {0x74, 7}, {0x75, 7}, {0x28, 6}, {0x29, 6}, {0x2a, 6}, {0x7, 5}, {0x2b, 6}, {0x76, 7}, {0x2c, 6}, {0x8, 5}, {0x9, 5}, {0x2d, 6}, {0x77, 7}, {0x78, 7}, {0x79, 7}, {0x7a, 7}, {0x7b, 7}, {0x0, 5}, {0x1, 5}, {0x2, 5}, {0x19, 6}, {0x1a, 6}, {0x1b, 6}, {0x1c, 6}, {0x1d, 6}, {0x1e, 6}, {0x1f, 6}, {0x7fb, 11}, {0x18, 6}}; static const uint8_t tail_xtra[3] = {0, 2, 3}; grpc_slice grpc_chttp2_base64_encode(grpc_slice input) { size_t input_length = GRPC_SLICE_LENGTH(input); size_t input_triplets = input_length / 3; size_t tail_case = input_length % 3; size_t output_length = input_triplets * 4 + tail_xtra[tail_case]; grpc_slice output = grpc_slice_malloc(output_length); uint8_t *in = GRPC_SLICE_START_PTR(input); char *out = (char *)GRPC_SLICE_START_PTR(output); size_t i; /* encode full triplets */ for (i = 0; i < input_triplets; i++) { out[0] = alphabet[in[0] >> 2]; out[1] = alphabet[((in[0] & 0x3) << 4) | (in[1] >> 4)]; out[2] = alphabet[((in[1] & 0xf) << 2) | (in[2] >> 6)]; out[3] = alphabet[in[2] & 0x3f]; out += 4; in += 3; } /* encode the remaining bytes */ switch (tail_case) { case 0: break; case 1: out[0] = alphabet[in[0] >> 2]; out[1] = alphabet[(in[0] & 0x3) << 4]; out += 2; in += 1; break; case 2: out[0] = alphabet[in[0] >> 2]; out[1] = alphabet[((in[0] & 0x3) << 4) | (in[1] >> 4)]; out[2] = alphabet[(in[1] & 0xf) << 2]; out += 3; in += 2; break; } GPR_ASSERT(out == (char *)GRPC_SLICE_END_PTR(output)); GPR_ASSERT(in == GRPC_SLICE_END_PTR(input)); return output; } grpc_slice grpc_chttp2_huffman_compress(grpc_slice input) { size_t nbits; uint8_t *in; uint8_t *out; grpc_slice output; uint32_t temp = 0; uint32_t temp_length = 0; nbits = 0; for (in = GRPC_SLICE_START_PTR(input); in != GRPC_SLICE_END_PTR(input); ++in) { nbits += grpc_chttp2_huffsyms[*in].length; } output = grpc_slice_malloc(nbits / 8 + (nbits % 8 != 0)); out = GRPC_SLICE_START_PTR(output); for (in = GRPC_SLICE_START_PTR(input); in != GRPC_SLICE_END_PTR(input); ++in) { int sym = *in; temp <<= grpc_chttp2_huffsyms[sym].length; temp |= grpc_chttp2_huffsyms[sym].bits; temp_length += grpc_chttp2_huffsyms[sym].length; while (temp_length > 8) { temp_length -= 8; *out++ = (uint8_t)(temp >> temp_length); } } if (temp_length) { /* NB: the following integer arithmetic operation needs to be in its * expanded form due to the "integral promotion" performed (see section * 3.2.1.1 of the C89 draft standard). A cast to the smaller container type * is then required to avoid the compiler warning */ *out++ = (uint8_t)((uint8_t)(temp << (8u - temp_length)) | (uint8_t)(0xffu >> temp_length)); } GPR_ASSERT(out == GRPC_SLICE_END_PTR(output)); return output; } typedef struct { uint32_t temp; uint32_t temp_length; uint8_t *out; } huff_out; static void enc_flush_some(huff_out *out) { while (out->temp_length > 8) { out->temp_length -= 8; *out->out++ = (uint8_t)(out->temp >> out->temp_length); } } static void enc_add2(huff_out *out, uint8_t a, uint8_t b) { b64_huff_sym sa = huff_alphabet[a]; b64_huff_sym sb = huff_alphabet[b]; out->temp = (out->temp << (sa.length + sb.length)) | ((uint32_t)sa.bits << sb.length) | sb.bits; out->temp_length += (uint32_t)sa.length + (uint32_t)sb.length; enc_flush_some(out); } static void enc_add1(huff_out *out, uint8_t a) { b64_huff_sym sa = huff_alphabet[a]; out->temp = (out->temp << sa.length) | sa.bits; out->temp_length += sa.length; enc_flush_some(out); } grpc_slice grpc_chttp2_base64_encode_and_huffman_compress(grpc_slice input) { size_t input_length = GRPC_SLICE_LENGTH(input); size_t input_triplets = input_length / 3; size_t tail_case = input_length % 3; size_t output_syms = input_triplets * 4 + tail_xtra[tail_case]; size_t max_output_bits = 11 * output_syms; size_t max_output_length = max_output_bits / 8 + (max_output_bits % 8 != 0); grpc_slice output = grpc_slice_malloc(max_output_length); uint8_t *in = GRPC_SLICE_START_PTR(input); uint8_t *start_out = GRPC_SLICE_START_PTR(output); huff_out out; size_t i; out.temp = 0; out.temp_length = 0; out.out = start_out; /* encode full triplets */ for (i = 0; i < input_triplets; i++) { const uint8_t low_to_high = (uint8_t)((in[0] & 0x3) << 4); const uint8_t high_to_low = in[1] >> 4; enc_add2(&out, in[0] >> 2, low_to_high | high_to_low); const uint8_t a = (uint8_t)((in[1] & 0xf) << 2); const uint8_t b = (in[2] >> 6); enc_add2(&out, a | b, in[2] & 0x3f); in += 3; } /* encode the remaining bytes */ switch (tail_case) { case 0: break; case 1: enc_add2(&out, in[0] >> 2, (uint8_t)((in[0] & 0x3) << 4)); in += 1; break; case 2: { const uint8_t low_to_high = (uint8_t)((in[0] & 0x3) << 4); const uint8_t high_to_low = in[1] >> 4; enc_add2(&out, in[0] >> 2, low_to_high | high_to_low); enc_add1(&out, (uint8_t)((in[1] & 0xf) << 2)); in += 2; break; } } if (out.temp_length) { /* NB: the following integer arithmetic operation needs to be in its * expanded form due to the "integral promotion" performed (see section * 3.2.1.1 of the C89 draft standard). A cast to the smaller container type * is then required to avoid the compiler warning */ *out.out++ = (uint8_t)((uint8_t)(out.temp << (8u - out.temp_length)) | (uint8_t)(0xffu >> out.temp_length)); } GPR_ASSERT(out.out <= GRPC_SLICE_END_PTR(output)); GRPC_SLICE_SET_LENGTH(output, out.out - start_out); GPR_ASSERT(in == GRPC_SLICE_END_PTR(input)); return output; } grpc-1.3.2/src/core/ext/transport/chttp2/transport/bin_encoder.h000066400000000000000000000045431310511640000247000ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_ENCODER_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_ENCODER_H #include /* base64 encode a slice. Returns a new slice, does not take ownership of the input */ grpc_slice grpc_chttp2_base64_encode(grpc_slice input); /* Compress a slice with the static huffman encoder detailed in the hpack standard. Returns a new slice, does not take ownership of the input */ grpc_slice grpc_chttp2_huffman_compress(grpc_slice input); /* equivalent to: grpc_slice x = grpc_chttp2_base64_encode(input); grpc_slice y = grpc_chttp2_huffman_compress(x); grpc_slice_unref_internal(exec_ctx, x); return y; */ grpc_slice grpc_chttp2_base64_encode_and_huffman_compress(grpc_slice input); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_ENCODER_H */ grpc-1.3.2/src/core/ext/transport/chttp2/transport/chttp2_plugin.c000066400000000000000000000035701310511640000252050ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/transport/metadata.h" void grpc_chttp2_plugin_init(void) { grpc_register_tracer("http", &grpc_http_trace); grpc_register_tracer("flowctl", &grpc_flowctl_trace); } void grpc_chttp2_plugin_shutdown(void) {} grpc-1.3.2/src/core/ext/transport/chttp2/transport/chttp2_transport.c000066400000000000000000003400271310511640000257440ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include #include #include #include #include #include #include #include #include #include "src/core/ext/transport/chttp2/transport/internal.h" #include "src/core/ext/transport/chttp2/transport/varint.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/workqueue.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" #include "src/core/lib/transport/error_utils.h" #include "src/core/lib/transport/http2_errors.h" #include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/status_conversion.h" #include "src/core/lib/transport/timeout_encoding.h" #include "src/core/lib/transport/transport.h" #include "src/core/lib/transport/transport_impl.h" #define DEFAULT_WINDOW 65535 #define DEFAULT_CONNECTION_WINDOW_TARGET (1024 * 1024) #define MAX_WINDOW 0x7fffffffu #define MAX_WRITE_BUFFER_SIZE (64 * 1024 * 1024) #define DEFAULT_MAX_HEADER_LIST_SIZE (16 * 1024) #define DEFAULT_CLIENT_KEEPALIVE_TIME_MS INT_MAX #define DEFAULT_CLIENT_KEEPALIVE_TIMEOUT_MS 20000 /* 20 seconds */ #define DEFAULT_SERVER_KEEPALIVE_TIME_MS 7200000 /* 2 hours */ #define DEFAULT_SERVER_KEEPALIVE_TIMEOUT_MS 20000 /* 20 seconds */ #define DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS false #define KEEPALIVE_TIME_BACKOFF_MULTIPLIER 2 static int g_default_client_keepalive_time_ms = DEFAULT_CLIENT_KEEPALIVE_TIME_MS; static int g_default_client_keepalive_timeout_ms = DEFAULT_CLIENT_KEEPALIVE_TIMEOUT_MS; static int g_default_server_keepalive_time_ms = DEFAULT_SERVER_KEEPALIVE_TIME_MS; static int g_default_server_keepalive_timeout_ms = DEFAULT_SERVER_KEEPALIVE_TIMEOUT_MS; static bool g_default_keepalive_permit_without_calls = DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS; #define MAX_CLIENT_STREAM_ID 0x7fffffffu int grpc_http_trace = 0; int grpc_flowctl_trace = 0; static const grpc_transport_vtable vtable; /* forward declarations of various callbacks that we'll build closures around */ static void write_action_begin_locked(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error); static void write_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error); static void write_action_end_locked(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error); static void read_action_locked(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error); static void complete_fetch_locked(grpc_exec_ctx *exec_ctx, void *gs, grpc_error *error); /** Set a transport level setting, and push it to our peer */ static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_setting_id id, uint32_t value); static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_error *error); /** Start new streams that have been created if we can */ static void maybe_start_some_streams(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); static void connectivity_state_set(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_connectivity_state state, grpc_error *error, const char *reason); static void incoming_byte_stream_update_flow_control(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, size_t max_size_hint, size_t have_already); static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx, void *byte_stream, grpc_error *error_ignored); static void benign_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error); static void destructive_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error); static void post_benign_reclaimer(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); static void post_destructive_reclaimer(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); static void close_transport_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_error *error); static void end_all_the_calls(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_error *error); static void start_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp, grpc_error *error); static void finish_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp, grpc_error *error); static void cancel_pings(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_error *error); static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_ping_type ping_type, grpc_closure *on_initiate, grpc_closure *on_complete); static void retry_initiate_ping_locked(grpc_exec_ctx *exec_ctx, void *tp, grpc_error *error); #define DEFAULT_MIN_TIME_BETWEEN_PINGS_MS 0 #define DEFAULT_MAX_PINGS_BETWEEN_DATA 3 #define DEFAULT_MAX_PING_STRIKES 2 #define DEFAULT_MIN_PING_INTERVAL_WITHOUT_DATA_MS 300000 /* 5 minutes */ /** keepalive-relevant functions */ static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); static void start_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); static void finish_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); static void keepalive_watchdog_fired_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); /******************************************************************************* * CONSTRUCTION/DESTRUCTION/REFCOUNTING */ static void destruct_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { size_t i; grpc_endpoint_destroy(exec_ctx, t->ep); grpc_slice_buffer_destroy_internal(exec_ctx, &t->qbuf); grpc_slice_buffer_destroy_internal(exec_ctx, &t->outbuf); grpc_chttp2_hpack_compressor_destroy(exec_ctx, &t->hpack_compressor); grpc_slice_buffer_destroy_internal(exec_ctx, &t->read_buffer); grpc_chttp2_hpack_parser_destroy(exec_ctx, &t->hpack_parser); grpc_chttp2_goaway_parser_destroy(&t->goaway_parser); for (i = 0; i < STREAM_LIST_COUNT; i++) { GPR_ASSERT(t->lists[i].head == NULL); GPR_ASSERT(t->lists[i].tail == NULL); } GPR_ASSERT(grpc_chttp2_stream_map_size(&t->stream_map) == 0); grpc_chttp2_stream_map_destroy(&t->stream_map); grpc_connectivity_state_destroy(exec_ctx, &t->channel_callback.state_tracker); GRPC_COMBINER_UNREF(exec_ctx, t->combiner, "chttp2_transport"); cancel_pings(exec_ctx, t, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Transport destroyed")); while (t->write_cb_pool) { grpc_chttp2_write_cb *next = t->write_cb_pool->next; gpr_free(t->write_cb_pool); t->write_cb_pool = next; } gpr_free(t->ping_acks); gpr_free(t->peer_string); gpr_free(t); } #ifdef GRPC_CHTTP2_REFCOUNTING_DEBUG void grpc_chttp2_unref_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, const char *reason, const char *file, int line) { gpr_log(GPR_DEBUG, "chttp2:unref:%p %" PRIdPTR "->%" PRIdPTR " %s [%s:%d]", t, t->refs.count, t->refs.count - 1, reason, file, line); if (!gpr_unref(&t->refs)) return; destruct_transport(exec_ctx, t); } void grpc_chttp2_ref_transport(grpc_chttp2_transport *t, const char *reason, const char *file, int line) { gpr_log(GPR_DEBUG, "chttp2: ref:%p %" PRIdPTR "->%" PRIdPTR " %s [%s:%d]", t, t->refs.count, t->refs.count + 1, reason, file, line); gpr_ref(&t->refs); } #else void grpc_chttp2_unref_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { if (!gpr_unref(&t->refs)) return; destruct_transport(exec_ctx, t); } void grpc_chttp2_ref_transport(grpc_chttp2_transport *t) { gpr_ref(&t->refs); } #endif static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, const grpc_channel_args *channel_args, grpc_endpoint *ep, bool is_client) { size_t i; int j; GPR_ASSERT(strlen(GRPC_CHTTP2_CLIENT_CONNECT_STRING) == GRPC_CHTTP2_CLIENT_CONNECT_STRLEN); t->base.vtable = &vtable; t->ep = ep; /* one ref is for destroy */ gpr_ref_init(&t->refs, 1); t->combiner = grpc_combiner_create(grpc_endpoint_get_workqueue(ep)); t->peer_string = grpc_endpoint_get_peer(ep); t->endpoint_reading = 1; t->next_stream_id = is_client ? 1 : 2; t->is_client = is_client; t->outgoing_window = DEFAULT_WINDOW; t->incoming_window = DEFAULT_WINDOW; t->deframe_state = is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0; t->is_first_frame = true; grpc_connectivity_state_init( &t->channel_callback.state_tracker, GRPC_CHANNEL_READY, is_client ? "client_transport" : "server_transport"); grpc_slice_buffer_init(&t->qbuf); grpc_slice_buffer_init(&t->outbuf); grpc_chttp2_hpack_compressor_init(&t->hpack_compressor); grpc_closure_init(&t->write_action, write_action, t, grpc_schedule_on_exec_ctx); grpc_closure_init(&t->read_action_locked, read_action_locked, t, grpc_combiner_scheduler(t->combiner, false)); grpc_closure_init(&t->benign_reclaimer_locked, benign_reclaimer_locked, t, grpc_combiner_scheduler(t->combiner, false)); grpc_closure_init(&t->destructive_reclaimer_locked, destructive_reclaimer_locked, t, grpc_combiner_scheduler(t->combiner, false)); grpc_closure_init(&t->retry_initiate_ping_locked, retry_initiate_ping_locked, t, grpc_combiner_scheduler(t->combiner, false)); grpc_closure_init(&t->start_bdp_ping_locked, start_bdp_ping_locked, t, grpc_combiner_scheduler(t->combiner, false)); grpc_closure_init(&t->finish_bdp_ping_locked, finish_bdp_ping_locked, t, grpc_combiner_scheduler(t->combiner, false)); grpc_closure_init(&t->init_keepalive_ping_locked, init_keepalive_ping_locked, t, grpc_combiner_scheduler(t->combiner, false)); grpc_closure_init(&t->start_keepalive_ping_locked, start_keepalive_ping_locked, t, grpc_combiner_scheduler(t->combiner, false)); grpc_closure_init(&t->finish_keepalive_ping_locked, finish_keepalive_ping_locked, t, grpc_combiner_scheduler(t->combiner, false)); grpc_closure_init(&t->keepalive_watchdog_fired_locked, keepalive_watchdog_fired_locked, t, grpc_combiner_scheduler(t->combiner, false)); grpc_bdp_estimator_init(&t->bdp_estimator, t->peer_string); t->last_pid_update = gpr_now(GPR_CLOCK_MONOTONIC); grpc_pid_controller_init( &t->pid_controller, (grpc_pid_controller_args){.gain_p = 4, .gain_i = 8, .gain_d = 0, .initial_control_value = log2(DEFAULT_WINDOW), .min_control_value = -1, .max_control_value = 25, .integral_range = 10}); grpc_chttp2_goaway_parser_init(&t->goaway_parser); grpc_chttp2_hpack_parser_init(exec_ctx, &t->hpack_parser); grpc_slice_buffer_init(&t->read_buffer); /* 8 is a random stab in the dark as to a good initial size: it's small enough that it shouldn't waste memory for infrequently used connections, yet large enough that the exponential growth should happen nicely when it's needed. TODO(ctiller): tune this */ grpc_chttp2_stream_map_init(&t->stream_map, 8); /* copy in initial settings to all setting sets */ for (i = 0; i < GRPC_CHTTP2_NUM_SETTINGS; i++) { for (j = 0; j < GRPC_NUM_SETTING_SETS; j++) { t->settings[j][i] = grpc_chttp2_settings_parameters[i].default_value; } } t->dirtied_local_settings = 1; /* Hack: it's common for implementations to assume 65536 bytes initial send window -- this should by rights be 0 */ t->force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; t->sent_local_settings = 0; t->write_buffer_size = DEFAULT_WINDOW; t->enable_bdp_probe = true; if (is_client) { grpc_slice_buffer_add(&t->outbuf, grpc_slice_from_copied_string( GRPC_CHTTP2_CLIENT_CONNECT_STRING)); grpc_chttp2_initiate_write(exec_ctx, t, false, "initial_write"); } /* configure http2 the way we like it */ if (is_client) { push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0); push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0); } push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, DEFAULT_WINDOW); push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE, DEFAULT_MAX_HEADER_LIST_SIZE); push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA, 1); t->ping_policy = (grpc_chttp2_repeated_ping_policy){ .max_pings_without_data = DEFAULT_MAX_PINGS_BETWEEN_DATA, .min_time_between_pings = gpr_time_from_millis(DEFAULT_MIN_TIME_BETWEEN_PINGS_MS, GPR_TIMESPAN), .max_ping_strikes = DEFAULT_MAX_PING_STRIKES, .min_ping_interval_without_data = gpr_time_from_millis( DEFAULT_MIN_PING_INTERVAL_WITHOUT_DATA_MS, GPR_TIMESPAN), }; /* Keepalive setting */ if (t->is_client) { t->keepalive_time = g_default_client_keepalive_time_ms == INT_MAX ? gpr_inf_future(GPR_TIMESPAN) : gpr_time_from_millis(g_default_client_keepalive_time_ms, GPR_TIMESPAN); t->keepalive_timeout = g_default_client_keepalive_timeout_ms == INT_MAX ? gpr_inf_future(GPR_TIMESPAN) : gpr_time_from_millis(g_default_client_keepalive_timeout_ms, GPR_TIMESPAN); } else { t->keepalive_time = g_default_server_keepalive_time_ms == INT_MAX ? gpr_inf_future(GPR_TIMESPAN) : gpr_time_from_millis(g_default_server_keepalive_time_ms, GPR_TIMESPAN); t->keepalive_timeout = g_default_server_keepalive_timeout_ms == INT_MAX ? gpr_inf_future(GPR_TIMESPAN) : gpr_time_from_millis(g_default_server_keepalive_timeout_ms, GPR_TIMESPAN); } t->keepalive_permit_without_calls = g_default_keepalive_permit_without_calls; if (channel_args) { for (i = 0; i < channel_args->num_args; i++) { if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER)) { const grpc_integer_options options = {-1, 0, INT_MAX}; const int value = grpc_channel_arg_get_integer(&channel_args->args[i], options); if (value >= 0) { if ((t->next_stream_id & 1) != (value & 1)) { gpr_log(GPR_ERROR, "%s: low bit must be %d on %s", GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER, t->next_stream_id & 1, is_client ? "client" : "server"); } else { t->next_stream_id = (uint32_t)value; } } } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER)) { const grpc_integer_options options = {-1, 0, INT_MAX}; const int value = grpc_channel_arg_get_integer(&channel_args->args[i], options); if (value >= 0) { grpc_chttp2_hpack_compressor_set_max_usable_size(&t->hpack_compressor, (uint32_t)value); } } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA)) { t->ping_policy.max_pings_without_data = grpc_channel_arg_get_integer( &channel_args->args[i], (grpc_integer_options){DEFAULT_MAX_PINGS_BETWEEN_DATA, 0, INT_MAX}); } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_MAX_PING_STRIKES)) { t->ping_policy.max_ping_strikes = grpc_channel_arg_get_integer( &channel_args->args[i], (grpc_integer_options){DEFAULT_MAX_PING_STRIKES, 0, INT_MAX}); } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_MIN_TIME_BETWEEN_PINGS_MS)) { t->ping_policy.min_time_between_pings = gpr_time_from_millis( grpc_channel_arg_get_integer( &channel_args->args[i], (grpc_integer_options){DEFAULT_MIN_TIME_BETWEEN_PINGS_MS, 0, INT_MAX}), GPR_TIMESPAN); } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_MIN_PING_INTERVAL_WITHOUT_DATA_MS)) { t->ping_policy.min_ping_interval_without_data = gpr_time_from_millis( grpc_channel_arg_get_integer( &channel_args->args[i], (grpc_integer_options){ DEFAULT_MIN_PING_INTERVAL_WITHOUT_DATA_MS, 0, INT_MAX}), GPR_TIMESPAN); } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE)) { t->write_buffer_size = (uint32_t)grpc_channel_arg_get_integer( &channel_args->args[i], (grpc_integer_options){0, 0, MAX_WRITE_BUFFER_SIZE}); } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_BDP_PROBE)) { t->enable_bdp_probe = grpc_channel_arg_get_integer( &channel_args->args[i], (grpc_integer_options){1, 0, 1}); } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_KEEPALIVE_TIME_MS)) { const int value = grpc_channel_arg_get_integer( &channel_args->args[i], (grpc_integer_options){t->is_client ? g_default_client_keepalive_time_ms : g_default_server_keepalive_time_ms, 1, INT_MAX}); t->keepalive_time = value == INT_MAX ? gpr_inf_future(GPR_TIMESPAN) : gpr_time_from_millis(value, GPR_TIMESPAN); } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_KEEPALIVE_TIMEOUT_MS)) { const int value = grpc_channel_arg_get_integer( &channel_args->args[i], (grpc_integer_options){t->is_client ? g_default_client_keepalive_timeout_ms : g_default_server_keepalive_timeout_ms, 0, INT_MAX}); t->keepalive_timeout = value == INT_MAX ? gpr_inf_future(GPR_TIMESPAN) : gpr_time_from_millis(value, GPR_TIMESPAN); } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS)) { t->keepalive_permit_without_calls = (uint32_t)grpc_channel_arg_get_integer( &channel_args->args[i], (grpc_integer_options){0, 0, 1}); } else { static const struct { const char *channel_arg_name; grpc_chttp2_setting_id setting_id; grpc_integer_options integer_options; bool availability[2] /* server, client */; } settings_map[] = { {GRPC_ARG_MAX_CONCURRENT_STREAMS, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, {-1, 0, INT32_MAX}, {true, false}}, {GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER, GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE, {-1, 0, INT32_MAX}, {true, true}}, {GRPC_ARG_MAX_METADATA_SIZE, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE, {-1, 0, INT32_MAX}, {true, true}}, {GRPC_ARG_HTTP2_MAX_FRAME_SIZE, GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE, {-1, 16384, 16777215}, {true, true}}, {GRPC_ARG_HTTP2_ENABLE_TRUE_BINARY, GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA, {1, 0, 1}, {true, true}}, {GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, {-1, 5, INT32_MAX}, {true, true}}}; for (j = 0; j < (int)GPR_ARRAY_SIZE(settings_map); j++) { if (0 == strcmp(channel_args->args[i].key, settings_map[j].channel_arg_name)) { if (!settings_map[j].availability[is_client]) { gpr_log(GPR_DEBUG, "%s is not available on %s", settings_map[j].channel_arg_name, is_client ? "clients" : "servers"); } else { int value = grpc_channel_arg_get_integer( &channel_args->args[i], settings_map[j].integer_options); if (value >= 0) { push_setting(exec_ctx, t, settings_map[j].setting_id, (uint32_t)value); } } break; } } } } } t->ping_state.pings_before_data_required = t->ping_policy.max_pings_without_data; t->ping_state.is_delayed_ping_timer_set = false; t->ping_recv_state.last_ping_recv_time = gpr_inf_past(GPR_CLOCK_MONOTONIC); t->ping_recv_state.ping_strikes = 0; /* Start keepalive pings */ if (gpr_time_cmp(t->keepalive_time, gpr_inf_future(GPR_TIMESPAN)) != 0) { t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING; GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping"); grpc_timer_init( exec_ctx, &t->keepalive_ping_timer, gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time), &t->init_keepalive_ping_locked, gpr_now(GPR_CLOCK_MONOTONIC)); } grpc_chttp2_initiate_write(exec_ctx, t, false, "init"); post_benign_reclaimer(exec_ctx, t); } static void destroy_transport_locked(grpc_exec_ctx *exec_ctx, void *tp, grpc_error *error) { grpc_chttp2_transport *t = tp; t->destroying = 1; close_transport_locked( exec_ctx, t, grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Transport destroyed"), GRPC_ERROR_INT_OCCURRED_DURING_WRITE, t->write_state)); GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "destroy"); } static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) { grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_closure_sched(exec_ctx, grpc_closure_create( destroy_transport_locked, t, grpc_combiner_scheduler(t->combiner, false)), GRPC_ERROR_NONE); } static void close_transport_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_error *error) { if (!t->closed) { if (!grpc_error_has_clear_grpc_status(error)) { error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); } if (t->write_state != GRPC_CHTTP2_WRITE_STATE_IDLE) { if (t->close_transport_on_writes_finished == NULL) { t->close_transport_on_writes_finished = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Delayed close due to in-progress write"); } t->close_transport_on_writes_finished = grpc_error_add_child(t->close_transport_on_writes_finished, error); return; } t->closed = 1; connectivity_state_set(exec_ctx, t, GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_REF(error), "close_transport"); grpc_endpoint_shutdown(exec_ctx, t->ep, GRPC_ERROR_REF(error)); if (t->is_client) { switch (t->keepalive_state) { case GRPC_CHTTP2_KEEPALIVE_STATE_WAITING: { grpc_timer_cancel(exec_ctx, &t->keepalive_ping_timer); break; } case GRPC_CHTTP2_KEEPALIVE_STATE_PINGING: { grpc_timer_cancel(exec_ctx, &t->keepalive_ping_timer); grpc_timer_cancel(exec_ctx, &t->keepalive_watchdog_timer); break; } case GRPC_CHTTP2_KEEPALIVE_STATE_DYING: { break; } } } /* flush writable stream list to avoid dangling references */ grpc_chttp2_stream *s; while (grpc_chttp2_list_pop_writable_stream(t, &s)) { GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2_writing:close"); } end_all_the_calls(exec_ctx, t, GRPC_ERROR_REF(error)); cancel_pings(exec_ctx, t, GRPC_ERROR_REF(error)); } GRPC_ERROR_UNREF(error); } #ifdef GRPC_STREAM_REFCOUNT_DEBUG void grpc_chttp2_stream_ref(grpc_chttp2_stream *s, const char *reason) { grpc_stream_ref(s->refcount, reason); } void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream *s, const char *reason) { grpc_stream_unref(exec_ctx, s->refcount, reason); } #else void grpc_chttp2_stream_ref(grpc_chttp2_stream *s) { grpc_stream_ref(s->refcount); } void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream *s) { grpc_stream_unref(exec_ctx, s->refcount); } #endif static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_stream_refcount *refcount, const void *server_data, gpr_arena *arena) { GPR_TIMER_BEGIN("init_stream", 0); grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; s->t = t; s->refcount = refcount; /* We reserve one 'active stream' that's dropped when the stream is read-closed. The others are for incoming_byte_streams that are actively reading */ gpr_ref_init(&s->active_streams, 1); GRPC_CHTTP2_STREAM_REF(s, "chttp2"); grpc_chttp2_incoming_metadata_buffer_init(&s->metadata_buffer[0], arena); grpc_chttp2_incoming_metadata_buffer_init(&s->metadata_buffer[1], arena); grpc_chttp2_data_parser_init(&s->data_parser); grpc_slice_buffer_init(&s->flow_controlled_buffer); s->deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC); grpc_closure_init(&s->complete_fetch_locked, complete_fetch_locked, s, grpc_schedule_on_exec_ctx); GRPC_CHTTP2_REF_TRANSPORT(t, "stream"); if (server_data) { s->id = (uint32_t)(uintptr_t)server_data; *t->accepting_stream = s; grpc_chttp2_stream_map_add(&t->stream_map, s->id, s); post_destructive_reclaimer(exec_ctx, t); } GPR_TIMER_END("init_stream", 0); return 0; } static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, void *sp, grpc_error *error) { grpc_byte_stream *bs; grpc_chttp2_stream *s = sp; grpc_chttp2_transport *t = s->t; GPR_TIMER_BEGIN("destroy_stream", 0); GPR_ASSERT((s->write_closed && s->read_closed) || s->id == 0); if (s->id != 0) { GPR_ASSERT(grpc_chttp2_stream_map_find(&t->stream_map, s->id) == NULL); } while ((bs = grpc_chttp2_incoming_frame_queue_pop(&s->incoming_frames))) { incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE); } grpc_chttp2_list_remove_stalled_by_transport(t, s); grpc_chttp2_list_remove_stalled_by_stream(t, s); for (int i = 0; i < STREAM_LIST_COUNT; i++) { if (s->included[i]) { gpr_log(GPR_ERROR, "%s stream %d still included in list %d", t->is_client ? "client" : "server", s->id, i); abort(); } } GPR_ASSERT(s->send_initial_metadata_finished == NULL); GPR_ASSERT(s->fetching_send_message == NULL); GPR_ASSERT(s->send_trailing_metadata_finished == NULL); GPR_ASSERT(s->recv_initial_metadata_ready == NULL); GPR_ASSERT(s->recv_message_ready == NULL); GPR_ASSERT(s->recv_trailing_metadata_finished == NULL); grpc_chttp2_data_parser_destroy(exec_ctx, &s->data_parser); grpc_chttp2_incoming_metadata_buffer_destroy(exec_ctx, &s->metadata_buffer[0]); grpc_chttp2_incoming_metadata_buffer_destroy(exec_ctx, &s->metadata_buffer[1]); grpc_slice_buffer_destroy_internal(exec_ctx, &s->flow_controlled_buffer); GRPC_ERROR_UNREF(s->read_closed_error); GRPC_ERROR_UNREF(s->write_closed_error); if (s->incoming_window_delta > 0) { GRPC_CHTTP2_FLOW_DEBIT_STREAM_INCOMING_WINDOW_DELTA( "destroy", t, s, s->incoming_window_delta); } else if (s->incoming_window_delta < 0) { GRPC_CHTTP2_FLOW_CREDIT_STREAM_INCOMING_WINDOW_DELTA( "destroy", t, s, -s->incoming_window_delta); } GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "stream"); GPR_TIMER_END("destroy_stream", 0); grpc_closure_sched(exec_ctx, s->destroy_stream_arg, GRPC_ERROR_NONE); } static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_closure *then_schedule_closure) { GPR_TIMER_BEGIN("destroy_stream", 0); grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; s->destroy_stream_arg = then_schedule_closure; grpc_closure_sched( exec_ctx, grpc_closure_init(&s->destroy_stream, destroy_stream_locked, s, grpc_combiner_scheduler(t->combiner, false)), GRPC_ERROR_NONE); GPR_TIMER_END("destroy_stream", 0); } grpc_chttp2_stream *grpc_chttp2_parsing_lookup_stream(grpc_chttp2_transport *t, uint32_t id) { return grpc_chttp2_stream_map_find(&t->stream_map, id); } grpc_chttp2_stream *grpc_chttp2_parsing_accept_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, uint32_t id) { if (t->channel_callback.accept_stream == NULL) { return NULL; } grpc_chttp2_stream *accepting; GPR_ASSERT(t->accepting_stream == NULL); t->accepting_stream = &accepting; t->channel_callback.accept_stream(exec_ctx, t->channel_callback.accept_stream_user_data, &t->base, (void *)(uintptr_t)id); t->accepting_stream = NULL; return accepting; } /******************************************************************************* * OUTPUT PROCESSING */ static const char *write_state_name(grpc_chttp2_write_state st) { switch (st) { case GRPC_CHTTP2_WRITE_STATE_IDLE: return "IDLE"; case GRPC_CHTTP2_WRITE_STATE_WRITING: return "WRITING"; case GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE: return "WRITING+MORE"; case GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE_AND_COVERED_BY_POLLER: return "WRITING+MORE+COVERED"; } GPR_UNREACHABLE_CODE(return "UNKNOWN"); } static void set_write_state(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_write_state st, const char *reason) { GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_DEBUG, "W:%p %s state %s -> %s [%s]", t, t->is_client ? "CLIENT" : "SERVER", write_state_name(t->write_state), write_state_name(st), reason)); t->write_state = st; if (st == GRPC_CHTTP2_WRITE_STATE_IDLE) { grpc_closure_list_sched(exec_ctx, &t->run_after_write); if (t->close_transport_on_writes_finished != NULL) { grpc_error *err = t->close_transport_on_writes_finished; t->close_transport_on_writes_finished = NULL; close_transport_locked(exec_ctx, t, err); } } } void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, bool covered_by_poller, const char *reason) { GPR_TIMER_BEGIN("grpc_chttp2_initiate_write", 0); switch (t->write_state) { case GRPC_CHTTP2_WRITE_STATE_IDLE: set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING, reason); GRPC_CHTTP2_REF_TRANSPORT(t, "writing"); grpc_closure_sched( exec_ctx, grpc_closure_init( &t->write_action_begin_locked, write_action_begin_locked, t, grpc_combiner_finally_scheduler(t->combiner, covered_by_poller)), GRPC_ERROR_NONE); break; case GRPC_CHTTP2_WRITE_STATE_WRITING: set_write_state( exec_ctx, t, covered_by_poller ? GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE_AND_COVERED_BY_POLLER : GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE, reason); break; case GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE: if (covered_by_poller) { set_write_state( exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE_AND_COVERED_BY_POLLER, reason); } break; case GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE_AND_COVERED_BY_POLLER: break; } GPR_TIMER_END("grpc_chttp2_initiate_write", 0); } void grpc_chttp2_become_writable( grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_chttp2_stream_write_type stream_write_type, const char *reason) { if (!t->closed && grpc_chttp2_list_add_writable_stream(t, s)) { GRPC_CHTTP2_STREAM_REF(s, "chttp2_writing:become"); } switch (stream_write_type) { case GRPC_CHTTP2_STREAM_WRITE_PIGGYBACK: break; case GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED: grpc_chttp2_initiate_write(exec_ctx, t, true, reason); break; case GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED: grpc_chttp2_initiate_write(exec_ctx, t, false, reason); break; } } static void write_action_begin_locked(grpc_exec_ctx *exec_ctx, void *gt, grpc_error *error_ignored) { GPR_TIMER_BEGIN("write_action_begin_locked", 0); grpc_chttp2_transport *t = gt; GPR_ASSERT(t->write_state != GRPC_CHTTP2_WRITE_STATE_IDLE); if (!t->closed && grpc_chttp2_begin_write(exec_ctx, t)) { set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING, "begin writing"); grpc_closure_sched(exec_ctx, &t->write_action, GRPC_ERROR_NONE); } else { set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_IDLE, "begin writing nothing"); GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "writing"); } GPR_TIMER_END("write_action_begin_locked", 0); } static void write_action(grpc_exec_ctx *exec_ctx, void *gt, grpc_error *error) { grpc_chttp2_transport *t = gt; GPR_TIMER_BEGIN("write_action", 0); grpc_endpoint_write( exec_ctx, t->ep, &t->outbuf, grpc_closure_init(&t->write_action_end_locked, write_action_end_locked, t, grpc_combiner_scheduler(t->combiner, false))); GPR_TIMER_END("write_action", 0); } static void write_action_end_locked(grpc_exec_ctx *exec_ctx, void *tp, grpc_error *error) { GPR_TIMER_BEGIN("terminate_writing_with_lock", 0); grpc_chttp2_transport *t = tp; if (error != GRPC_ERROR_NONE) { close_transport_locked(exec_ctx, t, GRPC_ERROR_REF(error)); } if (t->sent_goaway_state == GRPC_CHTTP2_GOAWAY_SEND_SCHEDULED) { t->sent_goaway_state = GRPC_CHTTP2_GOAWAY_SENT; if (grpc_chttp2_stream_map_size(&t->stream_map) == 0) { close_transport_locked( exec_ctx, t, GRPC_ERROR_CREATE_FROM_STATIC_STRING("goaway sent")); } } switch (t->write_state) { case GRPC_CHTTP2_WRITE_STATE_IDLE: GPR_UNREACHABLE_CODE(break); case GRPC_CHTTP2_WRITE_STATE_WRITING: GPR_TIMER_MARK("state=writing", 0); set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_IDLE, "finish writing"); break; case GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE: GPR_TIMER_MARK("state=writing_stale_no_poller", 0); set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING, "continue writing [!covered]"); GRPC_CHTTP2_REF_TRANSPORT(t, "writing"); grpc_closure_run( exec_ctx, grpc_closure_init( &t->write_action_begin_locked, write_action_begin_locked, t, grpc_combiner_finally_scheduler(t->combiner, false)), GRPC_ERROR_NONE); break; case GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE_AND_COVERED_BY_POLLER: GPR_TIMER_MARK("state=writing_stale_with_poller", 0); set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING, "continue writing [covered]"); GRPC_CHTTP2_REF_TRANSPORT(t, "writing"); grpc_closure_run( exec_ctx, grpc_closure_init(&t->write_action_begin_locked, write_action_begin_locked, t, grpc_combiner_finally_scheduler(t->combiner, true)), GRPC_ERROR_NONE); break; } grpc_chttp2_end_write(exec_ctx, t, GRPC_ERROR_REF(error)); GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "writing"); GPR_TIMER_END("terminate_writing_with_lock", 0); } static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_setting_id id, uint32_t value) { const grpc_chttp2_setting_parameters *sp = &grpc_chttp2_settings_parameters[id]; uint32_t use_value = GPR_CLAMP(value, sp->min_value, sp->max_value); if (use_value != value) { gpr_log(GPR_INFO, "Requested parameter %s clamped from %d to %d", sp->name, value, use_value); } if (use_value != t->settings[GRPC_LOCAL_SETTINGS][id]) { t->settings[GRPC_LOCAL_SETTINGS][id] = use_value; t->dirtied_local_settings = 1; grpc_chttp2_initiate_write(exec_ctx, t, false, "push_setting"); } } void grpc_chttp2_add_incoming_goaway(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, uint32_t goaway_error, grpc_slice goaway_text) { // GRPC_CHTTP2_IF_TRACING( // gpr_log(GPR_DEBUG, "got goaway [%d]: %s", goaway_error, msg)); t->seen_goaway = 1; /* When a client receives a GOAWAY with error code ENHANCE_YOUR_CALM and debug * data equal to “too_many_pingsâ€, it should log the occurrence at a log level * that is enabled by default and double the configured KEEPALIVE_TIME used * for new connections on that channel. */ if (t->is_client && goaway_error == GRPC_HTTP2_ENHANCE_YOUR_CALM && grpc_slice_str_cmp(goaway_text, "too_many_pings") == 0) { gpr_log(GPR_ERROR, "Received a GOAWAY with error code ENHANCE_YOUR_CALM and debug " "data equal to \"too_many_pings\""); double current_keepalive_time_ms = gpr_timespec_to_micros(t->keepalive_time) / 1000; t->keepalive_time = current_keepalive_time_ms > INT_MAX / KEEPALIVE_TIME_BACKOFF_MULTIPLIER ? gpr_inf_future(GPR_TIMESPAN) : gpr_time_from_millis((int64_t)(current_keepalive_time_ms * KEEPALIVE_TIME_BACKOFF_MULTIPLIER), GPR_TIMESPAN); } /* lie: use transient failure from the transport to indicate goaway has been * received */ connectivity_state_set( exec_ctx, t, GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_set_str( grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING("GOAWAY received"), GRPC_ERROR_INT_HTTP2_ERROR, (intptr_t)goaway_error), GRPC_ERROR_STR_RAW_BYTES, goaway_text), "got_goaway"); } static void maybe_start_some_streams(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { grpc_chttp2_stream *s; /* start streams where we have free grpc_chttp2_stream ids and free * concurrency */ while (t->next_stream_id <= MAX_CLIENT_STREAM_ID && grpc_chttp2_stream_map_size(&t->stream_map) < t->settings[GRPC_PEER_SETTINGS] [GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS] && grpc_chttp2_list_pop_waiting_for_concurrency(t, &s)) { /* safe since we can't (legally) be parsing this stream yet */ GRPC_CHTTP2_IF_TRACING(gpr_log( GPR_DEBUG, "HTTP:%s: Allocating new grpc_chttp2_stream %p to id %d", t->is_client ? "CLI" : "SVR", s, t->next_stream_id)); GPR_ASSERT(s->id == 0); s->id = t->next_stream_id; t->next_stream_id += 2; if (t->next_stream_id >= MAX_CLIENT_STREAM_ID) { connectivity_state_set( exec_ctx, t, GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Stream IDs exhausted"), "no_more_stream_ids"); } grpc_chttp2_stream_map_add(&t->stream_map, s->id, s); post_destructive_reclaimer(exec_ctx, t); grpc_chttp2_become_writable(exec_ctx, t, s, GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED, "new_stream"); } /* cancel out streams that will never be started */ while (t->next_stream_id >= MAX_CLIENT_STREAM_ID && grpc_chttp2_list_pop_waiting_for_concurrency(t, &s)) { grpc_chttp2_cancel_stream( exec_ctx, t, s, grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Stream IDs exhausted"), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE)); } } /* Flag that this closure barrier wants stats to be updated before finishing */ #define CLOSURE_BARRIER_STATS_BIT (1 << 0) /* Flag that this closure barrier may be covering a write in a pollset, and so we should not complete this closure until we can prove that the write got scheduled */ #define CLOSURE_BARRIER_MAY_COVER_WRITE (1 << 1) /* First bit of the reference count, stored in the high order bits (with the low bits being used for flags defined above) */ #define CLOSURE_BARRIER_FIRST_REF_BIT (1 << 16) static grpc_closure *add_closure_barrier(grpc_closure *closure) { closure->next_data.scratch += CLOSURE_BARRIER_FIRST_REF_BIT; return closure; } static void null_then_run_closure(grpc_exec_ctx *exec_ctx, grpc_closure **closure, grpc_error *error) { grpc_closure *c = *closure; *closure = NULL; grpc_closure_run(exec_ctx, c, error); } void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_closure **pclosure, grpc_error *error, const char *desc) { grpc_closure *closure = *pclosure; *pclosure = NULL; if (closure == NULL) { GRPC_ERROR_UNREF(error); return; } closure->next_data.scratch -= CLOSURE_BARRIER_FIRST_REF_BIT; if (grpc_http_trace) { const char *errstr = grpc_error_string(error); gpr_log(GPR_DEBUG, "complete_closure_step: %p refs=%d flags=0x%04x desc=%s err=%s", closure, (int)(closure->next_data.scratch / CLOSURE_BARRIER_FIRST_REF_BIT), (int)(closure->next_data.scratch % CLOSURE_BARRIER_FIRST_REF_BIT), desc, errstr); } if (error != GRPC_ERROR_NONE) { if (closure->error_data.error == GRPC_ERROR_NONE) { closure->error_data.error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Error in HTTP transport completing operation"); closure->error_data.error = grpc_error_set_str( closure->error_data.error, GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(t->peer_string)); } closure->error_data.error = grpc_error_add_child(closure->error_data.error, error); } if (closure->next_data.scratch < CLOSURE_BARRIER_FIRST_REF_BIT) { if (closure->next_data.scratch & CLOSURE_BARRIER_STATS_BIT) { grpc_transport_move_stats(&s->stats, s->collecting_stats); s->collecting_stats = NULL; } if ((t->write_state == GRPC_CHTTP2_WRITE_STATE_IDLE) || !(closure->next_data.scratch & CLOSURE_BARRIER_MAY_COVER_WRITE)) { grpc_closure_run(exec_ctx, closure, closure->error_data.error); } else { grpc_closure_list_append(&t->run_after_write, closure, closure->error_data.error); } } } static bool contains_non_ok_status(grpc_metadata_batch *batch) { if (batch->idx.named.grpc_status != NULL) { return !grpc_mdelem_eq(batch->idx.named.grpc_status->md, GRPC_MDELEM_GRPC_STATUS_0); } return false; } static void maybe_become_writable_due_to_send_msg(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s) { if (s->id != 0 && (!s->write_buffering || s->flow_controlled_buffer.length > t->write_buffer_size)) { grpc_chttp2_become_writable(exec_ctx, t, s, GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED, "op.send_message"); } } static void add_fetched_slice_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s) { s->fetched_send_message_length += (uint32_t)GRPC_SLICE_LENGTH(s->fetching_slice); grpc_slice_buffer_add(&s->flow_controlled_buffer, s->fetching_slice); maybe_become_writable_due_to_send_msg(exec_ctx, t, s); } static void continue_fetching_send_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s) { for (;;) { if (s->fetching_send_message == NULL) { /* Stream was cancelled before message fetch completed */ abort(); /* TODO(ctiller): what cleanup here? */ return; /* early out */ } if (s->fetched_send_message_length == s->fetching_send_message->length) { int64_t notify_offset = s->next_message_end_offset; if (notify_offset <= s->flow_controlled_bytes_written) { grpc_chttp2_complete_closure_step( exec_ctx, t, s, &s->fetching_send_message_finished, GRPC_ERROR_NONE, "fetching_send_message_finished"); } else { grpc_chttp2_write_cb *cb = t->write_cb_pool; if (cb == NULL) { cb = gpr_malloc(sizeof(*cb)); } else { t->write_cb_pool = cb->next; } cb->call_at_byte = notify_offset; cb->closure = s->fetching_send_message_finished; s->fetching_send_message_finished = NULL; cb->next = s->on_write_finished_cbs; s->on_write_finished_cbs = cb; } s->fetching_send_message = NULL; return; /* early out */ } else if (grpc_byte_stream_next(exec_ctx, s->fetching_send_message, &s->fetching_slice, UINT32_MAX, &s->complete_fetch_locked)) { add_fetched_slice_locked(exec_ctx, t, s); } } } static void complete_fetch_locked(grpc_exec_ctx *exec_ctx, void *gs, grpc_error *error) { grpc_chttp2_stream *s = gs; grpc_chttp2_transport *t = s->t; if (error == GRPC_ERROR_NONE) { add_fetched_slice_locked(exec_ctx, t, s); continue_fetching_send_locked(exec_ctx, t, s); } else { /* TODO(ctiller): what to do here */ abort(); } } static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {} static void log_metadata(const grpc_metadata_batch *md_batch, uint32_t id, bool is_client, bool is_initial) { for (grpc_linked_mdelem *md = md_batch->list.head; md != md_batch->list.tail; md = md->next) { char *key = grpc_slice_to_c_string(GRPC_MDKEY(md->md)); char *value = grpc_slice_to_c_string(GRPC_MDVALUE(md->md)); gpr_log(GPR_INFO, "HTTP:%d:%s:%s: %s: %s", id, is_initial ? "HDR" : "TRL", is_client ? "CLI" : "SVR", key, value); gpr_free(key); gpr_free(value); } } static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, grpc_error *error_ignored) { GPR_TIMER_BEGIN("perform_stream_op_locked", 0); grpc_transport_stream_op_batch *op = stream_op; grpc_chttp2_stream *s = op->handler_private.extra_arg; grpc_transport_stream_op_batch_payload *op_payload = op->payload; grpc_chttp2_transport *t = s->t; if (grpc_http_trace) { char *str = grpc_transport_stream_op_batch_string(op); gpr_log(GPR_DEBUG, "perform_stream_op_locked: %s; on_complete = %p", str, op->on_complete); gpr_free(str); if (op->send_initial_metadata) { log_metadata(op_payload->send_initial_metadata.send_initial_metadata, s->id, t->is_client, true); } if (op->send_trailing_metadata) { log_metadata(op_payload->send_trailing_metadata.send_trailing_metadata, s->id, t->is_client, false); } } grpc_closure *on_complete = op->on_complete; if (on_complete == NULL) { on_complete = grpc_closure_create(do_nothing, NULL, grpc_schedule_on_exec_ctx); } /* use final_data as a barrier until enqueue time; the inital counter is dropped at the end of this function */ on_complete->next_data.scratch = CLOSURE_BARRIER_FIRST_REF_BIT; on_complete->error_data.error = GRPC_ERROR_NONE; if (op->collect_stats) { GPR_ASSERT(s->collecting_stats == NULL); s->collecting_stats = op_payload->collect_stats.collect_stats; on_complete->next_data.scratch |= CLOSURE_BARRIER_STATS_BIT; } if (op->cancel_stream) { grpc_chttp2_cancel_stream(exec_ctx, t, s, op_payload->cancel_stream.cancel_error); } if (op->send_initial_metadata) { GPR_ASSERT(s->send_initial_metadata_finished == NULL); on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE; s->send_initial_metadata_finished = add_closure_barrier(on_complete); s->send_initial_metadata = op_payload->send_initial_metadata.send_initial_metadata; const size_t metadata_size = grpc_metadata_batch_size(s->send_initial_metadata); const size_t metadata_peer_limit = t->settings[GRPC_PEER_SETTINGS] [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE]; if (t->is_client) { s->deadline = gpr_time_min(s->deadline, s->send_initial_metadata->deadline); } if (metadata_size > metadata_peer_limit) { grpc_chttp2_cancel_stream( exec_ctx, t, s, grpc_error_set_int( grpc_error_set_int( grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "to-be-sent initial metadata size " "exceeds peer limit"), GRPC_ERROR_INT_SIZE, (intptr_t)metadata_size), GRPC_ERROR_INT_LIMIT, (intptr_t)metadata_peer_limit), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED)); } else { if (contains_non_ok_status(s->send_initial_metadata)) { s->seen_error = true; } if (!s->write_closed) { if (t->is_client) { if (!t->closed) { GPR_ASSERT(s->id == 0); grpc_chttp2_list_add_waiting_for_concurrency(t, s); maybe_start_some_streams(exec_ctx, t); } else { grpc_chttp2_cancel_stream( exec_ctx, t, s, grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Transport closed"), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE)); } } else { GPR_ASSERT(s->id != 0); grpc_chttp2_stream_write_type write_type = GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED; if (op->send_message && (op->payload->send_message.send_message->flags & GRPC_WRITE_BUFFER_HINT)) { write_type = GRPC_CHTTP2_STREAM_WRITE_PIGGYBACK; } grpc_chttp2_become_writable(exec_ctx, t, s, write_type, "op.send_initial_metadata"); } } else { s->send_initial_metadata = NULL; grpc_chttp2_complete_closure_step( exec_ctx, t, s, &s->send_initial_metadata_finished, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Attempt to send initial metadata after stream was closed", &s->write_closed_error, 1), "send_initial_metadata_finished"); } } } if (op->send_message) { on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE; s->fetching_send_message_finished = add_closure_barrier(op->on_complete); if (s->write_closed) { grpc_chttp2_complete_closure_step( exec_ctx, t, s, &s->fetching_send_message_finished, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Attempt to send message after stream was closed", &s->write_closed_error, 1), "fetching_send_message_finished"); } else { GPR_ASSERT(s->fetching_send_message == NULL); uint8_t *frame_hdr = grpc_slice_buffer_tiny_add(&s->flow_controlled_buffer, 5); uint32_t flags = op_payload->send_message.send_message->flags; frame_hdr[0] = (flags & GRPC_WRITE_INTERNAL_COMPRESS) != 0; size_t len = op_payload->send_message.send_message->length; frame_hdr[1] = (uint8_t)(len >> 24); frame_hdr[2] = (uint8_t)(len >> 16); frame_hdr[3] = (uint8_t)(len >> 8); frame_hdr[4] = (uint8_t)(len); s->fetching_send_message = op_payload->send_message.send_message; s->fetched_send_message_length = 0; s->next_message_end_offset = s->flow_controlled_bytes_written + (int64_t)s->flow_controlled_buffer.length + (int64_t)len; s->complete_fetch_covered_by_poller = op->covered_by_poller; if (flags & GRPC_WRITE_BUFFER_HINT) { s->next_message_end_offset -= t->write_buffer_size; s->write_buffering = true; } else { s->write_buffering = false; } continue_fetching_send_locked(exec_ctx, t, s); maybe_become_writable_due_to_send_msg(exec_ctx, t, s); } } if (op->send_trailing_metadata) { GPR_ASSERT(s->send_trailing_metadata_finished == NULL); on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE; s->send_trailing_metadata_finished = add_closure_barrier(on_complete); s->send_trailing_metadata = op_payload->send_trailing_metadata.send_trailing_metadata; s->write_buffering = false; const size_t metadata_size = grpc_metadata_batch_size(s->send_trailing_metadata); const size_t metadata_peer_limit = t->settings[GRPC_PEER_SETTINGS] [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE]; if (metadata_size > metadata_peer_limit) { grpc_chttp2_cancel_stream( exec_ctx, t, s, grpc_error_set_int( grpc_error_set_int( grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "to-be-sent trailing metadata size " "exceeds peer limit"), GRPC_ERROR_INT_SIZE, (intptr_t)metadata_size), GRPC_ERROR_INT_LIMIT, (intptr_t)metadata_peer_limit), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED)); } else { if (contains_non_ok_status(s->send_trailing_metadata)) { s->seen_error = true; } if (s->write_closed) { s->send_trailing_metadata = NULL; grpc_chttp2_complete_closure_step( exec_ctx, t, s, &s->send_trailing_metadata_finished, grpc_metadata_batch_is_empty( op->payload->send_trailing_metadata.send_trailing_metadata) ? GRPC_ERROR_NONE : GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Attempt to send trailing metadata after " "stream was closed"), "send_trailing_metadata_finished"); } else if (s->id != 0) { /* TODO(ctiller): check if there's flow control for any outstanding bytes before going writable */ grpc_chttp2_become_writable(exec_ctx, t, s, GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED, "op.send_trailing_metadata"); } } } if (op->recv_initial_metadata) { GPR_ASSERT(s->recv_initial_metadata_ready == NULL); s->recv_initial_metadata_ready = op_payload->recv_initial_metadata.recv_initial_metadata_ready; s->recv_initial_metadata = op_payload->recv_initial_metadata.recv_initial_metadata; grpc_chttp2_maybe_complete_recv_initial_metadata(exec_ctx, t, s); } if (op->recv_message) { GPR_ASSERT(s->recv_message_ready == NULL); s->recv_message_ready = op_payload->recv_message.recv_message_ready; s->recv_message = op_payload->recv_message.recv_message; if (s->id != 0 && (s->incoming_frames.head == NULL || s->incoming_frames.head->is_tail)) { incoming_byte_stream_update_flow_control(exec_ctx, t, s, 5, 0); } grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s); } if (op->recv_trailing_metadata) { GPR_ASSERT(s->recv_trailing_metadata_finished == NULL); s->recv_trailing_metadata_finished = add_closure_barrier(on_complete); s->recv_trailing_metadata = op_payload->recv_trailing_metadata.recv_trailing_metadata; s->final_metadata_requested = true; grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s); } grpc_chttp2_complete_closure_step(exec_ctx, t, s, &on_complete, GRPC_ERROR_NONE, "op->on_complete"); GPR_TIMER_END("perform_stream_op_locked", 0); GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "perform_stream_op"); } static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_transport_stream_op_batch *op) { GPR_TIMER_BEGIN("perform_stream_op", 0); grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; if (grpc_http_trace) { char *str = grpc_transport_stream_op_batch_string(op); gpr_log(GPR_DEBUG, "perform_stream_op[s=%p/%d]: %s", s, s->id, str); gpr_free(str); } op->handler_private.extra_arg = gs; GRPC_CHTTP2_STREAM_REF(s, "perform_stream_op"); grpc_closure_sched( exec_ctx, grpc_closure_init( &op->handler_private.closure, perform_stream_op_locked, op, grpc_combiner_scheduler(t->combiner, op->covered_by_poller)), GRPC_ERROR_NONE); GPR_TIMER_END("perform_stream_op", 0); } static void cancel_pings(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_error *error) { /* callback remaining pings: they're not allowed to call into the transpot, and maybe they hold resources that need to be freed */ for (size_t i = 0; i < GRPC_CHTTP2_PING_TYPE_COUNT; i++) { grpc_chttp2_ping_queue *pq = &t->ping_queues[i]; for (size_t j = 0; j < GRPC_CHTTP2_PCL_COUNT; j++) { grpc_closure_list_fail_all(&pq->lists[j], GRPC_ERROR_REF(error)); grpc_closure_list_sched(exec_ctx, &pq->lists[j]); } } GRPC_ERROR_UNREF(error); } static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_ping_type ping_type, grpc_closure *on_initiate, grpc_closure *on_ack) { grpc_chttp2_ping_queue *pq = &t->ping_queues[ping_type]; grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_INITIATE], on_initiate, GRPC_ERROR_NONE); if (grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_NEXT], on_ack, GRPC_ERROR_NONE)) { grpc_chttp2_initiate_write(exec_ctx, t, false, "send_ping"); } } static void retry_initiate_ping_locked(grpc_exec_ctx *exec_ctx, void *tp, grpc_error *error) { grpc_chttp2_transport *t = tp; t->ping_state.is_delayed_ping_timer_set = false; grpc_chttp2_initiate_write(exec_ctx, t, false, "retry_send_ping"); } void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, uint64_t id) { grpc_chttp2_ping_queue *pq = &t->ping_queues[id % GRPC_CHTTP2_PING_TYPE_COUNT]; if (pq->inflight_id != id) { char *from = grpc_endpoint_get_peer(t->ep); gpr_log(GPR_DEBUG, "Unknown ping response from %s: %" PRIx64, from, id); gpr_free(from); return; } grpc_closure_list_sched(exec_ctx, &pq->lists[GRPC_CHTTP2_PCL_INFLIGHT]); if (!grpc_closure_list_empty(pq->lists[GRPC_CHTTP2_PCL_NEXT])) { grpc_chttp2_initiate_write(exec_ctx, t, false, "continue_pings"); } } static void send_goaway(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_error *error) { t->sent_goaway_state = GRPC_CHTTP2_GOAWAY_SEND_SCHEDULED; grpc_http2_error_code http_error; grpc_slice slice; grpc_error_get_status(error, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL, &slice, &http_error); grpc_chttp2_goaway_append(t->last_new_stream_id, (uint32_t)http_error, grpc_slice_ref_internal(slice), &t->qbuf); grpc_chttp2_initiate_write(exec_ctx, t, false, "goaway_sent"); GRPC_ERROR_UNREF(error); } void grpc_chttp2_add_ping_strike(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { gpr_log(GPR_DEBUG, "PING strike"); if (++t->ping_recv_state.ping_strikes > t->ping_policy.max_ping_strikes && t->ping_policy.max_ping_strikes != 0) { send_goaway(exec_ctx, t, grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING("too_many_pings"), GRPC_ERROR_INT_HTTP2_ERROR, GRPC_HTTP2_ENHANCE_YOUR_CALM)); /*The transport will be closed after the write is done */ close_transport_locked( exec_ctx, t, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Too many pings")); } } static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, grpc_error *error_ignored) { grpc_transport_op *op = stream_op; grpc_chttp2_transport *t = op->handler_private.extra_arg; grpc_error *close_transport = op->disconnect_with_error; if (op->on_connectivity_state_change != NULL) { grpc_connectivity_state_notify_on_state_change( exec_ctx, &t->channel_callback.state_tracker, op->connectivity_state, op->on_connectivity_state_change); } if (op->goaway_error) { send_goaway(exec_ctx, t, op->goaway_error); } if (op->set_accept_stream) { t->channel_callback.accept_stream = op->set_accept_stream_fn; t->channel_callback.accept_stream_user_data = op->set_accept_stream_user_data; } if (op->bind_pollset) { grpc_endpoint_add_to_pollset(exec_ctx, t->ep, op->bind_pollset); } if (op->bind_pollset_set) { grpc_endpoint_add_to_pollset_set(exec_ctx, t->ep, op->bind_pollset_set); } if (op->send_ping) { send_ping_locked(exec_ctx, t, GRPC_CHTTP2_PING_ON_NEXT_WRITE, NULL, op->send_ping); } if (close_transport != GRPC_ERROR_NONE) { close_transport_locked(exec_ctx, t, close_transport); } grpc_closure_run(exec_ctx, op->on_consumed, GRPC_ERROR_NONE); GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "transport_op"); } static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_transport_op *op) { grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; char *msg = grpc_transport_op_string(op); gpr_free(msg); op->handler_private.extra_arg = gt; GRPC_CHTTP2_REF_TRANSPORT(t, "transport_op"); grpc_closure_sched( exec_ctx, grpc_closure_init(&op->handler_private.closure, perform_transport_op_locked, op, grpc_combiner_scheduler(t->combiner, false)), GRPC_ERROR_NONE); } /******************************************************************************* * INPUT PROCESSING - GENERAL */ void grpc_chttp2_maybe_complete_recv_initial_metadata(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s) { grpc_byte_stream *bs; if (s->recv_initial_metadata_ready != NULL && s->published_metadata[0] != GRPC_METADATA_NOT_PUBLISHED) { if (s->seen_error) { while ((bs = grpc_chttp2_incoming_frame_queue_pop(&s->incoming_frames)) != NULL) { incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE); } } grpc_chttp2_incoming_metadata_buffer_publish( exec_ctx, &s->metadata_buffer[0], s->recv_initial_metadata); null_then_run_closure(exec_ctx, &s->recv_initial_metadata_ready, GRPC_ERROR_NONE); } } void grpc_chttp2_maybe_complete_recv_message(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s) { grpc_byte_stream *bs; if (s->recv_message_ready != NULL) { while (s->final_metadata_requested && s->seen_error && (bs = grpc_chttp2_incoming_frame_queue_pop(&s->incoming_frames)) != NULL) { incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE); } if (s->incoming_frames.head != NULL) { *s->recv_message = grpc_chttp2_incoming_frame_queue_pop(&s->incoming_frames); GPR_ASSERT(*s->recv_message != NULL); null_then_run_closure(exec_ctx, &s->recv_message_ready, GRPC_ERROR_NONE); } else if (s->published_metadata[1] != GRPC_METADATA_NOT_PUBLISHED) { *s->recv_message = NULL; null_then_run_closure(exec_ctx, &s->recv_message_ready, GRPC_ERROR_NONE); } } } void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s) { grpc_byte_stream *bs; grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s); if (s->recv_trailing_metadata_finished != NULL && s->read_closed && s->write_closed) { if (s->seen_error) { while ((bs = grpc_chttp2_incoming_frame_queue_pop(&s->incoming_frames)) != NULL) { incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE); } } if (s->all_incoming_byte_streams_finished && s->recv_trailing_metadata_finished != NULL) { grpc_chttp2_incoming_metadata_buffer_publish( exec_ctx, &s->metadata_buffer[1], s->recv_trailing_metadata); grpc_chttp2_complete_closure_step( exec_ctx, t, s, &s->recv_trailing_metadata_finished, GRPC_ERROR_NONE, "recv_trailing_metadata_finished"); } } } static void decrement_active_streams_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s) { if ((s->all_incoming_byte_streams_finished = gpr_unref(&s->active_streams))) { grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s); } } static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, uint32_t id, grpc_error *error) { grpc_chttp2_stream *s = grpc_chttp2_stream_map_delete(&t->stream_map, id); GPR_ASSERT(s); if (t->incoming_stream == s) { t->incoming_stream = NULL; grpc_chttp2_parsing_become_skip_parser(exec_ctx, t); } if (s->data_parser.parsing_frame != NULL) { grpc_chttp2_incoming_byte_stream_finished( exec_ctx, s->data_parser.parsing_frame, GRPC_ERROR_REF(error)); s->data_parser.parsing_frame = NULL; } if (grpc_chttp2_stream_map_size(&t->stream_map) == 0) { post_benign_reclaimer(exec_ctx, t); if (t->sent_goaway_state == GRPC_CHTTP2_GOAWAY_SENT) { close_transport_locked( exec_ctx, t, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Last stream closed after sending GOAWAY", &error, 1)); } } if (grpc_chttp2_list_remove_writable_stream(t, s)) { GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2_writing:remove_stream"); } GRPC_ERROR_UNREF(error); maybe_start_some_streams(exec_ctx, t); } void grpc_chttp2_cancel_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_error *due_to_error) { if (!t->is_client && !s->sent_trailing_metadata && grpc_error_has_clear_grpc_status(due_to_error)) { close_from_api(exec_ctx, t, s, due_to_error); return; } if (!s->read_closed || !s->write_closed) { if (s->id != 0) { grpc_http2_error_code http_error; grpc_error_get_status(due_to_error, s->deadline, NULL, NULL, &http_error); grpc_slice_buffer_add( &t->qbuf, grpc_chttp2_rst_stream_create(s->id, (uint32_t)http_error, &s->stats.outgoing)); grpc_chttp2_initiate_write(exec_ctx, t, false, "rst_stream"); } } if (due_to_error != GRPC_ERROR_NONE && !s->seen_error) { s->seen_error = true; } grpc_chttp2_mark_stream_closed(exec_ctx, t, s, 1, 1, due_to_error); } void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_error *error) { grpc_status_code status; grpc_slice slice; grpc_error_get_status(error, s->deadline, &status, &slice, NULL); if (status != GRPC_STATUS_OK) { s->seen_error = true; } /* stream_global->recv_trailing_metadata_finished gives us a last chance replacement: we've received trailing metadata, but something more important has become available to signal to the upper layers - drop what we've got, and then publish what we want - which is safe because we haven't told anyone about the metadata yet */ if (s->published_metadata[1] == GRPC_METADATA_NOT_PUBLISHED || s->recv_trailing_metadata_finished != NULL) { char status_string[GPR_LTOA_MIN_BUFSIZE]; gpr_ltoa(status, status_string); GRPC_LOG_IF_ERROR("add_status", grpc_chttp2_incoming_metadata_buffer_replace_or_add( exec_ctx, &s->metadata_buffer[1], grpc_mdelem_from_slices( exec_ctx, GRPC_MDSTR_GRPC_STATUS, grpc_slice_from_copied_string(status_string)))); if (!GRPC_SLICE_IS_EMPTY(slice)) { GRPC_LOG_IF_ERROR( "add_status_message", grpc_chttp2_incoming_metadata_buffer_replace_or_add( exec_ctx, &s->metadata_buffer[1], grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_MESSAGE, grpc_slice_ref_internal(slice)))); } s->published_metadata[1] = GRPC_METADATA_SYNTHESIZED_FROM_FAKE; grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s); } GRPC_ERROR_UNREF(error); } static void add_error(grpc_error *error, grpc_error **refs, size_t *nrefs) { if (error == GRPC_ERROR_NONE) return; for (size_t i = 0; i < *nrefs; i++) { if (error == refs[i]) { return; } } refs[*nrefs] = error; ++*nrefs; } static grpc_error *removal_error(grpc_error *extra_error, grpc_chttp2_stream *s, const char *master_error_msg) { grpc_error *refs[3]; size_t nrefs = 0; add_error(s->read_closed_error, refs, &nrefs); add_error(s->write_closed_error, refs, &nrefs); add_error(extra_error, refs, &nrefs); grpc_error *error = GRPC_ERROR_NONE; if (nrefs > 0) { error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(master_error_msg, refs, nrefs); } GRPC_ERROR_UNREF(extra_error); return error; } void grpc_chttp2_fail_pending_writes(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_error *error) { error = removal_error(error, s, "Pending writes failed due to stream closure"); s->send_initial_metadata = NULL; grpc_chttp2_complete_closure_step( exec_ctx, t, s, &s->send_initial_metadata_finished, GRPC_ERROR_REF(error), "send_initial_metadata_finished"); s->send_trailing_metadata = NULL; grpc_chttp2_complete_closure_step( exec_ctx, t, s, &s->send_trailing_metadata_finished, GRPC_ERROR_REF(error), "send_trailing_metadata_finished"); s->fetching_send_message = NULL; grpc_chttp2_complete_closure_step( exec_ctx, t, s, &s->fetching_send_message_finished, GRPC_ERROR_REF(error), "fetching_send_message_finished"); while (s->on_write_finished_cbs) { grpc_chttp2_write_cb *cb = s->on_write_finished_cbs; s->on_write_finished_cbs = cb->next; grpc_chttp2_complete_closure_step(exec_ctx, t, s, &cb->closure, GRPC_ERROR_REF(error), "on_write_finished_cb"); cb->next = t->write_cb_pool; t->write_cb_pool = cb; } GRPC_ERROR_UNREF(error); } void grpc_chttp2_mark_stream_closed(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, int close_reads, int close_writes, grpc_error *error) { if (s->read_closed && s->write_closed) { /* already closed */ grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s); GRPC_ERROR_UNREF(error); return; } bool closed_read = false; bool became_closed = false; if (close_reads && !s->read_closed) { s->read_closed_error = GRPC_ERROR_REF(error); s->read_closed = true; closed_read = true; } if (close_writes && !s->write_closed) { s->write_closed_error = GRPC_ERROR_REF(error); s->write_closed = true; grpc_chttp2_fail_pending_writes(exec_ctx, t, s, GRPC_ERROR_REF(error)); } if (s->read_closed && s->write_closed) { became_closed = true; grpc_error *overall_error = removal_error(GRPC_ERROR_REF(error), s, "Stream removed"); if (s->id != 0) { remove_stream(exec_ctx, t, s->id, GRPC_ERROR_REF(overall_error)); } else { /* Purge streams waiting on concurrency still waiting for id assignment */ grpc_chttp2_list_remove_waiting_for_concurrency(t, s); } if (overall_error != GRPC_ERROR_NONE) { grpc_chttp2_fake_status(exec_ctx, t, s, overall_error); } } if (closed_read) { for (int i = 0; i < 2; i++) { if (s->published_metadata[i] == GRPC_METADATA_NOT_PUBLISHED) { s->published_metadata[i] = GPRC_METADATA_PUBLISHED_AT_CLOSE; } } decrement_active_streams_locked(exec_ctx, t, s); grpc_chttp2_maybe_complete_recv_initial_metadata(exec_ctx, t, s); grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s); } if (became_closed) { grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s); GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2"); } GRPC_ERROR_UNREF(error); } static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_error *error) { grpc_slice hdr; grpc_slice status_hdr; grpc_slice http_status_hdr; grpc_slice content_type_hdr; grpc_slice message_pfx; uint8_t *p; uint32_t len = 0; grpc_status_code grpc_status; grpc_slice slice; grpc_error_get_status(error, s->deadline, &grpc_status, &slice, NULL); GPR_ASSERT(grpc_status >= 0 && (int)grpc_status < 100); /* Hand roll a header block. This is unnecessarily ugly - at some point we should find a more elegant solution. It's complicated by the fact that our send machinery would be dead by the time we got around to sending this, so instead we ignore HPACK compression and just write the uncompressed bytes onto the wire. */ if (!s->sent_initial_metadata) { http_status_hdr = grpc_slice_malloc(13); p = GRPC_SLICE_START_PTR(http_status_hdr); *p++ = 0x00; *p++ = 7; *p++ = ':'; *p++ = 's'; *p++ = 't'; *p++ = 'a'; *p++ = 't'; *p++ = 'u'; *p++ = 's'; *p++ = 3; *p++ = '2'; *p++ = '0'; *p++ = '0'; GPR_ASSERT(p == GRPC_SLICE_END_PTR(http_status_hdr)); len += (uint32_t)GRPC_SLICE_LENGTH(http_status_hdr); content_type_hdr = grpc_slice_malloc(31); p = GRPC_SLICE_START_PTR(content_type_hdr); *p++ = 0x00; *p++ = 12; *p++ = 'c'; *p++ = 'o'; *p++ = 'n'; *p++ = 't'; *p++ = 'e'; *p++ = 'n'; *p++ = 't'; *p++ = '-'; *p++ = 't'; *p++ = 'y'; *p++ = 'p'; *p++ = 'e'; *p++ = 16; *p++ = 'a'; *p++ = 'p'; *p++ = 'p'; *p++ = 'l'; *p++ = 'i'; *p++ = 'c'; *p++ = 'a'; *p++ = 't'; *p++ = 'i'; *p++ = 'o'; *p++ = 'n'; *p++ = '/'; *p++ = 'g'; *p++ = 'r'; *p++ = 'p'; *p++ = 'c'; GPR_ASSERT(p == GRPC_SLICE_END_PTR(content_type_hdr)); len += (uint32_t)GRPC_SLICE_LENGTH(content_type_hdr); } status_hdr = grpc_slice_malloc(15 + (grpc_status >= 10)); p = GRPC_SLICE_START_PTR(status_hdr); *p++ = 0x00; /* literal header, not indexed */ *p++ = 11; /* len(grpc-status) */ *p++ = 'g'; *p++ = 'r'; *p++ = 'p'; *p++ = 'c'; *p++ = '-'; *p++ = 's'; *p++ = 't'; *p++ = 'a'; *p++ = 't'; *p++ = 'u'; *p++ = 's'; if (grpc_status < 10) { *p++ = 1; *p++ = (uint8_t)('0' + grpc_status); } else { *p++ = 2; *p++ = (uint8_t)('0' + (grpc_status / 10)); *p++ = (uint8_t)('0' + (grpc_status % 10)); } GPR_ASSERT(p == GRPC_SLICE_END_PTR(status_hdr)); len += (uint32_t)GRPC_SLICE_LENGTH(status_hdr); size_t msg_len = GRPC_SLICE_LENGTH(slice); GPR_ASSERT(msg_len <= UINT32_MAX); uint32_t msg_len_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)msg_len, 1); message_pfx = grpc_slice_malloc(14 + msg_len_len); p = GRPC_SLICE_START_PTR(message_pfx); *p++ = 0x00; /* literal header, not indexed */ *p++ = 12; /* len(grpc-message) */ *p++ = 'g'; *p++ = 'r'; *p++ = 'p'; *p++ = 'c'; *p++ = '-'; *p++ = 'm'; *p++ = 'e'; *p++ = 's'; *p++ = 's'; *p++ = 'a'; *p++ = 'g'; *p++ = 'e'; GRPC_CHTTP2_WRITE_VARINT((uint32_t)msg_len, 1, 0, p, (uint32_t)msg_len_len); p += msg_len_len; GPR_ASSERT(p == GRPC_SLICE_END_PTR(message_pfx)); len += (uint32_t)GRPC_SLICE_LENGTH(message_pfx); len += (uint32_t)msg_len; hdr = grpc_slice_malloc(9); p = GRPC_SLICE_START_PTR(hdr); *p++ = (uint8_t)(len >> 16); *p++ = (uint8_t)(len >> 8); *p++ = (uint8_t)(len); *p++ = GRPC_CHTTP2_FRAME_HEADER; *p++ = GRPC_CHTTP2_DATA_FLAG_END_STREAM | GRPC_CHTTP2_DATA_FLAG_END_HEADERS; *p++ = (uint8_t)(s->id >> 24); *p++ = (uint8_t)(s->id >> 16); *p++ = (uint8_t)(s->id >> 8); *p++ = (uint8_t)(s->id); GPR_ASSERT(p == GRPC_SLICE_END_PTR(hdr)); grpc_slice_buffer_add(&t->qbuf, hdr); if (!s->sent_initial_metadata) { grpc_slice_buffer_add(&t->qbuf, http_status_hdr); grpc_slice_buffer_add(&t->qbuf, content_type_hdr); } grpc_slice_buffer_add(&t->qbuf, status_hdr); grpc_slice_buffer_add(&t->qbuf, message_pfx); grpc_slice_buffer_add(&t->qbuf, grpc_slice_ref_internal(slice)); grpc_slice_buffer_add( &t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_HTTP2_NO_ERROR, &s->stats.outgoing)); grpc_chttp2_mark_stream_closed(exec_ctx, t, s, 1, 1, error); grpc_chttp2_initiate_write(exec_ctx, t, false, "close_from_api"); } typedef struct { grpc_exec_ctx *exec_ctx; grpc_error *error; grpc_chttp2_transport *t; } cancel_stream_cb_args; static void cancel_stream_cb(void *user_data, uint32_t key, void *stream) { cancel_stream_cb_args *args = user_data; grpc_chttp2_stream *s = stream; grpc_chttp2_cancel_stream(args->exec_ctx, args->t, s, GRPC_ERROR_REF(args->error)); } static void end_all_the_calls(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_error *error) { cancel_stream_cb_args args = {exec_ctx, error, t}; grpc_chttp2_stream_map_for_each(&t->stream_map, cancel_stream_cb, &args); GRPC_ERROR_UNREF(error); } /******************************************************************************* * INPUT PROCESSING - PARSING */ static void update_bdp(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, double bdp_dbl) { uint32_t bdp; if (bdp_dbl <= 0) { bdp = 0; } else if (bdp_dbl > UINT32_MAX) { bdp = UINT32_MAX; } else { bdp = (uint32_t)(bdp_dbl); } int64_t delta = (int64_t)bdp - (int64_t)t->settings[GRPC_LOCAL_SETTINGS] [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]; if (delta == 0 || (bdp != 0 && delta > -1024 && delta < 1024)) { return; } if (grpc_bdp_estimator_trace) { gpr_log(GPR_DEBUG, "%s: update initial window size to %d", t->peer_string, (int)bdp); } push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, bdp); } static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { grpc_http_parser parser; size_t i = 0; grpc_error *error = GRPC_ERROR_NONE; grpc_http_response response; memset(&response, 0, sizeof(response)); grpc_http_parser_init(&parser, GRPC_HTTP_RESPONSE, &response); grpc_error *parse_error = GRPC_ERROR_NONE; for (; i < t->read_buffer.count && parse_error == GRPC_ERROR_NONE; i++) { parse_error = grpc_http_parser_parse(&parser, t->read_buffer.slices[i], NULL); } if (parse_error == GRPC_ERROR_NONE && (parse_error = grpc_http_parser_eof(&parser)) == GRPC_ERROR_NONE) { error = grpc_error_set_int( grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Trying to connect an http1.x server"), GRPC_ERROR_INT_HTTP_STATUS, response.status), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); } GRPC_ERROR_UNREF(parse_error); grpc_http_parser_destroy(&parser); grpc_http_response_destroy(&response); return error; } static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp, grpc_error *error) { GPR_TIMER_BEGIN("reading_action_locked", 0); grpc_chttp2_transport *t = tp; bool need_bdp_ping = false; GRPC_ERROR_REF(error); grpc_error *err = error; if (err != GRPC_ERROR_NONE) { err = grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Endpoint read failed", &err, 1), GRPC_ERROR_INT_OCCURRED_DURING_WRITE, t->write_state); } GPR_SWAP(grpc_error *, err, error); GRPC_ERROR_UNREF(err); if (!t->closed) { GPR_TIMER_BEGIN("reading_action.parse", 0); size_t i = 0; grpc_error *errors[3] = {GRPC_ERROR_REF(error), GRPC_ERROR_NONE, GRPC_ERROR_NONE}; for (; i < t->read_buffer.count && errors[1] == GRPC_ERROR_NONE; i++) { if (grpc_bdp_estimator_add_incoming_bytes( &t->bdp_estimator, (int64_t)GRPC_SLICE_LENGTH(t->read_buffer.slices[i]))) { need_bdp_ping = true; } errors[1] = grpc_chttp2_perform_read(exec_ctx, t, t->read_buffer.slices[i]); } if (errors[1] != GRPC_ERROR_NONE) { errors[2] = try_http_parsing(exec_ctx, t); GRPC_ERROR_UNREF(error); error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Failed parsing HTTP/2", errors, GPR_ARRAY_SIZE(errors)); } for (i = 0; i < GPR_ARRAY_SIZE(errors); i++) { GRPC_ERROR_UNREF(errors[i]); } GPR_TIMER_END("reading_action.parse", 0); GPR_TIMER_BEGIN("post_parse_locked", 0); if (t->initial_window_update != 0) { if (t->initial_window_update > 0) { grpc_chttp2_stream *s; while (grpc_chttp2_list_pop_stalled_by_stream(t, &s)) { grpc_chttp2_become_writable( exec_ctx, t, s, GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED, "unstalled"); } } t->initial_window_update = 0; } GPR_TIMER_END("post_parse_locked", 0); } GPR_TIMER_BEGIN("post_reading_action_locked", 0); bool keep_reading = false; if (error == GRPC_ERROR_NONE && t->closed) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Transport closed"); } if (error != GRPC_ERROR_NONE) { close_transport_locked(exec_ctx, t, GRPC_ERROR_REF(error)); t->endpoint_reading = 0; } else if (!t->closed) { keep_reading = true; GRPC_CHTTP2_REF_TRANSPORT(t, "keep_reading"); } grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &t->read_buffer); if (keep_reading) { grpc_endpoint_read(exec_ctx, t->ep, &t->read_buffer, &t->read_action_locked); if (t->enable_bdp_probe) { if (need_bdp_ping) { GRPC_CHTTP2_REF_TRANSPORT(t, "bdp_ping"); grpc_bdp_estimator_schedule_ping(&t->bdp_estimator); send_ping_locked(exec_ctx, t, GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE, &t->start_bdp_ping_locked, &t->finish_bdp_ping_locked); } int64_t estimate = -1; if (grpc_bdp_estimator_get_estimate(&t->bdp_estimator, &estimate)) { double target = 1 + log2((double)estimate); double memory_pressure = grpc_resource_quota_get_memory_pressure( grpc_resource_user_quota(grpc_endpoint_get_resource_user(t->ep))); if (memory_pressure > 0.8) { target *= 1 - GPR_MIN(1, (memory_pressure - 0.8) / 0.1); } double bdp_error = target - grpc_pid_controller_last(&t->pid_controller); gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); gpr_timespec dt_timespec = gpr_time_sub(now, t->last_pid_update); double dt = (double)dt_timespec.tv_sec + dt_timespec.tv_nsec * 1e-9; if (dt > 0.1) { dt = 0.1; } double log2_bdp_guess = grpc_pid_controller_update(&t->pid_controller, bdp_error, dt); update_bdp(exec_ctx, t, pow(2, log2_bdp_guess)); t->last_pid_update = now; } } GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keep_reading"); } else { GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "reading_action"); } GPR_TIMER_END("post_reading_action_locked", 0); GRPC_ERROR_UNREF(error); GPR_TIMER_END("reading_action_locked", 0); } static void start_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp, grpc_error *error) { grpc_chttp2_transport *t = tp; if (grpc_http_trace) { gpr_log(GPR_DEBUG, "%s: Start BDP ping", t->peer_string); } /* Reset the keepalive ping timer */ if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING) { grpc_timer_cancel(exec_ctx, &t->keepalive_ping_timer); } grpc_bdp_estimator_start_ping(&t->bdp_estimator); } static void finish_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp, grpc_error *error) { grpc_chttp2_transport *t = tp; if (grpc_http_trace) { gpr_log(GPR_DEBUG, "%s: Complete BDP ping", t->peer_string); } grpc_bdp_estimator_complete_ping(&t->bdp_estimator); GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "bdp_ping"); } void grpc_chttp2_config_default_keepalive_args(grpc_channel_args *args, bool is_client) { size_t i; if (args) { for (i = 0; i < args->num_args; i++) { if (0 == strcmp(args->args[i].key, GRPC_ARG_KEEPALIVE_TIME_MS)) { const int value = grpc_channel_arg_get_integer( &args->args[i], (grpc_integer_options){g_default_client_keepalive_time_ms, 1, INT_MAX}); if (is_client) { g_default_client_keepalive_time_ms = value; } else { g_default_server_keepalive_time_ms = value; } } else if (0 == strcmp(args->args[i].key, GRPC_ARG_KEEPALIVE_TIMEOUT_MS)) { const int value = grpc_channel_arg_get_integer( &args->args[i], (grpc_integer_options){g_default_client_keepalive_timeout_ms, 0, INT_MAX}); if (is_client) { g_default_client_keepalive_timeout_ms = value; } else { g_default_server_keepalive_timeout_ms = value; } } else if (0 == strcmp(args->args[i].key, GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS)) { g_default_keepalive_permit_without_calls = (uint32_t)grpc_channel_arg_get_integer( &args->args[i], (grpc_integer_options){g_default_keepalive_permit_without_calls, 0, 1}); } } } } static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_chttp2_transport *t = arg; GPR_ASSERT(t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING); if (error == GRPC_ERROR_NONE && !(t->destroying || t->closed)) { if (t->keepalive_permit_without_calls || grpc_chttp2_stream_map_size(&t->stream_map) > 0) { t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_PINGING; GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive ping end"); send_ping_locked(exec_ctx, t, GRPC_CHTTP2_PING_ON_NEXT_WRITE, &t->start_keepalive_ping_locked, &t->finish_keepalive_ping_locked); } else { GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping"); grpc_timer_init( exec_ctx, &t->keepalive_ping_timer, gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time), &t->init_keepalive_ping_locked, gpr_now(GPR_CLOCK_MONOTONIC)); } } else if (error == GRPC_ERROR_CANCELLED && !(t->destroying || t->closed)) { /* The keepalive ping timer may be cancelled by bdp */ GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping"); grpc_timer_init( exec_ctx, &t->keepalive_ping_timer, gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time), &t->init_keepalive_ping_locked, gpr_now(GPR_CLOCK_MONOTONIC)); } GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "init keepalive ping"); } static void start_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_chttp2_transport *t = arg; GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive watchdog"); grpc_timer_init( exec_ctx, &t->keepalive_watchdog_timer, gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_timeout), &t->keepalive_watchdog_fired_locked, gpr_now(GPR_CLOCK_MONOTONIC)); } static void finish_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_chttp2_transport *t = arg; if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) { if (error == GRPC_ERROR_NONE) { t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING; grpc_timer_cancel(exec_ctx, &t->keepalive_watchdog_timer); GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping"); grpc_timer_init( exec_ctx, &t->keepalive_ping_timer, gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time), &t->init_keepalive_ping_locked, gpr_now(GPR_CLOCK_MONOTONIC)); } } GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keepalive ping end"); } static void keepalive_watchdog_fired_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_chttp2_transport *t = arg; if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) { if (error == GRPC_ERROR_NONE) { t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DYING; close_transport_locked(exec_ctx, t, GRPC_ERROR_CREATE_FROM_STATIC_STRING( "keepalive watchdog timeout")); } } else { /* The watchdog timer should have been cancelled by * finish_keepalive_ping_locked. */ if (error != GRPC_ERROR_CANCELLED) { gpr_log(GPR_ERROR, "keepalive_ping_end state error: %d (expect: %d)", t->keepalive_state, GRPC_CHTTP2_KEEPALIVE_STATE_PINGING); } } GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keepalive watchdog"); } /******************************************************************************* * CALLBACK LOOP */ static void connectivity_state_set(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_connectivity_state state, grpc_error *error, const char *reason) { GRPC_CHTTP2_IF_TRACING( gpr_log(GPR_DEBUG, "set connectivity_state=%d", state)); grpc_connectivity_state_set(exec_ctx, &t->channel_callback.state_tracker, state, error, reason); } /******************************************************************************* * POLLSET STUFF */ static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_pollset *pollset) { grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_endpoint_add_to_pollset(exec_ctx, t->ep, pollset); } static void set_pollset_set(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_pollset_set *pollset_set) { grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_endpoint_add_to_pollset_set(exec_ctx, t->ep, pollset_set); } /******************************************************************************* * BYTE STREAM */ static void incoming_byte_stream_unref(grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs) { if (gpr_unref(&bs->refs)) { GRPC_ERROR_UNREF(bs->error); grpc_slice_buffer_destroy_internal(exec_ctx, &bs->slices); gpr_mu_destroy(&bs->slice_mu); gpr_free(bs); } } static void incoming_byte_stream_update_flow_control(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, size_t max_size_hint, size_t have_already) { uint32_t max_recv_bytes; uint32_t initial_window_size = t->settings[GRPC_SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]; /* clamp max recv hint to an allowable size */ if (max_size_hint >= UINT32_MAX - initial_window_size) { max_recv_bytes = UINT32_MAX - initial_window_size; } else { max_recv_bytes = (uint32_t)max_size_hint; } /* account for bytes already received but unknown to higher layers */ if (max_recv_bytes >= have_already) { max_recv_bytes -= (uint32_t)have_already; } else { max_recv_bytes = 0; } /* add some small lookahead to keep pipelines flowing */ GPR_ASSERT(max_recv_bytes <= UINT32_MAX - initial_window_size); if (s->incoming_window_delta < max_recv_bytes && !s->read_closed) { uint32_t add_max_recv_bytes = (uint32_t)(max_recv_bytes - s->incoming_window_delta); grpc_chttp2_stream_write_type write_type = GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED; if (s->incoming_window_delta + initial_window_size < (int64_t)have_already) { write_type = GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED; } GRPC_CHTTP2_FLOW_CREDIT_STREAM_INCOMING_WINDOW_DELTA("op", t, s, add_max_recv_bytes); GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, announce_window, add_max_recv_bytes); if ((int64_t)s->incoming_window_delta + (int64_t)initial_window_size - (int64_t)s->announce_window > (int64_t)initial_window_size / 2) { write_type = GRPC_CHTTP2_STREAM_WRITE_PIGGYBACK; } grpc_chttp2_become_writable(exec_ctx, t, s, write_type, "read_incoming_stream"); } } static void incoming_byte_stream_next_locked(grpc_exec_ctx *exec_ctx, void *argp, grpc_error *error_ignored) { grpc_chttp2_incoming_byte_stream *bs = argp; grpc_chttp2_transport *t = bs->transport; grpc_chttp2_stream *s = bs->stream; if (bs->is_tail) { gpr_mu_lock(&bs->slice_mu); size_t cur_length = bs->slices.length; gpr_mu_unlock(&bs->slice_mu); incoming_byte_stream_update_flow_control( exec_ctx, t, s, bs->next_action.max_size_hint, cur_length); } gpr_mu_lock(&bs->slice_mu); if (bs->slices.count > 0) { *bs->next_action.slice = grpc_slice_buffer_take_first(&bs->slices); grpc_closure_run(exec_ctx, bs->next_action.on_complete, GRPC_ERROR_NONE); } else if (bs->error != GRPC_ERROR_NONE) { grpc_closure_run(exec_ctx, bs->next_action.on_complete, GRPC_ERROR_REF(bs->error)); } else { bs->on_next = bs->next_action.on_complete; bs->next = bs->next_action.slice; } gpr_mu_unlock(&bs->slice_mu); incoming_byte_stream_unref(exec_ctx, bs); } static int incoming_byte_stream_next(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream, grpc_slice *slice, size_t max_size_hint, grpc_closure *on_complete) { GPR_TIMER_BEGIN("incoming_byte_stream_next", 0); grpc_chttp2_incoming_byte_stream *bs = (grpc_chttp2_incoming_byte_stream *)byte_stream; gpr_ref(&bs->refs); bs->next_action.slice = slice; bs->next_action.max_size_hint = max_size_hint; bs->next_action.on_complete = on_complete; grpc_closure_sched( exec_ctx, grpc_closure_init( &bs->next_action.closure, incoming_byte_stream_next_locked, bs, grpc_combiner_scheduler(bs->transport->combiner, false)), GRPC_ERROR_NONE); GPR_TIMER_END("incoming_byte_stream_next", 0); return 0; } static void incoming_byte_stream_destroy(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream); static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx, void *byte_stream, grpc_error *error_ignored) { grpc_chttp2_incoming_byte_stream *bs = byte_stream; GPR_ASSERT(bs->base.destroy == incoming_byte_stream_destroy); decrement_active_streams_locked(exec_ctx, bs->transport, bs->stream); incoming_byte_stream_unref(exec_ctx, bs); } static void incoming_byte_stream_destroy(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream) { GPR_TIMER_BEGIN("incoming_byte_stream_destroy", 0); grpc_chttp2_incoming_byte_stream *bs = (grpc_chttp2_incoming_byte_stream *)byte_stream; grpc_closure_sched( exec_ctx, grpc_closure_init( &bs->destroy_action, incoming_byte_stream_destroy_locked, bs, grpc_combiner_scheduler(bs->transport->combiner, false)), GRPC_ERROR_NONE); GPR_TIMER_END("incoming_byte_stream_destroy", 0); } static void incoming_byte_stream_publish_error( grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, grpc_error *error) { GPR_ASSERT(error != GRPC_ERROR_NONE); grpc_closure_sched(exec_ctx, bs->on_next, GRPC_ERROR_REF(error)); bs->on_next = NULL; GRPC_ERROR_UNREF(bs->error); grpc_chttp2_cancel_stream(exec_ctx, bs->transport, bs->stream, GRPC_ERROR_REF(error)); bs->error = error; } void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, grpc_slice slice) { gpr_mu_lock(&bs->slice_mu); if (bs->remaining_bytes < GRPC_SLICE_LENGTH(slice)) { incoming_byte_stream_publish_error( exec_ctx, bs, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Too many bytes in stream")); } else { bs->remaining_bytes -= (uint32_t)GRPC_SLICE_LENGTH(slice); if (bs->on_next != NULL) { *bs->next = slice; grpc_closure_sched(exec_ctx, bs->on_next, GRPC_ERROR_NONE); bs->on_next = NULL; } else { grpc_slice_buffer_add(&bs->slices, slice); } } gpr_mu_unlock(&bs->slice_mu); } void grpc_chttp2_incoming_byte_stream_finished( grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, grpc_error *error) { if (error == GRPC_ERROR_NONE) { gpr_mu_lock(&bs->slice_mu); if (bs->remaining_bytes != 0) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Truncated message"); } gpr_mu_unlock(&bs->slice_mu); } if (error != GRPC_ERROR_NONE) { incoming_byte_stream_publish_error(exec_ctx, bs, error); } incoming_byte_stream_unref(exec_ctx, bs); } grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create( grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, uint32_t frame_size, uint32_t flags) { grpc_chttp2_incoming_byte_stream *incoming_byte_stream = gpr_malloc(sizeof(*incoming_byte_stream)); incoming_byte_stream->base.length = frame_size; incoming_byte_stream->remaining_bytes = frame_size; incoming_byte_stream->base.flags = flags; incoming_byte_stream->base.next = incoming_byte_stream_next; incoming_byte_stream->base.destroy = incoming_byte_stream_destroy; gpr_mu_init(&incoming_byte_stream->slice_mu); gpr_ref_init(&incoming_byte_stream->refs, 2); incoming_byte_stream->next_message = NULL; incoming_byte_stream->transport = t; incoming_byte_stream->stream = s; gpr_ref(&incoming_byte_stream->stream->active_streams); grpc_slice_buffer_init(&incoming_byte_stream->slices); incoming_byte_stream->on_next = NULL; incoming_byte_stream->is_tail = 1; incoming_byte_stream->error = GRPC_ERROR_NONE; grpc_chttp2_incoming_frame_queue *q = &s->incoming_frames; if (q->head == NULL) { q->head = incoming_byte_stream; } else { q->tail->is_tail = 0; q->tail->next_message = incoming_byte_stream; } q->tail = incoming_byte_stream; grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s); return incoming_byte_stream; } /******************************************************************************* * RESOURCE QUOTAS */ static void post_benign_reclaimer(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { if (!t->benign_reclaimer_registered) { t->benign_reclaimer_registered = true; GRPC_CHTTP2_REF_TRANSPORT(t, "benign_reclaimer"); grpc_resource_user_post_reclaimer(exec_ctx, grpc_endpoint_get_resource_user(t->ep), false, &t->benign_reclaimer_locked); } } static void post_destructive_reclaimer(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { if (!t->destructive_reclaimer_registered) { t->destructive_reclaimer_registered = true; GRPC_CHTTP2_REF_TRANSPORT(t, "destructive_reclaimer"); grpc_resource_user_post_reclaimer(exec_ctx, grpc_endpoint_get_resource_user(t->ep), true, &t->destructive_reclaimer_locked); } } static void benign_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_chttp2_transport *t = arg; if (error == GRPC_ERROR_NONE && grpc_chttp2_stream_map_size(&t->stream_map) == 0) { /* Channel with no active streams: send a goaway to try and make it * disconnect cleanly */ if (grpc_resource_quota_trace) { gpr_log(GPR_DEBUG, "HTTP2: %s - send goaway to free memory", t->peer_string); } send_goaway(exec_ctx, t, grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Buffers full"), GRPC_ERROR_INT_HTTP2_ERROR, GRPC_HTTP2_ENHANCE_YOUR_CALM)); } else if (error == GRPC_ERROR_NONE && grpc_resource_quota_trace) { gpr_log(GPR_DEBUG, "HTTP2: %s - skip benign reclamation, there are still %" PRIdPTR " streams", t->peer_string, grpc_chttp2_stream_map_size(&t->stream_map)); } t->benign_reclaimer_registered = false; if (error != GRPC_ERROR_CANCELLED) { grpc_resource_user_finish_reclamation( exec_ctx, grpc_endpoint_get_resource_user(t->ep)); } GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "benign_reclaimer"); } static void destructive_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_chttp2_transport *t = arg; size_t n = grpc_chttp2_stream_map_size(&t->stream_map); t->destructive_reclaimer_registered = false; if (error == GRPC_ERROR_NONE && n > 0) { grpc_chttp2_stream *s = grpc_chttp2_stream_map_rand(&t->stream_map); if (grpc_resource_quota_trace) { gpr_log(GPR_DEBUG, "HTTP2: %s - abandon stream id %d", t->peer_string, s->id); } grpc_chttp2_cancel_stream( exec_ctx, t, s, grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Buffers full"), GRPC_ERROR_INT_HTTP2_ERROR, GRPC_HTTP2_ENHANCE_YOUR_CALM)); if (n > 1) { /* Since we cancel one stream per destructive reclamation, if there are more streams left, we can immediately post a new reclaimer in case the resource quota needs to free more memory */ post_destructive_reclaimer(exec_ctx, t); } } if (error != GRPC_ERROR_CANCELLED) { grpc_resource_user_finish_reclamation( exec_ctx, grpc_endpoint_get_resource_user(t->ep)); } GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "destructive_reclaimer"); } /******************************************************************************* * TRACING */ static char *format_flowctl_context_var(const char *context, const char *var, int64_t val, uint32_t id) { char *name; if (context == NULL) { name = gpr_strdup(var); } else if (0 == strcmp(context, "t")) { GPR_ASSERT(id == 0); gpr_asprintf(&name, "TRANSPORT:%s", var); } else if (0 == strcmp(context, "s")) { GPR_ASSERT(id != 0); gpr_asprintf(&name, "STREAM[%d]:%s", id, var); } else { gpr_asprintf(&name, "BAD_CONTEXT[%s][%d]:%s", context, id, var); } char *name_fld = gpr_leftpad(name, ' ', 64); char *value; gpr_asprintf(&value, "%" PRId64, val); char *value_fld = gpr_leftpad(value, ' ', 8); char *result; gpr_asprintf(&result, "%s %s", name_fld, value_fld); gpr_free(name); gpr_free(name_fld); gpr_free(value); gpr_free(value_fld); return result; } void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase, grpc_chttp2_flowctl_op op, const char *context1, const char *var1, const char *context2, const char *var2, int is_client, uint32_t stream_id, int64_t val1, int64_t val2) { char *tmp_phase; char *label1 = format_flowctl_context_var(context1, var1, val1, stream_id); char *label2 = format_flowctl_context_var(context2, var2, val2, stream_id); char *clisvr = is_client ? "client" : "server"; char *prefix; tmp_phase = gpr_leftpad(phase, ' ', 8); gpr_asprintf(&prefix, "FLOW %s: %s ", tmp_phase, clisvr); gpr_free(tmp_phase); switch (op) { case GRPC_CHTTP2_FLOWCTL_MOVE: if (val2 != 0) { gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "%sMOVE %s <- %s giving %" PRId64, prefix, label1, label2, val1 + val2); } break; case GRPC_CHTTP2_FLOWCTL_CREDIT: GPR_ASSERT(val2 >= 0); if (val2 != 0) { gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "%sCREDIT %s by %s giving %" PRId64, prefix, label1, label2, val1 + val2); } break; case GRPC_CHTTP2_FLOWCTL_DEBIT: GPR_ASSERT(val2 >= 0); if (val2 != 0) { gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "%sDEBIT %s by %s giving %" PRId64, prefix, label1, label2, val1 - val2); } break; } gpr_free(label1); gpr_free(label2); gpr_free(prefix); } /******************************************************************************* * INTEGRATION GLUE */ static char *chttp2_get_peer(grpc_exec_ctx *exec_ctx, grpc_transport *t) { return gpr_strdup(((grpc_chttp2_transport *)t)->peer_string); } /******************************************************************************* * MONITORING */ static grpc_endpoint *chttp2_get_endpoint(grpc_exec_ctx *exec_ctx, grpc_transport *t) { return ((grpc_chttp2_transport *)t)->ep; } static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream), "chttp2", init_stream, set_pollset, set_pollset_set, perform_stream_op, perform_transport_op, destroy_stream, destroy_transport, chttp2_get_peer, chttp2_get_endpoint}; grpc_transport *grpc_create_chttp2_transport( grpc_exec_ctx *exec_ctx, const grpc_channel_args *channel_args, grpc_endpoint *ep, int is_client) { grpc_chttp2_transport *t = gpr_zalloc(sizeof(grpc_chttp2_transport)); init_transport(exec_ctx, t, channel_args, ep, is_client != 0); return &t->base; } void grpc_chttp2_transport_start_reading(grpc_exec_ctx *exec_ctx, grpc_transport *transport, grpc_slice_buffer *read_buffer) { grpc_chttp2_transport *t = (grpc_chttp2_transport *)transport; GRPC_CHTTP2_REF_TRANSPORT( t, "reading_action"); /* matches unref inside reading_action */ if (read_buffer != NULL) { grpc_slice_buffer_move_into(read_buffer, &t->read_buffer); gpr_free(read_buffer); } grpc_closure_sched(exec_ctx, &t->read_action_locked, GRPC_ERROR_NONE); } grpc-1.3.2/src/core/ext/transport/chttp2/transport/chttp2_transport.h000066400000000000000000000046041310511640000257470ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_CHTTP2_TRANSPORT_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_CHTTP2_TRANSPORT_H #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/transport/transport.h" extern int grpc_http_trace; extern int grpc_flowctl_trace; grpc_transport *grpc_create_chttp2_transport( grpc_exec_ctx *exec_ctx, const grpc_channel_args *channel_args, grpc_endpoint *ep, int is_client); /// Takes ownership of \a read_buffer, which (if non-NULL) contains /// leftover bytes previously read from the endpoint (e.g., by handshakers). void grpc_chttp2_transport_start_reading(grpc_exec_ctx *exec_ctx, grpc_transport *transport, grpc_slice_buffer *read_buffer); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_CHTTP2_TRANSPORT_H */ grpc-1.3.2/src/core/ext/transport/chttp2/transport/frame.h000066400000000000000000000046731310511640000235270ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_H #include #include #include "src/core/lib/iomgr/error.h" /* defined in internal.h */ typedef struct grpc_chttp2_stream grpc_chttp2_stream; typedef struct grpc_chttp2_transport grpc_chttp2_transport; #define GRPC_CHTTP2_FRAME_DATA 0 #define GRPC_CHTTP2_FRAME_HEADER 1 #define GRPC_CHTTP2_FRAME_CONTINUATION 9 #define GRPC_CHTTP2_FRAME_RST_STREAM 3 #define GRPC_CHTTP2_FRAME_SETTINGS 4 #define GRPC_CHTTP2_FRAME_PING 6 #define GRPC_CHTTP2_FRAME_GOAWAY 7 #define GRPC_CHTTP2_FRAME_WINDOW_UPDATE 8 #define GRPC_CHTTP2_DATA_FLAG_END_STREAM 1 #define GRPC_CHTTP2_FLAG_ACK 1 #define GRPC_CHTTP2_DATA_FLAG_END_HEADERS 4 #define GRPC_CHTTP2_DATA_FLAG_PADDED 8 #define GRPC_CHTTP2_FLAG_HAS_PRIORITY 0x20 #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_H */ grpc-1.3.2/src/core/ext/transport/chttp2/transport/frame_data.c000066400000000000000000000240721310511640000245060ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/transport/frame_data.h" #include #include #include #include #include #include "src/core/ext/transport/chttp2/transport/internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/string.h" #include "src/core/lib/transport/transport.h" grpc_error *grpc_chttp2_data_parser_init(grpc_chttp2_data_parser *parser) { parser->state = GRPC_CHTTP2_DATA_FH_0; parser->parsing_frame = NULL; return GRPC_ERROR_NONE; } void grpc_chttp2_data_parser_destroy(grpc_exec_ctx *exec_ctx, grpc_chttp2_data_parser *parser) { if (parser->parsing_frame != NULL) { grpc_chttp2_incoming_byte_stream_finished( exec_ctx, parser->parsing_frame, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Parser destroyed")); } GRPC_ERROR_UNREF(parser->error); } grpc_error *grpc_chttp2_data_parser_begin_frame(grpc_chttp2_data_parser *parser, uint8_t flags, uint32_t stream_id) { if (flags & ~GRPC_CHTTP2_DATA_FLAG_END_STREAM) { char *msg; gpr_asprintf(&msg, "unsupported data flags: 0x%02x", flags); grpc_error *err = grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg), GRPC_ERROR_INT_STREAM_ID, (intptr_t)stream_id); gpr_free(msg); return err; } if (flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) { parser->is_last_frame = 1; } else { parser->is_last_frame = 0; } return GRPC_ERROR_NONE; } void grpc_chttp2_incoming_frame_queue_merge( grpc_chttp2_incoming_frame_queue *head_dst, grpc_chttp2_incoming_frame_queue *tail_src) { if (tail_src->head == NULL) { return; } if (head_dst->head == NULL) { *head_dst = *tail_src; memset(tail_src, 0, sizeof(*tail_src)); return; } head_dst->tail->next_message = tail_src->head; head_dst->tail = tail_src->tail; memset(tail_src, 0, sizeof(*tail_src)); } grpc_byte_stream *grpc_chttp2_incoming_frame_queue_pop( grpc_chttp2_incoming_frame_queue *q) { grpc_byte_stream *out; if (q->head == NULL) { return NULL; } out = &q->head->base; if (q->head == q->tail) { memset(q, 0, sizeof(*q)); } else { q->head = q->head->next_message; } return out; } void grpc_chttp2_encode_data(uint32_t id, grpc_slice_buffer *inbuf, uint32_t write_bytes, int is_eof, grpc_transport_one_way_stats *stats, grpc_slice_buffer *outbuf) { grpc_slice hdr; uint8_t *p; static const size_t header_size = 9; hdr = grpc_slice_malloc(header_size); p = GRPC_SLICE_START_PTR(hdr); GPR_ASSERT(write_bytes < (1 << 24)); *p++ = (uint8_t)(write_bytes >> 16); *p++ = (uint8_t)(write_bytes >> 8); *p++ = (uint8_t)(write_bytes); *p++ = GRPC_CHTTP2_FRAME_DATA; *p++ = is_eof ? GRPC_CHTTP2_DATA_FLAG_END_STREAM : 0; *p++ = (uint8_t)(id >> 24); *p++ = (uint8_t)(id >> 16); *p++ = (uint8_t)(id >> 8); *p++ = (uint8_t)(id); grpc_slice_buffer_add(outbuf, hdr); grpc_slice_buffer_move_first(inbuf, write_bytes, outbuf); stats->framing_bytes += header_size; stats->data_bytes += write_bytes; } static grpc_error *parse_inner(grpc_exec_ctx *exec_ctx, grpc_chttp2_data_parser *p, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_slice slice) { uint8_t *const beg = GRPC_SLICE_START_PTR(slice); uint8_t *const end = GRPC_SLICE_END_PTR(slice); uint8_t *cur = beg; uint32_t message_flags; grpc_chttp2_incoming_byte_stream *incoming_byte_stream; char *msg; if (cur == end) { return GRPC_ERROR_NONE; } switch (p->state) { case GRPC_CHTTP2_DATA_ERROR: p->state = GRPC_CHTTP2_DATA_ERROR; return GRPC_ERROR_REF(p->error); fh_0: case GRPC_CHTTP2_DATA_FH_0: s->stats.incoming.framing_bytes++; p->frame_type = *cur; switch (p->frame_type) { case 0: p->is_frame_compressed = 0; /* GPR_FALSE */ break; case 1: p->is_frame_compressed = 1; /* GPR_TRUE */ break; default: gpr_asprintf(&msg, "Bad GRPC frame type 0x%02x", p->frame_type); p->error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); p->error = grpc_error_set_int(p->error, GRPC_ERROR_INT_STREAM_ID, (intptr_t)s->id); gpr_free(msg); msg = grpc_dump_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII); p->error = grpc_error_set_str(p->error, GRPC_ERROR_STR_RAW_BYTES, grpc_slice_from_copied_string(msg)); gpr_free(msg); p->error = grpc_error_set_int(p->error, GRPC_ERROR_INT_OFFSET, cur - beg); p->state = GRPC_CHTTP2_DATA_ERROR; return GRPC_ERROR_REF(p->error); } if (++cur == end) { p->state = GRPC_CHTTP2_DATA_FH_1; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_CHTTP2_DATA_FH_1: s->stats.incoming.framing_bytes++; p->frame_size = ((uint32_t)*cur) << 24; if (++cur == end) { p->state = GRPC_CHTTP2_DATA_FH_2; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_CHTTP2_DATA_FH_2: s->stats.incoming.framing_bytes++; p->frame_size |= ((uint32_t)*cur) << 16; if (++cur == end) { p->state = GRPC_CHTTP2_DATA_FH_3; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_CHTTP2_DATA_FH_3: s->stats.incoming.framing_bytes++; p->frame_size |= ((uint32_t)*cur) << 8; if (++cur == end) { p->state = GRPC_CHTTP2_DATA_FH_4; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_CHTTP2_DATA_FH_4: s->stats.incoming.framing_bytes++; p->frame_size |= ((uint32_t)*cur); p->state = GRPC_CHTTP2_DATA_FRAME; ++cur; message_flags = 0; if (p->is_frame_compressed) { message_flags |= GRPC_WRITE_INTERNAL_COMPRESS; } p->parsing_frame = incoming_byte_stream = grpc_chttp2_incoming_byte_stream_create(exec_ctx, t, s, p->frame_size, message_flags); /* fallthrough */ case GRPC_CHTTP2_DATA_FRAME: if (cur == end) { return GRPC_ERROR_NONE; } uint32_t remaining = (uint32_t)(end - cur); if (remaining == p->frame_size) { s->stats.incoming.data_bytes += p->frame_size; grpc_chttp2_incoming_byte_stream_push( exec_ctx, p->parsing_frame, grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg))); grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame, GRPC_ERROR_NONE); p->parsing_frame = NULL; p->state = GRPC_CHTTP2_DATA_FH_0; return GRPC_ERROR_NONE; } else if (remaining > p->frame_size) { s->stats.incoming.data_bytes += p->frame_size; grpc_chttp2_incoming_byte_stream_push( exec_ctx, p->parsing_frame, grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(cur + p->frame_size - beg))); grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame, GRPC_ERROR_NONE); p->parsing_frame = NULL; cur += p->frame_size; goto fh_0; /* loop */ } else { GPR_ASSERT(remaining <= p->frame_size); grpc_chttp2_incoming_byte_stream_push( exec_ctx, p->parsing_frame, grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg))); p->frame_size -= remaining; s->stats.incoming.data_bytes += remaining; return GRPC_ERROR_NONE; } } GPR_UNREACHABLE_CODE( return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Should never reach here")); } grpc_error *grpc_chttp2_data_parser_parse(grpc_exec_ctx *exec_ctx, void *parser, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_slice slice, int is_last) { grpc_chttp2_data_parser *p = parser; grpc_error *error = parse_inner(exec_ctx, p, t, s, slice); if (is_last && p->is_last_frame) { grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, false, GRPC_ERROR_NONE); } return error; } grpc-1.3.2/src/core/ext/transport/chttp2/transport/frame_data.h000066400000000000000000000101321310511640000245030ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_DATA_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_DATA_H /* Parser for GRPC streams embedded in DATA frames */ #include #include #include "src/core/ext/transport/chttp2/transport/frame.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/transport/byte_stream.h" #include "src/core/lib/transport/transport.h" typedef enum { GRPC_CHTTP2_DATA_FH_0, GRPC_CHTTP2_DATA_FH_1, GRPC_CHTTP2_DATA_FH_2, GRPC_CHTTP2_DATA_FH_3, GRPC_CHTTP2_DATA_FH_4, GRPC_CHTTP2_DATA_FRAME, GRPC_CHTTP2_DATA_ERROR } grpc_chttp2_stream_state; typedef struct grpc_chttp2_incoming_byte_stream grpc_chttp2_incoming_byte_stream; typedef struct grpc_chttp2_incoming_frame_queue { grpc_chttp2_incoming_byte_stream *head; grpc_chttp2_incoming_byte_stream *tail; } grpc_chttp2_incoming_frame_queue; typedef struct { grpc_chttp2_stream_state state; uint8_t is_last_frame; uint8_t frame_type; uint32_t frame_size; grpc_error *error; int is_frame_compressed; grpc_chttp2_incoming_byte_stream *parsing_frame; } grpc_chttp2_data_parser; void grpc_chttp2_incoming_frame_queue_merge( grpc_chttp2_incoming_frame_queue *head_dst, grpc_chttp2_incoming_frame_queue *tail_src); grpc_byte_stream *grpc_chttp2_incoming_frame_queue_pop( grpc_chttp2_incoming_frame_queue *q); /* initialize per-stream state for data frame parsing */ grpc_error *grpc_chttp2_data_parser_init(grpc_chttp2_data_parser *parser); void grpc_chttp2_data_parser_destroy(grpc_exec_ctx *exec_ctx, grpc_chttp2_data_parser *parser); /* start processing a new data frame */ grpc_error *grpc_chttp2_data_parser_begin_frame(grpc_chttp2_data_parser *parser, uint8_t flags, uint32_t stream_id); /* handle a slice of a data frame - is_last indicates the last slice of a frame */ grpc_error *grpc_chttp2_data_parser_parse(grpc_exec_ctx *exec_ctx, void *parser, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_slice slice, int is_last); void grpc_chttp2_encode_data(uint32_t id, grpc_slice_buffer *inbuf, uint32_t write_bytes, int is_eof, grpc_transport_one_way_stats *stats, grpc_slice_buffer *outbuf); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_DATA_H */ grpc-1.3.2/src/core/ext/transport/chttp2/transport/frame_goaway.c000066400000000000000000000153501310511640000250630ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/transport/frame_goaway.h" #include "src/core/ext/transport/chttp2/transport/internal.h" #include #include #include #include void grpc_chttp2_goaway_parser_init(grpc_chttp2_goaway_parser *p) { p->debug_data = NULL; } void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser *p) { gpr_free(p->debug_data); } grpc_error *grpc_chttp2_goaway_parser_begin_frame(grpc_chttp2_goaway_parser *p, uint32_t length, uint8_t flags) { if (length < 8) { char *msg; gpr_asprintf(&msg, "goaway frame too short (%d bytes)", length); grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return err; } gpr_free(p->debug_data); p->debug_length = length - 8; p->debug_data = gpr_malloc(p->debug_length); p->debug_pos = 0; p->state = GRPC_CHTTP2_GOAWAY_LSI0; return GRPC_ERROR_NONE; } grpc_error *grpc_chttp2_goaway_parser_parse(grpc_exec_ctx *exec_ctx, void *parser, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_slice slice, int is_last) { uint8_t *const beg = GRPC_SLICE_START_PTR(slice); uint8_t *const end = GRPC_SLICE_END_PTR(slice); uint8_t *cur = beg; grpc_chttp2_goaway_parser *p = parser; switch (p->state) { case GRPC_CHTTP2_GOAWAY_LSI0: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_LSI0; return GRPC_ERROR_NONE; } p->last_stream_id = ((uint32_t)*cur) << 24; ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_LSI1: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_LSI1; return GRPC_ERROR_NONE; } p->last_stream_id |= ((uint32_t)*cur) << 16; ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_LSI2: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_LSI2; return GRPC_ERROR_NONE; } p->last_stream_id |= ((uint32_t)*cur) << 8; ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_LSI3: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_LSI3; return GRPC_ERROR_NONE; } p->last_stream_id |= ((uint32_t)*cur); ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_ERR0: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_ERR0; return GRPC_ERROR_NONE; } p->error_code = ((uint32_t)*cur) << 24; ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_ERR1: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_ERR1; return GRPC_ERROR_NONE; } p->error_code |= ((uint32_t)*cur) << 16; ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_ERR2: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_ERR2; return GRPC_ERROR_NONE; } p->error_code |= ((uint32_t)*cur) << 8; ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_ERR3: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_ERR3; return GRPC_ERROR_NONE; } p->error_code |= ((uint32_t)*cur); ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_DEBUG: if (end != cur) memcpy(p->debug_data + p->debug_pos, cur, (size_t)(end - cur)); GPR_ASSERT((size_t)(end - cur) < UINT32_MAX - p->debug_pos); p->debug_pos += (uint32_t)(end - cur); p->state = GRPC_CHTTP2_GOAWAY_DEBUG; if (is_last) { grpc_chttp2_add_incoming_goaway( exec_ctx, t, (uint32_t)p->error_code, grpc_slice_new(p->debug_data, p->debug_length, gpr_free)); p->debug_data = NULL; } return GRPC_ERROR_NONE; } GPR_UNREACHABLE_CODE( return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Should never reach here")); } void grpc_chttp2_goaway_append(uint32_t last_stream_id, uint32_t error_code, grpc_slice debug_data, grpc_slice_buffer *slice_buffer) { grpc_slice header = grpc_slice_malloc(9 + 4 + 4); uint8_t *p = GRPC_SLICE_START_PTR(header); uint32_t frame_length; GPR_ASSERT(GRPC_SLICE_LENGTH(debug_data) < UINT32_MAX - 4 - 4); frame_length = 4 + 4 + (uint32_t)GRPC_SLICE_LENGTH(debug_data); /* frame header: length */ *p++ = (uint8_t)(frame_length >> 16); *p++ = (uint8_t)(frame_length >> 8); *p++ = (uint8_t)(frame_length); /* frame header: type */ *p++ = GRPC_CHTTP2_FRAME_GOAWAY; /* frame header: flags */ *p++ = 0; /* frame header: stream id */ *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; /* payload: last stream id */ *p++ = (uint8_t)(last_stream_id >> 24); *p++ = (uint8_t)(last_stream_id >> 16); *p++ = (uint8_t)(last_stream_id >> 8); *p++ = (uint8_t)(last_stream_id); /* payload: error code */ *p++ = (uint8_t)(error_code >> 24); *p++ = (uint8_t)(error_code >> 16); *p++ = (uint8_t)(error_code >> 8); *p++ = (uint8_t)(error_code); GPR_ASSERT(p == GRPC_SLICE_END_PTR(header)); grpc_slice_buffer_add(slice_buffer, header); grpc_slice_buffer_add(slice_buffer, debug_data); } grpc-1.3.2/src/core/ext/transport/chttp2/transport/frame_goaway.h000066400000000000000000000062731310511640000250740ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_GOAWAY_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_GOAWAY_H #include #include #include #include "src/core/ext/transport/chttp2/transport/frame.h" #include "src/core/lib/iomgr/exec_ctx.h" typedef enum { GRPC_CHTTP2_GOAWAY_LSI0, GRPC_CHTTP2_GOAWAY_LSI1, GRPC_CHTTP2_GOAWAY_LSI2, GRPC_CHTTP2_GOAWAY_LSI3, GRPC_CHTTP2_GOAWAY_ERR0, GRPC_CHTTP2_GOAWAY_ERR1, GRPC_CHTTP2_GOAWAY_ERR2, GRPC_CHTTP2_GOAWAY_ERR3, GRPC_CHTTP2_GOAWAY_DEBUG } grpc_chttp2_goaway_parse_state; typedef struct { grpc_chttp2_goaway_parse_state state; uint32_t last_stream_id; uint32_t error_code; char *debug_data; uint32_t debug_length; uint32_t debug_pos; } grpc_chttp2_goaway_parser; void grpc_chttp2_goaway_parser_init(grpc_chttp2_goaway_parser *p); void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser *p); grpc_error *grpc_chttp2_goaway_parser_begin_frame( grpc_chttp2_goaway_parser *parser, uint32_t length, uint8_t flags); grpc_error *grpc_chttp2_goaway_parser_parse(grpc_exec_ctx *exec_ctx, void *parser, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_slice slice, int is_last); void grpc_chttp2_goaway_append(uint32_t last_stream_id, uint32_t error_code, grpc_slice debug_data, grpc_slice_buffer *slice_buffer); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_GOAWAY_H */ grpc-1.3.2/src/core/ext/transport/chttp2/transport/frame_ping.c000066400000000000000000000123251310511640000245300ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/transport/frame_ping.h" #include "src/core/ext/transport/chttp2/transport/internal.h" #include #include #include #include static bool g_disable_ping_ack = false; grpc_slice grpc_chttp2_ping_create(uint8_t ack, uint64_t opaque_8bytes) { grpc_slice slice = grpc_slice_malloc(9 + 8); uint8_t *p = GRPC_SLICE_START_PTR(slice); *p++ = 0; *p++ = 0; *p++ = 8; *p++ = GRPC_CHTTP2_FRAME_PING; *p++ = ack ? 1 : 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = (uint8_t)(opaque_8bytes >> 56); *p++ = (uint8_t)(opaque_8bytes >> 48); *p++ = (uint8_t)(opaque_8bytes >> 40); *p++ = (uint8_t)(opaque_8bytes >> 32); *p++ = (uint8_t)(opaque_8bytes >> 24); *p++ = (uint8_t)(opaque_8bytes >> 16); *p++ = (uint8_t)(opaque_8bytes >> 8); *p++ = (uint8_t)(opaque_8bytes); return slice; } grpc_error *grpc_chttp2_ping_parser_begin_frame(grpc_chttp2_ping_parser *parser, uint32_t length, uint8_t flags) { if (flags & 0xfe || length != 8) { char *msg; gpr_asprintf(&msg, "invalid ping: length=%d, flags=%02x", length, flags); grpc_error *error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return error; } parser->byte = 0; parser->is_ack = flags; parser->opaque_8bytes = 0; return GRPC_ERROR_NONE; } grpc_error *grpc_chttp2_ping_parser_parse(grpc_exec_ctx *exec_ctx, void *parser, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_slice slice, int is_last) { uint8_t *const beg = GRPC_SLICE_START_PTR(slice); uint8_t *const end = GRPC_SLICE_END_PTR(slice); uint8_t *cur = beg; grpc_chttp2_ping_parser *p = parser; while (p->byte != 8 && cur != end) { p->opaque_8bytes |= (((uint64_t)*cur) << (56 - 8 * p->byte)); cur++; p->byte++; } if (p->byte == 8) { GPR_ASSERT(is_last); if (p->is_ack) { grpc_chttp2_ack_ping(exec_ctx, t, p->opaque_8bytes); } else { if (!t->is_client) { gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); gpr_timespec next_allowed_ping = gpr_time_add(t->ping_recv_state.last_ping_recv_time, t->ping_policy.min_ping_interval_without_data); if (t->keepalive_permit_without_calls == 0 && grpc_chttp2_stream_map_size(&t->stream_map) == 0) { /* According to RFC1122, the interval of TCP Keep-Alive is default to no less than two hours. When there is no outstanding streams, we restrict the number of PINGS equivalent to TCP Keep-Alive. */ next_allowed_ping = gpr_time_add(t->ping_recv_state.last_ping_recv_time, gpr_time_from_seconds(7200, GPR_TIMESPAN)); } if (gpr_time_cmp(next_allowed_ping, now) > 0) { grpc_chttp2_add_ping_strike(exec_ctx, t); } t->ping_recv_state.last_ping_recv_time = now; } if (!g_disable_ping_ack) { if (t->ping_ack_count == t->ping_ack_capacity) { t->ping_ack_capacity = GPR_MAX(t->ping_ack_capacity * 3 / 2, 3); t->ping_acks = gpr_realloc( t->ping_acks, t->ping_ack_capacity * sizeof(*t->ping_acks)); } t->ping_acks[t->ping_ack_count++] = p->opaque_8bytes; grpc_chttp2_initiate_write(exec_ctx, t, false, "ping response"); } } } return GRPC_ERROR_NONE; } void grpc_set_disable_ping_ack(bool disable_ping_ack) { g_disable_ping_ack = disable_ping_ack; } grpc-1.3.2/src/core/ext/transport/chttp2/transport/frame_ping.h000066400000000000000000000050751310511640000245410ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_PING_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_PING_H #include #include "src/core/ext/transport/chttp2/transport/frame.h" #include "src/core/lib/iomgr/exec_ctx.h" typedef struct { uint8_t byte; uint8_t is_ack; uint64_t opaque_8bytes; } grpc_chttp2_ping_parser; grpc_slice grpc_chttp2_ping_create(uint8_t ack, uint64_t opaque_8bytes); grpc_error *grpc_chttp2_ping_parser_begin_frame(grpc_chttp2_ping_parser *parser, uint32_t length, uint8_t flags); grpc_error *grpc_chttp2_ping_parser_parse(grpc_exec_ctx *exec_ctx, void *parser, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_slice slice, int is_last); /* Test-only function for disabling ping ack */ void grpc_set_disable_ping_ack(bool disable_ping_ack); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_PING_H */ grpc-1.3.2/src/core/ext/transport/chttp2/transport/frame_rst_stream.c000066400000000000000000000111561310511640000257570ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/transport/frame_rst_stream.h" #include "src/core/ext/transport/chttp2/transport/internal.h" #include #include #include #include "src/core/ext/transport/chttp2/transport/frame.h" #include "src/core/lib/transport/http2_errors.h" grpc_slice grpc_chttp2_rst_stream_create(uint32_t id, uint32_t code, grpc_transport_one_way_stats *stats) { static const size_t frame_size = 13; grpc_slice slice = grpc_slice_malloc(frame_size); stats->framing_bytes += frame_size; uint8_t *p = GRPC_SLICE_START_PTR(slice); // Frame size. *p++ = 0; *p++ = 0; *p++ = 4; // Frame type. *p++ = GRPC_CHTTP2_FRAME_RST_STREAM; // Flags. *p++ = 0; // Stream ID. *p++ = (uint8_t)(id >> 24); *p++ = (uint8_t)(id >> 16); *p++ = (uint8_t)(id >> 8); *p++ = (uint8_t)(id); // Error code. *p++ = (uint8_t)(code >> 24); *p++ = (uint8_t)(code >> 16); *p++ = (uint8_t)(code >> 8); *p++ = (uint8_t)(code); return slice; } grpc_error *grpc_chttp2_rst_stream_parser_begin_frame( grpc_chttp2_rst_stream_parser *parser, uint32_t length, uint8_t flags) { if (length != 4) { char *msg; gpr_asprintf(&msg, "invalid rst_stream: length=%d, flags=%02x", length, flags); grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return err; } parser->byte = 0; return GRPC_ERROR_NONE; } grpc_error *grpc_chttp2_rst_stream_parser_parse(grpc_exec_ctx *exec_ctx, void *parser, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_slice slice, int is_last) { uint8_t *const beg = GRPC_SLICE_START_PTR(slice); uint8_t *const end = GRPC_SLICE_END_PTR(slice); uint8_t *cur = beg; grpc_chttp2_rst_stream_parser *p = parser; while (p->byte != 4 && cur != end) { p->reason_bytes[p->byte] = *cur; cur++; p->byte++; } s->stats.incoming.framing_bytes += (uint64_t)(end - cur); if (p->byte == 4) { GPR_ASSERT(is_last); uint32_t reason = (((uint32_t)p->reason_bytes[0]) << 24) | (((uint32_t)p->reason_bytes[1]) << 16) | (((uint32_t)p->reason_bytes[2]) << 8) | (((uint32_t)p->reason_bytes[3])); grpc_error *error = GRPC_ERROR_NONE; if (reason != GRPC_HTTP2_NO_ERROR || s->header_frames_received < 2) { char *message; gpr_asprintf(&message, "Received RST_STREAM with error code %d", reason); error = grpc_error_set_int( grpc_error_set_str(GRPC_ERROR_CREATE_FROM_STATIC_STRING("RST_STREAM"), GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_copied_string(message)), GRPC_ERROR_INT_HTTP2_ERROR, (intptr_t)reason); gpr_free(message); } grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, true, error); } return GRPC_ERROR_NONE; } grpc-1.3.2/src/core/ext/transport/chttp2/transport/frame_rst_stream.h000066400000000000000000000052051310511640000257620ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_RST_STREAM_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_RST_STREAM_H #include #include "src/core/ext/transport/chttp2/transport/frame.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/transport/transport.h" typedef struct { uint8_t byte; uint8_t reason_bytes[4]; } grpc_chttp2_rst_stream_parser; grpc_slice grpc_chttp2_rst_stream_create(uint32_t stream_id, uint32_t code, grpc_transport_one_way_stats *stats); grpc_error *grpc_chttp2_rst_stream_parser_begin_frame( grpc_chttp2_rst_stream_parser *parser, uint32_t length, uint8_t flags); grpc_error *grpc_chttp2_rst_stream_parser_parse(grpc_exec_ctx *exec_ctx, void *parser, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_slice slice, int is_last); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_RST_STREAM_H */ grpc-1.3.2/src/core/ext/transport/chttp2/transport/frame_settings.c000066400000000000000000000205631310511640000254360ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/transport/frame_settings.h" #include "src/core/ext/transport/chttp2/transport/internal.h" #include #include #include #include #include #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/ext/transport/chttp2/transport/frame.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/transport/http2_errors.h" static uint8_t *fill_header(uint8_t *out, uint32_t length, uint8_t flags) { *out++ = (uint8_t)(length >> 16); *out++ = (uint8_t)(length >> 8); *out++ = (uint8_t)(length); *out++ = GRPC_CHTTP2_FRAME_SETTINGS; *out++ = flags; *out++ = 0; *out++ = 0; *out++ = 0; *out++ = 0; return out; } grpc_slice grpc_chttp2_settings_create(uint32_t *old, const uint32_t *new, uint32_t force_mask, size_t count) { size_t i; uint32_t n = 0; grpc_slice output; uint8_t *p; for (i = 0; i < count; i++) { n += (new[i] != old[i] || (force_mask & (1u << i)) != 0); } output = grpc_slice_malloc(9 + 6 * n); p = fill_header(GRPC_SLICE_START_PTR(output), 6 * n, 0); for (i = 0; i < count; i++) { if (new[i] != old[i] || (force_mask & (1u << i)) != 0) { *p++ = (uint8_t)(grpc_setting_id_to_wire_id[i] >> 8); *p++ = (uint8_t)(grpc_setting_id_to_wire_id[i]); *p++ = (uint8_t)(new[i] >> 24); *p++ = (uint8_t)(new[i] >> 16); *p++ = (uint8_t)(new[i] >> 8); *p++ = (uint8_t)(new[i]); old[i] = new[i]; } } GPR_ASSERT(p == GRPC_SLICE_END_PTR(output)); return output; } grpc_slice grpc_chttp2_settings_ack_create(void) { grpc_slice output = grpc_slice_malloc(9); fill_header(GRPC_SLICE_START_PTR(output), 0, GRPC_CHTTP2_FLAG_ACK); return output; } grpc_error *grpc_chttp2_settings_parser_begin_frame( grpc_chttp2_settings_parser *parser, uint32_t length, uint8_t flags, uint32_t *settings) { parser->target_settings = settings; memcpy(parser->incoming_settings, settings, GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t)); parser->is_ack = 0; parser->state = GRPC_CHTTP2_SPS_ID0; if (flags == GRPC_CHTTP2_FLAG_ACK) { parser->is_ack = 1; if (length != 0) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "non-empty settings ack frame received"); } return GRPC_ERROR_NONE; } else if (flags != 0) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "invalid flags on settings frame"); } else if (length % 6 != 0) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "settings frames must be a multiple of six bytes"); } else { return GRPC_ERROR_NONE; } } grpc_error *grpc_chttp2_settings_parser_parse(grpc_exec_ctx *exec_ctx, void *p, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_slice slice, int is_last) { grpc_chttp2_settings_parser *parser = p; const uint8_t *cur = GRPC_SLICE_START_PTR(slice); const uint8_t *end = GRPC_SLICE_END_PTR(slice); char *msg; grpc_chttp2_setting_id id; if (parser->is_ack) { return GRPC_ERROR_NONE; } for (;;) { switch (parser->state) { case GRPC_CHTTP2_SPS_ID0: if (cur == end) { parser->state = GRPC_CHTTP2_SPS_ID0; if (is_last) { memcpy(parser->target_settings, parser->incoming_settings, GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t)); grpc_slice_buffer_add(&t->qbuf, grpc_chttp2_settings_ack_create()); } return GRPC_ERROR_NONE; } parser->id = (uint16_t)(((uint16_t)*cur) << 8); cur++; /* fallthrough */ case GRPC_CHTTP2_SPS_ID1: if (cur == end) { parser->state = GRPC_CHTTP2_SPS_ID1; return GRPC_ERROR_NONE; } parser->id = (uint16_t)(parser->id | (*cur)); cur++; /* fallthrough */ case GRPC_CHTTP2_SPS_VAL0: if (cur == end) { parser->state = GRPC_CHTTP2_SPS_VAL0; return GRPC_ERROR_NONE; } parser->value = ((uint32_t)*cur) << 24; cur++; /* fallthrough */ case GRPC_CHTTP2_SPS_VAL1: if (cur == end) { parser->state = GRPC_CHTTP2_SPS_VAL1; return GRPC_ERROR_NONE; } parser->value |= ((uint32_t)*cur) << 16; cur++; /* fallthrough */ case GRPC_CHTTP2_SPS_VAL2: if (cur == end) { parser->state = GRPC_CHTTP2_SPS_VAL2; return GRPC_ERROR_NONE; } parser->value |= ((uint32_t)*cur) << 8; cur++; /* fallthrough */ case GRPC_CHTTP2_SPS_VAL3: if (cur == end) { parser->state = GRPC_CHTTP2_SPS_VAL3; return GRPC_ERROR_NONE; } else { parser->state = GRPC_CHTTP2_SPS_ID0; } parser->value |= *cur; cur++; if (grpc_wire_id_to_setting_id(parser->id, &id)) { const grpc_chttp2_setting_parameters *sp = &grpc_chttp2_settings_parameters[id]; if (parser->value < sp->min_value || parser->value > sp->max_value) { switch (sp->invalid_value_behavior) { case GRPC_CHTTP2_CLAMP_INVALID_VALUE: parser->value = GPR_CLAMP(parser->value, sp->min_value, sp->max_value); break; case GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE: grpc_chttp2_goaway_append( t->last_new_stream_id, sp->error_value, grpc_slice_from_static_string("HTTP2 settings error"), &t->qbuf); gpr_asprintf(&msg, "invalid value %u passed for %s", parser->value, sp->name); grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return err; } } if (id == GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE && parser->incoming_settings[id] != parser->value) { t->initial_window_update += (int64_t)parser->value - parser->incoming_settings[id]; if (grpc_http_trace) { gpr_log(GPR_DEBUG, "adding %d for initial_window change", (int)t->initial_window_update); } } parser->incoming_settings[id] = parser->value; if (grpc_http_trace) { gpr_log(GPR_DEBUG, "CHTTP2:%s:%s: got setting %s = %d", t->is_client ? "CLI" : "SVR", t->peer_string, sp->name, parser->value); } } else if (grpc_http_trace) { gpr_log(GPR_ERROR, "CHTTP2: Ignoring unknown setting %d (value %d)", parser->id, parser->value); } break; } } } grpc-1.3.2/src/core/ext/transport/chttp2/transport/frame_settings.h000066400000000000000000000062571310511640000254470ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_SETTINGS_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_SETTINGS_H #include #include #include "src/core/ext/transport/chttp2/transport/frame.h" #include "src/core/ext/transport/chttp2/transport/http2_settings.h" #include "src/core/lib/iomgr/exec_ctx.h" typedef enum { GRPC_CHTTP2_SPS_ID0, GRPC_CHTTP2_SPS_ID1, GRPC_CHTTP2_SPS_VAL0, GRPC_CHTTP2_SPS_VAL1, GRPC_CHTTP2_SPS_VAL2, GRPC_CHTTP2_SPS_VAL3 } grpc_chttp2_settings_parse_state; typedef struct { grpc_chttp2_settings_parse_state state; uint32_t *target_settings; uint8_t is_ack; uint16_t id; uint32_t value; uint32_t incoming_settings[GRPC_CHTTP2_NUM_SETTINGS]; } grpc_chttp2_settings_parser; /* Create a settings frame by diffing old & new, and updating old to be new */ grpc_slice grpc_chttp2_settings_create(uint32_t *old, const uint32_t *newval, uint32_t force_mask, size_t count); /* Create an ack settings frame */ grpc_slice grpc_chttp2_settings_ack_create(void); grpc_error *grpc_chttp2_settings_parser_begin_frame( grpc_chttp2_settings_parser *parser, uint32_t length, uint8_t flags, uint32_t *settings); grpc_error *grpc_chttp2_settings_parser_parse(grpc_exec_ctx *exec_ctx, void *parser, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_slice slice, int is_last); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_SETTINGS_H */ grpc-1.3.2/src/core/ext/transport/chttp2/transport/frame_window_update.c000066400000000000000000000112401310511640000264370ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/transport/frame_window_update.h" #include "src/core/ext/transport/chttp2/transport/internal.h" #include #include #include grpc_slice grpc_chttp2_window_update_create( uint32_t id, uint32_t window_update, grpc_transport_one_way_stats *stats) { static const size_t frame_size = 13; grpc_slice slice = grpc_slice_malloc(frame_size); stats->header_bytes += frame_size; uint8_t *p = GRPC_SLICE_START_PTR(slice); GPR_ASSERT(window_update); *p++ = 0; *p++ = 0; *p++ = 4; *p++ = GRPC_CHTTP2_FRAME_WINDOW_UPDATE; *p++ = 0; *p++ = (uint8_t)(id >> 24); *p++ = (uint8_t)(id >> 16); *p++ = (uint8_t)(id >> 8); *p++ = (uint8_t)(id); *p++ = (uint8_t)(window_update >> 24); *p++ = (uint8_t)(window_update >> 16); *p++ = (uint8_t)(window_update >> 8); *p++ = (uint8_t)(window_update); return slice; } grpc_error *grpc_chttp2_window_update_parser_begin_frame( grpc_chttp2_window_update_parser *parser, uint32_t length, uint8_t flags) { if (flags || length != 4) { char *msg; gpr_asprintf(&msg, "invalid window update: length=%d, flags=%02x", length, flags); grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return err; } parser->byte = 0; parser->amount = 0; return GRPC_ERROR_NONE; } grpc_error *grpc_chttp2_window_update_parser_parse( grpc_exec_ctx *exec_ctx, void *parser, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_slice slice, int is_last) { uint8_t *const beg = GRPC_SLICE_START_PTR(slice); uint8_t *const end = GRPC_SLICE_END_PTR(slice); uint8_t *cur = beg; grpc_chttp2_window_update_parser *p = parser; while (p->byte != 4 && cur != end) { p->amount |= ((uint32_t)*cur) << (8 * (3 - p->byte)); cur++; p->byte++; } if (s != NULL) { s->stats.incoming.framing_bytes += (uint32_t)(end - cur); } if (p->byte == 4) { uint32_t received_update = p->amount; if (received_update == 0 || (received_update & 0x80000000u)) { char *msg; gpr_asprintf(&msg, "invalid window update bytes: %d", p->amount); grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return err; } GPR_ASSERT(is_last); if (t->incoming_stream_id != 0) { if (s != NULL) { GRPC_CHTTP2_FLOW_CREDIT_STREAM("parse", t, s, outgoing_window_delta, received_update); if (grpc_chttp2_list_remove_stalled_by_stream(t, s)) { grpc_chttp2_become_writable( exec_ctx, t, s, GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED, "stream.read_flow_control"); } } } else { bool was_zero = t->outgoing_window <= 0; GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parse", t, outgoing_window, received_update); bool is_zero = t->outgoing_window <= 0; if (was_zero && !is_zero) { grpc_chttp2_initiate_write(exec_ctx, t, false, "new_global_flow_control"); } } } return GRPC_ERROR_NONE; } grpc-1.3.2/src/core/ext/transport/chttp2/transport/frame_window_update.h000066400000000000000000000047331310511640000264550ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_WINDOW_UPDATE_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_WINDOW_UPDATE_H #include #include "src/core/ext/transport/chttp2/transport/frame.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/transport/transport.h" typedef struct { uint8_t byte; uint8_t is_connection_update; uint32_t amount; } grpc_chttp2_window_update_parser; grpc_slice grpc_chttp2_window_update_create( uint32_t id, uint32_t window_delta, grpc_transport_one_way_stats *stats); grpc_error *grpc_chttp2_window_update_parser_begin_frame( grpc_chttp2_window_update_parser *parser, uint32_t length, uint8_t flags); grpc_error *grpc_chttp2_window_update_parser_parse( grpc_exec_ctx *exec_ctx, void *parser, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_slice slice, int is_last); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_WINDOW_UPDATE_H */ grpc-1.3.2/src/core/ext/transport/chttp2/transport/hpack_encoder.c000066400000000000000000000622621310511640000252130ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/transport/hpack_encoder.h" #include #include /* This is here for grpc_is_binary_header * TODO(murgatroid99): Remove this */ #include #include #include #include #include "src/core/ext/transport/chttp2/transport/bin_encoder.h" #include "src/core/ext/transport/chttp2/transport/hpack_table.h" #include "src/core/ext/transport/chttp2/transport/varint.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/timeout_encoding.h" #define HASH_FRAGMENT_1(x) ((x)&255) #define HASH_FRAGMENT_2(x) ((x >> 8) & 255) #define HASH_FRAGMENT_3(x) ((x >> 16) & 255) #define HASH_FRAGMENT_4(x) ((x >> 24) & 255) /* if the probability of this item being seen again is < 1/x then don't add it to the table */ #define ONE_ON_ADD_PROBABILITY 128 /* don't consider adding anything bigger than this to the hpack table */ #define MAX_DECODER_SPACE_USAGE 512 static grpc_slice_refcount terminal_slice_refcount = {NULL, NULL}; static const grpc_slice terminal_slice = {&terminal_slice_refcount, .data.refcounted = {0, 0}}; extern int grpc_http_trace; typedef struct { int is_first_frame; /* number of bytes in 'output' when we started the frame - used to calculate frame length */ size_t output_length_at_start_of_frame; /* index (in output) of the header for the current frame */ size_t header_idx; /* have we seen a regular (non-colon-prefixed) header yet? */ uint8_t seen_regular_header; /* output stream id */ uint32_t stream_id; grpc_slice_buffer *output; grpc_transport_one_way_stats *stats; /* maximum size of a frame */ size_t max_frame_size; bool use_true_binary_metadata; } framer_state; /* fills p (which is expected to be 9 bytes long) with a data frame header */ static void fill_header(uint8_t *p, uint8_t type, uint32_t id, size_t len, uint8_t flags) { GPR_ASSERT(len < 16777316); *p++ = (uint8_t)(len >> 16); *p++ = (uint8_t)(len >> 8); *p++ = (uint8_t)(len); *p++ = type; *p++ = flags; *p++ = (uint8_t)(id >> 24); *p++ = (uint8_t)(id >> 16); *p++ = (uint8_t)(id >> 8); *p++ = (uint8_t)(id); } /* finish a frame - fill in the previously reserved header */ static void finish_frame(framer_state *st, int is_header_boundary, int is_last_in_stream) { uint8_t type = 0xff; type = st->is_first_frame ? GRPC_CHTTP2_FRAME_HEADER : GRPC_CHTTP2_FRAME_CONTINUATION; fill_header( GRPC_SLICE_START_PTR(st->output->slices[st->header_idx]), type, st->stream_id, st->output->length - st->output_length_at_start_of_frame, (uint8_t)((is_last_in_stream ? GRPC_CHTTP2_DATA_FLAG_END_STREAM : 0) | (is_header_boundary ? GRPC_CHTTP2_DATA_FLAG_END_HEADERS : 0))); st->stats->framing_bytes += 9; st->is_first_frame = 0; } /* begin a new frame: reserve off header space, remember how many bytes we'd output before beginning */ static void begin_frame(framer_state *st) { st->header_idx = grpc_slice_buffer_add_indexed(st->output, grpc_slice_malloc(9)); st->output_length_at_start_of_frame = st->output->length; } /* make sure that the current frame is of the type desired, and has sufficient space to add at least about_to_add bytes -- finishes the current frame if needed */ static void ensure_space(framer_state *st, size_t need_bytes) { if (st->output->length - st->output_length_at_start_of_frame + need_bytes <= st->max_frame_size) { return; } finish_frame(st, 0, 0); begin_frame(st); } /* increment a filter count, halve all counts if one element reaches max */ static void inc_filter(uint8_t idx, uint32_t *sum, uint8_t *elems) { elems[idx]++; if (elems[idx] < 255) { (*sum)++; } else { int i; *sum = 0; for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_FILTERS; i++) { elems[i] /= 2; (*sum) += elems[i]; } } } static void add_header_data(framer_state *st, grpc_slice slice) { size_t len = GRPC_SLICE_LENGTH(slice); size_t remaining; if (len == 0) return; remaining = st->max_frame_size + st->output_length_at_start_of_frame - st->output->length; if (len <= remaining) { st->stats->header_bytes += len; grpc_slice_buffer_add(st->output, slice); } else { st->stats->header_bytes += remaining; grpc_slice_buffer_add(st->output, grpc_slice_split_head(&slice, remaining)); finish_frame(st, 0, 0); begin_frame(st); add_header_data(st, slice); } } static uint8_t *add_tiny_header_data(framer_state *st, size_t len) { ensure_space(st, len); st->stats->header_bytes += len; return grpc_slice_buffer_tiny_add(st->output, len); } static void evict_entry(grpc_chttp2_hpack_compressor *c) { c->tail_remote_index++; GPR_ASSERT(c->tail_remote_index > 0); GPR_ASSERT(c->table_size >= c->table_elem_size[c->tail_remote_index % c->cap_table_elems]); GPR_ASSERT(c->table_elems > 0); c->table_size = (uint16_t)(c->table_size - c->table_elem_size[c->tail_remote_index % c->cap_table_elems]); c->table_elems--; } /* add an element to the decoder table */ static void add_elem(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c, grpc_mdelem elem) { GPR_ASSERT(GRPC_MDELEM_IS_INTERNED(elem)); uint32_t key_hash = grpc_slice_hash(GRPC_MDKEY(elem)); uint32_t value_hash = grpc_slice_hash(GRPC_MDVALUE(elem)); uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, value_hash); uint32_t new_index = c->tail_remote_index + c->table_elems + 1; size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem); GPR_ASSERT(elem_size < 65536); if (elem_size > c->max_table_size) { while (c->table_size > 0) { evict_entry(c); } return; } /* Reserve space for this element in the remote table: if this overflows the current table, drop elements until it fits, matching the decompressor algorithm */ while (c->table_size + elem_size > c->max_table_size) { evict_entry(c); } GPR_ASSERT(c->table_elems < c->max_table_size); c->table_elem_size[new_index % c->cap_table_elems] = (uint16_t)elem_size; c->table_size = (uint16_t)(c->table_size + elem_size); c->table_elems++; /* Store this element into {entries,indices}_elem */ if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_2(elem_hash)], elem)) { /* already there: update with new index */ c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index; } else if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_3(elem_hash)], elem)) { /* already there (cuckoo): update with new index */ c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index; } else if (GRPC_MDISNULL(c->entries_elems[HASH_FRAGMENT_2(elem_hash)])) { /* not there, but a free element: add */ c->entries_elems[HASH_FRAGMENT_2(elem_hash)] = GRPC_MDELEM_REF(elem); c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index; } else if (GRPC_MDISNULL(c->entries_elems[HASH_FRAGMENT_3(elem_hash)])) { /* not there (cuckoo), but a free element: add */ c->entries_elems[HASH_FRAGMENT_3(elem_hash)] = GRPC_MDELEM_REF(elem); c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index; } else if (c->indices_elems[HASH_FRAGMENT_2(elem_hash)] < c->indices_elems[HASH_FRAGMENT_3(elem_hash)]) { /* not there: replace oldest */ GRPC_MDELEM_UNREF(exec_ctx, c->entries_elems[HASH_FRAGMENT_2(elem_hash)]); c->entries_elems[HASH_FRAGMENT_2(elem_hash)] = GRPC_MDELEM_REF(elem); c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index; } else { /* not there: replace oldest */ GRPC_MDELEM_UNREF(exec_ctx, c->entries_elems[HASH_FRAGMENT_3(elem_hash)]); c->entries_elems[HASH_FRAGMENT_3(elem_hash)] = GRPC_MDELEM_REF(elem); c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index; } /* do exactly the same for the key (so we can find by that again too) */ if (grpc_slice_eq(c->entries_keys[HASH_FRAGMENT_2(key_hash)], GRPC_MDKEY(elem))) { c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index; } else if (grpc_slice_eq(c->entries_keys[HASH_FRAGMENT_3(key_hash)], GRPC_MDKEY(elem))) { c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index; } else if (c->entries_keys[HASH_FRAGMENT_2(key_hash)].refcount == &terminal_slice_refcount) { c->entries_keys[HASH_FRAGMENT_2(key_hash)] = grpc_slice_ref_internal(GRPC_MDKEY(elem)); c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index; } else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)].refcount == &terminal_slice_refcount) { c->entries_keys[HASH_FRAGMENT_3(key_hash)] = grpc_slice_ref_internal(GRPC_MDKEY(elem)); c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index; } else if (c->indices_keys[HASH_FRAGMENT_2(key_hash)] < c->indices_keys[HASH_FRAGMENT_3(key_hash)]) { grpc_slice_unref_internal(exec_ctx, c->entries_keys[HASH_FRAGMENT_2(key_hash)]); c->entries_keys[HASH_FRAGMENT_2(key_hash)] = grpc_slice_ref_internal(GRPC_MDKEY(elem)); c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index; } else { grpc_slice_unref_internal(exec_ctx, c->entries_keys[HASH_FRAGMENT_3(key_hash)]); c->entries_keys[HASH_FRAGMENT_3(key_hash)] = grpc_slice_ref_internal(GRPC_MDKEY(elem)); c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index; } } static void emit_indexed(grpc_chttp2_hpack_compressor *c, uint32_t elem_index, framer_state *st) { uint32_t len = GRPC_CHTTP2_VARINT_LENGTH(elem_index, 1); GRPC_CHTTP2_WRITE_VARINT(elem_index, 1, 0x80, add_tiny_header_data(st, len), len); } typedef struct { grpc_slice data; uint8_t huffman_prefix; bool insert_null_before_wire_value; } wire_value; static wire_value get_wire_value(grpc_mdelem elem, bool true_binary_enabled) { if (grpc_is_binary_header(GRPC_MDKEY(elem))) { if (true_binary_enabled) { return (wire_value){ .huffman_prefix = 0x00, .insert_null_before_wire_value = true, .data = grpc_slice_ref_internal(GRPC_MDVALUE(elem)), }; } else { return (wire_value){ .huffman_prefix = 0x80, .insert_null_before_wire_value = false, .data = grpc_chttp2_base64_encode_and_huffman_compress( GRPC_MDVALUE(elem)), }; } } else { /* TODO(ctiller): opportunistically compress non-binary headers */ return (wire_value){ .huffman_prefix = 0x00, .insert_null_before_wire_value = false, .data = grpc_slice_ref_internal(GRPC_MDVALUE(elem)), }; } } static size_t wire_value_length(wire_value v) { return GPR_SLICE_LENGTH(v.data) + v.insert_null_before_wire_value; } static void add_wire_value(framer_state *st, wire_value v) { if (v.insert_null_before_wire_value) *add_tiny_header_data(st, 1) = 0; add_header_data(st, v.data); } static void emit_lithdr_incidx(grpc_chttp2_hpack_compressor *c, uint32_t key_index, grpc_mdelem elem, framer_state *st) { uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 2); wire_value value = get_wire_value(elem, st->use_true_binary_metadata); size_t len_val = wire_value_length(value); uint32_t len_val_len; GPR_ASSERT(len_val <= UINT32_MAX); len_val_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)len_val, 1); GRPC_CHTTP2_WRITE_VARINT(key_index, 2, 0x40, add_tiny_header_data(st, len_pfx), len_pfx); GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, value.huffman_prefix, add_tiny_header_data(st, len_val_len), len_val_len); add_wire_value(st, value); } static void emit_lithdr_noidx(grpc_chttp2_hpack_compressor *c, uint32_t key_index, grpc_mdelem elem, framer_state *st) { uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 4); wire_value value = get_wire_value(elem, st->use_true_binary_metadata); size_t len_val = wire_value_length(value); uint32_t len_val_len; GPR_ASSERT(len_val <= UINT32_MAX); len_val_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)len_val, 1); GRPC_CHTTP2_WRITE_VARINT(key_index, 4, 0x00, add_tiny_header_data(st, len_pfx), len_pfx); GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, value.huffman_prefix, add_tiny_header_data(st, len_val_len), len_val_len); add_wire_value(st, value); } static void emit_lithdr_incidx_v(grpc_chttp2_hpack_compressor *c, grpc_mdelem elem, framer_state *st) { uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(GRPC_MDKEY(elem)); wire_value value = get_wire_value(elem, st->use_true_binary_metadata); uint32_t len_val = (uint32_t)wire_value_length(value); uint32_t len_key_len = GRPC_CHTTP2_VARINT_LENGTH(len_key, 1); uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1); GPR_ASSERT(len_key <= UINT32_MAX); GPR_ASSERT(wire_value_length(value) <= UINT32_MAX); *add_tiny_header_data(st, 1) = 0x40; GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00, add_tiny_header_data(st, len_key_len), len_key_len); add_header_data(st, grpc_slice_ref_internal(GRPC_MDKEY(elem))); GRPC_CHTTP2_WRITE_VARINT(len_val, 1, value.huffman_prefix, add_tiny_header_data(st, len_val_len), len_val_len); add_wire_value(st, value); } static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor *c, grpc_mdelem elem, framer_state *st) { uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(GRPC_MDKEY(elem)); wire_value value = get_wire_value(elem, st->use_true_binary_metadata); uint32_t len_val = (uint32_t)wire_value_length(value); uint32_t len_key_len = GRPC_CHTTP2_VARINT_LENGTH(len_key, 1); uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1); GPR_ASSERT(len_key <= UINT32_MAX); GPR_ASSERT(wire_value_length(value) <= UINT32_MAX); *add_tiny_header_data(st, 1) = 0x00; GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00, add_tiny_header_data(st, len_key_len), len_key_len); add_header_data(st, grpc_slice_ref_internal(GRPC_MDKEY(elem))); GRPC_CHTTP2_WRITE_VARINT(len_val, 1, value.huffman_prefix, add_tiny_header_data(st, len_val_len), len_val_len); add_wire_value(st, value); } static void emit_advertise_table_size_change(grpc_chttp2_hpack_compressor *c, framer_state *st) { uint32_t len = GRPC_CHTTP2_VARINT_LENGTH(c->max_table_size, 3); GRPC_CHTTP2_WRITE_VARINT(c->max_table_size, 3, 0x20, add_tiny_header_data(st, len), len); c->advertise_table_size_change = 0; } static uint32_t dynidx(grpc_chttp2_hpack_compressor *c, uint32_t elem_index) { return 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY + c->tail_remote_index + c->table_elems - elem_index; } /* encode an mdelem */ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c, grpc_mdelem elem, framer_state *st) { GPR_ASSERT(GRPC_SLICE_LENGTH(GRPC_MDKEY(elem)) > 0); if (GRPC_SLICE_START_PTR(GRPC_MDKEY(elem))[0] != ':') { /* regular header */ st->seen_regular_header = 1; } else { GPR_ASSERT( st->seen_regular_header == 0 && "Reserved header (colon-prefixed) happening after regular ones."); } if (grpc_http_trace && !GRPC_MDELEM_IS_INTERNED(elem)) { char *k = grpc_slice_to_c_string(GRPC_MDKEY(elem)); char *v = grpc_slice_to_c_string(GRPC_MDVALUE(elem)); gpr_log( GPR_DEBUG, "Encode: '%s: %s', elem_interned=%d [%d], k_interned=%d, v_interned=%d", k, v, GRPC_MDELEM_IS_INTERNED(elem), GRPC_MDELEM_STORAGE(elem), grpc_slice_is_interned(GRPC_MDKEY(elem)), grpc_slice_is_interned(GRPC_MDVALUE(elem))); gpr_free(k); gpr_free(v); } if (!GRPC_MDELEM_IS_INTERNED(elem)) { emit_lithdr_noidx_v(c, elem, st); return; } uint32_t key_hash; uint32_t value_hash; uint32_t elem_hash; size_t decoder_space_usage; uint32_t indices_key; int should_add_elem; key_hash = grpc_slice_hash(GRPC_MDKEY(elem)); value_hash = grpc_slice_hash(GRPC_MDVALUE(elem)); elem_hash = GRPC_MDSTR_KV_HASH(key_hash, value_hash); inc_filter(HASH_FRAGMENT_1(elem_hash), &c->filter_elems_sum, c->filter_elems); /* is this elem currently in the decoders table? */ if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_2(elem_hash)], elem) && c->indices_elems[HASH_FRAGMENT_2(elem_hash)] > c->tail_remote_index) { /* HIT: complete element (first cuckoo hash) */ emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_2(elem_hash)]), st); return; } if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_3(elem_hash)], elem) && c->indices_elems[HASH_FRAGMENT_3(elem_hash)] > c->tail_remote_index) { /* HIT: complete element (second cuckoo hash) */ emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_3(elem_hash)]), st); return; } /* should this elem be in the table? */ decoder_space_usage = grpc_mdelem_get_size_in_hpack_table(elem); should_add_elem = decoder_space_usage < MAX_DECODER_SPACE_USAGE && c->filter_elems[HASH_FRAGMENT_1(elem_hash)] >= c->filter_elems_sum / ONE_ON_ADD_PROBABILITY; /* no hits for the elem... maybe there's a key? */ indices_key = c->indices_keys[HASH_FRAGMENT_2(key_hash)]; if (grpc_slice_eq(c->entries_keys[HASH_FRAGMENT_2(key_hash)], GRPC_MDKEY(elem)) && indices_key > c->tail_remote_index) { /* HIT: key (first cuckoo hash) */ if (should_add_elem) { emit_lithdr_incidx(c, dynidx(c, indices_key), elem, st); add_elem(exec_ctx, c, elem); return; } else { emit_lithdr_noidx(c, dynidx(c, indices_key), elem, st); return; } GPR_UNREACHABLE_CODE(return ); } indices_key = c->indices_keys[HASH_FRAGMENT_3(key_hash)]; if (grpc_slice_eq(c->entries_keys[HASH_FRAGMENT_3(key_hash)], GRPC_MDKEY(elem)) && indices_key > c->tail_remote_index) { /* HIT: key (first cuckoo hash) */ if (should_add_elem) { emit_lithdr_incidx(c, dynidx(c, indices_key), elem, st); add_elem(exec_ctx, c, elem); return; } else { emit_lithdr_noidx(c, dynidx(c, indices_key), elem, st); return; } GPR_UNREACHABLE_CODE(return ); } /* no elem, key in the table... fall back to literal emission */ if (should_add_elem) { emit_lithdr_incidx_v(c, elem, st); add_elem(exec_ctx, c, elem); return; } else { emit_lithdr_noidx_v(c, elem, st); return; } GPR_UNREACHABLE_CODE(return ); } #define STRLEN_LIT(x) (sizeof(x) - 1) #define TIMEOUT_KEY "grpc-timeout" static void deadline_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c, gpr_timespec deadline, framer_state *st) { char timeout_str[GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE]; grpc_mdelem mdelem; grpc_http2_encode_timeout( gpr_time_sub(deadline, gpr_now(deadline.clock_type)), timeout_str); mdelem = grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_TIMEOUT, grpc_slice_from_copied_string(timeout_str)); hpack_enc(exec_ctx, c, mdelem, st); GRPC_MDELEM_UNREF(exec_ctx, mdelem); } static uint32_t elems_for_bytes(uint32_t bytes) { return (bytes + 31) / 32; } void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c) { memset(c, 0, sizeof(*c)); c->max_table_size = GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE; c->cap_table_elems = elems_for_bytes(c->max_table_size); c->max_table_elems = c->cap_table_elems; c->max_usable_size = GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE; c->table_elem_size = gpr_malloc(sizeof(*c->table_elem_size) * c->cap_table_elems); memset(c->table_elem_size, 0, sizeof(*c->table_elem_size) * c->cap_table_elems); for (size_t i = 0; i < GPR_ARRAY_SIZE(c->entries_keys); i++) { c->entries_keys[i] = terminal_slice; } } void grpc_chttp2_hpack_compressor_destroy(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c) { int i; for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_VALUES; i++) { if (c->entries_keys[i].refcount != &terminal_slice_refcount) { grpc_slice_unref_internal(exec_ctx, c->entries_keys[i]); } GRPC_MDELEM_UNREF(exec_ctx, c->entries_elems[i]); } gpr_free(c->table_elem_size); } void grpc_chttp2_hpack_compressor_set_max_usable_size( grpc_chttp2_hpack_compressor *c, uint32_t max_table_size) { c->max_usable_size = max_table_size; grpc_chttp2_hpack_compressor_set_max_table_size( c, GPR_MIN(c->max_table_size, max_table_size)); } static void rebuild_elems(grpc_chttp2_hpack_compressor *c, uint32_t new_cap) { uint16_t *table_elem_size = gpr_malloc(sizeof(*table_elem_size) * new_cap); uint32_t i; memset(table_elem_size, 0, sizeof(*table_elem_size) * new_cap); GPR_ASSERT(c->table_elems <= new_cap); for (i = 0; i < c->table_elems; i++) { uint32_t ofs = c->tail_remote_index + i + 1; table_elem_size[ofs % new_cap] = c->table_elem_size[ofs % c->cap_table_elems]; } c->cap_table_elems = new_cap; gpr_free(c->table_elem_size); c->table_elem_size = table_elem_size; } void grpc_chttp2_hpack_compressor_set_max_table_size( grpc_chttp2_hpack_compressor *c, uint32_t max_table_size) { max_table_size = GPR_MIN(max_table_size, c->max_usable_size); if (max_table_size == c->max_table_size) { return; } while (c->table_size > 0 && c->table_size > max_table_size) { evict_entry(c); } c->max_table_size = max_table_size; c->max_table_elems = elems_for_bytes(max_table_size); if (c->max_table_elems > c->cap_table_elems) { rebuild_elems(c, GPR_MAX(c->max_table_elems, 2 * c->cap_table_elems)); } else if (c->max_table_elems < c->cap_table_elems / 3) { uint32_t new_cap = GPR_MAX(c->max_table_elems, 16); if (new_cap != c->cap_table_elems) { rebuild_elems(c, new_cap); } } c->advertise_table_size_change = 1; if (grpc_http_trace) { gpr_log(GPR_DEBUG, "set max table size from encoder to %d", max_table_size); } } void grpc_chttp2_encode_header(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c, grpc_metadata_batch *metadata, const grpc_encode_header_options *options, grpc_slice_buffer *outbuf) { framer_state st; grpc_linked_mdelem *l; gpr_timespec deadline; GPR_ASSERT(options->stream_id != 0); st.seen_regular_header = 0; st.stream_id = options->stream_id; st.output = outbuf; st.is_first_frame = 1; st.stats = options->stats; st.max_frame_size = options->max_frame_size; st.use_true_binary_metadata = options->use_true_binary_metadata; /* Encode a metadata batch; store the returned values, representing a metadata element that needs to be unreffed back into the metadata slot. THIS MAY NOT BE THE SAME ELEMENT (if a decoder table slot got updated). After this loop, we'll do a batch unref of elements. */ begin_frame(&st); if (c->advertise_table_size_change != 0) { emit_advertise_table_size_change(c, &st); } grpc_metadata_batch_assert_ok(metadata); for (l = metadata->list.head; l; l = l->next) { hpack_enc(exec_ctx, c, l->md, &st); } deadline = metadata->deadline; if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) != 0) { deadline_enc(exec_ctx, c, deadline, &st); } finish_frame(&st, 1, options->is_eof); } grpc-1.3.2/src/core/ext/transport/chttp2/transport/hpack_encoder.h000066400000000000000000000111311310511640000252050ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_ENCODER_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_ENCODER_H #include #include #include #include "src/core/ext/transport/chttp2/transport/frame.h" #include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata_batch.h" #include "src/core/lib/transport/transport.h" #define GRPC_CHTTP2_HPACKC_NUM_FILTERS 256 #define GRPC_CHTTP2_HPACKC_NUM_VALUES 256 /* initial table size, per spec */ #define GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE 4096 /* maximum table size we'll actually use */ #define GRPC_CHTTP2_HPACKC_MAX_TABLE_SIZE (1024 * 1024) typedef struct { uint32_t filter_elems_sum; uint32_t max_table_size; uint32_t max_table_elems; uint32_t cap_table_elems; /** if non-zero, advertise to the decoder that we'll start using a table of this size */ uint8_t advertise_table_size_change; /** maximum number of bytes we'll use for the decode table (to guard against peers ooming us by setting decode table size high) */ uint32_t max_usable_size; /* one before the lowest usable table index */ uint32_t tail_remote_index; uint32_t table_size; uint32_t table_elems; /* filter tables for elems: this tables provides an approximate popularity count for particular hashes, and are used to determine whether a new literal should be added to the compression table or not. They track a single integer that counts how often a particular value has been seen. When that count reaches max (255), all values are halved. */ uint8_t filter_elems[GRPC_CHTTP2_HPACKC_NUM_FILTERS]; /* entry tables for keys & elems: these tables track values that have been seen and *may* be in the decompressor table */ grpc_slice entries_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES]; grpc_mdelem entries_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES]; uint32_t indices_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES]; uint32_t indices_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES]; uint16_t *table_elem_size; } grpc_chttp2_hpack_compressor; void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c); void grpc_chttp2_hpack_compressor_destroy(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c); void grpc_chttp2_hpack_compressor_set_max_table_size( grpc_chttp2_hpack_compressor *c, uint32_t max_table_size); void grpc_chttp2_hpack_compressor_set_max_usable_size( grpc_chttp2_hpack_compressor *c, uint32_t max_table_size); typedef struct { uint32_t stream_id; bool is_eof; bool use_true_binary_metadata; size_t max_frame_size; grpc_transport_one_way_stats *stats; } grpc_encode_header_options; void grpc_chttp2_encode_header(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c, grpc_metadata_batch *metadata, const grpc_encode_header_options *options, grpc_slice_buffer *outbuf); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_ENCODER_H */ grpc-1.3.2/src/core/ext/transport/chttp2/transport/hpack_parser.c000066400000000000000000002454421310511640000250730ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/transport/hpack_parser.h" #include "src/core/ext/transport/chttp2/transport/internal.h" #include #include #include #include #include #include #include #include #include "src/core/ext/transport/chttp2/transport/bin_encoder.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/support/string.h" #include "src/core/lib/transport/http2_errors.h" extern int grpc_http_trace; typedef enum { NOT_BINARY, BINARY_BEGIN, B64_BYTE0, B64_BYTE1, B64_BYTE2, B64_BYTE3 } binary_state; /* How parsing works: The parser object keeps track of a function pointer which represents the current parse state. Each time new bytes are presented, we call into the current state, which recursively parses until all bytes in the given chunk are exhausted. The parse state that terminates then saves its function pointer to be the current state so that it can resume when more bytes are available. It's expected that most optimizing compilers will turn this code into a set of indirect jumps, and so not waste stack space. */ /* forward declarations for parsing states */ static grpc_error *parse_begin(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_error(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end, grpc_error *error); static grpc_error *still_parse_error(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_illegal_op(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_string_prefix(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_key_string(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_value_string_with_indexed_key( grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_value_string_with_literal_key( grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_value0(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_value1(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_value2(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_value3(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_value4(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_value5up(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_indexed_field(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_indexed_field_x(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_lithdr_incidx(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_lithdr_incidx_x(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_lithdr_incidx_v(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_lithdr_notidx(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_lithdr_notidx_x(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_lithdr_notidx_v(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_lithdr_nvridx(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_lithdr_nvridx_x(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_lithdr_nvridx_v(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_max_tbl_size(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); static grpc_error *parse_max_tbl_size_x(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end); /* we translate the first byte of a hpack field into one of these decoding cases, then use a lookup table to jump directly to the appropriate parser. _X => the integer index is all ones, meaning we need to do varint decoding _V => the integer index is all zeros, meaning we need to decode an additional string value */ typedef enum { INDEXED_FIELD, INDEXED_FIELD_X, LITHDR_INCIDX, LITHDR_INCIDX_X, LITHDR_INCIDX_V, LITHDR_NOTIDX, LITHDR_NOTIDX_X, LITHDR_NOTIDX_V, LITHDR_NVRIDX, LITHDR_NVRIDX_X, LITHDR_NVRIDX_V, MAX_TBL_SIZE, MAX_TBL_SIZE_X, ILLEGAL } first_byte_type; /* jump table of parse state functions -- order must match first_byte_type above */ static const grpc_chttp2_hpack_parser_state first_byte_action[] = { parse_indexed_field, parse_indexed_field_x, parse_lithdr_incidx, parse_lithdr_incidx_x, parse_lithdr_incidx_v, parse_lithdr_notidx, parse_lithdr_notidx_x, parse_lithdr_notidx_v, parse_lithdr_nvridx, parse_lithdr_nvridx_x, parse_lithdr_nvridx_v, parse_max_tbl_size, parse_max_tbl_size_x, parse_illegal_op}; /* indexes the first byte to a parse state function - generated by gen_hpack_tables.c */ static const uint8_t first_byte_lut[256] = { LITHDR_NOTIDX_V, LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX, LITHDR_NOTIDX_X, LITHDR_NVRIDX_V, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX_X, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE_X, LITHDR_INCIDX_V, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX, LITHDR_INCIDX_X, ILLEGAL, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD_X, }; /* state table for huffman decoding: given a state, gives an index/16 into next_sub_tbl. Taking that index and adding the value of the nibble being considered returns the next state. generated by gen_hpack_tables.c */ static const uint8_t next_tbl[256] = { 0, 1, 2, 3, 4, 1, 2, 5, 6, 1, 7, 8, 1, 3, 3, 9, 10, 11, 1, 1, 1, 12, 1, 2, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 14, 1, 15, 16, 1, 17, 1, 15, 2, 7, 3, 18, 19, 1, 1, 1, 1, 20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 15, 2, 2, 7, 21, 1, 22, 1, 1, 1, 1, 1, 1, 1, 1, 15, 2, 2, 2, 2, 2, 2, 23, 24, 25, 1, 1, 1, 1, 2, 2, 2, 26, 3, 3, 27, 10, 28, 1, 1, 1, 1, 1, 1, 2, 3, 29, 10, 30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 31, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 32, 1, 1, 15, 33, 1, 34, 35, 9, 36, 1, 1, 1, 1, 1, 1, 1, 37, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 26, 9, 38, 1, 1, 1, 1, 1, 1, 1, 15, 2, 2, 2, 2, 26, 3, 3, 39, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 7, 3, 3, 3, 40, 2, 41, 1, 1, 1, 42, 43, 1, 1, 44, 1, 1, 1, 1, 15, 2, 2, 2, 2, 2, 2, 3, 3, 3, 45, 46, 1, 1, 2, 2, 2, 35, 3, 3, 18, 47, 2, }; /* next state, based upon current state and the current nibble: see above. generated by gen_hpack_tables.c */ static const int16_t next_sub_tbl[48 * 16] = { 1, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 2, 6, 10, 13, 14, 15, 16, 17, 2, 6, 10, 13, 14, 15, 16, 17, 3, 7, 11, 24, 3, 7, 11, 24, 3, 7, 11, 24, 3, 7, 11, 24, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 199, 200, 201, 202, 203, 4, 8, 4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 3, 7, 11, 24, 3, 7, 11, 24, 4, 8, 4, 8, 4, 8, 4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 132, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 19, 20, 21, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 0, 0, 0, 22, 23, 91, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 3, 7, 11, 24, 3, 7, 11, 24, 0, 0, 0, 0, 0, 41, 42, 43, 2, 6, 10, 13, 14, 15, 16, 17, 3, 7, 11, 24, 3, 7, 11, 24, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 0, 0, 44, 45, 2, 6, 10, 13, 14, 15, 16, 17, 46, 47, 48, 49, 50, 51, 52, 57, 4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 54, 55, 56, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 3, 7, 11, 24, 3, 7, 11, 24, 3, 7, 11, 24, 0, 0, 0, 0, 3, 7, 11, 24, 3, 7, 11, 24, 4, 8, 4, 8, 0, 0, 0, 92, 0, 0, 0, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 3, 7, 11, 24, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 2, 6, 10, 13, 14, 15, 16, 17, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 148, 149, 150, 151, 3, 7, 11, 24, 4, 8, 4, 8, 0, 0, 0, 0, 0, 0, 152, 153, 3, 7, 11, 24, 3, 7, 11, 24, 3, 7, 11, 24, 154, 155, 156, 164, 3, 7, 11, 24, 3, 7, 11, 24, 3, 7, 11, 24, 4, 8, 4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 158, 159, 160, 161, 162, 163, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 197, 198, 4, 8, 4, 8, 4, 8, 4, 8, 0, 0, 0, 0, 0, 0, 219, 220, 3, 7, 11, 24, 4, 8, 4, 8, 4, 8, 0, 0, 221, 222, 223, 224, 3, 7, 11, 24, 3, 7, 11, 24, 4, 8, 4, 8, 4, 8, 225, 228, 4, 8, 4, 8, 4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 226, 227, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, }; /* emission table: indexed like next_tbl, ultimately gives the byte to be emitted, or -1 for no byte, or 256 for end of stream generated by gen_hpack_tables.c */ static const uint16_t emit_tbl[256] = { 0, 1, 2, 3, 4, 5, 6, 7, 0, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 0, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 0, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 0, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 0, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 0, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, }; /* generated by gen_hpack_tables.c */ static const int16_t emit_sub_tbl[249 * 16] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 97, 97, 97, 97, 48, 48, 49, 49, 50, 50, 97, 97, 99, 99, 101, 101, 105, 105, 111, 111, 48, 49, 50, 97, 99, 101, 105, 111, 115, 116, -1, -1, -1, -1, -1, -1, 32, 32, 32, 32, 32, 32, 32, 32, 37, 37, 37, 37, 37, 37, 37, 37, 99, 99, 99, 99, 101, 101, 101, 101, 105, 105, 105, 105, 111, 111, 111, 111, 115, 115, 116, 116, 32, 37, 45, 46, 47, 51, 52, 53, 54, 55, 56, 57, 61, 61, 61, 61, 61, 61, 61, 61, 65, 65, 65, 65, 65, 65, 65, 65, 115, 115, 115, 115, 116, 116, 116, 116, 32, 32, 37, 37, 45, 45, 46, 46, 61, 65, 95, 98, 100, 102, 103, 104, 108, 109, 110, 112, 114, 117, -1, -1, 58, 58, 58, 58, 58, 58, 58, 58, 66, 66, 66, 66, 66, 66, 66, 66, 47, 47, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55, 56, 56, 57, 57, 61, 61, 65, 65, 95, 95, 98, 98, 100, 100, 102, 102, 103, 103, 104, 104, 108, 108, 109, 109, 110, 110, 112, 112, 114, 114, 117, 117, 58, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 89, 106, 107, 113, 118, 119, 120, 121, 122, -1, -1, -1, -1, 38, 38, 38, 38, 38, 38, 38, 38, 42, 42, 42, 42, 42, 42, 42, 42, 44, 44, 44, 44, 44, 44, 44, 44, 59, 59, 59, 59, 59, 59, 59, 59, 88, 88, 88, 88, 88, 88, 88, 88, 90, 90, 90, 90, 90, 90, 90, 90, 33, 33, 34, 34, 40, 40, 41, 41, 63, 63, 39, 43, 124, -1, -1, -1, 35, 35, 35, 35, 35, 35, 35, 35, 62, 62, 62, 62, 62, 62, 62, 62, 0, 0, 0, 0, 36, 36, 36, 36, 64, 64, 64, 64, 91, 91, 91, 91, 69, 69, 69, 69, 69, 69, 69, 69, 70, 70, 70, 70, 70, 70, 70, 70, 71, 71, 71, 71, 71, 71, 71, 71, 72, 72, 72, 72, 72, 72, 72, 72, 73, 73, 73, 73, 73, 73, 73, 73, 74, 74, 74, 74, 74, 74, 74, 74, 75, 75, 75, 75, 75, 75, 75, 75, 76, 76, 76, 76, 76, 76, 76, 76, 77, 77, 77, 77, 77, 77, 77, 77, 78, 78, 78, 78, 78, 78, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 80, 80, 80, 80, 80, 80, 80, 80, 81, 81, 81, 81, 81, 81, 81, 81, 82, 82, 82, 82, 82, 82, 82, 82, 83, 83, 83, 83, 83, 83, 83, 83, 84, 84, 84, 84, 84, 84, 84, 84, 85, 85, 85, 85, 85, 85, 85, 85, 86, 86, 86, 86, 86, 86, 86, 86, 87, 87, 87, 87, 87, 87, 87, 87, 89, 89, 89, 89, 89, 89, 89, 89, 106, 106, 106, 106, 106, 106, 106, 106, 107, 107, 107, 107, 107, 107, 107, 107, 113, 113, 113, 113, 113, 113, 113, 113, 118, 118, 118, 118, 118, 118, 118, 118, 119, 119, 119, 119, 119, 119, 119, 119, 120, 120, 120, 120, 120, 120, 120, 120, 121, 121, 121, 121, 121, 121, 121, 121, 122, 122, 122, 122, 122, 122, 122, 122, 38, 38, 38, 38, 42, 42, 42, 42, 44, 44, 44, 44, 59, 59, 59, 59, 88, 88, 88, 88, 90, 90, 90, 90, 33, 34, 40, 41, 63, -1, -1, -1, 39, 39, 39, 39, 39, 39, 39, 39, 43, 43, 43, 43, 43, 43, 43, 43, 124, 124, 124, 124, 124, 124, 124, 124, 35, 35, 35, 35, 62, 62, 62, 62, 0, 0, 36, 36, 64, 64, 91, 91, 93, 93, 126, 126, 94, 125, -1, -1, 60, 60, 60, 60, 60, 60, 60, 60, 96, 96, 96, 96, 96, 96, 96, 96, 123, 123, 123, 123, 123, 123, 123, 123, -1, -1, -1, -1, -1, -1, -1, -1, 92, 92, 92, 92, 92, 92, 92, 92, 195, 195, 195, 195, 195, 195, 195, 195, 208, 208, 208, 208, 208, 208, 208, 208, 128, 128, 128, 128, 130, 130, 130, 130, 131, 131, 131, 131, 162, 162, 162, 162, 184, 184, 184, 184, 194, 194, 194, 194, 224, 224, 224, 224, 226, 226, 226, 226, 153, 153, 161, 161, 167, 167, 172, 172, 176, 176, 177, 177, 179, 179, 209, 209, 216, 216, 217, 217, 227, 227, 229, 229, 230, 230, 129, 132, 133, 134, 136, 146, 154, 156, 160, 163, 164, 169, 170, 173, 178, 181, 185, 186, 187, 189, 190, 196, 198, 228, 232, 233, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 135, 135, 135, 135, 135, 135, 135, 135, 137, 137, 137, 137, 137, 137, 137, 137, 138, 138, 138, 138, 138, 138, 138, 138, 139, 139, 139, 139, 139, 139, 139, 139, 140, 140, 140, 140, 140, 140, 140, 140, 141, 141, 141, 141, 141, 141, 141, 141, 143, 143, 143, 143, 143, 143, 143, 143, 147, 147, 147, 147, 147, 147, 147, 147, 149, 149, 149, 149, 149, 149, 149, 149, 150, 150, 150, 150, 150, 150, 150, 150, 151, 151, 151, 151, 151, 151, 151, 151, 152, 152, 152, 152, 152, 152, 152, 152, 155, 155, 155, 155, 155, 155, 155, 155, 157, 157, 157, 157, 157, 157, 157, 157, 158, 158, 158, 158, 158, 158, 158, 158, 165, 165, 165, 165, 165, 165, 165, 165, 166, 166, 166, 166, 166, 166, 166, 166, 168, 168, 168, 168, 168, 168, 168, 168, 174, 174, 174, 174, 174, 174, 174, 174, 175, 175, 175, 175, 175, 175, 175, 175, 180, 180, 180, 180, 180, 180, 180, 180, 182, 182, 182, 182, 182, 182, 182, 182, 183, 183, 183, 183, 183, 183, 183, 183, 188, 188, 188, 188, 188, 188, 188, 188, 191, 191, 191, 191, 191, 191, 191, 191, 197, 197, 197, 197, 197, 197, 197, 197, 231, 231, 231, 231, 231, 231, 231, 231, 239, 239, 239, 239, 239, 239, 239, 239, 9, 9, 9, 9, 142, 142, 142, 142, 144, 144, 144, 144, 145, 145, 145, 145, 148, 148, 148, 148, 159, 159, 159, 159, 171, 171, 171, 171, 206, 206, 206, 206, 215, 215, 215, 215, 225, 225, 225, 225, 236, 236, 236, 236, 237, 237, 237, 237, 199, 199, 207, 207, 234, 234, 235, 235, 192, 193, 200, 201, 202, 205, 210, 213, 218, 219, 238, 240, 242, 243, 255, -1, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 211, 211, 211, 211, 211, 211, 211, 211, 212, 212, 212, 212, 212, 212, 212, 212, 214, 214, 214, 214, 214, 214, 214, 214, 221, 221, 221, 221, 221, 221, 221, 221, 222, 222, 222, 222, 222, 222, 222, 222, 223, 223, 223, 223, 223, 223, 223, 223, 241, 241, 241, 241, 241, 241, 241, 241, 244, 244, 244, 244, 244, 244, 244, 244, 245, 245, 245, 245, 245, 245, 245, 245, 246, 246, 246, 246, 246, 246, 246, 246, 247, 247, 247, 247, 247, 247, 247, 247, 248, 248, 248, 248, 248, 248, 248, 248, 250, 250, 250, 250, 250, 250, 250, 250, 251, 251, 251, 251, 251, 251, 251, 251, 252, 252, 252, 252, 252, 252, 252, 252, 253, 253, 253, 253, 253, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 11, 11, 11, 11, 12, 12, 12, 12, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 23, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 127, 127, 127, 127, 220, 220, 220, 220, 249, 249, 249, 249, 10, 13, 22, 256, 93, 93, 93, 93, 126, 126, 126, 126, 94, 94, 125, 125, 60, 96, 123, -1, 92, 195, 208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 128, 128, 128, 128, 128, 128, 128, 128, 130, 130, 130, 130, 130, 130, 130, 130, 131, 131, 131, 131, 131, 131, 131, 131, 162, 162, 162, 162, 162, 162, 162, 162, 184, 184, 184, 184, 184, 184, 184, 184, 194, 194, 194, 194, 194, 194, 194, 194, 224, 224, 224, 224, 224, 224, 224, 224, 226, 226, 226, 226, 226, 226, 226, 226, 153, 153, 153, 153, 161, 161, 161, 161, 167, 167, 167, 167, 172, 172, 172, 172, 176, 176, 176, 176, 177, 177, 177, 177, 179, 179, 179, 179, 209, 209, 209, 209, 216, 216, 216, 216, 217, 217, 217, 217, 227, 227, 227, 227, 229, 229, 229, 229, 230, 230, 230, 230, 129, 129, 132, 132, 133, 133, 134, 134, 136, 136, 146, 146, 154, 154, 156, 156, 160, 160, 163, 163, 164, 164, 169, 169, 170, 170, 173, 173, 178, 178, 181, 181, 185, 185, 186, 186, 187, 187, 189, 189, 190, 190, 196, 196, 198, 198, 228, 228, 232, 232, 233, 233, 1, 135, 137, 138, 139, 140, 141, 143, 147, 149, 150, 151, 152, 155, 157, 158, 165, 166, 168, 174, 175, 180, 182, 183, 188, 191, 197, 231, 239, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, 9, 9, 9, 9, 9, 9, 9, 142, 142, 142, 142, 142, 142, 142, 142, 144, 144, 144, 144, 144, 144, 144, 144, 145, 145, 145, 145, 145, 145, 145, 145, 148, 148, 148, 148, 148, 148, 148, 148, 159, 159, 159, 159, 159, 159, 159, 159, 171, 171, 171, 171, 171, 171, 171, 171, 206, 206, 206, 206, 206, 206, 206, 206, 215, 215, 215, 215, 215, 215, 215, 215, 225, 225, 225, 225, 225, 225, 225, 225, 236, 236, 236, 236, 236, 236, 236, 236, 237, 237, 237, 237, 237, 237, 237, 237, 199, 199, 199, 199, 207, 207, 207, 207, 234, 234, 234, 234, 235, 235, 235, 235, 192, 192, 193, 193, 200, 200, 201, 201, 202, 202, 205, 205, 210, 210, 213, 213, 218, 218, 219, 219, 238, 238, 240, 240, 242, 242, 243, 243, 255, 255, 203, 204, 211, 212, 214, 221, 222, 223, 241, 244, 245, 246, 247, 248, 250, 251, 252, 253, 254, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 127, 127, 127, 127, 127, 127, 127, 127, 220, 220, 220, 220, 220, 220, 220, 220, 249, 249, 249, 249, 249, 249, 249, 249, 10, 10, 13, 13, 22, 22, 256, 256, 67, 67, 67, 67, 67, 67, 67, 67, 68, 68, 68, 68, 68, 68, 68, 68, 95, 95, 95, 95, 95, 95, 95, 95, 98, 98, 98, 98, 98, 98, 98, 98, 100, 100, 100, 100, 100, 100, 100, 100, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103, 103, 103, 103, 103, 104, 104, 104, 104, 104, 104, 104, 104, 108, 108, 108, 108, 108, 108, 108, 108, 109, 109, 109, 109, 109, 109, 109, 109, 110, 110, 110, 110, 110, 110, 110, 110, 112, 112, 112, 112, 112, 112, 112, 112, 114, 114, 114, 114, 114, 114, 114, 114, 117, 117, 117, 117, 117, 117, 117, 117, 58, 58, 58, 58, 66, 66, 66, 66, 67, 67, 67, 67, 68, 68, 68, 68, 69, 69, 69, 69, 70, 70, 70, 70, 71, 71, 71, 71, 72, 72, 72, 72, 73, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75, 75, 76, 76, 76, 76, 77, 77, 77, 77, 78, 78, 78, 78, 79, 79, 79, 79, 80, 80, 80, 80, 81, 81, 81, 81, 82, 82, 82, 82, 83, 83, 83, 83, 84, 84, 84, 84, 85, 85, 85, 85, 86, 86, 86, 86, 87, 87, 87, 87, 89, 89, 89, 89, 106, 106, 106, 106, 107, 107, 107, 107, 113, 113, 113, 113, 118, 118, 118, 118, 119, 119, 119, 119, 120, 120, 120, 120, 121, 121, 121, 121, 122, 122, 122, 122, 38, 38, 42, 42, 44, 44, 59, 59, 88, 88, 90, 90, -1, -1, -1, -1, 33, 33, 33, 33, 33, 33, 33, 33, 34, 34, 34, 34, 34, 34, 34, 34, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 63, 63, 63, 63, 63, 63, 63, 63, 39, 39, 39, 39, 43, 43, 43, 43, 124, 124, 124, 124, 35, 35, 62, 62, 0, 36, 64, 91, 93, 126, -1, -1, 94, 94, 94, 94, 94, 94, 94, 94, 125, 125, 125, 125, 125, 125, 125, 125, 60, 60, 60, 60, 96, 96, 96, 96, 123, 123, 123, 123, -1, -1, -1, -1, 92, 92, 92, 92, 195, 195, 195, 195, 208, 208, 208, 208, 128, 128, 130, 130, 131, 131, 162, 162, 184, 184, 194, 194, 224, 224, 226, 226, 153, 161, 167, 172, 176, 177, 179, 209, 216, 217, 227, 229, 230, -1, -1, -1, -1, -1, -1, -1, 129, 129, 129, 129, 129, 129, 129, 129, 132, 132, 132, 132, 132, 132, 132, 132, 133, 133, 133, 133, 133, 133, 133, 133, 134, 134, 134, 134, 134, 134, 134, 134, 136, 136, 136, 136, 136, 136, 136, 136, 146, 146, 146, 146, 146, 146, 146, 146, 154, 154, 154, 154, 154, 154, 154, 154, 156, 156, 156, 156, 156, 156, 156, 156, 160, 160, 160, 160, 160, 160, 160, 160, 163, 163, 163, 163, 163, 163, 163, 163, 164, 164, 164, 164, 164, 164, 164, 164, 169, 169, 169, 169, 169, 169, 169, 169, 170, 170, 170, 170, 170, 170, 170, 170, 173, 173, 173, 173, 173, 173, 173, 173, 178, 178, 178, 178, 178, 178, 178, 178, 181, 181, 181, 181, 181, 181, 181, 181, 185, 185, 185, 185, 185, 185, 185, 185, 186, 186, 186, 186, 186, 186, 186, 186, 187, 187, 187, 187, 187, 187, 187, 187, 189, 189, 189, 189, 189, 189, 189, 189, 190, 190, 190, 190, 190, 190, 190, 190, 196, 196, 196, 196, 196, 196, 196, 196, 198, 198, 198, 198, 198, 198, 198, 198, 228, 228, 228, 228, 228, 228, 228, 228, 232, 232, 232, 232, 232, 232, 232, 232, 233, 233, 233, 233, 233, 233, 233, 233, 1, 1, 1, 1, 135, 135, 135, 135, 137, 137, 137, 137, 138, 138, 138, 138, 139, 139, 139, 139, 140, 140, 140, 140, 141, 141, 141, 141, 143, 143, 143, 143, 147, 147, 147, 147, 149, 149, 149, 149, 150, 150, 150, 150, 151, 151, 151, 151, 152, 152, 152, 152, 155, 155, 155, 155, 157, 157, 157, 157, 158, 158, 158, 158, 165, 165, 165, 165, 166, 166, 166, 166, 168, 168, 168, 168, 174, 174, 174, 174, 175, 175, 175, 175, 180, 180, 180, 180, 182, 182, 182, 182, 183, 183, 183, 183, 188, 188, 188, 188, 191, 191, 191, 191, 197, 197, 197, 197, 231, 231, 231, 231, 239, 239, 239, 239, 9, 9, 142, 142, 144, 144, 145, 145, 148, 148, 159, 159, 171, 171, 206, 206, 215, 215, 225, 225, 236, 236, 237, 237, 199, 207, 234, 235, 192, 192, 192, 192, 192, 192, 192, 192, 193, 193, 193, 193, 193, 193, 193, 193, 200, 200, 200, 200, 200, 200, 200, 200, 201, 201, 201, 201, 201, 201, 201, 201, 202, 202, 202, 202, 202, 202, 202, 202, 205, 205, 205, 205, 205, 205, 205, 205, 210, 210, 210, 210, 210, 210, 210, 210, 213, 213, 213, 213, 213, 213, 213, 213, 218, 218, 218, 218, 218, 218, 218, 218, 219, 219, 219, 219, 219, 219, 219, 219, 238, 238, 238, 238, 238, 238, 238, 238, 240, 240, 240, 240, 240, 240, 240, 240, 242, 242, 242, 242, 242, 242, 242, 242, 243, 243, 243, 243, 243, 243, 243, 243, 255, 255, 255, 255, 255, 255, 255, 255, 203, 203, 203, 203, 204, 204, 204, 204, 211, 211, 211, 211, 212, 212, 212, 212, 214, 214, 214, 214, 221, 221, 221, 221, 222, 222, 222, 222, 223, 223, 223, 223, 241, 241, 241, 241, 244, 244, 244, 244, 245, 245, 245, 245, 246, 246, 246, 246, 247, 247, 247, 247, 248, 248, 248, 248, 250, 250, 250, 250, 251, 251, 251, 251, 252, 252, 252, 252, 253, 253, 253, 253, 254, 254, 254, 254, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 11, 11, 12, 12, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 127, 127, 220, 220, 249, 249, -1, -1, 10, 10, 10, 10, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, 22, 22, 22, 22, 22, 22, 22, 22, 256, 256, 256, 256, 256, 256, 256, 256, 45, 45, 45, 45, 45, 45, 45, 45, 46, 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 50, 50, 50, 50, 50, 50, 50, 50, 97, 97, 97, 97, 97, 97, 97, 97, 99, 99, 99, 99, 99, 99, 99, 99, 101, 101, 101, 101, 101, 101, 101, 101, 105, 105, 105, 105, 105, 105, 105, 105, 111, 111, 111, 111, 111, 111, 111, 111, 115, 115, 115, 115, 115, 115, 115, 115, 116, 116, 116, 116, 116, 116, 116, 116, 32, 32, 32, 32, 37, 37, 37, 37, 45, 45, 45, 45, 46, 46, 46, 46, 47, 47, 47, 47, 51, 51, 51, 51, 52, 52, 52, 52, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 56, 56, 56, 56, 57, 57, 57, 57, 61, 61, 61, 61, 65, 65, 65, 65, 95, 95, 95, 95, 98, 98, 98, 98, 100, 100, 100, 100, 102, 102, 102, 102, 103, 103, 103, 103, 104, 104, 104, 104, 108, 108, 108, 108, 109, 109, 109, 109, 110, 110, 110, 110, 112, 112, 112, 112, 114, 114, 114, 114, 117, 117, 117, 117, 58, 58, 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71, 72, 72, 73, 73, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79, 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 87, 87, 89, 89, 106, 106, 107, 107, 113, 113, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 38, 42, 44, 59, 88, 90, -1, -1, 33, 33, 33, 33, 34, 34, 34, 34, 40, 40, 40, 40, 41, 41, 41, 41, 63, 63, 63, 63, 39, 39, 43, 43, 124, 124, 35, 62, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 36, 36, 36, 36, 36, 36, 36, 36, 64, 64, 64, 64, 64, 64, 64, 64, 91, 91, 91, 91, 91, 91, 91, 91, 93, 93, 93, 93, 93, 93, 93, 93, 126, 126, 126, 126, 126, 126, 126, 126, 94, 94, 94, 94, 125, 125, 125, 125, 60, 60, 96, 96, 123, 123, -1, -1, 92, 92, 195, 195, 208, 208, 128, 130, 131, 162, 184, 194, 224, 226, -1, -1, 153, 153, 153, 153, 153, 153, 153, 153, 161, 161, 161, 161, 161, 161, 161, 161, 167, 167, 167, 167, 167, 167, 167, 167, 172, 172, 172, 172, 172, 172, 172, 172, 176, 176, 176, 176, 176, 176, 176, 176, 177, 177, 177, 177, 177, 177, 177, 177, 179, 179, 179, 179, 179, 179, 179, 179, 209, 209, 209, 209, 209, 209, 209, 209, 216, 216, 216, 216, 216, 216, 216, 216, 217, 217, 217, 217, 217, 217, 217, 217, 227, 227, 227, 227, 227, 227, 227, 227, 229, 229, 229, 229, 229, 229, 229, 229, 230, 230, 230, 230, 230, 230, 230, 230, 129, 129, 129, 129, 132, 132, 132, 132, 133, 133, 133, 133, 134, 134, 134, 134, 136, 136, 136, 136, 146, 146, 146, 146, 154, 154, 154, 154, 156, 156, 156, 156, 160, 160, 160, 160, 163, 163, 163, 163, 164, 164, 164, 164, 169, 169, 169, 169, 170, 170, 170, 170, 173, 173, 173, 173, 178, 178, 178, 178, 181, 181, 181, 181, 185, 185, 185, 185, 186, 186, 186, 186, 187, 187, 187, 187, 189, 189, 189, 189, 190, 190, 190, 190, 196, 196, 196, 196, 198, 198, 198, 198, 228, 228, 228, 228, 232, 232, 232, 232, 233, 233, 233, 233, 1, 1, 135, 135, 137, 137, 138, 138, 139, 139, 140, 140, 141, 141, 143, 143, 147, 147, 149, 149, 150, 150, 151, 151, 152, 152, 155, 155, 157, 157, 158, 158, 165, 165, 166, 166, 168, 168, 174, 174, 175, 175, 180, 180, 182, 182, 183, 183, 188, 188, 191, 191, 197, 197, 231, 231, 239, 239, 9, 142, 144, 145, 148, 159, 171, 206, 215, 225, 236, 237, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 199, 199, 199, 199, 199, 199, 199, 199, 207, 207, 207, 207, 207, 207, 207, 207, 234, 234, 234, 234, 234, 234, 234, 234, 235, 235, 235, 235, 235, 235, 235, 235, 192, 192, 192, 192, 193, 193, 193, 193, 200, 200, 200, 200, 201, 201, 201, 201, 202, 202, 202, 202, 205, 205, 205, 205, 210, 210, 210, 210, 213, 213, 213, 213, 218, 218, 218, 218, 219, 219, 219, 219, 238, 238, 238, 238, 240, 240, 240, 240, 242, 242, 242, 242, 243, 243, 243, 243, 255, 255, 255, 255, 203, 203, 204, 204, 211, 211, 212, 212, 214, 214, 221, 221, 222, 222, 223, 223, 241, 241, 244, 244, 245, 245, 246, 246, 247, 247, 248, 248, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 127, 220, 249, -1, 10, 10, 10, 10, 13, 13, 13, 13, 22, 22, 22, 22, 256, 256, 256, 256, }; static const uint8_t inverse_base64[256] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 64, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, }; /* emission helpers */ static grpc_error *on_hdr(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, grpc_mdelem md, int add_to_table) { if (grpc_http_trace && !GRPC_MDELEM_IS_INTERNED(md)) { char *k = grpc_slice_to_c_string(GRPC_MDKEY(md)); char *v = grpc_slice_to_c_string(GRPC_MDVALUE(md)); gpr_log( GPR_DEBUG, "Decode: '%s: %s', elem_interned=%d [%d], k_interned=%d, v_interned=%d", k, v, GRPC_MDELEM_IS_INTERNED(md), GRPC_MDELEM_STORAGE(md), grpc_slice_is_interned(GRPC_MDKEY(md)), grpc_slice_is_interned(GRPC_MDVALUE(md))); gpr_free(k); gpr_free(v); } if (add_to_table) { GPR_ASSERT(GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_INTERNED || GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_STATIC); grpc_error *err = grpc_chttp2_hptbl_add(exec_ctx, &p->table, md); if (err != GRPC_ERROR_NONE) return err; } if (p->on_header == NULL) { GRPC_MDELEM_UNREF(exec_ctx, md); return GRPC_ERROR_CREATE_FROM_STATIC_STRING("on_header callback not set"); } p->on_header(exec_ctx, p->on_header_user_data, md); return GRPC_ERROR_NONE; } static grpc_slice take_string(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, grpc_chttp2_hpack_parser_string *str, bool intern) { grpc_slice s; if (!str->copied) { if (intern) { s = grpc_slice_intern(str->data.referenced); grpc_slice_unref_internal(exec_ctx, str->data.referenced); } else { s = str->data.referenced; } str->copied = true; str->data.referenced = grpc_empty_slice(); } else if (intern) { s = grpc_slice_intern(grpc_slice_from_static_buffer( str->data.copied.str, str->data.copied.length)); } else { s = grpc_slice_from_copied_buffer(str->data.copied.str, str->data.copied.length); } str->data.copied.length = 0; return s; } /* jump to the next state */ static grpc_error *parse_next(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { p->state = *p->next_state++; return p->state(exec_ctx, p, cur, end); } /* begin parsing a header: all functionality is encoded into lookup tables above */ static grpc_error *parse_begin(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { if (cur == end) { p->state = parse_begin; return GRPC_ERROR_NONE; } return first_byte_action[first_byte_lut[*cur]](exec_ctx, p, cur, end); } /* stream dependency and prioritization data: we just skip it */ static grpc_error *parse_stream_weight(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { if (cur == end) { p->state = parse_stream_weight; return GRPC_ERROR_NONE; } return p->after_prioritization(exec_ctx, p, cur + 1, end); } static grpc_error *parse_stream_dep3(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { if (cur == end) { p->state = parse_stream_dep3; return GRPC_ERROR_NONE; } return parse_stream_weight(exec_ctx, p, cur + 1, end); } static grpc_error *parse_stream_dep2(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { if (cur == end) { p->state = parse_stream_dep2; return GRPC_ERROR_NONE; } return parse_stream_dep3(exec_ctx, p, cur + 1, end); } static grpc_error *parse_stream_dep1(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { if (cur == end) { p->state = parse_stream_dep1; return GRPC_ERROR_NONE; } return parse_stream_dep2(exec_ctx, p, cur + 1, end); } static grpc_error *parse_stream_dep0(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { if (cur == end) { p->state = parse_stream_dep0; return GRPC_ERROR_NONE; } return parse_stream_dep1(exec_ctx, p, cur + 1, end); } /* emit an indexed field; for now just logs it to console; jumps to begin the next field on completion */ static grpc_error *finish_indexed_field(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index); if (GRPC_MDISNULL(md)) { return grpc_error_set_int( grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Invalid HPACK index received"), GRPC_ERROR_INT_INDEX, (intptr_t)p->index), GRPC_ERROR_INT_SIZE, (intptr_t)p->table.num_ents); } GRPC_MDELEM_REF(md); grpc_error *err = on_hdr(exec_ctx, p, md, 0); if (err != GRPC_ERROR_NONE) return err; return parse_begin(exec_ctx, p, cur, end); } /* parse an indexed field with index < 127 */ static grpc_error *parse_indexed_field(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { p->dynamic_table_update_allowed = 0; p->index = (*cur) & 0x7f; return finish_indexed_field(exec_ctx, p, cur + 1, end); } /* parse an indexed field with index >= 127 */ static grpc_error *parse_indexed_field_x(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { static const grpc_chttp2_hpack_parser_state and_then[] = { finish_indexed_field}; p->dynamic_table_update_allowed = 0; p->next_state = and_then; p->index = 0x7f; p->parsing.value = &p->index; return parse_value0(exec_ctx, p, cur + 1, end); } /* finish a literal header with incremental indexing: just log, and jump to ' begin */ static grpc_error *finish_lithdr_incidx(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index); GPR_ASSERT(!GRPC_MDISNULL(md)); /* handled in string parsing */ grpc_error *err = on_hdr( exec_ctx, p, grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(md)), take_string(exec_ctx, p, &p->value, true)), 1); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); return parse_begin(exec_ctx, p, cur, end); } /* finish a literal header with incremental indexing with no index */ static grpc_error *finish_lithdr_incidx_v(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { grpc_error *err = on_hdr( exec_ctx, p, grpc_mdelem_from_slices(exec_ctx, take_string(exec_ctx, p, &p->key, true), take_string(exec_ctx, p, &p->value, true)), 1); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); return parse_begin(exec_ctx, p, cur, end); } /* parse a literal header with incremental indexing; index < 63 */ static grpc_error *parse_lithdr_incidx(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { static const grpc_chttp2_hpack_parser_state and_then[] = { parse_value_string_with_indexed_key, finish_lithdr_incidx}; p->dynamic_table_update_allowed = 0; p->next_state = and_then; p->index = (*cur) & 0x3f; return parse_string_prefix(exec_ctx, p, cur + 1, end); } /* parse a literal header with incremental indexing; index >= 63 */ static grpc_error *parse_lithdr_incidx_x(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { static const grpc_chttp2_hpack_parser_state and_then[] = { parse_string_prefix, parse_value_string_with_indexed_key, finish_lithdr_incidx}; p->dynamic_table_update_allowed = 0; p->next_state = and_then; p->index = 0x3f; p->parsing.value = &p->index; return parse_value0(exec_ctx, p, cur + 1, end); } /* parse a literal header with incremental indexing; index = 0 */ static grpc_error *parse_lithdr_incidx_v(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { static const grpc_chttp2_hpack_parser_state and_then[] = { parse_key_string, parse_string_prefix, parse_value_string_with_literal_key, finish_lithdr_incidx_v}; p->dynamic_table_update_allowed = 0; p->next_state = and_then; return parse_string_prefix(exec_ctx, p, cur + 1, end); } /* finish a literal header without incremental indexing */ static grpc_error *finish_lithdr_notidx(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index); GPR_ASSERT(!GRPC_MDISNULL(md)); /* handled in string parsing */ grpc_error *err = on_hdr( exec_ctx, p, grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(md)), take_string(exec_ctx, p, &p->value, false)), 0); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); return parse_begin(exec_ctx, p, cur, end); } /* finish a literal header without incremental indexing with index = 0 */ static grpc_error *finish_lithdr_notidx_v(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { grpc_error *err = on_hdr( exec_ctx, p, grpc_mdelem_from_slices(exec_ctx, take_string(exec_ctx, p, &p->key, true), take_string(exec_ctx, p, &p->value, false)), 0); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); return parse_begin(exec_ctx, p, cur, end); } /* parse a literal header without incremental indexing; index < 15 */ static grpc_error *parse_lithdr_notidx(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { static const grpc_chttp2_hpack_parser_state and_then[] = { parse_value_string_with_indexed_key, finish_lithdr_notidx}; p->dynamic_table_update_allowed = 0; p->next_state = and_then; p->index = (*cur) & 0xf; return parse_string_prefix(exec_ctx, p, cur + 1, end); } /* parse a literal header without incremental indexing; index >= 15 */ static grpc_error *parse_lithdr_notidx_x(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { static const grpc_chttp2_hpack_parser_state and_then[] = { parse_string_prefix, parse_value_string_with_indexed_key, finish_lithdr_notidx}; p->dynamic_table_update_allowed = 0; p->next_state = and_then; p->index = 0xf; p->parsing.value = &p->index; return parse_value0(exec_ctx, p, cur + 1, end); } /* parse a literal header without incremental indexing; index == 0 */ static grpc_error *parse_lithdr_notidx_v(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { static const grpc_chttp2_hpack_parser_state and_then[] = { parse_key_string, parse_string_prefix, parse_value_string_with_literal_key, finish_lithdr_notidx_v}; p->dynamic_table_update_allowed = 0; p->next_state = and_then; return parse_string_prefix(exec_ctx, p, cur + 1, end); } /* finish a literal header that is never indexed */ static grpc_error *finish_lithdr_nvridx(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index); GPR_ASSERT(!GRPC_MDISNULL(md)); /* handled in string parsing */ grpc_error *err = on_hdr( exec_ctx, p, grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(md)), take_string(exec_ctx, p, &p->value, false)), 0); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); return parse_begin(exec_ctx, p, cur, end); } /* finish a literal header that is never indexed with an extra value */ static grpc_error *finish_lithdr_nvridx_v(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { grpc_error *err = on_hdr( exec_ctx, p, grpc_mdelem_from_slices(exec_ctx, take_string(exec_ctx, p, &p->key, true), take_string(exec_ctx, p, &p->value, false)), 0); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); return parse_begin(exec_ctx, p, cur, end); } /* parse a literal header that is never indexed; index < 15 */ static grpc_error *parse_lithdr_nvridx(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { static const grpc_chttp2_hpack_parser_state and_then[] = { parse_value_string_with_indexed_key, finish_lithdr_nvridx}; p->dynamic_table_update_allowed = 0; p->next_state = and_then; p->index = (*cur) & 0xf; return parse_string_prefix(exec_ctx, p, cur + 1, end); } /* parse a literal header that is never indexed; index >= 15 */ static grpc_error *parse_lithdr_nvridx_x(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { static const grpc_chttp2_hpack_parser_state and_then[] = { parse_string_prefix, parse_value_string_with_indexed_key, finish_lithdr_nvridx}; p->dynamic_table_update_allowed = 0; p->next_state = and_then; p->index = 0xf; p->parsing.value = &p->index; return parse_value0(exec_ctx, p, cur + 1, end); } /* parse a literal header that is never indexed; index == 0 */ static grpc_error *parse_lithdr_nvridx_v(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { static const grpc_chttp2_hpack_parser_state and_then[] = { parse_key_string, parse_string_prefix, parse_value_string_with_literal_key, finish_lithdr_nvridx_v}; p->dynamic_table_update_allowed = 0; p->next_state = and_then; return parse_string_prefix(exec_ctx, p, cur + 1, end); } /* finish parsing a max table size change */ static grpc_error *finish_max_tbl_size(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { if (grpc_http_trace) { gpr_log(GPR_INFO, "MAX TABLE SIZE: %d", p->index); } grpc_error *err = grpc_chttp2_hptbl_set_current_table_size(exec_ctx, &p->table, p->index); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); return parse_begin(exec_ctx, p, cur, end); } /* parse a max table size change, max size < 15 */ static grpc_error *parse_max_tbl_size(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { if (p->dynamic_table_update_allowed == 0) { return parse_error( exec_ctx, p, cur, end, GRPC_ERROR_CREATE_FROM_STATIC_STRING( "More than two max table size changes in a single frame")); } p->dynamic_table_update_allowed--; p->index = (*cur) & 0x1f; return finish_max_tbl_size(exec_ctx, p, cur + 1, end); } /* parse a max table size change, max size >= 15 */ static grpc_error *parse_max_tbl_size_x(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { static const grpc_chttp2_hpack_parser_state and_then[] = { finish_max_tbl_size}; if (p->dynamic_table_update_allowed == 0) { return parse_error( exec_ctx, p, cur, end, GRPC_ERROR_CREATE_FROM_STATIC_STRING( "More than two max table size changes in a single frame")); } p->dynamic_table_update_allowed--; p->next_state = and_then; p->index = 0x1f; p->parsing.value = &p->index; return parse_value0(exec_ctx, p, cur + 1, end); } /* a parse error: jam the parse state into parse_error, and return error */ static grpc_error *parse_error(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end, grpc_error *err) { GPR_ASSERT(err != GRPC_ERROR_NONE); if (p->last_error == GRPC_ERROR_NONE) { p->last_error = GRPC_ERROR_REF(err); } p->state = still_parse_error; return err; } static grpc_error *still_parse_error(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { return GRPC_ERROR_REF(p->last_error); } static grpc_error *parse_illegal_op(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { GPR_ASSERT(cur != end); char *msg; gpr_asprintf(&msg, "Illegal hpack op code %d", *cur); grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return parse_error(exec_ctx, p, cur, end, err); } /* parse the 1st byte of a varint into p->parsing.value no overflow is possible */ static grpc_error *parse_value0(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { if (cur == end) { p->state = parse_value0; return GRPC_ERROR_NONE; } *p->parsing.value += (*cur) & 0x7f; if ((*cur) & 0x80) { return parse_value1(exec_ctx, p, cur + 1, end); } else { return parse_next(exec_ctx, p, cur + 1, end); } } /* parse the 2nd byte of a varint into p->parsing.value no overflow is possible */ static grpc_error *parse_value1(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { if (cur == end) { p->state = parse_value1; return GRPC_ERROR_NONE; } *p->parsing.value += (((uint32_t)*cur) & 0x7f) << 7; if ((*cur) & 0x80) { return parse_value2(exec_ctx, p, cur + 1, end); } else { return parse_next(exec_ctx, p, cur + 1, end); } } /* parse the 3rd byte of a varint into p->parsing.value no overflow is possible */ static grpc_error *parse_value2(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { if (cur == end) { p->state = parse_value2; return GRPC_ERROR_NONE; } *p->parsing.value += (((uint32_t)*cur) & 0x7f) << 14; if ((*cur) & 0x80) { return parse_value3(exec_ctx, p, cur + 1, end); } else { return parse_next(exec_ctx, p, cur + 1, end); } } /* parse the 4th byte of a varint into p->parsing.value no overflow is possible */ static grpc_error *parse_value3(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { if (cur == end) { p->state = parse_value3; return GRPC_ERROR_NONE; } *p->parsing.value += (((uint32_t)*cur) & 0x7f) << 21; if ((*cur) & 0x80) { return parse_value4(exec_ctx, p, cur + 1, end); } else { return parse_next(exec_ctx, p, cur + 1, end); } } /* parse the 5th byte of a varint into p->parsing.value depending on the byte, we may overflow, and care must be taken */ static grpc_error *parse_value4(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { uint8_t c; uint32_t cur_value; uint32_t add_value; char *msg; if (cur == end) { p->state = parse_value4; return GRPC_ERROR_NONE; } c = (*cur) & 0x7f; if (c > 0xf) { goto error; } cur_value = *p->parsing.value; add_value = ((uint32_t)c) << 28; if (add_value > 0xffffffffu - cur_value) { goto error; } *p->parsing.value = cur_value + add_value; if ((*cur) & 0x80) { return parse_value5up(exec_ctx, p, cur + 1, end); } else { return parse_next(exec_ctx, p, cur + 1, end); } error: gpr_asprintf(&msg, "integer overflow in hpack integer decoding: have 0x%08x, " "got byte 0x%02x on byte 5", *p->parsing.value, *cur); grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return parse_error(exec_ctx, p, cur, end, err); } /* parse any trailing bytes in a varint: it's possible to append an arbitrary number of 0x80's and not affect the value - a zero will terminate - and anything else will overflow */ static grpc_error *parse_value5up(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { while (cur != end && *cur == 0x80) { ++cur; } if (cur == end) { p->state = parse_value5up; return GRPC_ERROR_NONE; } if (*cur == 0) { return parse_next(exec_ctx, p, cur + 1, end); } char *msg; gpr_asprintf(&msg, "integer overflow in hpack integer decoding: have 0x%08x, " "got byte 0x%02x sometime after byte 5", *p->parsing.value, *cur); grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return parse_error(exec_ctx, p, cur, end, err); } /* parse a string prefix */ static grpc_error *parse_string_prefix(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { if (cur == end) { p->state = parse_string_prefix; return GRPC_ERROR_NONE; } p->strlen = (*cur) & 0x7f; p->huff = (*cur) >> 7; if (p->strlen == 0x7f) { p->parsing.value = &p->strlen; return parse_value0(exec_ctx, p, cur + 1, end); } else { return parse_next(exec_ctx, p, cur + 1, end); } } /* append some bytes to a string */ static void append_bytes(grpc_chttp2_hpack_parser_string *str, const uint8_t *data, size_t length) { if (length == 0) return; if (length + str->data.copied.length > str->data.copied.capacity) { GPR_ASSERT(str->data.copied.length + length <= UINT32_MAX); str->data.copied.capacity = (uint32_t)(str->data.copied.length + length); str->data.copied.str = gpr_realloc(str->data.copied.str, str->data.copied.capacity); } memcpy(str->data.copied.str + str->data.copied.length, data, length); GPR_ASSERT(length <= UINT32_MAX - str->data.copied.length); str->data.copied.length += (uint32_t)length; } static grpc_error *append_string(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { grpc_chttp2_hpack_parser_string *str = p->parsing.str; uint32_t bits; uint8_t decoded[3]; switch ((binary_state)p->binary) { case NOT_BINARY: append_bytes(str, cur, (size_t)(end - cur)); return GRPC_ERROR_NONE; case BINARY_BEGIN: if (cur == end) { p->binary = BINARY_BEGIN; return GRPC_ERROR_NONE; } if (*cur == 0) { /* 'true-binary' case */ ++cur; p->binary = NOT_BINARY; append_bytes(str, cur, (size_t)(end - cur)); return GRPC_ERROR_NONE; } /* fallthrough */ b64_byte0: case B64_BYTE0: if (cur == end) { p->binary = B64_BYTE0; return GRPC_ERROR_NONE; } bits = inverse_base64[*cur]; ++cur; if (bits == 255) return parse_error( exec_ctx, p, cur, end, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Illegal base64 character")); else if (bits == 64) goto b64_byte0; p->base64_buffer = bits << 18; /* fallthrough */ b64_byte1: case B64_BYTE1: if (cur == end) { p->binary = B64_BYTE1; return GRPC_ERROR_NONE; } bits = inverse_base64[*cur]; ++cur; if (bits == 255) return parse_error( exec_ctx, p, cur, end, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Illegal base64 character")); else if (bits == 64) goto b64_byte1; p->base64_buffer |= bits << 12; /* fallthrough */ b64_byte2: case B64_BYTE2: if (cur == end) { p->binary = B64_BYTE2; return GRPC_ERROR_NONE; } bits = inverse_base64[*cur]; ++cur; if (bits == 255) return parse_error( exec_ctx, p, cur, end, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Illegal base64 character")); else if (bits == 64) goto b64_byte2; p->base64_buffer |= bits << 6; /* fallthrough */ b64_byte3: case B64_BYTE3: if (cur == end) { p->binary = B64_BYTE3; return GRPC_ERROR_NONE; } bits = inverse_base64[*cur]; ++cur; if (bits == 255) return parse_error( exec_ctx, p, cur, end, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Illegal base64 character")); else if (bits == 64) goto b64_byte3; p->base64_buffer |= bits; bits = p->base64_buffer; decoded[0] = (uint8_t)(bits >> 16); decoded[1] = (uint8_t)(bits >> 8); decoded[2] = (uint8_t)(bits); append_bytes(str, decoded, 3); goto b64_byte0; } GPR_UNREACHABLE_CODE(return parse_error( exec_ctx, p, cur, end, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Should never reach here"))); } static grpc_error *finish_str(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { uint8_t decoded[2]; uint32_t bits; grpc_chttp2_hpack_parser_string *str = p->parsing.str; switch ((binary_state)p->binary) { case NOT_BINARY: break; case BINARY_BEGIN: break; case B64_BYTE0: break; case B64_BYTE1: return parse_error(exec_ctx, p, cur, end, GRPC_ERROR_CREATE_FROM_STATIC_STRING( "illegal base64 encoding")); /* illegal encoding */ case B64_BYTE2: bits = p->base64_buffer; if (bits & 0xffff) { char *msg; gpr_asprintf(&msg, "trailing bits in base64 encoding: 0x%04x", bits & 0xffff); grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return parse_error(exec_ctx, p, cur, end, err); } decoded[0] = (uint8_t)(bits >> 16); append_bytes(str, decoded, 1); break; case B64_BYTE3: bits = p->base64_buffer; if (bits & 0xff) { char *msg; gpr_asprintf(&msg, "trailing bits in base64 encoding: 0x%02x", bits & 0xff); grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return parse_error(exec_ctx, p, cur, end, err); } decoded[0] = (uint8_t)(bits >> 16); decoded[1] = (uint8_t)(bits >> 8); append_bytes(str, decoded, 2); break; } return GRPC_ERROR_NONE; } /* decode a nibble from a huffman encoded stream */ static grpc_error *huff_nibble(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, uint8_t nibble) { int16_t emit = emit_sub_tbl[16 * emit_tbl[p->huff_state] + nibble]; int16_t next = next_sub_tbl[16 * next_tbl[p->huff_state] + nibble]; if (emit != -1) { if (emit >= 0 && emit < 256) { uint8_t c = (uint8_t)emit; grpc_error *err = append_string(exec_ctx, p, &c, (&c) + 1); if (err != GRPC_ERROR_NONE) return err; } else { assert(emit == 256); } } p->huff_state = next; return GRPC_ERROR_NONE; } /* decode full bytes from a huffman encoded stream */ static grpc_error *add_huff_bytes(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { for (; cur != end; ++cur) { grpc_error *err = huff_nibble(exec_ctx, p, *cur >> 4); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); err = huff_nibble(exec_ctx, p, *cur & 0xf); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); } return GRPC_ERROR_NONE; } /* decode some string bytes based on the current decoding mode (huffman or not) */ static grpc_error *add_str_bytes(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { if (p->huff) { return add_huff_bytes(exec_ctx, p, cur, end); } else { return append_string(exec_ctx, p, cur, end); } } /* parse a string - tries to do large chunks at a time */ static grpc_error *parse_string(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { size_t remaining = p->strlen - p->strgot; size_t given = (size_t)(end - cur); if (remaining <= given) { grpc_error *err = add_str_bytes(exec_ctx, p, cur, cur + remaining); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); err = finish_str(exec_ctx, p, cur + remaining, end); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); return parse_next(exec_ctx, p, cur + remaining, end); } else { grpc_error *err = add_str_bytes(exec_ctx, p, cur, cur + given); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); GPR_ASSERT(given <= UINT32_MAX - p->strgot); p->strgot += (uint32_t)given; p->state = parse_string; return GRPC_ERROR_NONE; } } /* begin parsing a string - performs setup, calls parse_string */ static grpc_error *begin_parse_string(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end, uint8_t binary, grpc_chttp2_hpack_parser_string *str) { if (!p->huff && binary == NOT_BINARY && (end - cur) >= (intptr_t)p->strlen && p->current_slice_refcount != NULL) { str->copied = false; str->data.referenced.refcount = p->current_slice_refcount; str->data.referenced.data.refcounted.bytes = (uint8_t *)cur; str->data.referenced.data.refcounted.length = p->strlen; grpc_slice_ref_internal(str->data.referenced); return parse_next(exec_ctx, p, cur + p->strlen, end); } p->strgot = 0; str->copied = true; str->data.copied.length = 0; p->parsing.str = str; p->huff_state = 0; p->binary = binary; return parse_string(exec_ctx, p, cur, end); } /* parse the key string */ static grpc_error *parse_key_string(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { return begin_parse_string(exec_ctx, p, cur, end, NOT_BINARY, &p->key); } /* check if a key represents a binary header or not */ static bool is_binary_literal_header(grpc_chttp2_hpack_parser *p) { return grpc_is_binary_header( p->key.copied ? grpc_slice_from_static_buffer(p->key.data.copied.str, p->key.data.copied.length) : p->key.data.referenced); } static grpc_error *is_binary_indexed_header(grpc_chttp2_hpack_parser *p, bool *is) { grpc_mdelem elem = grpc_chttp2_hptbl_lookup(&p->table, p->index); if (GRPC_MDISNULL(elem)) { return grpc_error_set_int( grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Invalid HPACK index received"), GRPC_ERROR_INT_INDEX, (intptr_t)p->index), GRPC_ERROR_INT_SIZE, (intptr_t)p->table.num_ents); } *is = grpc_is_binary_header(GRPC_MDKEY(elem)); return GRPC_ERROR_NONE; } /* parse the value string */ static grpc_error *parse_value_string(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end, bool is_binary) { return begin_parse_string(exec_ctx, p, cur, end, is_binary ? BINARY_BEGIN : NOT_BINARY, &p->value); } static grpc_error *parse_value_string_with_indexed_key( grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { bool is_binary = false; grpc_error *err = is_binary_indexed_header(p, &is_binary); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); return parse_value_string(exec_ctx, p, cur, end, is_binary); } static grpc_error *parse_value_string_with_literal_key( grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { return parse_value_string(exec_ctx, p, cur, end, is_binary_literal_header(p)); } /* PUBLIC INTERFACE */ void grpc_chttp2_hpack_parser_init(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p) { p->on_header = NULL; p->on_header_user_data = NULL; p->state = parse_begin; p->key.data.referenced = grpc_empty_slice(); p->key.data.copied.str = NULL; p->key.data.copied.capacity = 0; p->key.data.copied.length = 0; p->value.data.referenced = grpc_empty_slice(); p->value.data.copied.str = NULL; p->value.data.copied.capacity = 0; p->value.data.copied.length = 0; p->dynamic_table_update_allowed = 2; p->last_error = GRPC_ERROR_NONE; grpc_chttp2_hptbl_init(exec_ctx, &p->table); } void grpc_chttp2_hpack_parser_set_has_priority(grpc_chttp2_hpack_parser *p) { p->after_prioritization = p->state; p->state = parse_stream_dep0; } void grpc_chttp2_hpack_parser_destroy(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p) { grpc_chttp2_hptbl_destroy(exec_ctx, &p->table); GRPC_ERROR_UNREF(p->last_error); grpc_slice_unref_internal(exec_ctx, p->key.data.referenced); grpc_slice_unref_internal(exec_ctx, p->value.data.referenced); gpr_free(p->key.data.copied.str); gpr_free(p->value.data.copied.str); } grpc_error *grpc_chttp2_hpack_parser_parse(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, grpc_slice slice) { /* max number of bytes to parse at a time... limits call stack depth on * compilers without TCO */ #define MAX_PARSE_LENGTH 1024 p->current_slice_refcount = slice.refcount; uint8_t *start = GRPC_SLICE_START_PTR(slice); uint8_t *end = GRPC_SLICE_END_PTR(slice); grpc_error *error = GRPC_ERROR_NONE; while (start != end && error == GRPC_ERROR_NONE) { uint8_t *target = start + GPR_MIN(MAX_PARSE_LENGTH, end - start); error = p->state(exec_ctx, p, start, target); start = target; } p->current_slice_refcount = NULL; return error; } typedef void (*maybe_complete_func_type)(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s); static const maybe_complete_func_type maybe_complete_funcs[] = { grpc_chttp2_maybe_complete_recv_initial_metadata, grpc_chttp2_maybe_complete_recv_trailing_metadata}; static void force_client_rst_stream(grpc_exec_ctx *exec_ctx, void *sp, grpc_error *error) { grpc_chttp2_stream *s = sp; grpc_chttp2_transport *t = s->t; if (!s->write_closed) { grpc_slice_buffer_add( &t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_HTTP2_NO_ERROR, &s->stats.outgoing)); grpc_chttp2_initiate_write(exec_ctx, t, false, "force_rst_stream"); grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, true, GRPC_ERROR_NONE); } GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "final_rst"); } grpc_error *grpc_chttp2_header_parser_parse(grpc_exec_ctx *exec_ctx, void *hpack_parser, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_slice slice, int is_last) { grpc_chttp2_hpack_parser *parser = hpack_parser; GPR_TIMER_BEGIN("grpc_chttp2_hpack_parser_parse", 0); if (s != NULL) { s->stats.incoming.header_bytes += GRPC_SLICE_LENGTH(slice); } grpc_error *error = grpc_chttp2_hpack_parser_parse(exec_ctx, parser, slice); if (error != GRPC_ERROR_NONE) { GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0); return error; } if (is_last) { if (parser->is_boundary && parser->state != parse_begin) { GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0); return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "end of header frame not aligned with a hpack record boundary"); } /* need to check for null stream: this can occur if we receive an invalid stream id on a header */ if (s != NULL) { if (parser->is_boundary) { if (s->header_frames_received == GPR_ARRAY_SIZE(s->metadata_buffer)) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Too many trailer frames"); } s->published_metadata[s->header_frames_received] = GRPC_METADATA_PUBLISHED_FROM_WIRE; maybe_complete_funcs[s->header_frames_received](exec_ctx, t, s); s->header_frames_received++; } if (parser->is_eof) { if (t->is_client && !s->write_closed) { /* server eof ==> complete closure; we may need to forcefully close the stream. Wait until the combiner lock is ready to be released however -- it might be that we receive a RST_STREAM following this and can avoid the extra write */ GRPC_CHTTP2_STREAM_REF(s, "final_rst"); grpc_closure_sched( exec_ctx, grpc_closure_create(force_client_rst_stream, s, grpc_combiner_finally_scheduler( t->combiner, false)), GRPC_ERROR_NONE); } grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, false, GRPC_ERROR_NONE); } } parser->on_header = NULL; parser->on_header_user_data = NULL; parser->is_boundary = 0xde; parser->is_eof = 0xde; parser->dynamic_table_update_allowed = 2; } GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0); return GRPC_ERROR_NONE; } grpc-1.3.2/src/core/ext/transport/chttp2/transport/hpack_parser.h000066400000000000000000000117421310511640000250720ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_PARSER_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_PARSER_H #include #include #include "src/core/ext/transport/chttp2/transport/frame.h" #include "src/core/ext/transport/chttp2/transport/hpack_table.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/transport/metadata.h" typedef struct grpc_chttp2_hpack_parser grpc_chttp2_hpack_parser; typedef grpc_error *(*grpc_chttp2_hpack_parser_state)( grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *beg, const uint8_t *end); typedef struct { bool copied; struct { grpc_slice referenced; struct { char *str; uint32_t length; uint32_t capacity; } copied; } data; } grpc_chttp2_hpack_parser_string; struct grpc_chttp2_hpack_parser { /* user specified callback for each header output */ void (*on_header)(grpc_exec_ctx *exec_ctx, void *user_data, grpc_mdelem md); void *on_header_user_data; grpc_error *last_error; /* current parse state - or a function that implements it */ grpc_chttp2_hpack_parser_state state; /* future states dependent on the opening op code */ const grpc_chttp2_hpack_parser_state *next_state; /* what to do after skipping prioritization data */ grpc_chttp2_hpack_parser_state after_prioritization; /* the refcount of the slice that we're currently parsing */ grpc_slice_refcount *current_slice_refcount; /* the value we're currently parsing */ union { uint32_t *value; grpc_chttp2_hpack_parser_string *str; } parsing; /* string parameters for each chunk */ grpc_chttp2_hpack_parser_string key; grpc_chttp2_hpack_parser_string value; /* parsed index */ uint32_t index; /* length of source bytes for the currently parsing string */ uint32_t strlen; /* number of source bytes read for the currently parsing string */ uint32_t strgot; /* huffman decoding state */ int16_t huff_state; /* is the string being decoded binary? */ uint8_t binary; /* is the current string huffman encoded? */ uint8_t huff; /* is a dynamic table update allowed? */ uint8_t dynamic_table_update_allowed; /* set by higher layers, used by grpc_chttp2_header_parser_parse to signal it should append a metadata boundary at the end of frame */ uint8_t is_boundary; uint8_t is_eof; uint32_t base64_buffer; /* hpack table */ grpc_chttp2_hptbl table; }; void grpc_chttp2_hpack_parser_init(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p); void grpc_chttp2_hpack_parser_destroy(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p); void grpc_chttp2_hpack_parser_set_has_priority(grpc_chttp2_hpack_parser *p); grpc_error *grpc_chttp2_hpack_parser_parse(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, grpc_slice slice); /* wraps grpc_chttp2_hpack_parser_parse to provide a frame level parser for the transport */ grpc_error *grpc_chttp2_header_parser_parse(grpc_exec_ctx *exec_ctx, void *hpack_parser, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_slice slice, int is_last); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_PARSER_H */ grpc-1.3.2/src/core/ext/transport/chttp2/transport/hpack_table.c000066400000000000000000000264421310511640000246630ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/transport/hpack_table.h" #include #include #include #include #include #include "src/core/lib/support/murmur_hash.h" extern int grpc_http_trace; static struct { const char *key; const char *value; } static_table[] = { /* 0: */ {NULL, NULL}, /* 1: */ {":authority", ""}, /* 2: */ {":method", "GET"}, /* 3: */ {":method", "POST"}, /* 4: */ {":path", "/"}, /* 5: */ {":path", "/index.html"}, /* 6: */ {":scheme", "http"}, /* 7: */ {":scheme", "https"}, /* 8: */ {":status", "200"}, /* 9: */ {":status", "204"}, /* 10: */ {":status", "206"}, /* 11: */ {":status", "304"}, /* 12: */ {":status", "400"}, /* 13: */ {":status", "404"}, /* 14: */ {":status", "500"}, /* 15: */ {"accept-charset", ""}, /* 16: */ {"accept-encoding", "gzip, deflate"}, /* 17: */ {"accept-language", ""}, /* 18: */ {"accept-ranges", ""}, /* 19: */ {"accept", ""}, /* 20: */ {"access-control-allow-origin", ""}, /* 21: */ {"age", ""}, /* 22: */ {"allow", ""}, /* 23: */ {"authorization", ""}, /* 24: */ {"cache-control", ""}, /* 25: */ {"content-disposition", ""}, /* 26: */ {"content-encoding", ""}, /* 27: */ {"content-language", ""}, /* 28: */ {"content-length", ""}, /* 29: */ {"content-location", ""}, /* 30: */ {"content-range", ""}, /* 31: */ {"content-type", ""}, /* 32: */ {"cookie", ""}, /* 33: */ {"date", ""}, /* 34: */ {"etag", ""}, /* 35: */ {"expect", ""}, /* 36: */ {"expires", ""}, /* 37: */ {"from", ""}, /* 38: */ {"host", ""}, /* 39: */ {"if-match", ""}, /* 40: */ {"if-modified-since", ""}, /* 41: */ {"if-none-match", ""}, /* 42: */ {"if-range", ""}, /* 43: */ {"if-unmodified-since", ""}, /* 44: */ {"last-modified", ""}, /* 45: */ {"link", ""}, /* 46: */ {"location", ""}, /* 47: */ {"max-forwards", ""}, /* 48: */ {"proxy-authenticate", ""}, /* 49: */ {"proxy-authorization", ""}, /* 50: */ {"range", ""}, /* 51: */ {"referer", ""}, /* 52: */ {"refresh", ""}, /* 53: */ {"retry-after", ""}, /* 54: */ {"server", ""}, /* 55: */ {"set-cookie", ""}, /* 56: */ {"strict-transport-security", ""}, /* 57: */ {"transfer-encoding", ""}, /* 58: */ {"user-agent", ""}, /* 59: */ {"vary", ""}, /* 60: */ {"via", ""}, /* 61: */ {"www-authenticate", ""}, }; static uint32_t entries_for_bytes(uint32_t bytes) { return (bytes + GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD - 1) / GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD; } void grpc_chttp2_hptbl_init(grpc_exec_ctx *exec_ctx, grpc_chttp2_hptbl *tbl) { size_t i; memset(tbl, 0, sizeof(*tbl)); tbl->current_table_bytes = tbl->max_bytes = GRPC_CHTTP2_INITIAL_HPACK_TABLE_SIZE; tbl->max_entries = tbl->cap_entries = entries_for_bytes(tbl->current_table_bytes); tbl->ents = gpr_malloc(sizeof(*tbl->ents) * tbl->cap_entries); memset(tbl->ents, 0, sizeof(*tbl->ents) * tbl->cap_entries); for (i = 1; i <= GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) { tbl->static_ents[i - 1] = grpc_mdelem_from_slices( exec_ctx, grpc_slice_intern(grpc_slice_from_static_string(static_table[i].key)), grpc_slice_intern( grpc_slice_from_static_string(static_table[i].value))); } } void grpc_chttp2_hptbl_destroy(grpc_exec_ctx *exec_ctx, grpc_chttp2_hptbl *tbl) { size_t i; for (i = 0; i < GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) { GRPC_MDELEM_UNREF(exec_ctx, tbl->static_ents[i]); } for (i = 0; i < tbl->num_ents; i++) { GRPC_MDELEM_UNREF(exec_ctx, tbl->ents[(tbl->first_ent + i) % tbl->cap_entries]); } gpr_free(tbl->ents); } grpc_mdelem grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl, uint32_t tbl_index) { /* Static table comes first, just return an entry from it */ if (tbl_index <= GRPC_CHTTP2_LAST_STATIC_ENTRY) { return tbl->static_ents[tbl_index - 1]; } /* Otherwise, find the value in the list of valid entries */ tbl_index -= (GRPC_CHTTP2_LAST_STATIC_ENTRY + 1); if (tbl_index < tbl->num_ents) { uint32_t offset = (tbl->num_ents - 1u - tbl_index + tbl->first_ent) % tbl->cap_entries; return tbl->ents[offset]; } /* Invalid entry: return error */ return GRPC_MDNULL; } /* Evict one element from the table */ static void evict1(grpc_exec_ctx *exec_ctx, grpc_chttp2_hptbl *tbl) { grpc_mdelem first_ent = tbl->ents[tbl->first_ent]; size_t elem_bytes = GRPC_SLICE_LENGTH(GRPC_MDKEY(first_ent)) + GRPC_SLICE_LENGTH(GRPC_MDVALUE(first_ent)) + GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD; GPR_ASSERT(elem_bytes <= tbl->mem_used); tbl->mem_used -= (uint32_t)elem_bytes; tbl->first_ent = ((tbl->first_ent + 1) % tbl->cap_entries); tbl->num_ents--; GRPC_MDELEM_UNREF(exec_ctx, first_ent); } static void rebuild_ents(grpc_chttp2_hptbl *tbl, uint32_t new_cap) { grpc_mdelem *ents = gpr_malloc(sizeof(*ents) * new_cap); uint32_t i; for (i = 0; i < tbl->num_ents; i++) { ents[i] = tbl->ents[(tbl->first_ent + i) % tbl->cap_entries]; } gpr_free(tbl->ents); tbl->ents = ents; tbl->cap_entries = new_cap; tbl->first_ent = 0; } void grpc_chttp2_hptbl_set_max_bytes(grpc_exec_ctx *exec_ctx, grpc_chttp2_hptbl *tbl, uint32_t max_bytes) { if (tbl->max_bytes == max_bytes) { return; } if (grpc_http_trace) { gpr_log(GPR_DEBUG, "Update hpack parser max size to %d", max_bytes); } while (tbl->mem_used > max_bytes) { evict1(exec_ctx, tbl); } tbl->max_bytes = max_bytes; } grpc_error *grpc_chttp2_hptbl_set_current_table_size(grpc_exec_ctx *exec_ctx, grpc_chttp2_hptbl *tbl, uint32_t bytes) { if (tbl->current_table_bytes == bytes) { return GRPC_ERROR_NONE; } if (bytes > tbl->max_bytes) { char *msg; gpr_asprintf(&msg, "Attempt to make hpack table %d bytes when max is %d bytes", bytes, tbl->max_bytes); grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return err; } if (grpc_http_trace) { gpr_log(GPR_DEBUG, "Update hpack parser table size to %d", bytes); } while (tbl->mem_used > bytes) { evict1(exec_ctx, tbl); } tbl->current_table_bytes = bytes; tbl->max_entries = entries_for_bytes(bytes); if (tbl->max_entries > tbl->cap_entries) { rebuild_ents(tbl, GPR_MAX(tbl->max_entries, 2 * tbl->cap_entries)); } else if (tbl->max_entries < tbl->cap_entries / 3) { uint32_t new_cap = GPR_MAX(tbl->max_entries, 16u); if (new_cap != tbl->cap_entries) { rebuild_ents(tbl, new_cap); } } return GRPC_ERROR_NONE; } grpc_error *grpc_chttp2_hptbl_add(grpc_exec_ctx *exec_ctx, grpc_chttp2_hptbl *tbl, grpc_mdelem md) { /* determine how many bytes of buffer this entry represents */ size_t elem_bytes = GRPC_SLICE_LENGTH(GRPC_MDKEY(md)) + GRPC_SLICE_LENGTH(GRPC_MDVALUE(md)) + GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD; if (tbl->current_table_bytes > tbl->max_bytes) { char *msg; gpr_asprintf( &msg, "HPACK max table size reduced to %d but not reflected by hpack " "stream (still at %d)", tbl->max_bytes, tbl->current_table_bytes); grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return err; } /* we can't add elements bigger than the max table size */ if (elem_bytes > tbl->current_table_bytes) { /* HPACK draft 10 section 4.4 states: * If the size of the new entry is less than or equal to the maximum * size, that entry is added to the table. It is not an error to * attempt to add an entry that is larger than the maximum size; an * attempt to add an entry larger than the entire table causes * the table * to be emptied of all existing entries, and results in an * empty table. */ while (tbl->num_ents) { evict1(exec_ctx, tbl); } return GRPC_ERROR_NONE; } /* evict entries to ensure no overflow */ while (elem_bytes > (size_t)tbl->current_table_bytes - tbl->mem_used) { evict1(exec_ctx, tbl); } /* copy the finalized entry in */ tbl->ents[(tbl->first_ent + tbl->num_ents) % tbl->cap_entries] = GRPC_MDELEM_REF(md); /* update accounting values */ tbl->num_ents++; tbl->mem_used += (uint32_t)elem_bytes; return GRPC_ERROR_NONE; } grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find( const grpc_chttp2_hptbl *tbl, grpc_mdelem md) { grpc_chttp2_hptbl_find_result r = {0, 0}; uint32_t i; /* See if the string is in the static table */ for (i = 0; i < GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) { grpc_mdelem ent = tbl->static_ents[i]; if (!grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDKEY(ent))) continue; r.index = i + 1u; r.has_value = grpc_slice_eq(GRPC_MDVALUE(md), GRPC_MDVALUE(ent)); if (r.has_value) return r; } /* Scan the dynamic table */ for (i = 0; i < tbl->num_ents; i++) { uint32_t idx = (uint32_t)(tbl->num_ents - i + GRPC_CHTTP2_LAST_STATIC_ENTRY); grpc_mdelem ent = tbl->ents[(tbl->first_ent + i) % tbl->cap_entries]; if (!grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDKEY(ent))) continue; r.index = idx; r.has_value = grpc_slice_eq(GRPC_MDVALUE(md), GRPC_MDVALUE(ent)); if (r.has_value) return r; } return r; } grpc-1.3.2/src/core/ext/transport/chttp2/transport/hpack_table.h000066400000000000000000000115321310511640000246620ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_TABLE_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_TABLE_H #include #include #include "src/core/lib/iomgr/error.h" #include "src/core/lib/transport/metadata.h" /* HPACK header table */ /* last index in the static table */ #define GRPC_CHTTP2_LAST_STATIC_ENTRY 61 /* Initial table size as per the spec */ #define GRPC_CHTTP2_INITIAL_HPACK_TABLE_SIZE 4096 /* Maximum table size that we'll use */ #define GRPC_CHTTP2_MAX_HPACK_TABLE_SIZE GRPC_CHTTP2_INITIAL_HPACK_TABLE_SIZE /* Per entry overhead bytes as per the spec */ #define GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD 32 #if 0 /* Maximum number of entries we could possibly fit in the table, given defined overheads */ #define GRPC_CHTTP2_MAX_TABLE_COUNT \ ((GRPC_CHTTP2_MAX_HPACK_TABLE_SIZE + GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD - 1) / \ GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD) #endif /* hpack decoder table */ typedef struct { /* the first used entry in ents */ uint32_t first_ent; /* how many entries are in the table */ uint32_t num_ents; /* the amount of memory used by the table, according to the hpack algorithm */ uint32_t mem_used; /* the max memory allowed to be used by the table, according to the hpack algorithm */ uint32_t max_bytes; /* the currently agreed size of the table, according to the hpack algorithm */ uint32_t current_table_bytes; /* Maximum number of entries we could possibly fit in the table, given defined overheads */ uint32_t max_entries; /* Number of entries allocated in ents */ uint32_t cap_entries; /* a circular buffer of headers - this is stored in the opposite order to what hpack specifies, in order to simplify table management a little... meaning lookups need to SUBTRACT from the end position */ grpc_mdelem *ents; grpc_mdelem static_ents[GRPC_CHTTP2_LAST_STATIC_ENTRY]; } grpc_chttp2_hptbl; /* initialize a hpack table */ void grpc_chttp2_hptbl_init(grpc_exec_ctx *exec_ctx, grpc_chttp2_hptbl *tbl); void grpc_chttp2_hptbl_destroy(grpc_exec_ctx *exec_ctx, grpc_chttp2_hptbl *tbl); void grpc_chttp2_hptbl_set_max_bytes(grpc_exec_ctx *exec_ctx, grpc_chttp2_hptbl *tbl, uint32_t max_bytes); grpc_error *grpc_chttp2_hptbl_set_current_table_size(grpc_exec_ctx *exec_ctx, grpc_chttp2_hptbl *tbl, uint32_t bytes); /* lookup a table entry based on its hpack index */ grpc_mdelem grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl, uint32_t index); /* add a table entry to the index */ grpc_error *grpc_chttp2_hptbl_add(grpc_exec_ctx *exec_ctx, grpc_chttp2_hptbl *tbl, grpc_mdelem md) GRPC_MUST_USE_RESULT; /* Find a key/value pair in the table... returns the index in the table of the most similar entry, or 0 if the value was not found */ typedef struct { uint32_t index; int has_value; } grpc_chttp2_hptbl_find_result; grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find( const grpc_chttp2_hptbl *tbl, grpc_mdelem md); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_TABLE_H */ grpc-1.3.2/src/core/ext/transport/chttp2/transport/hpack_tables.txt000066400000000000000000000103371310511640000254370ustar00rootroot00000000000000Static table, from the spec: +-------+-----------------------------+---------------+ | Index | Header Name | Header Value | +-------+-----------------------------+---------------+ | 1 | :authority | | | 2 | :method | GET | | 3 | :method | POST | | 4 | :path | / | | 5 | :path | /index.html | | 6 | :scheme | http | | 7 | :scheme | https | | 8 | :status | 200 | | 9 | :status | 204 | | 10 | :status | 206 | | 11 | :status | 304 | | 12 | :status | 400 | | 13 | :status | 404 | | 14 | :status | 500 | | 15 | accept-charset | | | 16 | accept-encoding | gzip, deflate | | 17 | accept-language | | | 18 | accept-ranges | | | 19 | accept | | | 20 | access-control-allow-origin | | | 21 | age | | | 22 | allow | | | 23 | authorization | | | 24 | cache-control | | | 25 | content-disposition | | | 26 | content-encoding | | | 27 | content-language | | | 28 | content-length | | | 29 | content-location | | | 30 | content-range | | | 31 | content-type | | | 32 | cookie | | | 33 | date | | | 34 | etag | | | 35 | expect | | | 36 | expires | | | 37 | from | | | 38 | host | | | 39 | if-match | | | 40 | if-modified-since | | | 41 | if-none-match | | | 42 | if-range | | | 43 | if-unmodified-since | | | 44 | last-modified | | | 45 | link | | | 46 | location | | | 47 | max-forwards | | | 48 | proxy-authenticate | | | 49 | proxy-authorization | | | 50 | range | | | 51 | referer | | | 52 | refresh | | | 53 | retry-after | | | 54 | server | | | 55 | set-cookie | | | 56 | strict-transport-security | | | 57 | transfer-encoding | | | 58 | user-agent | | | 59 | vary | | | 60 | via | | | 61 | www-authenticate | | +-------+-----------------------------+---------------+ grpc-1.3.2/src/core/ext/transport/chttp2/transport/http2_settings.c000066400000000000000000000063111310511640000254000ustar00rootroot00000000000000/* * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Automatically generated by tools/codegen/core/gen_settings_ids.py */ #include "src/core/ext/transport/chttp2/transport/http2_settings.h" #include #include "src/core/lib/transport/http2_errors.h" const uint16_t grpc_setting_id_to_wire_id[] = {1, 2, 3, 4, 5, 6, 65027}; bool grpc_wire_id_to_setting_id(uint32_t wire_id, grpc_chttp2_setting_id *out) { uint32_t i = wire_id - 1; uint32_t x = i % 256; uint32_t y = i / 256; uint32_t h = x; switch (y) { case 254: h += 4; break; } *out = (grpc_chttp2_setting_id)h; return h < GPR_ARRAY_SIZE(grpc_setting_id_to_wire_id) && grpc_setting_id_to_wire_id[h] == wire_id; } const grpc_chttp2_setting_parameters grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS] = { {"HEADER_TABLE_SIZE", 4096u, 0u, 4294967295u, GRPC_CHTTP2_CLAMP_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR}, {"ENABLE_PUSH", 1u, 0u, 1u, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR}, {"MAX_CONCURRENT_STREAMS", 4294967295u, 0u, 4294967295u, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR}, {"INITIAL_WINDOW_SIZE", 65535u, 0u, 2147483647u, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_HTTP2_FLOW_CONTROL_ERROR}, {"MAX_FRAME_SIZE", 16384u, 16384u, 16777215u, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR}, {"MAX_HEADER_LIST_SIZE", 16777216u, 0u, 16777216u, GRPC_CHTTP2_CLAMP_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR}, {"GRPC_ALLOW_TRUE_BINARY_METADATA", 0u, 0u, 1u, GRPC_CHTTP2_CLAMP_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR}, }; grpc-1.3.2/src/core/ext/transport/chttp2/transport/http2_settings.h000066400000000000000000000060341310511640000254070ustar00rootroot00000000000000/* * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Automatically generated by tools/codegen/core/gen_settings_ids.py */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_SETTINGS_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_SETTINGS_H #include #include typedef enum { GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE = 0, /* wire id 1 */ GRPC_CHTTP2_SETTINGS_ENABLE_PUSH = 1, /* wire id 2 */ GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS = 2, /* wire id 3 */ GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE = 3, /* wire id 4 */ GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE = 4, /* wire id 5 */ GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 5, /* wire id 6 */ GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA = 6, /* wire id 65027 */ } grpc_chttp2_setting_id; #define GRPC_CHTTP2_NUM_SETTINGS 7 extern const uint16_t grpc_setting_id_to_wire_id[]; bool grpc_wire_id_to_setting_id(uint32_t wire_id, grpc_chttp2_setting_id *out); typedef enum { GRPC_CHTTP2_CLAMP_INVALID_VALUE, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE } grpc_chttp2_invalid_value_behavior; typedef struct { const char *name; uint32_t default_value; uint32_t min_value; uint32_t max_value; grpc_chttp2_invalid_value_behavior invalid_value_behavior; uint32_t error_value; } grpc_chttp2_setting_parameters; extern const grpc_chttp2_setting_parameters grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS]; #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_SETTINGS_H */ grpc-1.3.2/src/core/ext/transport/chttp2/transport/huffsyms.c000066400000000000000000000146061310511640000242710ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/transport/huffsyms.h" /* Constants pulled from the HPACK spec, and converted to C using the vim command: :%s/.* \([0-9a-f]\+\) \[ *\([0-9]\+\)\]/{0x\1, \2},/g */ const grpc_chttp2_huffsym grpc_chttp2_huffsyms[GRPC_CHTTP2_NUM_HUFFSYMS] = { {0x1ff8, 13}, {0x7fffd8, 23}, {0xfffffe2, 28}, {0xfffffe3, 28}, {0xfffffe4, 28}, {0xfffffe5, 28}, {0xfffffe6, 28}, {0xfffffe7, 28}, {0xfffffe8, 28}, {0xffffea, 24}, {0x3ffffffc, 30}, {0xfffffe9, 28}, {0xfffffea, 28}, {0x3ffffffd, 30}, {0xfffffeb, 28}, {0xfffffec, 28}, {0xfffffed, 28}, {0xfffffee, 28}, {0xfffffef, 28}, {0xffffff0, 28}, {0xffffff1, 28}, {0xffffff2, 28}, {0x3ffffffe, 30}, {0xffffff3, 28}, {0xffffff4, 28}, {0xffffff5, 28}, {0xffffff6, 28}, {0xffffff7, 28}, {0xffffff8, 28}, {0xffffff9, 28}, {0xffffffa, 28}, {0xffffffb, 28}, {0x14, 6}, {0x3f8, 10}, {0x3f9, 10}, {0xffa, 12}, {0x1ff9, 13}, {0x15, 6}, {0xf8, 8}, {0x7fa, 11}, {0x3fa, 10}, {0x3fb, 10}, {0xf9, 8}, {0x7fb, 11}, {0xfa, 8}, {0x16, 6}, {0x17, 6}, {0x18, 6}, {0x0, 5}, {0x1, 5}, {0x2, 5}, {0x19, 6}, {0x1a, 6}, {0x1b, 6}, {0x1c, 6}, {0x1d, 6}, {0x1e, 6}, {0x1f, 6}, {0x5c, 7}, {0xfb, 8}, {0x7ffc, 15}, {0x20, 6}, {0xffb, 12}, {0x3fc, 10}, {0x1ffa, 13}, {0x21, 6}, {0x5d, 7}, {0x5e, 7}, {0x5f, 7}, {0x60, 7}, {0x61, 7}, {0x62, 7}, {0x63, 7}, {0x64, 7}, {0x65, 7}, {0x66, 7}, {0x67, 7}, {0x68, 7}, {0x69, 7}, {0x6a, 7}, {0x6b, 7}, {0x6c, 7}, {0x6d, 7}, {0x6e, 7}, {0x6f, 7}, {0x70, 7}, {0x71, 7}, {0x72, 7}, {0xfc, 8}, {0x73, 7}, {0xfd, 8}, {0x1ffb, 13}, {0x7fff0, 19}, {0x1ffc, 13}, {0x3ffc, 14}, {0x22, 6}, {0x7ffd, 15}, {0x3, 5}, {0x23, 6}, {0x4, 5}, {0x24, 6}, {0x5, 5}, {0x25, 6}, {0x26, 6}, {0x27, 6}, {0x6, 5}, {0x74, 7}, {0x75, 7}, {0x28, 6}, {0x29, 6}, {0x2a, 6}, {0x7, 5}, {0x2b, 6}, {0x76, 7}, {0x2c, 6}, {0x8, 5}, {0x9, 5}, {0x2d, 6}, {0x77, 7}, {0x78, 7}, {0x79, 7}, {0x7a, 7}, {0x7b, 7}, {0x7ffe, 15}, {0x7fc, 11}, {0x3ffd, 14}, {0x1ffd, 13}, {0xffffffc, 28}, {0xfffe6, 20}, {0x3fffd2, 22}, {0xfffe7, 20}, {0xfffe8, 20}, {0x3fffd3, 22}, {0x3fffd4, 22}, {0x3fffd5, 22}, {0x7fffd9, 23}, {0x3fffd6, 22}, {0x7fffda, 23}, {0x7fffdb, 23}, {0x7fffdc, 23}, {0x7fffdd, 23}, {0x7fffde, 23}, {0xffffeb, 24}, {0x7fffdf, 23}, {0xffffec, 24}, {0xffffed, 24}, {0x3fffd7, 22}, {0x7fffe0, 23}, {0xffffee, 24}, {0x7fffe1, 23}, {0x7fffe2, 23}, {0x7fffe3, 23}, {0x7fffe4, 23}, {0x1fffdc, 21}, {0x3fffd8, 22}, {0x7fffe5, 23}, {0x3fffd9, 22}, {0x7fffe6, 23}, {0x7fffe7, 23}, {0xffffef, 24}, {0x3fffda, 22}, {0x1fffdd, 21}, {0xfffe9, 20}, {0x3fffdb, 22}, {0x3fffdc, 22}, {0x7fffe8, 23}, {0x7fffe9, 23}, {0x1fffde, 21}, {0x7fffea, 23}, {0x3fffdd, 22}, {0x3fffde, 22}, {0xfffff0, 24}, {0x1fffdf, 21}, {0x3fffdf, 22}, {0x7fffeb, 23}, {0x7fffec, 23}, {0x1fffe0, 21}, {0x1fffe1, 21}, {0x3fffe0, 22}, {0x1fffe2, 21}, {0x7fffed, 23}, {0x3fffe1, 22}, {0x7fffee, 23}, {0x7fffef, 23}, {0xfffea, 20}, {0x3fffe2, 22}, {0x3fffe3, 22}, {0x3fffe4, 22}, {0x7ffff0, 23}, {0x3fffe5, 22}, {0x3fffe6, 22}, {0x7ffff1, 23}, {0x3ffffe0, 26}, {0x3ffffe1, 26}, {0xfffeb, 20}, {0x7fff1, 19}, {0x3fffe7, 22}, {0x7ffff2, 23}, {0x3fffe8, 22}, {0x1ffffec, 25}, {0x3ffffe2, 26}, {0x3ffffe3, 26}, {0x3ffffe4, 26}, {0x7ffffde, 27}, {0x7ffffdf, 27}, {0x3ffffe5, 26}, {0xfffff1, 24}, {0x1ffffed, 25}, {0x7fff2, 19}, {0x1fffe3, 21}, {0x3ffffe6, 26}, {0x7ffffe0, 27}, {0x7ffffe1, 27}, {0x3ffffe7, 26}, {0x7ffffe2, 27}, {0xfffff2, 24}, {0x1fffe4, 21}, {0x1fffe5, 21}, {0x3ffffe8, 26}, {0x3ffffe9, 26}, {0xffffffd, 28}, {0x7ffffe3, 27}, {0x7ffffe4, 27}, {0x7ffffe5, 27}, {0xfffec, 20}, {0xfffff3, 24}, {0xfffed, 20}, {0x1fffe6, 21}, {0x3fffe9, 22}, {0x1fffe7, 21}, {0x1fffe8, 21}, {0x7ffff3, 23}, {0x3fffea, 22}, {0x3fffeb, 22}, {0x1ffffee, 25}, {0x1ffffef, 25}, {0xfffff4, 24}, {0xfffff5, 24}, {0x3ffffea, 26}, {0x7ffff4, 23}, {0x3ffffeb, 26}, {0x7ffffe6, 27}, {0x3ffffec, 26}, {0x3ffffed, 26}, {0x7ffffe7, 27}, {0x7ffffe8, 27}, {0x7ffffe9, 27}, {0x7ffffea, 27}, {0x7ffffeb, 27}, {0xffffffe, 28}, {0x7ffffec, 27}, {0x7ffffed, 27}, {0x7ffffee, 27}, {0x7ffffef, 27}, {0x7fffff0, 27}, {0x3ffffee, 26}, {0x3fffffff, 30}, }; grpc-1.3.2/src/core/ext/transport/chttp2/transport/huffsyms.h000066400000000000000000000037031310511640000242720ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HUFFSYMS_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HUFFSYMS_H /* HPACK static huffman table */ #define GRPC_CHTTP2_NUM_HUFFSYMS 257 typedef struct { unsigned bits; unsigned length; } grpc_chttp2_huffsym; extern const grpc_chttp2_huffsym grpc_chttp2_huffsyms[GRPC_CHTTP2_NUM_HUFFSYMS]; #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HUFFSYMS_H */ grpc-1.3.2/src/core/ext/transport/chttp2/transport/incoming_metadata.c000066400000000000000000000066201310511640000260650ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/transport/incoming_metadata.h" #include #include "src/core/ext/transport/chttp2/transport/internal.h" #include #include void grpc_chttp2_incoming_metadata_buffer_init( grpc_chttp2_incoming_metadata_buffer *buffer, gpr_arena *arena) { buffer->arena = arena; grpc_metadata_batch_init(&buffer->batch); buffer->batch.deadline = gpr_inf_future(GPR_CLOCK_REALTIME); } void grpc_chttp2_incoming_metadata_buffer_destroy( grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer) { grpc_metadata_batch_destroy(exec_ctx, &buffer->batch); } grpc_error *grpc_chttp2_incoming_metadata_buffer_add( grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem elem) { buffer->size += GRPC_MDELEM_LENGTH(elem); return grpc_metadata_batch_add_tail( exec_ctx, &buffer->batch, gpr_arena_alloc(buffer->arena, sizeof(grpc_linked_mdelem)), elem); } grpc_error *grpc_chttp2_incoming_metadata_buffer_replace_or_add( grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem elem) { for (grpc_linked_mdelem *l = buffer->batch.list.head; l != NULL; l = l->next) { if (grpc_slice_eq(GRPC_MDKEY(l->md), GRPC_MDKEY(elem))) { GRPC_MDELEM_UNREF(exec_ctx, l->md); l->md = elem; return GRPC_ERROR_NONE; } } return grpc_chttp2_incoming_metadata_buffer_add(exec_ctx, buffer, elem); } void grpc_chttp2_incoming_metadata_buffer_set_deadline( grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline) { buffer->batch.deadline = deadline; } void grpc_chttp2_incoming_metadata_buffer_publish( grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer, grpc_metadata_batch *batch) { *batch = buffer->batch; grpc_metadata_batch_init(&buffer->batch); } grpc-1.3.2/src/core/ext/transport/chttp2/transport/incoming_metadata.h000066400000000000000000000055421310511640000260740ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INCOMING_METADATA_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INCOMING_METADATA_H #include "src/core/lib/transport/transport.h" typedef struct { gpr_arena *arena; grpc_metadata_batch batch; size_t size; // total size of metadata } grpc_chttp2_incoming_metadata_buffer; /** assumes everything initially zeroed */ void grpc_chttp2_incoming_metadata_buffer_init( grpc_chttp2_incoming_metadata_buffer *buffer, gpr_arena *arena); void grpc_chttp2_incoming_metadata_buffer_destroy( grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer); void grpc_chttp2_incoming_metadata_buffer_publish( grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer, grpc_metadata_batch *batch); grpc_error *grpc_chttp2_incoming_metadata_buffer_add( grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem elem) GRPC_MUST_USE_RESULT; grpc_error *grpc_chttp2_incoming_metadata_buffer_replace_or_add( grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem elem) GRPC_MUST_USE_RESULT; void grpc_chttp2_incoming_metadata_buffer_set_deadline( grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INCOMING_METADATA_H */ grpc-1.3.2/src/core/ext/transport/chttp2/transport/internal.h000066400000000000000000001052771310511640000242530ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INTERNAL_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INTERNAL_H #include #include #include "src/core/ext/transport/chttp2/transport/frame.h" #include "src/core/ext/transport/chttp2/transport/frame_data.h" #include "src/core/ext/transport/chttp2/transport/frame_goaway.h" #include "src/core/ext/transport/chttp2/transport/frame_ping.h" #include "src/core/ext/transport/chttp2/transport/frame_rst_stream.h" #include "src/core/ext/transport/chttp2/transport/frame_settings.h" #include "src/core/ext/transport/chttp2/transport/frame_window_update.h" #include "src/core/ext/transport/chttp2/transport/hpack_encoder.h" #include "src/core/ext/transport/chttp2/transport/hpack_parser.h" #include "src/core/ext/transport/chttp2/transport/incoming_metadata.h" #include "src/core/ext/transport/chttp2/transport/stream_map.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/transport/bdp_estimator.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/pid_controller.h" #include "src/core/lib/transport/transport_impl.h" /* streams are kept in various linked lists depending on what things need to happen to them... this enum labels each list */ typedef enum { GRPC_CHTTP2_LIST_WRITABLE, GRPC_CHTTP2_LIST_WRITING, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT, GRPC_CHTTP2_LIST_STALLED_BY_STREAM, /** streams that are waiting to start because there are too many concurrent streams on the connection */ GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY, STREAM_LIST_COUNT /* must be last */ } grpc_chttp2_stream_list_id; typedef enum { GRPC_CHTTP2_WRITE_STATE_IDLE, GRPC_CHTTP2_WRITE_STATE_WRITING, GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE, GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE_AND_COVERED_BY_POLLER, } grpc_chttp2_write_state; typedef enum { GRPC_CHTTP2_PING_ON_NEXT_WRITE = 0, GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE, GRPC_CHTTP2_PING_TYPE_COUNT /* must be last */ } grpc_chttp2_ping_type; typedef enum { GRPC_CHTTP2_PCL_INITIATE = 0, GRPC_CHTTP2_PCL_NEXT, GRPC_CHTTP2_PCL_INFLIGHT, GRPC_CHTTP2_PCL_COUNT /* must be last */ } grpc_chttp2_ping_closure_list; typedef struct { grpc_closure_list lists[GRPC_CHTTP2_PCL_COUNT]; uint64_t inflight_id; } grpc_chttp2_ping_queue; typedef struct { gpr_timespec min_time_between_pings; int max_pings_without_data; int max_ping_strikes; gpr_timespec min_ping_interval_without_data; } grpc_chttp2_repeated_ping_policy; typedef struct { gpr_timespec last_ping_sent_time; int pings_before_data_required; grpc_timer delayed_ping_timer; bool is_delayed_ping_timer_set; } grpc_chttp2_repeated_ping_state; typedef struct { gpr_timespec last_ping_recv_time; int ping_strikes; } grpc_chttp2_server_ping_recv_state; /* deframer state for the overall http2 stream of bytes */ typedef enum { /* prefix: one entry per http2 connection prefix byte */ GRPC_DTS_CLIENT_PREFIX_0 = 0, GRPC_DTS_CLIENT_PREFIX_1, GRPC_DTS_CLIENT_PREFIX_2, GRPC_DTS_CLIENT_PREFIX_3, GRPC_DTS_CLIENT_PREFIX_4, GRPC_DTS_CLIENT_PREFIX_5, GRPC_DTS_CLIENT_PREFIX_6, GRPC_DTS_CLIENT_PREFIX_7, GRPC_DTS_CLIENT_PREFIX_8, GRPC_DTS_CLIENT_PREFIX_9, GRPC_DTS_CLIENT_PREFIX_10, GRPC_DTS_CLIENT_PREFIX_11, GRPC_DTS_CLIENT_PREFIX_12, GRPC_DTS_CLIENT_PREFIX_13, GRPC_DTS_CLIENT_PREFIX_14, GRPC_DTS_CLIENT_PREFIX_15, GRPC_DTS_CLIENT_PREFIX_16, GRPC_DTS_CLIENT_PREFIX_17, GRPC_DTS_CLIENT_PREFIX_18, GRPC_DTS_CLIENT_PREFIX_19, GRPC_DTS_CLIENT_PREFIX_20, GRPC_DTS_CLIENT_PREFIX_21, GRPC_DTS_CLIENT_PREFIX_22, GRPC_DTS_CLIENT_PREFIX_23, /* frame header byte 0... */ /* must follow from the prefix states */ GRPC_DTS_FH_0, GRPC_DTS_FH_1, GRPC_DTS_FH_2, GRPC_DTS_FH_3, GRPC_DTS_FH_4, GRPC_DTS_FH_5, GRPC_DTS_FH_6, GRPC_DTS_FH_7, /* ... frame header byte 8 */ GRPC_DTS_FH_8, /* inside a http2 frame */ GRPC_DTS_FRAME } grpc_chttp2_deframe_transport_state; typedef struct { grpc_chttp2_stream *head; grpc_chttp2_stream *tail; } grpc_chttp2_stream_list; typedef struct { grpc_chttp2_stream *next; grpc_chttp2_stream *prev; } grpc_chttp2_stream_link; /* We keep several sets of connection wide parameters */ typedef enum { /* The settings our peer has asked for (and we have acked) */ GRPC_PEER_SETTINGS = 0, /* The settings we'd like to have */ GRPC_LOCAL_SETTINGS, /* The settings we've published to our peer */ GRPC_SENT_SETTINGS, /* The settings the peer has acked */ GRPC_ACKED_SETTINGS, GRPC_NUM_SETTING_SETS } grpc_chttp2_setting_set; typedef enum { GRPC_CHTTP2_NO_GOAWAY_SEND, GRPC_CHTTP2_GOAWAY_SEND_SCHEDULED, GRPC_CHTTP2_GOAWAY_SENT, } grpc_chttp2_sent_goaway_state; typedef struct grpc_chttp2_write_cb { int64_t call_at_byte; grpc_closure *closure; struct grpc_chttp2_write_cb *next; } grpc_chttp2_write_cb; /* forward declared in frame_data.h */ struct grpc_chttp2_incoming_byte_stream { grpc_byte_stream base; gpr_refcount refs; struct grpc_chttp2_incoming_byte_stream *next_message; grpc_error *error; grpc_chttp2_transport *transport; grpc_chttp2_stream *stream; bool is_tail; gpr_mu slice_mu; // protects slices, on_next grpc_slice_buffer slices; grpc_closure *on_next; grpc_slice *next; uint32_t remaining_bytes; struct { grpc_closure closure; grpc_slice *slice; size_t max_size_hint; grpc_closure *on_complete; } next_action; grpc_closure destroy_action; grpc_closure finished_action; }; typedef enum { GRPC_CHTTP2_KEEPALIVE_STATE_WAITING, GRPC_CHTTP2_KEEPALIVE_STATE_PINGING, GRPC_CHTTP2_KEEPALIVE_STATE_DYING, } grpc_chttp2_keepalive_state; struct grpc_chttp2_transport { grpc_transport base; /* must be first */ gpr_refcount refs; grpc_endpoint *ep; char *peer_string; grpc_combiner *combiner; /** write execution state of the transport */ grpc_chttp2_write_state write_state; /** is the transport destroying itself? */ uint8_t destroying; /** has the upper layer closed the transport? */ uint8_t closed; /** is there a read request to the endpoint outstanding? */ uint8_t endpoint_reading; /** should we probe bdp? */ bool enable_bdp_probe; /** various lists of streams */ grpc_chttp2_stream_list lists[STREAM_LIST_COUNT]; /** maps stream id to grpc_chttp2_stream objects */ grpc_chttp2_stream_map stream_map; grpc_closure write_action_begin_locked; grpc_closure write_action; grpc_closure write_action_end_locked; grpc_closure read_action_locked; /** incoming read bytes */ grpc_slice_buffer read_buffer; /** address to place a newly accepted stream - set and unset by grpc_chttp2_parsing_accept_stream; used by init_stream to publish the accepted server stream */ grpc_chttp2_stream **accepting_stream; struct { /* accept stream callback */ void (*accept_stream)(grpc_exec_ctx *exec_ctx, void *user_data, grpc_transport *transport, const void *server_data); void *accept_stream_user_data; /** connectivity tracking */ grpc_connectivity_state_tracker state_tracker; } channel_callback; /** data to write now */ grpc_slice_buffer outbuf; /** hpack encoding */ grpc_chttp2_hpack_compressor hpack_compressor; int64_t outgoing_window; /** is this a client? */ uint8_t is_client; /** data to write next write */ grpc_slice_buffer qbuf; /** how much data are we willing to buffer when the WRITE_BUFFER_HINT is set? */ uint32_t write_buffer_size; /** have we seen a goaway */ uint8_t seen_goaway; /** have we sent a goaway */ grpc_chttp2_sent_goaway_state sent_goaway_state; /** are the local settings dirty and need to be sent? */ uint8_t dirtied_local_settings; /** have local settings been sent? */ uint8_t sent_local_settings; /** bitmask of setting indexes to send out */ uint32_t force_send_settings; /** settings values */ uint32_t settings[GRPC_NUM_SETTING_SETS][GRPC_CHTTP2_NUM_SETTINGS]; /** what is the next stream id to be allocated by this peer? copied to next_stream_id in parsing when parsing commences */ uint32_t next_stream_id; /** last new stream id */ uint32_t last_new_stream_id; /** ping queues for various ping insertion points */ grpc_chttp2_ping_queue ping_queues[GRPC_CHTTP2_PING_TYPE_COUNT]; grpc_chttp2_repeated_ping_policy ping_policy; grpc_chttp2_repeated_ping_state ping_state; uint64_t ping_ctr; /* unique id for pings */ grpc_closure retry_initiate_ping_locked; /** ping acks */ size_t ping_ack_count; size_t ping_ack_capacity; uint64_t *ping_acks; grpc_chttp2_server_ping_recv_state ping_recv_state; /** parser for headers */ grpc_chttp2_hpack_parser hpack_parser; /** simple one shot parsers */ union { grpc_chttp2_window_update_parser window_update; grpc_chttp2_settings_parser settings; grpc_chttp2_ping_parser ping; grpc_chttp2_rst_stream_parser rst_stream; } simple; /** parser for goaway frames */ grpc_chttp2_goaway_parser goaway_parser; /** initial window change */ int64_t initial_window_update; /** window available for peer to send to us */ int64_t incoming_window; /** calculating what we should give for incoming window: we track the total amount of flow control over initial window size across all streams: this is data that we want to receive right now (it has an outstanding read) and the total amount of flow control under initial window size across all streams: this is data we've read early we want to adjust incoming_window such that: incoming_window = total_over - max(bdp - total_under, 0) */ int64_t stream_total_over_incoming_window; int64_t stream_total_under_incoming_window; /* deframing */ grpc_chttp2_deframe_transport_state deframe_state; uint8_t incoming_frame_type; uint8_t incoming_frame_flags; uint8_t header_eof; bool is_first_frame; uint32_t expect_continuation_stream_id; uint32_t incoming_frame_size; uint32_t incoming_stream_id; /* active parser */ void *parser_data; grpc_chttp2_stream *incoming_stream; grpc_error *(*parser)(grpc_exec_ctx *exec_ctx, void *parser_user_data, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_slice slice, int is_last); /* goaway data */ grpc_status_code goaway_error; uint32_t goaway_last_stream_index; grpc_slice goaway_text; grpc_chttp2_write_cb *write_cb_pool; /* bdp estimator */ grpc_bdp_estimator bdp_estimator; grpc_pid_controller pid_controller; grpc_closure start_bdp_ping_locked; grpc_closure finish_bdp_ping_locked; gpr_timespec last_pid_update; /* if non-NULL, close the transport with this error when writes are finished */ grpc_error *close_transport_on_writes_finished; /* a list of closures to run after writes are finished */ grpc_closure_list run_after_write; /* buffer pool state */ /** have we scheduled a benign cleanup? */ bool benign_reclaimer_registered; /** have we scheduled a destructive cleanup? */ bool destructive_reclaimer_registered; /** benign cleanup closure */ grpc_closure benign_reclaimer_locked; /** destructive cleanup closure */ grpc_closure destructive_reclaimer_locked; /* keep-alive ping support */ /** Closure to initialize a keepalive ping */ grpc_closure init_keepalive_ping_locked; /** Closure to run when the keepalive ping is sent */ grpc_closure start_keepalive_ping_locked; /** Cousure to run when the keepalive ping ack is received */ grpc_closure finish_keepalive_ping_locked; /** Closrue to run when the keepalive ping timeouts */ grpc_closure keepalive_watchdog_fired_locked; /** timer to initiate ping events */ grpc_timer keepalive_ping_timer; /** watchdog to kill the transport when waiting for the keepalive ping */ grpc_timer keepalive_watchdog_timer; /** time duration in between pings */ gpr_timespec keepalive_time; /** grace period for a ping to complete before watchdog kicks in */ gpr_timespec keepalive_timeout; /** if keepalive pings are allowed when there's no outstanding streams */ bool keepalive_permit_without_calls; /** keep-alive state machine state */ grpc_chttp2_keepalive_state keepalive_state; }; typedef enum { GRPC_METADATA_NOT_PUBLISHED, GRPC_METADATA_SYNTHESIZED_FROM_FAKE, GRPC_METADATA_PUBLISHED_FROM_WIRE, GPRC_METADATA_PUBLISHED_AT_CLOSE } grpc_published_metadata_method; struct grpc_chttp2_stream { grpc_chttp2_transport *t; grpc_stream_refcount *refcount; grpc_closure destroy_stream; grpc_closure *destroy_stream_arg; grpc_chttp2_stream_link links[STREAM_LIST_COUNT]; uint8_t included[STREAM_LIST_COUNT]; /** HTTP2 stream id for this stream, or zero if one has not been assigned */ uint32_t id; /** window available for us to send to peer, over or under the initial window * size of the transport... ie: * outgoing_window = outgoing_window_delta + transport.initial_window_size */ int64_t outgoing_window_delta; /** things the upper layers would like to send */ grpc_metadata_batch *send_initial_metadata; grpc_closure *send_initial_metadata_finished; grpc_metadata_batch *send_trailing_metadata; grpc_closure *send_trailing_metadata_finished; grpc_byte_stream *fetching_send_message; uint32_t fetched_send_message_length; grpc_slice fetching_slice; int64_t next_message_end_offset; int64_t flow_controlled_bytes_written; bool complete_fetch_covered_by_poller; grpc_closure complete_fetch_locked; grpc_closure *fetching_send_message_finished; grpc_metadata_batch *recv_initial_metadata; grpc_closure *recv_initial_metadata_ready; grpc_byte_stream **recv_message; grpc_closure *recv_message_ready; grpc_metadata_batch *recv_trailing_metadata; grpc_closure *recv_trailing_metadata_finished; grpc_transport_stream_stats *collecting_stats; grpc_transport_stream_stats stats; /** number of streams that are currently being read */ gpr_refcount active_streams; /** Is this stream closed for writing. */ bool write_closed; /** Is this stream reading half-closed. */ bool read_closed; /** Are all published incoming byte streams closed. */ bool all_incoming_byte_streams_finished; /** Has this stream seen an error. If true, then pending incoming frames can be thrown away. */ bool seen_error; /** Are we buffering writes on this stream? If yes, we won't become writable until there's enough queued up in the flow_controlled_buffer */ bool write_buffering; /** the error that resulted in this stream being read-closed */ grpc_error *read_closed_error; /** the error that resulted in this stream being write-closed */ grpc_error *write_closed_error; grpc_published_metadata_method published_metadata[2]; bool final_metadata_requested; grpc_chttp2_incoming_metadata_buffer metadata_buffer[2]; grpc_chttp2_incoming_frame_queue incoming_frames; gpr_timespec deadline; /** saw some stream level error */ grpc_error *forced_close_error; /** how many header frames have we received? */ uint8_t header_frames_received; /** window available for peer to send to us (as a delta on * transport.initial_window_size) * incoming_window = incoming_window_delta + transport.initial_window_size */ int64_t incoming_window_delta; /** parsing state for data frames */ grpc_chttp2_data_parser data_parser; /** number of bytes received - reset at end of parse thread execution */ int64_t received_bytes; bool sent_initial_metadata; bool sent_trailing_metadata; /** how much window should we announce? */ uint32_t announce_window; grpc_slice_buffer flow_controlled_buffer; grpc_chttp2_write_cb *on_write_finished_cbs; grpc_chttp2_write_cb *finish_after_write; size_t sending_bytes; }; /** Transport writing call flow: grpc_chttp2_initiate_write() is called anywhere that we know bytes need to go out on the wire. If no other write has been started, a task is enqueued onto our workqueue. When that task executes, it obtains the global lock, and gathers the data to write. The global lock is dropped and we do the syscall to write. After writing, a follow-up check is made to see if another round of writing should be performed. The actual call chain is documented in the implementation of this function. */ void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, bool covered_by_poller, const char *reason); /** Someone is unlocking the transport mutex: check to see if writes are required, and frame them if so */ bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); void grpc_chttp2_end_write(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_error *error); /** Process one slice of incoming data; return 1 if the connection is still viable after reading, or 0 if the connection should be torn down */ grpc_error *grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_slice slice); bool grpc_chttp2_list_add_writable_stream(grpc_chttp2_transport *t, grpc_chttp2_stream *s); /** Get a writable stream returns non-zero if there was a stream available */ bool grpc_chttp2_list_pop_writable_stream(grpc_chttp2_transport *t, grpc_chttp2_stream **s); bool grpc_chttp2_list_remove_writable_stream( grpc_chttp2_transport *t, grpc_chttp2_stream *s) GRPC_MUST_USE_RESULT; bool grpc_chttp2_list_add_writing_stream(grpc_chttp2_transport *t, grpc_chttp2_stream *s); bool grpc_chttp2_list_have_writing_streams(grpc_chttp2_transport *t); bool grpc_chttp2_list_pop_writing_stream(grpc_chttp2_transport *t, grpc_chttp2_stream **s); void grpc_chttp2_list_add_written_stream(grpc_chttp2_transport *t, grpc_chttp2_stream *s); bool grpc_chttp2_list_pop_written_stream(grpc_chttp2_transport *t, grpc_chttp2_stream **s); void grpc_chttp2_list_add_waiting_for_concurrency(grpc_chttp2_transport *t, grpc_chttp2_stream *s); bool grpc_chttp2_list_pop_waiting_for_concurrency(grpc_chttp2_transport *t, grpc_chttp2_stream **s); void grpc_chttp2_list_remove_waiting_for_concurrency(grpc_chttp2_transport *t, grpc_chttp2_stream *s); void grpc_chttp2_list_add_stalled_by_transport(grpc_chttp2_transport *t, grpc_chttp2_stream *s); bool grpc_chttp2_list_pop_stalled_by_transport(grpc_chttp2_transport *t, grpc_chttp2_stream **s); void grpc_chttp2_list_remove_stalled_by_transport(grpc_chttp2_transport *t, grpc_chttp2_stream *s); void grpc_chttp2_list_add_stalled_by_stream(grpc_chttp2_transport *t, grpc_chttp2_stream *s); bool grpc_chttp2_list_pop_stalled_by_stream(grpc_chttp2_transport *t, grpc_chttp2_stream **s); bool grpc_chttp2_list_remove_stalled_by_stream(grpc_chttp2_transport *t, grpc_chttp2_stream *s); grpc_chttp2_stream *grpc_chttp2_parsing_lookup_stream(grpc_chttp2_transport *t, uint32_t id); grpc_chttp2_stream *grpc_chttp2_parsing_accept_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, uint32_t id); void grpc_chttp2_add_incoming_goaway(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, uint32_t goaway_error, grpc_slice goaway_text); void grpc_chttp2_parsing_become_skip_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_closure **pclosure, grpc_error *error, const char *desc); #define GRPC_CHTTP2_CLIENT_CONNECT_STRING "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" #define GRPC_CHTTP2_CLIENT_CONNECT_STRLEN \ (sizeof(GRPC_CHTTP2_CLIENT_CONNECT_STRING) - 1) extern int grpc_http_trace; extern int grpc_flowctl_trace; #define GRPC_CHTTP2_IF_TRACING(stmt) \ if (!(grpc_http_trace)) \ ; \ else \ stmt typedef enum { GRPC_CHTTP2_FLOWCTL_MOVE, GRPC_CHTTP2_FLOWCTL_CREDIT, GRPC_CHTTP2_FLOWCTL_DEBIT } grpc_chttp2_flowctl_op; #define GRPC_CHTTP2_FLOW_MOVE_COMMON(phase, transport, id1, id2, dst_context, \ dst_var, src_context, src_var) \ do { \ assert(id1 == id2); \ if (grpc_flowctl_trace) { \ grpc_chttp2_flowctl_trace( \ __FILE__, __LINE__, phase, GRPC_CHTTP2_FLOWCTL_MOVE, #dst_context, \ #dst_var, #src_context, #src_var, transport->is_client, id1, \ dst_context->dst_var, src_context->src_var); \ } \ dst_context->dst_var += src_context->src_var; \ src_context->src_var = 0; \ } while (0) #define GRPC_CHTTP2_FLOW_MOVE_STREAM(phase, transport, dst_context, dst_var, \ src_context, src_var) \ GRPC_CHTTP2_FLOW_MOVE_COMMON(phase, transport, dst_context->id, \ src_context->id, dst_context, dst_var, \ src_context, src_var) #define GRPC_CHTTP2_FLOW_MOVE_TRANSPORT(phase, dst_context, dst_var, \ src_context, src_var) \ GRPC_CHTTP2_FLOW_MOVE_COMMON(phase, dst_context, 0, 0, dst_context, dst_var, \ src_context, src_var) #define GRPC_CHTTP2_FLOW_CREDIT_COMMON(phase, transport, id, dst_context, \ dst_var, amount) \ do { \ if (grpc_flowctl_trace) { \ grpc_chttp2_flowctl_trace(__FILE__, __LINE__, phase, \ GRPC_CHTTP2_FLOWCTL_CREDIT, #dst_context, \ #dst_var, NULL, #amount, transport->is_client, \ id, dst_context->dst_var, amount); \ } \ dst_context->dst_var += amount; \ } while (0) #define GRPC_CHTTP2_FLOW_CREDIT_STREAM(phase, transport, dst_context, dst_var, \ amount) \ GRPC_CHTTP2_FLOW_CREDIT_COMMON(phase, transport, dst_context->id, \ dst_context, dst_var, amount) #define GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT(phase, dst_context, dst_var, amount) \ GRPC_CHTTP2_FLOW_CREDIT_COMMON(phase, dst_context, 0, dst_context, dst_var, \ amount) #define GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_PREUPDATE( \ phase, transport, dst_context) \ if (dst_context->incoming_window_delta < 0) { \ transport->stream_total_under_incoming_window += \ dst_context->incoming_window_delta; \ } else if (dst_context->incoming_window_delta > 0) { \ transport->stream_total_over_incoming_window -= \ dst_context->incoming_window_delta; \ } #define GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_POSTUPDATE( \ phase, transport, dst_context) \ if (dst_context->incoming_window_delta < 0) { \ transport->stream_total_under_incoming_window -= \ dst_context->incoming_window_delta; \ } else if (dst_context->incoming_window_delta > 0) { \ transport->stream_total_over_incoming_window += \ dst_context->incoming_window_delta; \ } #define GRPC_CHTTP2_FLOW_DEBIT_STREAM_INCOMING_WINDOW_DELTA( \ phase, transport, dst_context, amount) \ GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_PREUPDATE(phase, transport, \ dst_context); \ GRPC_CHTTP2_FLOW_DEBIT_STREAM(phase, transport, dst_context, \ incoming_window_delta, amount); \ GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_POSTUPDATE(phase, transport, \ dst_context); #define GRPC_CHTTP2_FLOW_CREDIT_STREAM_INCOMING_WINDOW_DELTA( \ phase, transport, dst_context, amount) \ GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_PREUPDATE(phase, transport, \ dst_context); \ GRPC_CHTTP2_FLOW_CREDIT_STREAM(phase, transport, dst_context, \ incoming_window_delta, amount); \ GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_POSTUPDATE(phase, transport, \ dst_context); #define GRPC_CHTTP2_FLOW_DEBIT_COMMON(phase, transport, id, dst_context, \ dst_var, amount) \ do { \ if (grpc_flowctl_trace) { \ grpc_chttp2_flowctl_trace(__FILE__, __LINE__, phase, \ GRPC_CHTTP2_FLOWCTL_DEBIT, #dst_context, \ #dst_var, NULL, #amount, transport->is_client, \ id, dst_context->dst_var, amount); \ } \ dst_context->dst_var -= amount; \ } while (0) #define GRPC_CHTTP2_FLOW_DEBIT_STREAM(phase, transport, dst_context, dst_var, \ amount) \ GRPC_CHTTP2_FLOW_DEBIT_COMMON(phase, transport, dst_context->id, \ dst_context, dst_var, amount) #define GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT(phase, dst_context, dst_var, amount) \ GRPC_CHTTP2_FLOW_DEBIT_COMMON(phase, dst_context, 0, dst_context, dst_var, \ amount) void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase, grpc_chttp2_flowctl_op op, const char *context1, const char *var1, const char *context2, const char *var2, int is_client, uint32_t stream_id, int64_t val1, int64_t val2); void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *stream, grpc_error *error); void grpc_chttp2_mark_stream_closed(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, int close_reads, int close_writes, grpc_error *error); void grpc_chttp2_start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); #ifdef GRPC_STREAM_REFCOUNT_DEBUG #define GRPC_CHTTP2_STREAM_REF(stream, reason) \ grpc_chttp2_stream_ref(stream, reason) #define GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream, reason) \ grpc_chttp2_stream_unref(exec_ctx, stream, reason) void grpc_chttp2_stream_ref(grpc_chttp2_stream *s, const char *reason); void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream *s, const char *reason); #else #define GRPC_CHTTP2_STREAM_REF(stream, reason) grpc_chttp2_stream_ref(stream) #define GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream, reason) \ grpc_chttp2_stream_unref(exec_ctx, stream) void grpc_chttp2_stream_ref(grpc_chttp2_stream *s); void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream *s); #endif //#define GRPC_CHTTP2_REFCOUNTING_DEBUG 1 #ifdef GRPC_CHTTP2_REFCOUNTING_DEBUG #define GRPC_CHTTP2_REF_TRANSPORT(t, r) \ grpc_chttp2_ref_transport(t, r, __FILE__, __LINE__) #define GRPC_CHTTP2_UNREF_TRANSPORT(cl, t, r) \ grpc_chttp2_unref_transport(cl, t, r, __FILE__, __LINE__) void grpc_chttp2_unref_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, const char *reason, const char *file, int line); void grpc_chttp2_ref_transport(grpc_chttp2_transport *t, const char *reason, const char *file, int line); #else #define GRPC_CHTTP2_REF_TRANSPORT(t, r) grpc_chttp2_ref_transport(t) #define GRPC_CHTTP2_UNREF_TRANSPORT(cl, t, r) grpc_chttp2_unref_transport(cl, t) void grpc_chttp2_unref_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); void grpc_chttp2_ref_transport(grpc_chttp2_transport *t); #endif grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create( grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, uint32_t frame_size, uint32_t flags); void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, grpc_slice slice); void grpc_chttp2_incoming_byte_stream_finished( grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, grpc_error *error); void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, uint64_t id); /** Add a new ping strike to ping_recv_state.ping_strikes. If ping_recv_state.ping_strikes > ping_policy.max_ping_strikes, it sends GOAWAY with error code ENHANCE_YOUR_CALM and additional debug data resembling “too_many_pings†followed by immediately closing the connection. */ void grpc_chttp2_add_ping_strike(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); typedef enum { /* don't initiate a transport write, but piggyback on the next one */ GRPC_CHTTP2_STREAM_WRITE_PIGGYBACK, /* initiate a covered write */ GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED, /* initiate an uncovered write */ GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED } grpc_chttp2_stream_write_type; /** add a ref to the stream and add it to the writable list; ref will be dropped in writing.c */ void grpc_chttp2_become_writable(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_chttp2_stream_write_type type, const char *reason); void grpc_chttp2_cancel_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_error *due_to_error); void grpc_chttp2_maybe_complete_recv_initial_metadata(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s); void grpc_chttp2_maybe_complete_recv_message(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s); void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s); void grpc_chttp2_fail_pending_writes(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_error *error); uint32_t grpc_chttp2_target_incoming_window(grpc_chttp2_transport *t); /** Set the default keepalive configurations, must only be called at initialization */ void grpc_chttp2_config_default_keepalive_args(grpc_channel_args *args, bool is_client); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INTERNAL_H */ grpc-1.3.2/src/core/ext/transport/chttp2/transport/parsing.c000066400000000000000000000754741310511640000241020ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/transport/internal.h" #include #include #include #include #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/transport/http2_errors.h" #include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/status_conversion.h" #include "src/core/lib/transport/timeout_encoding.h" static grpc_error *init_frame_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); static grpc_error *init_header_frame_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, int is_continuation); static grpc_error *init_data_frame_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); static grpc_error *init_rst_stream_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); static grpc_error *init_settings_frame_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); static grpc_error *init_window_update_frame_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); static grpc_error *init_ping_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); static grpc_error *init_goaway_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); static grpc_error *init_skip_frame_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, int is_header); static grpc_error *parse_frame_slice(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_slice slice, int is_last); grpc_error *grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_slice slice) { uint8_t *beg = GRPC_SLICE_START_PTR(slice); uint8_t *end = GRPC_SLICE_END_PTR(slice); uint8_t *cur = beg; grpc_error *err; if (cur == end) return GRPC_ERROR_NONE; switch (t->deframe_state) { case GRPC_DTS_CLIENT_PREFIX_0: case GRPC_DTS_CLIENT_PREFIX_1: case GRPC_DTS_CLIENT_PREFIX_2: case GRPC_DTS_CLIENT_PREFIX_3: case GRPC_DTS_CLIENT_PREFIX_4: case GRPC_DTS_CLIENT_PREFIX_5: case GRPC_DTS_CLIENT_PREFIX_6: case GRPC_DTS_CLIENT_PREFIX_7: case GRPC_DTS_CLIENT_PREFIX_8: case GRPC_DTS_CLIENT_PREFIX_9: case GRPC_DTS_CLIENT_PREFIX_10: case GRPC_DTS_CLIENT_PREFIX_11: case GRPC_DTS_CLIENT_PREFIX_12: case GRPC_DTS_CLIENT_PREFIX_13: case GRPC_DTS_CLIENT_PREFIX_14: case GRPC_DTS_CLIENT_PREFIX_15: case GRPC_DTS_CLIENT_PREFIX_16: case GRPC_DTS_CLIENT_PREFIX_17: case GRPC_DTS_CLIENT_PREFIX_18: case GRPC_DTS_CLIENT_PREFIX_19: case GRPC_DTS_CLIENT_PREFIX_20: case GRPC_DTS_CLIENT_PREFIX_21: case GRPC_DTS_CLIENT_PREFIX_22: case GRPC_DTS_CLIENT_PREFIX_23: while (cur != end && t->deframe_state != GRPC_DTS_FH_0) { if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[t->deframe_state]) { char *msg; gpr_asprintf( &msg, "Connect string mismatch: expected '%c' (%d) got '%c' (%d) " "at byte %d", GRPC_CHTTP2_CLIENT_CONNECT_STRING[t->deframe_state], (int)(uint8_t)GRPC_CHTTP2_CLIENT_CONNECT_STRING[t->deframe_state], *cur, (int)*cur, t->deframe_state); err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return err; } ++cur; ++t->deframe_state; } if (cur == end) { return GRPC_ERROR_NONE; } /* fallthrough */ dts_fh_0: case GRPC_DTS_FH_0: GPR_ASSERT(cur < end); t->incoming_frame_size = ((uint32_t)*cur) << 16; if (++cur == end) { t->deframe_state = GRPC_DTS_FH_1; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_1: GPR_ASSERT(cur < end); t->incoming_frame_size |= ((uint32_t)*cur) << 8; if (++cur == end) { t->deframe_state = GRPC_DTS_FH_2; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_2: GPR_ASSERT(cur < end); t->incoming_frame_size |= *cur; if (++cur == end) { t->deframe_state = GRPC_DTS_FH_3; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_3: GPR_ASSERT(cur < end); t->incoming_frame_type = *cur; if (++cur == end) { t->deframe_state = GRPC_DTS_FH_4; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_4: GPR_ASSERT(cur < end); t->incoming_frame_flags = *cur; if (++cur == end) { t->deframe_state = GRPC_DTS_FH_5; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_5: GPR_ASSERT(cur < end); t->incoming_stream_id = (((uint32_t)*cur) & 0x7f) << 24; if (++cur == end) { t->deframe_state = GRPC_DTS_FH_6; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_6: GPR_ASSERT(cur < end); t->incoming_stream_id |= ((uint32_t)*cur) << 16; if (++cur == end) { t->deframe_state = GRPC_DTS_FH_7; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_7: GPR_ASSERT(cur < end); t->incoming_stream_id |= ((uint32_t)*cur) << 8; if (++cur == end) { t->deframe_state = GRPC_DTS_FH_8; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_8: GPR_ASSERT(cur < end); t->incoming_stream_id |= ((uint32_t)*cur); t->deframe_state = GRPC_DTS_FRAME; err = init_frame_parser(exec_ctx, t); if (err != GRPC_ERROR_NONE) { return err; } if (t->incoming_frame_size == 0) { err = parse_frame_slice(exec_ctx, t, grpc_empty_slice(), 1); if (err != GRPC_ERROR_NONE) { return err; } t->incoming_stream = NULL; if (++cur == end) { t->deframe_state = GRPC_DTS_FH_0; return GRPC_ERROR_NONE; } goto dts_fh_0; /* loop */ } else if (t->incoming_frame_size > t->settings[GRPC_ACKED_SETTINGS] [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE]) { char *msg; gpr_asprintf(&msg, "Frame size %d is larger than max frame size %d", t->incoming_frame_size, t->settings[GRPC_ACKED_SETTINGS] [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE]); err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return err; } if (++cur == end) { return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FRAME: GPR_ASSERT(cur < end); if ((uint32_t)(end - cur) == t->incoming_frame_size) { err = parse_frame_slice( exec_ctx, t, grpc_slice_sub_no_ref(slice, (size_t)(cur - beg), (size_t)(end - beg)), 1); if (err != GRPC_ERROR_NONE) { return err; } t->deframe_state = GRPC_DTS_FH_0; t->incoming_stream = NULL; return GRPC_ERROR_NONE; } else if ((uint32_t)(end - cur) > t->incoming_frame_size) { size_t cur_offset = (size_t)(cur - beg); err = parse_frame_slice( exec_ctx, t, grpc_slice_sub_no_ref(slice, cur_offset, cur_offset + t->incoming_frame_size), 1); if (err != GRPC_ERROR_NONE) { return err; } cur += t->incoming_frame_size; t->incoming_stream = NULL; goto dts_fh_0; /* loop */ } else { err = parse_frame_slice( exec_ctx, t, grpc_slice_sub_no_ref(slice, (size_t)(cur - beg), (size_t)(end - beg)), 0); if (err != GRPC_ERROR_NONE) { return err; } t->incoming_frame_size -= (uint32_t)(end - cur); return GRPC_ERROR_NONE; } GPR_UNREACHABLE_CODE(return 0); } GPR_UNREACHABLE_CODE(return 0); } static grpc_error *init_frame_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { if (t->is_first_frame && t->incoming_frame_type != GRPC_CHTTP2_FRAME_SETTINGS) { char *msg; gpr_asprintf( &msg, "Expected SETTINGS frame as the first frame, got frame type %d", t->incoming_frame_type); grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return err; } t->is_first_frame = false; if (t->expect_continuation_stream_id != 0) { if (t->incoming_frame_type != GRPC_CHTTP2_FRAME_CONTINUATION) { char *msg; gpr_asprintf(&msg, "Expected CONTINUATION frame, got frame type %02x", t->incoming_frame_type); grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return err; } if (t->expect_continuation_stream_id != t->incoming_stream_id) { char *msg; gpr_asprintf( &msg, "Expected CONTINUATION frame for grpc_chttp2_stream %08x, got " "grpc_chttp2_stream %08x", t->expect_continuation_stream_id, t->incoming_stream_id); grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return err; } return init_header_frame_parser(exec_ctx, t, 1); } switch (t->incoming_frame_type) { case GRPC_CHTTP2_FRAME_DATA: return init_data_frame_parser(exec_ctx, t); case GRPC_CHTTP2_FRAME_HEADER: return init_header_frame_parser(exec_ctx, t, 0); case GRPC_CHTTP2_FRAME_CONTINUATION: return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Unexpected CONTINUATION frame"); case GRPC_CHTTP2_FRAME_RST_STREAM: return init_rst_stream_parser(exec_ctx, t); case GRPC_CHTTP2_FRAME_SETTINGS: return init_settings_frame_parser(exec_ctx, t); case GRPC_CHTTP2_FRAME_WINDOW_UPDATE: return init_window_update_frame_parser(exec_ctx, t); case GRPC_CHTTP2_FRAME_PING: return init_ping_parser(exec_ctx, t); case GRPC_CHTTP2_FRAME_GOAWAY: return init_goaway_parser(exec_ctx, t); default: if (grpc_http_trace) { gpr_log(GPR_ERROR, "Unknown frame type %02x", t->incoming_frame_type); } return init_skip_frame_parser(exec_ctx, t, 0); } } static grpc_error *skip_parser(grpc_exec_ctx *exec_ctx, void *parser, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_slice slice, int is_last) { return GRPC_ERROR_NONE; } static void skip_header(grpc_exec_ctx *exec_ctx, void *tp, grpc_mdelem md) { GRPC_MDELEM_UNREF(exec_ctx, md); } static grpc_error *init_skip_frame_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, int is_header) { if (is_header) { uint8_t is_eoh = t->expect_continuation_stream_id != 0; t->parser = grpc_chttp2_header_parser_parse; t->parser_data = &t->hpack_parser; t->hpack_parser.on_header = skip_header; t->hpack_parser.on_header_user_data = NULL; t->hpack_parser.is_boundary = is_eoh; t->hpack_parser.is_eof = (uint8_t)(is_eoh ? t->header_eof : 0); } else { t->parser = skip_parser; } return GRPC_ERROR_NONE; } void grpc_chttp2_parsing_become_skip_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { init_skip_frame_parser(exec_ctx, t, t->parser == grpc_chttp2_header_parser_parse); } static grpc_error *update_incoming_window(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s) { uint32_t incoming_frame_size = t->incoming_frame_size; if (incoming_frame_size > t->incoming_window) { char *msg; gpr_asprintf(&msg, "frame of size %d overflows incoming window of %" PRId64, t->incoming_frame_size, t->incoming_window); grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return err; } if (s != NULL) { if (incoming_frame_size > s->incoming_window_delta + t->settings[GRPC_ACKED_SETTINGS] [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]) { if (incoming_frame_size <= s->incoming_window_delta + t->settings[GRPC_SENT_SETTINGS] [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]) { gpr_log( GPR_ERROR, "Incoming frame of size %d exceeds incoming window size of %" PRId64 ".\n" "The (un-acked, future) window size would be %" PRId64 " which is not exceeded.\n" "This would usually cause a disconnection, but allowing it due to " "broken HTTP2 implementations in the wild.\n" "See (for example) https://github.com/netty/netty/issues/6520.", t->incoming_frame_size, s->incoming_window_delta + t->settings[GRPC_ACKED_SETTINGS] [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE], s->incoming_window_delta + t->settings[GRPC_SENT_SETTINGS] [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]); } else { char *msg; gpr_asprintf(&msg, "frame of size %d overflows incoming window of %" PRId64, t->incoming_frame_size, s->incoming_window_delta + t->settings[GRPC_ACKED_SETTINGS] [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]); grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return err; } } GRPC_CHTTP2_FLOW_DEBIT_STREAM_INCOMING_WINDOW_DELTA("parse", t, s, incoming_frame_size); if ((int64_t)t->settings[GRPC_SENT_SETTINGS] [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] + (int64_t)s->incoming_window_delta - (int64_t)s->announce_window <= (int64_t)t->settings[GRPC_SENT_SETTINGS] [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] / 2) { grpc_chttp2_become_writable(exec_ctx, t, s, GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED, "window-update-required"); } s->received_bytes += incoming_frame_size; } uint32_t target_incoming_window = grpc_chttp2_target_incoming_window(t); GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("parse", t, incoming_window, incoming_frame_size); if (t->incoming_window <= target_incoming_window / 2) { grpc_chttp2_initiate_write(exec_ctx, t, false, "flow_control"); } return GRPC_ERROR_NONE; } static grpc_error *init_data_frame_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { grpc_chttp2_stream *s = grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id); grpc_error *err = GRPC_ERROR_NONE; err = update_incoming_window(exec_ctx, t, s); if (err != GRPC_ERROR_NONE) { goto error_handler; } if (s == NULL) { return init_skip_frame_parser(exec_ctx, t, 0); } s->stats.incoming.framing_bytes += 9; if (err == GRPC_ERROR_NONE && s->read_closed) { return init_skip_frame_parser(exec_ctx, t, 0); } if (err == GRPC_ERROR_NONE) { err = grpc_chttp2_data_parser_begin_frame(&s->data_parser, t->incoming_frame_flags, s->id); } error_handler: if (err == GRPC_ERROR_NONE) { t->incoming_stream = s; t->parser = grpc_chttp2_data_parser_parse; t->parser_data = &s->data_parser; return GRPC_ERROR_NONE; } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, NULL)) { /* handle stream errors by closing the stream */ if (s != NULL) { grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, false, err); } grpc_slice_buffer_add( &t->qbuf, grpc_chttp2_rst_stream_create(t->incoming_stream_id, GRPC_HTTP2_PROTOCOL_ERROR, &s->stats.outgoing)); return init_skip_frame_parser(exec_ctx, t, 0); } else { return err; } } static void free_timeout(void *p) { gpr_free(p); } static void on_initial_header(grpc_exec_ctx *exec_ctx, void *tp, grpc_mdelem md) { grpc_chttp2_transport *t = tp; grpc_chttp2_stream *s = t->incoming_stream; GPR_TIMER_BEGIN("on_initial_header", 0); GPR_ASSERT(s != NULL); if (grpc_http_trace) { char *key = grpc_slice_to_c_string(GRPC_MDKEY(md)); char *value = grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", s->id, t->is_client ? "CLI" : "SVR", key, value); gpr_free(key); gpr_free(value); } if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) && !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) { /* TODO(ctiller): check for a status like " 0" */ s->seen_error = true; } if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT)) { gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout); gpr_timespec timeout; if (cached_timeout == NULL) { /* not already parsed: parse it now, and store the result away */ cached_timeout = gpr_malloc(sizeof(gpr_timespec)); if (!grpc_http2_decode_timeout(GRPC_MDVALUE(md), cached_timeout)) { char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md)); gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", val); gpr_free(val); *cached_timeout = gpr_inf_future(GPR_TIMESPAN); } timeout = *cached_timeout; grpc_mdelem_set_user_data(md, free_timeout, cached_timeout); } else { timeout = *cached_timeout; } grpc_chttp2_incoming_metadata_buffer_set_deadline( &s->metadata_buffer[0], gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), timeout)); GRPC_MDELEM_UNREF(exec_ctx, md); } else { const size_t new_size = s->metadata_buffer[0].size + GRPC_MDELEM_LENGTH(md); const size_t metadata_size_limit = t->settings[GRPC_ACKED_SETTINGS] [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE]; if (new_size > metadata_size_limit) { gpr_log(GPR_DEBUG, "received initial metadata size exceeds limit (%" PRIuPTR " vs. %" PRIuPTR ")", new_size, metadata_size_limit); grpc_chttp2_cancel_stream( exec_ctx, t, s, grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING( "received initial metadata size exceeds limit"), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED)); grpc_chttp2_parsing_become_skip_parser(exec_ctx, t); s->seen_error = true; GRPC_MDELEM_UNREF(exec_ctx, md); } else { grpc_error *error = grpc_chttp2_incoming_metadata_buffer_add( exec_ctx, &s->metadata_buffer[0], md); if (error != GRPC_ERROR_NONE) { grpc_chttp2_cancel_stream(exec_ctx, t, s, error); grpc_chttp2_parsing_become_skip_parser(exec_ctx, t); s->seen_error = true; GRPC_MDELEM_UNREF(exec_ctx, md); } } } GPR_TIMER_END("on_initial_header", 0); } static void on_trailing_header(grpc_exec_ctx *exec_ctx, void *tp, grpc_mdelem md) { grpc_chttp2_transport *t = tp; grpc_chttp2_stream *s = t->incoming_stream; GPR_TIMER_BEGIN("on_trailing_header", 0); GPR_ASSERT(s != NULL); if (grpc_http_trace) { char *key = grpc_slice_to_c_string(GRPC_MDKEY(md)); char *value = grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_INFO, "HTTP:%d:TRL:%s: %s: %s", s->id, t->is_client ? "CLI" : "SVR", key, value); gpr_free(key); gpr_free(value); } if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) && !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) { /* TODO(ctiller): check for a status like " 0" */ s->seen_error = true; } const size_t new_size = s->metadata_buffer[1].size + GRPC_MDELEM_LENGTH(md); const size_t metadata_size_limit = t->settings[GRPC_ACKED_SETTINGS] [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE]; if (new_size > metadata_size_limit) { gpr_log(GPR_DEBUG, "received trailing metadata size exceeds limit (%" PRIuPTR " vs. %" PRIuPTR ")", new_size, metadata_size_limit); grpc_chttp2_cancel_stream( exec_ctx, t, s, grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "received trailing metadata size exceeds limit"), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED)); grpc_chttp2_parsing_become_skip_parser(exec_ctx, t); s->seen_error = true; GRPC_MDELEM_UNREF(exec_ctx, md); } else { grpc_error *error = grpc_chttp2_incoming_metadata_buffer_add( exec_ctx, &s->metadata_buffer[1], md); if (error != GRPC_ERROR_NONE) { grpc_chttp2_cancel_stream(exec_ctx, t, s, error); grpc_chttp2_parsing_become_skip_parser(exec_ctx, t); s->seen_error = true; GRPC_MDELEM_UNREF(exec_ctx, md); } } GPR_TIMER_END("on_trailing_header", 0); } static grpc_error *init_header_frame_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, int is_continuation) { uint8_t is_eoh = (t->incoming_frame_flags & GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0; grpc_chttp2_stream *s; /* TODO(ctiller): when to increment header_frames_received? */ if (is_eoh) { t->expect_continuation_stream_id = 0; } else { t->expect_continuation_stream_id = t->incoming_stream_id; } if (!is_continuation) { t->header_eof = (t->incoming_frame_flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0; } /* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */ s = grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id); if (s == NULL) { if (is_continuation) { GRPC_CHTTP2_IF_TRACING( gpr_log(GPR_ERROR, "grpc_chttp2_stream disbanded before CONTINUATION received")); return init_skip_frame_parser(exec_ctx, t, 1); } if (t->is_client) { if ((t->incoming_stream_id & 1) && t->incoming_stream_id < t->next_stream_id) { /* this is an old (probably cancelled) grpc_chttp2_stream */ } else { GRPC_CHTTP2_IF_TRACING(gpr_log( GPR_ERROR, "ignoring new grpc_chttp2_stream creation on client")); } return init_skip_frame_parser(exec_ctx, t, 1); } else if (t->last_new_stream_id >= t->incoming_stream_id) { GRPC_CHTTP2_IF_TRACING(gpr_log( GPR_ERROR, "ignoring out of order new grpc_chttp2_stream request on server; " "last grpc_chttp2_stream " "id=%d, new grpc_chttp2_stream id=%d", t->last_new_stream_id, t->incoming_stream_id)); return init_skip_frame_parser(exec_ctx, t, 1); } else if ((t->incoming_stream_id & 1) == 0) { GRPC_CHTTP2_IF_TRACING(gpr_log( GPR_ERROR, "ignoring grpc_chttp2_stream with non-client generated index %d", t->incoming_stream_id)); return init_skip_frame_parser(exec_ctx, t, 1); } t->last_new_stream_id = t->incoming_stream_id; s = t->incoming_stream = grpc_chttp2_parsing_accept_stream(exec_ctx, t, t->incoming_stream_id); if (s == NULL) { GRPC_CHTTP2_IF_TRACING( gpr_log(GPR_ERROR, "grpc_chttp2_stream not accepted")); return init_skip_frame_parser(exec_ctx, t, 1); } } else { t->incoming_stream = s; } GPR_ASSERT(s != NULL); s->stats.incoming.framing_bytes += 9; if (s->read_closed) { GRPC_CHTTP2_IF_TRACING(gpr_log( GPR_ERROR, "skipping already closed grpc_chttp2_stream header")); t->incoming_stream = NULL; return init_skip_frame_parser(exec_ctx, t, 1); } t->parser = grpc_chttp2_header_parser_parse; t->parser_data = &t->hpack_parser; switch (s->header_frames_received) { case 0: t->hpack_parser.on_header = on_initial_header; break; case 1: t->hpack_parser.on_header = on_trailing_header; break; case 2: gpr_log(GPR_ERROR, "too many header frames received"); return init_skip_frame_parser(exec_ctx, t, 1); } t->hpack_parser.on_header_user_data = t; t->hpack_parser.is_boundary = is_eoh; t->hpack_parser.is_eof = (uint8_t)(is_eoh ? t->header_eof : 0); if (!is_continuation && (t->incoming_frame_flags & GRPC_CHTTP2_FLAG_HAS_PRIORITY)) { grpc_chttp2_hpack_parser_set_has_priority(&t->hpack_parser); } return GRPC_ERROR_NONE; } static grpc_error *init_window_update_frame_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { grpc_error *err = grpc_chttp2_window_update_parser_begin_frame( &t->simple.window_update, t->incoming_frame_size, t->incoming_frame_flags); if (err != GRPC_ERROR_NONE) return err; if (t->incoming_stream_id != 0) { grpc_chttp2_stream *s = t->incoming_stream = grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id); if (s == NULL) { return init_skip_frame_parser(exec_ctx, t, 0); } s->stats.incoming.framing_bytes += 9; } t->parser = grpc_chttp2_window_update_parser_parse; t->parser_data = &t->simple.window_update; return GRPC_ERROR_NONE; } static grpc_error *init_ping_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { grpc_error *err = grpc_chttp2_ping_parser_begin_frame( &t->simple.ping, t->incoming_frame_size, t->incoming_frame_flags); if (err != GRPC_ERROR_NONE) return err; t->parser = grpc_chttp2_ping_parser_parse; t->parser_data = &t->simple.ping; return GRPC_ERROR_NONE; } static grpc_error *init_rst_stream_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { grpc_error *err = grpc_chttp2_rst_stream_parser_begin_frame( &t->simple.rst_stream, t->incoming_frame_size, t->incoming_frame_flags); if (err != GRPC_ERROR_NONE) return err; grpc_chttp2_stream *s = t->incoming_stream = grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id); if (!t->incoming_stream) { return init_skip_frame_parser(exec_ctx, t, 0); } s->stats.incoming.framing_bytes += 9; t->parser = grpc_chttp2_rst_stream_parser_parse; t->parser_data = &t->simple.rst_stream; return GRPC_ERROR_NONE; } static grpc_error *init_goaway_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { grpc_error *err = grpc_chttp2_goaway_parser_begin_frame( &t->goaway_parser, t->incoming_frame_size, t->incoming_frame_flags); if (err != GRPC_ERROR_NONE) return err; t->parser = grpc_chttp2_goaway_parser_parse; t->parser_data = &t->goaway_parser; return GRPC_ERROR_NONE; } static grpc_error *init_settings_frame_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { if (t->incoming_stream_id != 0) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Settings frame received for grpc_chttp2_stream"); } grpc_error *err = grpc_chttp2_settings_parser_begin_frame( &t->simple.settings, t->incoming_frame_size, t->incoming_frame_flags, t->settings[GRPC_PEER_SETTINGS]); if (err != GRPC_ERROR_NONE) { return err; } if (t->incoming_frame_flags & GRPC_CHTTP2_FLAG_ACK) { memcpy(t->settings[GRPC_ACKED_SETTINGS], t->settings[GRPC_SENT_SETTINGS], GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t)); grpc_chttp2_hptbl_set_max_bytes( exec_ctx, &t->hpack_parser.table, t->settings[GRPC_ACKED_SETTINGS] [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]); t->sent_local_settings = 0; } t->parser = grpc_chttp2_settings_parser_parse; t->parser_data = &t->simple.settings; return GRPC_ERROR_NONE; } static grpc_error *parse_frame_slice(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_slice slice, int is_last) { grpc_chttp2_stream *s = t->incoming_stream; grpc_error *err = t->parser(exec_ctx, t->parser_data, t, s, slice, is_last); if (err == GRPC_ERROR_NONE) { return err; } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, NULL)) { if (grpc_http_trace) { const char *msg = grpc_error_string(err); gpr_log(GPR_ERROR, "%s", msg); } grpc_chttp2_parsing_become_skip_parser(exec_ctx, t); if (s) { s->forced_close_error = err; grpc_slice_buffer_add( &t->qbuf, grpc_chttp2_rst_stream_create(t->incoming_stream_id, GRPC_HTTP2_PROTOCOL_ERROR, &s->stats.outgoing)); } else { GRPC_ERROR_UNREF(err); } } return err; } grpc-1.3.2/src/core/ext/transport/chttp2/transport/stream_lists.c000066400000000000000000000157351310511640000251420ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/transport/internal.h" #include /* core list management */ static bool stream_list_empty(grpc_chttp2_transport *t, grpc_chttp2_stream_list_id id) { return t->lists[id].head == NULL; } static bool stream_list_pop(grpc_chttp2_transport *t, grpc_chttp2_stream **stream, grpc_chttp2_stream_list_id id) { grpc_chttp2_stream *s = t->lists[id].head; if (s) { grpc_chttp2_stream *new_head = s->links[id].next; GPR_ASSERT(s->included[id]); if (new_head) { t->lists[id].head = new_head; new_head->links[id].prev = NULL; } else { t->lists[id].head = NULL; t->lists[id].tail = NULL; } s->included[id] = 0; } *stream = s; return s != 0; } static void stream_list_remove(grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_chttp2_stream_list_id id) { GPR_ASSERT(s->included[id]); s->included[id] = 0; if (s->links[id].prev) { s->links[id].prev->links[id].next = s->links[id].next; } else { GPR_ASSERT(t->lists[id].head == s); t->lists[id].head = s->links[id].next; } if (s->links[id].next) { s->links[id].next->links[id].prev = s->links[id].prev; } else { t->lists[id].tail = s->links[id].prev; } } static bool stream_list_maybe_remove(grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_chttp2_stream_list_id id) { if (s->included[id]) { stream_list_remove(t, s, id); return true; } else { return false; } } static void stream_list_add_tail(grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_chttp2_stream_list_id id) { grpc_chttp2_stream *old_tail; GPR_ASSERT(!s->included[id]); old_tail = t->lists[id].tail; s->links[id].next = NULL; s->links[id].prev = old_tail; if (old_tail) { old_tail->links[id].next = s; } else { t->lists[id].head = s; } t->lists[id].tail = s; s->included[id] = 1; } static bool stream_list_add(grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_chttp2_stream_list_id id) { if (s->included[id]) { return false; } stream_list_add_tail(t, s, id); return true; } /* wrappers for specializations */ bool grpc_chttp2_list_add_writable_stream(grpc_chttp2_transport *t, grpc_chttp2_stream *s) { GPR_ASSERT(s->id != 0); return stream_list_add(t, s, GRPC_CHTTP2_LIST_WRITABLE); } bool grpc_chttp2_list_pop_writable_stream(grpc_chttp2_transport *t, grpc_chttp2_stream **s) { return stream_list_pop(t, s, GRPC_CHTTP2_LIST_WRITABLE); } bool grpc_chttp2_list_remove_writable_stream(grpc_chttp2_transport *t, grpc_chttp2_stream *s) { return stream_list_maybe_remove(t, s, GRPC_CHTTP2_LIST_WRITABLE); } bool grpc_chttp2_list_add_writing_stream(grpc_chttp2_transport *t, grpc_chttp2_stream *s) { return stream_list_add(t, s, GRPC_CHTTP2_LIST_WRITING); } bool grpc_chttp2_list_have_writing_streams(grpc_chttp2_transport *t) { return !stream_list_empty(t, GRPC_CHTTP2_LIST_WRITING); } bool grpc_chttp2_list_pop_writing_stream(grpc_chttp2_transport *t, grpc_chttp2_stream **s) { return stream_list_pop(t, s, GRPC_CHTTP2_LIST_WRITING); } void grpc_chttp2_list_add_waiting_for_concurrency(grpc_chttp2_transport *t, grpc_chttp2_stream *s) { stream_list_add(t, s, GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY); } bool grpc_chttp2_list_pop_waiting_for_concurrency(grpc_chttp2_transport *t, grpc_chttp2_stream **s) { return stream_list_pop(t, s, GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY); } void grpc_chttp2_list_remove_waiting_for_concurrency(grpc_chttp2_transport *t, grpc_chttp2_stream *s) { stream_list_maybe_remove(t, s, GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY); } void grpc_chttp2_list_add_stalled_by_transport(grpc_chttp2_transport *t, grpc_chttp2_stream *s) { stream_list_add(t, s, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT); } bool grpc_chttp2_list_pop_stalled_by_transport(grpc_chttp2_transport *t, grpc_chttp2_stream **s) { return stream_list_pop(t, s, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT); } void grpc_chttp2_list_remove_stalled_by_transport(grpc_chttp2_transport *t, grpc_chttp2_stream *s) { stream_list_maybe_remove(t, s, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT); } void grpc_chttp2_list_add_stalled_by_stream(grpc_chttp2_transport *t, grpc_chttp2_stream *s) { stream_list_add(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM); } bool grpc_chttp2_list_pop_stalled_by_stream(grpc_chttp2_transport *t, grpc_chttp2_stream **s) { return stream_list_pop(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM); } bool grpc_chttp2_list_remove_stalled_by_stream(grpc_chttp2_transport *t, grpc_chttp2_stream *s) { return stream_list_maybe_remove(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM); } grpc-1.3.2/src/core/ext/transport/chttp2/transport/stream_map.c000066400000000000000000000124671310511640000245600ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/transport/stream_map.h" #include #include #include #include void grpc_chttp2_stream_map_init(grpc_chttp2_stream_map *map, size_t initial_capacity) { GPR_ASSERT(initial_capacity > 1); map->keys = gpr_malloc(sizeof(uint32_t) * initial_capacity); map->values = gpr_malloc(sizeof(void *) * initial_capacity); map->count = 0; map->free = 0; map->capacity = initial_capacity; } void grpc_chttp2_stream_map_destroy(grpc_chttp2_stream_map *map) { gpr_free(map->keys); gpr_free(map->values); } static size_t compact(uint32_t *keys, void **values, size_t count) { size_t i, out; for (i = 0, out = 0; i < count; i++) { if (values[i]) { keys[out] = keys[i]; values[out] = values[i]; out++; } } return out; } void grpc_chttp2_stream_map_add(grpc_chttp2_stream_map *map, uint32_t key, void *value) { size_t count = map->count; size_t capacity = map->capacity; uint32_t *keys = map->keys; void **values = map->values; GPR_ASSERT(count == 0 || keys[count - 1] < key); GPR_ASSERT(value); GPR_ASSERT(grpc_chttp2_stream_map_find(map, key) == NULL); if (count == capacity) { if (map->free > capacity / 4) { count = compact(keys, values, count); map->free = 0; } else { /* resize when less than 25% of the table is free, because compaction won't help much */ map->capacity = capacity = 3 * capacity / 2; map->keys = keys = gpr_realloc(keys, capacity * sizeof(uint32_t)); map->values = values = gpr_realloc(values, capacity * sizeof(void *)); } } keys[count] = key; values[count] = value; map->count = count + 1; } static void **find(grpc_chttp2_stream_map *map, uint32_t key) { size_t min_idx = 0; size_t max_idx = map->count; size_t mid_idx; uint32_t *keys = map->keys; void **values = map->values; uint32_t mid_key; if (max_idx == 0) return NULL; while (min_idx < max_idx) { /* find the midpoint, avoiding overflow */ mid_idx = min_idx + ((max_idx - min_idx) / 2); mid_key = keys[mid_idx]; if (mid_key < key) { min_idx = mid_idx + 1; } else if (mid_key > key) { max_idx = mid_idx; } else /* mid_key == key */ { return &values[mid_idx]; } } return NULL; } void *grpc_chttp2_stream_map_delete(grpc_chttp2_stream_map *map, uint32_t key) { void **pvalue = find(map, key); void *out = NULL; if (pvalue != NULL) { out = *pvalue; *pvalue = NULL; map->free += (out != NULL); /* recognize complete emptyness and ensure we can skip * defragmentation later */ if (map->free == map->count) { map->free = map->count = 0; } GPR_ASSERT(grpc_chttp2_stream_map_find(map, key) == NULL); } return out; } void *grpc_chttp2_stream_map_find(grpc_chttp2_stream_map *map, uint32_t key) { void **pvalue = find(map, key); return pvalue != NULL ? *pvalue : NULL; } size_t grpc_chttp2_stream_map_size(grpc_chttp2_stream_map *map) { return map->count - map->free; } void *grpc_chttp2_stream_map_rand(grpc_chttp2_stream_map *map) { if (map->count == map->free) { return NULL; } if (map->free != 0) { map->count = compact(map->keys, map->values, map->count); map->free = 0; } return map->values[((size_t)rand()) % map->count]; } void grpc_chttp2_stream_map_for_each(grpc_chttp2_stream_map *map, void (*f)(void *user_data, uint32_t key, void *value), void *user_data) { size_t i; for (i = 0; i < map->count; i++) { if (map->values[i]) { f(user_data, map->keys[i], map->values[i]); } } } grpc-1.3.2/src/core/ext/transport/chttp2/transport/stream_map.h000066400000000000000000000067001310511640000245560ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_STREAM_MAP_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_STREAM_MAP_H #include #include /* Data structure to map a uint32_t to a data object (represented by a void*) Represented as a sorted array of keys, and a corresponding array of values. Lookups are performed with binary search. Adds are restricted to strictly higher keys than previously seen (this is guaranteed by http2). */ typedef struct { uint32_t *keys; void **values; size_t count; size_t free; size_t capacity; } grpc_chttp2_stream_map; void grpc_chttp2_stream_map_init(grpc_chttp2_stream_map *map, size_t initial_capacity); void grpc_chttp2_stream_map_destroy(grpc_chttp2_stream_map *map); /* Add a new key: given http2 semantics, new keys must always be greater than existing keys - this is asserted */ void grpc_chttp2_stream_map_add(grpc_chttp2_stream_map *map, uint32_t key, void *value); /* Delete an existing key - returns the previous value of the key if it existed, or NULL otherwise */ void *grpc_chttp2_stream_map_delete(grpc_chttp2_stream_map *map, uint32_t key); /* Return an existing key, or NULL if it does not exist */ void *grpc_chttp2_stream_map_find(grpc_chttp2_stream_map *map, uint32_t key); /* Return a random entry */ void *grpc_chttp2_stream_map_rand(grpc_chttp2_stream_map *map); /* How many (populated) entries are in the stream map? */ size_t grpc_chttp2_stream_map_size(grpc_chttp2_stream_map *map); /* Callback on each stream */ void grpc_chttp2_stream_map_for_each(grpc_chttp2_stream_map *map, void (*f)(void *user_data, uint32_t key, void *value), void *user_data); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_STREAM_MAP_H */ grpc-1.3.2/src/core/ext/transport/chttp2/transport/varint.c000066400000000000000000000046521310511640000237300ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/transport/varint.h" uint32_t grpc_chttp2_hpack_varint_length(uint32_t tail_value) { if (tail_value < (1 << 7)) { return 2; } else if (tail_value < (1 << 14)) { return 3; } else if (tail_value < (1 << 21)) { return 4; } else if (tail_value < (1 << 28)) { return 5; } else { return 6; } } void grpc_chttp2_hpack_write_varint_tail(uint32_t tail_value, uint8_t* target, uint32_t tail_length) { switch (tail_length) { case 5: target[4] = (uint8_t)((tail_value >> 28) | 0x80); case 4: target[3] = (uint8_t)((tail_value >> 21) | 0x80); case 3: target[2] = (uint8_t)((tail_value >> 14) | 0x80); case 2: target[1] = (uint8_t)((tail_value >> 7) | 0x80); case 1: target[0] = (uint8_t)((tail_value) | 0x80); } target[tail_length - 1] &= 0x7f; } grpc-1.3.2/src/core/ext/transport/chttp2/transport/varint.h000066400000000000000000000070541310511640000237340ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_VARINT_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_VARINT_H #include /* Helpers for hpack varint encoding */ /* length of a value that needs varint tail encoding (it's bigger than can be bitpacked into the opcode byte) - returned value includes the length of the opcode byte */ uint32_t grpc_chttp2_hpack_varint_length(uint32_t tail_value); void grpc_chttp2_hpack_write_varint_tail(uint32_t tail_value, uint8_t* target, uint32_t tail_length); /* maximum value that can be bitpacked with the opcode if the opcode has a prefix of length prefix_bits */ #define GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits) \ ((uint32_t)((1 << (8 - (prefix_bits))) - 1)) /* length required to bitpack a value */ #define GRPC_CHTTP2_VARINT_LENGTH(n, prefix_bits) \ ((n) < GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits) \ ? 1u \ : grpc_chttp2_hpack_varint_length( \ (n)-GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits))) #define GRPC_CHTTP2_WRITE_VARINT(n, prefix_bits, prefix_or, target, length) \ do { \ uint8_t* tgt = target; \ if ((length) == 1u) { \ (tgt)[0] = (uint8_t)((prefix_or) | (n)); \ } else { \ (tgt)[0] = \ (prefix_or) | (uint8_t)GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits); \ grpc_chttp2_hpack_write_varint_tail( \ (n)-GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits), (tgt) + 1, (length)-1); \ } \ } while (0) #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_VARINT_H */ grpc-1.3.2/src/core/ext/transport/chttp2/transport/writing.c000066400000000000000000000432301310511640000241030ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/ext/transport/chttp2/transport/internal.h" #include #include #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/transport/http2_errors.h" static void add_to_write_list(grpc_chttp2_write_cb **list, grpc_chttp2_write_cb *cb) { cb->next = *list; *list = cb; } static void finish_write_cb(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_chttp2_write_cb *cb, grpc_error *error) { grpc_chttp2_complete_closure_step(exec_ctx, t, s, &cb->closure, error, "finish_write_cb"); cb->next = t->write_cb_pool; t->write_cb_pool = cb; } static void collapse_pings_from_into(grpc_chttp2_transport *t, grpc_chttp2_ping_type ping_type, grpc_chttp2_ping_queue *pq) { for (size_t i = 0; i < GRPC_CHTTP2_PCL_COUNT; i++) { grpc_closure_list_move(&t->ping_queues[ping_type].lists[i], &pq->lists[i]); } } static void maybe_initiate_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_ping_type ping_type) { grpc_chttp2_ping_queue *pq = &t->ping_queues[ping_type]; if (grpc_closure_list_empty(pq->lists[GRPC_CHTTP2_PCL_NEXT])) { /* no ping needed: wait */ return; } if (!grpc_closure_list_empty(pq->lists[GRPC_CHTTP2_PCL_INFLIGHT])) { /* ping already in-flight: wait */ if (grpc_http_trace || grpc_bdp_estimator_trace) { gpr_log(GPR_DEBUG, "Ping delayed [%p]: already pinging", t->peer_string); } return; } if (t->ping_state.pings_before_data_required == 0 && t->ping_policy.max_pings_without_data != 0) { /* need to send something of substance before sending a ping again */ if (grpc_http_trace || grpc_bdp_estimator_trace) { gpr_log(GPR_DEBUG, "Ping delayed [%p]: too many recent pings: %d/%d", t->peer_string, t->ping_state.pings_before_data_required, t->ping_policy.max_pings_without_data); } return; } gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); gpr_timespec elapsed = gpr_time_sub(now, t->ping_state.last_ping_sent_time); /*gpr_log(GPR_DEBUG, "elapsed:%d.%09d min:%d.%09d", (int)elapsed.tv_sec, elapsed.tv_nsec, (int)t->ping_policy.min_time_between_pings.tv_sec, (int)t->ping_policy.min_time_between_pings.tv_nsec);*/ if (gpr_time_cmp(elapsed, t->ping_policy.min_time_between_pings) < 0) { /* not enough elapsed time between successive pings */ if (grpc_http_trace || grpc_bdp_estimator_trace) { gpr_log(GPR_DEBUG, "Ping delayed [%p]: not enough time elapsed since last ping", t->peer_string); } if (!t->ping_state.is_delayed_ping_timer_set) { t->ping_state.is_delayed_ping_timer_set = true; grpc_timer_init(exec_ctx, &t->ping_state.delayed_ping_timer, gpr_time_add(t->ping_state.last_ping_sent_time, t->ping_policy.min_time_between_pings), &t->retry_initiate_ping_locked, gpr_now(GPR_CLOCK_MONOTONIC)); } return; } /* coalesce equivalent pings into this one */ switch (ping_type) { case GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE: collapse_pings_from_into(t, GRPC_CHTTP2_PING_ON_NEXT_WRITE, pq); break; case GRPC_CHTTP2_PING_ON_NEXT_WRITE: break; case GRPC_CHTTP2_PING_TYPE_COUNT: GPR_UNREACHABLE_CODE(break); } pq->inflight_id = t->ping_ctr * GRPC_CHTTP2_PING_TYPE_COUNT + ping_type; t->ping_ctr++; grpc_closure_list_sched(exec_ctx, &pq->lists[GRPC_CHTTP2_PCL_INITIATE]); grpc_closure_list_move(&pq->lists[GRPC_CHTTP2_PCL_NEXT], &pq->lists[GRPC_CHTTP2_PCL_INFLIGHT]); grpc_slice_buffer_add(&t->outbuf, grpc_chttp2_ping_create(false, pq->inflight_id)); t->ping_state.last_ping_sent_time = now; t->ping_state.pings_before_data_required -= (t->ping_state.pings_before_data_required != 0); } static void update_list(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, int64_t send_bytes, grpc_chttp2_write_cb **list, grpc_error *error) { grpc_chttp2_write_cb *cb = *list; *list = NULL; s->flow_controlled_bytes_written += send_bytes; while (cb) { grpc_chttp2_write_cb *next = cb->next; if (cb->call_at_byte <= s->flow_controlled_bytes_written) { finish_write_cb(exec_ctx, t, s, cb, GRPC_ERROR_REF(error)); } else { add_to_write_list(list, cb); } cb = next; } GRPC_ERROR_UNREF(error); } static bool stream_ref_if_not_destroyed(gpr_refcount *r) { gpr_atm count; do { count = gpr_atm_acq_load(&r->count); if (count == 0) return false; } while (!gpr_atm_rel_cas(&r->count, count, count + 1)); return true; } uint32_t grpc_chttp2_target_incoming_window(grpc_chttp2_transport *t) { return (uint32_t)GPR_MAX( (int64_t)((1u << 31) - 1), t->stream_total_over_incoming_window + (int64_t)GPR_MAX( t->settings[GRPC_SENT_SETTINGS] [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] - t->stream_total_under_incoming_window, 0)); } bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { grpc_chttp2_stream *s; GPR_TIMER_BEGIN("grpc_chttp2_begin_write", 0); if (t->dirtied_local_settings && !t->sent_local_settings) { grpc_slice_buffer_add( &t->outbuf, grpc_chttp2_settings_create( t->settings[GRPC_SENT_SETTINGS], t->settings[GRPC_LOCAL_SETTINGS], t->force_send_settings, GRPC_CHTTP2_NUM_SETTINGS)); t->force_send_settings = 0; t->dirtied_local_settings = 0; t->sent_local_settings = 1; } /* simple writes are queued to qbuf, and flushed here */ grpc_slice_buffer_move_into(&t->qbuf, &t->outbuf); GPR_ASSERT(t->qbuf.count == 0); grpc_chttp2_hpack_compressor_set_max_table_size( &t->hpack_compressor, t->settings[GRPC_PEER_SETTINGS][GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]); if (t->outgoing_window > 0) { while (grpc_chttp2_list_pop_stalled_by_transport(t, &s)) { if (!t->closed && grpc_chttp2_list_add_writable_stream(t, s) && stream_ref_if_not_destroyed(&s->refcount->refs)) { grpc_chttp2_initiate_write(exec_ctx, t, false, "transport.read_flow_control"); } } } /* for each grpc_chttp2_stream that's become writable, frame it's data (according to available window sizes) and add to the output buffer */ while (grpc_chttp2_list_pop_writable_stream(t, &s)) { bool sent_initial_metadata = s->sent_initial_metadata; bool now_writing = false; GRPC_CHTTP2_IF_TRACING(gpr_log( GPR_DEBUG, "W:%p %s[%d] im-(sent,send)=(%d,%d) announce=%d", t, t->is_client ? "CLIENT" : "SERVER", s->id, sent_initial_metadata, s->send_initial_metadata != NULL, s->announce_window)); /* send initial metadata if it's available */ if (!sent_initial_metadata && s->send_initial_metadata) { grpc_encode_header_options hopt = { .stream_id = s->id, .is_eof = false, .use_true_binary_metadata = t->settings [GRPC_PEER_SETTINGS] [GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA] != 0, .max_frame_size = t->settings[GRPC_PEER_SETTINGS] [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE], .stats = &s->stats.outgoing}; grpc_chttp2_encode_header(exec_ctx, &t->hpack_compressor, s->send_initial_metadata, &hopt, &t->outbuf); s->send_initial_metadata = NULL; s->sent_initial_metadata = true; sent_initial_metadata = true; now_writing = true; t->ping_state.pings_before_data_required = t->ping_policy.max_pings_without_data; if (!t->is_client) { t->ping_recv_state.last_ping_recv_time = gpr_inf_past(GPR_CLOCK_MONOTONIC); t->ping_recv_state.ping_strikes = 0; } } /* send any window updates */ if (s->announce_window > 0) { uint32_t announce = s->announce_window; grpc_slice_buffer_add(&t->outbuf, grpc_chttp2_window_update_create( s->id, s->announce_window, &s->stats.outgoing)); t->ping_state.pings_before_data_required = t->ping_policy.max_pings_without_data; if (!t->is_client) { t->ping_recv_state.last_ping_recv_time = gpr_inf_past(GPR_CLOCK_MONOTONIC); t->ping_recv_state.ping_strikes = 0; } GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", t, s, announce_window, announce); } if (sent_initial_metadata) { /* send any body bytes, if allowed by flow control */ if (s->flow_controlled_buffer.length > 0) { uint32_t stream_outgoing_window = (uint32_t)GPR_MAX( 0, s->outgoing_window_delta + (int64_t)t->settings[GRPC_PEER_SETTINGS] [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]); uint32_t max_outgoing = (uint32_t)GPR_MIN( t->settings[GRPC_PEER_SETTINGS] [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE], GPR_MIN(stream_outgoing_window, t->outgoing_window)); if (max_outgoing > 0) { uint32_t send_bytes = (uint32_t)GPR_MIN(max_outgoing, s->flow_controlled_buffer.length); bool is_last_data_frame = s->fetching_send_message == NULL && send_bytes == s->flow_controlled_buffer.length; bool is_last_frame = is_last_data_frame && s->send_trailing_metadata != NULL && grpc_metadata_batch_is_empty(s->send_trailing_metadata); grpc_chttp2_encode_data(s->id, &s->flow_controlled_buffer, send_bytes, is_last_frame, &s->stats.outgoing, &t->outbuf); GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", t, s, outgoing_window_delta, send_bytes); GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("write", t, outgoing_window, send_bytes); t->ping_state.pings_before_data_required = t->ping_policy.max_pings_without_data; if (!t->is_client) { t->ping_recv_state.last_ping_recv_time = gpr_inf_past(GPR_CLOCK_MONOTONIC); t->ping_recv_state.ping_strikes = 0; } if (is_last_frame) { s->send_trailing_metadata = NULL; s->sent_trailing_metadata = true; if (!t->is_client && !s->read_closed) { grpc_slice_buffer_add(&t->outbuf, grpc_chttp2_rst_stream_create( s->id, GRPC_HTTP2_NO_ERROR, &s->stats.outgoing)); } } s->sending_bytes += send_bytes; now_writing = true; if (s->flow_controlled_buffer.length > 0) { GRPC_CHTTP2_STREAM_REF(s, "chttp2_writing:fork"); grpc_chttp2_list_add_writable_stream(t, s); } } else if (t->outgoing_window == 0) { grpc_chttp2_list_add_stalled_by_transport(t, s); now_writing = true; } else if (stream_outgoing_window == 0) { grpc_chttp2_list_add_stalled_by_stream(t, s); now_writing = true; } } if (s->send_trailing_metadata != NULL && s->fetching_send_message == NULL && s->flow_controlled_buffer.length == 0) { if (grpc_metadata_batch_is_empty(s->send_trailing_metadata)) { grpc_chttp2_encode_data(s->id, &s->flow_controlled_buffer, 0, true, &s->stats.outgoing, &t->outbuf); } else { grpc_encode_header_options hopt = { .stream_id = s->id, .is_eof = true, .use_true_binary_metadata = t->settings [GRPC_PEER_SETTINGS] [GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA] != 0, .max_frame_size = t->settings[GRPC_PEER_SETTINGS] [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE], .stats = &s->stats.outgoing}; grpc_chttp2_encode_header(exec_ctx, &t->hpack_compressor, s->send_trailing_metadata, &hopt, &t->outbuf); } s->send_trailing_metadata = NULL; s->sent_trailing_metadata = true; if (!t->is_client && !s->read_closed) { grpc_slice_buffer_add( &t->outbuf, grpc_chttp2_rst_stream_create( s->id, GRPC_HTTP2_NO_ERROR, &s->stats.outgoing)); } now_writing = true; } } if (now_writing) { if (!grpc_chttp2_list_add_writing_stream(t, s)) { /* already in writing list: drop ref */ GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2_writing:already_writing"); } } else { GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2_writing:no_write"); } } /* if the grpc_chttp2_transport is ready to send a window update, do so here also; 3/4 is a magic number that will likely get tuned soon */ uint32_t target_incoming_window = grpc_chttp2_target_incoming_window(t); uint32_t threshold_to_send_transport_window_update = t->outbuf.count > 0 ? 3 * target_incoming_window / 4 : target_incoming_window / 2; if (t->incoming_window <= threshold_to_send_transport_window_update && t->incoming_window != target_incoming_window) { maybe_initiate_ping(exec_ctx, t, GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE); uint32_t announced = (uint32_t)GPR_CLAMP( target_incoming_window - t->incoming_window, 0, UINT32_MAX); GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("write", t, incoming_window, announced); grpc_transport_one_way_stats throwaway_stats; grpc_slice_buffer_add(&t->outbuf, grpc_chttp2_window_update_create( 0, announced, &throwaway_stats)); t->ping_state.pings_before_data_required = t->ping_policy.max_pings_without_data; if (!t->is_client) { t->ping_recv_state.last_ping_recv_time = gpr_inf_past(GPR_CLOCK_MONOTONIC); t->ping_recv_state.ping_strikes = 0; } } for (size_t i = 0; i < t->ping_ack_count; i++) { grpc_slice_buffer_add(&t->outbuf, grpc_chttp2_ping_create(1, t->ping_acks[i])); } t->ping_ack_count = 0; maybe_initiate_ping(exec_ctx, t, GRPC_CHTTP2_PING_ON_NEXT_WRITE); GPR_TIMER_END("grpc_chttp2_begin_write", 0); return t->outbuf.count > 0; } void grpc_chttp2_end_write(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_error *error) { GPR_TIMER_BEGIN("grpc_chttp2_end_write", 0); grpc_chttp2_stream *s; while (grpc_chttp2_list_pop_writing_stream(t, &s)) { if (s->sent_initial_metadata) { grpc_chttp2_complete_closure_step( exec_ctx, t, s, &s->send_initial_metadata_finished, GRPC_ERROR_REF(error), "send_initial_metadata_finished"); } if (s->sending_bytes != 0) { update_list(exec_ctx, t, s, (int64_t)s->sending_bytes, &s->on_write_finished_cbs, GRPC_ERROR_REF(error)); s->sending_bytes = 0; } if (s->sent_trailing_metadata) { grpc_chttp2_complete_closure_step( exec_ctx, t, s, &s->send_trailing_metadata_finished, GRPC_ERROR_REF(error), "send_trailing_metadata_finished"); grpc_chttp2_mark_stream_closed(exec_ctx, t, s, !t->is_client, 1, GRPC_ERROR_REF(error)); } GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2_writing:end"); } grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &t->outbuf); GRPC_ERROR_UNREF(error); GPR_TIMER_END("grpc_chttp2_end_write", 0); } grpc-1.3.2/src/core/ext/transport/cronet/000077500000000000000000000000001310511640000203045ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/transport/cronet/client/000077500000000000000000000000001310511640000215625ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/transport/cronet/client/secure/000077500000000000000000000000001310511640000230505ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c000066400000000000000000000051171310511640000275250ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include "src/core/ext/transport/cronet/transport/cronet_transport.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/transport/transport_impl.h" // Cronet transport object typedef struct cronet_transport { grpc_transport base; // must be first element in this structure void *engine; char *host; } cronet_transport; extern grpc_transport_vtable grpc_cronet_vtable; GRPCAPI grpc_channel *grpc_cronet_secure_channel_create( void *engine, const char *target, const grpc_channel_args *args, void *reserved) { gpr_log(GPR_DEBUG, "grpc_create_cronet_transport: stream_engine = %p, target=%s", engine, target); grpc_transport *ct = grpc_create_cronet_transport(engine, target, args, reserved); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; return grpc_channel_create(&exec_ctx, target, args, GRPC_CLIENT_DIRECT_CHANNEL, ct); } grpc-1.3.2/src/core/ext/transport/cronet/transport/000077500000000000000000000000001310511640000223405ustar00rootroot00000000000000grpc-1.3.2/src/core/ext/transport/cronet/transport/cronet_api_dummy.c000066400000000000000000000065441310511640000260530ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* This file has empty implementation of all the functions exposed by the cronet library, so we can build it in all environments */ #include #include #include "third_party/objective_c/Cronet/bidirectional_stream_c.h" #ifdef GRPC_COMPILE_WITH_CRONET /* link with the real CRONET library in the build system */ #else /* Dummy implementation of cronet API just to test for build-ability */ bidirectional_stream* bidirectional_stream_create( stream_engine* engine, void* annotation, bidirectional_stream_callback* callback) { GPR_ASSERT(0); return NULL; } int bidirectional_stream_destroy(bidirectional_stream* stream) { GPR_ASSERT(0); return 0; } int bidirectional_stream_start(bidirectional_stream* stream, const char* url, int priority, const char* method, const bidirectional_stream_header_array* headers, bool end_of_stream) { GPR_ASSERT(0); return 0; } int bidirectional_stream_read(bidirectional_stream* stream, char* buffer, int capacity) { GPR_ASSERT(0); return 0; } int bidirectional_stream_write(bidirectional_stream* stream, const char* buffer, int count, bool end_of_stream) { GPR_ASSERT(0); return 0; } void bidirectional_stream_cancel(bidirectional_stream* stream) { GPR_ASSERT(0); } void bidirectional_stream_disable_auto_flush(bidirectional_stream* stream, bool disable_auto_flush) { GPR_ASSERT(0); } void bidirectional_stream_delay_request_headers_until_flush( bidirectional_stream* stream, bool delay_headers_until_flush) { GPR_ASSERT(0); } void bidirectional_stream_flush(bidirectional_stream* stream) { GPR_ASSERT(0); } #endif /* GRPC_COMPILE_WITH_CRONET */ grpc-1.3.2/src/core/ext/transport/cronet/transport/cronet_transport.c000066400000000000000000001540431310511640000261210ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include "src/core/ext/transport/chttp2/transport/incoming_metadata.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/string.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/transport/metadata_batch.h" #include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/transport_impl.h" #include "third_party/objective_c/Cronet/bidirectional_stream_c.h" #define GRPC_HEADER_SIZE_IN_BYTES 5 #define GRPC_FLUSH_READ_SIZE 4096 #define CRONET_LOG(...) \ do { \ if (grpc_cronet_trace) gpr_log(__VA_ARGS__); \ } while (0) /* TODO (makdharma): Hook up into the wider tracing mechanism */ int grpc_cronet_trace = 0; enum e_op_result { ACTION_TAKEN_WITH_CALLBACK, ACTION_TAKEN_NO_CALLBACK, NO_ACTION_POSSIBLE }; enum e_op_id { OP_SEND_INITIAL_METADATA = 0, OP_SEND_MESSAGE, OP_SEND_TRAILING_METADATA, OP_RECV_MESSAGE, OP_RECV_INITIAL_METADATA, OP_RECV_TRAILING_METADATA, OP_CANCEL_ERROR, OP_ON_COMPLETE, OP_FAILED, OP_SUCCEEDED, OP_CANCELED, OP_RECV_MESSAGE_AND_ON_COMPLETE, OP_READ_REQ_MADE, OP_NUM_OPS }; /* Cronet callbacks. See cronet_c_for_grpc.h for documentation for each. */ static void on_stream_ready(bidirectional_stream *); static void on_response_headers_received( bidirectional_stream *, const bidirectional_stream_header_array *, const char *); static void on_write_completed(bidirectional_stream *, const char *); static void on_read_completed(bidirectional_stream *, char *, int); static void on_response_trailers_received( bidirectional_stream *, const bidirectional_stream_header_array *); static void on_succeeded(bidirectional_stream *); static void on_failed(bidirectional_stream *, int); static void on_canceled(bidirectional_stream *); static bidirectional_stream_callback cronet_callbacks = { on_stream_ready, on_response_headers_received, on_read_completed, on_write_completed, on_response_trailers_received, on_succeeded, on_failed, on_canceled}; /* Cronet transport object */ struct grpc_cronet_transport { grpc_transport base; /* must be first element in this structure */ stream_engine *engine; char *host; bool use_packet_coalescing; }; typedef struct grpc_cronet_transport grpc_cronet_transport; /* TODO (makdharma): reorder structure for memory efficiency per http://www.catb.org/esr/structure-packing/#_structure_reordering: */ struct read_state { /* vars to store data coming from server */ char *read_buffer; bool length_field_received; int received_bytes; int remaining_bytes; int length_field; bool compressed; char grpc_header_bytes[GRPC_HEADER_SIZE_IN_BYTES]; char *payload_field; bool read_stream_closed; /* vars for holding data destined for the application */ struct grpc_slice_buffer_stream sbs; grpc_slice_buffer read_slice_buffer; /* vars for trailing metadata */ grpc_chttp2_incoming_metadata_buffer trailing_metadata; bool trailing_metadata_valid; /* vars for initial metadata */ grpc_chttp2_incoming_metadata_buffer initial_metadata; }; struct write_state { char *write_buffer; }; /* track state of one stream op */ struct op_state { bool state_op_done[OP_NUM_OPS]; bool state_callback_received[OP_NUM_OPS]; /* A non-zero gRPC status code has been seen */ bool fail_state; /* Transport is discarding all buffered messages */ bool flush_read; bool flush_cronet_when_ready; bool pending_write_for_trailer; bool pending_send_message; /* User requested RECV_TRAILING_METADATA */ bool pending_recv_trailing_metadata; /* Cronet has not issued a callback of a bidirectional read */ bool pending_read_from_cronet; grpc_error *cancel_error; /* data structure for storing data coming from server */ struct read_state rs; /* data structure for storing data going to the server */ struct write_state ws; }; struct op_and_state { grpc_transport_stream_op_batch op; struct op_state state; bool done; struct stream_obj *s; /* Pointer back to the stream object */ struct op_and_state *next; /* next op_and_state in the linked list */ }; struct op_storage { int num_pending_ops; struct op_and_state *head; }; struct stream_obj { gpr_arena *arena; struct op_and_state *oas; grpc_transport_stream_op_batch *curr_op; grpc_cronet_transport *curr_ct; grpc_stream *curr_gs; bidirectional_stream *cbs; bidirectional_stream_header_array header_array; /* Stream level state. Some state will be tracked both at stream and stream_op * level */ struct op_state state; /* OP storage */ struct op_storage storage; /* Mutex to protect storage */ gpr_mu mu; }; typedef struct stream_obj stream_obj; static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, struct op_and_state *oas); /* Utility function to translate enum into string for printing */ static const char *op_result_string(enum e_op_result i) { switch (i) { case ACTION_TAKEN_WITH_CALLBACK: return "ACTION_TAKEN_WITH_CALLBACK"; case ACTION_TAKEN_NO_CALLBACK: return "ACTION_TAKEN_NO_CALLBACK"; case NO_ACTION_POSSIBLE: return "NO_ACTION_POSSIBLE"; } GPR_UNREACHABLE_CODE(return "UNKNOWN"); } static const char *op_id_string(enum e_op_id i) { switch (i) { case OP_SEND_INITIAL_METADATA: return "OP_SEND_INITIAL_METADATA"; case OP_SEND_MESSAGE: return "OP_SEND_MESSAGE"; case OP_SEND_TRAILING_METADATA: return "OP_SEND_TRAILING_METADATA"; case OP_RECV_MESSAGE: return "OP_RECV_MESSAGE"; case OP_RECV_INITIAL_METADATA: return "OP_RECV_INITIAL_METADATA"; case OP_RECV_TRAILING_METADATA: return "OP_RECV_TRAILING_METADATA"; case OP_CANCEL_ERROR: return "OP_CANCEL_ERROR"; case OP_ON_COMPLETE: return "OP_ON_COMPLETE"; case OP_FAILED: return "OP_FAILED"; case OP_SUCCEEDED: return "OP_SUCCEEDED"; case OP_CANCELED: return "OP_CANCELED"; case OP_RECV_MESSAGE_AND_ON_COMPLETE: return "OP_RECV_MESSAGE_AND_ON_COMPLETE"; case OP_READ_REQ_MADE: return "OP_READ_REQ_MADE"; case OP_NUM_OPS: return "OP_NUM_OPS"; } return "UNKNOWN"; } static void null_and_maybe_free_read_buffer(stream_obj *s) { if (s->state.rs.read_buffer && s->state.rs.read_buffer != s->state.rs.grpc_header_bytes) { gpr_free(s->state.rs.read_buffer); } s->state.rs.read_buffer = NULL; } static void maybe_flush_read(stream_obj *s) { /* To enter flush read state (discarding all the buffered messages in * transport layer), two conditions must be satisfied: 1) non-zero grpc status * has been received, and 2) an op requesting the status code * (RECV_TRAILING_METADATA) is issued by the user. (See * doc/status_ordering.md) */ /* Whenever the evaluation of any of the two condition is changed, we check * whether we should enter the flush read state. */ if (s->state.pending_recv_trailing_metadata && s->state.fail_state) { if (!s->state.flush_read && !s->state.rs.read_stream_closed) { CRONET_LOG(GPR_DEBUG, "%p: Flush read", s); s->state.flush_read = true; null_and_maybe_free_read_buffer(s); s->state.rs.read_buffer = gpr_malloc(GRPC_FLUSH_READ_SIZE); if (!s->state.pending_read_from_cronet) { CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); bidirectional_stream_read(s->cbs, s->state.rs.read_buffer, GRPC_FLUSH_READ_SIZE); s->state.pending_read_from_cronet = true; } } } } static grpc_error *make_error_with_desc(int error_code, const char *desc) { grpc_error *error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(desc); error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, error_code); return error; } /* Add a new stream op to op storage. */ static void add_to_storage(struct stream_obj *s, grpc_transport_stream_op_batch *op) { struct op_storage *storage = &s->storage; /* add new op at the beginning of the linked list. The memory is freed in remove_from_storage */ struct op_and_state *new_op = gpr_malloc(sizeof(struct op_and_state)); memcpy(&new_op->op, op, sizeof(grpc_transport_stream_op_batch)); memset(&new_op->state, 0, sizeof(new_op->state)); new_op->s = s; new_op->done = false; gpr_mu_lock(&s->mu); new_op->next = storage->head; storage->head = new_op; storage->num_pending_ops++; if (op->send_message) { s->state.pending_send_message = true; } if (op->recv_trailing_metadata) { s->state.pending_recv_trailing_metadata = true; maybe_flush_read(s); } CRONET_LOG(GPR_DEBUG, "adding new op %p. %d in the queue.", new_op, storage->num_pending_ops); gpr_mu_unlock(&s->mu); } /* Traverse the linked list and delete op and free memory */ static void remove_from_storage(struct stream_obj *s, struct op_and_state *oas) { struct op_and_state *curr; if (s->storage.head == NULL || oas == NULL) { return; } if (s->storage.head == oas) { s->storage.head = oas->next; gpr_free(oas); s->storage.num_pending_ops--; CRONET_LOG(GPR_DEBUG, "Freed %p. Now %d in the queue", oas, s->storage.num_pending_ops); } else { for (curr = s->storage.head; curr != NULL; curr = curr->next) { if (curr->next == oas) { curr->next = oas->next; s->storage.num_pending_ops--; CRONET_LOG(GPR_DEBUG, "Freed %p. Now %d in the queue", oas, s->storage.num_pending_ops); gpr_free(oas); break; } else if (curr->next == NULL) { CRONET_LOG(GPR_ERROR, "Reached end of LL and did not find op to free"); } } } } /* Cycle through ops and try to take next action. Break when either an action with callback is taken, or no action is possible. This can get executed from the Cronet network thread via cronet callback or on the application supplied thread via the perform_stream_op function. */ static void execute_from_storage(stream_obj *s) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; gpr_mu_lock(&s->mu); for (struct op_and_state *curr = s->storage.head; curr != NULL;) { CRONET_LOG(GPR_DEBUG, "calling op at %p. done = %d", curr, curr->done); GPR_ASSERT(curr->done == 0); enum e_op_result result = execute_stream_op(&exec_ctx, curr); CRONET_LOG(GPR_DEBUG, "execute_stream_op[%p] returns %s", curr, op_result_string(result)); /* if this op is done, then remove it and free memory */ if (curr->done) { struct op_and_state *next = curr->next; remove_from_storage(s, curr); curr = next; } /* continue processing the same op if ACTION_TAKEN_WITHOUT_CALLBACK */ if (result == NO_ACTION_POSSIBLE) { curr = curr->next; } else if (result == ACTION_TAKEN_WITH_CALLBACK) { break; } } gpr_mu_unlock(&s->mu); grpc_exec_ctx_finish(&exec_ctx); } /* Cronet callback */ static void on_failed(bidirectional_stream *stream, int net_error) { CRONET_LOG(GPR_DEBUG, "on_failed(%p, %d)", stream, net_error); stream_obj *s = (stream_obj *)stream->annotation; gpr_mu_lock(&s->mu); bidirectional_stream_destroy(s->cbs); s->state.state_callback_received[OP_FAILED] = true; s->cbs = NULL; if (s->header_array.headers) { gpr_free(s->header_array.headers); s->header_array.headers = NULL; } if (s->state.ws.write_buffer) { gpr_free(s->state.ws.write_buffer); s->state.ws.write_buffer = NULL; } null_and_maybe_free_read_buffer(s); gpr_mu_unlock(&s->mu); execute_from_storage(s); } /* Cronet callback */ static void on_canceled(bidirectional_stream *stream) { CRONET_LOG(GPR_DEBUG, "on_canceled(%p)", stream); stream_obj *s = (stream_obj *)stream->annotation; gpr_mu_lock(&s->mu); bidirectional_stream_destroy(s->cbs); s->state.state_callback_received[OP_CANCELED] = true; s->cbs = NULL; if (s->header_array.headers) { gpr_free(s->header_array.headers); s->header_array.headers = NULL; } if (s->state.ws.write_buffer) { gpr_free(s->state.ws.write_buffer); s->state.ws.write_buffer = NULL; } null_and_maybe_free_read_buffer(s); gpr_mu_unlock(&s->mu); execute_from_storage(s); } /* Cronet callback */ static void on_succeeded(bidirectional_stream *stream) { CRONET_LOG(GPR_DEBUG, "on_succeeded(%p)", stream); stream_obj *s = (stream_obj *)stream->annotation; gpr_mu_lock(&s->mu); bidirectional_stream_destroy(s->cbs); s->state.state_callback_received[OP_SUCCEEDED] = true; s->cbs = NULL; null_and_maybe_free_read_buffer(s); gpr_mu_unlock(&s->mu); execute_from_storage(s); } /* Cronet callback */ static void on_stream_ready(bidirectional_stream *stream) { CRONET_LOG(GPR_DEBUG, "W: on_stream_ready(%p)", stream); stream_obj *s = (stream_obj *)stream->annotation; grpc_cronet_transport *t = (grpc_cronet_transport *)s->curr_ct; gpr_mu_lock(&s->mu); s->state.state_op_done[OP_SEND_INITIAL_METADATA] = true; s->state.state_callback_received[OP_SEND_INITIAL_METADATA] = true; /* Free the memory allocated for headers */ if (s->header_array.headers) { gpr_free(s->header_array.headers); s->header_array.headers = NULL; } /* Send the initial metadata on wire if there is no SEND_MESSAGE or * SEND_TRAILING_METADATA ops pending */ if (t->use_packet_coalescing) { if (s->state.flush_cronet_when_ready) { CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_flush (%p)", s->cbs); bidirectional_stream_flush(stream); } } gpr_mu_unlock(&s->mu); execute_from_storage(s); } /* Cronet callback */ static void on_response_headers_received( bidirectional_stream *stream, const bidirectional_stream_header_array *headers, const char *negotiated_protocol) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; CRONET_LOG(GPR_DEBUG, "R: on_response_headers_received(%p, %p, %s)", stream, headers, negotiated_protocol); stream_obj *s = (stream_obj *)stream->annotation; /* Identify if this is a header or a trailer (in a trailer-only response case) */ for (size_t i = 0; i < headers->count; i++) { if (0 == strcmp("grpc-status", headers->headers[i].key)) { on_response_trailers_received(stream, headers); return; } } gpr_mu_lock(&s->mu); memset(&s->state.rs.initial_metadata, 0, sizeof(s->state.rs.initial_metadata)); grpc_chttp2_incoming_metadata_buffer_init(&s->state.rs.initial_metadata, s->arena); for (size_t i = 0; i < headers->count; i++) { GRPC_LOG_IF_ERROR( "on_response_headers_received", grpc_chttp2_incoming_metadata_buffer_add( &exec_ctx, &s->state.rs.initial_metadata, grpc_mdelem_from_slices( &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string( headers->headers[i].key)), grpc_slice_intern(grpc_slice_from_static_string( headers->headers[i].value))))); } s->state.state_callback_received[OP_RECV_INITIAL_METADATA] = true; if (!(s->state.state_op_done[OP_CANCEL_ERROR] || s->state.state_callback_received[OP_FAILED])) { /* Do an extra read to trigger on_succeeded() callback in case connection is closed */ GPR_ASSERT(s->state.rs.length_field_received == false); s->state.rs.read_buffer = s->state.rs.grpc_header_bytes; s->state.rs.compressed = false; s->state.rs.received_bytes = 0; s->state.rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES; CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); bidirectional_stream_read(s->cbs, s->state.rs.read_buffer, s->state.rs.remaining_bytes); s->state.pending_read_from_cronet = true; } gpr_mu_unlock(&s->mu); grpc_exec_ctx_finish(&exec_ctx); execute_from_storage(s); } /* Cronet callback */ static void on_write_completed(bidirectional_stream *stream, const char *data) { stream_obj *s = (stream_obj *)stream->annotation; CRONET_LOG(GPR_DEBUG, "W: on_write_completed(%p, %s)", stream, data); gpr_mu_lock(&s->mu); if (s->state.ws.write_buffer) { gpr_free(s->state.ws.write_buffer); s->state.ws.write_buffer = NULL; } s->state.state_callback_received[OP_SEND_MESSAGE] = true; gpr_mu_unlock(&s->mu); execute_from_storage(s); } /* Cronet callback */ static void on_read_completed(bidirectional_stream *stream, char *data, int count) { stream_obj *s = (stream_obj *)stream->annotation; CRONET_LOG(GPR_DEBUG, "R: on_read_completed(%p, %p, %d)", stream, data, count); gpr_mu_lock(&s->mu); s->state.pending_read_from_cronet = false; s->state.state_callback_received[OP_RECV_MESSAGE] = true; if (count > 0 && s->state.flush_read) { CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); bidirectional_stream_read(s->cbs, s->state.rs.read_buffer, GRPC_FLUSH_READ_SIZE); s->state.pending_read_from_cronet = true; gpr_mu_unlock(&s->mu); } else if (count > 0) { s->state.rs.received_bytes += count; s->state.rs.remaining_bytes -= count; if (s->state.rs.remaining_bytes > 0) { CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); s->state.state_op_done[OP_READ_REQ_MADE] = true; bidirectional_stream_read( s->cbs, s->state.rs.read_buffer + s->state.rs.received_bytes, s->state.rs.remaining_bytes); s->state.pending_read_from_cronet = true; gpr_mu_unlock(&s->mu); } else { gpr_mu_unlock(&s->mu); execute_from_storage(s); } } else { null_and_maybe_free_read_buffer(s); s->state.rs.read_stream_closed = true; gpr_mu_unlock(&s->mu); execute_from_storage(s); } } /* Cronet callback */ static void on_response_trailers_received( bidirectional_stream *stream, const bidirectional_stream_header_array *trailers) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; CRONET_LOG(GPR_DEBUG, "R: on_response_trailers_received(%p,%p)", stream, trailers); stream_obj *s = (stream_obj *)stream->annotation; grpc_cronet_transport *t = (grpc_cronet_transport *)s->curr_ct; gpr_mu_lock(&s->mu); memset(&s->state.rs.trailing_metadata, 0, sizeof(s->state.rs.trailing_metadata)); s->state.rs.trailing_metadata_valid = false; grpc_chttp2_incoming_metadata_buffer_init(&s->state.rs.trailing_metadata, s->arena); for (size_t i = 0; i < trailers->count; i++) { CRONET_LOG(GPR_DEBUG, "trailer key=%s, value=%s", trailers->headers[i].key, trailers->headers[i].value); GRPC_LOG_IF_ERROR( "on_response_trailers_received", grpc_chttp2_incoming_metadata_buffer_add( &exec_ctx, &s->state.rs.trailing_metadata, grpc_mdelem_from_slices( &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string( trailers->headers[i].key)), grpc_slice_intern(grpc_slice_from_static_string( trailers->headers[i].value))))); s->state.rs.trailing_metadata_valid = true; if (0 == strcmp(trailers->headers[i].key, "grpc-status") && 0 != strcmp(trailers->headers[i].value, "0")) { s->state.fail_state = true; maybe_flush_read(s); } } s->state.state_callback_received[OP_RECV_TRAILING_METADATA] = true; /* Send a EOS when server terminates the stream (testServerFinishesRequest) to * trigger on_succeeded */ if (!s->state.state_op_done[OP_SEND_TRAILING_METADATA] && !(s->state.state_op_done[OP_CANCEL_ERROR] || s->state.state_callback_received[OP_FAILED])) { CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, 0)", s->cbs); s->state.state_callback_received[OP_SEND_MESSAGE] = false; bidirectional_stream_write(s->cbs, "", 0, true); if (t->use_packet_coalescing) { CRONET_LOG(GPR_DEBUG, "bidirectional_stream_flush (%p)", s->cbs); bidirectional_stream_flush(s->cbs); } s->state.state_op_done[OP_SEND_TRAILING_METADATA] = true; gpr_mu_unlock(&s->mu); grpc_exec_ctx_finish(&exec_ctx); } else { gpr_mu_unlock(&s->mu); grpc_exec_ctx_finish(&exec_ctx); execute_from_storage(s); } } /* Utility function that takes the data from s->write_slice_buffer and assembles into a contiguous byte stream with 5 byte gRPC header prepended. */ static void create_grpc_frame(grpc_slice_buffer *write_slice_buffer, char **pp_write_buffer, size_t *p_write_buffer_size, uint32_t flags) { grpc_slice slice = grpc_slice_buffer_take_first(write_slice_buffer); size_t length = GRPC_SLICE_LENGTH(slice); *p_write_buffer_size = length + GRPC_HEADER_SIZE_IN_BYTES; /* This is freed in the on_write_completed callback */ char *write_buffer = gpr_malloc(length + GRPC_HEADER_SIZE_IN_BYTES); *pp_write_buffer = write_buffer; uint8_t *p = (uint8_t *)write_buffer; /* Append 5 byte header */ /* Compressed flag */ *p++ = (flags & GRPC_WRITE_INTERNAL_COMPRESS) ? 1 : 0; /* Message length */ *p++ = (uint8_t)(length >> 24); *p++ = (uint8_t)(length >> 16); *p++ = (uint8_t)(length >> 8); *p++ = (uint8_t)(length); /* append actual data */ memcpy(p, GRPC_SLICE_START_PTR(slice), length); } /* Convert metadata in a format that Cronet can consume */ static void convert_metadata_to_cronet_headers( grpc_linked_mdelem *head, const char *host, char **pp_url, bidirectional_stream_header **pp_headers, size_t *p_num_headers, const char **method) { grpc_linked_mdelem *curr = head; /* Walk the linked list and get number of header fields */ size_t num_headers_available = 0; while (curr != NULL) { curr = curr->next; num_headers_available++; } /* Allocate enough memory. It is freed in the on_stream_ready callback */ bidirectional_stream_header *headers = (bidirectional_stream_header *)gpr_malloc( sizeof(bidirectional_stream_header) * num_headers_available); *pp_headers = headers; /* Walk the linked list again, this time copying the header fields. s->num_headers can be less than num_headers_available, as some headers are not used for cronet. TODO (makdharma): Eliminate need to traverse the LL second time for perf. */ curr = head; size_t num_headers = 0; while (num_headers < num_headers_available) { grpc_mdelem mdelem = curr->md; curr = curr->next; char *key = grpc_slice_to_c_string(GRPC_MDKEY(mdelem)); char *value = grpc_slice_to_c_string(GRPC_MDVALUE(mdelem)); if (grpc_slice_eq(GRPC_MDKEY(mdelem), GRPC_MDSTR_SCHEME) || grpc_slice_eq(GRPC_MDKEY(mdelem), GRPC_MDSTR_AUTHORITY)) { /* Cronet populates these fields on its own */ gpr_free(key); gpr_free(value); continue; } if (grpc_slice_eq(GRPC_MDKEY(mdelem), GRPC_MDSTR_METHOD)) { if (grpc_slice_eq(GRPC_MDVALUE(mdelem), GRPC_MDSTR_PUT)) { *method = "PUT"; } else { /* POST method in default*/ *method = "POST"; } gpr_free(key); gpr_free(value); continue; } if (grpc_slice_eq(GRPC_MDKEY(mdelem), GRPC_MDSTR_PATH)) { /* Create URL by appending :path value to the hostname */ gpr_asprintf(pp_url, "https://%s%s", host, value); gpr_free(key); gpr_free(value); continue; } CRONET_LOG(GPR_DEBUG, "header %s = %s", key, value); headers[num_headers].key = key; headers[num_headers].value = value; num_headers++; if (curr == NULL) { break; } } *p_num_headers = (size_t)num_headers; } static void parse_grpc_header(const uint8_t *data, int *length, bool *compressed) { const uint8_t c = *data; const uint8_t *p = data + 1; *compressed = ((c & 0x01) == 0x01); *length = 0; *length |= ((uint8_t)*p++) << 24; *length |= ((uint8_t)*p++) << 16; *length |= ((uint8_t)*p++) << 8; *length |= ((uint8_t)*p++); } static bool header_has_authority(grpc_linked_mdelem *head) { while (head != NULL) { if (grpc_slice_eq(GRPC_MDKEY(head->md), GRPC_MDSTR_AUTHORITY)) { return true; } head = head->next; } return false; } /* Op Execution: Decide if one of the actions contained in the stream op can be executed. This is the heart of the state machine. */ static bool op_can_be_run(grpc_transport_stream_op_batch *curr_op, struct stream_obj *s, struct op_state *op_state, enum e_op_id op_id) { struct op_state *stream_state = &s->state; grpc_cronet_transport *t = s->curr_ct; bool result = true; /* When call is canceled, every op can be run, except under following conditions */ bool is_canceled_or_failed = stream_state->state_op_done[OP_CANCEL_ERROR] || stream_state->state_callback_received[OP_FAILED]; if (is_canceled_or_failed) { if (op_id == OP_SEND_INITIAL_METADATA) result = false; if (op_id == OP_SEND_MESSAGE) result = false; if (op_id == OP_SEND_TRAILING_METADATA) result = false; if (op_id == OP_CANCEL_ERROR) result = false; /* already executed */ if (op_id == OP_RECV_INITIAL_METADATA && stream_state->state_op_done[OP_RECV_INITIAL_METADATA]) result = false; if (op_id == OP_RECV_MESSAGE && stream_state->state_op_done[OP_RECV_MESSAGE]) result = false; if (op_id == OP_RECV_TRAILING_METADATA && stream_state->state_op_done[OP_RECV_TRAILING_METADATA]) result = false; } else if (op_id == OP_SEND_INITIAL_METADATA) { /* already executed */ if (stream_state->state_op_done[OP_SEND_INITIAL_METADATA]) result = false; } else if (op_id == OP_RECV_INITIAL_METADATA) { /* already executed */ if (stream_state->state_op_done[OP_RECV_INITIAL_METADATA]) result = false; /* we haven't sent headers yet. */ else if (!stream_state->state_callback_received[OP_SEND_INITIAL_METADATA]) result = false; /* we haven't received headers yet. */ else if (!stream_state->state_callback_received[OP_RECV_INITIAL_METADATA] && !stream_state->state_op_done[OP_RECV_TRAILING_METADATA]) result = false; } else if (op_id == OP_SEND_MESSAGE) { /* already executed (note we're checking op specific state, not stream state) */ if (op_state->state_op_done[OP_SEND_MESSAGE]) result = false; /* we haven't sent headers yet. */ else if (!stream_state->state_callback_received[OP_SEND_INITIAL_METADATA]) result = false; } else if (op_id == OP_RECV_MESSAGE) { /* already executed */ if (op_state->state_op_done[OP_RECV_MESSAGE]) result = false; /* we haven't received headers yet. */ else if (!stream_state->state_callback_received[OP_RECV_INITIAL_METADATA] && !stream_state->state_op_done[OP_RECV_TRAILING_METADATA]) result = false; } else if (op_id == OP_RECV_TRAILING_METADATA) { /* already executed */ if (stream_state->state_op_done[OP_RECV_TRAILING_METADATA]) result = false; /* we have asked for but haven't received message yet. */ else if (stream_state->state_op_done[OP_READ_REQ_MADE] && !stream_state->state_op_done[OP_RECV_MESSAGE]) result = false; /* we haven't received trailers yet. */ else if (!stream_state->state_callback_received[OP_RECV_TRAILING_METADATA]) result = false; /* we haven't received on_succeeded yet. */ else if (!stream_state->state_callback_received[OP_SUCCEEDED]) result = false; } else if (op_id == OP_SEND_TRAILING_METADATA) { /* already executed */ if (stream_state->state_op_done[OP_SEND_TRAILING_METADATA]) result = false; /* we haven't sent initial metadata yet */ else if (!stream_state->state_callback_received[OP_SEND_INITIAL_METADATA]) result = false; /* we haven't sent message yet */ else if (stream_state->pending_send_message && !stream_state->state_op_done[OP_SEND_MESSAGE]) result = false; /* we haven't got on_write_completed for the send yet */ else if (stream_state->state_op_done[OP_SEND_MESSAGE] && !stream_state->state_callback_received[OP_SEND_MESSAGE] && !(t->use_packet_coalescing && stream_state->pending_write_for_trailer)) result = false; } else if (op_id == OP_CANCEL_ERROR) { /* already executed */ if (stream_state->state_op_done[OP_CANCEL_ERROR]) result = false; } else if (op_id == OP_ON_COMPLETE) { /* already executed (note we're checking op specific state, not stream state) */ if (op_state->state_op_done[OP_ON_COMPLETE]) { CRONET_LOG(GPR_DEBUG, "Because"); result = false; } /* Check if every op that was asked for is done. */ else if (curr_op->send_initial_metadata && !stream_state->state_callback_received[OP_SEND_INITIAL_METADATA]) { CRONET_LOG(GPR_DEBUG, "Because"); result = false; } else if (curr_op->send_message && !op_state->state_op_done[OP_SEND_MESSAGE]) { CRONET_LOG(GPR_DEBUG, "Because"); result = false; } else if (curr_op->send_message && !stream_state->state_callback_received[OP_SEND_MESSAGE]) { CRONET_LOG(GPR_DEBUG, "Because"); result = false; } else if (curr_op->send_trailing_metadata && !stream_state->state_op_done[OP_SEND_TRAILING_METADATA]) { CRONET_LOG(GPR_DEBUG, "Because"); result = false; } else if (curr_op->recv_initial_metadata && !stream_state->state_op_done[OP_RECV_INITIAL_METADATA]) { CRONET_LOG(GPR_DEBUG, "Because"); result = false; } else if (curr_op->recv_message && !stream_state->state_op_done[OP_RECV_MESSAGE]) { CRONET_LOG(GPR_DEBUG, "Because"); result = false; } else if (curr_op->recv_trailing_metadata) { /* We aren't done with trailing metadata yet */ if (!stream_state->state_op_done[OP_RECV_TRAILING_METADATA]) { CRONET_LOG(GPR_DEBUG, "Because"); result = false; } /* We've asked for actual message in an earlier op, and it hasn't been delivered yet. */ else if (stream_state->state_op_done[OP_READ_REQ_MADE]) { /* If this op is not the one asking for read, (which means some earlier op has asked), and the read hasn't been delivered. */ if (!curr_op->recv_message && !stream_state->state_callback_received[OP_SUCCEEDED]) { CRONET_LOG(GPR_DEBUG, "Because"); result = false; } } } /* We should see at least one on_write_completed for the trailers that we sent */ else if (curr_op->send_trailing_metadata && !stream_state->state_callback_received[OP_SEND_MESSAGE]) result = false; } CRONET_LOG(GPR_DEBUG, "op_can_be_run %s : %s", op_id_string(op_id), result ? "YES" : "NO"); return result; } /* TODO (makdharma): Break down this function in smaller chunks for readability. */ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, struct op_and_state *oas) { grpc_transport_stream_op_batch *stream_op = &oas->op; struct stream_obj *s = oas->s; grpc_cronet_transport *t = (grpc_cronet_transport *)s->curr_ct; struct op_state *stream_state = &s->state; enum e_op_result result = NO_ACTION_POSSIBLE; if (stream_op->send_initial_metadata && op_can_be_run(stream_op, s, &oas->state, OP_SEND_INITIAL_METADATA)) { CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_INITIAL_METADATA", oas); /* Start new cronet stream. It is destroyed in on_succeeded, on_canceled, * on_failed */ GPR_ASSERT(s->cbs == NULL); GPR_ASSERT(!stream_state->state_op_done[OP_SEND_INITIAL_METADATA]); s->cbs = bidirectional_stream_create(t->engine, s->curr_gs, &cronet_callbacks); CRONET_LOG(GPR_DEBUG, "%p = bidirectional_stream_create()", s->cbs); if (t->use_packet_coalescing) { bidirectional_stream_disable_auto_flush(s->cbs, true); bidirectional_stream_delay_request_headers_until_flush(s->cbs, true); } char *url = NULL; const char *method = "POST"; s->header_array.headers = NULL; convert_metadata_to_cronet_headers(stream_op->payload->send_initial_metadata .send_initial_metadata->list.head, t->host, &url, &s->header_array.headers, &s->header_array.count, &method); s->header_array.capacity = s->header_array.count; CRONET_LOG(GPR_DEBUG, "bidirectional_stream_start(%p, %s)", s->cbs, url); bidirectional_stream_start(s->cbs, url, 0, method, &s->header_array, false); unsigned int header_index; for (header_index = 0; header_index < s->header_array.count; header_index++) { gpr_free((void *)s->header_array.headers[header_index].key); gpr_free((void *)s->header_array.headers[header_index].value); } stream_state->state_op_done[OP_SEND_INITIAL_METADATA] = true; if (t->use_packet_coalescing) { if (!stream_op->send_message && !stream_op->send_trailing_metadata) { s->state.flush_cronet_when_ready = true; } } result = ACTION_TAKEN_WITH_CALLBACK; } else if (stream_op->send_message && op_can_be_run(stream_op, s, &oas->state, OP_SEND_MESSAGE)) { CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_MESSAGE", oas); stream_state->pending_send_message = false; if (stream_state->state_callback_received[OP_FAILED]) { result = NO_ACTION_POSSIBLE; CRONET_LOG(GPR_DEBUG, "Stream is either cancelled or failed."); } else { grpc_slice_buffer write_slice_buffer; grpc_slice slice; grpc_slice_buffer_init(&write_slice_buffer); grpc_byte_stream_next( NULL, stream_op->payload->send_message.send_message, &slice, stream_op->payload->send_message.send_message->length, NULL); grpc_slice_buffer_add(&write_slice_buffer, slice); if (write_slice_buffer.count != 1) { /* Empty request not handled yet */ gpr_log(GPR_ERROR, "Empty request is not supported"); GPR_ASSERT(write_slice_buffer.count == 1); } if (write_slice_buffer.count > 0) { size_t write_buffer_size; create_grpc_frame(&write_slice_buffer, &stream_state->ws.write_buffer, &write_buffer_size, stream_op->payload->send_message.send_message->flags); CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, %p)", s->cbs, stream_state->ws.write_buffer); stream_state->state_callback_received[OP_SEND_MESSAGE] = false; bidirectional_stream_write(s->cbs, stream_state->ws.write_buffer, (int)write_buffer_size, false); if (t->use_packet_coalescing) { if (!stream_op->send_trailing_metadata) { CRONET_LOG(GPR_DEBUG, "bidirectional_stream_flush (%p)", s->cbs); bidirectional_stream_flush(s->cbs); result = ACTION_TAKEN_WITH_CALLBACK; } else { stream_state->pending_write_for_trailer = true; result = ACTION_TAKEN_NO_CALLBACK; } } else { result = ACTION_TAKEN_WITH_CALLBACK; } } else { result = NO_ACTION_POSSIBLE; } } stream_state->state_op_done[OP_SEND_MESSAGE] = true; oas->state.state_op_done[OP_SEND_MESSAGE] = true; } else if (stream_op->send_trailing_metadata && op_can_be_run(stream_op, s, &oas->state, OP_SEND_TRAILING_METADATA)) { CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_TRAILING_METADATA", oas); if (stream_state->state_callback_received[OP_FAILED]) { result = NO_ACTION_POSSIBLE; CRONET_LOG(GPR_DEBUG, "Stream is either cancelled or failed."); } else { CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, 0)", s->cbs); stream_state->state_callback_received[OP_SEND_MESSAGE] = false; bidirectional_stream_write(s->cbs, "", 0, true); if (t->use_packet_coalescing) { CRONET_LOG(GPR_DEBUG, "bidirectional_stream_flush (%p)", s->cbs); bidirectional_stream_flush(s->cbs); } result = ACTION_TAKEN_WITH_CALLBACK; } stream_state->state_op_done[OP_SEND_TRAILING_METADATA] = true; } else if (stream_op->recv_initial_metadata && op_can_be_run(stream_op, s, &oas->state, OP_RECV_INITIAL_METADATA)) { CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_INITIAL_METADATA", oas); if (stream_state->state_op_done[OP_CANCEL_ERROR]) { grpc_closure_sched( exec_ctx, stream_op->payload->recv_initial_metadata.recv_initial_metadata_ready, GRPC_ERROR_NONE); } else if (stream_state->state_callback_received[OP_FAILED]) { grpc_closure_sched( exec_ctx, stream_op->payload->recv_initial_metadata.recv_initial_metadata_ready, GRPC_ERROR_NONE); } else if (stream_state->state_op_done[OP_RECV_TRAILING_METADATA]) { grpc_closure_sched( exec_ctx, stream_op->payload->recv_initial_metadata.recv_initial_metadata_ready, GRPC_ERROR_NONE); } else { grpc_chttp2_incoming_metadata_buffer_publish( exec_ctx, &oas->s->state.rs.initial_metadata, stream_op->payload->recv_initial_metadata.recv_initial_metadata); grpc_closure_sched( exec_ctx, stream_op->payload->recv_initial_metadata.recv_initial_metadata_ready, GRPC_ERROR_NONE); } stream_state->state_op_done[OP_RECV_INITIAL_METADATA] = true; result = ACTION_TAKEN_NO_CALLBACK; } else if (stream_op->recv_message && op_can_be_run(stream_op, s, &oas->state, OP_RECV_MESSAGE)) { CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_MESSAGE", oas); if (stream_state->state_op_done[OP_CANCEL_ERROR]) { CRONET_LOG(GPR_DEBUG, "Stream is cancelled."); grpc_closure_sched(exec_ctx, stream_op->payload->recv_message.recv_message_ready, GRPC_ERROR_NONE); stream_state->state_op_done[OP_RECV_MESSAGE] = true; result = ACTION_TAKEN_NO_CALLBACK; } else if (stream_state->state_callback_received[OP_FAILED]) { CRONET_LOG(GPR_DEBUG, "Stream failed."); grpc_closure_sched(exec_ctx, stream_op->payload->recv_message.recv_message_ready, GRPC_ERROR_NONE); stream_state->state_op_done[OP_RECV_MESSAGE] = true; result = ACTION_TAKEN_NO_CALLBACK; } else if (stream_state->rs.read_stream_closed == true) { /* No more data will be received */ CRONET_LOG(GPR_DEBUG, "read stream closed"); grpc_closure_sched(exec_ctx, stream_op->payload->recv_message.recv_message_ready, GRPC_ERROR_NONE); stream_state->state_op_done[OP_RECV_MESSAGE] = true; oas->state.state_op_done[OP_RECV_MESSAGE] = true; result = ACTION_TAKEN_NO_CALLBACK; } else if (stream_state->flush_read) { CRONET_LOG(GPR_DEBUG, "flush read"); grpc_closure_sched(exec_ctx, stream_op->payload->recv_message.recv_message_ready, GRPC_ERROR_NONE); stream_state->state_op_done[OP_RECV_MESSAGE] = true; oas->state.state_op_done[OP_RECV_MESSAGE] = true; result = ACTION_TAKEN_NO_CALLBACK; } else if (stream_state->rs.length_field_received == false) { if (stream_state->rs.received_bytes == GRPC_HEADER_SIZE_IN_BYTES && stream_state->rs.remaining_bytes == 0) { /* Start a read operation for data */ stream_state->rs.length_field_received = true; parse_grpc_header((const uint8_t *)stream_state->rs.read_buffer, &stream_state->rs.length_field, &stream_state->rs.compressed); CRONET_LOG(GPR_DEBUG, "length field = %d", stream_state->rs.length_field); if (stream_state->rs.length_field > 0) { stream_state->rs.read_buffer = gpr_malloc((size_t)stream_state->rs.length_field); GPR_ASSERT(stream_state->rs.read_buffer); stream_state->rs.remaining_bytes = stream_state->rs.length_field; stream_state->rs.received_bytes = 0; CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); stream_state->state_op_done[OP_READ_REQ_MADE] = true; /* Indicates that at least one read request has been made */ bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer, stream_state->rs.remaining_bytes); stream_state->pending_read_from_cronet = true; result = ACTION_TAKEN_WITH_CALLBACK; } else { stream_state->rs.remaining_bytes = 0; CRONET_LOG(GPR_DEBUG, "read operation complete. Empty response."); grpc_slice_buffer_init(&stream_state->rs.read_slice_buffer); grpc_slice_buffer_stream_init(&stream_state->rs.sbs, &stream_state->rs.read_slice_buffer, 0); if (stream_state->rs.compressed) { stream_state->rs.sbs.base.flags |= GRPC_WRITE_INTERNAL_COMPRESS; } *((grpc_byte_buffer **) stream_op->payload->recv_message.recv_message) = (grpc_byte_buffer *)&stream_state->rs.sbs; grpc_closure_sched( exec_ctx, stream_op->payload->recv_message.recv_message_ready, GRPC_ERROR_NONE); stream_state->state_op_done[OP_RECV_MESSAGE] = true; oas->state.state_op_done[OP_RECV_MESSAGE] = true; /* Extra read to trigger on_succeed */ stream_state->rs.read_buffer = stream_state->rs.grpc_header_bytes; stream_state->rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES; stream_state->rs.received_bytes = 0; stream_state->rs.compressed = false; stream_state->rs.length_field_received = false; CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); stream_state->state_op_done[OP_READ_REQ_MADE] = true; /* Indicates that at least one read request has been made */ bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer, stream_state->rs.remaining_bytes); stream_state->pending_read_from_cronet = true; result = ACTION_TAKEN_NO_CALLBACK; } } else if (stream_state->rs.remaining_bytes == 0) { /* Start a read operation for first 5 bytes (GRPC header) */ stream_state->rs.read_buffer = stream_state->rs.grpc_header_bytes; stream_state->rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES; stream_state->rs.received_bytes = 0; stream_state->rs.compressed = false; CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); stream_state->state_op_done[OP_READ_REQ_MADE] = true; /* Indicates that at least one read request has been made */ bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer, stream_state->rs.remaining_bytes); stream_state->pending_read_from_cronet = true; result = ACTION_TAKEN_WITH_CALLBACK; } else { result = NO_ACTION_POSSIBLE; } } else if (stream_state->rs.remaining_bytes == 0) { CRONET_LOG(GPR_DEBUG, "read operation complete"); grpc_slice read_data_slice = grpc_slice_malloc((uint32_t)stream_state->rs.length_field); uint8_t *dst_p = GRPC_SLICE_START_PTR(read_data_slice); memcpy(dst_p, stream_state->rs.read_buffer, (size_t)stream_state->rs.length_field); null_and_maybe_free_read_buffer(s); grpc_slice_buffer_init(&stream_state->rs.read_slice_buffer); grpc_slice_buffer_add(&stream_state->rs.read_slice_buffer, read_data_slice); grpc_slice_buffer_stream_init(&stream_state->rs.sbs, &stream_state->rs.read_slice_buffer, 0); if (stream_state->rs.compressed) { stream_state->rs.sbs.base.flags = GRPC_WRITE_INTERNAL_COMPRESS; } *((grpc_byte_buffer **)stream_op->payload->recv_message.recv_message) = (grpc_byte_buffer *)&stream_state->rs.sbs; grpc_closure_sched(exec_ctx, stream_op->payload->recv_message.recv_message_ready, GRPC_ERROR_NONE); stream_state->state_op_done[OP_RECV_MESSAGE] = true; oas->state.state_op_done[OP_RECV_MESSAGE] = true; /* Do an extra read to trigger on_succeeded() callback in case connection is closed */ stream_state->rs.read_buffer = stream_state->rs.grpc_header_bytes; stream_state->rs.compressed = false; stream_state->rs.received_bytes = 0; stream_state->rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES; stream_state->rs.length_field_received = false; CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer, stream_state->rs.remaining_bytes); stream_state->pending_read_from_cronet = true; result = ACTION_TAKEN_NO_CALLBACK; } } else if (stream_op->recv_trailing_metadata && op_can_be_run(stream_op, s, &oas->state, OP_RECV_TRAILING_METADATA)) { CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_TRAILING_METADATA", oas); if (oas->s->state.rs.trailing_metadata_valid) { grpc_chttp2_incoming_metadata_buffer_publish( exec_ctx, &oas->s->state.rs.trailing_metadata, stream_op->payload->recv_trailing_metadata.recv_trailing_metadata); stream_state->rs.trailing_metadata_valid = false; } stream_state->state_op_done[OP_RECV_TRAILING_METADATA] = true; result = ACTION_TAKEN_NO_CALLBACK; } else if (stream_op->cancel_stream && op_can_be_run(stream_op, s, &oas->state, OP_CANCEL_ERROR)) { CRONET_LOG(GPR_DEBUG, "running: %p OP_CANCEL_ERROR", oas); CRONET_LOG(GPR_DEBUG, "W: bidirectional_stream_cancel(%p)", s->cbs); if (s->cbs) { bidirectional_stream_cancel(s->cbs); result = ACTION_TAKEN_WITH_CALLBACK; } else { result = ACTION_TAKEN_NO_CALLBACK; } stream_state->state_op_done[OP_CANCEL_ERROR] = true; if (!stream_state->cancel_error) { stream_state->cancel_error = GRPC_ERROR_REF(stream_op->payload->cancel_stream.cancel_error); } } else if (stream_op->on_complete && op_can_be_run(stream_op, s, &oas->state, OP_ON_COMPLETE)) { CRONET_LOG(GPR_DEBUG, "running: %p OP_ON_COMPLETE", oas); if (stream_state->state_op_done[OP_CANCEL_ERROR]) { grpc_closure_sched(exec_ctx, stream_op->on_complete, GRPC_ERROR_REF(stream_state->cancel_error)); } else if (stream_state->state_callback_received[OP_FAILED]) { grpc_closure_sched( exec_ctx, stream_op->on_complete, make_error_with_desc(GRPC_STATUS_UNAVAILABLE, "Unavailable.")); } else { /* All actions in this stream_op are complete. Call the on_complete * callback */ grpc_closure_sched(exec_ctx, stream_op->on_complete, GRPC_ERROR_NONE); } oas->state.state_op_done[OP_ON_COMPLETE] = true; oas->done = true; /* reset any send message state, only if this ON_COMPLETE is about a send. */ if (stream_op->send_message) { stream_state->state_callback_received[OP_SEND_MESSAGE] = false; stream_state->state_op_done[OP_SEND_MESSAGE] = false; } result = ACTION_TAKEN_NO_CALLBACK; /* If this is the on_complete callback being called for a received message - make a note */ if (stream_op->recv_message) stream_state->state_op_done[OP_RECV_MESSAGE_AND_ON_COMPLETE] = true; } else { result = NO_ACTION_POSSIBLE; } return result; } /* Functions used by upper layers to access transport functionality. */ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_stream_refcount *refcount, const void *server_data, gpr_arena *arena) { stream_obj *s = (stream_obj *)gs; memset(&s->storage, 0, sizeof(s->storage)); s->storage.head = NULL; memset(&s->state, 0, sizeof(s->state)); s->curr_op = NULL; s->cbs = NULL; memset(&s->header_array, 0, sizeof(s->header_array)); memset(&s->state.rs, 0, sizeof(s->state.rs)); memset(&s->state.ws, 0, sizeof(s->state.ws)); memset(s->state.state_op_done, 0, sizeof(s->state.state_op_done)); memset(s->state.state_callback_received, 0, sizeof(s->state.state_callback_received)); s->state.fail_state = s->state.flush_read = false; s->state.cancel_error = NULL; s->state.flush_cronet_when_ready = s->state.pending_write_for_trailer = false; s->state.pending_send_message = false; s->state.pending_recv_trailing_metadata = false; s->state.pending_read_from_cronet = false; s->curr_gs = gs; s->curr_ct = (grpc_cronet_transport *)gt; s->arena = arena; gpr_mu_init(&s->mu); return 0; } static void set_pollset_do_nothing(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_pollset *pollset) {} static void set_pollset_set_do_nothing(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_pollset_set *pollset_set) {} static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_transport_stream_op_batch *op) { CRONET_LOG(GPR_DEBUG, "perform_stream_op"); if (op->send_initial_metadata && header_has_authority(op->payload->send_initial_metadata .send_initial_metadata->list.head)) { /* Cronet does not support :authority header field. We cancel the call when this field is present in metadata */ if (op->recv_initial_metadata) { grpc_closure_sched( exec_ctx, op->payload->recv_initial_metadata.recv_initial_metadata_ready, GRPC_ERROR_CANCELLED); } if (op->recv_message) { grpc_closure_sched(exec_ctx, op->payload->recv_message.recv_message_ready, GRPC_ERROR_CANCELLED); } grpc_closure_sched(exec_ctx, op->on_complete, GRPC_ERROR_CANCELLED); return; } stream_obj *s = (stream_obj *)gs; add_to_storage(s, op); execute_from_storage(s); } static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_closure *then_schedule_closure) { stream_obj *s = (stream_obj *)gs; null_and_maybe_free_read_buffer(s); GRPC_ERROR_UNREF(s->state.cancel_error); grpc_closure_sched(exec_ctx, then_schedule_closure, GRPC_ERROR_NONE); } static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {} static char *get_peer(grpc_exec_ctx *exec_ctx, grpc_transport *gt) { return NULL; } static grpc_endpoint *get_endpoint(grpc_exec_ctx *exec_ctx, grpc_transport *gt) { return NULL; } static void perform_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_transport_op *op) {} static const grpc_transport_vtable grpc_cronet_vtable = { sizeof(stream_obj), "cronet_http", init_stream, set_pollset_do_nothing, set_pollset_set_do_nothing, perform_stream_op, perform_op, destroy_stream, destroy_transport, get_peer, get_endpoint}; grpc_transport *grpc_create_cronet_transport(void *engine, const char *target, const grpc_channel_args *args, void *reserved) { grpc_cronet_transport *ct = gpr_malloc(sizeof(grpc_cronet_transport)); if (!ct) { goto error; } ct->base.vtable = &grpc_cronet_vtable; ct->engine = engine; ct->host = gpr_malloc(strlen(target) + 1); if (!ct->host) { goto error; } strcpy(ct->host, target); ct->use_packet_coalescing = true; if (args) { for (size_t i = 0; i < args->num_args; i++) { if (0 == strcmp(args->args[i].key, GRPC_ARG_USE_CRONET_PACKET_COALESCING)) { if (args->args[i].type != GRPC_ARG_INTEGER) { gpr_log(GPR_ERROR, "%s ignored: it must be an integer", GRPC_ARG_USE_CRONET_PACKET_COALESCING); } else { ct->use_packet_coalescing = (args->args[i].value.integer != 0); } } } } return &ct->base; error: if (ct) { if (ct->host) { gpr_free(ct->host); } gpr_free(ct); } return NULL; } grpc-1.3.2/src/core/ext/transport/cronet/transport/cronet_transport.h000066400000000000000000000037751310511640000261330ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_EXT_TRANSPORT_CRONET_TRANSPORT_CRONET_TRANSPORT_H #define GRPC_CORE_EXT_TRANSPORT_CRONET_TRANSPORT_CRONET_TRANSPORT_H #include "src/core/lib/transport/transport.h" grpc_transport *grpc_create_cronet_transport(void *engine, const char *target, const grpc_channel_args *args, void *reserved); #endif /* GRPC_CORE_EXT_TRANSPORT_CRONET_TRANSPORT_CRONET_TRANSPORT_H */ grpc-1.3.2/src/core/lib/000077500000000000000000000000001310511640000147245ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/README.md000066400000000000000000000005231310511640000162030ustar00rootroot00000000000000Required elements of gRPC Core: Each module in this directory is required to build gRPC. If it's possible to envisage a configuration where code is not required, then that code belongs in ext/ instead. NOTE: The movement of code between lib and ext is an ongoing effort, so this directory currently contains too much of the core library. grpc-1.3.2/src/core/lib/channel/000077500000000000000000000000001310511640000163345ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/channel/README.md000066400000000000000000000001651310511640000176150ustar00rootroot00000000000000# Channel Provides channel/call stack implementation, and implementation of common filters for that implementation. grpc-1.3.2/src/core/lib/channel/channel_args.c000066400000000000000000000277471310511640000211450ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/channel/channel_args.h" #include #include "src/core/lib/support/string.h" #include #include #include #include #include #include static grpc_arg copy_arg(const grpc_arg *src) { grpc_arg dst; dst.type = src->type; dst.key = gpr_strdup(src->key); switch (dst.type) { case GRPC_ARG_STRING: dst.value.string = gpr_strdup(src->value.string); break; case GRPC_ARG_INTEGER: dst.value.integer = src->value.integer; break; case GRPC_ARG_POINTER: dst.value.pointer = src->value.pointer; dst.value.pointer.p = src->value.pointer.vtable->copy(src->value.pointer.p); break; } return dst; } grpc_channel_args *grpc_channel_args_copy_and_add(const grpc_channel_args *src, const grpc_arg *to_add, size_t num_to_add) { return grpc_channel_args_copy_and_add_and_remove(src, NULL, 0, to_add, num_to_add); } grpc_channel_args *grpc_channel_args_copy_and_remove( const grpc_channel_args *src, const char **to_remove, size_t num_to_remove) { return grpc_channel_args_copy_and_add_and_remove(src, to_remove, num_to_remove, NULL, 0); } static bool should_remove_arg(const grpc_arg *arg, const char **to_remove, size_t num_to_remove) { for (size_t i = 0; i < num_to_remove; ++i) { if (strcmp(arg->key, to_remove[i]) == 0) return true; } return false; } grpc_channel_args *grpc_channel_args_copy_and_add_and_remove( const grpc_channel_args *src, const char **to_remove, size_t num_to_remove, const grpc_arg *to_add, size_t num_to_add) { // Figure out how many args we'll be copying. size_t num_args_to_copy = 0; if (src != NULL) { for (size_t i = 0; i < src->num_args; ++i) { if (!should_remove_arg(&src->args[i], to_remove, num_to_remove)) { ++num_args_to_copy; } } } // Create result. grpc_channel_args *dst = gpr_malloc(sizeof(grpc_channel_args)); dst->num_args = num_args_to_copy + num_to_add; if (dst->num_args == 0) { dst->args = NULL; return dst; } dst->args = gpr_malloc(sizeof(grpc_arg) * dst->num_args); // Copy args from src that are not being removed. size_t dst_idx = 0; if (src != NULL) { for (size_t i = 0; i < src->num_args; ++i) { if (!should_remove_arg(&src->args[i], to_remove, num_to_remove)) { dst->args[dst_idx++] = copy_arg(&src->args[i]); } } } // Add args from to_add. for (size_t i = 0; i < num_to_add; ++i) { dst->args[dst_idx++] = copy_arg(&to_add[i]); } GPR_ASSERT(dst_idx == dst->num_args); return dst; } grpc_channel_args *grpc_channel_args_copy(const grpc_channel_args *src) { return grpc_channel_args_copy_and_add(src, NULL, 0); } grpc_channel_args *grpc_channel_args_merge(const grpc_channel_args *a, const grpc_channel_args *b) { return grpc_channel_args_copy_and_add(a, b->args, b->num_args); } static int cmp_arg(const grpc_arg *a, const grpc_arg *b) { int c = GPR_ICMP(a->type, b->type); if (c != 0) return c; c = strcmp(a->key, b->key); if (c != 0) return c; switch (a->type) { case GRPC_ARG_STRING: return strcmp(a->value.string, b->value.string); case GRPC_ARG_INTEGER: return GPR_ICMP(a->value.integer, b->value.integer); case GRPC_ARG_POINTER: c = GPR_ICMP(a->value.pointer.p, b->value.pointer.p); if (c != 0) { c = GPR_ICMP(a->value.pointer.vtable, b->value.pointer.vtable); if (c == 0) { c = a->value.pointer.vtable->cmp(a->value.pointer.p, b->value.pointer.p); } } return c; } GPR_UNREACHABLE_CODE(return 0); } /* stabilizing comparison function: since channel_args ordering matters for * keys with the same name, we need to preserve that ordering */ static int cmp_key_stable(const void *ap, const void *bp) { const grpc_arg *const *a = ap; const grpc_arg *const *b = bp; int c = strcmp((*a)->key, (*b)->key); if (c == 0) c = GPR_ICMP(*a, *b); return c; } grpc_channel_args *grpc_channel_args_normalize(const grpc_channel_args *a) { grpc_arg **args = gpr_malloc(sizeof(grpc_arg *) * a->num_args); for (size_t i = 0; i < a->num_args; i++) { args[i] = &a->args[i]; } if (a->num_args > 1) qsort(args, a->num_args, sizeof(grpc_arg *), cmp_key_stable); grpc_channel_args *b = gpr_malloc(sizeof(grpc_channel_args)); b->num_args = a->num_args; b->args = gpr_malloc(sizeof(grpc_arg) * b->num_args); for (size_t i = 0; i < a->num_args; i++) { b->args[i] = copy_arg(args[i]); } gpr_free(args); return b; } void grpc_channel_args_destroy(grpc_exec_ctx *exec_ctx, grpc_channel_args *a) { size_t i; if (!a) return; for (i = 0; i < a->num_args; i++) { switch (a->args[i].type) { case GRPC_ARG_STRING: gpr_free(a->args[i].value.string); break; case GRPC_ARG_INTEGER: break; case GRPC_ARG_POINTER: a->args[i].value.pointer.vtable->destroy(exec_ctx, a->args[i].value.pointer.p); break; } gpr_free(a->args[i].key); } gpr_free(a->args); gpr_free(a); } grpc_compression_algorithm grpc_channel_args_get_compression_algorithm( const grpc_channel_args *a) { size_t i; if (a == NULL) return 0; for (i = 0; i < a->num_args; ++i) { if (a->args[i].type == GRPC_ARG_INTEGER && !strcmp(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, a->args[i].key)) { return (grpc_compression_algorithm)a->args[i].value.integer; break; } } return GRPC_COMPRESS_NONE; } grpc_channel_args *grpc_channel_args_set_compression_algorithm( grpc_channel_args *a, grpc_compression_algorithm algorithm) { GPR_ASSERT(algorithm < GRPC_COMPRESS_ALGORITHMS_COUNT); grpc_arg tmp; tmp.type = GRPC_ARG_INTEGER; tmp.key = GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM; tmp.value.integer = algorithm; return grpc_channel_args_copy_and_add(a, &tmp, 1); } /** Returns 1 if the argument for compression algorithm's enabled states bitset * was found in \a a, returning the arg's value in \a states. Otherwise, returns * 0. */ static int find_compression_algorithm_states_bitset(const grpc_channel_args *a, int **states_arg) { if (a != NULL) { size_t i; for (i = 0; i < a->num_args; ++i) { if (a->args[i].type == GRPC_ARG_INTEGER && !strcmp(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET, a->args[i].key)) { *states_arg = &a->args[i].value.integer; **states_arg |= 0x1; /* forcefully enable support for no compression */ return 1; } } } return 0; /* GPR_FALSE */ } grpc_channel_args *grpc_channel_args_compression_algorithm_set_state( grpc_exec_ctx *exec_ctx, grpc_channel_args **a, grpc_compression_algorithm algorithm, int state) { int *states_arg = NULL; grpc_channel_args *result = *a; const int states_arg_found = find_compression_algorithm_states_bitset(*a, &states_arg); if (grpc_channel_args_get_compression_algorithm(*a) == algorithm && state == 0) { char *algo_name = NULL; GPR_ASSERT(grpc_compression_algorithm_name(algorithm, &algo_name) != 0); gpr_log(GPR_ERROR, "Tried to disable default compression algorithm '%s'. The " "operation has been ignored.", algo_name); } else if (states_arg_found) { if (state != 0) { GPR_BITSET((unsigned *)states_arg, algorithm); } else if (algorithm != GRPC_COMPRESS_NONE) { GPR_BITCLEAR((unsigned *)states_arg, algorithm); } } else { /* create a new arg */ grpc_arg tmp; tmp.type = GRPC_ARG_INTEGER; tmp.key = GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET; /* all enabled by default */ tmp.value.integer = (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1; if (state != 0) { GPR_BITSET((unsigned *)&tmp.value.integer, algorithm); } else if (algorithm != GRPC_COMPRESS_NONE) { GPR_BITCLEAR((unsigned *)&tmp.value.integer, algorithm); } result = grpc_channel_args_copy_and_add(*a, &tmp, 1); grpc_channel_args_destroy(exec_ctx, *a); *a = result; } return result; } uint32_t grpc_channel_args_compression_algorithm_get_states( const grpc_channel_args *a) { int *states_arg; if (find_compression_algorithm_states_bitset(a, &states_arg)) { return (uint32_t)*states_arg; } else { return (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1; /* All algs. enabled */ } } grpc_channel_args *grpc_channel_args_set_socket_mutator( grpc_channel_args *a, grpc_socket_mutator *mutator) { grpc_arg tmp = grpc_socket_mutator_to_arg(mutator); return grpc_channel_args_copy_and_add(a, &tmp, 1); } int grpc_channel_args_compare(const grpc_channel_args *a, const grpc_channel_args *b) { int c = GPR_ICMP(a->num_args, b->num_args); if (c != 0) return c; for (size_t i = 0; i < a->num_args; i++) { c = cmp_arg(&a->args[i], &b->args[i]); if (c != 0) return c; } return 0; } const grpc_arg *grpc_channel_args_find(const grpc_channel_args *args, const char *name) { if (args != NULL) { for (size_t i = 0; i < args->num_args; ++i) { if (strcmp(args->args[i].key, name) == 0) { return &args->args[i]; } } } return NULL; } int grpc_channel_arg_get_integer(grpc_arg *arg, grpc_integer_options options) { if (arg->type != GRPC_ARG_INTEGER) { gpr_log(GPR_ERROR, "%s ignored: it must be an integer", arg->key); return options.default_value; } if (arg->value.integer < options.min_value) { gpr_log(GPR_ERROR, "%s ignored: it must be >= %d", arg->key, options.min_value); return options.default_value; } if (arg->value.integer > options.max_value) { gpr_log(GPR_ERROR, "%s ignored: it must be <= %d", arg->key, options.max_value); return options.default_value; } return arg->value.integer; } bool grpc_channel_args_want_minimal_stack(const grpc_channel_args *args) { const grpc_arg *arg = grpc_channel_args_find(args, GRPC_ARG_MINIMAL_STACK); if (arg == NULL) return false; if (arg->type == GRPC_ARG_INTEGER && arg->value.integer == 0) return false; return true; } grpc-1.3.2/src/core/lib/channel/channel_args.h000066400000000000000000000133611310511640000211350ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_CHANNEL_CHANNEL_ARGS_H #define GRPC_CORE_LIB_CHANNEL_CHANNEL_ARGS_H #include #include #include "src/core/lib/iomgr/socket_mutator.h" // Channel args are intentionally immutable, to avoid the need for locking. /** Copy the arguments in \a src into a new instance */ grpc_channel_args *grpc_channel_args_copy(const grpc_channel_args *src); /** Copy the arguments in \a src into a new instance, stably sorting keys */ grpc_channel_args *grpc_channel_args_normalize(const grpc_channel_args *src); /** Copy the arguments in \a src and append \a to_add. If \a to_add is NULL, it * is equivalent to calling \a grpc_channel_args_copy. */ grpc_channel_args *grpc_channel_args_copy_and_add(const grpc_channel_args *src, const grpc_arg *to_add, size_t num_to_add); /** Copies the arguments in \a src except for those whose keys are in \a to_remove. */ grpc_channel_args *grpc_channel_args_copy_and_remove( const grpc_channel_args *src, const char **to_remove, size_t num_to_remove); /** Copies the arguments from \a src except for those whose keys are in \a to_remove and appends the arguments in \a to_add. */ grpc_channel_args *grpc_channel_args_copy_and_add_and_remove( const grpc_channel_args *src, const char **to_remove, size_t num_to_remove, const grpc_arg *to_add, size_t num_to_add); /** Concatenate args from \a a and \a b into a new instance */ grpc_channel_args *grpc_channel_args_merge(const grpc_channel_args *a, const grpc_channel_args *b); /** Destroy arguments created by \a grpc_channel_args_copy */ void grpc_channel_args_destroy(grpc_exec_ctx *exec_ctx, grpc_channel_args *a); /** Returns the compression algorithm set in \a a. */ grpc_compression_algorithm grpc_channel_args_get_compression_algorithm( const grpc_channel_args *a); /** Returns a channel arg instance with compression enabled. If \a a is * non-NULL, its args are copied. N.B. GRPC_COMPRESS_NONE disables compression * for the channel. */ grpc_channel_args *grpc_channel_args_set_compression_algorithm( grpc_channel_args *a, grpc_compression_algorithm algorithm); /** Sets the support for the given compression algorithm. By default, all * compression algorithms are enabled. It's an error to disable an algorithm set * by grpc_channel_args_set_compression_algorithm. * * Returns an instance with the updated algorithm states. The \a a pointer is * modified to point to the returned instance (which may be different from the * input value of \a a). */ grpc_channel_args *grpc_channel_args_compression_algorithm_set_state( grpc_exec_ctx *exec_ctx, grpc_channel_args **a, grpc_compression_algorithm algorithm, int enabled); /** Returns the bitset representing the support state (true for enabled, false * for disabled) for compression algorithms. * * The i-th bit of the returned bitset corresponds to the i-th entry in the * grpc_compression_algorithm enum. */ uint32_t grpc_channel_args_compression_algorithm_get_states( const grpc_channel_args *a); int grpc_channel_args_compare(const grpc_channel_args *a, const grpc_channel_args *b); /** Returns a channel arg instance with socket mutator added. The socket mutator * will perform its mutate_fd method on all file descriptors used by the * channel. * If \a a is non-MULL, its args are copied. */ grpc_channel_args *grpc_channel_args_set_socket_mutator( grpc_channel_args *a, grpc_socket_mutator *mutator); /** Returns the value of argument \a name from \a args, or NULL if not found. */ const grpc_arg *grpc_channel_args_find(const grpc_channel_args *args, const char *name); bool grpc_channel_args_want_minimal_stack(const grpc_channel_args *args); typedef struct grpc_integer_options { int default_value; // Return this if value is outside of expected bounds. int min_value; int max_value; } grpc_integer_options; /** Returns the value of \a arg, subject to the contraints in \a options. */ int grpc_channel_arg_get_integer(grpc_arg *arg, grpc_integer_options options); #endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_ARGS_H */ grpc-1.3.2/src/core/lib/channel/channel_stack.c000066400000000000000000000254171310511640000213060ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/channel/channel_stack.h" #include #include #include #include int grpc_trace_channel = 0; /* Memory layouts. Channel stack is laid out as: { grpc_channel_stack stk; padding to GPR_MAX_ALIGNMENT grpc_channel_element[stk.count]; per-filter memory, aligned to GPR_MAX_ALIGNMENT } Call stack is laid out as: { grpc_call_stack stk; padding to GPR_MAX_ALIGNMENT grpc_call_element[stk.count]; per-filter memory, aligned to GPR_MAX_ALIGNMENT } */ /* Given a size, round up to the next multiple of sizeof(void*) */ #define ROUND_UP_TO_ALIGNMENT_SIZE(x) \ (((x) + GPR_MAX_ALIGNMENT - 1u) & ~(GPR_MAX_ALIGNMENT - 1u)) size_t grpc_channel_stack_size(const grpc_channel_filter **filters, size_t filter_count) { /* always need the header, and size for the channel elements */ size_t size = ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_channel_stack)) + ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_channel_element)); size_t i; GPR_ASSERT((GPR_MAX_ALIGNMENT & (GPR_MAX_ALIGNMENT - 1)) == 0 && "GPR_MAX_ALIGNMENT must be a power of two"); /* add the size for each filter */ for (i = 0; i < filter_count; i++) { size += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data); } return size; } #define CHANNEL_ELEMS_FROM_STACK(stk) \ ((grpc_channel_element *)((char *)(stk) + ROUND_UP_TO_ALIGNMENT_SIZE( \ sizeof(grpc_channel_stack)))) #define CALL_ELEMS_FROM_STACK(stk) \ ((grpc_call_element *)((char *)(stk) + \ ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)))) grpc_channel_element *grpc_channel_stack_element( grpc_channel_stack *channel_stack, size_t index) { return CHANNEL_ELEMS_FROM_STACK(channel_stack) + index; } grpc_channel_element *grpc_channel_stack_last_element( grpc_channel_stack *channel_stack) { return grpc_channel_stack_element(channel_stack, channel_stack->count - 1); } grpc_call_element *grpc_call_stack_element(grpc_call_stack *call_stack, size_t index) { return CALL_ELEMS_FROM_STACK(call_stack) + index; } grpc_error *grpc_channel_stack_init( grpc_exec_ctx *exec_ctx, int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg, const grpc_channel_filter **filters, size_t filter_count, const grpc_channel_args *channel_args, grpc_transport *optional_transport, const char *name, grpc_channel_stack *stack) { size_t call_size = ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)) + ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_call_element)); grpc_channel_element *elems; grpc_channel_element_args args; char *user_data; size_t i; stack->count = filter_count; GRPC_STREAM_REF_INIT(&stack->refcount, initial_refs, destroy, destroy_arg, name); elems = CHANNEL_ELEMS_FROM_STACK(stack); user_data = ((char *)elems) + ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_channel_element)); /* init per-filter data */ grpc_error *first_error = GRPC_ERROR_NONE; for (i = 0; i < filter_count; i++) { args.channel_stack = stack; args.channel_args = channel_args; args.optional_transport = optional_transport; args.is_first = i == 0; args.is_last = i == (filter_count - 1); elems[i].filter = filters[i]; elems[i].channel_data = user_data; grpc_error *error = elems[i].filter->init_channel_elem(exec_ctx, &elems[i], &args); if (error != GRPC_ERROR_NONE) { if (first_error == GRPC_ERROR_NONE) { first_error = error; } else { GRPC_ERROR_UNREF(error); } } user_data += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data); call_size += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_call_data); } GPR_ASSERT(user_data > (char *)stack); GPR_ASSERT((uintptr_t)(user_data - (char *)stack) == grpc_channel_stack_size(filters, filter_count)); stack->call_stack_size = call_size; return first_error; } void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_channel_stack *stack) { grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(stack); size_t count = stack->count; size_t i; /* destroy per-filter data */ for (i = 0; i < count; i++) { channel_elems[i].filter->destroy_channel_elem(exec_ctx, &channel_elems[i]); } } grpc_error *grpc_call_stack_init(grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack, int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg, const grpc_call_element_args *elem_args) { grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack); size_t count = channel_stack->count; grpc_call_element *call_elems; char *user_data; size_t i; elem_args->call_stack->count = count; GRPC_STREAM_REF_INIT(&elem_args->call_stack->refcount, initial_refs, destroy, destroy_arg, "CALL_STACK"); call_elems = CALL_ELEMS_FROM_STACK(elem_args->call_stack); user_data = ((char *)call_elems) + ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element)); /* init per-filter data */ grpc_error *first_error = GRPC_ERROR_NONE; for (i = 0; i < count; i++) { call_elems[i].filter = channel_elems[i].filter; call_elems[i].channel_data = channel_elems[i].channel_data; call_elems[i].call_data = user_data; grpc_error *error = call_elems[i].filter->init_call_elem( exec_ctx, &call_elems[i], elem_args); if (error != GRPC_ERROR_NONE) { if (first_error == GRPC_ERROR_NONE) { first_error = error; } else { GRPC_ERROR_UNREF(error); } } user_data += ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data); } return first_error; } void grpc_call_stack_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx, grpc_call_stack *call_stack, grpc_polling_entity *pollent) { size_t count = call_stack->count; grpc_call_element *call_elems; char *user_data; size_t i; call_elems = CALL_ELEMS_FROM_STACK(call_stack); user_data = ((char *)call_elems) + ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element)); /* init per-filter data */ for (i = 0; i < count; i++) { call_elems[i].filter->set_pollset_or_pollset_set(exec_ctx, &call_elems[i], pollent); user_data += ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data); } } void grpc_call_stack_ignore_set_pollset_or_pollset_set( grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_polling_entity *pollent) {} void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack, const grpc_call_final_info *final_info, grpc_closure *then_schedule_closure) { grpc_call_element *elems = CALL_ELEMS_FROM_STACK(stack); size_t count = stack->count; size_t i; /* destroy per-filter data */ for (i = 0; i < count; i++) { elems[i].filter->destroy_call_elem( exec_ctx, &elems[i], final_info, i == count - 1 ? then_schedule_closure : NULL); } } void grpc_call_next_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op_batch *op) { grpc_call_element *next_elem = elem + 1; next_elem->filter->start_transport_stream_op_batch(exec_ctx, next_elem, op); } char *grpc_call_next_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { grpc_call_element *next_elem = elem + 1; return next_elem->filter->get_peer(exec_ctx, next_elem); } void grpc_channel_next_get_info(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, const grpc_channel_info *channel_info) { grpc_channel_element *next_elem = elem + 1; next_elem->filter->get_channel_info(exec_ctx, next_elem, channel_info); } void grpc_channel_next_op(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_transport_op *op) { grpc_channel_element *next_elem = elem + 1; next_elem->filter->start_transport_op(exec_ctx, next_elem, op); } grpc_channel_stack *grpc_channel_stack_from_top_element( grpc_channel_element *elem) { return (grpc_channel_stack *)((char *)(elem)-ROUND_UP_TO_ALIGNMENT_SIZE( sizeof(grpc_channel_stack))); } grpc_call_stack *grpc_call_stack_from_top_element(grpc_call_element *elem) { return (grpc_call_stack *)((char *)(elem)-ROUND_UP_TO_ALIGNMENT_SIZE( sizeof(grpc_call_stack))); } void grpc_call_element_signal_error(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_error *error) { grpc_transport_stream_op_batch *op = grpc_make_transport_stream_op(NULL); op->cancel_stream = true; op->payload->cancel_stream.cancel_error = error; elem->filter->start_transport_stream_op_batch(exec_ctx, elem, op); } grpc-1.3.2/src/core/lib/channel/channel_stack.h000066400000000000000000000330721310511640000213070ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_CHANNEL_CHANNEL_STACK_H #define GRPC_CORE_LIB_CHANNEL_CHANNEL_STACK_H ////////////////////////////////////////////////////////////////////////////// // IMPORTANT NOTE: // // When you update this API, please make the corresponding changes to // the C++ API in src/cpp/common/channel_filter.{h,cc} ////////////////////////////////////////////////////////////////////////////// /* A channel filter defines how operations on a channel are implemented. Channel filters are chained together to create full channels, and if those chains are linear, then channel stacks provide a mechanism to minimize allocations for that chain. Call stacks are created by channel stacks and represent the per-call data for that stack. */ #include #include #include #include #include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/support/arena.h" #include "src/core/lib/transport/transport.h" #ifdef __cplusplus extern "C" { #endif typedef struct grpc_channel_element grpc_channel_element; typedef struct grpc_call_element grpc_call_element; typedef struct grpc_channel_stack grpc_channel_stack; typedef struct grpc_call_stack grpc_call_stack; typedef struct { grpc_channel_stack *channel_stack; const grpc_channel_args *channel_args; /** Transport, iff it is known */ grpc_transport *optional_transport; int is_first; int is_last; } grpc_channel_element_args; typedef struct { grpc_call_stack *call_stack; const void *server_transport_data; grpc_call_context_element *context; grpc_slice path; gpr_timespec start_time; gpr_timespec deadline; gpr_arena *arena; } grpc_call_element_args; typedef struct { grpc_transport_stream_stats transport_stream_stats; gpr_timespec latency; /* From call creating to enqueing of received status */ } grpc_call_stats; /** Information about the call upon completion. */ typedef struct { grpc_call_stats stats; grpc_status_code final_status; } grpc_call_final_info; /* Channel filters specify: 1. the amount of memory needed in the channel & call (via the sizeof_XXX members) 2. functions to initialize and destroy channel & call data (init_XXX, destroy_XXX) 3. functions to implement call operations and channel operations (call_op, channel_op) 4. a name, which is useful when debugging Members are laid out in approximate frequency of use order. */ typedef struct { /* Called to eg. send/receive data on a call. See grpc_call_next_op on how to call the next element in the stack */ void (*start_transport_stream_op_batch)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op_batch *op); /* Called to handle channel level operations - e.g. new calls, or transport closure. See grpc_channel_next_op on how to call the next element in the stack */ void (*start_transport_op)(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_transport_op *op); /* sizeof(per call data) */ size_t sizeof_call_data; /* Initialize per call data. elem is initialized at the start of the call, and elem->call_data is what needs initializing. The filter does not need to do any chaining. server_transport_data is an opaque pointer. If it is NULL, this call is on a client; if it is non-NULL, then it points to memory owned by the transport and is on the server. Most filters want to ignore this argument. Implementations may assume that elem->call_data is all zeros. */ grpc_error *(*init_call_elem)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_element_args *args); void (*set_pollset_or_pollset_set)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_polling_entity *pollent); /* Destroy per call data. The filter does not need to do any chaining. The bottom filter of a stack will be passed a non-NULL pointer to \a then_schedule_closure that should be passed to grpc_closure_sched when destruction is complete. \a final_info contains data about the completed call, mainly for reporting purposes. */ void (*destroy_call_elem)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, grpc_closure *then_schedule_closure); /* sizeof(per channel data) */ size_t sizeof_channel_data; /* Initialize per-channel data. elem is initialized at the creating of the channel, and elem->channel_data is what needs initializing. is_first, is_last designate this elements position in the stack, and are useful for asserting correct configuration by upper layer code. The filter does not need to do any chaining. Implementations may assume that elem->call_data is all zeros. */ grpc_error *(*init_channel_elem)(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_channel_element_args *args); /* Destroy per channel data. The filter does not need to do any chaining */ void (*destroy_channel_elem)(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem); /* Implement grpc_call_get_peer() */ char *(*get_peer)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem); /* Implement grpc_channel_get_info() */ void (*get_channel_info)(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, const grpc_channel_info *channel_info); /* The name of this filter */ const char *name; } grpc_channel_filter; /* A channel_element tracks its filter and the filter requested memory within a channel allocation */ struct grpc_channel_element { const grpc_channel_filter *filter; void *channel_data; }; /* A call_element tracks its filter, the filter requested memory within a channel allocation, and the filter requested memory within a call allocation */ struct grpc_call_element { const grpc_channel_filter *filter; void *channel_data; void *call_data; }; /* A channel stack tracks a set of related filters for one channel, and guarantees they live within a single malloc() allocation */ struct grpc_channel_stack { grpc_stream_refcount refcount; size_t count; /* Memory required for a call stack (computed at channel stack initialization) */ size_t call_stack_size; }; /* A call stack tracks a set of related filters for one call, and guarantees they live within a single malloc() allocation */ struct grpc_call_stack { /* shared refcount for this channel stack. MUST be the first element: the underlying code calls destroy with the address of the refcount, but higher layers prefer to think about the address of the call stack itself. */ grpc_stream_refcount refcount; size_t count; }; /* Get a channel element given a channel stack and its index */ grpc_channel_element *grpc_channel_stack_element(grpc_channel_stack *stack, size_t i); /* Get the last channel element in a channel stack */ grpc_channel_element *grpc_channel_stack_last_element( grpc_channel_stack *stack); /* Get a call stack element given a call stack and an index */ grpc_call_element *grpc_call_stack_element(grpc_call_stack *stack, size_t i); /* Determine memory required for a channel stack containing a set of filters */ size_t grpc_channel_stack_size(const grpc_channel_filter **filters, size_t filter_count); /* Initialize a channel stack given some filters */ grpc_error *grpc_channel_stack_init( grpc_exec_ctx *exec_ctx, int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg, const grpc_channel_filter **filters, size_t filter_count, const grpc_channel_args *args, grpc_transport *optional_transport, const char *name, grpc_channel_stack *stack); /* Destroy a channel stack */ void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_channel_stack *stack); /* Initialize a call stack given a channel stack. transport_server_data is expected to be NULL on a client, or an opaque transport owned pointer on the server. */ grpc_error *grpc_call_stack_init(grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack, int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg, const grpc_call_element_args *elem_args); /* Set a pollset or a pollset_set for a call stack: must occur before the first * op is started */ void grpc_call_stack_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx, grpc_call_stack *call_stack, grpc_polling_entity *pollent); #ifdef GRPC_STREAM_REFCOUNT_DEBUG #define GRPC_CALL_STACK_REF(call_stack, reason) \ grpc_stream_ref(&(call_stack)->refcount, reason) #define GRPC_CALL_STACK_UNREF(exec_ctx, call_stack, reason) \ grpc_stream_unref(exec_ctx, &(call_stack)->refcount, reason) #define GRPC_CHANNEL_STACK_REF(channel_stack, reason) \ grpc_stream_ref(&(channel_stack)->refcount, reason) #define GRPC_CHANNEL_STACK_UNREF(exec_ctx, channel_stack, reason) \ grpc_stream_unref(exec_ctx, &(channel_stack)->refcount, reason) #else #define GRPC_CALL_STACK_REF(call_stack, reason) \ grpc_stream_ref(&(call_stack)->refcount) #define GRPC_CALL_STACK_UNREF(exec_ctx, call_stack, reason) \ grpc_stream_unref(exec_ctx, &(call_stack)->refcount) #define GRPC_CHANNEL_STACK_REF(channel_stack, reason) \ grpc_stream_ref(&(channel_stack)->refcount) #define GRPC_CHANNEL_STACK_UNREF(exec_ctx, channel_stack, reason) \ grpc_stream_unref(exec_ctx, &(channel_stack)->refcount) #endif /* Destroy a call stack */ void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack, const grpc_call_final_info *final_info, grpc_closure *then_schedule_closure); /* Ignore set pollset{_set} - used by filters if they don't care about pollsets * at all. Does nothing. */ void grpc_call_stack_ignore_set_pollset_or_pollset_set( grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_polling_entity *pollent); /* Call the next operation in a call stack */ void grpc_call_next_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op_batch *op); /* Call the next operation (depending on call directionality) in a channel stack */ void grpc_channel_next_op(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_transport_op *op); /* Pass through a request to get_peer to the next child element */ char *grpc_call_next_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem); /* Pass through a request to get_channel_info() to the next child element */ void grpc_channel_next_get_info(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, const grpc_channel_info *channel_info); /* Given the top element of a channel stack, get the channel stack itself */ grpc_channel_stack *grpc_channel_stack_from_top_element( grpc_channel_element *elem); /* Given the top element of a call stack, get the call stack itself */ grpc_call_stack *grpc_call_stack_from_top_element(grpc_call_element *elem); void grpc_call_log_op(char *file, int line, gpr_log_severity severity, grpc_call_element *elem, grpc_transport_stream_op_batch *op); void grpc_call_element_signal_error(grpc_exec_ctx *exec_ctx, grpc_call_element *cur_elem, grpc_error *error); extern int grpc_trace_channel; #define GRPC_CALL_LOG_OP(sev, elem, op) \ if (grpc_trace_channel) grpc_call_log_op(sev, elem, op) #ifdef __cplusplus } #endif #endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_STACK_H */ grpc-1.3.2/src/core/lib/channel/channel_stack_builder.c000066400000000000000000000226441310511640000230130ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/channel/channel_stack_builder.h" #include #include #include int grpc_trace_channel_stack_builder = 0; typedef struct filter_node { struct filter_node *next; struct filter_node *prev; const grpc_channel_filter *filter; grpc_post_filter_create_init_func init; void *init_arg; } filter_node; struct grpc_channel_stack_builder { // sentinel nodes for filters that have been added filter_node begin; filter_node end; // various set/get-able parameters grpc_channel_args *args; grpc_transport *transport; char *target; const char *name; }; struct grpc_channel_stack_builder_iterator { grpc_channel_stack_builder *builder; filter_node *node; }; grpc_channel_stack_builder *grpc_channel_stack_builder_create(void) { grpc_channel_stack_builder *b = gpr_zalloc(sizeof(*b)); b->begin.filter = NULL; b->end.filter = NULL; b->begin.next = &b->end; b->begin.prev = &b->end; b->end.next = &b->begin; b->end.prev = &b->begin; return b; } void grpc_channel_stack_builder_set_target(grpc_channel_stack_builder *b, const char *target) { gpr_free(b->target); b->target = gpr_strdup(target); } const char *grpc_channel_stack_builder_get_target( grpc_channel_stack_builder *b) { return b->target; } static grpc_channel_stack_builder_iterator *create_iterator_at_filter_node( grpc_channel_stack_builder *builder, filter_node *node) { grpc_channel_stack_builder_iterator *it = gpr_malloc(sizeof(*it)); it->builder = builder; it->node = node; return it; } void grpc_channel_stack_builder_iterator_destroy( grpc_channel_stack_builder_iterator *it) { gpr_free(it); } grpc_channel_stack_builder_iterator * grpc_channel_stack_builder_create_iterator_at_first( grpc_channel_stack_builder *builder) { return create_iterator_at_filter_node(builder, &builder->begin); } grpc_channel_stack_builder_iterator * grpc_channel_stack_builder_create_iterator_at_last( grpc_channel_stack_builder *builder) { return create_iterator_at_filter_node(builder, &builder->end); } bool grpc_channel_stack_builder_move_next( grpc_channel_stack_builder_iterator *iterator) { if (iterator->node == &iterator->builder->end) return false; iterator->node = iterator->node->next; return true; } bool grpc_channel_stack_builder_move_prev( grpc_channel_stack_builder_iterator *iterator) { if (iterator->node == &iterator->builder->begin) return false; iterator->node = iterator->node->prev; return true; } bool grpc_channel_stack_builder_move_prev( grpc_channel_stack_builder_iterator *iterator); void grpc_channel_stack_builder_set_name(grpc_channel_stack_builder *builder, const char *name) { GPR_ASSERT(builder->name == NULL); builder->name = name; } void grpc_channel_stack_builder_set_channel_arguments( grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, const grpc_channel_args *args) { if (builder->args != NULL) { grpc_channel_args_destroy(exec_ctx, builder->args); } builder->args = grpc_channel_args_copy(args); } void grpc_channel_stack_builder_set_transport( grpc_channel_stack_builder *builder, grpc_transport *transport) { GPR_ASSERT(builder->transport == NULL); builder->transport = transport; } grpc_transport *grpc_channel_stack_builder_get_transport( grpc_channel_stack_builder *builder) { return builder->transport; } const grpc_channel_args *grpc_channel_stack_builder_get_channel_arguments( grpc_channel_stack_builder *builder) { return builder->args; } bool grpc_channel_stack_builder_append_filter( grpc_channel_stack_builder *builder, const grpc_channel_filter *filter, grpc_post_filter_create_init_func post_init_func, void *user_data) { grpc_channel_stack_builder_iterator *it = grpc_channel_stack_builder_create_iterator_at_last(builder); bool ok = grpc_channel_stack_builder_add_filter_before( it, filter, post_init_func, user_data); grpc_channel_stack_builder_iterator_destroy(it); return ok; } bool grpc_channel_stack_builder_prepend_filter( grpc_channel_stack_builder *builder, const grpc_channel_filter *filter, grpc_post_filter_create_init_func post_init_func, void *user_data) { grpc_channel_stack_builder_iterator *it = grpc_channel_stack_builder_create_iterator_at_first(builder); bool ok = grpc_channel_stack_builder_add_filter_after( it, filter, post_init_func, user_data); grpc_channel_stack_builder_iterator_destroy(it); return ok; } static void add_after(filter_node *before, const grpc_channel_filter *filter, grpc_post_filter_create_init_func post_init_func, void *user_data) { filter_node *new = gpr_malloc(sizeof(*new)); new->next = before->next; new->prev = before; new->next->prev = new->prev->next = new; new->filter = filter; new->init = post_init_func; new->init_arg = user_data; } bool grpc_channel_stack_builder_add_filter_before( grpc_channel_stack_builder_iterator *iterator, const grpc_channel_filter *filter, grpc_post_filter_create_init_func post_init_func, void *user_data) { if (iterator->node == &iterator->builder->begin) return false; add_after(iterator->node->prev, filter, post_init_func, user_data); return true; } bool grpc_channel_stack_builder_add_filter_after( grpc_channel_stack_builder_iterator *iterator, const grpc_channel_filter *filter, grpc_post_filter_create_init_func post_init_func, void *user_data) { if (iterator->node == &iterator->builder->end) return false; add_after(iterator->node, filter, post_init_func, user_data); return true; } void grpc_channel_stack_builder_destroy(grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder) { filter_node *p = builder->begin.next; while (p != &builder->end) { filter_node *next = p->next; gpr_free(p); p = next; } if (builder->args != NULL) { grpc_channel_args_destroy(exec_ctx, builder->args); } gpr_free(builder->target); gpr_free(builder); } grpc_error *grpc_channel_stack_builder_finish( grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, size_t prefix_bytes, int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg, void **result) { // count the number of filters size_t num_filters = 0; for (filter_node *p = builder->begin.next; p != &builder->end; p = p->next) { num_filters++; } // create an array of filters const grpc_channel_filter **filters = gpr_malloc(sizeof(*filters) * num_filters); size_t i = 0; for (filter_node *p = builder->begin.next; p != &builder->end; p = p->next) { filters[i++] = p->filter; } // calculate the size of the channel stack size_t channel_stack_size = grpc_channel_stack_size(filters, num_filters); // allocate memory, with prefix_bytes followed by channel_stack_size *result = gpr_zalloc(prefix_bytes + channel_stack_size); // fetch a pointer to the channel stack grpc_channel_stack *channel_stack = (grpc_channel_stack *)((char *)(*result) + prefix_bytes); // and initialize it grpc_error *error = grpc_channel_stack_init( exec_ctx, initial_refs, destroy, destroy_arg == NULL ? *result : destroy_arg, filters, num_filters, builder->args, builder->transport, builder->name, channel_stack); if (error != GRPC_ERROR_NONE) { grpc_channel_stack_destroy(exec_ctx, channel_stack); gpr_free(*result); *result = NULL; } else { // run post-initialization functions i = 0; for (filter_node *p = builder->begin.next; p != &builder->end; p = p->next) { if (p->init != NULL) { p->init(channel_stack, grpc_channel_stack_element(channel_stack, i), p->init_arg); } i++; } } grpc_channel_stack_builder_destroy(exec_ctx, builder); gpr_free((grpc_channel_filter **)filters); return error; } grpc-1.3.2/src/core/lib/channel/channel_stack_builder.h000066400000000000000000000154121310511640000230130ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_CHANNEL_CHANNEL_STACK_BUILDER_H #define GRPC_CORE_LIB_CHANNEL_CHANNEL_STACK_BUILDER_H #include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_stack.h" #ifdef __cplusplus extern "C" { #endif /// grpc_channel_stack_builder offers a programmatic interface to selected /// and order channel filters typedef struct grpc_channel_stack_builder grpc_channel_stack_builder; typedef struct grpc_channel_stack_builder_iterator grpc_channel_stack_builder_iterator; /// Create a new channel stack builder grpc_channel_stack_builder *grpc_channel_stack_builder_create(void); /// Assign a name to the channel stack: \a name must be statically allocated void grpc_channel_stack_builder_set_name(grpc_channel_stack_builder *builder, const char *name); /// Set the target uri void grpc_channel_stack_builder_set_target(grpc_channel_stack_builder *b, const char *target); const char *grpc_channel_stack_builder_get_target( grpc_channel_stack_builder *b); /// Attach \a transport to the builder (does not take ownership) void grpc_channel_stack_builder_set_transport( grpc_channel_stack_builder *builder, grpc_transport *transport); /// Fetch attached transport grpc_transport *grpc_channel_stack_builder_get_transport( grpc_channel_stack_builder *builder); /// Set channel arguments: copies args void grpc_channel_stack_builder_set_channel_arguments( grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, const grpc_channel_args *args); /// Return a borrowed pointer to the channel arguments const grpc_channel_args *grpc_channel_stack_builder_get_channel_arguments( grpc_channel_stack_builder *builder); /// Begin iterating over already defined filters in the builder at the beginning grpc_channel_stack_builder_iterator * grpc_channel_stack_builder_create_iterator_at_first( grpc_channel_stack_builder *builder); /// Begin iterating over already defined filters in the builder at the end grpc_channel_stack_builder_iterator * grpc_channel_stack_builder_create_iterator_at_last( grpc_channel_stack_builder *builder); /// Is an iterator at the first element? bool grpc_channel_stack_builder_iterator_is_first( grpc_channel_stack_builder_iterator *iterator); /// Is an iterator at the end? bool grpc_channel_stack_builder_iterator_is_end( grpc_channel_stack_builder_iterator *iterator); /// Move an iterator to the next item bool grpc_channel_stack_builder_move_next( grpc_channel_stack_builder_iterator *iterator); /// Move an iterator to the previous item bool grpc_channel_stack_builder_move_prev( grpc_channel_stack_builder_iterator *iterator); typedef void (*grpc_post_filter_create_init_func)( grpc_channel_stack *channel_stack, grpc_channel_element *elem, void *arg); /// Add \a filter to the stack, after \a iterator. /// Call \a post_init_func(..., \a user_data) once the channel stack is /// created. bool grpc_channel_stack_builder_add_filter_after( grpc_channel_stack_builder_iterator *iterator, const grpc_channel_filter *filter, grpc_post_filter_create_init_func post_init_func, void *user_data) GRPC_MUST_USE_RESULT; /// Add \a filter to the stack, before \a iterator. /// Call \a post_init_func(..., \a user_data) once the channel stack is /// created. bool grpc_channel_stack_builder_add_filter_before( grpc_channel_stack_builder_iterator *iterator, const grpc_channel_filter *filter, grpc_post_filter_create_init_func post_init_func, void *user_data) GRPC_MUST_USE_RESULT; /// Add \a filter to the beginning of the filter list. /// Call \a post_init_func(..., \a user_data) once the channel stack is /// created. bool grpc_channel_stack_builder_prepend_filter( grpc_channel_stack_builder *builder, const grpc_channel_filter *filter, grpc_post_filter_create_init_func post_init_func, void *user_data) GRPC_MUST_USE_RESULT; /// Add \a filter to the end of the filter list. /// Call \a post_init_func(..., \a user_data) once the channel stack is /// created. bool grpc_channel_stack_builder_append_filter( grpc_channel_stack_builder *builder, const grpc_channel_filter *filter, grpc_post_filter_create_init_func post_init_func, void *user_data) GRPC_MUST_USE_RESULT; /// Terminate iteration and destroy \a iterator void grpc_channel_stack_builder_iterator_destroy( grpc_channel_stack_builder_iterator *iterator); /// Destroy the builder, return the freshly minted channel stack in \a result. /// Allocates \a prefix_bytes bytes before the channel stack /// Returns the base pointer of the allocated block /// \a initial_refs, \a destroy, \a destroy_arg are as per /// grpc_channel_stack_init grpc_error *grpc_channel_stack_builder_finish( grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, size_t prefix_bytes, int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg, void **result); /// Destroy the builder without creating a channel stack void grpc_channel_stack_builder_destroy(grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder); extern int grpc_trace_channel_stack_builder; #ifdef __cplusplus } #endif #endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_STACK_BUILDER_H */ grpc-1.3.2/src/core/lib/channel/compress_filter.c000066400000000000000000000327031310511640000217050ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/compress_filter.h" #include "src/core/lib/compression/algorithm_metadata.h" #include "src/core/lib/compression/message_compress.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/string.h" #include "src/core/lib/transport/static_metadata.h" int grpc_compression_trace = 0; typedef struct call_data { grpc_slice_buffer slices; /**< Buffers up input slices to be compressed */ grpc_linked_mdelem compression_algorithm_storage; grpc_linked_mdelem accept_encoding_storage; uint32_t remaining_slice_bytes; /** Compression algorithm we'll try to use. It may be given by incoming * metadata, or by the channel's default compression settings. */ grpc_compression_algorithm compression_algorithm; /** If true, contents of \a compression_algorithm are authoritative */ int has_compression_algorithm; grpc_transport_stream_op_batch *send_op; uint32_t send_length; uint32_t send_flags; grpc_slice incoming_slice; grpc_slice_buffer_stream replacement_stream; grpc_closure *post_send; grpc_closure send_done; grpc_closure got_slice; } call_data; typedef struct channel_data { /** The default, channel-level, compression algorithm */ grpc_compression_algorithm default_compression_algorithm; /** Bitset of enabled algorithms */ uint32_t enabled_algorithms_bitset; /** Supported compression algorithms */ uint32_t supported_compression_algorithms; } channel_data; static int skip_compression(grpc_call_element *elem, uint32_t flags) { call_data *calld = elem->call_data; channel_data *channeld = elem->channel_data; if (flags & (GRPC_WRITE_NO_COMPRESS | GRPC_WRITE_INTERNAL_COMPRESS)) { return 1; } if (calld->has_compression_algorithm) { if (calld->compression_algorithm == GRPC_COMPRESS_NONE) { return 1; } return 0; /* we have an actual call-specific algorithm */ } /* no per-call compression override */ return channeld->default_compression_algorithm == GRPC_COMPRESS_NONE; } /** Filter initial metadata */ static grpc_error *process_send_initial_metadata( grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_metadata_batch *initial_metadata) GRPC_MUST_USE_RESULT; static grpc_error *process_send_initial_metadata( grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_metadata_batch *initial_metadata) { call_data *calld = elem->call_data; channel_data *channeld = elem->channel_data; /* Parse incoming request for compression. If any, it'll be available * at calld->compression_algorithm */ if (initial_metadata->idx.named.grpc_internal_encoding_request != NULL) { grpc_mdelem md = initial_metadata->idx.named.grpc_internal_encoding_request->md; if (!grpc_compression_algorithm_parse(GRPC_MDVALUE(md), &calld->compression_algorithm)) { char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md)); gpr_log(GPR_ERROR, "Invalid compression algorithm: '%s' (unknown). Ignoring.", val); gpr_free(val); calld->compression_algorithm = GRPC_COMPRESS_NONE; } if (!GPR_BITGET(channeld->enabled_algorithms_bitset, calld->compression_algorithm)) { char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md)); gpr_log(GPR_ERROR, "Invalid compression algorithm: '%s' (previously disabled). " "Ignoring.", val); gpr_free(val); calld->compression_algorithm = GRPC_COMPRESS_NONE; } calld->has_compression_algorithm = 1; grpc_metadata_batch_remove( exec_ctx, initial_metadata, initial_metadata->idx.named.grpc_internal_encoding_request); } else { /* If no algorithm was found in the metadata and we aren't * exceptionally skipping compression, fall back to the channel * default */ calld->compression_algorithm = channeld->default_compression_algorithm; calld->has_compression_algorithm = 1; /* GPR_TRUE */ } grpc_error *error = GRPC_ERROR_NONE; /* hint compression algorithm */ if (calld->compression_algorithm != GRPC_COMPRESS_NONE) { error = grpc_metadata_batch_add_tail( exec_ctx, initial_metadata, &calld->compression_algorithm_storage, grpc_compression_encoding_mdelem(calld->compression_algorithm)); } if (error != GRPC_ERROR_NONE) return error; /* convey supported compression algorithms */ error = grpc_metadata_batch_add_tail( exec_ctx, initial_metadata, &calld->accept_encoding_storage, GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS( channeld->supported_compression_algorithms)); return error; } static void continue_send_message(grpc_exec_ctx *exec_ctx, grpc_call_element *elem); static void send_done(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) { grpc_call_element *elem = elemp; call_data *calld = elem->call_data; grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &calld->slices); calld->post_send->cb(exec_ctx, calld->post_send->cb_arg, error); } static void finish_send_message(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { call_data *calld = elem->call_data; int did_compress; grpc_slice_buffer tmp; grpc_slice_buffer_init(&tmp); did_compress = grpc_msg_compress(exec_ctx, calld->compression_algorithm, &calld->slices, &tmp); if (did_compress) { if (grpc_compression_trace) { char *algo_name; const size_t before_size = calld->slices.length; const size_t after_size = tmp.length; const float savings_ratio = 1.0f - (float)after_size / (float)before_size; GPR_ASSERT(grpc_compression_algorithm_name(calld->compression_algorithm, &algo_name)); gpr_log(GPR_DEBUG, "Compressed[%s] %" PRIuPTR " bytes vs. %" PRIuPTR " bytes (%.2f%% savings)", algo_name, before_size, after_size, 100 * savings_ratio); } grpc_slice_buffer_swap(&calld->slices, &tmp); calld->send_flags |= GRPC_WRITE_INTERNAL_COMPRESS; } else { if (grpc_compression_trace) { char *algo_name; GPR_ASSERT(grpc_compression_algorithm_name(calld->compression_algorithm, &algo_name)); gpr_log(GPR_DEBUG, "Algorithm '%s' enabled but decided not to compress. Input size: " "%" PRIuPTR, algo_name, calld->slices.length); } } grpc_slice_buffer_destroy_internal(exec_ctx, &tmp); grpc_slice_buffer_stream_init(&calld->replacement_stream, &calld->slices, calld->send_flags); calld->send_op->payload->send_message.send_message = &calld->replacement_stream.base; calld->post_send = calld->send_op->on_complete; calld->send_op->on_complete = &calld->send_done; grpc_call_next_op(exec_ctx, elem, calld->send_op); } static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) { grpc_call_element *elem = elemp; call_data *calld = elem->call_data; grpc_slice_buffer_add(&calld->slices, calld->incoming_slice); if (calld->send_length == calld->slices.length) { finish_send_message(exec_ctx, elem); } else { continue_send_message(exec_ctx, elem); } } static void continue_send_message(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { call_data *calld = elem->call_data; while (grpc_byte_stream_next( exec_ctx, calld->send_op->payload->send_message.send_message, &calld->incoming_slice, ~(size_t)0, &calld->got_slice)) { grpc_slice_buffer_add(&calld->slices, calld->incoming_slice); if (calld->send_length == calld->slices.length) { finish_send_message(exec_ctx, elem); break; } } } static void compress_start_transport_stream_op_batch( grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op_batch *op) { call_data *calld = elem->call_data; GPR_TIMER_BEGIN("compress_start_transport_stream_op_batch", 0); if (op->send_initial_metadata) { grpc_error *error = process_send_initial_metadata( exec_ctx, elem, op->payload->send_initial_metadata.send_initial_metadata); if (error != GRPC_ERROR_NONE) { grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, op, error); return; } } if (op->send_message && !skip_compression(elem, op->payload->send_message.send_message->flags)) { calld->send_op = op; calld->send_length = op->payload->send_message.send_message->length; calld->send_flags = op->payload->send_message.send_message->flags; continue_send_message(exec_ctx, elem); } else { /* pass control down the stack */ grpc_call_next_op(exec_ctx, elem, op); } GPR_TIMER_END("compress_start_transport_stream_op_batch", 0); } /* Constructor for call_data */ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_element_args *args) { /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; /* initialize members */ grpc_slice_buffer_init(&calld->slices); calld->has_compression_algorithm = 0; grpc_closure_init(&calld->got_slice, got_slice, elem, grpc_schedule_on_exec_ctx); grpc_closure_init(&calld->send_done, send_done, elem, grpc_schedule_on_exec_ctx); return GRPC_ERROR_NONE; } /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, grpc_closure *ignored) { /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; grpc_slice_buffer_destroy_internal(exec_ctx, &calld->slices); } /* Constructor for channel_data */ static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_channel_element_args *args) { channel_data *channeld = elem->channel_data; channeld->enabled_algorithms_bitset = grpc_channel_args_compression_algorithm_get_states(args->channel_args); channeld->default_compression_algorithm = grpc_channel_args_get_compression_algorithm(args->channel_args); /* Make sure the default isn't disabled. */ if (!GPR_BITGET(channeld->enabled_algorithms_bitset, channeld->default_compression_algorithm)) { gpr_log(GPR_DEBUG, "compression algorithm %d not enabled: switching to none", channeld->default_compression_algorithm); channeld->default_compression_algorithm = GRPC_COMPRESS_NONE; } channeld->supported_compression_algorithms = 1; /* always support identity */ for (grpc_compression_algorithm algo_idx = 1; algo_idx < GRPC_COMPRESS_ALGORITHMS_COUNT; ++algo_idx) { /* skip disabled algorithms */ if (!GPR_BITGET(channeld->enabled_algorithms_bitset, algo_idx)) { continue; } channeld->supported_compression_algorithms |= 1u << algo_idx; } GPR_ASSERT(!args->is_last); return GRPC_ERROR_NONE; } /* Destructor for channel data */ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) {} const grpc_channel_filter grpc_compress_filter = { compress_start_transport_stream_op_batch, grpc_channel_next_op, sizeof(call_data), init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, destroy_call_elem, sizeof(channel_data), init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer, grpc_channel_next_get_info, "compress"}; grpc-1.3.2/src/core/lib/channel/compress_filter.h000066400000000000000000000055441310511640000217150ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_CHANNEL_COMPRESS_FILTER_H #define GRPC_CORE_LIB_CHANNEL_COMPRESS_FILTER_H #include #include "src/core/lib/channel/channel_stack.h" extern int grpc_compression_trace; /** Compression filter for outgoing data. * * See for the available compression settings. * * Compression settings may come from: * - Channel configuration, as established at channel creation time. * - The metadata accompanying the outgoing data to be compressed. This is * taken as a request only. We may choose not to honor it. The metadata key * is given by \a GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY. * * Compression can be disabled for concrete messages (for instance in order to * prevent CRIME/BEAST type attacks) by having the GRPC_WRITE_NO_COMPRESS set in * the BEGIN_MESSAGE flags. * * The attempted compression mechanism is added to the resulting initial * metadata under the'grpc-encoding' key. * * If compression is actually performed, BEGIN_MESSAGE's flag is modified to * incorporate GRPC_WRITE_INTERNAL_COMPRESS. Otherwise, and regardless of the * aforementioned 'grpc-encoding' metadata value, data will pass through * uncompressed. */ extern const grpc_channel_filter grpc_compress_filter; #endif /* GRPC_CORE_LIB_CHANNEL_COMPRESS_FILTER_H */ grpc-1.3.2/src/core/lib/channel/connected_channel.c000066400000000000000000000167101310511640000221370ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/channel/connected_channel.h" #include #include #include #include #include #include #include #include "src/core/lib/profiling/timers.h" #include "src/core/lib/support/string.h" #include "src/core/lib/transport/transport.h" #define MAX_BUFFER_LENGTH 8192 typedef struct connected_channel_channel_data { grpc_transport *transport; } channel_data; typedef struct connected_channel_call_data { void *unused; } call_data; /* We perform a small hack to locate transport data alongside the connected channel data in call allocations, to allow everything to be pulled in minimal cache line requests */ #define TRANSPORT_STREAM_FROM_CALL_DATA(calld) ((grpc_stream *)((calld) + 1)) #define CALL_DATA_FROM_TRANSPORT_STREAM(transport_stream) \ (((call_data *)(transport_stream)) - 1) /* Intercept a call operation and either push it directly up or translate it into transport stream operations */ static void con_start_transport_stream_op_batch( grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op_batch *op) { call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; GRPC_CALL_LOG_OP(GPR_INFO, elem, op); grpc_transport_perform_stream_op(exec_ctx, chand->transport, TRANSPORT_STREAM_FROM_CALL_DATA(calld), op); } static void con_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_transport_op *op) { channel_data *chand = elem->channel_data; grpc_transport_perform_op(exec_ctx, chand->transport, op); } /* Constructor for call_data */ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_element_args *args) { call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; int r = grpc_transport_init_stream( exec_ctx, chand->transport, TRANSPORT_STREAM_FROM_CALL_DATA(calld), &args->call_stack->refcount, args->server_transport_data, args->arena); return r == 0 ? GRPC_ERROR_NONE : GRPC_ERROR_CREATE_FROM_STATIC_STRING( "transport stream initialization failed"); } static void set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_polling_entity *pollent) { call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; grpc_transport_set_pops(exec_ctx, chand->transport, TRANSPORT_STREAM_FROM_CALL_DATA(calld), pollent); } /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, grpc_closure *then_schedule_closure) { call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; grpc_transport_destroy_stream(exec_ctx, chand->transport, TRANSPORT_STREAM_FROM_CALL_DATA(calld), then_schedule_closure); } /* Constructor for channel_data */ static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_channel_element_args *args) { channel_data *cd = (channel_data *)elem->channel_data; GPR_ASSERT(args->is_last); cd->transport = NULL; return GRPC_ERROR_NONE; } /* Destructor for channel_data */ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) { channel_data *cd = (channel_data *)elem->channel_data; grpc_transport_destroy(exec_ctx, cd->transport); } static char *con_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { channel_data *chand = elem->channel_data; return grpc_transport_get_peer(exec_ctx, chand->transport); } /* No-op. */ static void con_get_channel_info(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, const grpc_channel_info *channel_info) {} const grpc_channel_filter grpc_connected_filter = { con_start_transport_stream_op_batch, con_start_transport_op, sizeof(call_data), init_call_elem, set_pollset_or_pollset_set, destroy_call_elem, sizeof(channel_data), init_channel_elem, destroy_channel_elem, con_get_peer, con_get_channel_info, "connected", }; static void bind_transport(grpc_channel_stack *channel_stack, grpc_channel_element *elem, void *t) { channel_data *cd = (channel_data *)elem->channel_data; GPR_ASSERT(elem->filter == &grpc_connected_filter); GPR_ASSERT(cd->transport == NULL); cd->transport = t; /* HACK(ctiller): increase call stack size for the channel to make space for channel data. We need a cleaner (but performant) way to do this, and I'm not sure what that is yet. This is only "safe" because call stacks place no additional data after the last call element, and the last call element MUST be the connected channel. */ channel_stack->call_stack_size += grpc_transport_stream_size(t); } bool grpc_add_connected_filter(grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, void *arg_must_be_null) { GPR_ASSERT(arg_must_be_null == NULL); grpc_transport *t = grpc_channel_stack_builder_get_transport(builder); GPR_ASSERT(t != NULL); return grpc_channel_stack_builder_append_filter( builder, &grpc_connected_filter, bind_transport, t); } grpc_stream *grpc_connected_channel_get_stream(grpc_call_element *elem) { call_data *calld = elem->call_data; return TRANSPORT_STREAM_FROM_CALL_DATA(calld); } grpc-1.3.2/src/core/lib/channel/connected_channel.h000066400000000000000000000041641310511640000221440ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_CHANNEL_CONNECTED_CHANNEL_H #define GRPC_CORE_LIB_CHANNEL_CONNECTED_CHANNEL_H #include "src/core/lib/channel/channel_stack_builder.h" extern const grpc_channel_filter grpc_connected_filter; bool grpc_add_connected_filter(grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, void *arg_must_be_null); /* Debug helper to dig the transport stream out of a call element */ grpc_stream *grpc_connected_channel_get_stream(grpc_call_element *elem); #endif /* GRPC_CORE_LIB_CHANNEL_CONNECTED_CHANNEL_H */ grpc-1.3.2/src/core/lib/channel/context.h000066400000000000000000000045161310511640000201770ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_CHANNEL_CONTEXT_H #define GRPC_CORE_LIB_CHANNEL_CONTEXT_H /// Call object context pointers. /// Call context is represented as an array of \a grpc_call_context_elements. /// This enum represents the indexes into the array, where each index /// contains a different type of value. typedef enum { /// Value is either a \a grpc_client_security_context or a /// \a grpc_server_security_context. GRPC_CONTEXT_SECURITY = 0, /// Value is a \a census_context. GRPC_CONTEXT_TRACING, /// Reserved for traffic_class_context. GRPC_CONTEXT_TRAFFIC, /// Costs for Load Reporting. GRPC_CONTEXT_LR_COST, GRPC_CONTEXT_COUNT } grpc_context_index; typedef struct { void *value; void (*destroy)(void *); } grpc_call_context_element; #endif /* GRPC_CORE_LIB_CHANNEL_CONTEXT_H */ grpc-1.3.2/src/core/lib/channel/deadline_filter.c000066400000000000000000000334411310511640000216170ustar00rootroot00000000000000// // Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #include "src/core/lib/channel/deadline_filter.h" #include #include #include #include #include #include #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/slice/slice_internal.h" // // grpc_deadline_state // // Timer callback. static void timer_callback(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { grpc_call_element* elem = arg; grpc_deadline_state* deadline_state = elem->call_data; if (error != GRPC_ERROR_CANCELLED) { grpc_call_element_signal_error( exec_ctx, elem, grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Deadline Exceeded"), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_DEADLINE_EXCEEDED)); } GRPC_CALL_STACK_UNREF(exec_ctx, deadline_state->call_stack, "deadline_timer"); } // Starts the deadline timer. static void start_timer_if_needed(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, gpr_timespec deadline) { deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC); if (gpr_time_cmp(deadline, gpr_inf_future(GPR_CLOCK_MONOTONIC)) == 0) { return; } grpc_deadline_state* deadline_state = elem->call_data; grpc_deadline_timer_state cur_state; grpc_closure* closure = NULL; retry: cur_state = (grpc_deadline_timer_state)gpr_atm_acq_load(&deadline_state->timer_state); switch (cur_state) { case GRPC_DEADLINE_STATE_PENDING: // Note: We do not start the timer if there is already a timer return; case GRPC_DEADLINE_STATE_FINISHED: if (gpr_atm_rel_cas(&deadline_state->timer_state, GRPC_DEADLINE_STATE_FINISHED, GRPC_DEADLINE_STATE_PENDING)) { // If we've already created and destroyed a timer, we always create a // new closure: we have no other guarantee that the inlined closure is // not in use (it may hold a pending call to timer_callback) closure = grpc_closure_create(timer_callback, elem, grpc_schedule_on_exec_ctx); } else { goto retry; } break; case GRPC_DEADLINE_STATE_INITIAL: if (gpr_atm_rel_cas(&deadline_state->timer_state, GRPC_DEADLINE_STATE_INITIAL, GRPC_DEADLINE_STATE_PENDING)) { closure = grpc_closure_init(&deadline_state->timer_callback, timer_callback, elem, grpc_schedule_on_exec_ctx); } else { goto retry; } break; } GPR_ASSERT(closure); GRPC_CALL_STACK_REF(deadline_state->call_stack, "deadline_timer"); grpc_timer_init(exec_ctx, &deadline_state->timer, deadline, closure, gpr_now(GPR_CLOCK_MONOTONIC)); } // Cancels the deadline timer. static void cancel_timer_if_needed(grpc_exec_ctx* exec_ctx, grpc_deadline_state* deadline_state) { if (gpr_atm_rel_cas(&deadline_state->timer_state, GRPC_DEADLINE_STATE_PENDING, GRPC_DEADLINE_STATE_FINISHED)) { grpc_timer_cancel(exec_ctx, &deadline_state->timer); } else { // timer was either in STATE_INITAL (nothing to cancel) // OR in STATE_FINISHED (again nothing to cancel) } } // Callback run when the call is complete. static void on_complete(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { grpc_deadline_state* deadline_state = arg; cancel_timer_if_needed(exec_ctx, deadline_state); // Invoke the next callback. grpc_closure_run(exec_ctx, deadline_state->next_on_complete, GRPC_ERROR_REF(error)); } // Inject our own on_complete callback into op. static void inject_on_complete_cb(grpc_deadline_state* deadline_state, grpc_transport_stream_op_batch* op) { deadline_state->next_on_complete = op->on_complete; grpc_closure_init(&deadline_state->on_complete, on_complete, deadline_state, grpc_schedule_on_exec_ctx); op->on_complete = &deadline_state->on_complete; } void grpc_deadline_state_init(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_call_stack* call_stack) { grpc_deadline_state* deadline_state = elem->call_data; deadline_state->call_stack = call_stack; } void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx, grpc_call_element* elem) { grpc_deadline_state* deadline_state = elem->call_data; cancel_timer_if_needed(exec_ctx, deadline_state); } // Callback and associated state for starting the timer after call stack // initialization has been completed. struct start_timer_after_init_state { grpc_call_element* elem; gpr_timespec deadline; grpc_closure closure; }; static void start_timer_after_init(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { struct start_timer_after_init_state* state = arg; start_timer_if_needed(exec_ctx, state->elem, state->deadline); gpr_free(state); } void grpc_deadline_state_start(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, gpr_timespec deadline) { // Deadline will always be infinite on servers, so the timer will only be // set on clients with a finite deadline. deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC); if (gpr_time_cmp(deadline, gpr_inf_future(GPR_CLOCK_MONOTONIC)) != 0) { // When the deadline passes, we indicate the failure by sending down // an op with cancel_error set. However, we can't send down any ops // until after the call stack is fully initialized. If we start the // timer here, we have no guarantee that the timer won't pop before // call stack initialization is finished. To avoid that problem, we // create a closure to start the timer, and we schedule that closure // to be run after call stack initialization is done. struct start_timer_after_init_state* state = gpr_malloc(sizeof(*state)); state->elem = elem; state->deadline = deadline; grpc_closure_init(&state->closure, start_timer_after_init, state, grpc_schedule_on_exec_ctx); grpc_closure_sched(exec_ctx, &state->closure, GRPC_ERROR_NONE); } } void grpc_deadline_state_reset(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, gpr_timespec new_deadline) { grpc_deadline_state* deadline_state = elem->call_data; cancel_timer_if_needed(exec_ctx, deadline_state); start_timer_if_needed(exec_ctx, elem, new_deadline); } void grpc_deadline_state_client_start_transport_stream_op_batch( grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_transport_stream_op_batch* op) { grpc_deadline_state* deadline_state = elem->call_data; if (op->cancel_stream) { cancel_timer_if_needed(exec_ctx, deadline_state); } else { // Make sure we know when the call is complete, so that we can cancel // the timer. if (op->recv_trailing_metadata) { inject_on_complete_cb(deadline_state, op); } } } // // filter code // // Constructor for channel_data. Used for both client and server filters. static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx, grpc_channel_element* elem, grpc_channel_element_args* args) { GPR_ASSERT(!args->is_last); return GRPC_ERROR_NONE; } // Destructor for channel_data. Used for both client and server filters. static void destroy_channel_elem(grpc_exec_ctx* exec_ctx, grpc_channel_element* elem) {} // Call data used for both client and server filter. typedef struct base_call_data { grpc_deadline_state deadline_state; } base_call_data; // Additional call data used only for the server filter. typedef struct server_call_data { base_call_data base; // Must be first. // The closure for receiving initial metadata. grpc_closure recv_initial_metadata_ready; // Received initial metadata batch. grpc_metadata_batch* recv_initial_metadata; // The original recv_initial_metadata_ready closure, which we chain to // after our own closure is invoked. grpc_closure* next_recv_initial_metadata_ready; } server_call_data; // Constructor for call_data. Used for both client and server filters. static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, const grpc_call_element_args* args) { grpc_deadline_state_init(exec_ctx, elem, args->call_stack); grpc_deadline_state_start(exec_ctx, elem, args->deadline); return GRPC_ERROR_NONE; } // Destructor for call_data. Used for both client and server filters. static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, const grpc_call_final_info* final_info, grpc_closure* ignored) { grpc_deadline_state_destroy(exec_ctx, elem); } // Method for starting a call op for client filter. static void client_start_transport_stream_op_batch( grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_transport_stream_op_batch* op) { grpc_deadline_state_client_start_transport_stream_op_batch(exec_ctx, elem, op); // Chain to next filter. grpc_call_next_op(exec_ctx, elem, op); } // Callback for receiving initial metadata on the server. static void recv_initial_metadata_ready(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { grpc_call_element* elem = arg; server_call_data* calld = elem->call_data; // Get deadline from metadata and start the timer if needed. start_timer_if_needed(exec_ctx, elem, calld->recv_initial_metadata->deadline); // Invoke the next callback. calld->next_recv_initial_metadata_ready->cb( exec_ctx, calld->next_recv_initial_metadata_ready->cb_arg, error); } // Method for starting a call op for server filter. static void server_start_transport_stream_op_batch( grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_transport_stream_op_batch* op) { server_call_data* calld = elem->call_data; if (op->cancel_stream) { cancel_timer_if_needed(exec_ctx, &calld->base.deadline_state); } else { // If we're receiving initial metadata, we need to get the deadline // from the recv_initial_metadata_ready callback. So we inject our // own callback into that hook. if (op->recv_initial_metadata) { calld->next_recv_initial_metadata_ready = op->payload->recv_initial_metadata.recv_initial_metadata_ready; calld->recv_initial_metadata = op->payload->recv_initial_metadata.recv_initial_metadata; grpc_closure_init(&calld->recv_initial_metadata_ready, recv_initial_metadata_ready, elem, grpc_schedule_on_exec_ctx); op->payload->recv_initial_metadata.recv_initial_metadata_ready = &calld->recv_initial_metadata_ready; } // Make sure we know when the call is complete, so that we can cancel // the timer. // Note that we trigger this on recv_trailing_metadata, even though // the client never sends trailing metadata, because this is the // hook that tells us when the call is complete on the server side. if (op->recv_trailing_metadata) { inject_on_complete_cb(&calld->base.deadline_state, op); } } // Chain to next filter. grpc_call_next_op(exec_ctx, elem, op); } const grpc_channel_filter grpc_client_deadline_filter = { client_start_transport_stream_op_batch, grpc_channel_next_op, sizeof(base_call_data), init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, destroy_call_elem, 0, // sizeof(channel_data) init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer, grpc_channel_next_get_info, "deadline", }; const grpc_channel_filter grpc_server_deadline_filter = { server_start_transport_stream_op_batch, grpc_channel_next_op, sizeof(server_call_data), init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, destroy_call_elem, 0, // sizeof(channel_data) init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer, grpc_channel_next_get_info, "deadline", }; grpc-1.3.2/src/core/lib/channel/deadline_filter.h000066400000000000000000000106241310511640000216220ustar00rootroot00000000000000// // Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #ifndef GRPC_CORE_LIB_CHANNEL_DEADLINE_FILTER_H #define GRPC_CORE_LIB_CHANNEL_DEADLINE_FILTER_H #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/iomgr/timer.h" typedef enum grpc_deadline_timer_state { GRPC_DEADLINE_STATE_INITIAL, GRPC_DEADLINE_STATE_PENDING, GRPC_DEADLINE_STATE_FINISHED } grpc_deadline_timer_state; // State used for filters that enforce call deadlines. // Must be the first field in the filter's call_data. typedef struct grpc_deadline_state { // We take a reference to the call stack for the timer callback. grpc_call_stack* call_stack; gpr_atm timer_state; grpc_timer timer; grpc_closure timer_callback; // Closure to invoke when the call is complete. // We use this to cancel the timer. grpc_closure on_complete; // The original on_complete closure, which we chain to after our own // closure is invoked. grpc_closure* next_on_complete; } grpc_deadline_state; // // NOTE: All of these functions require that the first field in // elem->call_data is a grpc_deadline_state. // // assumes elem->call_data is zero'd void grpc_deadline_state_init(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_call_stack* call_stack); void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx, grpc_call_element* elem); // Starts the timer with the specified deadline. // Should be called from the filter's init_call_elem() method. void grpc_deadline_state_start(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, gpr_timespec deadline); // Cancels the existing timer and starts a new one with new_deadline. // // Note: It is generally safe to call this with an earlier deadline // value than the current one, but not the reverse. No checks are done // to ensure that the timer callback is not invoked while it is in the // process of being reset, which means that attempting to increase the // deadline may result in the timer being called twice. void grpc_deadline_state_reset(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, gpr_timespec new_deadline); // To be called from the client-side filter's start_transport_stream_op_batch() // method. Ensures that the deadline timer is cancelled when the call // is completed. // // Note: It is the caller's responsibility to chain to the next filter if // necessary after this function returns. void grpc_deadline_state_client_start_transport_stream_op_batch( grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_transport_stream_op_batch* op); // Deadline filters for direct client channels and server channels. // Note: Deadlines for non-direct client channels are handled by the // client_channel filter. extern const grpc_channel_filter grpc_client_deadline_filter; extern const grpc_channel_filter grpc_server_deadline_filter; #endif /* GRPC_CORE_LIB_CHANNEL_DEADLINE_FILTER_H */ grpc-1.3.2/src/core/lib/channel/handshaker.c000066400000000000000000000245131310511640000206150ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/handshaker.h" #include "src/core/lib/iomgr/timer.h" // // grpc_handshaker // void grpc_handshaker_init(const grpc_handshaker_vtable* vtable, grpc_handshaker* handshaker) { handshaker->vtable = vtable; } void grpc_handshaker_destroy(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker) { handshaker->vtable->destroy(exec_ctx, handshaker); } void grpc_handshaker_shutdown(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker, grpc_error* why) { handshaker->vtable->shutdown(exec_ctx, handshaker, why); } void grpc_handshaker_do_handshake(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker, grpc_tcp_server_acceptor* acceptor, grpc_closure* on_handshake_done, grpc_handshaker_args* args) { handshaker->vtable->do_handshake(exec_ctx, handshaker, acceptor, on_handshake_done, args); } // // grpc_handshake_manager // struct grpc_handshake_manager { gpr_mu mu; gpr_refcount refs; bool shutdown; // An array of handshakers added via grpc_handshake_manager_add(). size_t count; grpc_handshaker** handshakers; // The index of the handshaker to invoke next and closure to invoke it. size_t index; grpc_closure call_next_handshaker; // The acceptor to call the handshakers with. grpc_tcp_server_acceptor* acceptor; // Deadline timer across all handshakers. grpc_timer deadline_timer; grpc_closure on_timeout; // The final callback and user_data to invoke after the last handshaker. grpc_closure on_handshake_done; void* user_data; // Handshaker args. grpc_handshaker_args args; // Links to the previous and next managers in a list of all pending handshakes // Used at server side only. grpc_handshake_manager* prev; grpc_handshake_manager* next; }; grpc_handshake_manager* grpc_handshake_manager_create() { grpc_handshake_manager* mgr = gpr_zalloc(sizeof(grpc_handshake_manager)); gpr_mu_init(&mgr->mu); gpr_ref_init(&mgr->refs, 1); return mgr; } void grpc_handshake_manager_pending_list_add(grpc_handshake_manager** head, grpc_handshake_manager* mgr) { GPR_ASSERT(mgr->prev == NULL); GPR_ASSERT(mgr->next == NULL); mgr->next = *head; if (*head) { (*head)->prev = mgr; } *head = mgr; } void grpc_handshake_manager_pending_list_remove(grpc_handshake_manager** head, grpc_handshake_manager* mgr) { if (mgr->next != NULL) { mgr->next->prev = mgr->prev; } if (mgr->prev != NULL) { mgr->prev->next = mgr->next; } else { GPR_ASSERT(*head == mgr); *head = mgr->next; } } void grpc_handshake_manager_pending_list_shutdown_all( grpc_exec_ctx* exec_ctx, grpc_handshake_manager* head, grpc_error* why) { while (head != NULL) { grpc_handshake_manager_shutdown(exec_ctx, head, GRPC_ERROR_REF(why)); head = head->next; } GRPC_ERROR_UNREF(why); } static bool is_power_of_2(size_t n) { return (n & (n - 1)) == 0; } void grpc_handshake_manager_add(grpc_handshake_manager* mgr, grpc_handshaker* handshaker) { gpr_mu_lock(&mgr->mu); // To avoid allocating memory for each handshaker we add, we double // the number of elements every time we need more. size_t realloc_count = 0; if (mgr->count == 0) { realloc_count = 2; } else if (mgr->count >= 2 && is_power_of_2(mgr->count)) { realloc_count = mgr->count * 2; } if (realloc_count > 0) { mgr->handshakers = gpr_realloc(mgr->handshakers, realloc_count * sizeof(grpc_handshaker*)); } mgr->handshakers[mgr->count++] = handshaker; gpr_mu_unlock(&mgr->mu); } static void grpc_handshake_manager_unref(grpc_exec_ctx* exec_ctx, grpc_handshake_manager* mgr) { if (gpr_unref(&mgr->refs)) { for (size_t i = 0; i < mgr->count; ++i) { grpc_handshaker_destroy(exec_ctx, mgr->handshakers[i]); } gpr_free(mgr->handshakers); gpr_mu_destroy(&mgr->mu); gpr_free(mgr); } } void grpc_handshake_manager_destroy(grpc_exec_ctx* exec_ctx, grpc_handshake_manager* mgr) { grpc_handshake_manager_unref(exec_ctx, mgr); } void grpc_handshake_manager_shutdown(grpc_exec_ctx* exec_ctx, grpc_handshake_manager* mgr, grpc_error* why) { gpr_mu_lock(&mgr->mu); // Shutdown the handshaker that's currently in progress, if any. if (!mgr->shutdown && mgr->index > 0) { mgr->shutdown = true; grpc_handshaker_shutdown(exec_ctx, mgr->handshakers[mgr->index - 1], GRPC_ERROR_REF(why)); } gpr_mu_unlock(&mgr->mu); GRPC_ERROR_UNREF(why); } // Helper function to call either the next handshaker or the // on_handshake_done callback. // Returns true if we've scheduled the on_handshake_done callback. static bool call_next_handshaker_locked(grpc_exec_ctx* exec_ctx, grpc_handshake_manager* mgr, grpc_error* error) { GPR_ASSERT(mgr->index <= mgr->count); // If we got an error or we've been shut down or we're exiting early or // we've finished the last handshaker, invoke the on_handshake_done // callback. Otherwise, call the next handshaker. if (error != GRPC_ERROR_NONE || mgr->shutdown || mgr->args.exit_early || mgr->index == mgr->count) { // Cancel deadline timer, since we're invoking the on_handshake_done // callback now. grpc_timer_cancel(exec_ctx, &mgr->deadline_timer); grpc_closure_sched(exec_ctx, &mgr->on_handshake_done, error); mgr->shutdown = true; } else { grpc_handshaker_do_handshake(exec_ctx, mgr->handshakers[mgr->index], mgr->acceptor, &mgr->call_next_handshaker, &mgr->args); } ++mgr->index; return mgr->shutdown; } // A function used as the handshaker-done callback when chaining // handshakers together. static void call_next_handshaker(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { grpc_handshake_manager* mgr = arg; gpr_mu_lock(&mgr->mu); bool done = call_next_handshaker_locked(exec_ctx, mgr, GRPC_ERROR_REF(error)); gpr_mu_unlock(&mgr->mu); // If we're invoked the final callback, we won't be coming back // to this function, so we can release our reference to the // handshake manager. if (done) { grpc_handshake_manager_unref(exec_ctx, mgr); } } // Callback invoked when deadline is exceeded. static void on_timeout(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { grpc_handshake_manager* mgr = arg; if (error == GRPC_ERROR_NONE) { // Timer fired, rather than being cancelled. grpc_handshake_manager_shutdown( exec_ctx, mgr, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake timed out")); } grpc_handshake_manager_unref(exec_ctx, mgr); } void grpc_handshake_manager_do_handshake( grpc_exec_ctx* exec_ctx, grpc_handshake_manager* mgr, grpc_endpoint* endpoint, const grpc_channel_args* channel_args, gpr_timespec deadline, grpc_tcp_server_acceptor* acceptor, grpc_iomgr_cb_func on_handshake_done, void* user_data) { gpr_mu_lock(&mgr->mu); GPR_ASSERT(mgr->index == 0); GPR_ASSERT(!mgr->shutdown); // Construct handshaker args. These will be passed through all // handshakers and eventually be freed by the on_handshake_done callback. mgr->args.endpoint = endpoint; mgr->args.args = grpc_channel_args_copy(channel_args); mgr->args.user_data = user_data; mgr->args.read_buffer = gpr_malloc(sizeof(*mgr->args.read_buffer)); grpc_slice_buffer_init(mgr->args.read_buffer); // Initialize state needed for calling handshakers. mgr->acceptor = acceptor; grpc_closure_init(&mgr->call_next_handshaker, call_next_handshaker, mgr, grpc_schedule_on_exec_ctx); grpc_closure_init(&mgr->on_handshake_done, on_handshake_done, &mgr->args, grpc_schedule_on_exec_ctx); // Start deadline timer, which owns a ref. gpr_ref(&mgr->refs); grpc_closure_init(&mgr->on_timeout, on_timeout, mgr, grpc_schedule_on_exec_ctx); grpc_timer_init(exec_ctx, &mgr->deadline_timer, gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC), &mgr->on_timeout, gpr_now(GPR_CLOCK_MONOTONIC)); // Start first handshaker, which also owns a ref. gpr_ref(&mgr->refs); bool done = call_next_handshaker_locked(exec_ctx, mgr, GRPC_ERROR_NONE); gpr_mu_unlock(&mgr->mu); if (done) { grpc_handshake_manager_unref(exec_ctx, mgr); } } grpc-1.3.2/src/core/lib/channel/handshaker.h000066400000000000000000000174541310511640000206300ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_CHANNEL_HANDSHAKER_H #define GRPC_CORE_LIB_CHANNEL_HANDSHAKER_H #include #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/tcp_server.h" /// Handshakers are used to perform initial handshakes on a connection /// before the client sends the initial request. Some examples of what /// a handshaker can be used for includes support for HTTP CONNECT on /// the client side and various types of security initialization. /// /// In general, handshakers should be used via a handshake manager. /// /// grpc_handshaker /// typedef struct grpc_handshaker grpc_handshaker; /// Arguments passed through handshakers and to the on_handshake_done callback. /// /// For handshakers, all members are input/output parameters; for /// example, a handshaker may read from or write to \a endpoint and /// then later replace it with a wrapped endpoint. Similarly, a /// handshaker may modify \a args. /// /// A handshaker takes ownership of the members while a handshake is in /// progress. Upon failure or shutdown of an in-progress handshaker, /// the handshaker is responsible for destroying the members and setting /// them to NULL before invoking the on_handshake_done callback. /// /// For the on_handshake_done callback, all members are input arguments, /// which the callback takes ownership of. typedef struct { grpc_endpoint* endpoint; grpc_channel_args* args; grpc_slice_buffer* read_buffer; // A handshaker may set this to true before invoking on_handshake_done // to indicate that subsequent handshakers should be skipped. bool exit_early; // User data passed through the handshake manager. Not used by // individual handshakers. void* user_data; } grpc_handshaker_args; typedef struct { /// Destroys the handshaker. void (*destroy)(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker); /// Shuts down the handshaker (e.g., to clean up when the operation is /// aborted in the middle). void (*shutdown)(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker, grpc_error* why); /// Performs handshaking, modifying \a args as needed (e.g., to /// replace \a endpoint with a wrapped endpoint). /// When finished, invokes \a on_handshake_done. /// \a acceptor will be NULL for client-side handshakers. void (*do_handshake)(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker, grpc_tcp_server_acceptor* acceptor, grpc_closure* on_handshake_done, grpc_handshaker_args* args); } grpc_handshaker_vtable; /// Base struct. To subclass, make this the first member of the /// implementation struct. struct grpc_handshaker { const grpc_handshaker_vtable* vtable; }; /// Called by concrete implementations to initialize the base struct. void grpc_handshaker_init(const grpc_handshaker_vtable* vtable, grpc_handshaker* handshaker); void grpc_handshaker_destroy(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker); void grpc_handshaker_shutdown(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker, grpc_error* why); void grpc_handshaker_do_handshake(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker, grpc_tcp_server_acceptor* acceptor, grpc_closure* on_handshake_done, grpc_handshaker_args* args); /// /// grpc_handshake_manager /// typedef struct grpc_handshake_manager grpc_handshake_manager; /// Creates a new handshake manager. Caller takes ownership. grpc_handshake_manager* grpc_handshake_manager_create(); /// Adds a handshaker to the handshake manager. /// Takes ownership of \a handshaker. void grpc_handshake_manager_add(grpc_handshake_manager* mgr, grpc_handshaker* handshaker); /// Destroys the handshake manager. void grpc_handshake_manager_destroy(grpc_exec_ctx* exec_ctx, grpc_handshake_manager* mgr); /// Shuts down the handshake manager (e.g., to clean up when the operation is /// aborted in the middle). /// The caller must still call grpc_handshake_manager_destroy() after /// calling this function. void grpc_handshake_manager_shutdown(grpc_exec_ctx* exec_ctx, grpc_handshake_manager* mgr, grpc_error* why); /// Invokes handshakers in the order they were added. /// Takes ownership of \a endpoint, and then passes that ownership to /// the \a on_handshake_done callback. /// Does NOT take ownership of \a channel_args. Instead, makes a copy before /// invoking the first handshaker. /// \a acceptor will be NULL for client-side handshakers. /// /// When done, invokes \a on_handshake_done with a grpc_handshaker_args /// object as its argument. If the callback is invoked with error != /// GRPC_ERROR_NONE, then handshaking failed and the handshaker has done /// the necessary clean-up. Otherwise, the callback takes ownership of /// the arguments. void grpc_handshake_manager_do_handshake( grpc_exec_ctx* exec_ctx, grpc_handshake_manager* mgr, grpc_endpoint* endpoint, const grpc_channel_args* channel_args, gpr_timespec deadline, grpc_tcp_server_acceptor* acceptor, grpc_iomgr_cb_func on_handshake_done, void* user_data); /// Add \a mgr to the server side list of all pending handshake managers, the /// list starts with \a *head. // Not thread-safe. Caller needs to synchronize. void grpc_handshake_manager_pending_list_add(grpc_handshake_manager** head, grpc_handshake_manager* mgr); /// Remove \a mgr from the server side list of all pending handshake managers. // Not thread-safe. Caller needs to synchronize. void grpc_handshake_manager_pending_list_remove(grpc_handshake_manager** head, grpc_handshake_manager* mgr); /// Shutdown all pending handshake managers on the server side. // Not thread-safe. Caller needs to synchronize. void grpc_handshake_manager_pending_list_shutdown_all( grpc_exec_ctx* exec_ctx, grpc_handshake_manager* head, grpc_error* why); #endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_H */ grpc-1.3.2/src/core/lib/channel/handshaker_factory.c000066400000000000000000000045051310511640000223430ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/channel/handshaker_factory.h" #include void grpc_handshaker_factory_add_handshakers( grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory, const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr) { if (handshaker_factory != NULL) { GPR_ASSERT(handshaker_factory->vtable != NULL); handshaker_factory->vtable->add_handshakers(exec_ctx, handshaker_factory, args, handshake_mgr); } } void grpc_handshaker_factory_destroy( grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory) { if (handshaker_factory != NULL) { GPR_ASSERT(handshaker_factory->vtable != NULL); handshaker_factory->vtable->destroy(exec_ctx, handshaker_factory); } } grpc-1.3.2/src/core/lib/channel/handshaker_factory.h000066400000000000000000000053331310511640000223500ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_CHANNEL_HANDSHAKER_FACTORY_H #define GRPC_CORE_LIB_CHANNEL_HANDSHAKER_FACTORY_H #include #include "src/core/lib/channel/handshaker.h" #include "src/core/lib/iomgr/exec_ctx.h" // A handshaker factory is used to create handshakers. typedef struct grpc_handshaker_factory grpc_handshaker_factory; typedef struct { void (*add_handshakers)(grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory, const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr); void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory); } grpc_handshaker_factory_vtable; struct grpc_handshaker_factory { const grpc_handshaker_factory_vtable *vtable; }; void grpc_handshaker_factory_add_handshakers( grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory, const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr); void grpc_handshaker_factory_destroy( grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory); #endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_FACTORY_H */ grpc-1.3.2/src/core/lib/channel/handshaker_registry.c000066400000000000000000000101211310511640000225330ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/channel/handshaker_registry.h" #include #include // // grpc_handshaker_factory_list // typedef struct { grpc_handshaker_factory** list; size_t num_factories; } grpc_handshaker_factory_list; static void grpc_handshaker_factory_list_register( grpc_handshaker_factory_list* list, bool at_start, grpc_handshaker_factory* factory) { list->list = gpr_realloc( list->list, (list->num_factories + 1) * sizeof(grpc_handshaker_factory*)); if (at_start) { memmove(list->list + 1, list->list, sizeof(grpc_handshaker_factory*) * list->num_factories); list->list[0] = factory; } else { list->list[list->num_factories] = factory; } ++list->num_factories; } static void grpc_handshaker_factory_list_add_handshakers( grpc_exec_ctx* exec_ctx, grpc_handshaker_factory_list* list, const grpc_channel_args* args, grpc_handshake_manager* handshake_mgr) { for (size_t i = 0; i < list->num_factories; ++i) { grpc_handshaker_factory_add_handshakers(exec_ctx, list->list[i], args, handshake_mgr); } } static void grpc_handshaker_factory_list_destroy( grpc_exec_ctx* exec_ctx, grpc_handshaker_factory_list* list) { for (size_t i = 0; i < list->num_factories; ++i) { grpc_handshaker_factory_destroy(exec_ctx, list->list[i]); } gpr_free(list->list); } // // plugin // static grpc_handshaker_factory_list g_handshaker_factory_lists[NUM_HANDSHAKER_TYPES]; void grpc_handshaker_factory_registry_init() { memset(g_handshaker_factory_lists, 0, sizeof(g_handshaker_factory_lists)); } void grpc_handshaker_factory_registry_shutdown(grpc_exec_ctx* exec_ctx) { for (size_t i = 0; i < NUM_HANDSHAKER_TYPES; ++i) { grpc_handshaker_factory_list_destroy(exec_ctx, &g_handshaker_factory_lists[i]); } } void grpc_handshaker_factory_register(bool at_start, grpc_handshaker_type handshaker_type, grpc_handshaker_factory* factory) { grpc_handshaker_factory_list_register( &g_handshaker_factory_lists[handshaker_type], at_start, factory); } void grpc_handshakers_add(grpc_exec_ctx* exec_ctx, grpc_handshaker_type handshaker_type, const grpc_channel_args* args, grpc_handshake_manager* handshake_mgr) { grpc_handshaker_factory_list_add_handshakers( exec_ctx, &g_handshaker_factory_lists[handshaker_type], args, handshake_mgr); } grpc-1.3.2/src/core/lib/channel/handshaker_registry.h000066400000000000000000000052741310511640000225550ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_CHANNEL_HANDSHAKER_REGISTRY_H #define GRPC_CORE_LIB_CHANNEL_HANDSHAKER_REGISTRY_H #include #include "src/core/lib/channel/handshaker_factory.h" #include "src/core/lib/iomgr/exec_ctx.h" typedef enum { HANDSHAKER_CLIENT = 0, HANDSHAKER_SERVER, NUM_HANDSHAKER_TYPES, // Must be last. } grpc_handshaker_type; void grpc_handshaker_factory_registry_init(); void grpc_handshaker_factory_registry_shutdown(grpc_exec_ctx* exec_ctx); /// Registers a new handshaker factory. Takes ownership. /// If \a at_start is true, the new handshaker will be at the beginning of /// the list. Otherwise, it will be added to the end. void grpc_handshaker_factory_register(bool at_start, grpc_handshaker_type handshaker_type, grpc_handshaker_factory* factory); void grpc_handshakers_add(grpc_exec_ctx* exec_ctx, grpc_handshaker_type handshaker_type, const grpc_channel_args* args, grpc_handshake_manager* handshake_mgr); #endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_REGISTRY_H */ grpc-1.3.2/src/core/lib/channel/http_client_filter.c000066400000000000000000000606141310511640000223710ustar00rootroot00000000000000/* * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/channel/http_client_filter.h" #include #include #include #include #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/b64.h" #include "src/core/lib/slice/percent_encoding.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/string.h" #include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/transport_impl.h" #define EXPECTED_CONTENT_TYPE "application/grpc" #define EXPECTED_CONTENT_TYPE_LENGTH sizeof(EXPECTED_CONTENT_TYPE) - 1 /* default maximum size of payload eligable for GET request */ static const size_t kMaxPayloadSizeForGet = 2048; typedef struct call_data { grpc_linked_mdelem method; grpc_linked_mdelem scheme; grpc_linked_mdelem authority; grpc_linked_mdelem te_trailers; grpc_linked_mdelem content_type; grpc_linked_mdelem user_agent; grpc_metadata_batch *recv_initial_metadata; grpc_metadata_batch *recv_trailing_metadata; uint8_t *payload_bytes; /* Vars to read data off of send_message */ grpc_transport_stream_op_batch *send_op; uint32_t send_length; uint32_t send_flags; grpc_slice incoming_slice; grpc_slice_buffer_stream replacement_stream; grpc_slice_buffer slices; /* flag that indicates that all slices of send_messages aren't availble */ bool send_message_blocked; /** Closure to call when finished with the hc_on_recv hook */ grpc_closure *on_done_recv_initial_metadata; grpc_closure *on_done_recv_trailing_metadata; grpc_closure *on_complete; grpc_closure *post_send; /** Receive closures are chained: we inject this closure as the on_done_recv up-call on transport_op, and remember to call our on_done_recv member after handling it. */ grpc_closure hc_on_recv_initial_metadata; grpc_closure hc_on_recv_trailing_metadata; grpc_closure hc_on_complete; grpc_closure got_slice; grpc_closure send_done; } call_data; typedef struct channel_data { grpc_mdelem static_scheme; grpc_mdelem user_agent; size_t max_payload_size_for_get; } channel_data; static grpc_error *client_filter_incoming_metadata(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_metadata_batch *b) { if (b->idx.named.status != NULL) { if (grpc_mdelem_eq(b->idx.named.status->md, GRPC_MDELEM_STATUS_200)) { grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.status); } else { char *val = grpc_dump_slice(GRPC_MDVALUE(b->idx.named.status->md), GPR_DUMP_ASCII); char *msg; gpr_asprintf(&msg, "Received http2 header with status: %s", val); grpc_error *e = grpc_error_set_str( grpc_error_set_int( grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Received http2 :status header with non-200 OK status"), GRPC_ERROR_STR_VALUE, grpc_slice_from_copied_string(val)), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_CANCELLED), GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_copied_string(msg)); gpr_free(val); gpr_free(msg); return e; } } if (b->idx.named.grpc_message != NULL) { grpc_slice pct_decoded_msg = grpc_permissive_percent_decode_slice( GRPC_MDVALUE(b->idx.named.grpc_message->md)); if (grpc_slice_is_equivalent(pct_decoded_msg, GRPC_MDVALUE(b->idx.named.grpc_message->md))) { grpc_slice_unref_internal(exec_ctx, pct_decoded_msg); } else { grpc_metadata_batch_set_value(exec_ctx, b->idx.named.grpc_message, pct_decoded_msg); } } if (b->idx.named.content_type != NULL) { if (!grpc_mdelem_eq(b->idx.named.content_type->md, GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)) { if (grpc_slice_buf_start_eq(GRPC_MDVALUE(b->idx.named.content_type->md), EXPECTED_CONTENT_TYPE, EXPECTED_CONTENT_TYPE_LENGTH) && (GRPC_SLICE_START_PTR(GRPC_MDVALUE( b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] == '+' || GRPC_SLICE_START_PTR(GRPC_MDVALUE( b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] == ';')) { /* Although the C implementation doesn't (currently) generate them, any custom +-suffix is explicitly valid. */ /* TODO(klempner): We should consider preallocating common values such as +proto or +json, or at least stashing them if we see them. */ /* TODO(klempner): Should we be surfacing this to application code? */ } else { /* TODO(klempner): We're currently allowing this, but we shouldn't see it without a proxy so log for now. */ char *val = grpc_dump_slice(GRPC_MDVALUE(b->idx.named.content_type->md), GPR_DUMP_ASCII); gpr_log(GPR_INFO, "Unexpected content-type '%s'", val); gpr_free(val); } } grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.content_type); } return GRPC_ERROR_NONE; } static void hc_on_recv_initial_metadata(grpc_exec_ctx *exec_ctx, void *user_data, grpc_error *error) { grpc_call_element *elem = user_data; call_data *calld = elem->call_data; if (error == GRPC_ERROR_NONE) { error = client_filter_incoming_metadata(exec_ctx, elem, calld->recv_initial_metadata); } else { GRPC_ERROR_REF(error); } grpc_closure_run(exec_ctx, calld->on_done_recv_initial_metadata, error); } static void hc_on_recv_trailing_metadata(grpc_exec_ctx *exec_ctx, void *user_data, grpc_error *error) { grpc_call_element *elem = user_data; call_data *calld = elem->call_data; if (error == GRPC_ERROR_NONE) { error = client_filter_incoming_metadata(exec_ctx, elem, calld->recv_trailing_metadata); } else { GRPC_ERROR_REF(error); } grpc_closure_run(exec_ctx, calld->on_done_recv_trailing_metadata, error); } static void hc_on_complete(grpc_exec_ctx *exec_ctx, void *user_data, grpc_error *error) { grpc_call_element *elem = user_data; call_data *calld = elem->call_data; if (calld->payload_bytes) { gpr_free(calld->payload_bytes); calld->payload_bytes = NULL; } calld->on_complete->cb(exec_ctx, calld->on_complete->cb_arg, error); } static void send_done(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) { grpc_call_element *elem = elemp; call_data *calld = elem->call_data; grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &calld->slices); calld->post_send->cb(exec_ctx, calld->post_send->cb_arg, error); } static void remove_if_present(grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, grpc_metadata_batch_callouts_index idx) { if (batch->idx.array[idx] != NULL) { grpc_metadata_batch_remove(exec_ctx, batch, batch->idx.array[idx]); } } static void continue_send_message(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { call_data *calld = elem->call_data; uint8_t *wrptr = calld->payload_bytes; while (grpc_byte_stream_next( exec_ctx, calld->send_op->payload->send_message.send_message, &calld->incoming_slice, ~(size_t)0, &calld->got_slice)) { memcpy(wrptr, GRPC_SLICE_START_PTR(calld->incoming_slice), GRPC_SLICE_LENGTH(calld->incoming_slice)); wrptr += GRPC_SLICE_LENGTH(calld->incoming_slice); grpc_slice_buffer_add(&calld->slices, calld->incoming_slice); if (calld->send_length == calld->slices.length) { calld->send_message_blocked = false; break; } } } static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) { grpc_call_element *elem = elemp; call_data *calld = elem->call_data; calld->send_message_blocked = false; grpc_slice_buffer_add(&calld->slices, calld->incoming_slice); if (calld->send_length == calld->slices.length) { /* Pass down the original send_message op that was blocked.*/ grpc_slice_buffer_stream_init(&calld->replacement_stream, &calld->slices, calld->send_flags); calld->send_op->payload->send_message.send_message = &calld->replacement_stream.base; calld->post_send = calld->send_op->on_complete; calld->send_op->on_complete = &calld->send_done; grpc_call_next_op(exec_ctx, elem, calld->send_op); } else { continue_send_message(exec_ctx, elem); } } static grpc_error *hc_mutate_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op_batch *op) { /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; channel_data *channeld = elem->channel_data; grpc_error *error; if (op->send_initial_metadata) { /* Decide which HTTP VERB to use. We use GET if the request is marked cacheable, and the operation contains both initial metadata and send message, and the payload is below the size threshold, and all the data for this request is immediately available. */ grpc_mdelem method = GRPC_MDELEM_METHOD_POST; if (op->send_message && (op->payload->send_initial_metadata.send_initial_metadata_flags & GRPC_INITIAL_METADATA_CACHEABLE_REQUEST) && op->payload->send_message.send_message->length < channeld->max_payload_size_for_get) { method = GRPC_MDELEM_METHOD_GET; /* The following write to calld->send_message_blocked isn't racy with reads in hc_start_transport_op (which deals with SEND_MESSAGE ops) because being here means ops->send_message is not NULL, which is primarily guarding the read there. */ calld->send_message_blocked = true; } else if (op->payload->send_initial_metadata.send_initial_metadata_flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) { method = GRPC_MDELEM_METHOD_PUT; } /* Attempt to read the data from send_message and create a header field. */ if (grpc_mdelem_eq(method, GRPC_MDELEM_METHOD_GET)) { /* allocate memory to hold the entire payload */ calld->payload_bytes = gpr_malloc(op->payload->send_message.send_message->length); /* read slices of send_message and copy into payload_bytes */ calld->send_op = op; calld->send_length = op->payload->send_message.send_message->length; calld->send_flags = op->payload->send_message.send_message->flags; continue_send_message(exec_ctx, elem); if (calld->send_message_blocked == false) { /* when all the send_message data is available, then modify the path * MDELEM by appending base64 encoded query to the path */ const int k_url_safe = 1; const int k_multi_line = 0; const unsigned char k_query_separator = '?'; grpc_slice path_slice = GRPC_MDVALUE(op->payload->send_initial_metadata .send_initial_metadata->idx.named.path->md); /* sum up individual component's lengths and allocate enough memory to * hold combined path+query */ size_t estimated_len = GRPC_SLICE_LENGTH(path_slice); estimated_len++; /* for the '?' */ estimated_len += grpc_base64_estimate_encoded_size( op->payload->send_message.send_message->length, k_url_safe, k_multi_line); estimated_len += 1; /* for the trailing 0 */ grpc_slice path_with_query_slice = grpc_slice_malloc(estimated_len); /* memcopy individual pieces into this slice */ uint8_t *write_ptr = (uint8_t *)GRPC_SLICE_START_PTR(path_with_query_slice); uint8_t *original_path = (uint8_t *)GRPC_SLICE_START_PTR(path_slice); memcpy(write_ptr, original_path, GRPC_SLICE_LENGTH(path_slice)); write_ptr += GRPC_SLICE_LENGTH(path_slice); *write_ptr = k_query_separator; write_ptr++; /* for the '?' */ grpc_base64_encode_core((char *)write_ptr, calld->payload_bytes, op->payload->send_message.send_message->length, k_url_safe, k_multi_line); /* remove trailing unused memory and add trailing 0 to terminate string */ char *t = (char *)GRPC_SLICE_START_PTR(path_with_query_slice); /* safe to use strlen since base64_encode will always add '\0' */ size_t path_length = strlen(t) + 1; *(t + path_length) = '\0'; path_with_query_slice = grpc_slice_sub(path_with_query_slice, 0, path_length); /* substitute previous path with the new path+query */ grpc_mdelem mdelem_path_and_query = grpc_mdelem_from_slices( exec_ctx, GRPC_MDSTR_PATH, path_with_query_slice); grpc_metadata_batch *b = op->payload->send_initial_metadata.send_initial_metadata; error = grpc_metadata_batch_substitute(exec_ctx, b, b->idx.named.path, mdelem_path_and_query); if (error != GRPC_ERROR_NONE) return error; calld->on_complete = op->on_complete; op->on_complete = &calld->hc_on_complete; op->send_message = false; grpc_slice_unref_internal(exec_ctx, path_with_query_slice); } else { /* Not all data is available. Fall back to POST. */ gpr_log(GPR_DEBUG, "Request is marked Cacheable but not all data is available.\ Falling back to POST"); method = GRPC_MDELEM_METHOD_POST; } } remove_if_present(exec_ctx, op->payload->send_initial_metadata.send_initial_metadata, GRPC_BATCH_METHOD); remove_if_present(exec_ctx, op->payload->send_initial_metadata.send_initial_metadata, GRPC_BATCH_SCHEME); remove_if_present(exec_ctx, op->payload->send_initial_metadata.send_initial_metadata, GRPC_BATCH_TE); remove_if_present(exec_ctx, op->payload->send_initial_metadata.send_initial_metadata, GRPC_BATCH_CONTENT_TYPE); remove_if_present(exec_ctx, op->payload->send_initial_metadata.send_initial_metadata, GRPC_BATCH_USER_AGENT); /* Send : prefixed headers, which have to be before any application layer headers. */ error = grpc_metadata_batch_add_head( exec_ctx, op->payload->send_initial_metadata.send_initial_metadata, &calld->method, method); if (error != GRPC_ERROR_NONE) return error; error = grpc_metadata_batch_add_head( exec_ctx, op->payload->send_initial_metadata.send_initial_metadata, &calld->scheme, channeld->static_scheme); if (error != GRPC_ERROR_NONE) return error; error = grpc_metadata_batch_add_tail( exec_ctx, op->payload->send_initial_metadata.send_initial_metadata, &calld->te_trailers, GRPC_MDELEM_TE_TRAILERS); if (error != GRPC_ERROR_NONE) return error; error = grpc_metadata_batch_add_tail( exec_ctx, op->payload->send_initial_metadata.send_initial_metadata, &calld->content_type, GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC); if (error != GRPC_ERROR_NONE) return error; error = grpc_metadata_batch_add_tail( exec_ctx, op->payload->send_initial_metadata.send_initial_metadata, &calld->user_agent, GRPC_MDELEM_REF(channeld->user_agent)); if (error != GRPC_ERROR_NONE) return error; } if (op->recv_initial_metadata) { /* substitute our callback for the higher callback */ calld->recv_initial_metadata = op->payload->recv_initial_metadata.recv_initial_metadata; calld->on_done_recv_initial_metadata = op->payload->recv_initial_metadata.recv_initial_metadata_ready; op->payload->recv_initial_metadata.recv_initial_metadata_ready = &calld->hc_on_recv_initial_metadata; } if (op->recv_trailing_metadata) { /* substitute our callback for the higher callback */ calld->recv_trailing_metadata = op->payload->recv_trailing_metadata.recv_trailing_metadata; calld->on_done_recv_trailing_metadata = op->on_complete; op->on_complete = &calld->hc_on_recv_trailing_metadata; } return GRPC_ERROR_NONE; } static void hc_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op_batch *op) { GPR_TIMER_BEGIN("hc_start_transport_op", 0); GRPC_CALL_LOG_OP(GPR_INFO, elem, op); grpc_error *error = hc_mutate_op(exec_ctx, elem, op); if (error != GRPC_ERROR_NONE) { grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, op, error); } else { call_data *calld = elem->call_data; if (op->send_message && calld->send_message_blocked) { /* Don't forward the op. send_message contains slices that aren't ready yet. The call will be forwarded by the op_complete of slice read call. */ } else { grpc_call_next_op(exec_ctx, elem, op); } } GPR_TIMER_END("hc_start_transport_op", 0); } /* Constructor for call_data */ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_element_args *args) { call_data *calld = elem->call_data; calld->on_done_recv_initial_metadata = NULL; calld->on_done_recv_trailing_metadata = NULL; calld->on_complete = NULL; calld->payload_bytes = NULL; calld->send_message_blocked = false; grpc_slice_buffer_init(&calld->slices); grpc_closure_init(&calld->hc_on_recv_initial_metadata, hc_on_recv_initial_metadata, elem, grpc_schedule_on_exec_ctx); grpc_closure_init(&calld->hc_on_recv_trailing_metadata, hc_on_recv_trailing_metadata, elem, grpc_schedule_on_exec_ctx); grpc_closure_init(&calld->hc_on_complete, hc_on_complete, elem, grpc_schedule_on_exec_ctx); grpc_closure_init(&calld->got_slice, got_slice, elem, grpc_schedule_on_exec_ctx); grpc_closure_init(&calld->send_done, send_done, elem, grpc_schedule_on_exec_ctx); return GRPC_ERROR_NONE; } /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, grpc_closure *ignored) { call_data *calld = elem->call_data; grpc_slice_buffer_destroy_internal(exec_ctx, &calld->slices); } static grpc_mdelem scheme_from_args(const grpc_channel_args *args) { unsigned i; size_t j; grpc_mdelem valid_schemes[] = {GRPC_MDELEM_SCHEME_HTTP, GRPC_MDELEM_SCHEME_HTTPS}; if (args != NULL) { for (i = 0; i < args->num_args; ++i) { if (args->args[i].type == GRPC_ARG_STRING && strcmp(args->args[i].key, GRPC_ARG_HTTP2_SCHEME) == 0) { for (j = 0; j < GPR_ARRAY_SIZE(valid_schemes); j++) { if (0 == grpc_slice_str_cmp(GRPC_MDVALUE(valid_schemes[j]), args->args[i].value.string)) { return valid_schemes[j]; } } } } } return GRPC_MDELEM_SCHEME_HTTP; } static size_t max_payload_size_from_args(const grpc_channel_args *args) { if (args != NULL) { for (size_t i = 0; i < args->num_args; ++i) { if (0 == strcmp(args->args[i].key, GRPC_ARG_MAX_PAYLOAD_SIZE_FOR_GET)) { if (args->args[i].type != GRPC_ARG_INTEGER) { gpr_log(GPR_ERROR, "%s: must be an integer", GRPC_ARG_MAX_PAYLOAD_SIZE_FOR_GET); } else { return (size_t)args->args[i].value.integer; } } } } return kMaxPayloadSizeForGet; } static grpc_slice user_agent_from_args(const grpc_channel_args *args, const char *transport_name) { gpr_strvec v; size_t i; int is_first = 1; char *tmp; grpc_slice result; gpr_strvec_init(&v); for (i = 0; args && i < args->num_args; i++) { if (0 == strcmp(args->args[i].key, GRPC_ARG_PRIMARY_USER_AGENT_STRING)) { if (args->args[i].type != GRPC_ARG_STRING) { gpr_log(GPR_ERROR, "Channel argument '%s' should be a string", GRPC_ARG_PRIMARY_USER_AGENT_STRING); } else { if (!is_first) gpr_strvec_add(&v, gpr_strdup(" ")); is_first = 0; gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string)); } } } gpr_asprintf(&tmp, "%sgrpc-c/%s (%s; %s; %s)", is_first ? "" : " ", grpc_version_string(), GPR_PLATFORM_STRING, transport_name, grpc_g_stands_for()); is_first = 0; gpr_strvec_add(&v, tmp); for (i = 0; args && i < args->num_args; i++) { if (0 == strcmp(args->args[i].key, GRPC_ARG_SECONDARY_USER_AGENT_STRING)) { if (args->args[i].type != GRPC_ARG_STRING) { gpr_log(GPR_ERROR, "Channel argument '%s' should be a string", GRPC_ARG_SECONDARY_USER_AGENT_STRING); } else { if (!is_first) gpr_strvec_add(&v, gpr_strdup(" ")); is_first = 0; gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string)); } } } tmp = gpr_strvec_flatten(&v, NULL); gpr_strvec_destroy(&v); result = grpc_slice_intern(grpc_slice_from_static_string(tmp)); gpr_free(tmp); return result; } /* Constructor for channel_data */ static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_channel_element_args *args) { channel_data *chand = elem->channel_data; GPR_ASSERT(!args->is_last); GPR_ASSERT(args->optional_transport != NULL); chand->static_scheme = scheme_from_args(args->channel_args); chand->max_payload_size_for_get = max_payload_size_from_args(args->channel_args); chand->user_agent = grpc_mdelem_from_slices( exec_ctx, GRPC_MDSTR_USER_AGENT, user_agent_from_args(args->channel_args, args->optional_transport->vtable->name)); return GRPC_ERROR_NONE; } /* Destructor for channel data */ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) { channel_data *chand = elem->channel_data; GRPC_MDELEM_UNREF(exec_ctx, chand->user_agent); } const grpc_channel_filter grpc_http_client_filter = { hc_start_transport_op, grpc_channel_next_op, sizeof(call_data), init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, destroy_call_elem, sizeof(channel_data), init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer, grpc_channel_next_get_info, "http-client"}; grpc-1.3.2/src/core/lib/channel/http_client_filter.h000066400000000000000000000041601310511640000223700ustar00rootroot00000000000000/* * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_CHANNEL_HTTP_CLIENT_FILTER_H #define GRPC_CORE_LIB_CHANNEL_HTTP_CLIENT_FILTER_H #include "src/core/lib/channel/channel_stack.h" /* Processes metadata on the client side for HTTP2 transports */ extern const grpc_channel_filter grpc_http_client_filter; /* Channel arg to override the http2 :scheme header */ #define GRPC_ARG_HTTP2_SCHEME "grpc.http2_scheme" /* Channel arg to determine maximum size of payload eligable for GET request */ #define GRPC_ARG_MAX_PAYLOAD_SIZE_FOR_GET "grpc.max_payload_size_for_get" #endif /* GRPC_CORE_LIB_CHANNEL_HTTP_CLIENT_FILTER_H */ grpc-1.3.2/src/core/lib/channel/http_server_filter.c000066400000000000000000000437201310511640000224200ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/channel/http_server_filter.h" #include #include #include #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/b64.h" #include "src/core/lib/slice/percent_encoding.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/transport/static_metadata.h" #define EXPECTED_CONTENT_TYPE "application/grpc" #define EXPECTED_CONTENT_TYPE_LENGTH sizeof(EXPECTED_CONTENT_TYPE) - 1 extern int grpc_http_trace; typedef struct call_data { grpc_linked_mdelem status; grpc_linked_mdelem content_type; /* did this request come with path query containing request payload */ bool seen_path_with_query; /* flag to ensure payload_bin is delivered only once */ bool payload_bin_delivered; grpc_metadata_batch *recv_initial_metadata; uint32_t *recv_initial_metadata_flags; /** Closure to call when finished with the hs_on_recv hook */ grpc_closure *on_done_recv; /** Closure to call when we retrieve read message from the path URI */ grpc_closure *recv_message_ready; grpc_closure *on_complete; grpc_byte_stream **pp_recv_message; grpc_slice_buffer read_slice_buffer; grpc_slice_buffer_stream read_stream; /** Receive closures are chained: we inject this closure as the on_done_recv up-call on transport_op, and remember to call our on_done_recv member after handling it. */ grpc_closure hs_on_recv; grpc_closure hs_on_complete; grpc_closure hs_recv_message_ready; } call_data; typedef struct channel_data { uint8_t unused; } channel_data; static grpc_error *server_filter_outgoing_metadata(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_metadata_batch *b) { if (b->idx.named.grpc_message != NULL) { grpc_slice pct_encoded_msg = grpc_percent_encode_slice( GRPC_MDVALUE(b->idx.named.grpc_message->md), grpc_compatible_percent_encoding_unreserved_bytes); if (grpc_slice_is_equivalent(pct_encoded_msg, GRPC_MDVALUE(b->idx.named.grpc_message->md))) { grpc_slice_unref_internal(exec_ctx, pct_encoded_msg); } else { grpc_metadata_batch_set_value(exec_ctx, b->idx.named.grpc_message, pct_encoded_msg); } } return GRPC_ERROR_NONE; } static void add_error(const char *error_name, grpc_error **cumulative, grpc_error *new) { if (new == GRPC_ERROR_NONE) return; if (*cumulative == GRPC_ERROR_NONE) { *cumulative = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_name); } *cumulative = grpc_error_add_child(*cumulative, new); } static grpc_error *server_filter_incoming_metadata(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_metadata_batch *b) { call_data *calld = elem->call_data; grpc_error *error = GRPC_ERROR_NONE; static const char *error_name = "Failed processing incoming headers"; if (b->idx.named.method != NULL) { if (grpc_mdelem_eq(b->idx.named.method->md, GRPC_MDELEM_METHOD_POST)) { *calld->recv_initial_metadata_flags &= ~(GRPC_INITIAL_METADATA_CACHEABLE_REQUEST | GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST); } else if (grpc_mdelem_eq(b->idx.named.method->md, GRPC_MDELEM_METHOD_PUT)) { *calld->recv_initial_metadata_flags &= ~GRPC_INITIAL_METADATA_CACHEABLE_REQUEST; *calld->recv_initial_metadata_flags |= GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; } else if (grpc_mdelem_eq(b->idx.named.method->md, GRPC_MDELEM_METHOD_GET)) { *calld->recv_initial_metadata_flags |= GRPC_INITIAL_METADATA_CACHEABLE_REQUEST; *calld->recv_initial_metadata_flags &= ~GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; } else { add_error(error_name, &error, grpc_attach_md_to_error( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"), b->idx.named.method->md)); } grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.method); } else { add_error( error_name, &error, grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"), GRPC_ERROR_STR_KEY, grpc_slice_from_static_string(":method"))); } if (b->idx.named.te != NULL) { if (!grpc_mdelem_eq(b->idx.named.te->md, GRPC_MDELEM_TE_TRAILERS)) { add_error(error_name, &error, grpc_attach_md_to_error( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"), b->idx.named.te->md)); } grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.te); } else { add_error(error_name, &error, grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"), GRPC_ERROR_STR_KEY, grpc_slice_from_static_string("te"))); } if (b->idx.named.scheme != NULL) { if (!grpc_mdelem_eq(b->idx.named.scheme->md, GRPC_MDELEM_SCHEME_HTTP) && !grpc_mdelem_eq(b->idx.named.scheme->md, GRPC_MDELEM_SCHEME_HTTPS) && !grpc_mdelem_eq(b->idx.named.scheme->md, GRPC_MDELEM_SCHEME_GRPC)) { add_error(error_name, &error, grpc_attach_md_to_error( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"), b->idx.named.scheme->md)); } grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.scheme); } else { add_error( error_name, &error, grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"), GRPC_ERROR_STR_KEY, grpc_slice_from_static_string(":scheme"))); } if (b->idx.named.content_type != NULL) { if (!grpc_mdelem_eq(b->idx.named.content_type->md, GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)) { if (grpc_slice_buf_start_eq(GRPC_MDVALUE(b->idx.named.content_type->md), EXPECTED_CONTENT_TYPE, EXPECTED_CONTENT_TYPE_LENGTH) && (GRPC_SLICE_START_PTR(GRPC_MDVALUE( b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] == '+' || GRPC_SLICE_START_PTR(GRPC_MDVALUE( b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] == ';')) { /* Although the C implementation doesn't (currently) generate them, any custom +-suffix is explicitly valid. */ /* TODO(klempner): We should consider preallocating common values such as +proto or +json, or at least stashing them if we see them. */ /* TODO(klempner): Should we be surfacing this to application code? */ } else { /* TODO(klempner): We're currently allowing this, but we shouldn't see it without a proxy so log for now. */ char *val = grpc_dump_slice(GRPC_MDVALUE(b->idx.named.content_type->md), GPR_DUMP_ASCII); gpr_log(GPR_INFO, "Unexpected content-type '%s'", val); gpr_free(val); } } grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.content_type); } if (b->idx.named.path == NULL) { add_error(error_name, &error, grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"), GRPC_ERROR_STR_KEY, grpc_slice_from_static_string(":path"))); } else if (*calld->recv_initial_metadata_flags & GRPC_INITIAL_METADATA_CACHEABLE_REQUEST) { /* We have a cacheable request made with GET verb. The path contains the * query parameter which is base64 encoded request payload. */ const char k_query_separator = '?'; grpc_slice path_slice = GRPC_MDVALUE(b->idx.named.path->md); uint8_t *path_ptr = (uint8_t *)GRPC_SLICE_START_PTR(path_slice); size_t path_length = GRPC_SLICE_LENGTH(path_slice); /* offset of the character '?' */ size_t offset = 0; for (offset = 0; offset < path_length && *path_ptr != k_query_separator; path_ptr++, offset++) ; if (offset < path_length) { grpc_slice query_slice = grpc_slice_sub(path_slice, offset + 1, path_length); /* substitute path metadata with just the path (not query) */ grpc_mdelem mdelem_path_without_query = grpc_mdelem_from_slices( exec_ctx, GRPC_MDSTR_PATH, grpc_slice_sub(path_slice, 0, offset)); grpc_metadata_batch_substitute(exec_ctx, b, b->idx.named.path, mdelem_path_without_query); /* decode payload from query and add to the slice buffer to be returned */ const int k_url_safe = 1; grpc_slice_buffer_add( &calld->read_slice_buffer, grpc_base64_decode(exec_ctx, (const char *)GRPC_SLICE_START_PTR(query_slice), k_url_safe)); grpc_slice_buffer_stream_init(&calld->read_stream, &calld->read_slice_buffer, 0); calld->seen_path_with_query = true; grpc_slice_unref_internal(exec_ctx, query_slice); } else { gpr_log(GPR_ERROR, "GET request without QUERY"); } } if (b->idx.named.host != NULL && b->idx.named.authority == NULL) { grpc_linked_mdelem *el = b->idx.named.host; grpc_mdelem md = GRPC_MDELEM_REF(el->md); grpc_metadata_batch_remove(exec_ctx, b, el); add_error( error_name, &error, grpc_metadata_batch_add_head( exec_ctx, b, el, grpc_mdelem_from_slices( exec_ctx, GRPC_MDSTR_AUTHORITY, grpc_slice_ref_internal(GRPC_MDVALUE(md))))); GRPC_MDELEM_UNREF(exec_ctx, md); } if (b->idx.named.authority == NULL) { add_error( error_name, &error, grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"), GRPC_ERROR_STR_KEY, grpc_slice_from_static_string(":authority"))); } return error; } static void hs_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, grpc_error *err) { grpc_call_element *elem = user_data; call_data *calld = elem->call_data; if (err == GRPC_ERROR_NONE) { err = server_filter_incoming_metadata(exec_ctx, elem, calld->recv_initial_metadata); } else { GRPC_ERROR_REF(err); } grpc_closure_run(exec_ctx, calld->on_done_recv, err); } static void hs_on_complete(grpc_exec_ctx *exec_ctx, void *user_data, grpc_error *err) { grpc_call_element *elem = user_data; call_data *calld = elem->call_data; /* Call recv_message_ready if we got the payload via the path field */ if (calld->seen_path_with_query && calld->recv_message_ready != NULL) { *calld->pp_recv_message = calld->payload_bin_delivered ? NULL : (grpc_byte_stream *)&calld->read_stream; grpc_closure_run(exec_ctx, calld->recv_message_ready, GRPC_ERROR_REF(err)); calld->recv_message_ready = NULL; calld->payload_bin_delivered = true; } grpc_closure_run(exec_ctx, calld->on_complete, GRPC_ERROR_REF(err)); } static void hs_recv_message_ready(grpc_exec_ctx *exec_ctx, void *user_data, grpc_error *err) { grpc_call_element *elem = user_data; call_data *calld = elem->call_data; if (calld->seen_path_with_query) { /* do nothing. This is probably a GET request, and payload will be returned in hs_on_complete callback. */ } else { grpc_closure_run(exec_ctx, calld->recv_message_ready, GRPC_ERROR_REF(err)); } } static void hs_mutate_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op_batch *op) { /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; if (op->send_initial_metadata) { grpc_error *error = GRPC_ERROR_NONE; static const char *error_name = "Failed sending initial metadata"; add_error( error_name, &error, grpc_metadata_batch_add_head( exec_ctx, op->payload->send_initial_metadata.send_initial_metadata, &calld->status, GRPC_MDELEM_STATUS_200)); add_error( error_name, &error, grpc_metadata_batch_add_tail( exec_ctx, op->payload->send_initial_metadata.send_initial_metadata, &calld->content_type, GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)); add_error(error_name, &error, server_filter_outgoing_metadata( exec_ctx, elem, op->payload->send_initial_metadata.send_initial_metadata)); if (error != GRPC_ERROR_NONE) { grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, op, error); return; } } if (op->recv_initial_metadata) { /* substitute our callback for the higher callback */ GPR_ASSERT(op->payload->recv_initial_metadata.recv_flags != NULL); calld->recv_initial_metadata = op->payload->recv_initial_metadata.recv_initial_metadata; calld->recv_initial_metadata_flags = op->payload->recv_initial_metadata.recv_flags; calld->on_done_recv = op->payload->recv_initial_metadata.recv_initial_metadata_ready; op->payload->recv_initial_metadata.recv_initial_metadata_ready = &calld->hs_on_recv; } if (op->recv_message) { calld->recv_message_ready = op->payload->recv_message.recv_message_ready; calld->pp_recv_message = op->payload->recv_message.recv_message; if (op->payload->recv_message.recv_message_ready) { op->payload->recv_message.recv_message_ready = &calld->hs_recv_message_ready; } if (op->on_complete) { calld->on_complete = op->on_complete; op->on_complete = &calld->hs_on_complete; } } if (op->send_trailing_metadata) { grpc_error *error = server_filter_outgoing_metadata( exec_ctx, elem, op->payload->send_trailing_metadata.send_trailing_metadata); if (error != GRPC_ERROR_NONE) { grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, op, error); return; } } } static void hs_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op_batch *op) { GRPC_CALL_LOG_OP(GPR_INFO, elem, op); GPR_TIMER_BEGIN("hs_start_transport_op", 0); hs_mutate_op(exec_ctx, elem, op); grpc_call_next_op(exec_ctx, elem, op); GPR_TIMER_END("hs_start_transport_op", 0); } /* Constructor for call_data */ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_element_args *args) { /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; /* initialize members */ grpc_closure_init(&calld->hs_on_recv, hs_on_recv, elem, grpc_schedule_on_exec_ctx); grpc_closure_init(&calld->hs_on_complete, hs_on_complete, elem, grpc_schedule_on_exec_ctx); grpc_closure_init(&calld->hs_recv_message_ready, hs_recv_message_ready, elem, grpc_schedule_on_exec_ctx); grpc_slice_buffer_init(&calld->read_slice_buffer); return GRPC_ERROR_NONE; } /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, grpc_closure *ignored) { call_data *calld = elem->call_data; grpc_slice_buffer_destroy_internal(exec_ctx, &calld->read_slice_buffer); } /* Constructor for channel_data */ static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_channel_element_args *args) { GPR_ASSERT(!args->is_last); return GRPC_ERROR_NONE; } /* Destructor for channel data */ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) {} const grpc_channel_filter grpc_http_server_filter = { hs_start_transport_op, grpc_channel_next_op, sizeof(call_data), init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, destroy_call_elem, sizeof(channel_data), init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer, grpc_channel_next_get_info, "http-server"}; grpc-1.3.2/src/core/lib/channel/http_server_filter.h000066400000000000000000000035561310511640000224300ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_CHANNEL_HTTP_SERVER_FILTER_H #define GRPC_CORE_LIB_CHANNEL_HTTP_SERVER_FILTER_H #include "src/core/lib/channel/channel_stack.h" /* Processes metadata on the client side for HTTP2 transports */ extern const grpc_channel_filter grpc_http_server_filter; #endif /* GRPC_CORE_LIB_CHANNEL_HTTP_SERVER_FILTER_H */ grpc-1.3.2/src/core/lib/channel/message_size_filter.c000066400000000000000000000253431310511640000225320ustar00rootroot00000000000000// // Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #include "src/core/lib/channel/message_size_filter.h" #include #include #include #include #include #include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/support/string.h" #include "src/core/lib/transport/service_config.h" typedef struct message_size_limits { int max_send_size; int max_recv_size; } message_size_limits; static void* message_size_limits_copy(void* value) { void* new_value = gpr_malloc(sizeof(message_size_limits)); memcpy(new_value, value, sizeof(message_size_limits)); return new_value; } static void message_size_limits_free(grpc_exec_ctx* exec_ctx, void* value) { gpr_free(value); } static const grpc_slice_hash_table_vtable message_size_limits_vtable = { message_size_limits_free, message_size_limits_copy}; static void* message_size_limits_create_from_json(const grpc_json* json) { int max_request_message_bytes = -1; int max_response_message_bytes = -1; for (grpc_json* field = json->child; field != NULL; field = field->next) { if (field->key == NULL) continue; if (strcmp(field->key, "maxRequestMessageBytes") == 0) { if (max_request_message_bytes >= 0) return NULL; // Duplicate. if (field->type != GRPC_JSON_STRING && field->type != GRPC_JSON_NUMBER) { return NULL; } max_request_message_bytes = gpr_parse_nonnegative_int(field->value); if (max_request_message_bytes == -1) return NULL; } else if (strcmp(field->key, "maxResponseMessageBytes") == 0) { if (max_response_message_bytes >= 0) return NULL; // Duplicate. if (field->type != GRPC_JSON_STRING && field->type != GRPC_JSON_NUMBER) { return NULL; } max_response_message_bytes = gpr_parse_nonnegative_int(field->value); if (max_response_message_bytes == -1) return NULL; } } message_size_limits* value = gpr_malloc(sizeof(message_size_limits)); value->max_send_size = max_request_message_bytes; value->max_recv_size = max_response_message_bytes; return value; } typedef struct call_data { int max_send_size; int max_recv_size; // Receive closures are chained: we inject this closure as the // recv_message_ready up-call on transport_stream_op, and remember to // call our next_recv_message_ready member after handling it. grpc_closure recv_message_ready; // Used by recv_message_ready. grpc_byte_stream** recv_message; // Original recv_message_ready callback, invoked after our own. grpc_closure* next_recv_message_ready; } call_data; typedef struct channel_data { int max_send_size; int max_recv_size; // Maps path names to message_size_limits structs. grpc_slice_hash_table* method_limit_table; } channel_data; // Callback invoked when we receive a message. Here we check the max // receive message size. static void recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data, grpc_error* error) { grpc_call_element* elem = user_data; call_data* calld = elem->call_data; if (*calld->recv_message != NULL && calld->max_recv_size >= 0 && (*calld->recv_message)->length > (size_t)calld->max_recv_size) { char* message_string; gpr_asprintf(&message_string, "Received message larger than max (%u vs. %d)", (*calld->recv_message)->length, calld->max_recv_size); grpc_error* new_error = grpc_error_set_int( GRPC_ERROR_CREATE_FROM_COPIED_STRING(message_string), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED); if (error == GRPC_ERROR_NONE) { error = new_error; } else { error = grpc_error_add_child(error, new_error); GRPC_ERROR_UNREF(new_error); } gpr_free(message_string); } // Invoke the next callback. grpc_closure_run(exec_ctx, calld->next_recv_message_ready, error); } // Start transport stream op. static void start_transport_stream_op_batch( grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_transport_stream_op_batch* op) { call_data* calld = elem->call_data; // Check max send message size. if (op->send_message && calld->max_send_size >= 0 && op->payload->send_message.send_message->length > (size_t)calld->max_send_size) { char* message_string; gpr_asprintf(&message_string, "Sent message larger than max (%u vs. %d)", op->payload->send_message.send_message->length, calld->max_send_size); grpc_transport_stream_op_batch_finish_with_failure( exec_ctx, op, grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(message_string), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED)); gpr_free(message_string); return; } // Inject callback for receiving a message. if (op->recv_message) { calld->next_recv_message_ready = op->payload->recv_message.recv_message_ready; calld->recv_message = op->payload->recv_message.recv_message; op->payload->recv_message.recv_message_ready = &calld->recv_message_ready; } // Chain to the next filter. grpc_call_next_op(exec_ctx, elem, op); } // Constructor for call_data. static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, const grpc_call_element_args* args) { channel_data* chand = elem->channel_data; call_data* calld = elem->call_data; calld->next_recv_message_ready = NULL; grpc_closure_init(&calld->recv_message_ready, recv_message_ready, elem, grpc_schedule_on_exec_ctx); // Get max sizes from channel data, then merge in per-method config values. // Note: Per-method config is only available on the client, so we // apply the max request size to the send limit and the max response // size to the receive limit. calld->max_send_size = chand->max_send_size; calld->max_recv_size = chand->max_recv_size; if (chand->method_limit_table != NULL) { message_size_limits* limits = grpc_method_config_table_get( exec_ctx, chand->method_limit_table, args->path); if (limits != NULL) { if (limits->max_send_size >= 0 && (limits->max_send_size < calld->max_send_size || calld->max_send_size < 0)) { calld->max_send_size = limits->max_send_size; } if (limits->max_recv_size >= 0 && (limits->max_recv_size < calld->max_recv_size || calld->max_recv_size < 0)) { calld->max_recv_size = limits->max_recv_size; } } } return GRPC_ERROR_NONE; } // Destructor for call_data. static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, const grpc_call_final_info* final_info, grpc_closure* ignored) {} // Constructor for channel_data. static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx, grpc_channel_element* elem, grpc_channel_element_args* args) { GPR_ASSERT(!args->is_last); channel_data* chand = elem->channel_data; chand->max_send_size = GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH; chand->max_recv_size = GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH; for (size_t i = 0; i < args->channel_args->num_args; ++i) { if (strcmp(args->channel_args->args[i].key, GRPC_ARG_MAX_SEND_MESSAGE_LENGTH) == 0) { const grpc_integer_options options = { GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH, -1, INT_MAX}; chand->max_send_size = grpc_channel_arg_get_integer(&args->channel_args->args[i], options); } if (strcmp(args->channel_args->args[i].key, GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH) == 0) { const grpc_integer_options options = { GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH, -1, INT_MAX}; chand->max_recv_size = grpc_channel_arg_get_integer(&args->channel_args->args[i], options); } } // Get method config table from channel args. const grpc_arg* channel_arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVICE_CONFIG); if (channel_arg != NULL) { GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING); grpc_service_config* service_config = grpc_service_config_create(channel_arg->value.string); if (service_config != NULL) { chand->method_limit_table = grpc_service_config_create_method_config_table( exec_ctx, service_config, message_size_limits_create_from_json, &message_size_limits_vtable); grpc_service_config_destroy(service_config); } } return GRPC_ERROR_NONE; } // Destructor for channel_data. static void destroy_channel_elem(grpc_exec_ctx* exec_ctx, grpc_channel_element* elem) { channel_data* chand = elem->channel_data; grpc_slice_hash_table_unref(exec_ctx, chand->method_limit_table); } const grpc_channel_filter grpc_message_size_filter = { start_transport_stream_op_batch, grpc_channel_next_op, sizeof(call_data), init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, destroy_call_elem, sizeof(channel_data), init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer, grpc_channel_next_get_info, "message_size"}; grpc-1.3.2/src/core/lib/channel/message_size_filter.h000066400000000000000000000034521310511640000225340ustar00rootroot00000000000000// // Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #ifndef GRPC_CORE_LIB_CHANNEL_MESSAGE_SIZE_FILTER_H #define GRPC_CORE_LIB_CHANNEL_MESSAGE_SIZE_FILTER_H #include "src/core/lib/channel/channel_stack.h" extern const grpc_channel_filter grpc_message_size_filter; #endif /* GRPC_CORE_LIB_CHANNEL_MESSAGE_SIZE_FILTER_H */ grpc-1.3.2/src/core/lib/compression/000077500000000000000000000000001310511640000172655ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/compression/algorithm_metadata.h000066400000000000000000000044361310511640000232730ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_COMPRESSION_ALGORITHM_METADATA_H #define GRPC_CORE_LIB_COMPRESSION_ALGORITHM_METADATA_H #include #include "src/core/lib/transport/metadata.h" /** Return compression algorithm based metadata value */ grpc_slice grpc_compression_algorithm_slice( grpc_compression_algorithm algorithm); /** Return compression algorithm based metadata element (grpc-encoding: xxx) */ grpc_mdelem grpc_compression_encoding_mdelem( grpc_compression_algorithm algorithm); /** Find compression algorithm based on passed in mdstr - returns * GRPC_COMPRESS_ALGORITHM_COUNT on failure */ grpc_compression_algorithm grpc_compression_algorithm_from_slice( grpc_slice str); #endif /* GRPC_CORE_LIB_COMPRESSION_ALGORITHM_METADATA_H */ grpc-1.3.2/src/core/lib/compression/compression.c000066400000000000000000000157601310511640000220030ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include "src/core/lib/compression/algorithm_metadata.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/transport/static_metadata.h" int grpc_compression_algorithm_parse(grpc_slice name, grpc_compression_algorithm *algorithm) { /* we use strncmp not only because it's safer (even though in this case it * doesn't matter, given that we are comparing against string literals, but * because this way we needn't have "name" nil-terminated (useful for slice * data, for example) */ if (grpc_slice_eq(name, GRPC_MDSTR_IDENTITY)) { *algorithm = GRPC_COMPRESS_NONE; return 1; } else if (grpc_slice_eq(name, GRPC_MDSTR_GZIP)) { *algorithm = GRPC_COMPRESS_GZIP; return 1; } else if (grpc_slice_eq(name, GRPC_MDSTR_DEFLATE)) { *algorithm = GRPC_COMPRESS_DEFLATE; return 1; } else { return 0; } } int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm, char **name) { GRPC_API_TRACE("grpc_compression_algorithm_parse(algorithm=%d, name=%p)", 2, ((int)algorithm, name)); switch (algorithm) { case GRPC_COMPRESS_NONE: *name = "identity"; return 1; case GRPC_COMPRESS_DEFLATE: *name = "deflate"; return 1; case GRPC_COMPRESS_GZIP: *name = "gzip"; return 1; case GRPC_COMPRESS_ALGORITHMS_COUNT: return 0; } return 0; } grpc_compression_algorithm grpc_compression_algorithm_from_slice( grpc_slice str) { if (grpc_slice_eq(str, GRPC_MDSTR_IDENTITY)) return GRPC_COMPRESS_NONE; if (grpc_slice_eq(str, GRPC_MDSTR_DEFLATE)) return GRPC_COMPRESS_DEFLATE; if (grpc_slice_eq(str, GRPC_MDSTR_GZIP)) return GRPC_COMPRESS_GZIP; return GRPC_COMPRESS_ALGORITHMS_COUNT; } grpc_slice grpc_compression_algorithm_slice( grpc_compression_algorithm algorithm) { switch (algorithm) { case GRPC_COMPRESS_NONE: return GRPC_MDSTR_IDENTITY; case GRPC_COMPRESS_DEFLATE: return GRPC_MDSTR_DEFLATE; case GRPC_COMPRESS_GZIP: return GRPC_MDSTR_GZIP; case GRPC_COMPRESS_ALGORITHMS_COUNT: return grpc_empty_slice(); } return grpc_empty_slice(); } grpc_mdelem grpc_compression_encoding_mdelem( grpc_compression_algorithm algorithm) { switch (algorithm) { case GRPC_COMPRESS_NONE: return GRPC_MDELEM_GRPC_ENCODING_IDENTITY; case GRPC_COMPRESS_DEFLATE: return GRPC_MDELEM_GRPC_ENCODING_DEFLATE; case GRPC_COMPRESS_GZIP: return GRPC_MDELEM_GRPC_ENCODING_GZIP; default: break; } return GRPC_MDNULL; } void grpc_compression_options_init(grpc_compression_options *opts) { memset(opts, 0, sizeof(*opts)); /* all enabled by default */ opts->enabled_algorithms_bitset = (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1; } void grpc_compression_options_enable_algorithm( grpc_compression_options *opts, grpc_compression_algorithm algorithm) { GPR_BITSET(&opts->enabled_algorithms_bitset, algorithm); } void grpc_compression_options_disable_algorithm( grpc_compression_options *opts, grpc_compression_algorithm algorithm) { GPR_BITCLEAR(&opts->enabled_algorithms_bitset, algorithm); } int grpc_compression_options_is_algorithm_enabled( const grpc_compression_options *opts, grpc_compression_algorithm algorithm) { return GPR_BITGET(opts->enabled_algorithms_bitset, algorithm); } /* TODO(dgq): Add the ability to specify parameters to the individual * compression algorithms */ grpc_compression_algorithm grpc_compression_algorithm_for_level( grpc_compression_level level, uint32_t accepted_encodings) { GRPC_API_TRACE("grpc_compression_algorithm_for_level(level=%d)", 1, ((int)level)); if (level > GRPC_COMPRESS_LEVEL_HIGH) { gpr_log(GPR_ERROR, "Unknown compression level %d.", (int)level); abort(); } const size_t num_supported = GPR_BITCOUNT(accepted_encodings) - 1; /* discard NONE */ if (level == GRPC_COMPRESS_LEVEL_NONE || num_supported == 0) { return GRPC_COMPRESS_NONE; } GPR_ASSERT(level > 0); /* Establish a "ranking" or compression algorithms in increasing order of * compression. * This is simplistic and we will probably want to introduce other dimensions * in the future (cpu/memory cost, etc). */ const grpc_compression_algorithm algos_ranking[] = {GRPC_COMPRESS_GZIP, GRPC_COMPRESS_DEFLATE}; /* intersect algos_ranking with the supported ones keeping the ranked order */ grpc_compression_algorithm sorted_supported_algos[GRPC_COMPRESS_ALGORITHMS_COUNT]; size_t algos_supported_idx = 0; for (size_t i = 0; i < GPR_ARRAY_SIZE(algos_ranking); i++) { const grpc_compression_algorithm alg = algos_ranking[i]; for (size_t j = 0; j < num_supported; j++) { if (GPR_BITGET(accepted_encodings, alg) == 1) { /* if \a alg in supported */ sorted_supported_algos[algos_supported_idx++] = alg; break; } } if (algos_supported_idx == num_supported) break; } switch (level) { case GRPC_COMPRESS_LEVEL_NONE: abort(); /* should have been handled already */ case GRPC_COMPRESS_LEVEL_LOW: return sorted_supported_algos[0]; case GRPC_COMPRESS_LEVEL_MED: return sorted_supported_algos[num_supported / 2]; case GRPC_COMPRESS_LEVEL_HIGH: return sorted_supported_algos[num_supported - 1]; default: abort(); }; } grpc-1.3.2/src/core/lib/compression/message_compress.c000066400000000000000000000154441310511640000230000ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/compression/message_compress.h" #include #include #include #include #include "src/core/lib/slice/slice_internal.h" #define OUTPUT_BLOCK_SIZE 1024 static int zlib_body(grpc_exec_ctx* exec_ctx, z_stream* zs, grpc_slice_buffer* input, grpc_slice_buffer* output, int (*flate)(z_stream* zs, int flush)) { int r; int flush; size_t i; grpc_slice outbuf = grpc_slice_malloc(OUTPUT_BLOCK_SIZE); const uInt uint_max = ~(uInt)0; GPR_ASSERT(GRPC_SLICE_LENGTH(outbuf) <= uint_max); zs->avail_out = (uInt)GRPC_SLICE_LENGTH(outbuf); zs->next_out = GRPC_SLICE_START_PTR(outbuf); flush = Z_NO_FLUSH; for (i = 0; i < input->count; i++) { if (i == input->count - 1) flush = Z_FINISH; GPR_ASSERT(GRPC_SLICE_LENGTH(input->slices[i]) <= uint_max); zs->avail_in = (uInt)GRPC_SLICE_LENGTH(input->slices[i]); zs->next_in = GRPC_SLICE_START_PTR(input->slices[i]); do { if (zs->avail_out == 0) { grpc_slice_buffer_add_indexed(output, outbuf); outbuf = grpc_slice_malloc(OUTPUT_BLOCK_SIZE); GPR_ASSERT(GRPC_SLICE_LENGTH(outbuf) <= uint_max); zs->avail_out = (uInt)GRPC_SLICE_LENGTH(outbuf); zs->next_out = GRPC_SLICE_START_PTR(outbuf); } r = flate(zs, flush); if (r < 0 && r != Z_BUF_ERROR /* not fatal */) { gpr_log(GPR_INFO, "zlib error (%d)", r); goto error; } } while (zs->avail_out == 0); if (zs->avail_in) { gpr_log(GPR_INFO, "zlib: not all input consumed"); goto error; } } GPR_ASSERT(outbuf.refcount); outbuf.data.refcounted.length -= zs->avail_out; grpc_slice_buffer_add_indexed(output, outbuf); return 1; error: grpc_slice_unref_internal(exec_ctx, outbuf); return 0; } static void* zalloc_gpr(void* opaque, unsigned int items, unsigned int size) { return gpr_malloc(items * size); } static void zfree_gpr(void* opaque, void* address) { gpr_free(address); } static int zlib_compress(grpc_exec_ctx* exec_ctx, grpc_slice_buffer* input, grpc_slice_buffer* output, int gzip) { z_stream zs; int r; size_t i; size_t count_before = output->count; size_t length_before = output->length; memset(&zs, 0, sizeof(zs)); zs.zalloc = zalloc_gpr; zs.zfree = zfree_gpr; r = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 | (gzip ? 16 : 0), 8, Z_DEFAULT_STRATEGY); GPR_ASSERT(r == Z_OK); r = zlib_body(exec_ctx, &zs, input, output, deflate) && output->length < input->length; if (!r) { for (i = count_before; i < output->count; i++) { grpc_slice_unref_internal(exec_ctx, output->slices[i]); } output->count = count_before; output->length = length_before; } deflateEnd(&zs); return r; } static int zlib_decompress(grpc_exec_ctx* exec_ctx, grpc_slice_buffer* input, grpc_slice_buffer* output, int gzip) { z_stream zs; int r; size_t i; size_t count_before = output->count; size_t length_before = output->length; memset(&zs, 0, sizeof(zs)); zs.zalloc = zalloc_gpr; zs.zfree = zfree_gpr; r = inflateInit2(&zs, 15 | (gzip ? 16 : 0)); GPR_ASSERT(r == Z_OK); r = zlib_body(exec_ctx, &zs, input, output, inflate); if (!r) { for (i = count_before; i < output->count; i++) { grpc_slice_unref_internal(exec_ctx, output->slices[i]); } output->count = count_before; output->length = length_before; } inflateEnd(&zs); return r; } static int copy(grpc_slice_buffer* input, grpc_slice_buffer* output) { size_t i; for (i = 0; i < input->count; i++) { grpc_slice_buffer_add(output, grpc_slice_ref_internal(input->slices[i])); } return 1; } static int compress_inner(grpc_exec_ctx* exec_ctx, grpc_compression_algorithm algorithm, grpc_slice_buffer* input, grpc_slice_buffer* output) { switch (algorithm) { case GRPC_COMPRESS_NONE: /* the fallback path always needs to be send uncompressed: we simply rely on that here */ return 0; case GRPC_COMPRESS_DEFLATE: return zlib_compress(exec_ctx, input, output, 0); case GRPC_COMPRESS_GZIP: return zlib_compress(exec_ctx, input, output, 1); case GRPC_COMPRESS_ALGORITHMS_COUNT: break; } gpr_log(GPR_ERROR, "invalid compression algorithm %d", algorithm); return 0; } int grpc_msg_compress(grpc_exec_ctx* exec_ctx, grpc_compression_algorithm algorithm, grpc_slice_buffer* input, grpc_slice_buffer* output) { if (!compress_inner(exec_ctx, algorithm, input, output)) { copy(input, output); return 0; } return 1; } int grpc_msg_decompress(grpc_exec_ctx* exec_ctx, grpc_compression_algorithm algorithm, grpc_slice_buffer* input, grpc_slice_buffer* output) { switch (algorithm) { case GRPC_COMPRESS_NONE: return copy(input, output); case GRPC_COMPRESS_DEFLATE: return zlib_decompress(exec_ctx, input, output, 0); case GRPC_COMPRESS_GZIP: return zlib_decompress(exec_ctx, input, output, 1); case GRPC_COMPRESS_ALGORITHMS_COUNT: break; } gpr_log(GPR_ERROR, "invalid compression algorithm %d", algorithm); return 0; } grpc-1.3.2/src/core/lib/compression/message_compress.h000066400000000000000000000047311310511640000230020ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_COMPRESSION_MESSAGE_COMPRESS_H #define GRPC_CORE_LIB_COMPRESSION_MESSAGE_COMPRESS_H #include #include /* compress 'input' to 'output' using 'algorithm'. On success, appends compressed slices to output and returns 1. On failure, appends uncompressed slices to output and returns 0. */ int grpc_msg_compress(grpc_exec_ctx* exec_ctx, grpc_compression_algorithm algorithm, grpc_slice_buffer* input, grpc_slice_buffer* output); /* decompress 'input' to 'output' using 'algorithm'. On success, appends slices to output and returns 1. On failure, output is unchanged, and returns 0. */ int grpc_msg_decompress(grpc_exec_ctx* exec_ctx, grpc_compression_algorithm algorithm, grpc_slice_buffer* input, grpc_slice_buffer* output); #endif /* GRPC_CORE_LIB_COMPRESSION_MESSAGE_COMPRESS_H */ grpc-1.3.2/src/core/lib/debug/000077500000000000000000000000001310511640000160125ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/debug/trace.c000066400000000000000000000072551310511640000172650ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/debug/trace.h" #include #include #include #include #include "src/core/lib/support/env.h" typedef struct tracer { const char *name; int *flag; struct tracer *next; } tracer; static tracer *tracers; void grpc_register_tracer(const char *name, int *flag) { tracer *t = gpr_malloc(sizeof(*t)); t->name = name; t->flag = flag; t->next = tracers; *flag = 0; tracers = t; } static void add(const char *beg, const char *end, char ***ss, size_t *ns) { size_t n = *ns; size_t np = n + 1; char *s; size_t len; GPR_ASSERT(end >= beg); len = (size_t)(end - beg); s = gpr_malloc(len + 1); memcpy(s, beg, len); s[len] = 0; *ss = gpr_realloc(*ss, sizeof(char **) * np); (*ss)[n] = s; *ns = np; } static void split(const char *s, char ***ss, size_t *ns) { const char *c = strchr(s, ','); if (c == NULL) { add(s, s + strlen(s), ss, ns); } else { add(s, c, ss, ns); split(c + 1, ss, ns); } } static void parse(const char *s) { char **strings = NULL; size_t nstrings = 0; size_t i; split(s, &strings, &nstrings); for (i = 0; i < nstrings; i++) { if (strings[i][0] == '-') { grpc_tracer_set_enabled(strings[i] + 1, 0); } else { grpc_tracer_set_enabled(strings[i], 1); } } for (i = 0; i < nstrings; i++) { gpr_free(strings[i]); } gpr_free(strings); } void grpc_tracer_init(const char *env_var) { char *e = gpr_getenv(env_var); if (e != NULL) { parse(e); gpr_free(e); } } void grpc_tracer_shutdown(void) { while (tracers) { tracer *t = tracers; tracers = t->next; gpr_free(t); } } int grpc_tracer_set_enabled(const char *name, int enabled) { tracer *t; if (0 == strcmp(name, "all")) { for (t = tracers; t; t = t->next) { *t->flag = enabled; } } else { int found = 0; for (t = tracers; t; t = t->next) { if (0 == strcmp(name, t->name)) { *t->flag = enabled; found = 1; } } if (!found) { gpr_log(GPR_ERROR, "Unknown trace var: '%s'", name); return 0; /* early return */ } } return 1; } grpc-1.3.2/src/core/lib/debug/trace.h000066400000000000000000000035101310511640000172600ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_DEBUG_TRACE_H #define GRPC_CORE_LIB_DEBUG_TRACE_H #include void grpc_register_tracer(const char *name, int *flag); void grpc_tracer_init(const char *env_var_name); void grpc_tracer_shutdown(void); #endif /* GRPC_CORE_LIB_DEBUG_TRACE_H */ grpc-1.3.2/src/core/lib/http/000077500000000000000000000000001310511640000157035ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/http/format_request.c000066400000000000000000000113041310511640000211060ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/http/format_request.h" #include #include #include #include #include #include #include #include "src/core/lib/support/string.h" static void fill_common_header(const grpc_httpcli_request *request, gpr_strvec *buf, bool connection_close) { size_t i; gpr_strvec_add(buf, gpr_strdup(request->http.path)); gpr_strvec_add(buf, gpr_strdup(" HTTP/1.0\r\n")); /* just in case some crazy server really expects HTTP/1.1 */ gpr_strvec_add(buf, gpr_strdup("Host: ")); gpr_strvec_add(buf, gpr_strdup(request->host)); gpr_strvec_add(buf, gpr_strdup("\r\n")); if (connection_close) gpr_strvec_add(buf, gpr_strdup("Connection: close\r\n")); gpr_strvec_add(buf, gpr_strdup("User-Agent: " GRPC_HTTPCLI_USER_AGENT "\r\n")); /* user supplied headers */ for (i = 0; i < request->http.hdr_count; i++) { gpr_strvec_add(buf, gpr_strdup(request->http.hdrs[i].key)); gpr_strvec_add(buf, gpr_strdup(": ")); gpr_strvec_add(buf, gpr_strdup(request->http.hdrs[i].value)); gpr_strvec_add(buf, gpr_strdup("\r\n")); } } grpc_slice grpc_httpcli_format_get_request( const grpc_httpcli_request *request) { gpr_strvec out; char *flat; size_t flat_len; gpr_strvec_init(&out); gpr_strvec_add(&out, gpr_strdup("GET ")); fill_common_header(request, &out, true); gpr_strvec_add(&out, gpr_strdup("\r\n")); flat = gpr_strvec_flatten(&out, &flat_len); gpr_strvec_destroy(&out); return grpc_slice_new(flat, flat_len, gpr_free); } grpc_slice grpc_httpcli_format_post_request(const grpc_httpcli_request *request, const char *body_bytes, size_t body_size) { gpr_strvec out; char *tmp; size_t out_len; size_t i; gpr_strvec_init(&out); gpr_strvec_add(&out, gpr_strdup("POST ")); fill_common_header(request, &out, true); if (body_bytes) { uint8_t has_content_type = 0; for (i = 0; i < request->http.hdr_count; i++) { if (strcmp(request->http.hdrs[i].key, "Content-Type") == 0) { has_content_type = 1; break; } } if (!has_content_type) { gpr_strvec_add(&out, gpr_strdup("Content-Type: text/plain\r\n")); } gpr_asprintf(&tmp, "Content-Length: %lu\r\n", (unsigned long)body_size); gpr_strvec_add(&out, tmp); } gpr_strvec_add(&out, gpr_strdup("\r\n")); tmp = gpr_strvec_flatten(&out, &out_len); gpr_strvec_destroy(&out); if (body_bytes) { tmp = gpr_realloc(tmp, out_len + body_size); memcpy(tmp + out_len, body_bytes, body_size); out_len += body_size; } return grpc_slice_new(tmp, out_len, gpr_free); } grpc_slice grpc_httpcli_format_connect_request( const grpc_httpcli_request *request) { gpr_strvec out; gpr_strvec_init(&out); gpr_strvec_add(&out, gpr_strdup("CONNECT ")); fill_common_header(request, &out, false); gpr_strvec_add(&out, gpr_strdup("\r\n")); size_t flat_len; char *flat = gpr_strvec_flatten(&out, &flat_len); gpr_strvec_destroy(&out); return grpc_slice_new(flat, flat_len, gpr_free); } grpc-1.3.2/src/core/lib/http/format_request.h000066400000000000000000000041541310511640000211200ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_HTTP_FORMAT_REQUEST_H #define GRPC_CORE_LIB_HTTP_FORMAT_REQUEST_H #include #include "src/core/lib/http/httpcli.h" grpc_slice grpc_httpcli_format_get_request(const grpc_httpcli_request *request); grpc_slice grpc_httpcli_format_post_request(const grpc_httpcli_request *request, const char *body_bytes, size_t body_size); grpc_slice grpc_httpcli_format_connect_request( const grpc_httpcli_request *request); #endif /* GRPC_CORE_LIB_HTTP_FORMAT_REQUEST_H */ grpc-1.3.2/src/core/lib/http/httpcli.c000066400000000000000000000307301310511640000175210ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/http/httpcli.h" #include #include #include #include #include #include "src/core/lib/http/format_request.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/support/string.h" typedef struct { grpc_slice request_text; grpc_http_parser parser; grpc_resolved_addresses *addresses; size_t next_address; grpc_endpoint *ep; char *host; char *ssl_host_override; gpr_timespec deadline; int have_read_byte; const grpc_httpcli_handshaker *handshaker; grpc_closure *on_done; grpc_httpcli_context *context; grpc_polling_entity *pollent; grpc_iomgr_object iomgr_obj; grpc_slice_buffer incoming; grpc_slice_buffer outgoing; grpc_closure on_read; grpc_closure done_write; grpc_closure connected; grpc_error *overall_error; grpc_resource_quota *resource_quota; } internal_request; static grpc_httpcli_get_override g_get_override = NULL; static grpc_httpcli_post_override g_post_override = NULL; static void plaintext_handshake(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *endpoint, const char *host, gpr_timespec deadline, void (*on_done)(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *endpoint)) { on_done(exec_ctx, arg, endpoint); } const grpc_httpcli_handshaker grpc_httpcli_plaintext = {"http", plaintext_handshake}; void grpc_httpcli_context_init(grpc_httpcli_context *context) { context->pollset_set = grpc_pollset_set_create(); } void grpc_httpcli_context_destroy(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context) { grpc_pollset_set_destroy(exec_ctx, context->pollset_set); } static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req, grpc_error *due_to_error); static void finish(grpc_exec_ctx *exec_ctx, internal_request *req, grpc_error *error) { grpc_polling_entity_del_from_pollset_set(exec_ctx, req->pollent, req->context->pollset_set); grpc_closure_sched(exec_ctx, req->on_done, error); grpc_http_parser_destroy(&req->parser); if (req->addresses != NULL) { grpc_resolved_addresses_destroy(req->addresses); } if (req->ep != NULL) { grpc_endpoint_destroy(exec_ctx, req->ep); } grpc_slice_unref_internal(exec_ctx, req->request_text); gpr_free(req->host); gpr_free(req->ssl_host_override); grpc_iomgr_unregister_object(&req->iomgr_obj); grpc_slice_buffer_destroy_internal(exec_ctx, &req->incoming); grpc_slice_buffer_destroy_internal(exec_ctx, &req->outgoing); GRPC_ERROR_UNREF(req->overall_error); grpc_resource_quota_unref_internal(exec_ctx, req->resource_quota); gpr_free(req); } static void append_error(internal_request *req, grpc_error *error) { if (req->overall_error == GRPC_ERROR_NONE) { req->overall_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed HTTP/1 client request"); } grpc_resolved_address *addr = &req->addresses->addrs[req->next_address - 1]; char *addr_text = grpc_sockaddr_to_uri(addr); req->overall_error = grpc_error_add_child( req->overall_error, grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(addr_text))); gpr_free(addr_text); } static void do_read(grpc_exec_ctx *exec_ctx, internal_request *req) { grpc_endpoint_read(exec_ctx, req->ep, &req->incoming, &req->on_read); } static void on_read(grpc_exec_ctx *exec_ctx, void *user_data, grpc_error *error) { internal_request *req = user_data; size_t i; for (i = 0; i < req->incoming.count; i++) { if (GRPC_SLICE_LENGTH(req->incoming.slices[i])) { req->have_read_byte = 1; grpc_error *err = grpc_http_parser_parse(&req->parser, req->incoming.slices[i], NULL); if (err != GRPC_ERROR_NONE) { finish(exec_ctx, req, err); return; } } } if (error == GRPC_ERROR_NONE) { do_read(exec_ctx, req); } else if (!req->have_read_byte) { next_address(exec_ctx, req, GRPC_ERROR_REF(error)); } else { finish(exec_ctx, req, grpc_http_parser_eof(&req->parser)); } } static void on_written(grpc_exec_ctx *exec_ctx, internal_request *req) { do_read(exec_ctx, req); } static void done_write(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { internal_request *req = arg; if (error == GRPC_ERROR_NONE) { on_written(exec_ctx, req); } else { next_address(exec_ctx, req, GRPC_ERROR_REF(error)); } } static void start_write(grpc_exec_ctx *exec_ctx, internal_request *req) { grpc_slice_ref_internal(req->request_text); grpc_slice_buffer_add(&req->outgoing, req->request_text); grpc_endpoint_write(exec_ctx, req->ep, &req->outgoing, &req->done_write); } static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *ep) { internal_request *req = arg; if (!ep) { next_address(exec_ctx, req, GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Unexplained handshake failure")); return; } req->ep = ep; start_write(exec_ctx, req); } static void on_connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { internal_request *req = arg; if (!req->ep) { next_address(exec_ctx, req, GRPC_ERROR_REF(error)); return; } req->handshaker->handshake( exec_ctx, req, req->ep, req->ssl_host_override ? req->ssl_host_override : req->host, req->deadline, on_handshake_done); } static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req, grpc_error *error) { grpc_resolved_address *addr; if (error != GRPC_ERROR_NONE) { append_error(req, error); } if (req->next_address == req->addresses->naddrs) { finish(exec_ctx, req, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Failed HTTP requests to all targets", &req->overall_error, 1)); return; } addr = &req->addresses->addrs[req->next_address++]; grpc_closure_init(&req->connected, on_connected, req, grpc_schedule_on_exec_ctx); grpc_arg arg; arg.key = GRPC_ARG_RESOURCE_QUOTA; arg.type = GRPC_ARG_POINTER; arg.value.pointer.p = req->resource_quota; arg.value.pointer.vtable = grpc_resource_quota_arg_vtable(); grpc_channel_args args = {1, &arg}; grpc_tcp_client_connect(exec_ctx, &req->connected, &req->ep, req->context->pollset_set, &args, addr, req->deadline); } static void on_resolved(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { internal_request *req = arg; if (error != GRPC_ERROR_NONE) { finish(exec_ctx, req, error); return; } req->next_address = 0; next_address(exec_ctx, req, GRPC_ERROR_NONE); } static void internal_request_begin(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context, grpc_polling_entity *pollent, grpc_resource_quota *resource_quota, const grpc_httpcli_request *request, gpr_timespec deadline, grpc_closure *on_done, grpc_httpcli_response *response, const char *name, grpc_slice request_text) { internal_request *req = gpr_malloc(sizeof(internal_request)); memset(req, 0, sizeof(*req)); req->request_text = request_text; grpc_http_parser_init(&req->parser, GRPC_HTTP_RESPONSE, response); req->on_done = on_done; req->deadline = deadline; req->handshaker = request->handshaker ? request->handshaker : &grpc_httpcli_plaintext; req->context = context; req->pollent = pollent; req->overall_error = GRPC_ERROR_NONE; req->resource_quota = grpc_resource_quota_ref_internal(resource_quota); grpc_closure_init(&req->on_read, on_read, req, grpc_schedule_on_exec_ctx); grpc_closure_init(&req->done_write, done_write, req, grpc_schedule_on_exec_ctx); grpc_slice_buffer_init(&req->incoming); grpc_slice_buffer_init(&req->outgoing); grpc_iomgr_register_object(&req->iomgr_obj, name); req->host = gpr_strdup(request->host); req->ssl_host_override = gpr_strdup(request->ssl_host_override); GPR_ASSERT(pollent); grpc_polling_entity_add_to_pollset_set(exec_ctx, req->pollent, req->context->pollset_set); grpc_resolve_address( exec_ctx, request->host, req->handshaker->default_port, req->context->pollset_set, grpc_closure_create(on_resolved, req, grpc_schedule_on_exec_ctx), &req->addresses); } void grpc_httpcli_get(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context, grpc_polling_entity *pollent, grpc_resource_quota *resource_quota, const grpc_httpcli_request *request, gpr_timespec deadline, grpc_closure *on_done, grpc_httpcli_response *response) { char *name; if (g_get_override && g_get_override(exec_ctx, request, deadline, on_done, response)) { return; } gpr_asprintf(&name, "HTTP:GET:%s:%s", request->host, request->http.path); internal_request_begin(exec_ctx, context, pollent, resource_quota, request, deadline, on_done, response, name, grpc_httpcli_format_get_request(request)); gpr_free(name); } void grpc_httpcli_post(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context, grpc_polling_entity *pollent, grpc_resource_quota *resource_quota, const grpc_httpcli_request *request, const char *body_bytes, size_t body_size, gpr_timespec deadline, grpc_closure *on_done, grpc_httpcli_response *response) { char *name; if (g_post_override && g_post_override(exec_ctx, request, body_bytes, body_size, deadline, on_done, response)) { return; } gpr_asprintf(&name, "HTTP:POST:%s:%s", request->host, request->http.path); internal_request_begin( exec_ctx, context, pollent, resource_quota, request, deadline, on_done, response, name, grpc_httpcli_format_post_request(request, body_bytes, body_size)); gpr_free(name); } void grpc_httpcli_set_override(grpc_httpcli_get_override get, grpc_httpcli_post_override post) { g_get_override = get; g_post_override = post; } grpc-1.3.2/src/core/lib/http/httpcli.h000066400000000000000000000145071310511640000175320ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_HTTP_HTTPCLI_H #define GRPC_CORE_LIB_HTTP_HTTPCLI_H #include #include #include "src/core/lib/http/parser.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/pollset_set.h" /* User agent this library reports */ #define GRPC_HTTPCLI_USER_AGENT "grpc-httpcli/0.0" /* Tracks in-progress http requests TODO(ctiller): allow caching and capturing multiple requests for the same content and combining them */ typedef struct grpc_httpcli_context { grpc_pollset_set *pollset_set; } grpc_httpcli_context; typedef struct { const char *default_port; void (*handshake)(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *endpoint, const char *host, gpr_timespec deadline, void (*on_done)(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *endpoint)); } grpc_httpcli_handshaker; extern const grpc_httpcli_handshaker grpc_httpcli_plaintext; extern const grpc_httpcli_handshaker grpc_httpcli_ssl; /* A request */ typedef struct grpc_httpcli_request { /* The host name to connect to */ char *host; /* The host to verify in the SSL handshake (or NULL) */ char *ssl_host_override; /* The main part of the request The following headers are supplied automatically and MUST NOT be set here: Host, Connection, User-Agent */ grpc_http_request http; /* handshaker to use ssl for the request */ const grpc_httpcli_handshaker *handshaker; } grpc_httpcli_request; /* Expose the parser response type as a httpcli response too */ typedef struct grpc_http_response grpc_httpcli_response; void grpc_httpcli_context_init(grpc_httpcli_context *context); void grpc_httpcli_context_destroy(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context); /* Asynchronously perform a HTTP GET. 'context' specifies the http context under which to do the get 'pollset' indicates a grpc_pollset that is interested in the result of the get - work on this pollset may be used to progress the get operation 'request' contains request parameters - these are caller owned and can be destroyed once the call returns 'deadline' contains a deadline for the request (or gpr_inf_future) 'on_response' is a callback to report results to */ void grpc_httpcli_get(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context, grpc_polling_entity *pollent, grpc_resource_quota *resource_quota, const grpc_httpcli_request *request, gpr_timespec deadline, grpc_closure *on_complete, grpc_httpcli_response *response); /* Asynchronously perform a HTTP POST. 'context' specifies the http context under which to do the post 'pollset' indicates a grpc_pollset that is interested in the result of the post - work on this pollset may be used to progress the post operation 'request' contains request parameters - these are caller owned and can be destroyed once the call returns 'body_bytes' and 'body_size' specify the payload for the post. When there is no body, pass in NULL as body_bytes. 'deadline' contains a deadline for the request (or gpr_inf_future) 'em' points to a caller owned event manager that must be alive for the lifetime of the request 'on_response' is a callback to report results to Does not support ?var1=val1&var2=val2 in the path. */ void grpc_httpcli_post(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context, grpc_polling_entity *pollent, grpc_resource_quota *resource_quota, const grpc_httpcli_request *request, const char *body_bytes, size_t body_size, gpr_timespec deadline, grpc_closure *on_complete, grpc_httpcli_response *response); /* override functions return 1 if they handled the request, 0 otherwise */ typedef int (*grpc_httpcli_get_override)(grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, gpr_timespec deadline, grpc_closure *on_complete, grpc_httpcli_response *response); typedef int (*grpc_httpcli_post_override)( grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request, const char *body_bytes, size_t body_size, gpr_timespec deadline, grpc_closure *on_complete, grpc_httpcli_response *response); void grpc_httpcli_set_override(grpc_httpcli_get_override get, grpc_httpcli_post_override post); #endif /* GRPC_CORE_LIB_HTTP_HTTPCLI_H */ grpc-1.3.2/src/core/lib/http/httpcli_security_connector.c000066400000000000000000000174421310511640000235270ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/http/httpcli.h" #include #include #include #include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/security/transport/security_handshaker.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/support/string.h" #include "src/core/tsi/ssl_transport_security.h" typedef struct { grpc_channel_security_connector base; tsi_ssl_client_handshaker_factory *handshaker_factory; char *secure_peer_name; } grpc_httpcli_ssl_channel_security_connector; static void httpcli_ssl_destroy(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc) { grpc_httpcli_ssl_channel_security_connector *c = (grpc_httpcli_ssl_channel_security_connector *)sc; if (c->handshaker_factory != NULL) { tsi_ssl_client_handshaker_factory_destroy(c->handshaker_factory); } if (c->secure_peer_name != NULL) gpr_free(c->secure_peer_name); gpr_free(sc); } static void httpcli_ssl_add_handshakers(grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, grpc_handshake_manager *handshake_mgr) { grpc_httpcli_ssl_channel_security_connector *c = (grpc_httpcli_ssl_channel_security_connector *)sc; tsi_handshaker *handshaker = NULL; if (c->handshaker_factory != NULL) { tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker( c->handshaker_factory, c->secure_peer_name, &handshaker); if (result != TSI_OK) { gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.", tsi_result_to_string(result)); } } grpc_handshake_manager_add( handshake_mgr, grpc_security_handshaker_create(exec_ctx, handshaker, &sc->base)); } static void httpcli_ssl_check_peer(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, grpc_auth_context **auth_context, grpc_closure *on_peer_checked) { grpc_httpcli_ssl_channel_security_connector *c = (grpc_httpcli_ssl_channel_security_connector *)sc; grpc_error *error = GRPC_ERROR_NONE; /* Check the peer name. */ if (c->secure_peer_name != NULL && !tsi_ssl_peer_matches_name(&peer, c->secure_peer_name)) { char *msg; gpr_asprintf(&msg, "Peer name %s is not in peer certificate", c->secure_peer_name); error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); } grpc_closure_sched(exec_ctx, on_peer_checked, error); tsi_peer_destruct(&peer); } static grpc_security_connector_vtable httpcli_ssl_vtable = { httpcli_ssl_destroy, httpcli_ssl_check_peer}; static grpc_security_status httpcli_ssl_channel_security_connector_create( grpc_exec_ctx *exec_ctx, const unsigned char *pem_root_certs, size_t pem_root_certs_size, const char *secure_peer_name, grpc_channel_security_connector **sc) { tsi_result result = TSI_OK; grpc_httpcli_ssl_channel_security_connector *c; if (secure_peer_name != NULL && pem_root_certs == NULL) { gpr_log(GPR_ERROR, "Cannot assert a secure peer name without a trust root."); return GRPC_SECURITY_ERROR; } c = gpr_zalloc(sizeof(grpc_httpcli_ssl_channel_security_connector)); gpr_ref_init(&c->base.base.refcount, 1); c->base.base.vtable = &httpcli_ssl_vtable; if (secure_peer_name != NULL) { c->secure_peer_name = gpr_strdup(secure_peer_name); } result = tsi_create_ssl_client_handshaker_factory( NULL, 0, NULL, 0, pem_root_certs, pem_root_certs_size, NULL, NULL, NULL, 0, &c->handshaker_factory); if (result != TSI_OK) { gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", tsi_result_to_string(result)); httpcli_ssl_destroy(exec_ctx, &c->base.base); *sc = NULL; return GRPC_SECURITY_ERROR; } c->base.add_handshakers = httpcli_ssl_add_handshakers; *sc = &c->base; return GRPC_SECURITY_OK; } /* handshaker */ typedef struct { void (*func)(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *endpoint); void *arg; grpc_handshake_manager *handshake_mgr; } on_done_closure; static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_handshaker_args *args = arg; on_done_closure *c = args->user_data; if (error != GRPC_ERROR_NONE) { const char *msg = grpc_error_string(error); gpr_log(GPR_ERROR, "Secure transport setup failed: %s", msg); c->func(exec_ctx, c->arg, NULL); } else { grpc_channel_args_destroy(exec_ctx, args->args); grpc_slice_buffer_destroy_internal(exec_ctx, args->read_buffer); gpr_free(args->read_buffer); c->func(exec_ctx, c->arg, args->endpoint); } grpc_handshake_manager_destroy(exec_ctx, c->handshake_mgr); gpr_free(c); } static void ssl_handshake(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp, const char *host, gpr_timespec deadline, void (*on_done)(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *endpoint)) { grpc_channel_security_connector *sc = NULL; const unsigned char *pem_root_certs = NULL; on_done_closure *c = gpr_malloc(sizeof(*c)); size_t pem_root_certs_size = grpc_get_default_ssl_roots(&pem_root_certs); if (pem_root_certs == NULL || pem_root_certs_size == 0) { gpr_log(GPR_ERROR, "Could not get default pem root certs."); on_done(exec_ctx, arg, NULL); gpr_free(c); return; } c->func = on_done; c->arg = arg; c->handshake_mgr = grpc_handshake_manager_create(); GPR_ASSERT(httpcli_ssl_channel_security_connector_create( exec_ctx, pem_root_certs, pem_root_certs_size, host, &sc) == GRPC_SECURITY_OK); grpc_channel_security_connector_add_handshakers(exec_ctx, sc, c->handshake_mgr); grpc_handshake_manager_do_handshake( exec_ctx, c->handshake_mgr, tcp, NULL /* channel_args */, deadline, NULL /* acceptor */, on_handshake_done, c /* user_data */); GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, &sc->base, "httpcli"); } const grpc_httpcli_handshaker grpc_httpcli_ssl = {"https", ssl_handshake}; grpc-1.3.2/src/core/lib/http/parser.c000066400000000000000000000306711310511640000173520ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/http/parser.h" #include #include #include #include #include int grpc_http1_trace = 0; static char *buf2str(void *buffer, size_t length) { char *out = gpr_malloc(length + 1); memcpy(out, buffer, length); out[length] = 0; return out; } static grpc_error *handle_response_line(grpc_http_parser *parser) { uint8_t *beg = parser->cur_line; uint8_t *cur = beg; uint8_t *end = beg + parser->cur_line_length; if (cur == end || *cur++ != 'H') return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected 'H'"); if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected 'T'"); if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected 'T'"); if (cur == end || *cur++ != 'P') return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected 'P'"); if (cur == end || *cur++ != '/') return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected '/'"); if (cur == end || *cur++ != '1') return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected '1'"); if (cur == end || *cur++ != '.') return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected '.'"); if (cur == end || *cur < '0' || *cur++ > '1') { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Expected HTTP/1.0 or HTTP/1.1"); } if (cur == end || *cur++ != ' ') return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected ' '"); if (cur == end || *cur < '1' || *cur++ > '9') return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected status code"); if (cur == end || *cur < '0' || *cur++ > '9') return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected status code"); if (cur == end || *cur < '0' || *cur++ > '9') return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected status code"); parser->http.response->status = (cur[-3] - '0') * 100 + (cur[-2] - '0') * 10 + (cur[-1] - '0'); if (cur == end || *cur++ != ' ') return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected ' '"); /* we don't really care about the status code message */ return GRPC_ERROR_NONE; } static grpc_error *handle_request_line(grpc_http_parser *parser) { uint8_t *beg = parser->cur_line; uint8_t *cur = beg; uint8_t *end = beg + parser->cur_line_length; uint8_t vers_major = 0; uint8_t vers_minor = 0; while (cur != end && *cur++ != ' ') ; if (cur == end) return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "No method on HTTP request line"); parser->http.request->method = buf2str(beg, (size_t)(cur - beg - 1)); beg = cur; while (cur != end && *cur++ != ' ') ; if (cur == end) return GRPC_ERROR_CREATE_FROM_STATIC_STRING("No path on HTTP request line"); parser->http.request->path = buf2str(beg, (size_t)(cur - beg - 1)); if (cur == end || *cur++ != 'H') return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected 'H'"); if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected 'T'"); if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected 'T'"); if (cur == end || *cur++ != 'P') return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected 'P'"); if (cur == end || *cur++ != '/') return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected '/'"); vers_major = (uint8_t)(*cur++ - '1' + 1); ++cur; if (cur == end) return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "End of line in HTTP version string"); vers_minor = (uint8_t)(*cur++ - '1' + 1); if (vers_major == 1) { if (vers_minor == 0) { parser->http.request->version = GRPC_HTTP_HTTP10; } else if (vers_minor == 1) { parser->http.request->version = GRPC_HTTP_HTTP11; } else { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0"); } } else if (vers_major == 2) { if (vers_minor == 0) { parser->http.request->version = GRPC_HTTP_HTTP20; } else { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0"); } } else { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0"); } return GRPC_ERROR_NONE; } static grpc_error *handle_first_line(grpc_http_parser *parser) { switch (parser->type) { case GRPC_HTTP_REQUEST: return handle_request_line(parser); case GRPC_HTTP_RESPONSE: return handle_response_line(parser); } GPR_UNREACHABLE_CODE( return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Should never reach here")); } static grpc_error *add_header(grpc_http_parser *parser) { uint8_t *beg = parser->cur_line; uint8_t *cur = beg; uint8_t *end = beg + parser->cur_line_length; size_t *hdr_count = NULL; grpc_http_header **hdrs = NULL; grpc_http_header hdr = {NULL, NULL}; grpc_error *error = GRPC_ERROR_NONE; GPR_ASSERT(cur != end); if (*cur == ' ' || *cur == '\t') { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Continued header lines not supported yet"); goto done; } while (cur != end && *cur != ':') { cur++; } if (cur == end) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Didn't find ':' in header string"); goto done; } GPR_ASSERT(cur >= beg); hdr.key = buf2str(beg, (size_t)(cur - beg)); cur++; /* skip : */ while (cur != end && (*cur == ' ' || *cur == '\t')) { cur++; } GPR_ASSERT((size_t)(end - cur) >= parser->cur_line_end_length); hdr.value = buf2str(cur, (size_t)(end - cur) - parser->cur_line_end_length); switch (parser->type) { case GRPC_HTTP_RESPONSE: hdr_count = &parser->http.response->hdr_count; hdrs = &parser->http.response->hdrs; break; case GRPC_HTTP_REQUEST: hdr_count = &parser->http.request->hdr_count; hdrs = &parser->http.request->hdrs; break; } if (*hdr_count == parser->hdr_capacity) { parser->hdr_capacity = GPR_MAX(parser->hdr_capacity + 1, parser->hdr_capacity * 3 / 2); *hdrs = gpr_realloc(*hdrs, parser->hdr_capacity * sizeof(**hdrs)); } (*hdrs)[(*hdr_count)++] = hdr; done: if (error != GRPC_ERROR_NONE) { gpr_free(hdr.key); gpr_free(hdr.value); } return error; } static grpc_error *finish_line(grpc_http_parser *parser, bool *found_body_start) { grpc_error *err; switch (parser->state) { case GRPC_HTTP_FIRST_LINE: err = handle_first_line(parser); if (err != GRPC_ERROR_NONE) return err; parser->state = GRPC_HTTP_HEADERS; break; case GRPC_HTTP_HEADERS: if (parser->cur_line_length == parser->cur_line_end_length) { parser->state = GRPC_HTTP_BODY; *found_body_start = true; break; } err = add_header(parser); if (err != GRPC_ERROR_NONE) { return err; } break; case GRPC_HTTP_BODY: GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Should never reach here")); } parser->cur_line_length = 0; return GRPC_ERROR_NONE; } static grpc_error *addbyte_body(grpc_http_parser *parser, uint8_t byte) { size_t *body_length = NULL; char **body = NULL; if (parser->type == GRPC_HTTP_RESPONSE) { body_length = &parser->http.response->body_length; body = &parser->http.response->body; } else if (parser->type == GRPC_HTTP_REQUEST) { body_length = &parser->http.request->body_length; body = &parser->http.request->body; } else { GPR_UNREACHABLE_CODE( return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Should never reach here")); } if (*body_length == parser->body_capacity) { parser->body_capacity = GPR_MAX(8, parser->body_capacity * 3 / 2); *body = gpr_realloc((void *)*body, parser->body_capacity); } (*body)[*body_length] = (char)byte; (*body_length)++; return GRPC_ERROR_NONE; } static bool check_line(grpc_http_parser *parser) { if (parser->cur_line_length >= 2 && parser->cur_line[parser->cur_line_length - 2] == '\r' && parser->cur_line[parser->cur_line_length - 1] == '\n') { return true; } // HTTP request with \n\r line termiantors. else if (parser->cur_line_length >= 2 && parser->cur_line[parser->cur_line_length - 2] == '\n' && parser->cur_line[parser->cur_line_length - 1] == '\r') { return true; } // HTTP request with only \n line terminators. else if (parser->cur_line_length >= 1 && parser->cur_line[parser->cur_line_length - 1] == '\n') { parser->cur_line_end_length = 1; return true; } return false; } static grpc_error *addbyte(grpc_http_parser *parser, uint8_t byte, bool *found_body_start) { switch (parser->state) { case GRPC_HTTP_FIRST_LINE: case GRPC_HTTP_HEADERS: if (parser->cur_line_length >= GRPC_HTTP_PARSER_MAX_HEADER_LENGTH) { if (grpc_http1_trace) gpr_log(GPR_ERROR, "HTTP header max line length (%d) exceeded", GRPC_HTTP_PARSER_MAX_HEADER_LENGTH); return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "HTTP header max line length exceeded"); } parser->cur_line[parser->cur_line_length] = byte; parser->cur_line_length++; if (check_line(parser)) { return finish_line(parser, found_body_start); } return GRPC_ERROR_NONE; case GRPC_HTTP_BODY: return addbyte_body(parser, byte); } GPR_UNREACHABLE_CODE(return GRPC_ERROR_NONE); } void grpc_http_parser_init(grpc_http_parser *parser, grpc_http_type type, void *request_or_response) { memset(parser, 0, sizeof(*parser)); parser->state = GRPC_HTTP_FIRST_LINE; parser->type = type; parser->http.request_or_response = request_or_response; parser->cur_line_end_length = 2; } void grpc_http_parser_destroy(grpc_http_parser *parser) {} void grpc_http_request_destroy(grpc_http_request *request) { size_t i; gpr_free(request->body); for (i = 0; i < request->hdr_count; i++) { gpr_free(request->hdrs[i].key); gpr_free(request->hdrs[i].value); } gpr_free(request->hdrs); gpr_free(request->method); gpr_free(request->path); } void grpc_http_response_destroy(grpc_http_response *response) { size_t i; gpr_free(response->body); for (i = 0; i < response->hdr_count; i++) { gpr_free(response->hdrs[i].key); gpr_free(response->hdrs[i].value); } gpr_free(response->hdrs); } grpc_error *grpc_http_parser_parse(grpc_http_parser *parser, grpc_slice slice, size_t *start_of_body) { for (size_t i = 0; i < GRPC_SLICE_LENGTH(slice); i++) { bool found_body_start = false; grpc_error *err = addbyte(parser, GRPC_SLICE_START_PTR(slice)[i], &found_body_start); if (err != GRPC_ERROR_NONE) return err; if (found_body_start && start_of_body != NULL) *start_of_body = i + 1; } return GRPC_ERROR_NONE; } grpc_error *grpc_http_parser_eof(grpc_http_parser *parser) { if (parser->state != GRPC_HTTP_BODY) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Did not finish headers"); } return GRPC_ERROR_NONE; } grpc-1.3.2/src/core/lib/http/parser.h000066400000000000000000000077171310511640000173640ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_HTTP_PARSER_H #define GRPC_CORE_LIB_HTTP_PARSER_H #include #include #include "src/core/lib/iomgr/error.h" /* Maximum length of a header string of the form 'Key: Value\r\n' */ #define GRPC_HTTP_PARSER_MAX_HEADER_LENGTH 4096 /* A single header to be passed in a request */ typedef struct grpc_http_header { char *key; char *value; } grpc_http_header; typedef enum { GRPC_HTTP_FIRST_LINE, GRPC_HTTP_HEADERS, GRPC_HTTP_BODY } grpc_http_parser_state; typedef enum { GRPC_HTTP_HTTP10, GRPC_HTTP_HTTP11, GRPC_HTTP_HTTP20, } grpc_http_version; typedef enum { GRPC_HTTP_RESPONSE, GRPC_HTTP_REQUEST, } grpc_http_type; /* A request */ typedef struct grpc_http_request { /* Method of the request (e.g. GET, POST) */ char *method; /* The path of the resource to fetch */ char *path; /* HTTP version to use */ grpc_http_version version; /* Headers attached to the request */ size_t hdr_count; grpc_http_header *hdrs; /* Body: length and contents; contents are NOT null-terminated */ size_t body_length; char *body; } grpc_http_request; /* A response */ typedef struct grpc_http_response { /* HTTP status code */ int status; /* Headers: count and key/values */ size_t hdr_count; grpc_http_header *hdrs; /* Body: length and contents; contents are NOT null-terminated */ size_t body_length; char *body; } grpc_http_response; typedef struct { grpc_http_parser_state state; grpc_http_type type; union { grpc_http_response *response; grpc_http_request *request; void *request_or_response; } http; size_t body_capacity; size_t hdr_capacity; uint8_t cur_line[GRPC_HTTP_PARSER_MAX_HEADER_LENGTH]; size_t cur_line_length; size_t cur_line_end_length; } grpc_http_parser; void grpc_http_parser_init(grpc_http_parser *parser, grpc_http_type type, void *request_or_response); void grpc_http_parser_destroy(grpc_http_parser *parser); /* Sets \a start_of_body to the offset in \a slice of the start of the body. */ grpc_error *grpc_http_parser_parse(grpc_http_parser *parser, grpc_slice slice, size_t *start_of_body); grpc_error *grpc_http_parser_eof(grpc_http_parser *parser); void grpc_http_request_destroy(grpc_http_request *request); void grpc_http_response_destroy(grpc_http_response *response); extern int grpc_http1_trace; #endif /* GRPC_CORE_LIB_HTTP_PARSER_H */ grpc-1.3.2/src/core/lib/iomgr/000077500000000000000000000000001310511640000160415ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/iomgr/README.md000066400000000000000000000002631310511640000173210ustar00rootroot00000000000000# iomgr Platform abstractions for I/O (mostly network). Provides abstractions over TCP/UDP I/O, file loading, polling, and concurrency management for various operating systems. grpc-1.3.2/src/core/lib/iomgr/closure.c000066400000000000000000000122141310511640000176610ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/closure.h" #include #include #include #include "src/core/lib/profiling/timers.h" grpc_closure *grpc_closure_init(grpc_closure *closure, grpc_iomgr_cb_func cb, void *cb_arg, grpc_closure_scheduler *scheduler) { closure->cb = cb; closure->cb_arg = cb_arg; closure->scheduler = scheduler; #ifndef NDEBUG closure->scheduled = false; #endif return closure; } void grpc_closure_list_init(grpc_closure_list *closure_list) { closure_list->head = closure_list->tail = NULL; } bool grpc_closure_list_append(grpc_closure_list *closure_list, grpc_closure *closure, grpc_error *error) { if (closure == NULL) { GRPC_ERROR_UNREF(error); return false; } closure->error_data.error = error; closure->next_data.next = NULL; bool was_empty = (closure_list->head == NULL); if (was_empty) { closure_list->head = closure; } else { closure_list->tail->next_data.next = closure; } closure_list->tail = closure; return was_empty; } void grpc_closure_list_fail_all(grpc_closure_list *list, grpc_error *forced_failure) { for (grpc_closure *c = list->head; c != NULL; c = c->next_data.next) { if (c->error_data.error == GRPC_ERROR_NONE) { c->error_data.error = GRPC_ERROR_REF(forced_failure); } } GRPC_ERROR_UNREF(forced_failure); } bool grpc_closure_list_empty(grpc_closure_list closure_list) { return closure_list.head == NULL; } void grpc_closure_list_move(grpc_closure_list *src, grpc_closure_list *dst) { if (src->head == NULL) { return; } if (dst->head == NULL) { *dst = *src; } else { dst->tail->next_data.next = src->head; dst->tail = src->tail; } src->head = src->tail = NULL; } typedef struct { grpc_iomgr_cb_func cb; void *cb_arg; grpc_closure wrapper; } wrapped_closure; static void closure_wrapper(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { wrapped_closure *wc = arg; grpc_iomgr_cb_func cb = wc->cb; void *cb_arg = wc->cb_arg; gpr_free(wc); cb(exec_ctx, cb_arg, error); } grpc_closure *grpc_closure_create(grpc_iomgr_cb_func cb, void *cb_arg, grpc_closure_scheduler *scheduler) { wrapped_closure *wc = gpr_malloc(sizeof(*wc)); wc->cb = cb; wc->cb_arg = cb_arg; grpc_closure_init(&wc->wrapper, closure_wrapper, wc, scheduler); return &wc->wrapper; } void grpc_closure_run(grpc_exec_ctx *exec_ctx, grpc_closure *c, grpc_error *error) { GPR_TIMER_BEGIN("grpc_closure_run", 0); if (c != NULL) { assert(c->cb); c->scheduler->vtable->run(exec_ctx, c, error); } else { GRPC_ERROR_UNREF(error); } GPR_TIMER_END("grpc_closure_run", 0); } void grpc_closure_sched(grpc_exec_ctx *exec_ctx, grpc_closure *c, grpc_error *error) { GPR_TIMER_BEGIN("grpc_closure_sched", 0); if (c != NULL) { #ifndef NDEBUG GPR_ASSERT(!c->scheduled); c->scheduled = true; #endif assert(c->cb); c->scheduler->vtable->sched(exec_ctx, c, error); } else { GRPC_ERROR_UNREF(error); } GPR_TIMER_END("grpc_closure_sched", 0); } void grpc_closure_list_sched(grpc_exec_ctx *exec_ctx, grpc_closure_list *list) { grpc_closure *c = list->head; while (c != NULL) { grpc_closure *next = c->next_data.next; #ifndef NDEBUG GPR_ASSERT(!c->scheduled); c->scheduled = true; #endif assert(c->cb); c->scheduler->vtable->sched(exec_ctx, c, c->error_data.error); c = next; } list->head = list->tail = NULL; } grpc-1.3.2/src/core/lib/iomgr/closure.h000066400000000000000000000130341310511640000176670ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_CLOSURE_H #define GRPC_CORE_LIB_IOMGR_CLOSURE_H #include #include #include #include "src/core/lib/iomgr/error.h" #include "src/core/lib/support/mpscq.h" struct grpc_closure; typedef struct grpc_closure grpc_closure; typedef struct grpc_closure_list { grpc_closure *head; grpc_closure *tail; } grpc_closure_list; /** gRPC Callback definition. * * \param arg Arbitrary input. * \param error GRPC_ERROR_NONE if no error occurred, otherwise some grpc_error * describing what went wrong */ typedef void (*grpc_iomgr_cb_func)(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); typedef struct grpc_closure_scheduler grpc_closure_scheduler; typedef struct grpc_closure_scheduler_vtable { /* NOTE: for all these functions, closure->scheduler == the scheduler that was used to find this vtable */ void (*run)(grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_error *error); void (*sched)(grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_error *error); const char *name; } grpc_closure_scheduler_vtable; /** Abstract type that can schedule closures for execution */ struct grpc_closure_scheduler { const grpc_closure_scheduler_vtable *vtable; }; /** A closure over a grpc_iomgr_cb_func. */ struct grpc_closure { /** Once queued, next indicates the next queued closure; before then, scratch * space */ union { grpc_closure *next; gpr_mpscq_node atm_next; uintptr_t scratch; } next_data; /** Bound callback. */ grpc_iomgr_cb_func cb; /** Arguments to be passed to "cb". */ void *cb_arg; /** Scheduler to schedule against: NULL to schedule against current execution context */ grpc_closure_scheduler *scheduler; /** Once queued, the result of the closure. Before then: scratch space */ union { grpc_error *error; uintptr_t scratch; } error_data; #ifndef NDEBUG bool scheduled; #endif }; /** Initializes \a closure with \a cb and \a cb_arg. Returns \a closure. */ grpc_closure *grpc_closure_init(grpc_closure *closure, grpc_iomgr_cb_func cb, void *cb_arg, grpc_closure_scheduler *scheduler); /* Create a heap allocated closure: try to avoid except for very rare events */ grpc_closure *grpc_closure_create(grpc_iomgr_cb_func cb, void *cb_arg, grpc_closure_scheduler *scheduler); #define GRPC_CLOSURE_LIST_INIT \ { NULL, NULL } void grpc_closure_list_init(grpc_closure_list *list); /** add \a closure to the end of \a list and set \a closure's result to \a error Returns true if \a list becomes non-empty */ bool grpc_closure_list_append(grpc_closure_list *list, grpc_closure *closure, grpc_error *error); /** force all success bits in \a list to false */ void grpc_closure_list_fail_all(grpc_closure_list *list, grpc_error *forced_failure); /** append all closures from \a src to \a dst and empty \a src. */ void grpc_closure_list_move(grpc_closure_list *src, grpc_closure_list *dst); /** return whether \a list is empty. */ bool grpc_closure_list_empty(grpc_closure_list list); /** Run a closure directly. Caller ensures that no locks are being held above. * Note that calling this at the end of a closure callback function itself is * by definition safe. */ void grpc_closure_run(grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_error *error); /** Schedule a closure to be run. Does not need to be run from a safe point. */ void grpc_closure_sched(grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_error *error); /** Schedule all closures in a list to be run. Does not need to be run from a * safe point. */ void grpc_closure_list_sched(grpc_exec_ctx *exec_ctx, grpc_closure_list *closure_list); #endif /* GRPC_CORE_LIB_IOMGR_CLOSURE_H */ grpc-1.3.2/src/core/lib/iomgr/combiner.c000066400000000000000000000434371310511640000200160ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/combiner.h" #include #include #include #include #include "src/core/lib/iomgr/workqueue.h" #include "src/core/lib/profiling/timers.h" int grpc_combiner_trace = 0; #define GRPC_COMBINER_TRACE(fn) \ do { \ if (grpc_combiner_trace) { \ fn; \ } \ } while (0) #define STATE_UNORPHANED 1 #define STATE_ELEM_COUNT_LOW_BIT 2 struct grpc_combiner { grpc_combiner *next_combiner_on_this_exec_ctx; grpc_workqueue *optional_workqueue; grpc_closure_scheduler uncovered_scheduler; grpc_closure_scheduler covered_scheduler; grpc_closure_scheduler uncovered_finally_scheduler; grpc_closure_scheduler covered_finally_scheduler; gpr_mpscq queue; // state is: // lower bit - zero if orphaned (STATE_UNORPHANED) // other bits - number of items queued on the lock (STATE_ELEM_COUNT_LOW_BIT) gpr_atm state; // number of elements in the list that are covered by a poller: if >0, we can // offload safely gpr_atm elements_covered_by_poller; bool time_to_execute_final_list; bool final_list_covered_by_poller; grpc_closure_list final_list; grpc_closure offload; gpr_refcount refs; }; static void combiner_exec_uncovered(grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_error *error); static void combiner_exec_covered(grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_error *error); static void combiner_finally_exec_uncovered(grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_error *error); static void combiner_finally_exec_covered(grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_error *error); static const grpc_closure_scheduler_vtable scheduler_uncovered = { combiner_exec_uncovered, combiner_exec_uncovered, "combiner:immediately:uncovered"}; static const grpc_closure_scheduler_vtable scheduler_covered = { combiner_exec_covered, combiner_exec_covered, "combiner:immediately:covered"}; static const grpc_closure_scheduler_vtable finally_scheduler_uncovered = { combiner_finally_exec_uncovered, combiner_finally_exec_uncovered, "combiner:finally:uncovered"}; static const grpc_closure_scheduler_vtable finally_scheduler_covered = { combiner_finally_exec_covered, combiner_finally_exec_covered, "combiner:finally:covered"}; static void offload(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); typedef struct { grpc_error *error; bool covered_by_poller; } error_data; static uintptr_t pack_error_data(error_data d) { return ((uintptr_t)d.error) | (d.covered_by_poller ? 1 : 0); } static error_data unpack_error_data(uintptr_t p) { return (error_data){(grpc_error *)(p & ~(uintptr_t)1), p & 1}; } static bool is_covered_by_poller(grpc_combiner *lock) { return lock->final_list_covered_by_poller || gpr_atm_acq_load(&lock->elements_covered_by_poller) > 0; } #define IS_COVERED_BY_POLLER_FMT "(final=%d elems=%" PRIdPTR ")->%d" #define IS_COVERED_BY_POLLER_ARGS(lock) \ (lock)->final_list_covered_by_poller, \ gpr_atm_acq_load(&(lock)->elements_covered_by_poller), \ is_covered_by_poller((lock)) grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue) { grpc_combiner *lock = gpr_malloc(sizeof(*lock)); gpr_ref_init(&lock->refs, 1); lock->next_combiner_on_this_exec_ctx = NULL; lock->time_to_execute_final_list = false; lock->optional_workqueue = optional_workqueue; lock->final_list_covered_by_poller = false; lock->uncovered_scheduler.vtable = &scheduler_uncovered; lock->covered_scheduler.vtable = &scheduler_covered; lock->uncovered_finally_scheduler.vtable = &finally_scheduler_uncovered; lock->covered_finally_scheduler.vtable = &finally_scheduler_covered; gpr_atm_no_barrier_store(&lock->state, STATE_UNORPHANED); gpr_atm_no_barrier_store(&lock->elements_covered_by_poller, 0); gpr_mpscq_init(&lock->queue); grpc_closure_list_init(&lock->final_list); grpc_closure_init(&lock->offload, offload, lock, grpc_workqueue_scheduler(lock->optional_workqueue)); GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, "C:%p create", lock)); return lock; } static void really_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, "C:%p really_destroy", lock)); GPR_ASSERT(gpr_atm_no_barrier_load(&lock->state) == 0); gpr_mpscq_destroy(&lock->queue); GRPC_WORKQUEUE_UNREF(exec_ctx, lock->optional_workqueue, "combiner"); gpr_free(lock); } static void start_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { gpr_atm old_state = gpr_atm_full_fetch_add(&lock->state, -STATE_UNORPHANED); GRPC_COMBINER_TRACE(gpr_log( GPR_DEBUG, "C:%p really_destroy old_state=%" PRIdPTR, lock, old_state)); if (old_state == 1) { really_destroy(exec_ctx, lock); } } #ifdef GRPC_COMBINER_REFCOUNT_DEBUG #define GRPC_COMBINER_DEBUG_SPAM(op, delta) \ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, \ "combiner[%p] %s %" PRIdPTR " --> %" PRIdPTR " %s", lock, (op), \ gpr_atm_no_barrier_load(&lock->refs.count), \ gpr_atm_no_barrier_load(&lock->refs.count) + (delta), reason); #else #define GRPC_COMBINER_DEBUG_SPAM(op, delta) #endif void grpc_combiner_unref(grpc_exec_ctx *exec_ctx, grpc_combiner *lock GRPC_COMBINER_DEBUG_ARGS) { GRPC_COMBINER_DEBUG_SPAM("UNREF", -1); if (gpr_unref(&lock->refs)) { start_destroy(exec_ctx, lock); } } grpc_combiner *grpc_combiner_ref(grpc_combiner *lock GRPC_COMBINER_DEBUG_ARGS) { GRPC_COMBINER_DEBUG_SPAM(" REF", 1); gpr_ref(&lock->refs); return lock; } static void push_last_on_exec_ctx(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { lock->next_combiner_on_this_exec_ctx = NULL; if (exec_ctx->active_combiner == NULL) { exec_ctx->active_combiner = exec_ctx->last_combiner = lock; } else { exec_ctx->last_combiner->next_combiner_on_this_exec_ctx = lock; exec_ctx->last_combiner = lock; } } static void push_first_on_exec_ctx(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { lock->next_combiner_on_this_exec_ctx = exec_ctx->active_combiner; exec_ctx->active_combiner = lock; if (lock->next_combiner_on_this_exec_ctx == NULL) { exec_ctx->last_combiner = lock; } } static void combiner_exec(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, grpc_closure *cl, grpc_error *error, bool covered_by_poller) { GPR_TIMER_BEGIN("combiner.execute", 0); gpr_atm last = gpr_atm_full_fetch_add(&lock->state, STATE_ELEM_COUNT_LOW_BIT); GRPC_COMBINER_TRACE(gpr_log( GPR_DEBUG, "C:%p grpc_combiner_execute c=%p cov=%d last=%" PRIdPTR, lock, cl, covered_by_poller, last)); GPR_ASSERT(last & STATE_UNORPHANED); // ensure lock has not been destroyed assert(cl->cb); cl->error_data.scratch = pack_error_data((error_data){error, covered_by_poller}); if (covered_by_poller) { gpr_atm_no_barrier_fetch_add(&lock->elements_covered_by_poller, 1); } gpr_mpscq_push(&lock->queue, &cl->next_data.atm_next); if (last == 1) { // first element on this list: add it to the list of combiner locks // executing within this exec_ctx push_last_on_exec_ctx(exec_ctx, lock); } GPR_TIMER_END("combiner.execute", 0); } #define COMBINER_FROM_CLOSURE_SCHEDULER(closure, scheduler_name) \ ((grpc_combiner *)(((char *)((closure)->scheduler)) - \ offsetof(grpc_combiner, scheduler_name))) static void combiner_exec_uncovered(grpc_exec_ctx *exec_ctx, grpc_closure *cl, grpc_error *error) { combiner_exec(exec_ctx, COMBINER_FROM_CLOSURE_SCHEDULER(cl, uncovered_scheduler), cl, error, false); } static void combiner_exec_covered(grpc_exec_ctx *exec_ctx, grpc_closure *cl, grpc_error *error) { combiner_exec(exec_ctx, COMBINER_FROM_CLOSURE_SCHEDULER(cl, covered_scheduler), cl, error, true); } static void move_next(grpc_exec_ctx *exec_ctx) { exec_ctx->active_combiner = exec_ctx->active_combiner->next_combiner_on_this_exec_ctx; if (exec_ctx->active_combiner == NULL) { exec_ctx->last_combiner = NULL; } } static void offload(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_combiner *lock = arg; push_last_on_exec_ctx(exec_ctx, lock); } static void queue_offload(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { move_next(exec_ctx); GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, "C:%p queue_offload --> %p", lock, lock->optional_workqueue)); grpc_closure_sched(exec_ctx, &lock->offload, GRPC_ERROR_NONE); } bool grpc_combiner_continue_exec_ctx(grpc_exec_ctx *exec_ctx) { GPR_TIMER_BEGIN("combiner.continue_exec_ctx", 0); grpc_combiner *lock = exec_ctx->active_combiner; if (lock == NULL) { GPR_TIMER_END("combiner.continue_exec_ctx", 0); return false; } GRPC_COMBINER_TRACE( gpr_log(GPR_DEBUG, "C:%p grpc_combiner_continue_exec_ctx workqueue=%p " "is_covered_by_poller=" IS_COVERED_BY_POLLER_FMT " exec_ctx_ready_to_finish=%d " "time_to_execute_final_list=%d", lock, lock->optional_workqueue, IS_COVERED_BY_POLLER_ARGS(lock), grpc_exec_ctx_ready_to_finish(exec_ctx), lock->time_to_execute_final_list)); if (lock->optional_workqueue != NULL && is_covered_by_poller(lock) && grpc_exec_ctx_ready_to_finish(exec_ctx)) { GPR_TIMER_MARK("offload_from_finished_exec_ctx", 0); // this execution context wants to move on, and we have a workqueue (and // so can help the execution context out): schedule remaining work to be // picked up on the workqueue queue_offload(exec_ctx, lock); GPR_TIMER_END("combiner.continue_exec_ctx", 0); return true; } if (!lock->time_to_execute_final_list || // peek to see if something new has shown up, and execute that with // priority (gpr_atm_acq_load(&lock->state) >> 1) > 1) { gpr_mpscq_node *n = gpr_mpscq_pop(&lock->queue); GRPC_COMBINER_TRACE( gpr_log(GPR_DEBUG, "C:%p maybe_finish_one n=%p", lock, n)); if (n == NULL) { // queue is in an inconsistent state: use this as a cue that we should // go off and do something else for a while (and come back later) GPR_TIMER_MARK("delay_busy", 0); if (lock->optional_workqueue != NULL && is_covered_by_poller(lock)) { queue_offload(exec_ctx, lock); } GPR_TIMER_END("combiner.continue_exec_ctx", 0); return true; } GPR_TIMER_BEGIN("combiner.exec1", 0); grpc_closure *cl = (grpc_closure *)n; error_data err = unpack_error_data(cl->error_data.scratch); #ifndef NDEBUG cl->scheduled = false; #endif cl->cb(exec_ctx, cl->cb_arg, err.error); if (err.covered_by_poller) { gpr_atm_no_barrier_fetch_add(&lock->elements_covered_by_poller, -1); } GRPC_ERROR_UNREF(err.error); GPR_TIMER_END("combiner.exec1", 0); } else { grpc_closure *c = lock->final_list.head; GPR_ASSERT(c != NULL); grpc_closure_list_init(&lock->final_list); lock->final_list_covered_by_poller = false; int loops = 0; while (c != NULL) { GPR_TIMER_BEGIN("combiner.exec_1final", 0); GRPC_COMBINER_TRACE( gpr_log(GPR_DEBUG, "C:%p execute_final[%d] c=%p", lock, loops, c)); grpc_closure *next = c->next_data.next; grpc_error *error = c->error_data.error; #ifndef NDEBUG c->scheduled = false; #endif c->cb(exec_ctx, c->cb_arg, error); GRPC_ERROR_UNREF(error); c = next; GPR_TIMER_END("combiner.exec_1final", 0); } } GPR_TIMER_MARK("unref", 0); move_next(exec_ctx); lock->time_to_execute_final_list = false; gpr_atm old_state = gpr_atm_full_fetch_add(&lock->state, -STATE_ELEM_COUNT_LOW_BIT); GRPC_COMBINER_TRACE( gpr_log(GPR_DEBUG, "C:%p finish old_state=%" PRIdPTR, lock, old_state)); // Define a macro to ease readability of the following switch statement. #define OLD_STATE_WAS(orphaned, elem_count) \ (((orphaned) ? 0 : STATE_UNORPHANED) | \ ((elem_count)*STATE_ELEM_COUNT_LOW_BIT)) // Depending on what the previous state was, we need to perform different // actions. switch (old_state) { default: // we have multiple queued work items: just continue executing them break; case OLD_STATE_WAS(false, 2): case OLD_STATE_WAS(true, 2): // we're down to one queued item: if it's the final list we should do that if (!grpc_closure_list_empty(lock->final_list)) { lock->time_to_execute_final_list = true; } break; case OLD_STATE_WAS(false, 1): // had one count, one unorphaned --> unlocked unorphaned GPR_TIMER_END("combiner.continue_exec_ctx", 0); return true; case OLD_STATE_WAS(true, 1): // and one count, one orphaned --> unlocked and orphaned really_destroy(exec_ctx, lock); GPR_TIMER_END("combiner.continue_exec_ctx", 0); return true; case OLD_STATE_WAS(false, 0): case OLD_STATE_WAS(true, 0): // these values are illegal - representing an already unlocked or // deleted lock GPR_TIMER_END("combiner.continue_exec_ctx", 0); GPR_UNREACHABLE_CODE(return true); } push_first_on_exec_ctx(exec_ctx, lock); GPR_TIMER_END("combiner.continue_exec_ctx", 0); return true; } static void enqueue_finally(grpc_exec_ctx *exec_ctx, void *closure, grpc_error *error); static void combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, grpc_closure *closure, grpc_error *error, bool covered_by_poller) { GRPC_COMBINER_TRACE(gpr_log( GPR_DEBUG, "C:%p grpc_combiner_execute_finally c=%p; ac=%p; cov=%d", lock, closure, exec_ctx->active_combiner, covered_by_poller)); GPR_TIMER_BEGIN("combiner.execute_finally", 0); if (exec_ctx->active_combiner != lock) { GPR_TIMER_MARK("slowpath", 0); grpc_closure_sched( exec_ctx, grpc_closure_create(enqueue_finally, closure, grpc_combiner_scheduler(lock, false)), error); GPR_TIMER_END("combiner.execute_finally", 0); return; } if (grpc_closure_list_empty(lock->final_list)) { gpr_atm_full_fetch_add(&lock->state, STATE_ELEM_COUNT_LOW_BIT); } if (covered_by_poller) { lock->final_list_covered_by_poller = true; } grpc_closure_list_append(&lock->final_list, closure, error); GPR_TIMER_END("combiner.execute_finally", 0); } static void enqueue_finally(grpc_exec_ctx *exec_ctx, void *closure, grpc_error *error) { combiner_execute_finally(exec_ctx, exec_ctx->active_combiner, closure, GRPC_ERROR_REF(error), false); } static void combiner_finally_exec_uncovered(grpc_exec_ctx *exec_ctx, grpc_closure *cl, grpc_error *error) { combiner_execute_finally(exec_ctx, COMBINER_FROM_CLOSURE_SCHEDULER( cl, uncovered_finally_scheduler), cl, error, false); } static void combiner_finally_exec_covered(grpc_exec_ctx *exec_ctx, grpc_closure *cl, grpc_error *error) { combiner_execute_finally( exec_ctx, COMBINER_FROM_CLOSURE_SCHEDULER(cl, covered_finally_scheduler), cl, error, true); } grpc_closure_scheduler *grpc_combiner_scheduler(grpc_combiner *combiner, bool covered_by_poller) { return covered_by_poller ? &combiner->covered_scheduler : &combiner->uncovered_scheduler; } grpc_closure_scheduler *grpc_combiner_finally_scheduler( grpc_combiner *combiner, bool covered_by_poller) { return covered_by_poller ? &combiner->covered_finally_scheduler : &combiner->uncovered_finally_scheduler; } grpc-1.3.2/src/core/lib/iomgr/combiner.h000066400000000000000000000071331310511640000200140ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_COMBINER_H #define GRPC_CORE_LIB_IOMGR_COMBINER_H #include #include #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/support/mpscq.h" // Provides serialized access to some resource. // Each action queued on a combiner is executed serially in a borrowed thread. // The actual thread executing actions may change over time (but there will only // every be one at a time). // Initialize the lock, with an optional workqueue to shift load to when // necessary grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue); //#define GRPC_COMBINER_REFCOUNT_DEBUG #ifdef GRPC_COMBINER_REFCOUNT_DEBUG #define GRPC_COMBINER_DEBUG_ARGS \ , const char *file, int line, const char *reason #define GRPC_COMBINER_REF(combiner, reason) \ grpc_combiner_ref((combiner), __FILE__, __LINE__, (reason)) #define GRPC_COMBINER_UNREF(exec_ctx, combiner, reason) \ grpc_combiner_unref((exec_ctx), (combiner), __FILE__, __LINE__, (reason)) #else #define GRPC_COMBINER_DEBUG_ARGS #define GRPC_COMBINER_REF(combiner, reason) grpc_combiner_ref((combiner)) #define GRPC_COMBINER_UNREF(exec_ctx, combiner, reason) \ grpc_combiner_unref((exec_ctx), (combiner)) #endif // Ref/unref the lock, for when we're sharing the lock ownership // Prefer to use the macros above grpc_combiner *grpc_combiner_ref(grpc_combiner *lock GRPC_COMBINER_DEBUG_ARGS); void grpc_combiner_unref(grpc_exec_ctx *exec_ctx, grpc_combiner *lock GRPC_COMBINER_DEBUG_ARGS); // Fetch a scheduler to schedule closures against grpc_closure_scheduler *grpc_combiner_scheduler(grpc_combiner *lock, bool covered_by_poller); // Scheduler to execute \a action within the lock just prior to unlocking. grpc_closure_scheduler *grpc_combiner_finally_scheduler(grpc_combiner *lock, bool covered_by_poller); bool grpc_combiner_continue_exec_ctx(grpc_exec_ctx *exec_ctx); extern int grpc_combiner_trace; #endif /* GRPC_CORE_LIB_IOMGR_COMBINER_H */ grpc-1.3.2/src/core/lib/iomgr/endpoint.c000066400000000000000000000060501310511640000200260ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/endpoint.h" void grpc_endpoint_read(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep, grpc_slice_buffer* slices, grpc_closure* cb) { ep->vtable->read(exec_ctx, ep, slices, cb); } void grpc_endpoint_write(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep, grpc_slice_buffer* slices, grpc_closure* cb) { ep->vtable->write(exec_ctx, ep, slices, cb); } void grpc_endpoint_add_to_pollset(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep, grpc_pollset* pollset) { ep->vtable->add_to_pollset(exec_ctx, ep, pollset); } void grpc_endpoint_add_to_pollset_set(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep, grpc_pollset_set* pollset_set) { ep->vtable->add_to_pollset_set(exec_ctx, ep, pollset_set); } void grpc_endpoint_shutdown(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep, grpc_error* why) { ep->vtable->shutdown(exec_ctx, ep, why); } void grpc_endpoint_destroy(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep) { ep->vtable->destroy(exec_ctx, ep); } char* grpc_endpoint_get_peer(grpc_endpoint* ep) { return ep->vtable->get_peer(ep); } int grpc_endpoint_get_fd(grpc_endpoint* ep) { return ep->vtable->get_fd(ep); } grpc_workqueue* grpc_endpoint_get_workqueue(grpc_endpoint* ep) { return ep->vtable->get_workqueue(ep); } grpc_resource_user* grpc_endpoint_get_resource_user(grpc_endpoint* ep) { return ep->vtable->get_resource_user(ep); } grpc-1.3.2/src/core/lib/iomgr/endpoint.h000066400000000000000000000121751310511640000200400ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_ENDPOINT_H #define GRPC_CORE_LIB_IOMGR_ENDPOINT_H #include #include #include #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/pollset_set.h" #include "src/core/lib/iomgr/resource_quota.h" /* An endpoint caps a streaming channel between two communicating processes. Examples may be: a tcp socket, , or some shared memory. */ typedef struct grpc_endpoint grpc_endpoint; typedef struct grpc_endpoint_vtable grpc_endpoint_vtable; struct grpc_endpoint_vtable { void (*read)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_slice_buffer *slices, grpc_closure *cb); void (*write)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_slice_buffer *slices, grpc_closure *cb); grpc_workqueue *(*get_workqueue)(grpc_endpoint *ep); void (*add_to_pollset)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_pollset *pollset); void (*add_to_pollset_set)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_pollset_set *pollset); void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_error *why); void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep); grpc_resource_user *(*get_resource_user)(grpc_endpoint *ep); char *(*get_peer)(grpc_endpoint *ep); int (*get_fd)(grpc_endpoint *ep); }; /* When data is available on the connection, calls the callback with slices. Callback success indicates that the endpoint can accept more reads, failure indicates the endpoint is closed. Valid slices may be placed into \a slices even when the callback is invoked with error != GRPC_ERROR_NONE. */ void grpc_endpoint_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_slice_buffer *slices, grpc_closure *cb); char *grpc_endpoint_get_peer(grpc_endpoint *ep); /* Get the file descriptor used by \a ep. Return -1 if \a ep is not using an fd. */ int grpc_endpoint_get_fd(grpc_endpoint *ep); /* Retrieve a reference to the workqueue associated with this endpoint */ grpc_workqueue *grpc_endpoint_get_workqueue(grpc_endpoint *ep); /* Write slices out to the socket. If the connection is ready for more data after the end of the call, it returns GRPC_ENDPOINT_DONE. Otherwise it returns GRPC_ENDPOINT_PENDING and calls cb when the connection is ready for more data. \a slices may be mutated at will by the endpoint until cb is called. No guarantee is made to the content of slices after a write EXCEPT that it is a valid slice buffer. */ void grpc_endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_slice_buffer *slices, grpc_closure *cb); /* Causes any pending and future read/write callbacks to run immediately with success==0 */ void grpc_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_error *why); void grpc_endpoint_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep); /* Add an endpoint to a pollset, so that when the pollset is polled, events from this endpoint are considered */ void grpc_endpoint_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_pollset *pollset); void grpc_endpoint_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_pollset_set *pollset_set); grpc_resource_user *grpc_endpoint_get_resource_user(grpc_endpoint *endpoint); struct grpc_endpoint { const grpc_endpoint_vtable *vtable; }; #endif /* GRPC_CORE_LIB_IOMGR_ENDPOINT_H */ grpc-1.3.2/src/core/lib/iomgr/endpoint_pair.h000066400000000000000000000037031310511640000210500ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_ENDPOINT_PAIR_H #define GRPC_CORE_LIB_IOMGR_ENDPOINT_PAIR_H #include "src/core/lib/iomgr/endpoint.h" typedef struct { grpc_endpoint *client; grpc_endpoint *server; } grpc_endpoint_pair; grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name, grpc_channel_args *args); #endif /* GRPC_CORE_LIB_IOMGR_ENDPOINT_PAIR_H */ grpc-1.3.2/src/core/lib/iomgr/endpoint_pair_posix.c000066400000000000000000000063001310511640000222610ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_POSIX_SOCKET #include "src/core/lib/iomgr/endpoint_pair.h" #include "src/core/lib/iomgr/socket_utils_posix.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" #include #include #include #include #include #include #include #include #include "src/core/lib/iomgr/tcp_posix.h" #include "src/core/lib/support/string.h" static void create_sockets(int sv[2]) { int flags; grpc_create_socketpair_if_unix(sv); flags = fcntl(sv[0], F_GETFL, 0); GPR_ASSERT(fcntl(sv[0], F_SETFL, flags | O_NONBLOCK) == 0); flags = fcntl(sv[1], F_GETFL, 0); GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0); GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[0]) == GRPC_ERROR_NONE); GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[1]) == GRPC_ERROR_NONE); } grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name, grpc_channel_args *args) { int sv[2]; grpc_endpoint_pair p; char *final_name; create_sockets(sv); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; gpr_asprintf(&final_name, "%s:client", name); p.client = grpc_tcp_create(&exec_ctx, grpc_fd_create(sv[1], final_name), args, "socketpair-server"); gpr_free(final_name); gpr_asprintf(&final_name, "%s:server", name); p.server = grpc_tcp_create(&exec_ctx, grpc_fd_create(sv[0], final_name), args, "socketpair-client"); gpr_free(final_name); grpc_exec_ctx_finish(&exec_ctx); return p; } #endif grpc-1.3.2/src/core/lib/iomgr/endpoint_pair_uv.c000066400000000000000000000040741310511640000215570ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_UV #include #include #include "src/core/lib/iomgr/endpoint_pair.h" grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name, grpc_channel_args *args) { grpc_endpoint_pair endpoint_pair; // TODO(mlumish): implement this properly under libuv GPR_ASSERT(false && "grpc_iomgr_create_endpoint_pair is not suppoted with libuv"); return endpoint_pair; } #endif /* GRPC_UV */ grpc-1.3.2/src/core/lib/iomgr/endpoint_pair_windows.c000066400000000000000000000073451310511640000226230ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_WINSOCK_SOCKET #include "src/core/lib/iomgr/endpoint_pair.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include #include #include #include #include "src/core/lib/iomgr/socket_windows.h" #include "src/core/lib/iomgr/tcp_windows.h" static void create_sockets(SOCKET sv[2]) { SOCKET svr_sock = INVALID_SOCKET; SOCKET lst_sock = INVALID_SOCKET; SOCKET cli_sock = INVALID_SOCKET; SOCKADDR_IN addr; int addr_len = sizeof(addr); lst_sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); GPR_ASSERT(lst_sock != INVALID_SOCKET); memset(&addr, 0, sizeof(addr)); addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); addr.sin_family = AF_INET; GPR_ASSERT(bind(lst_sock, (struct sockaddr *)&addr, sizeof(addr)) != SOCKET_ERROR); GPR_ASSERT(listen(lst_sock, SOMAXCONN) != SOCKET_ERROR); GPR_ASSERT(getsockname(lst_sock, (struct sockaddr *)&addr, &addr_len) != SOCKET_ERROR); cli_sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); GPR_ASSERT(cli_sock != INVALID_SOCKET); GPR_ASSERT(WSAConnect(cli_sock, (struct sockaddr *)&addr, addr_len, NULL, NULL, NULL, NULL) == 0); svr_sock = accept(lst_sock, (struct sockaddr *)&addr, &addr_len); GPR_ASSERT(svr_sock != INVALID_SOCKET); closesocket(lst_sock); grpc_tcp_prepare_socket(cli_sock); grpc_tcp_prepare_socket(svr_sock); sv[1] = cli_sock; sv[0] = svr_sock; } grpc_endpoint_pair grpc_iomgr_create_endpoint_pair( const char *name, grpc_channel_args *channel_args) { SOCKET sv[2]; grpc_endpoint_pair p; create_sockets(sv); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; p.client = grpc_tcp_create(&exec_ctx, grpc_winsocket_create(sv[1], "endpoint:client"), channel_args, "endpoint:server"); p.server = grpc_tcp_create(&exec_ctx, grpc_winsocket_create(sv[0], "endpoint:server"), channel_args, "endpoint:client"); grpc_exec_ctx_finish(&exec_ctx); return p; } #endif grpc-1.3.2/src/core/lib/iomgr/error.c000066400000000000000000000614531310511640000173470ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/error.h" #include #include #include #include #include #include #ifdef GPR_WINDOWS #include #endif #include "src/core/lib/iomgr/error_internal.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" static const char *error_int_name(grpc_error_ints key) { switch (key) { case GRPC_ERROR_INT_ERRNO: return "errno"; case GRPC_ERROR_INT_FILE_LINE: return "file_line"; case GRPC_ERROR_INT_STREAM_ID: return "stream_id"; case GRPC_ERROR_INT_GRPC_STATUS: return "grpc_status"; case GRPC_ERROR_INT_OFFSET: return "offset"; case GRPC_ERROR_INT_INDEX: return "index"; case GRPC_ERROR_INT_SIZE: return "size"; case GRPC_ERROR_INT_HTTP2_ERROR: return "http2_error"; case GRPC_ERROR_INT_TSI_CODE: return "tsi_code"; case GRPC_ERROR_INT_SECURITY_STATUS: return "security_status"; case GRPC_ERROR_INT_FD: return "fd"; case GRPC_ERROR_INT_WSA_ERROR: return "wsa_error"; case GRPC_ERROR_INT_HTTP_STATUS: return "http_status"; case GRPC_ERROR_INT_LIMIT: return "limit"; case GRPC_ERROR_INT_OCCURRED_DURING_WRITE: return "occurred_during_write"; case GRPC_ERROR_INT_MAX: GPR_UNREACHABLE_CODE(return "unknown"); } GPR_UNREACHABLE_CODE(return "unknown"); } static const char *error_str_name(grpc_error_strs key) { switch (key) { case GRPC_ERROR_STR_KEY: return "key"; case GRPC_ERROR_STR_VALUE: return "value"; case GRPC_ERROR_STR_DESCRIPTION: return "description"; case GRPC_ERROR_STR_OS_ERROR: return "os_error"; case GRPC_ERROR_STR_TARGET_ADDRESS: return "target_address"; case GRPC_ERROR_STR_SYSCALL: return "syscall"; case GRPC_ERROR_STR_FILE: return "file"; case GRPC_ERROR_STR_GRPC_MESSAGE: return "grpc_message"; case GRPC_ERROR_STR_RAW_BYTES: return "raw_bytes"; case GRPC_ERROR_STR_TSI_ERROR: return "tsi_error"; case GRPC_ERROR_STR_FILENAME: return "filename"; case GRPC_ERROR_STR_QUEUED_BUFFERS: return "queued_buffers"; case GRPC_ERROR_STR_MAX: GPR_UNREACHABLE_CODE(return "unknown"); } GPR_UNREACHABLE_CODE(return "unknown"); } static const char *error_time_name(grpc_error_times key) { switch (key) { case GRPC_ERROR_TIME_CREATED: return "created"; case GRPC_ERROR_TIME_MAX: GPR_UNREACHABLE_CODE(return "unknown"); } GPR_UNREACHABLE_CODE(return "unknown"); } bool grpc_error_is_special(grpc_error *err) { return err == GRPC_ERROR_NONE || err == GRPC_ERROR_OOM || err == GRPC_ERROR_CANCELLED; } #ifdef GRPC_ERROR_REFCOUNT_DEBUG grpc_error *grpc_error_ref(grpc_error *err, const char *file, int line, const char *func) { if (grpc_error_is_special(err)) return err; gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d %s]", err, gpr_atm_no_barrier_load(&err->atomics.refs.count), gpr_atm_no_barrier_load(&err->atomics.refs.count) + 1, file, line, func); gpr_ref(&err->atomics.refs); return err; } #else grpc_error *grpc_error_ref(grpc_error *err) { if (grpc_error_is_special(err)) return err; gpr_ref(&err->atomics.refs); return err; } #endif static void unref_errs(grpc_error *err) { uint8_t slot = err->first_err; while (slot != UINT8_MAX) { grpc_linked_error *lerr = (grpc_linked_error *)(err->arena + slot); GRPC_ERROR_UNREF(lerr->err); GPR_ASSERT(err->last_err == slot ? lerr->next == UINT8_MAX : lerr->next != UINT8_MAX); slot = lerr->next; } } static void unref_slice(grpc_slice slice) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_slice_unref_internal(&exec_ctx, slice); grpc_exec_ctx_finish(&exec_ctx); } static void unref_strs(grpc_error *err) { for (size_t which = 0; which < GRPC_ERROR_STR_MAX; ++which) { uint8_t slot = err->strs[which]; if (slot != UINT8_MAX) { unref_slice(*(grpc_slice *)(err->arena + slot)); } } } static void error_destroy(grpc_error *err) { GPR_ASSERT(!grpc_error_is_special(err)); unref_errs(err); unref_strs(err); gpr_free((void *)gpr_atm_acq_load(&err->atomics.error_string)); gpr_free(err); } #ifdef GRPC_ERROR_REFCOUNT_DEBUG void grpc_error_unref(grpc_error *err, const char *file, int line, const char *func) { if (grpc_error_is_special(err)) return; gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d %s]", err, gpr_atm_no_barrier_load(&err->atomics.refs.count), gpr_atm_no_barrier_load(&err->atomics.refs.count) - 1, file, line, func); if (gpr_unref(&err->atomics.refs)) { error_destroy(err); } } #else void grpc_error_unref(grpc_error *err) { if (grpc_error_is_special(err)) return; if (gpr_unref(&err->atomics.refs)) { error_destroy(err); } } #endif static uint8_t get_placement(grpc_error **err, size_t size) { GPR_ASSERT(*err); uint8_t slots = (uint8_t)(size / sizeof(intptr_t)); if ((*err)->arena_size + slots > (*err)->arena_capacity) { (*err)->arena_capacity = (uint8_t)GPR_MIN(UINT8_MAX - 1, (3 * (*err)->arena_capacity / 2)); if ((*err)->arena_size + slots > (*err)->arena_capacity) { return UINT8_MAX; } *err = gpr_realloc( *err, sizeof(grpc_error) + (*err)->arena_capacity * sizeof(intptr_t)); } uint8_t placement = (*err)->arena_size; (*err)->arena_size = (uint8_t)((*err)->arena_size + slots); return placement; } static void internal_set_int(grpc_error **err, grpc_error_ints which, intptr_t value) { uint8_t slot = (*err)->ints[which]; if (slot == UINT8_MAX) { slot = get_placement(err, sizeof(value)); if (slot == UINT8_MAX) { gpr_log(GPR_ERROR, "Error %p is full, dropping int {\"%s\":%" PRIiPTR "}", *err, error_int_name(which), value); return; } } (*err)->ints[which] = slot; (*err)->arena[slot] = value; } static void internal_set_str(grpc_error **err, grpc_error_strs which, grpc_slice value) { uint8_t slot = (*err)->strs[which]; if (slot == UINT8_MAX) { slot = get_placement(err, sizeof(value)); if (slot == UINT8_MAX) { const char *str = grpc_slice_to_c_string(value); gpr_log(GPR_ERROR, "Error %p is full, dropping string {\"%s\":\"%s\"}", *err, error_str_name(which), str); gpr_free((void *)str); return; } } else { unref_slice(*(grpc_slice *)((*err)->arena + slot)); } (*err)->strs[which] = slot; memcpy((*err)->arena + slot, &value, sizeof(value)); } static char *fmt_time(gpr_timespec tm); static void internal_set_time(grpc_error **err, grpc_error_times which, gpr_timespec value) { uint8_t slot = (*err)->times[which]; if (slot == UINT8_MAX) { slot = get_placement(err, sizeof(value)); if (slot == UINT8_MAX) { const char *time_str = fmt_time(value); gpr_log(GPR_ERROR, "Error %p is full, dropping \"%s\":\"%s\"}", *err, error_time_name(which), time_str); gpr_free((void *)time_str); return; } } (*err)->times[which] = slot; memcpy((*err)->arena + slot, &value, sizeof(value)); } static void internal_add_error(grpc_error **err, grpc_error *new) { grpc_linked_error new_last = {new, UINT8_MAX}; uint8_t slot = get_placement(err, sizeof(grpc_linked_error)); if (slot == UINT8_MAX) { gpr_log(GPR_ERROR, "Error %p is full, dropping error %p = %s", *err, new, grpc_error_string(new)); GRPC_ERROR_UNREF(new); return; } if ((*err)->first_err == UINT8_MAX) { GPR_ASSERT((*err)->last_err == UINT8_MAX); (*err)->last_err = slot; (*err)->first_err = slot; } else { GPR_ASSERT((*err)->last_err != UINT8_MAX); grpc_linked_error *old_last = (grpc_linked_error *)((*err)->arena + (*err)->last_err); old_last->next = slot; (*err)->last_err = slot; } memcpy((*err)->arena + slot, &new_last, sizeof(grpc_linked_error)); } #define SLOTS_PER_INT (sizeof(intptr_t) / sizeof(intptr_t)) #define SLOTS_PER_STR (sizeof(grpc_slice) / sizeof(intptr_t)) #define SLOTS_PER_TIME (sizeof(gpr_timespec) / sizeof(intptr_t)) #define SLOTS_PER_LINKED_ERROR (sizeof(grpc_linked_error) / sizeof(intptr_t)) // size of storing one int and two slices and a timespec. For line, desc, file, // and time created #define DEFAULT_ERROR_CAPACITY \ (SLOTS_PER_INT + (SLOTS_PER_STR * 2) + SLOTS_PER_TIME) // It is very common to include and extra int and string in an error #define SURPLUS_CAPACITY (2 * SLOTS_PER_INT + SLOTS_PER_TIME) grpc_error *grpc_error_create(grpc_slice file, int line, grpc_slice desc, grpc_error **referencing, size_t num_referencing) { GPR_TIMER_BEGIN("grpc_error_create", 0); uint8_t initial_arena_capacity = (uint8_t)( DEFAULT_ERROR_CAPACITY + (uint8_t)(num_referencing * SLOTS_PER_LINKED_ERROR) + SURPLUS_CAPACITY); grpc_error *err = gpr_malloc(sizeof(*err) + initial_arena_capacity * sizeof(intptr_t)); if (err == NULL) { // TODO(ctiller): make gpr_malloc return NULL return GRPC_ERROR_OOM; } #ifdef GRPC_ERROR_REFCOUNT_DEBUG gpr_log(GPR_DEBUG, "%p create [%s:%d]", err, file, line); #endif err->arena_size = 0; err->arena_capacity = initial_arena_capacity; err->first_err = UINT8_MAX; err->last_err = UINT8_MAX; memset(err->ints, UINT8_MAX, GRPC_ERROR_INT_MAX); memset(err->strs, UINT8_MAX, GRPC_ERROR_STR_MAX); memset(err->times, UINT8_MAX, GRPC_ERROR_TIME_MAX); internal_set_int(&err, GRPC_ERROR_INT_FILE_LINE, line); internal_set_str(&err, GRPC_ERROR_STR_FILE, file); internal_set_str(&err, GRPC_ERROR_STR_DESCRIPTION, desc); for (size_t i = 0; i < num_referencing; ++i) { if (referencing[i] == GRPC_ERROR_NONE) continue; internal_add_error( &err, GRPC_ERROR_REF( referencing[i])); // TODO(ncteisen), change ownership semantics } internal_set_time(&err, GRPC_ERROR_TIME_CREATED, gpr_now(GPR_CLOCK_REALTIME)); gpr_atm_no_barrier_store(&err->atomics.error_string, 0); gpr_ref_init(&err->atomics.refs, 1); GPR_TIMER_END("grpc_error_create", 0); return err; } static void ref_strs(grpc_error *err) { for (size_t i = 0; i < GRPC_ERROR_STR_MAX; ++i) { uint8_t slot = err->strs[i]; if (slot != UINT8_MAX) { grpc_slice_ref_internal(*(grpc_slice *)(err->arena + slot)); } } } static void ref_errs(grpc_error *err) { uint8_t slot = err->first_err; while (slot != UINT8_MAX) { grpc_linked_error *lerr = (grpc_linked_error *)(err->arena + slot); GRPC_ERROR_REF(lerr->err); slot = lerr->next; } } static grpc_error *copy_error_and_unref(grpc_error *in) { GPR_TIMER_BEGIN("copy_error_and_unref", 0); grpc_error *out; if (grpc_error_is_special(in)) { out = GRPC_ERROR_CREATE_FROM_STATIC_STRING("unknown"); if (in == GRPC_ERROR_NONE) { internal_set_str(&out, GRPC_ERROR_STR_DESCRIPTION, grpc_slice_from_static_string("no error")); internal_set_int(&out, GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_OK); } else if (in == GRPC_ERROR_OOM) { internal_set_str(&out, GRPC_ERROR_STR_DESCRIPTION, grpc_slice_from_static_string("oom")); } else if (in == GRPC_ERROR_CANCELLED) { internal_set_str(&out, GRPC_ERROR_STR_DESCRIPTION, grpc_slice_from_static_string("cancelled")); internal_set_int(&out, GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_CANCELLED); } } else if (gpr_ref_is_unique(&in->atomics.refs)) { out = in; } else { uint8_t new_arena_capacity = in->arena_capacity; // the returned err will be added to, so we ensure this is room to avoid // unneeded allocations. if (in->arena_capacity - in->arena_size < (uint8_t)SLOTS_PER_STR) { new_arena_capacity = (uint8_t)(3 * new_arena_capacity / 2); } out = gpr_malloc(sizeof(*in) + new_arena_capacity * sizeof(intptr_t)); #ifdef GRPC_ERROR_REFCOUNT_DEBUG gpr_log(GPR_DEBUG, "%p create copying %p", out, in); #endif // bulk memcpy of the rest of the struct. size_t skip = sizeof(&out->atomics); memcpy((void *)((uintptr_t)out + skip), (void *)((uintptr_t)in + skip), sizeof(*in) + (in->arena_size * sizeof(intptr_t)) - skip); // manually set the atomics and the new capacity gpr_atm_no_barrier_store(&out->atomics.error_string, 0); gpr_ref_init(&out->atomics.refs, 1); out->arena_capacity = new_arena_capacity; ref_strs(out); ref_errs(out); GRPC_ERROR_UNREF(in); } GPR_TIMER_END("copy_error_and_unref", 0); return out; } grpc_error *grpc_error_set_int(grpc_error *src, grpc_error_ints which, intptr_t value) { GPR_TIMER_BEGIN("grpc_error_set_int", 0); grpc_error *new = copy_error_and_unref(src); internal_set_int(&new, which, value); GPR_TIMER_END("grpc_error_set_int", 0); return new; } typedef struct { grpc_error *error; grpc_status_code code; const char *msg; } special_error_status_map; static special_error_status_map error_status_map[] = { {GRPC_ERROR_NONE, GRPC_STATUS_OK, ""}, {GRPC_ERROR_CANCELLED, GRPC_STATUS_CANCELLED, "Cancelled"}, {GRPC_ERROR_OOM, GRPC_STATUS_RESOURCE_EXHAUSTED, "Out of memory"}, }; bool grpc_error_get_int(grpc_error *err, grpc_error_ints which, intptr_t *p) { GPR_TIMER_BEGIN("grpc_error_get_int", 0); if (grpc_error_is_special(err)) { if (which == GRPC_ERROR_INT_GRPC_STATUS) { for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) { if (error_status_map[i].error == err) { if (p != NULL) *p = error_status_map[i].code; GPR_TIMER_END("grpc_error_get_int", 0); return true; } } } GPR_TIMER_END("grpc_error_get_int", 0); return false; } uint8_t slot = err->ints[which]; if (slot != UINT8_MAX) { if (p != NULL) *p = err->arena[slot]; GPR_TIMER_END("grpc_error_get_int", 0); return true; } GPR_TIMER_END("grpc_error_get_int", 0); return false; } grpc_error *grpc_error_set_str(grpc_error *src, grpc_error_strs which, grpc_slice str) { GPR_TIMER_BEGIN("grpc_error_set_str", 0); grpc_error *new = copy_error_and_unref(src); internal_set_str(&new, which, str); GPR_TIMER_END("grpc_error_set_str", 0); return new; } bool grpc_error_get_str(grpc_error *err, grpc_error_strs which, grpc_slice *str) { if (grpc_error_is_special(err)) { if (which == GRPC_ERROR_STR_GRPC_MESSAGE) { for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) { if (error_status_map[i].error == err) { *str = grpc_slice_from_static_string(error_status_map[i].msg); return true; } } } return false; } uint8_t slot = err->strs[which]; if (slot != UINT8_MAX) { *str = *(grpc_slice *)(err->arena + slot); return true; } else { return false; } } grpc_error *grpc_error_add_child(grpc_error *src, grpc_error *child) { GPR_TIMER_BEGIN("grpc_error_add_child", 0); grpc_error *new = copy_error_and_unref(src); internal_add_error(&new, child); GPR_TIMER_END("grpc_error_add_child", 0); return new; } static const char *no_error_string = "\"No Error\""; static const char *oom_error_string = "\"Out of memory\""; static const char *cancelled_error_string = "\"Cancelled\""; typedef struct { char *key; char *value; } kv_pair; typedef struct { kv_pair *kvs; size_t num_kvs; size_t cap_kvs; } kv_pairs; static void append_chr(char c, char **s, size_t *sz, size_t *cap) { if (*sz == *cap) { *cap = GPR_MAX(8, 3 * *cap / 2); *s = gpr_realloc(*s, *cap); } (*s)[(*sz)++] = c; } static void append_str(const char *str, char **s, size_t *sz, size_t *cap) { for (const char *c = str; *c; c++) { append_chr(*c, s, sz, cap); } } static void append_esc_str(const uint8_t *str, size_t len, char **s, size_t *sz, size_t *cap) { static const char *hex = "0123456789abcdef"; append_chr('"', s, sz, cap); for (size_t i = 0; i < len; i++, str++) { if (*str < 32 || *str >= 127) { append_chr('\\', s, sz, cap); switch (*str) { case '\b': append_chr('b', s, sz, cap); break; case '\f': append_chr('f', s, sz, cap); break; case '\n': append_chr('n', s, sz, cap); break; case '\r': append_chr('r', s, sz, cap); break; case '\t': append_chr('t', s, sz, cap); break; default: append_chr('u', s, sz, cap); append_chr('0', s, sz, cap); append_chr('0', s, sz, cap); append_chr(hex[*str >> 4], s, sz, cap); append_chr(hex[*str & 0x0f], s, sz, cap); break; } } else { append_chr((char)*str, s, sz, cap); } } append_chr('"', s, sz, cap); } static void append_kv(kv_pairs *kvs, char *key, char *value) { if (kvs->num_kvs == kvs->cap_kvs) { kvs->cap_kvs = GPR_MAX(3 * kvs->cap_kvs / 2, 4); kvs->kvs = gpr_realloc(kvs->kvs, sizeof(*kvs->kvs) * kvs->cap_kvs); } kvs->kvs[kvs->num_kvs].key = key; kvs->kvs[kvs->num_kvs].value = value; kvs->num_kvs++; } static char *key_int(grpc_error_ints which) { return gpr_strdup(error_int_name(which)); } static char *fmt_int(intptr_t p) { char *s; gpr_asprintf(&s, "%" PRIdPTR, p); return s; } static void collect_ints_kvs(grpc_error *err, kv_pairs *kvs) { for (size_t which = 0; which < GRPC_ERROR_INT_MAX; ++which) { uint8_t slot = err->ints[which]; if (slot != UINT8_MAX) { append_kv(kvs, key_int((grpc_error_ints)which), fmt_int(err->arena[slot])); } } } static char *key_str(grpc_error_strs which) { return gpr_strdup(error_str_name(which)); } static char *fmt_str(grpc_slice slice) { char *s = NULL; size_t sz = 0; size_t cap = 0; append_esc_str((const uint8_t *)GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice), &s, &sz, &cap); append_chr(0, &s, &sz, &cap); return s; } static void collect_strs_kvs(grpc_error *err, kv_pairs *kvs) { for (size_t which = 0; which < GRPC_ERROR_STR_MAX; ++which) { uint8_t slot = err->strs[which]; if (slot != UINT8_MAX) { append_kv(kvs, key_str((grpc_error_strs)which), fmt_str(*(grpc_slice *)(err->arena + slot))); } } } static char *key_time(grpc_error_times which) { return gpr_strdup(error_time_name(which)); } static char *fmt_time(gpr_timespec tm) { char *out; char *pfx = "!!"; switch (tm.clock_type) { case GPR_CLOCK_MONOTONIC: pfx = "@monotonic:"; break; case GPR_CLOCK_REALTIME: pfx = "@"; break; case GPR_CLOCK_PRECISE: pfx = "@precise:"; break; case GPR_TIMESPAN: pfx = ""; break; } gpr_asprintf(&out, "\"%s%" PRId64 ".%09d\"", pfx, tm.tv_sec, tm.tv_nsec); return out; } static void collect_times_kvs(grpc_error *err, kv_pairs *kvs) { for (size_t which = 0; which < GRPC_ERROR_TIME_MAX; ++which) { uint8_t slot = err->times[which]; if (slot != UINT8_MAX) { append_kv(kvs, key_time((grpc_error_times)which), fmt_time(*(gpr_timespec *)(err->arena + slot))); } } } static void add_errs(grpc_error *err, char **s, size_t *sz, size_t *cap) { uint8_t slot = err->first_err; bool first = true; while (slot != UINT8_MAX) { grpc_linked_error *lerr = (grpc_linked_error *)(err->arena + slot); if (!first) append_chr(',', s, sz, cap); first = false; const char *e = grpc_error_string(lerr->err); append_str(e, s, sz, cap); GPR_ASSERT(err->last_err == slot ? lerr->next == UINT8_MAX : lerr->next != UINT8_MAX); slot = lerr->next; } } static char *errs_string(grpc_error *err) { char *s = NULL; size_t sz = 0; size_t cap = 0; append_chr('[', &s, &sz, &cap); add_errs(err, &s, &sz, &cap); append_chr(']', &s, &sz, &cap); append_chr(0, &s, &sz, &cap); return s; } static int cmp_kvs(const void *a, const void *b) { const kv_pair *ka = a; const kv_pair *kb = b; return strcmp(ka->key, kb->key); } static char *finish_kvs(kv_pairs *kvs) { char *s = NULL; size_t sz = 0; size_t cap = 0; append_chr('{', &s, &sz, &cap); for (size_t i = 0; i < kvs->num_kvs; i++) { if (i != 0) append_chr(',', &s, &sz, &cap); append_esc_str((const uint8_t *)kvs->kvs[i].key, strlen(kvs->kvs[i].key), &s, &sz, &cap); gpr_free(kvs->kvs[i].key); append_chr(':', &s, &sz, &cap); append_str(kvs->kvs[i].value, &s, &sz, &cap); gpr_free(kvs->kvs[i].value); } append_chr('}', &s, &sz, &cap); append_chr(0, &s, &sz, &cap); gpr_free(kvs->kvs); return s; } const char *grpc_error_string(grpc_error *err) { GPR_TIMER_BEGIN("grpc_error_string", 0); if (err == GRPC_ERROR_NONE) return no_error_string; if (err == GRPC_ERROR_OOM) return oom_error_string; if (err == GRPC_ERROR_CANCELLED) return cancelled_error_string; void *p = (void *)gpr_atm_acq_load(&err->atomics.error_string); if (p != NULL) { GPR_TIMER_END("grpc_error_string", 0); return p; } kv_pairs kvs; memset(&kvs, 0, sizeof(kvs)); collect_ints_kvs(err, &kvs); collect_strs_kvs(err, &kvs); collect_times_kvs(err, &kvs); if (err->first_err != UINT8_MAX) { append_kv(&kvs, gpr_strdup("referenced_errors"), errs_string(err)); } qsort(kvs.kvs, kvs.num_kvs, sizeof(kv_pair), cmp_kvs); char *out = finish_kvs(&kvs); if (!gpr_atm_rel_cas(&err->atomics.error_string, 0, (gpr_atm)out)) { gpr_free(out); out = (char *)gpr_atm_no_barrier_load(&err->atomics.error_string); } GPR_TIMER_END("grpc_error_string", 0); return out; } grpc_error *grpc_os_error(const char *file, int line, int err, const char *call_name) { return grpc_error_set_str( grpc_error_set_str( grpc_error_set_int( grpc_error_create(grpc_slice_from_static_string(file), line, grpc_slice_from_static_string("OS Error"), NULL, 0), GRPC_ERROR_INT_ERRNO, err), GRPC_ERROR_STR_OS_ERROR, grpc_slice_from_static_string(strerror(err))), GRPC_ERROR_STR_SYSCALL, grpc_slice_from_static_string(call_name)); } #ifdef GPR_WINDOWS grpc_error *grpc_wsa_error(const char *file, int line, int err, const char *call_name) { char *utf8_message = gpr_format_message(err); grpc_error *error = grpc_error_set_str( grpc_error_set_str( grpc_error_set_int( grpc_error_create(grpc_slice_from_static_string(file), line, grpc_slice_from_static_string("OS Error"), NULL, 0), GRPC_ERROR_INT_WSA_ERROR, err), GRPC_ERROR_STR_OS_ERROR, grpc_slice_from_copied_string(utf8_message)), GRPC_ERROR_STR_SYSCALL, grpc_slice_from_static_string(call_name)); gpr_free(utf8_message); return error; } #endif bool grpc_log_if_error(const char *what, grpc_error *error, const char *file, int line) { if (error == GRPC_ERROR_NONE) return true; const char *msg = grpc_error_string(error); gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "%s: %s", what, msg); GRPC_ERROR_UNREF(error); return false; } grpc-1.3.2/src/core/lib/iomgr/error.h000066400000000000000000000217021310511640000173450ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_ERROR_H #define GRPC_CORE_LIB_IOMGR_ERROR_H #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /// Opaque representation of an error. /// See https://github.com/grpc/grpc/blob/master/doc/core/grpc-error.md for a /// full write up of this object. typedef struct grpc_error grpc_error; typedef enum { /// 'errno' from the operating system GRPC_ERROR_INT_ERRNO, /// __LINE__ from the call site creating the error GRPC_ERROR_INT_FILE_LINE, /// stream identifier: for errors that are associated with an individual /// wire stream GRPC_ERROR_INT_STREAM_ID, /// grpc status code representing this error GRPC_ERROR_INT_GRPC_STATUS, /// offset into some binary blob (usually represented by /// GRPC_ERROR_STR_RAW_BYTES) where the error occurred GRPC_ERROR_INT_OFFSET, /// context sensitive index associated with the error GRPC_ERROR_INT_INDEX, /// context sensitive size associated with the error GRPC_ERROR_INT_SIZE, /// http2 error code associated with the error (see the HTTP2 RFC) GRPC_ERROR_INT_HTTP2_ERROR, /// TSI status code associated with the error GRPC_ERROR_INT_TSI_CODE, /// grpc_security_status associated with the error GRPC_ERROR_INT_SECURITY_STATUS, /// WSAGetLastError() reported when this error occurred GRPC_ERROR_INT_WSA_ERROR, /// File descriptor associated with this error GRPC_ERROR_INT_FD, /// HTTP status (i.e. 404) GRPC_ERROR_INT_HTTP_STATUS, /// context sensitive limit associated with the error GRPC_ERROR_INT_LIMIT, /// chttp2: did the error occur while a write was in progress GRPC_ERROR_INT_OCCURRED_DURING_WRITE, /// Must always be last GRPC_ERROR_INT_MAX, } grpc_error_ints; typedef enum { /// top-level textual description of this error GRPC_ERROR_STR_DESCRIPTION, /// source file in which this error occurred GRPC_ERROR_STR_FILE, /// operating system description of this error GRPC_ERROR_STR_OS_ERROR, /// syscall that generated this error GRPC_ERROR_STR_SYSCALL, /// peer that we were trying to communicate when this error occurred GRPC_ERROR_STR_TARGET_ADDRESS, /// grpc status message associated with this error GRPC_ERROR_STR_GRPC_MESSAGE, /// hex dump (or similar) with the data that generated this error GRPC_ERROR_STR_RAW_BYTES, /// tsi error string associated with this error GRPC_ERROR_STR_TSI_ERROR, /// filename that we were trying to read/write when this error occurred GRPC_ERROR_STR_FILENAME, /// which data was queued for writing when the error occurred GRPC_ERROR_STR_QUEUED_BUFFERS, /// key associated with the error GRPC_ERROR_STR_KEY, /// value associated with the error GRPC_ERROR_STR_VALUE, /// Must always be last GRPC_ERROR_STR_MAX, } grpc_error_strs; typedef enum { /// timestamp of error creation GRPC_ERROR_TIME_CREATED, /// Must always be last GRPC_ERROR_TIME_MAX, } grpc_error_times; /// The following "special" errors can be propagated without allocating memory. /// They are always even so that other code (particularly combiner locks, /// polling engines) can safely use the lower bit for themselves. #define GRPC_ERROR_NONE ((grpc_error *)NULL) #define GRPC_ERROR_OOM ((grpc_error *)2) #define GRPC_ERROR_CANCELLED ((grpc_error *)4) const char *grpc_error_string(grpc_error *error); /// Create an error - but use GRPC_ERROR_CREATE instead grpc_error *grpc_error_create(grpc_slice file, int line, grpc_slice desc, grpc_error **referencing, size_t num_referencing); /// Create an error (this is the preferred way of generating an error that is /// not due to a system call - for system calls, use GRPC_OS_ERROR or /// GRPC_WSA_ERROR as appropriate) /// \a referencing is an array of num_referencing elements indicating one or /// more errors that are believed to have contributed to this one /// err = grpc_error_create(x, y, z, r, nr) is equivalent to: /// err = grpc_error_create(x, y, z, NULL, 0); /// for (i=0; i #include // TODO, do we need this? #include typedef struct grpc_linked_error grpc_linked_error; struct grpc_linked_error { grpc_error *err; uint8_t next; }; // c core representation of an error. See error.h for high level description of // this object. struct grpc_error { // All atomics in grpc_error must be stored in this nested struct. The rest of // the object is memcpy-ed in bulk in copy_and_unref. struct atomics { gpr_refcount refs; gpr_atm error_string; } atomics; // These arrays index into dynamic arena at the bottom of the struct. // UINT8_MAX is used as a sentinel value. uint8_t ints[GRPC_ERROR_INT_MAX]; uint8_t strs[GRPC_ERROR_STR_MAX]; uint8_t times[GRPC_ERROR_TIME_MAX]; // The child errors are stored in the arena, but are effectively a linked list // structure, since they are contained withing grpc_linked_error objects. uint8_t first_err; uint8_t last_err; // The arena is dynamically reallocated with a grow factor of 1.5. uint8_t arena_size; uint8_t arena_capacity; intptr_t arena[0]; }; bool grpc_error_is_special(grpc_error *err); #endif /* GRPC_CORE_LIB_IOMGR_ERROR_INTERNAL_H */ grpc-1.3.2/src/core/lib/iomgr/ev_epoll_linux.c000066400000000000000000002071521310511640000212400ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" /* This polling engine is only relevant on linux kernels supporting epoll() */ #ifdef GRPC_LINUX_EPOLL #include "src/core/lib/iomgr/ev_epoll_linux.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/lockfree_event.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/wakeup_fd_posix.h" #include "src/core/lib/iomgr/workqueue.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/support/block_annotate.h" /* TODO: sreek - Move this to init.c and initialize this like other tracers. */ static int grpc_polling_trace = 0; /* Disabled by default */ #define GRPC_POLLING_TRACE(fmt, ...) \ if (grpc_polling_trace) { \ gpr_log(GPR_INFO, (fmt), __VA_ARGS__); \ } /* Uncomment the following to enable extra checks on poll_object operations */ /* #define PO_DEBUG */ static int grpc_wakeup_signal = -1; static bool is_grpc_wakeup_signal_initialized = false; /* TODO: sreek: Right now, this wakes up all pollers. In future we should make * sure to wake up one polling thread (which can wake up other threads if * needed) */ static grpc_wakeup_fd global_wakeup_fd; /* Implements the function defined in grpc_posix.h. This function might be * called before even calling grpc_init() to set either a different signal to * use. If signum == -1, then the use of signals is disabled */ void grpc_use_signal(int signum) { grpc_wakeup_signal = signum; is_grpc_wakeup_signal_initialized = true; if (grpc_wakeup_signal < 0) { gpr_log(GPR_INFO, "Use of signals is disabled. Epoll engine will not be used"); } else { gpr_log(GPR_INFO, "epoll engine will be using signal: %d", grpc_wakeup_signal); } } struct polling_island; typedef enum { POLL_OBJ_FD, POLL_OBJ_POLLSET, POLL_OBJ_POLLSET_SET } poll_obj_type; typedef struct poll_obj { #ifdef PO_DEBUG poll_obj_type obj_type; #endif gpr_mu mu; struct polling_island *pi; } poll_obj; const char *poll_obj_string(poll_obj_type po_type) { switch (po_type) { case POLL_OBJ_FD: return "fd"; case POLL_OBJ_POLLSET: return "pollset"; case POLL_OBJ_POLLSET_SET: return "pollset_set"; } GPR_UNREACHABLE_CODE(return "UNKNOWN"); } /******************************************************************************* * Fd Declarations */ #define FD_FROM_PO(po) ((grpc_fd *)(po)) struct grpc_fd { poll_obj po; int fd; /* refst format: bit 0 : 1=Active / 0=Orphaned bits 1-n : refcount Ref/Unref by two to avoid altering the orphaned bit */ gpr_atm refst; /* The fd is either closed or we relinquished control of it. In either cases, this indicates that the 'fd' on this structure is no longer valid */ bool orphaned; gpr_atm read_closure; gpr_atm write_closure; struct grpc_fd *freelist_next; grpc_closure *on_done_closure; /* The pollset that last noticed that the fd is readable. The actual type * stored in this is (grpc_pollset *) */ gpr_atm read_notifier_pollset; grpc_iomgr_object iomgr_object; }; /* Reference counting for fds */ // #define GRPC_FD_REF_COUNT_DEBUG #ifdef GRPC_FD_REF_COUNT_DEBUG static void fd_ref(grpc_fd *fd, const char *reason, const char *file, int line); static void fd_unref(grpc_fd *fd, const char *reason, const char *file, int line); #define GRPC_FD_REF(fd, reason) fd_ref(fd, reason, __FILE__, __LINE__) #define GRPC_FD_UNREF(fd, reason) fd_unref(fd, reason, __FILE__, __LINE__) #else static void fd_ref(grpc_fd *fd); static void fd_unref(grpc_fd *fd); #define GRPC_FD_REF(fd, reason) fd_ref(fd) #define GRPC_FD_UNREF(fd, reason) fd_unref(fd) #endif static void fd_global_init(void); static void fd_global_shutdown(void); /******************************************************************************* * Polling island Declarations */ #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG #define PI_ADD_REF(p, r) pi_add_ref_dbg((p), (r), __FILE__, __LINE__) #define PI_UNREF(exec_ctx, p, r) \ pi_unref_dbg((exec_ctx), (p), (r), __FILE__, __LINE__) #else /* defined(GRPC_WORKQUEUE_REFCOUNT_DEBUG) */ #define PI_ADD_REF(p, r) pi_add_ref((p)) #define PI_UNREF(exec_ctx, p, r) pi_unref((exec_ctx), (p)) #endif /* !defined(GRPC_PI_REF_COUNT_DEBUG) */ /* This is also used as grpc_workqueue (by directly casing it) */ typedef struct polling_island { grpc_closure_scheduler workqueue_scheduler; gpr_mu mu; /* Ref count. Use PI_ADD_REF() and PI_UNREF() macros to increment/decrement the refcount. Once the ref count becomes zero, this structure is destroyed which means we should ensure that there is never a scenario where a PI_ADD_REF() is racing with a PI_UNREF() that just made the ref_count zero. */ gpr_atm ref_count; /* Pointer to the polling_island this merged into. * merged_to value is only set once in polling_island's lifetime (and that too * only if the island is merged with another island). Because of this, we can * use gpr_atm type here so that we can do atomic access on this and reduce * lock contention on 'mu' mutex. * * Note that if this field is not NULL (i.e not 0), all the remaining fields * (except mu and ref_count) are invalid and must be ignored. */ gpr_atm merged_to; /* Number of threads currently polling on this island */ gpr_atm poller_count; /* Mutex guarding the read end of the workqueue (must be held to pop from * workqueue_items) */ gpr_mu workqueue_read_mu; /* Queue of closures to be executed */ gpr_mpscq workqueue_items; /* Count of items in workqueue_items */ gpr_atm workqueue_item_count; /* Wakeup fd used to wake pollers to check the contents of workqueue_items */ grpc_wakeup_fd workqueue_wakeup_fd; /* The fd of the underlying epoll set */ int epoll_fd; /* The file descriptors in the epoll set */ size_t fd_cnt; size_t fd_capacity; grpc_fd **fds; } polling_island; /******************************************************************************* * Pollset Declarations */ struct grpc_pollset_worker { /* Thread id of this worker */ pthread_t pt_id; /* Used to prevent a worker from getting kicked multiple times */ gpr_atm is_kicked; struct grpc_pollset_worker *next; struct grpc_pollset_worker *prev; }; struct grpc_pollset { poll_obj po; grpc_pollset_worker root_worker; bool kicked_without_pollers; bool shutting_down; /* Is the pollset shutting down ? */ bool finish_shutdown_called; /* Is the 'finish_shutdown_locked()' called ? */ grpc_closure *shutdown_done; /* Called after after shutdown is complete */ }; /******************************************************************************* * Pollset-set Declarations */ struct grpc_pollset_set { poll_obj po; }; /******************************************************************************* * Common helpers */ static bool append_error(grpc_error **composite, grpc_error *error, const char *desc) { if (error == GRPC_ERROR_NONE) return true; if (*composite == GRPC_ERROR_NONE) { *composite = GRPC_ERROR_CREATE_FROM_COPIED_STRING(desc); } *composite = grpc_error_add_child(*composite, error); return false; } /******************************************************************************* * Polling island Definitions */ /* The wakeup fd that is used to wake up all threads in a Polling island. This is useful in the polling island merge operation where we need to wakeup all the threads currently polling the smaller polling island (so that they can start polling the new/merged polling island) NOTE: This fd is initialized to be readable and MUST NOT be consumed i.e the threads that woke up MUST NOT call grpc_wakeup_fd_consume_wakeup() */ static grpc_wakeup_fd polling_island_wakeup_fd; /* The polling island being polled right now. See comments in workqueue_maybe_wakeup for why this is tracked. */ static __thread polling_island *g_current_thread_polling_island; /* Forward declaration */ static void polling_island_delete(grpc_exec_ctx *exec_ctx, polling_island *pi); static void workqueue_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_error *error); #ifdef GRPC_TSAN /* Currently TSAN may incorrectly flag data races between epoll_ctl and epoll_wait for any grpc_fd structs that are added to the epoll set via epoll_ctl and are returned (within a very short window) via epoll_wait(). To work-around this race, we establish a happens-before relation between the code just-before epoll_ctl() and the code after epoll_wait() by using this atomic */ gpr_atm g_epoll_sync; #endif /* defined(GRPC_TSAN) */ static const grpc_closure_scheduler_vtable workqueue_scheduler_vtable = { workqueue_enqueue, workqueue_enqueue, "workqueue"}; static void pi_add_ref(polling_island *pi); static void pi_unref(grpc_exec_ctx *exec_ctx, polling_island *pi); #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG static void pi_add_ref_dbg(polling_island *pi, const char *reason, const char *file, int line) { long old_cnt = gpr_atm_acq_load(&pi->ref_count); pi_add_ref(pi); gpr_log(GPR_DEBUG, "Add ref pi: %p, old: %ld -> new:%ld (%s) - (%s, %d)", (void *)pi, old_cnt, old_cnt + 1, reason, file, line); } static void pi_unref_dbg(grpc_exec_ctx *exec_ctx, polling_island *pi, const char *reason, const char *file, int line) { long old_cnt = gpr_atm_acq_load(&pi->ref_count); pi_unref(exec_ctx, pi); gpr_log(GPR_DEBUG, "Unref pi: %p, old:%ld -> new:%ld (%s) - (%s, %d)", (void *)pi, old_cnt, (old_cnt - 1), reason, file, line); } static grpc_workqueue *workqueue_ref(grpc_workqueue *workqueue, const char *file, int line, const char *reason) { if (workqueue != NULL) { pi_add_ref_dbg((polling_island *)workqueue, reason, file, line); } return workqueue; } static void workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, const char *file, int line, const char *reason) { if (workqueue != NULL) { pi_unref_dbg(exec_ctx, (polling_island *)workqueue, reason, file, line); } } #else static grpc_workqueue *workqueue_ref(grpc_workqueue *workqueue) { if (workqueue != NULL) { pi_add_ref((polling_island *)workqueue); } return workqueue; } static void workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { if (workqueue != NULL) { pi_unref(exec_ctx, (polling_island *)workqueue); } } #endif static void pi_add_ref(polling_island *pi) { gpr_atm_no_barrier_fetch_add(&pi->ref_count, 1); } static void pi_unref(grpc_exec_ctx *exec_ctx, polling_island *pi) { /* If ref count went to zero, delete the polling island. Note that this deletion not be done under a lock. Once the ref count goes to zero, we are guaranteed that no one else holds a reference to the polling island (and that there is no racing pi_add_ref() call either). Also, if we are deleting the polling island and the merged_to field is non-empty, we should remove a ref to the merged_to polling island */ if (1 == gpr_atm_full_fetch_add(&pi->ref_count, -1)) { polling_island *next = (polling_island *)gpr_atm_acq_load(&pi->merged_to); polling_island_delete(exec_ctx, pi); if (next != NULL) { PI_UNREF(exec_ctx, next, "pi_delete"); /* Recursive call */ } } } /* The caller is expected to hold pi->mu lock before calling this function */ static void polling_island_add_fds_locked(polling_island *pi, grpc_fd **fds, size_t fd_count, bool add_fd_refs, grpc_error **error) { int err; size_t i; struct epoll_event ev; char *err_msg; const char *err_desc = "polling_island_add_fds"; #ifdef GRPC_TSAN /* See the definition of g_epoll_sync for more context */ gpr_atm_rel_store(&g_epoll_sync, (gpr_atm)0); #endif /* defined(GRPC_TSAN) */ for (i = 0; i < fd_count; i++) { ev.events = (uint32_t)(EPOLLIN | EPOLLOUT | EPOLLET); ev.data.ptr = fds[i]; err = epoll_ctl(pi->epoll_fd, EPOLL_CTL_ADD, fds[i]->fd, &ev); if (err < 0) { if (errno != EEXIST) { gpr_asprintf( &err_msg, "epoll_ctl (epoll_fd: %d) add fd: %d failed with error: %d (%s)", pi->epoll_fd, fds[i]->fd, errno, strerror(errno)); append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); gpr_free(err_msg); } continue; } if (pi->fd_cnt == pi->fd_capacity) { pi->fd_capacity = GPR_MAX(pi->fd_capacity + 8, pi->fd_cnt * 3 / 2); pi->fds = gpr_realloc(pi->fds, sizeof(grpc_fd *) * pi->fd_capacity); } pi->fds[pi->fd_cnt++] = fds[i]; if (add_fd_refs) { GRPC_FD_REF(fds[i], "polling_island"); } } } /* The caller is expected to hold pi->mu before calling this */ static void polling_island_add_wakeup_fd_locked(polling_island *pi, grpc_wakeup_fd *wakeup_fd, grpc_error **error) { struct epoll_event ev; int err; char *err_msg; const char *err_desc = "polling_island_add_wakeup_fd"; ev.events = (uint32_t)(EPOLLIN | EPOLLET); ev.data.ptr = wakeup_fd; err = epoll_ctl(pi->epoll_fd, EPOLL_CTL_ADD, GRPC_WAKEUP_FD_GET_READ_FD(wakeup_fd), &ev); if (err < 0 && errno != EEXIST) { gpr_asprintf(&err_msg, "epoll_ctl (epoll_fd: %d) add wakeup fd: %d failed with " "error: %d (%s)", pi->epoll_fd, GRPC_WAKEUP_FD_GET_READ_FD(&global_wakeup_fd), errno, strerror(errno)); append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); gpr_free(err_msg); } } /* The caller is expected to hold pi->mu lock before calling this function */ static void polling_island_remove_all_fds_locked(polling_island *pi, bool remove_fd_refs, grpc_error **error) { int err; size_t i; char *err_msg; const char *err_desc = "polling_island_remove_fds"; for (i = 0; i < pi->fd_cnt; i++) { err = epoll_ctl(pi->epoll_fd, EPOLL_CTL_DEL, pi->fds[i]->fd, NULL); if (err < 0 && errno != ENOENT) { gpr_asprintf(&err_msg, "epoll_ctl (epoll_fd: %d) delete fds[%zu]: %d failed with " "error: %d (%s)", pi->epoll_fd, i, pi->fds[i]->fd, errno, strerror(errno)); append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); gpr_free(err_msg); } if (remove_fd_refs) { GRPC_FD_UNREF(pi->fds[i], "polling_island"); } } pi->fd_cnt = 0; } /* The caller is expected to hold pi->mu lock before calling this function */ static void polling_island_remove_fd_locked(polling_island *pi, grpc_fd *fd, bool is_fd_closed, grpc_error **error) { int err; size_t i; char *err_msg; const char *err_desc = "polling_island_remove_fd"; /* If fd is already closed, then it would have been automatically been removed from the epoll set */ if (!is_fd_closed) { err = epoll_ctl(pi->epoll_fd, EPOLL_CTL_DEL, fd->fd, NULL); if (err < 0 && errno != ENOENT) { gpr_asprintf( &err_msg, "epoll_ctl (epoll_fd: %d) del fd: %d failed with error: %d (%s)", pi->epoll_fd, fd->fd, errno, strerror(errno)); append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); gpr_free(err_msg); } } for (i = 0; i < pi->fd_cnt; i++) { if (pi->fds[i] == fd) { pi->fds[i] = pi->fds[--pi->fd_cnt]; GRPC_FD_UNREF(fd, "polling_island"); break; } } } /* Might return NULL in case of an error */ static polling_island *polling_island_create(grpc_exec_ctx *exec_ctx, grpc_fd *initial_fd, grpc_error **error) { polling_island *pi = NULL; const char *err_desc = "polling_island_create"; *error = GRPC_ERROR_NONE; pi = gpr_malloc(sizeof(*pi)); pi->workqueue_scheduler.vtable = &workqueue_scheduler_vtable; gpr_mu_init(&pi->mu); pi->fd_cnt = 0; pi->fd_capacity = 0; pi->fds = NULL; pi->epoll_fd = -1; gpr_mu_init(&pi->workqueue_read_mu); gpr_mpscq_init(&pi->workqueue_items); gpr_atm_rel_store(&pi->workqueue_item_count, 0); gpr_atm_rel_store(&pi->ref_count, 0); gpr_atm_rel_store(&pi->poller_count, 0); gpr_atm_rel_store(&pi->merged_to, (gpr_atm)NULL); if (!append_error(error, grpc_wakeup_fd_init(&pi->workqueue_wakeup_fd), err_desc)) { goto done; } pi->epoll_fd = epoll_create1(EPOLL_CLOEXEC); if (pi->epoll_fd < 0) { append_error(error, GRPC_OS_ERROR(errno, "epoll_create1"), err_desc); goto done; } polling_island_add_wakeup_fd_locked(pi, &global_wakeup_fd, error); polling_island_add_wakeup_fd_locked(pi, &pi->workqueue_wakeup_fd, error); if (initial_fd != NULL) { polling_island_add_fds_locked(pi, &initial_fd, 1, true, error); } done: if (*error != GRPC_ERROR_NONE) { polling_island_delete(exec_ctx, pi); pi = NULL; } return pi; } static void polling_island_delete(grpc_exec_ctx *exec_ctx, polling_island *pi) { GPR_ASSERT(pi->fd_cnt == 0); if (pi->epoll_fd >= 0) { close(pi->epoll_fd); } GPR_ASSERT(gpr_atm_no_barrier_load(&pi->workqueue_item_count) == 0); gpr_mu_destroy(&pi->workqueue_read_mu); gpr_mpscq_destroy(&pi->workqueue_items); gpr_mu_destroy(&pi->mu); grpc_wakeup_fd_destroy(&pi->workqueue_wakeup_fd); gpr_free(pi->fds); gpr_free(pi); } /* Attempts to gets the last polling island in the linked list (liked by the * 'merged_to' field). Since this does not lock the polling island, there are no * guarantees that the island returned is the last island */ static polling_island *polling_island_maybe_get_latest(polling_island *pi) { polling_island *next = (polling_island *)gpr_atm_acq_load(&pi->merged_to); while (next != NULL) { pi = next; next = (polling_island *)gpr_atm_acq_load(&pi->merged_to); } return pi; } /* Gets the lock on the *latest* polling island i.e the last polling island in the linked list (linked by the 'merged_to' field). Call gpr_mu_unlock on the returned polling island's mu. Usage: To lock/unlock polling island "pi", do the following: polling_island *pi_latest = polling_island_lock(pi); ... ... critical section .. ... gpr_mu_unlock(&pi_latest->mu); // NOTE: use pi_latest->mu. NOT pi->mu */ static polling_island *polling_island_lock(polling_island *pi) { polling_island *next = NULL; while (true) { next = (polling_island *)gpr_atm_acq_load(&pi->merged_to); if (next == NULL) { /* Looks like 'pi' is the last node in the linked list but unless we check this by holding the pi->mu lock, we cannot be sure (i.e without the pi->mu lock, we don't prevent island merges). To be absolutely sure, check once more by holding the pi->mu lock */ gpr_mu_lock(&pi->mu); next = (polling_island *)gpr_atm_acq_load(&pi->merged_to); if (next == NULL) { /* pi is infact the last node and we have the pi->mu lock. we're done */ break; } /* pi->merged_to is not NULL i.e pi isn't the last node anymore. pi->mu * isn't the lock we are interested in. Continue traversing the list */ gpr_mu_unlock(&pi->mu); } pi = next; } return pi; } /* Gets the lock on the *latest* polling islands in the linked lists pointed by *p and *q (and also updates *p and *q to point to the latest polling islands) This function is needed because calling the following block of code to obtain locks on polling islands (*p and *q) is prone to deadlocks. { polling_island_lock(*p, true); polling_island_lock(*q, true); } Usage/example: polling_island *p1; polling_island *p2; .. polling_island_lock_pair(&p1, &p2); .. .. Critical section with both p1 and p2 locked .. // Release locks: Always call polling_island_unlock_pair() to release locks polling_island_unlock_pair(p1, p2); */ static void polling_island_lock_pair(polling_island **p, polling_island **q) { polling_island *pi_1 = *p; polling_island *pi_2 = *q; polling_island *next_1 = NULL; polling_island *next_2 = NULL; /* The algorithm is simple: - Go to the last polling islands in the linked lists *pi_1 and *pi_2 (and keep updating pi_1 and pi_2) - Then obtain locks on the islands by following a lock order rule of locking polling_island with lower address first Special case: Before obtaining the locks, check if pi_1 and pi_2 are pointing to the same island. If that is the case, we can just call polling_island_lock() - After obtaining both the locks, double check that the polling islands are still the last polling islands in their respective linked lists (this is because there might have been polling island merges before we got the lock) - If the polling islands are the last islands, we are done. If not, release the locks and continue the process from the first step */ while (true) { next_1 = (polling_island *)gpr_atm_acq_load(&pi_1->merged_to); while (next_1 != NULL) { pi_1 = next_1; next_1 = (polling_island *)gpr_atm_acq_load(&pi_1->merged_to); } next_2 = (polling_island *)gpr_atm_acq_load(&pi_2->merged_to); while (next_2 != NULL) { pi_2 = next_2; next_2 = (polling_island *)gpr_atm_acq_load(&pi_2->merged_to); } if (pi_1 == pi_2) { pi_1 = pi_2 = polling_island_lock(pi_1); break; } if (pi_1 < pi_2) { gpr_mu_lock(&pi_1->mu); gpr_mu_lock(&pi_2->mu); } else { gpr_mu_lock(&pi_2->mu); gpr_mu_lock(&pi_1->mu); } next_1 = (polling_island *)gpr_atm_acq_load(&pi_1->merged_to); next_2 = (polling_island *)gpr_atm_acq_load(&pi_2->merged_to); if (next_1 == NULL && next_2 == NULL) { break; } gpr_mu_unlock(&pi_1->mu); gpr_mu_unlock(&pi_2->mu); } *p = pi_1; *q = pi_2; } static void polling_island_unlock_pair(polling_island *p, polling_island *q) { if (p == q) { gpr_mu_unlock(&p->mu); } else { gpr_mu_unlock(&p->mu); gpr_mu_unlock(&q->mu); } } static void workqueue_maybe_wakeup(polling_island *pi) { /* If this thread is the current poller, then it may be that it's about to decrement the current poller count, so we need to look past this thread */ bool is_current_poller = (g_current_thread_polling_island == pi); gpr_atm min_current_pollers_for_wakeup = is_current_poller ? 1 : 0; gpr_atm current_pollers = gpr_atm_no_barrier_load(&pi->poller_count); /* Only issue a wakeup if it's likely that some poller could come in and take it right now. Note that since we do an anticipatory mpscq_pop every poll loop, it's ok if we miss the wakeup here, as we'll get the work item when the next poller enters anyway. */ if (current_pollers > min_current_pollers_for_wakeup) { GRPC_LOG_IF_ERROR("workqueue_wakeup_fd", grpc_wakeup_fd_wakeup(&pi->workqueue_wakeup_fd)); } } static void workqueue_move_items_to_parent(polling_island *q) { polling_island *p = (polling_island *)gpr_atm_no_barrier_load(&q->merged_to); if (p == NULL) { return; } gpr_mu_lock(&q->workqueue_read_mu); int num_added = 0; while (gpr_atm_no_barrier_load(&q->workqueue_item_count) > 0) { gpr_mpscq_node *n = gpr_mpscq_pop(&q->workqueue_items); if (n != NULL) { gpr_atm_no_barrier_fetch_add(&q->workqueue_item_count, -1); gpr_atm_no_barrier_fetch_add(&p->workqueue_item_count, 1); gpr_mpscq_push(&p->workqueue_items, n); num_added++; } } gpr_mu_unlock(&q->workqueue_read_mu); if (num_added > 0) { workqueue_maybe_wakeup(p); } workqueue_move_items_to_parent(p); } static polling_island *polling_island_merge(polling_island *p, polling_island *q, grpc_error **error) { /* Get locks on both the polling islands */ polling_island_lock_pair(&p, &q); if (p != q) { /* Make sure that p points to the polling island with fewer fds than q */ if (p->fd_cnt > q->fd_cnt) { GPR_SWAP(polling_island *, p, q); } /* Merge p with q i.e move all the fds from p (The one with fewer fds) to q Note that the refcounts on the fds being moved will not change here. This is why the last param in the following two functions is 'false') */ polling_island_add_fds_locked(q, p->fds, p->fd_cnt, false, error); polling_island_remove_all_fds_locked(p, false, error); /* Wakeup all the pollers (if any) on p so that they pickup this change */ polling_island_add_wakeup_fd_locked(p, &polling_island_wakeup_fd, error); /* Add the 'merged_to' link from p --> q */ gpr_atm_rel_store(&p->merged_to, (gpr_atm)q); PI_ADD_REF(q, "pi_merge"); /* To account for the new incoming ref from p */ workqueue_move_items_to_parent(p); } /* else if p == q, nothing needs to be done */ polling_island_unlock_pair(p, q); /* Return the merged polling island (Note that no merge would have happened if p == q which is ok) */ return q; } static void workqueue_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_error *error) { GPR_TIMER_BEGIN("workqueue.enqueue", 0); grpc_workqueue *workqueue = (grpc_workqueue *)closure->scheduler; /* take a ref to the workqueue: otherwise it can happen that whatever events * this kicks off ends up destroying the workqueue before this function * completes */ GRPC_WORKQUEUE_REF(workqueue, "enqueue"); polling_island *pi = (polling_island *)workqueue; gpr_atm last = gpr_atm_no_barrier_fetch_add(&pi->workqueue_item_count, 1); closure->error_data.error = error; gpr_mpscq_push(&pi->workqueue_items, &closure->next_data.atm_next); if (last == 0) { workqueue_maybe_wakeup(pi); } workqueue_move_items_to_parent(pi); GRPC_WORKQUEUE_UNREF(exec_ctx, workqueue, "enqueue"); GPR_TIMER_END("workqueue.enqueue", 0); } static grpc_closure_scheduler *workqueue_scheduler(grpc_workqueue *workqueue) { polling_island *pi = (polling_island *)workqueue; return workqueue == NULL ? grpc_schedule_on_exec_ctx : &pi->workqueue_scheduler; } static grpc_error *polling_island_global_init() { grpc_error *error = GRPC_ERROR_NONE; error = grpc_wakeup_fd_init(&polling_island_wakeup_fd); if (error == GRPC_ERROR_NONE) { error = grpc_wakeup_fd_wakeup(&polling_island_wakeup_fd); } return error; } static void polling_island_global_shutdown() { grpc_wakeup_fd_destroy(&polling_island_wakeup_fd); } /******************************************************************************* * Fd Definitions */ /* We need to keep a freelist not because of any concerns of malloc performance * but instead so that implementations with multiple threads in (for example) * epoll_wait deal with the race between pollset removal and incoming poll * notifications. * * The problem is that the poller ultimately holds a reference to this * object, so it is very difficult to know when is safe to free it, at least * without some expensive synchronization. * * If we keep the object freelisted, in the worst case losing this race just * becomes a spurious read notification on a reused fd. */ /* The alarm system needs to be able to wakeup 'some poller' sometimes * (specifically when a new alarm needs to be triggered earlier than the next * alarm 'epoch'). This wakeup_fd gives us something to alert on when such a * case occurs. */ static grpc_fd *fd_freelist = NULL; static gpr_mu fd_freelist_mu; #ifdef GRPC_FD_REF_COUNT_DEBUG #define REF_BY(fd, n, reason) ref_by(fd, n, reason, __FILE__, __LINE__) #define UNREF_BY(fd, n, reason) unref_by(fd, n, reason, __FILE__, __LINE__) static void ref_by(grpc_fd *fd, int n, const char *reason, const char *file, int line) { gpr_log(GPR_DEBUG, "FD %d %p ref %d %ld -> %ld [%s; %s:%d]", fd->fd, (void *)fd, n, gpr_atm_no_barrier_load(&fd->refst), gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line); #else #define REF_BY(fd, n, reason) ref_by(fd, n) #define UNREF_BY(fd, n, reason) unref_by(fd, n) static void ref_by(grpc_fd *fd, int n) { #endif GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0); } #ifdef GRPC_FD_REF_COUNT_DEBUG static void unref_by(grpc_fd *fd, int n, const char *reason, const char *file, int line) { gpr_atm old; gpr_log(GPR_DEBUG, "FD %d %p unref %d %ld -> %ld [%s; %s:%d]", fd->fd, (void *)fd, n, gpr_atm_no_barrier_load(&fd->refst), gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line); #else static void unref_by(grpc_fd *fd, int n) { gpr_atm old; #endif old = gpr_atm_full_fetch_add(&fd->refst, -n); if (old == n) { /* Add the fd to the freelist */ gpr_mu_lock(&fd_freelist_mu); fd->freelist_next = fd_freelist; fd_freelist = fd; grpc_iomgr_unregister_object(&fd->iomgr_object); grpc_lfev_destroy(&fd->read_closure); grpc_lfev_destroy(&fd->write_closure); gpr_mu_unlock(&fd_freelist_mu); } else { GPR_ASSERT(old > n); } } /* Increment refcount by two to avoid changing the orphan bit */ #ifdef GRPC_FD_REF_COUNT_DEBUG static void fd_ref(grpc_fd *fd, const char *reason, const char *file, int line) { ref_by(fd, 2, reason, file, line); } static void fd_unref(grpc_fd *fd, const char *reason, const char *file, int line) { unref_by(fd, 2, reason, file, line); } #else static void fd_ref(grpc_fd *fd) { ref_by(fd, 2); } static void fd_unref(grpc_fd *fd) { unref_by(fd, 2); } #endif static void fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); } static void fd_global_shutdown(void) { gpr_mu_lock(&fd_freelist_mu); gpr_mu_unlock(&fd_freelist_mu); while (fd_freelist != NULL) { grpc_fd *fd = fd_freelist; fd_freelist = fd_freelist->freelist_next; gpr_mu_destroy(&fd->po.mu); gpr_free(fd); } gpr_mu_destroy(&fd_freelist_mu); } static grpc_fd *fd_create(int fd, const char *name) { grpc_fd *new_fd = NULL; gpr_mu_lock(&fd_freelist_mu); if (fd_freelist != NULL) { new_fd = fd_freelist; fd_freelist = fd_freelist->freelist_next; } gpr_mu_unlock(&fd_freelist_mu); if (new_fd == NULL) { new_fd = gpr_malloc(sizeof(grpc_fd)); gpr_mu_init(&new_fd->po.mu); } /* Note: It is not really needed to get the new_fd->po.mu lock here. If this * is a newly created fd (or an fd we got from the freelist), no one else * would be holding a lock to it anyway. */ gpr_mu_lock(&new_fd->po.mu); new_fd->po.pi = NULL; #ifdef PO_DEBUG new_fd->po.obj_type = POLL_OBJ_FD; #endif gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1); new_fd->fd = fd; new_fd->orphaned = false; grpc_lfev_init(&new_fd->read_closure); grpc_lfev_init(&new_fd->write_closure); gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL); new_fd->freelist_next = NULL; new_fd->on_done_closure = NULL; gpr_mu_unlock(&new_fd->po.mu); char *fd_name; gpr_asprintf(&fd_name, "%s fd=%d", name, fd); grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name); #ifdef GRPC_FD_REF_COUNT_DEBUG gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, (void *)new_fd, fd_name); #endif gpr_free(fd_name); return new_fd; } static int fd_wrapped_fd(grpc_fd *fd) { int ret_fd = -1; gpr_mu_lock(&fd->po.mu); if (!fd->orphaned) { ret_fd = fd->fd; } gpr_mu_unlock(&fd->po.mu); return ret_fd; } static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done, int *release_fd, const char *reason) { bool is_fd_closed = false; grpc_error *error = GRPC_ERROR_NONE; polling_island *unref_pi = NULL; gpr_mu_lock(&fd->po.mu); fd->on_done_closure = on_done; /* If release_fd is not NULL, we should be relinquishing control of the file descriptor fd->fd (but we still own the grpc_fd structure). */ if (release_fd != NULL) { *release_fd = fd->fd; } else { close(fd->fd); is_fd_closed = true; } fd->orphaned = true; /* Remove the active status but keep referenced. We want this grpc_fd struct to be alive (and not added to freelist) until the end of this function */ REF_BY(fd, 1, reason); /* Remove the fd from the polling island: - Get a lock on the latest polling island (i.e the last island in the linked list pointed by fd->po.pi). This is the island that would actually contain the fd - Remove the fd from the latest polling island - Unlock the latest polling island - Set fd->po.pi to NULL (but remove the ref on the polling island before doing this.) */ if (fd->po.pi != NULL) { polling_island *pi_latest = polling_island_lock(fd->po.pi); polling_island_remove_fd_locked(pi_latest, fd, is_fd_closed, &error); gpr_mu_unlock(&pi_latest->mu); unref_pi = fd->po.pi; fd->po.pi = NULL; } grpc_closure_sched(exec_ctx, fd->on_done_closure, GRPC_ERROR_REF(error)); gpr_mu_unlock(&fd->po.mu); UNREF_BY(fd, 2, reason); /* Drop the reference */ if (unref_pi != NULL) { /* Unref stale polling island here, outside the fd lock above. The polling island owns a workqueue which owns an fd, and unreffing inside the lock can cause an eventual lock loop that makes TSAN very unhappy. */ PI_UNREF(exec_ctx, unref_pi, "fd_orphan"); } GRPC_LOG_IF_ERROR("fd_orphan", GRPC_ERROR_REF(error)); GRPC_ERROR_UNREF(error); } static grpc_pollset *fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { gpr_atm notifier = gpr_atm_acq_load(&fd->read_notifier_pollset); return (grpc_pollset *)notifier; } static bool fd_is_shutdown(grpc_fd *fd) { return grpc_lfev_is_shutdown(&fd->read_closure); } /* Might be called multiple times */ static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why) { if (grpc_lfev_set_shutdown(exec_ctx, &fd->read_closure, GRPC_ERROR_REF(why))) { shutdown(fd->fd, SHUT_RDWR); grpc_lfev_set_shutdown(exec_ctx, &fd->write_closure, GRPC_ERROR_REF(why)); } GRPC_ERROR_UNREF(why); } static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *closure) { grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure); } static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *closure) { grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure); } static grpc_workqueue *fd_get_workqueue(grpc_fd *fd) { gpr_mu_lock(&fd->po.mu); grpc_workqueue *workqueue = GRPC_WORKQUEUE_REF((grpc_workqueue *)fd->po.pi, "fd_get_workqueue"); gpr_mu_unlock(&fd->po.mu); return workqueue; } /******************************************************************************* * Pollset Definitions */ GPR_TLS_DECL(g_current_thread_pollset); GPR_TLS_DECL(g_current_thread_worker); static __thread bool g_initialized_sigmask; static __thread sigset_t g_orig_sigmask; static void sig_handler(int sig_num) { #ifdef GRPC_EPOLL_DEBUG gpr_log(GPR_INFO, "Received signal %d", sig_num); #endif } static void poller_kick_init() { signal(grpc_wakeup_signal, sig_handler); } /* Global state management */ static grpc_error *pollset_global_init(void) { gpr_tls_init(&g_current_thread_pollset); gpr_tls_init(&g_current_thread_worker); poller_kick_init(); return grpc_wakeup_fd_init(&global_wakeup_fd); } static void pollset_global_shutdown(void) { grpc_wakeup_fd_destroy(&global_wakeup_fd); gpr_tls_destroy(&g_current_thread_pollset); gpr_tls_destroy(&g_current_thread_worker); } static grpc_error *pollset_worker_kick(grpc_pollset_worker *worker) { grpc_error *err = GRPC_ERROR_NONE; /* Kick the worker only if it was not already kicked */ if (gpr_atm_no_barrier_cas(&worker->is_kicked, (gpr_atm)0, (gpr_atm)1)) { GRPC_POLLING_TRACE( "pollset_worker_kick: Kicking worker: %p (thread id: %ld)", (void *)worker, (long int)worker->pt_id); int err_num = pthread_kill(worker->pt_id, grpc_wakeup_signal); if (err_num != 0) { err = GRPC_OS_ERROR(err_num, "pthread_kill"); } } return err; } /* Return 1 if the pollset has active threads in pollset_work (pollset must * be locked) */ static int pollset_has_workers(grpc_pollset *p) { return p->root_worker.next != &p->root_worker; } static void remove_worker(grpc_pollset *p, grpc_pollset_worker *worker) { worker->prev->next = worker->next; worker->next->prev = worker->prev; } static grpc_pollset_worker *pop_front_worker(grpc_pollset *p) { if (pollset_has_workers(p)) { grpc_pollset_worker *w = p->root_worker.next; remove_worker(p, w); return w; } else { return NULL; } } static void push_back_worker(grpc_pollset *p, grpc_pollset_worker *worker) { worker->next = &p->root_worker; worker->prev = worker->next->prev; worker->prev->next = worker->next->prev = worker; } static void push_front_worker(grpc_pollset *p, grpc_pollset_worker *worker) { worker->prev = &p->root_worker; worker->next = worker->prev->next; worker->prev->next = worker->next->prev = worker; } /* p->mu must be held before calling this function */ static grpc_error *pollset_kick(grpc_pollset *p, grpc_pollset_worker *specific_worker) { GPR_TIMER_BEGIN("pollset_kick", 0); grpc_error *error = GRPC_ERROR_NONE; const char *err_desc = "Kick Failure"; grpc_pollset_worker *worker = specific_worker; if (worker != NULL) { if (worker == GRPC_POLLSET_KICK_BROADCAST) { if (pollset_has_workers(p)) { GPR_TIMER_BEGIN("pollset_kick.broadcast", 0); for (worker = p->root_worker.next; worker != &p->root_worker; worker = worker->next) { if (gpr_tls_get(&g_current_thread_worker) != (intptr_t)worker) { append_error(&error, pollset_worker_kick(worker), err_desc); } } GPR_TIMER_END("pollset_kick.broadcast", 0); } else { p->kicked_without_pollers = true; } } else { GPR_TIMER_MARK("kicked_specifically", 0); if (gpr_tls_get(&g_current_thread_worker) != (intptr_t)worker) { append_error(&error, pollset_worker_kick(worker), err_desc); } } } else if (gpr_tls_get(&g_current_thread_pollset) != (intptr_t)p) { /* Since worker == NULL, it means that we can kick "any" worker on this pollset 'p'. If 'p' happens to be the same pollset this thread is currently polling (i.e in pollset_work() function), then there is no need to kick any other worker since the current thread can just absorb the kick. This is the reason why we enter this case only when g_current_thread_pollset is != p */ GPR_TIMER_MARK("kick_anonymous", 0); worker = pop_front_worker(p); if (worker != NULL) { GPR_TIMER_MARK("finally_kick", 0); push_back_worker(p, worker); append_error(&error, pollset_worker_kick(worker), err_desc); } else { GPR_TIMER_MARK("kicked_no_pollers", 0); p->kicked_without_pollers = true; } } GPR_TIMER_END("pollset_kick", 0); GRPC_LOG_IF_ERROR("pollset_kick", GRPC_ERROR_REF(error)); return error; } static grpc_error *kick_poller(void) { return grpc_wakeup_fd_wakeup(&global_wakeup_fd); } static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) { gpr_mu_init(&pollset->po.mu); *mu = &pollset->po.mu; pollset->po.pi = NULL; #ifdef PO_DEBUG pollset->po.obj_type = POLL_OBJ_POLLSET; #endif pollset->root_worker.next = pollset->root_worker.prev = &pollset->root_worker; pollset->kicked_without_pollers = false; pollset->shutting_down = false; pollset->finish_shutdown_called = false; pollset->shutdown_done = NULL; } /* Convert a timespec to milliseconds: - Very small or negative poll times are clamped to zero to do a non-blocking poll (which becomes spin polling) - Other small values are rounded up to one millisecond - Longer than a millisecond polls are rounded up to the next nearest millisecond to avoid spinning - Infinite timeouts are converted to -1 */ static int poll_deadline_to_millis_timeout(gpr_timespec deadline, gpr_timespec now) { gpr_timespec timeout; static const int64_t max_spin_polling_us = 10; if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) == 0) { return -1; } if (gpr_time_cmp(deadline, gpr_time_add(now, gpr_time_from_micros( max_spin_polling_us, GPR_TIMESPAN))) <= 0) { return 0; } timeout = gpr_time_sub(deadline, now); int millis = gpr_time_to_millis(gpr_time_add( timeout, gpr_time_from_nanos(GPR_NS_PER_MS - 1, GPR_TIMESPAN))); return millis >= 1 ? millis : 1; } static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_pollset *notifier) { grpc_lfev_set_ready(exec_ctx, &fd->read_closure); /* Note, it is possible that fd_become_readable might be called twice with different 'notifier's when an fd becomes readable and it is in two epoll sets (This can happen briefly during polling island merges). In such cases it does not really matter which notifer is set as the read_notifier_pollset (They would both point to the same polling island anyway) */ /* Use release store to match with acquire load in fd_get_read_notifier */ gpr_atm_rel_store(&fd->read_notifier_pollset, (gpr_atm)notifier); } static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { grpc_lfev_set_ready(exec_ctx, &fd->write_closure); } static void pollset_release_polling_island(grpc_exec_ctx *exec_ctx, grpc_pollset *ps, char *reason) { if (ps->po.pi != NULL) { PI_UNREF(exec_ctx, ps->po.pi, reason); } ps->po.pi = NULL; } static void finish_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) { /* The pollset cannot have any workers if we are at this stage */ GPR_ASSERT(!pollset_has_workers(pollset)); pollset->finish_shutdown_called = true; /* Release the ref and set pollset->po.pi to NULL */ pollset_release_polling_island(exec_ctx, pollset, "ps_shutdown"); grpc_closure_sched(exec_ctx, pollset->shutdown_done, GRPC_ERROR_NONE); } /* pollset->po.mu lock must be held by the caller before calling this */ static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_closure *closure) { GPR_TIMER_BEGIN("pollset_shutdown", 0); GPR_ASSERT(!pollset->shutting_down); pollset->shutting_down = true; pollset->shutdown_done = closure; pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST); /* If the pollset has any workers, we cannot call finish_shutdown_locked() because it would release the underlying polling island. In such a case, we let the last worker call finish_shutdown_locked() from pollset_work() */ if (!pollset_has_workers(pollset)) { GPR_ASSERT(!pollset->finish_shutdown_called); GPR_TIMER_MARK("pollset_shutdown.finish_shutdown_locked", 0); finish_shutdown_locked(exec_ctx, pollset); } GPR_TIMER_END("pollset_shutdown", 0); } /* pollset_shutdown is guaranteed to be called before pollset_destroy. So other * than destroying the mutexes, there is nothing special that needs to be done * here */ static void pollset_destroy(grpc_pollset *pollset) { GPR_ASSERT(!pollset_has_workers(pollset)); gpr_mu_destroy(&pollset->po.mu); } static bool maybe_do_workqueue_work(grpc_exec_ctx *exec_ctx, polling_island *pi) { if (gpr_mu_trylock(&pi->workqueue_read_mu)) { gpr_mpscq_node *n = gpr_mpscq_pop(&pi->workqueue_items); gpr_mu_unlock(&pi->workqueue_read_mu); if (n != NULL) { if (gpr_atm_full_fetch_add(&pi->workqueue_item_count, -1) > 1) { workqueue_maybe_wakeup(pi); } grpc_closure *c = (grpc_closure *)n; grpc_error *error = c->error_data.error; #ifndef NDEBUG c->scheduled = false; #endif c->cb(exec_ctx, c->cb_arg, error); GRPC_ERROR_UNREF(error); return true; } else if (gpr_atm_no_barrier_load(&pi->workqueue_item_count) > 0) { /* n == NULL might mean there's work but it's not available to be popped * yet - try to ensure another workqueue wakes up to check shortly if so */ workqueue_maybe_wakeup(pi); } } return false; } #define GRPC_EPOLL_MAX_EVENTS 100 /* Note: sig_mask contains the signal mask to use *during* epoll_wait() */ static void pollset_work_and_unlock(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker *worker, int timeout_ms, sigset_t *sig_mask, grpc_error **error) { struct epoll_event ep_ev[GRPC_EPOLL_MAX_EVENTS]; int epoll_fd = -1; int ep_rv; polling_island *pi = NULL; char *err_msg; const char *err_desc = "pollset_work_and_unlock"; GPR_TIMER_BEGIN("pollset_work_and_unlock", 0); /* We need to get the epoll_fd to wait on. The epoll_fd is in inside the latest polling island pointed by pollset->po.pi Since epoll_fd is immutable, we can read it without obtaining the polling island lock. There is however a possibility that the polling island (from which we got the epoll_fd) got merged with another island while we are in this function. This is still okay because in such a case, we will wakeup right-away from epoll_wait() and pick up the latest polling_island the next this function (i.e pollset_work_and_unlock()) is called */ if (pollset->po.pi == NULL) { pollset->po.pi = polling_island_create(exec_ctx, NULL, error); if (pollset->po.pi == NULL) { GPR_TIMER_END("pollset_work_and_unlock", 0); return; /* Fatal error. We cannot continue */ } PI_ADD_REF(pollset->po.pi, "ps"); GRPC_POLLING_TRACE("pollset_work: pollset: %p created new pi: %p", (void *)pollset, (void *)pollset->po.pi); } pi = polling_island_maybe_get_latest(pollset->po.pi); epoll_fd = pi->epoll_fd; /* Update the pollset->po.pi since the island being pointed by pollset->po.pi maybe older than the one pointed by pi) */ if (pollset->po.pi != pi) { /* Always do PI_ADD_REF before PI_UNREF because PI_UNREF may cause the polling island to be deleted */ PI_ADD_REF(pi, "ps"); PI_UNREF(exec_ctx, pollset->po.pi, "ps"); pollset->po.pi = pi; } /* Add an extra ref so that the island does not get destroyed (which means the epoll_fd won't be closed) while we are are doing an epoll_wait() on the epoll_fd */ PI_ADD_REF(pi, "ps_work"); gpr_mu_unlock(&pollset->po.mu); /* If we get some workqueue work to do, it might end up completing an item on the completion queue, so there's no need to poll... so we skip that and redo the complete loop to verify */ if (!maybe_do_workqueue_work(exec_ctx, pi)) { gpr_atm_no_barrier_fetch_add(&pi->poller_count, 1); g_current_thread_polling_island = pi; GRPC_SCHEDULING_START_BLOCKING_REGION; ep_rv = epoll_pwait(epoll_fd, ep_ev, GRPC_EPOLL_MAX_EVENTS, timeout_ms, sig_mask); GRPC_SCHEDULING_END_BLOCKING_REGION; if (ep_rv < 0) { if (errno != EINTR) { gpr_asprintf(&err_msg, "epoll_wait() epoll fd: %d failed with error: %d (%s)", epoll_fd, errno, strerror(errno)); append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); } else { /* We were interrupted. Save an interation by doing a zero timeout epoll_wait to see if there are any other events of interest */ GRPC_POLLING_TRACE( "pollset_work: pollset: %p, worker: %p received kick", (void *)pollset, (void *)worker); ep_rv = epoll_wait(epoll_fd, ep_ev, GRPC_EPOLL_MAX_EVENTS, 0); } } #ifdef GRPC_TSAN /* See the definition of g_poll_sync for more details */ gpr_atm_acq_load(&g_epoll_sync); #endif /* defined(GRPC_TSAN) */ for (int i = 0; i < ep_rv; ++i) { void *data_ptr = ep_ev[i].data.ptr; if (data_ptr == &global_wakeup_fd) { grpc_timer_consume_kick(); append_error(error, grpc_wakeup_fd_consume_wakeup(&global_wakeup_fd), err_desc); } else if (data_ptr == &pi->workqueue_wakeup_fd) { append_error(error, grpc_wakeup_fd_consume_wakeup(&pi->workqueue_wakeup_fd), err_desc); maybe_do_workqueue_work(exec_ctx, pi); } else if (data_ptr == &polling_island_wakeup_fd) { GRPC_POLLING_TRACE( "pollset_work: pollset: %p, worker: %p polling island (epoll_fd: " "%d) got merged", (void *)pollset, (void *)worker, epoll_fd); /* This means that our polling island is merged with a different island. We do not have to do anything here since the subsequent call to the function pollset_work_and_unlock() will pick up the correct epoll_fd */ } else { grpc_fd *fd = data_ptr; int cancel = ep_ev[i].events & (EPOLLERR | EPOLLHUP); int read_ev = ep_ev[i].events & (EPOLLIN | EPOLLPRI); int write_ev = ep_ev[i].events & EPOLLOUT; if (read_ev || cancel) { fd_become_readable(exec_ctx, fd, pollset); } if (write_ev || cancel) { fd_become_writable(exec_ctx, fd); } } } g_current_thread_polling_island = NULL; gpr_atm_no_barrier_fetch_add(&pi->poller_count, -1); } GPR_ASSERT(pi != NULL); /* Before leaving, release the extra ref we added to the polling island. It is important to use "pi" here (i.e our old copy of pollset->po.pi that we got before releasing the polling island lock). This is because pollset->po.pi pointer might get udpated in other parts of the code when there is an island merge while we are doing epoll_wait() above */ PI_UNREF(exec_ctx, pi, "ps_work"); GPR_TIMER_END("pollset_work_and_unlock", 0); } /* pollset->po.mu lock must be held by the caller before calling this. The function pollset_work() may temporarily release the lock (pollset->po.mu) during the course of its execution but it will always re-acquire the lock and ensure that it is held by the time the function returns */ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker **worker_hdl, gpr_timespec now, gpr_timespec deadline) { GPR_TIMER_BEGIN("pollset_work", 0); grpc_error *error = GRPC_ERROR_NONE; int timeout_ms = poll_deadline_to_millis_timeout(deadline, now); sigset_t new_mask; grpc_pollset_worker worker; worker.next = worker.prev = NULL; worker.pt_id = pthread_self(); gpr_atm_no_barrier_store(&worker.is_kicked, (gpr_atm)0); if (worker_hdl) *worker_hdl = &worker; gpr_tls_set(&g_current_thread_pollset, (intptr_t)pollset); gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker); if (pollset->kicked_without_pollers) { /* If the pollset was kicked without pollers, pretend that the current worker got the kick and skip polling. A kick indicates that there is some work that needs attention like an event on the completion queue or an alarm */ GPR_TIMER_MARK("pollset_work.kicked_without_pollers", 0); pollset->kicked_without_pollers = 0; } else if (!pollset->shutting_down) { /* We use the posix-signal with number 'grpc_wakeup_signal' for waking up (i.e 'kicking') a worker in the pollset. A 'kick' is a way to inform the worker that there is some pending work that needs immediate attention (like an event on the completion queue, or a polling island merge that results in a new epoll-fd to wait on) and that the worker should not spend time waiting in epoll_pwait(). A worker can be kicked anytime from the point it is added to the pollset via push_front_worker() (or push_back_worker()) to the point it is removed via remove_worker(). If the worker is kicked before/during it calls epoll_pwait(), it should immediately exit from epoll_wait(). If the worker is kicked after it returns from epoll_wait(), then nothing really needs to be done. To accomplish this, we mask 'grpc_wakeup_signal' on this thread at all times *except* when it is in epoll_pwait(). This way, the worker never misses acting on a kick */ if (!g_initialized_sigmask) { sigemptyset(&new_mask); sigaddset(&new_mask, grpc_wakeup_signal); pthread_sigmask(SIG_BLOCK, &new_mask, &g_orig_sigmask); sigdelset(&g_orig_sigmask, grpc_wakeup_signal); g_initialized_sigmask = true; /* new_mask: The new thread mask which blocks 'grpc_wakeup_signal'. This is the mask used at all times *except during epoll_wait()*" g_orig_sigmask: The thread mask which allows 'grpc_wakeup_signal' and this is the mask to use *during epoll_wait()* The new_mask is set on the worker before it is added to the pollset (i.e before it can be kicked) */ } push_front_worker(pollset, &worker); /* Add worker to pollset */ pollset_work_and_unlock(exec_ctx, pollset, &worker, timeout_ms, &g_orig_sigmask, &error); grpc_exec_ctx_flush(exec_ctx); gpr_mu_lock(&pollset->po.mu); /* Note: There is no need to reset worker.is_kicked to 0 since we are no longer going to use this worker */ remove_worker(pollset, &worker); } /* If we are the last worker on the pollset (i.e pollset_has_workers() is false at this point) and the pollset is shutting down, we may have to finish the shutdown process by calling finish_shutdown_locked(). See pollset_shutdown() for more details. Note: Continuing to access pollset here is safe; it is the caller's responsibility to not destroy a pollset when it has outstanding calls to pollset_work() */ if (pollset->shutting_down && !pollset_has_workers(pollset) && !pollset->finish_shutdown_called) { GPR_TIMER_MARK("pollset_work.finish_shutdown_locked", 0); finish_shutdown_locked(exec_ctx, pollset); gpr_mu_unlock(&pollset->po.mu); grpc_exec_ctx_flush(exec_ctx); gpr_mu_lock(&pollset->po.mu); } if (worker_hdl) *worker_hdl = NULL; gpr_tls_set(&g_current_thread_pollset, (intptr_t)0); gpr_tls_set(&g_current_thread_worker, (intptr_t)0); GPR_TIMER_END("pollset_work", 0); GRPC_LOG_IF_ERROR("pollset_work", GRPC_ERROR_REF(error)); return error; } static void add_poll_object(grpc_exec_ctx *exec_ctx, poll_obj *bag, poll_obj_type bag_type, poll_obj *item, poll_obj_type item_type) { GPR_TIMER_BEGIN("add_poll_object", 0); #ifdef PO_DEBUG GPR_ASSERT(item->obj_type == item_type); GPR_ASSERT(bag->obj_type == bag_type); #endif grpc_error *error = GRPC_ERROR_NONE; polling_island *pi_new = NULL; gpr_mu_lock(&bag->mu); gpr_mu_lock(&item->mu); retry: /* * 1) If item->pi and bag->pi are both non-NULL and equal, do nothing * 2) If item->pi and bag->pi are both NULL, create a new polling island (with * a refcount of 2) and point item->pi and bag->pi to the new island * 3) If exactly one of item->pi or bag->pi is NULL, update it to point to * the other's non-NULL pi * 4) Finally if item->pi and bag-pi are non-NULL and not-equal, merge the * polling islands and update item->pi and bag->pi to point to the new * island */ /* Early out if we are trying to add an 'fd' to a 'bag' but the fd is already * orphaned */ if (item_type == POLL_OBJ_FD && (FD_FROM_PO(item))->orphaned) { gpr_mu_unlock(&item->mu); gpr_mu_unlock(&bag->mu); return; } if (item->pi == bag->pi) { pi_new = item->pi; if (pi_new == NULL) { /* GPR_ASSERT(item->pi == bag->pi == NULL) */ /* If we are adding an fd to a bag (i.e pollset or pollset_set), then * we need to do some extra work to make TSAN happy */ if (item_type == POLL_OBJ_FD) { /* Unlock before creating a new polling island: the polling island will create a workqueue which creates a file descriptor, and holding an fd lock here can eventually cause a loop to appear to TSAN (making it unhappy). We don't think it's a real loop (there's an epoch point where that loop possibility disappears), but the advantages of keeping TSAN happy outweigh any performance advantage we might have by keeping the lock held. */ gpr_mu_unlock(&item->mu); pi_new = polling_island_create(exec_ctx, FD_FROM_PO(item), &error); gpr_mu_lock(&item->mu); /* Need to reverify any assumptions made between the initial lock and getting to this branch: if they've changed, we need to throw away our work and figure things out again. */ if (item->pi != NULL) { GRPC_POLLING_TRACE( "add_poll_object: Raced creating new polling island. pi_new: %p " "(fd: %d, %s: %p)", (void *)pi_new, FD_FROM_PO(item)->fd, poll_obj_string(bag_type), (void *)bag); /* No need to lock 'pi_new' here since this is a new polling island and no one has a reference to it yet */ polling_island_remove_all_fds_locked(pi_new, true, &error); /* Ref and unref so that the polling island gets deleted during unref */ PI_ADD_REF(pi_new, "dance_of_destruction"); PI_UNREF(exec_ctx, pi_new, "dance_of_destruction"); goto retry; } } else { pi_new = polling_island_create(exec_ctx, NULL, &error); } GRPC_POLLING_TRACE( "add_poll_object: Created new polling island. pi_new: %p (%s: %p, " "%s: %p)", (void *)pi_new, poll_obj_string(item_type), (void *)item, poll_obj_string(bag_type), (void *)bag); } else { GRPC_POLLING_TRACE( "add_poll_object: Same polling island. pi: %p (%s, %s)", (void *)pi_new, poll_obj_string(item_type), poll_obj_string(bag_type)); } } else if (item->pi == NULL) { /* GPR_ASSERT(bag->pi != NULL) */ /* Make pi_new point to latest pi*/ pi_new = polling_island_lock(bag->pi); if (item_type == POLL_OBJ_FD) { grpc_fd *fd = FD_FROM_PO(item); polling_island_add_fds_locked(pi_new, &fd, 1, true, &error); } gpr_mu_unlock(&pi_new->mu); GRPC_POLLING_TRACE( "add_poll_obj: item->pi was NULL. pi_new: %p (item(%s): %p, " "bag(%s): %p)", (void *)pi_new, poll_obj_string(item_type), (void *)item, poll_obj_string(bag_type), (void *)bag); } else if (bag->pi == NULL) { /* GPR_ASSERT(item->pi != NULL) */ /* Make pi_new to point to latest pi */ pi_new = polling_island_lock(item->pi); gpr_mu_unlock(&pi_new->mu); GRPC_POLLING_TRACE( "add_poll_obj: bag->pi was NULL. pi_new: %p (item(%s): %p, " "bag(%s): %p)", (void *)pi_new, poll_obj_string(item_type), (void *)item, poll_obj_string(bag_type), (void *)bag); } else { pi_new = polling_island_merge(item->pi, bag->pi, &error); GRPC_POLLING_TRACE( "add_poll_obj: polling islands merged. pi_new: %p (item(%s): %p, " "bag(%s): %p)", (void *)pi_new, poll_obj_string(item_type), (void *)item, poll_obj_string(bag_type), (void *)bag); } /* At this point, pi_new is the polling island that both item->pi and bag->pi MUST be pointing to */ if (item->pi != pi_new) { PI_ADD_REF(pi_new, poll_obj_string(item_type)); if (item->pi != NULL) { PI_UNREF(exec_ctx, item->pi, poll_obj_string(item_type)); } item->pi = pi_new; } if (bag->pi != pi_new) { PI_ADD_REF(pi_new, poll_obj_string(bag_type)); if (bag->pi != NULL) { PI_UNREF(exec_ctx, bag->pi, poll_obj_string(bag_type)); } bag->pi = pi_new; } gpr_mu_unlock(&item->mu); gpr_mu_unlock(&bag->mu); GRPC_LOG_IF_ERROR("add_poll_object", error); GPR_TIMER_END("add_poll_object", 0); } static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_fd *fd) { add_poll_object(exec_ctx, &pollset->po, POLL_OBJ_POLLSET, &fd->po, POLL_OBJ_FD); } /******************************************************************************* * Pollset-set Definitions */ static grpc_pollset_set *pollset_set_create(void) { grpc_pollset_set *pss = gpr_malloc(sizeof(*pss)); gpr_mu_init(&pss->po.mu); pss->po.pi = NULL; #ifdef PO_DEBUG pss->po.obj_type = POLL_OBJ_POLLSET_SET; #endif return pss; } static void pollset_set_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss) { gpr_mu_destroy(&pss->po.mu); if (pss->po.pi != NULL) { PI_UNREF(exec_ctx, pss->po.pi, "pss_destroy"); } gpr_free(pss); } static void pollset_set_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss, grpc_fd *fd) { add_poll_object(exec_ctx, &pss->po, POLL_OBJ_POLLSET_SET, &fd->po, POLL_OBJ_FD); } static void pollset_set_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss, grpc_fd *fd) { /* Nothing to do */ } static void pollset_set_add_pollset(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss, grpc_pollset *ps) { add_poll_object(exec_ctx, &pss->po, POLL_OBJ_POLLSET_SET, &ps->po, POLL_OBJ_POLLSET); } static void pollset_set_del_pollset(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss, grpc_pollset *ps) { /* Nothing to do */ } static void pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx, grpc_pollset_set *bag, grpc_pollset_set *item) { add_poll_object(exec_ctx, &bag->po, POLL_OBJ_POLLSET_SET, &item->po, POLL_OBJ_POLLSET_SET); } static void pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx, grpc_pollset_set *bag, grpc_pollset_set *item) { /* Nothing to do */ } /* Test helper functions * */ void *grpc_fd_get_polling_island(grpc_fd *fd) { polling_island *pi; gpr_mu_lock(&fd->po.mu); pi = fd->po.pi; gpr_mu_unlock(&fd->po.mu); return pi; } void *grpc_pollset_get_polling_island(grpc_pollset *ps) { polling_island *pi; gpr_mu_lock(&ps->po.mu); pi = ps->po.pi; gpr_mu_unlock(&ps->po.mu); return pi; } bool grpc_are_polling_islands_equal(void *p, void *q) { polling_island *p1 = p; polling_island *p2 = q; /* Note: polling_island_lock_pair() may change p1 and p2 to point to the latest polling islands in their respective linked lists */ polling_island_lock_pair(&p1, &p2); polling_island_unlock_pair(p1, p2); return p1 == p2; } /******************************************************************************* * Event engine binding */ static void shutdown_engine(void) { fd_global_shutdown(); pollset_global_shutdown(); polling_island_global_shutdown(); } static const grpc_event_engine_vtable vtable = { .pollset_size = sizeof(grpc_pollset), .fd_create = fd_create, .fd_wrapped_fd = fd_wrapped_fd, .fd_orphan = fd_orphan, .fd_shutdown = fd_shutdown, .fd_is_shutdown = fd_is_shutdown, .fd_notify_on_read = fd_notify_on_read, .fd_notify_on_write = fd_notify_on_write, .fd_get_read_notifier_pollset = fd_get_read_notifier_pollset, .fd_get_workqueue = fd_get_workqueue, .pollset_init = pollset_init, .pollset_shutdown = pollset_shutdown, .pollset_destroy = pollset_destroy, .pollset_work = pollset_work, .pollset_kick = pollset_kick, .pollset_add_fd = pollset_add_fd, .pollset_set_create = pollset_set_create, .pollset_set_destroy = pollset_set_destroy, .pollset_set_add_pollset = pollset_set_add_pollset, .pollset_set_del_pollset = pollset_set_del_pollset, .pollset_set_add_pollset_set = pollset_set_add_pollset_set, .pollset_set_del_pollset_set = pollset_set_del_pollset_set, .pollset_set_add_fd = pollset_set_add_fd, .pollset_set_del_fd = pollset_set_del_fd, .kick_poller = kick_poller, .workqueue_ref = workqueue_ref, .workqueue_unref = workqueue_unref, .workqueue_scheduler = workqueue_scheduler, .shutdown_engine = shutdown_engine, }; /* It is possible that GLIBC has epoll but the underlying kernel doesn't. * Create a dummy epoll_fd to make sure epoll support is available */ static bool is_epoll_available() { int fd = epoll_create1(EPOLL_CLOEXEC); if (fd < 0) { gpr_log( GPR_ERROR, "epoll_create1 failed with error: %d. Not using epoll polling engine", fd); return false; } close(fd); return true; } const grpc_event_engine_vtable *grpc_init_epoll_linux(void) { /* If use of signals is disabled, we cannot use epoll engine*/ if (is_grpc_wakeup_signal_initialized && grpc_wakeup_signal < 0) { return NULL; } if (!grpc_has_wakeup_fd()) { return NULL; } if (!is_epoll_available()) { return NULL; } if (!is_grpc_wakeup_signal_initialized) { grpc_use_signal(SIGRTMIN + 6); } fd_global_init(); if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) { return NULL; } if (!GRPC_LOG_IF_ERROR("polling_island_global_init", polling_island_global_init())) { return NULL; } return &vtable; } #else /* defined(GRPC_LINUX_EPOLL) */ #if defined(GRPC_POSIX_SOCKET) #include "src/core/lib/iomgr/ev_posix.h" /* If GRPC_LINUX_EPOLL is not defined, it means epoll is not available. Return * NULL */ const grpc_event_engine_vtable *grpc_init_epoll_linux(void) { return NULL; } #endif /* defined(GRPC_POSIX_SOCKET) */ void grpc_use_signal(int signum) {} #endif /* !defined(GRPC_LINUX_EPOLL) */ grpc-1.3.2/src/core/lib/iomgr/ev_epoll_linux.h000066400000000000000000000040331310511640000212360ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_EV_EPOLL_LINUX_H #define GRPC_CORE_LIB_IOMGR_EV_EPOLL_LINUX_H #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/port.h" const grpc_event_engine_vtable *grpc_init_epoll_linux(void); #ifdef GRPC_LINUX_EPOLL void *grpc_fd_get_polling_island(grpc_fd *fd); void *grpc_pollset_get_polling_island(grpc_pollset *ps); bool grpc_are_polling_islands_equal(void *p, void *q); #endif /* defined(GRPC_LINUX_EPOLL) */ #endif /* GRPC_CORE_LIB_IOMGR_EV_EPOLL_LINUX_H */ grpc-1.3.2/src/core/lib/iomgr/ev_poll_posix.c000066400000000000000000001477471310511640000211130ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_POSIX_SOCKET #include "src/core/lib/iomgr/ev_poll_posix.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/wakeup_fd_cv.h" #include "src/core/lib/iomgr/wakeup_fd_posix.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/support/block_annotate.h" /******************************************************************************* * FD declarations */ typedef struct grpc_fd_watcher { struct grpc_fd_watcher *next; struct grpc_fd_watcher *prev; grpc_pollset *pollset; grpc_pollset_worker *worker; grpc_fd *fd; } grpc_fd_watcher; struct grpc_fd { int fd; /* refst format: bit0: 1=active/0=orphaned bit1-n: refcount meaning that mostly we ref by two to avoid altering the orphaned bit, and just unref by 1 when we're ready to flag the object as orphaned */ gpr_atm refst; gpr_mu mu; int shutdown; int closed; int released; grpc_error *shutdown_error; /* The watcher list. The following watcher related fields are protected by watcher_mu. An fd_watcher is an ephemeral object created when an fd wants to begin polling, and destroyed after the poll. It denotes the fd's interest in whether to read poll or write poll or both or neither on this fd. If a watcher is asked to poll for reads or writes, the read_watcher or write_watcher fields are set respectively. A watcher may be asked to poll for both, in which case both fields will be set. read_watcher and write_watcher may be NULL if no watcher has been asked to poll for reads or writes. If an fd_watcher is not asked to poll for reads or writes, it's added to a linked list of inactive watchers, rooted at inactive_watcher_root. If at a later time there becomes need of a poller to poll, one of the inactive pollers may be kicked out of their poll loops to take that responsibility. */ grpc_fd_watcher inactive_watcher_root; grpc_fd_watcher *read_watcher; grpc_fd_watcher *write_watcher; grpc_closure *read_closure; grpc_closure *write_closure; grpc_closure *on_done_closure; grpc_iomgr_object iomgr_object; /* The pollset that last noticed and notified that the fd is readable */ grpc_pollset *read_notifier_pollset; }; static grpc_wakeup_fd global_wakeup_fd; /* Begin polling on an fd. Registers that the given pollset is interested in this fd - so that if read or writability interest changes, the pollset can be kicked to pick up that new interest. Return value is: (fd_needs_read? read_mask : 0) | (fd_needs_write? write_mask : 0) i.e. a combination of read_mask and write_mask determined by the fd's current interest in said events. Polling strategies that do not need to alter their behavior depending on the fd's current interest (such as epoll) do not need to call this function. MUST NOT be called with a pollset lock taken */ static uint32_t fd_begin_poll(grpc_fd *fd, grpc_pollset *pollset, grpc_pollset_worker *worker, uint32_t read_mask, uint32_t write_mask, grpc_fd_watcher *rec); /* Complete polling previously started with fd_begin_poll MUST NOT be called with a pollset lock taken if got_read or got_write are 1, also does the become_{readable,writable} as appropriate. */ static void fd_end_poll(grpc_exec_ctx *exec_ctx, grpc_fd_watcher *rec, int got_read, int got_write, grpc_pollset *read_notifier_pollset); /* Return 1 if this fd is orphaned, 0 otherwise */ static bool fd_is_orphaned(grpc_fd *fd); /* Reference counting for fds */ //#define GRPC_FD_REF_COUNT_DEBUG #ifdef GRPC_FD_REF_COUNT_DEBUG static void fd_ref(grpc_fd *fd, const char *reason, const char *file, int line); static void fd_unref(grpc_fd *fd, const char *reason, const char *file, int line); #define GRPC_FD_REF(fd, reason) fd_ref(fd, reason, __FILE__, __LINE__) #define GRPC_FD_UNREF(fd, reason) fd_unref(fd, reason, __FILE__, __LINE__) #else static void fd_ref(grpc_fd *fd); static void fd_unref(grpc_fd *fd); #define GRPC_FD_REF(fd, reason) fd_ref(fd) #define GRPC_FD_UNREF(fd, reason) fd_unref(fd) #endif #define CLOSURE_NOT_READY ((grpc_closure *)0) #define CLOSURE_READY ((grpc_closure *)1) /******************************************************************************* * pollset declarations */ typedef struct grpc_cached_wakeup_fd { grpc_wakeup_fd fd; struct grpc_cached_wakeup_fd *next; } grpc_cached_wakeup_fd; struct grpc_pollset_worker { grpc_cached_wakeup_fd *wakeup_fd; int reevaluate_polling_on_wakeup; int kicked_specifically; struct grpc_pollset_worker *next; struct grpc_pollset_worker *prev; }; struct grpc_pollset { gpr_mu mu; grpc_pollset_worker root_worker; int shutting_down; int called_shutdown; int kicked_without_pollers; grpc_closure *shutdown_done; grpc_closure_list idle_jobs; int pollset_set_count; /* all polled fds */ size_t fd_count; size_t fd_capacity; grpc_fd **fds; /* Local cache of eventfds for workers */ grpc_cached_wakeup_fd *local_wakeup_cache; }; /* Add an fd to a pollset */ static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, struct grpc_fd *fd); static void pollset_set_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set, grpc_fd *fd); /* Convert a timespec to milliseconds: - very small or negative poll times are clamped to zero to do a non-blocking poll (which becomes spin polling) - other small values are rounded up to one millisecond - longer than a millisecond polls are rounded up to the next nearest millisecond to avoid spinning - infinite timeouts are converted to -1 */ static int poll_deadline_to_millis_timeout(gpr_timespec deadline, gpr_timespec now); /* Allow kick to wakeup the currently polling worker */ #define GRPC_POLLSET_CAN_KICK_SELF 1 /* Force the wakee to repoll when awoken */ #define GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP 2 /* As per pollset_kick, with an extended set of flags (defined above) -- mostly for fd_posix's use. */ static grpc_error *pollset_kick_ext(grpc_pollset *p, grpc_pollset_worker *specific_worker, uint32_t flags) GRPC_MUST_USE_RESULT; /* Return 1 if the pollset has active threads in pollset_work (pollset must * be locked) */ static bool pollset_has_workers(grpc_pollset *pollset); /******************************************************************************* * pollset_set definitions */ struct grpc_pollset_set { gpr_mu mu; size_t pollset_count; size_t pollset_capacity; grpc_pollset **pollsets; size_t pollset_set_count; size_t pollset_set_capacity; struct grpc_pollset_set **pollset_sets; size_t fd_count; size_t fd_capacity; grpc_fd **fds; }; /******************************************************************************* * condition variable polling definitions */ #define CV_POLL_PERIOD_MS 1000 #define CV_DEFAULT_TABLE_SIZE 16 typedef enum poll_status_t { INPROGRESS, COMPLETED, CANCELLED } poll_status_t; typedef struct poll_args { gpr_refcount refcount; gpr_cv *cv; struct pollfd *fds; nfds_t nfds; int timeout; int retval; int err; gpr_atm status; } poll_args; cv_fd_table g_cvfds; /******************************************************************************* * fd_posix.c */ #ifdef GRPC_FD_REF_COUNT_DEBUG #define REF_BY(fd, n, reason) ref_by(fd, n, reason, __FILE__, __LINE__) #define UNREF_BY(fd, n, reason) unref_by(fd, n, reason, __FILE__, __LINE__) static void ref_by(grpc_fd *fd, int n, const char *reason, const char *file, int line) { gpr_log(GPR_DEBUG, "FD %d %p ref %d %d -> %d [%s; %s:%d]", fd->fd, fd, n, (int)gpr_atm_no_barrier_load(&fd->refst), (int)gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line); #else #define REF_BY(fd, n, reason) ref_by(fd, n) #define UNREF_BY(fd, n, reason) unref_by(fd, n) static void ref_by(grpc_fd *fd, int n) { #endif GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0); } #ifdef GRPC_FD_REF_COUNT_DEBUG static void unref_by(grpc_fd *fd, int n, const char *reason, const char *file, int line) { gpr_atm old; gpr_log(GPR_DEBUG, "FD %d %p unref %d %d -> %d [%s; %s:%d]", fd->fd, fd, n, (int)gpr_atm_no_barrier_load(&fd->refst), (int)gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line); #else static void unref_by(grpc_fd *fd, int n) { gpr_atm old; #endif old = gpr_atm_full_fetch_add(&fd->refst, -n); if (old == n) { gpr_mu_destroy(&fd->mu); grpc_iomgr_unregister_object(&fd->iomgr_object); if (fd->shutdown) GRPC_ERROR_UNREF(fd->shutdown_error); gpr_free(fd); } else { GPR_ASSERT(old > n); } } static grpc_fd *fd_create(int fd, const char *name) { grpc_fd *r = gpr_malloc(sizeof(*r)); gpr_mu_init(&r->mu); gpr_atm_rel_store(&r->refst, 1); r->shutdown = 0; r->read_closure = CLOSURE_NOT_READY; r->write_closure = CLOSURE_NOT_READY; r->fd = fd; r->inactive_watcher_root.next = r->inactive_watcher_root.prev = &r->inactive_watcher_root; r->read_watcher = r->write_watcher = NULL; r->on_done_closure = NULL; r->closed = 0; r->released = 0; r->read_notifier_pollset = NULL; char *name2; gpr_asprintf(&name2, "%s fd=%d", name, fd); grpc_iomgr_register_object(&r->iomgr_object, name2); gpr_free(name2); #ifdef GRPC_FD_REF_COUNT_DEBUG gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, r, name); #endif return r; } static bool fd_is_orphaned(grpc_fd *fd) { return (gpr_atm_acq_load(&fd->refst) & 1) == 0; } /* Return the read-notifier pollset */ static grpc_pollset *fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { grpc_pollset *notifier = NULL; gpr_mu_lock(&fd->mu); notifier = fd->read_notifier_pollset; gpr_mu_unlock(&fd->mu); return notifier; } static grpc_error *pollset_kick_locked(grpc_fd_watcher *watcher) { gpr_mu_lock(&watcher->pollset->mu); GPR_ASSERT(watcher->worker); grpc_error *err = pollset_kick_ext(watcher->pollset, watcher->worker, GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP); gpr_mu_unlock(&watcher->pollset->mu); return err; } static void maybe_wake_one_watcher_locked(grpc_fd *fd) { if (fd->inactive_watcher_root.next != &fd->inactive_watcher_root) { pollset_kick_locked(fd->inactive_watcher_root.next); } else if (fd->read_watcher) { pollset_kick_locked(fd->read_watcher); } else if (fd->write_watcher) { pollset_kick_locked(fd->write_watcher); } } static void wake_all_watchers_locked(grpc_fd *fd) { grpc_fd_watcher *watcher; for (watcher = fd->inactive_watcher_root.next; watcher != &fd->inactive_watcher_root; watcher = watcher->next) { pollset_kick_locked(watcher); } if (fd->read_watcher) { pollset_kick_locked(fd->read_watcher); } if (fd->write_watcher && fd->write_watcher != fd->read_watcher) { pollset_kick_locked(fd->write_watcher); } } static int has_watchers(grpc_fd *fd) { return fd->read_watcher != NULL || fd->write_watcher != NULL || fd->inactive_watcher_root.next != &fd->inactive_watcher_root; } static void close_fd_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { fd->closed = 1; if (!fd->released) { close(fd->fd); } grpc_closure_sched(exec_ctx, fd->on_done_closure, GRPC_ERROR_NONE); } static int fd_wrapped_fd(grpc_fd *fd) { if (fd->released || fd->closed) { return -1; } else { return fd->fd; } } static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done, int *release_fd, const char *reason) { fd->on_done_closure = on_done; fd->released = release_fd != NULL; if (fd->released) { *release_fd = fd->fd; } gpr_mu_lock(&fd->mu); REF_BY(fd, 1, reason); /* remove active status, but keep referenced */ if (!has_watchers(fd)) { close_fd_locked(exec_ctx, fd); } else { wake_all_watchers_locked(fd); } gpr_mu_unlock(&fd->mu); UNREF_BY(fd, 2, reason); /* drop the reference */ } /* increment refcount by two to avoid changing the orphan bit */ #ifdef GRPC_FD_REF_COUNT_DEBUG static void fd_ref(grpc_fd *fd, const char *reason, const char *file, int line) { ref_by(fd, 2, reason, file, line); } static void fd_unref(grpc_fd *fd, const char *reason, const char *file, int line) { unref_by(fd, 2, reason, file, line); } #else static void fd_ref(grpc_fd *fd) { ref_by(fd, 2); } static void fd_unref(grpc_fd *fd) { unref_by(fd, 2); } #endif static grpc_error *fd_shutdown_error(grpc_fd *fd) { if (!fd->shutdown) { return GRPC_ERROR_NONE; } else { return GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "FD shutdown", &fd->shutdown_error, 1); } } static void notify_on_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure **st, grpc_closure *closure) { if (fd->shutdown) { grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_CREATE_FROM_STATIC_STRING("FD shutdown")); } else if (*st == CLOSURE_NOT_READY) { /* not ready ==> switch to a waiting state by setting the closure */ *st = closure; } else if (*st == CLOSURE_READY) { /* already ready ==> queue the closure to run immediately */ *st = CLOSURE_NOT_READY; grpc_closure_sched(exec_ctx, closure, fd_shutdown_error(fd)); maybe_wake_one_watcher_locked(fd); } else { /* upcallptr was set to a different closure. This is an error! */ gpr_log(GPR_ERROR, "User called a notify_on function with a previous callback still " "pending"); abort(); } } /* returns 1 if state becomes not ready */ static int set_ready_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure **st) { if (*st == CLOSURE_READY) { /* duplicate ready ==> ignore */ return 0; } else if (*st == CLOSURE_NOT_READY) { /* not ready, and not waiting ==> flag ready */ *st = CLOSURE_READY; return 0; } else { /* waiting ==> queue closure */ grpc_closure_sched(exec_ctx, *st, fd_shutdown_error(fd)); *st = CLOSURE_NOT_READY; return 1; } } static void set_read_notifier_pollset_locked( grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_pollset *read_notifier_pollset) { fd->read_notifier_pollset = read_notifier_pollset; } static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why) { gpr_mu_lock(&fd->mu); /* only shutdown once */ if (!fd->shutdown) { fd->shutdown = 1; fd->shutdown_error = why; /* signal read/write closed to OS so that future operations fail */ shutdown(fd->fd, SHUT_RDWR); set_ready_locked(exec_ctx, fd, &fd->read_closure); set_ready_locked(exec_ctx, fd, &fd->write_closure); } else { GRPC_ERROR_UNREF(why); } gpr_mu_unlock(&fd->mu); } static bool fd_is_shutdown(grpc_fd *fd) { gpr_mu_lock(&fd->mu); bool r = fd->shutdown; gpr_mu_unlock(&fd->mu); return r; } static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *closure) { gpr_mu_lock(&fd->mu); notify_on_locked(exec_ctx, fd, &fd->read_closure, closure); gpr_mu_unlock(&fd->mu); } static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *closure) { gpr_mu_lock(&fd->mu); notify_on_locked(exec_ctx, fd, &fd->write_closure, closure); gpr_mu_unlock(&fd->mu); } static uint32_t fd_begin_poll(grpc_fd *fd, grpc_pollset *pollset, grpc_pollset_worker *worker, uint32_t read_mask, uint32_t write_mask, grpc_fd_watcher *watcher) { uint32_t mask = 0; grpc_closure *cur; int requested; /* keep track of pollers that have requested our events, in case they change */ GRPC_FD_REF(fd, "poll"); gpr_mu_lock(&fd->mu); /* if we are shutdown, then don't add to the watcher set */ if (fd->shutdown) { watcher->fd = NULL; watcher->pollset = NULL; watcher->worker = NULL; gpr_mu_unlock(&fd->mu); GRPC_FD_UNREF(fd, "poll"); return 0; } /* if there is nobody polling for read, but we need to, then start doing so */ cur = fd->read_closure; requested = cur != CLOSURE_READY; if (read_mask && fd->read_watcher == NULL && requested) { fd->read_watcher = watcher; mask |= read_mask; } /* if there is nobody polling for write, but we need to, then start doing so */ cur = fd->write_closure; requested = cur != CLOSURE_READY; if (write_mask && fd->write_watcher == NULL && requested) { fd->write_watcher = watcher; mask |= write_mask; } /* if not polling, remember this watcher in case we need someone to later */ if (mask == 0 && worker != NULL) { watcher->next = &fd->inactive_watcher_root; watcher->prev = watcher->next->prev; watcher->next->prev = watcher->prev->next = watcher; } watcher->pollset = pollset; watcher->worker = worker; watcher->fd = fd; gpr_mu_unlock(&fd->mu); return mask; } static void fd_end_poll(grpc_exec_ctx *exec_ctx, grpc_fd_watcher *watcher, int got_read, int got_write, grpc_pollset *read_notifier_pollset) { int was_polling = 0; int kick = 0; grpc_fd *fd = watcher->fd; if (fd == NULL) { return; } gpr_mu_lock(&fd->mu); if (watcher == fd->read_watcher) { /* remove read watcher, kick if we still need a read */ was_polling = 1; if (!got_read) { kick = 1; } fd->read_watcher = NULL; } if (watcher == fd->write_watcher) { /* remove write watcher, kick if we still need a write */ was_polling = 1; if (!got_write) { kick = 1; } fd->write_watcher = NULL; } if (!was_polling && watcher->worker != NULL) { /* remove from inactive list */ watcher->next->prev = watcher->prev; watcher->prev->next = watcher->next; } if (got_read) { if (set_ready_locked(exec_ctx, fd, &fd->read_closure)) { kick = 1; } if (read_notifier_pollset != NULL) { set_read_notifier_pollset_locked(exec_ctx, fd, read_notifier_pollset); } } if (got_write) { if (set_ready_locked(exec_ctx, fd, &fd->write_closure)) { kick = 1; } } if (kick) { maybe_wake_one_watcher_locked(fd); } if (fd_is_orphaned(fd) && !has_watchers(fd) && !fd->closed) { close_fd_locked(exec_ctx, fd); } gpr_mu_unlock(&fd->mu); GRPC_FD_UNREF(fd, "poll"); } static grpc_workqueue *fd_get_workqueue(grpc_fd *fd) { return NULL; } /******************************************************************************* * pollset_posix.c */ GPR_TLS_DECL(g_current_thread_poller); GPR_TLS_DECL(g_current_thread_worker); static void remove_worker(grpc_pollset *p, grpc_pollset_worker *worker) { worker->prev->next = worker->next; worker->next->prev = worker->prev; } static bool pollset_has_workers(grpc_pollset *p) { return p->root_worker.next != &p->root_worker; } static bool pollset_in_pollset_sets(grpc_pollset *p) { return p->pollset_set_count; } static bool pollset_has_observers(grpc_pollset *p) { return pollset_has_workers(p) || pollset_in_pollset_sets(p); } static grpc_pollset_worker *pop_front_worker(grpc_pollset *p) { if (pollset_has_workers(p)) { grpc_pollset_worker *w = p->root_worker.next; remove_worker(p, w); return w; } else { return NULL; } } static void push_back_worker(grpc_pollset *p, grpc_pollset_worker *worker) { worker->next = &p->root_worker; worker->prev = worker->next->prev; worker->prev->next = worker->next->prev = worker; } static void push_front_worker(grpc_pollset *p, grpc_pollset_worker *worker) { worker->prev = &p->root_worker; worker->next = worker->prev->next; worker->prev->next = worker->next->prev = worker; } static void kick_append_error(grpc_error **composite, grpc_error *error) { if (error == GRPC_ERROR_NONE) return; if (*composite == GRPC_ERROR_NONE) { *composite = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Kick Failure"); } *composite = grpc_error_add_child(*composite, error); } static grpc_error *pollset_kick_ext(grpc_pollset *p, grpc_pollset_worker *specific_worker, uint32_t flags) { GPR_TIMER_BEGIN("pollset_kick_ext", 0); grpc_error *error = GRPC_ERROR_NONE; /* pollset->mu already held */ if (specific_worker != NULL) { if (specific_worker == GRPC_POLLSET_KICK_BROADCAST) { GPR_TIMER_BEGIN("pollset_kick_ext.broadcast", 0); GPR_ASSERT((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) == 0); for (specific_worker = p->root_worker.next; specific_worker != &p->root_worker; specific_worker = specific_worker->next) { kick_append_error( &error, grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd)); } p->kicked_without_pollers = true; GPR_TIMER_END("pollset_kick_ext.broadcast", 0); } else if (gpr_tls_get(&g_current_thread_worker) != (intptr_t)specific_worker) { GPR_TIMER_MARK("different_thread_worker", 0); if ((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) != 0) { specific_worker->reevaluate_polling_on_wakeup = true; } specific_worker->kicked_specifically = true; kick_append_error(&error, grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd)); } else if ((flags & GRPC_POLLSET_CAN_KICK_SELF) != 0) { GPR_TIMER_MARK("kick_yoself", 0); if ((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) != 0) { specific_worker->reevaluate_polling_on_wakeup = true; } specific_worker->kicked_specifically = true; kick_append_error(&error, grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd)); } } else if (gpr_tls_get(&g_current_thread_poller) != (intptr_t)p) { GPR_ASSERT((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) == 0); GPR_TIMER_MARK("kick_anonymous", 0); specific_worker = pop_front_worker(p); if (specific_worker != NULL) { if (gpr_tls_get(&g_current_thread_worker) == (intptr_t)specific_worker) { GPR_TIMER_MARK("kick_anonymous_not_self", 0); push_back_worker(p, specific_worker); specific_worker = pop_front_worker(p); if ((flags & GRPC_POLLSET_CAN_KICK_SELF) == 0 && gpr_tls_get(&g_current_thread_worker) == (intptr_t)specific_worker) { push_back_worker(p, specific_worker); specific_worker = NULL; } } if (specific_worker != NULL) { GPR_TIMER_MARK("finally_kick", 0); push_back_worker(p, specific_worker); kick_append_error( &error, grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd)); } } else { GPR_TIMER_MARK("kicked_no_pollers", 0); p->kicked_without_pollers = true; } } GPR_TIMER_END("pollset_kick_ext", 0); GRPC_LOG_IF_ERROR("pollset_kick_ext", GRPC_ERROR_REF(error)); return error; } static grpc_error *pollset_kick(grpc_pollset *p, grpc_pollset_worker *specific_worker) { return pollset_kick_ext(p, specific_worker, 0); } /* global state management */ static grpc_error *pollset_global_init(void) { gpr_tls_init(&g_current_thread_poller); gpr_tls_init(&g_current_thread_worker); return grpc_wakeup_fd_init(&global_wakeup_fd); } static void pollset_global_shutdown(void) { grpc_wakeup_fd_destroy(&global_wakeup_fd); gpr_tls_destroy(&g_current_thread_poller); gpr_tls_destroy(&g_current_thread_worker); } static grpc_error *kick_poller(void) { return grpc_wakeup_fd_wakeup(&global_wakeup_fd); } /* main interface */ static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) { gpr_mu_init(&pollset->mu); *mu = &pollset->mu; pollset->root_worker.next = pollset->root_worker.prev = &pollset->root_worker; pollset->shutting_down = 0; pollset->called_shutdown = 0; pollset->kicked_without_pollers = 0; pollset->idle_jobs.head = pollset->idle_jobs.tail = NULL; pollset->local_wakeup_cache = NULL; pollset->kicked_without_pollers = 0; pollset->fd_count = 0; pollset->fd_capacity = 0; pollset->fds = NULL; pollset->pollset_set_count = 0; } static void pollset_destroy(grpc_pollset *pollset) { GPR_ASSERT(!pollset_has_workers(pollset)); GPR_ASSERT(pollset->idle_jobs.head == pollset->idle_jobs.tail); while (pollset->local_wakeup_cache) { grpc_cached_wakeup_fd *next = pollset->local_wakeup_cache->next; grpc_wakeup_fd_destroy(&pollset->local_wakeup_cache->fd); gpr_free(pollset->local_wakeup_cache); pollset->local_wakeup_cache = next; } gpr_free(pollset->fds); gpr_mu_destroy(&pollset->mu); } static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_fd *fd) { gpr_mu_lock(&pollset->mu); size_t i; /* TODO(ctiller): this is O(num_fds^2); maybe switch to a hash set here */ for (i = 0; i < pollset->fd_count; i++) { if (pollset->fds[i] == fd) goto exit; } if (pollset->fd_count == pollset->fd_capacity) { pollset->fd_capacity = GPR_MAX(pollset->fd_capacity + 8, pollset->fd_count * 3 / 2); pollset->fds = gpr_realloc(pollset->fds, sizeof(grpc_fd *) * pollset->fd_capacity); } pollset->fds[pollset->fd_count++] = fd; GRPC_FD_REF(fd, "multipoller"); pollset_kick(pollset, NULL); exit: gpr_mu_unlock(&pollset->mu); } static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) { GPR_ASSERT(grpc_closure_list_empty(pollset->idle_jobs)); size_t i; for (i = 0; i < pollset->fd_count; i++) { GRPC_FD_UNREF(pollset->fds[i], "multipoller"); } pollset->fd_count = 0; grpc_closure_sched(exec_ctx, pollset->shutdown_done, GRPC_ERROR_NONE); } static void work_combine_error(grpc_error **composite, grpc_error *error) { if (error == GRPC_ERROR_NONE) return; if (*composite == GRPC_ERROR_NONE) { *composite = GRPC_ERROR_CREATE_FROM_STATIC_STRING("pollset_work"); } *composite = grpc_error_add_child(*composite, error); } static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker **worker_hdl, gpr_timespec now, gpr_timespec deadline) { grpc_pollset_worker worker; if (worker_hdl) *worker_hdl = &worker; grpc_error *error = GRPC_ERROR_NONE; /* Avoid malloc for small number of elements. */ enum { inline_elements = 96 }; struct pollfd pollfd_space[inline_elements]; struct grpc_fd_watcher watcher_space[inline_elements]; /* pollset->mu already held */ int added_worker = 0; int locked = 1; int queued_work = 0; int keep_polling = 0; GPR_TIMER_BEGIN("pollset_work", 0); /* this must happen before we (potentially) drop pollset->mu */ worker.next = worker.prev = NULL; worker.reevaluate_polling_on_wakeup = 0; if (pollset->local_wakeup_cache != NULL) { worker.wakeup_fd = pollset->local_wakeup_cache; pollset->local_wakeup_cache = worker.wakeup_fd->next; } else { worker.wakeup_fd = gpr_malloc(sizeof(*worker.wakeup_fd)); error = grpc_wakeup_fd_init(&worker.wakeup_fd->fd); if (error != GRPC_ERROR_NONE) { GRPC_LOG_IF_ERROR("pollset_work", GRPC_ERROR_REF(error)); return error; } } worker.kicked_specifically = 0; /* If there's work waiting for the pollset to be idle, and the pollset is idle, then do that work */ if (!pollset_has_workers(pollset) && !grpc_closure_list_empty(pollset->idle_jobs)) { GPR_TIMER_MARK("pollset_work.idle_jobs", 0); grpc_closure_list_sched(exec_ctx, &pollset->idle_jobs); goto done; } /* If we're shutting down then we don't execute any extended work */ if (pollset->shutting_down) { GPR_TIMER_MARK("pollset_work.shutting_down", 0); goto done; } /* Start polling, and keep doing so while we're being asked to re-evaluate our pollers (this allows poll() based pollers to ensure they don't miss wakeups) */ keep_polling = 1; gpr_tls_set(&g_current_thread_poller, (intptr_t)pollset); while (keep_polling) { keep_polling = 0; if (!pollset->kicked_without_pollers) { if (!added_worker) { push_front_worker(pollset, &worker); added_worker = 1; gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker); } GPR_TIMER_BEGIN("maybe_work_and_unlock", 0); #define POLLOUT_CHECK (POLLOUT | POLLHUP | POLLERR) #define POLLIN_CHECK (POLLIN | POLLHUP | POLLERR) int timeout; int r; size_t i, fd_count; nfds_t pfd_count; grpc_fd_watcher *watchers; struct pollfd *pfds; timeout = poll_deadline_to_millis_timeout(deadline, now); if (pollset->fd_count + 2 <= inline_elements) { pfds = pollfd_space; watchers = watcher_space; } else { /* Allocate one buffer to hold both pfds and watchers arrays */ const size_t pfd_size = sizeof(*pfds) * (pollset->fd_count + 2); const size_t watch_size = sizeof(*watchers) * (pollset->fd_count + 2); void *buf = gpr_malloc(pfd_size + watch_size); pfds = buf; watchers = (void *)((char *)buf + pfd_size); } fd_count = 0; pfd_count = 2; pfds[0].fd = GRPC_WAKEUP_FD_GET_READ_FD(&global_wakeup_fd); pfds[0].events = POLLIN; pfds[0].revents = 0; pfds[1].fd = GRPC_WAKEUP_FD_GET_READ_FD(&worker.wakeup_fd->fd); pfds[1].events = POLLIN; pfds[1].revents = 0; for (i = 0; i < pollset->fd_count; i++) { if (fd_is_orphaned(pollset->fds[i])) { GRPC_FD_UNREF(pollset->fds[i], "multipoller"); } else { pollset->fds[fd_count++] = pollset->fds[i]; watchers[pfd_count].fd = pollset->fds[i]; GRPC_FD_REF(watchers[pfd_count].fd, "multipoller_start"); pfds[pfd_count].fd = pollset->fds[i]->fd; pfds[pfd_count].revents = 0; pfd_count++; } } pollset->fd_count = fd_count; gpr_mu_unlock(&pollset->mu); for (i = 2; i < pfd_count; i++) { grpc_fd *fd = watchers[i].fd; pfds[i].events = (short)fd_begin_poll(fd, pollset, &worker, POLLIN, POLLOUT, &watchers[i]); GRPC_FD_UNREF(fd, "multipoller_start"); } /* TODO(vpai): Consider first doing a 0 timeout poll here to avoid even going into the blocking annotation if possible */ GRPC_SCHEDULING_START_BLOCKING_REGION; r = grpc_poll_function(pfds, pfd_count, timeout); GRPC_SCHEDULING_END_BLOCKING_REGION; if (r < 0) { if (errno != EINTR) { work_combine_error(&error, GRPC_OS_ERROR(errno, "poll")); } for (i = 2; i < pfd_count; i++) { if (watchers[i].fd == NULL) { fd_end_poll(exec_ctx, &watchers[i], 0, 0, NULL); } else { // Wake up all the file descriptors, if we have an invalid one // we can identify it on the next pollset_work() fd_end_poll(exec_ctx, &watchers[i], 1, 1, pollset); } } } else if (r == 0) { for (i = 2; i < pfd_count; i++) { fd_end_poll(exec_ctx, &watchers[i], 0, 0, NULL); } } else { if (pfds[0].revents & POLLIN_CHECK) { grpc_timer_consume_kick(); work_combine_error(&error, grpc_wakeup_fd_consume_wakeup(&global_wakeup_fd)); } if (pfds[1].revents & POLLIN_CHECK) { work_combine_error( &error, grpc_wakeup_fd_consume_wakeup(&worker.wakeup_fd->fd)); } for (i = 2; i < pfd_count; i++) { if (watchers[i].fd == NULL) { fd_end_poll(exec_ctx, &watchers[i], 0, 0, NULL); } else { fd_end_poll(exec_ctx, &watchers[i], pfds[i].revents & POLLIN_CHECK, pfds[i].revents & POLLOUT_CHECK, pollset); } } } if (pfds != pollfd_space) { /* pfds and watchers are in the same memory block pointed to by pfds */ gpr_free(pfds); } GPR_TIMER_END("maybe_work_and_unlock", 0); locked = 0; } else { GPR_TIMER_MARK("pollset_work.kicked_without_pollers", 0); pollset->kicked_without_pollers = 0; } /* Finished execution - start cleaning up. Note that we may arrive here from outside the enclosing while() loop. In that case we won't loop though as we haven't added worker to the worker list, which means nobody could ask us to re-evaluate polling). */ done: if (!locked) { queued_work |= grpc_exec_ctx_flush(exec_ctx); gpr_mu_lock(&pollset->mu); locked = 1; } /* If we're forced to re-evaluate polling (via pollset_kick with GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) then we land here and force a loop */ if (worker.reevaluate_polling_on_wakeup && error == GRPC_ERROR_NONE) { worker.reevaluate_polling_on_wakeup = 0; pollset->kicked_without_pollers = 0; if (queued_work || worker.kicked_specifically) { /* If there's queued work on the list, then set the deadline to be immediate so we get back out of the polling loop quickly */ deadline = gpr_inf_past(GPR_CLOCK_MONOTONIC); } keep_polling = 1; } if (keep_polling) { now = gpr_now(now.clock_type); } } gpr_tls_set(&g_current_thread_poller, 0); if (added_worker) { remove_worker(pollset, &worker); gpr_tls_set(&g_current_thread_worker, 0); } /* release wakeup fd to the local pool */ worker.wakeup_fd->next = pollset->local_wakeup_cache; pollset->local_wakeup_cache = worker.wakeup_fd; /* check shutdown conditions */ if (pollset->shutting_down) { if (pollset_has_workers(pollset)) { pollset_kick(pollset, NULL); } else if (!pollset->called_shutdown && !pollset_has_observers(pollset)) { pollset->called_shutdown = 1; gpr_mu_unlock(&pollset->mu); finish_shutdown(exec_ctx, pollset); grpc_exec_ctx_flush(exec_ctx); /* Continuing to access pollset here is safe -- it is the caller's * responsibility to not destroy when it has outstanding calls to * pollset_work. * TODO(dklempner): Can we refactor the shutdown logic to avoid this? */ gpr_mu_lock(&pollset->mu); } else if (!grpc_closure_list_empty(pollset->idle_jobs)) { grpc_closure_list_sched(exec_ctx, &pollset->idle_jobs); gpr_mu_unlock(&pollset->mu); grpc_exec_ctx_flush(exec_ctx); gpr_mu_lock(&pollset->mu); } } if (worker_hdl) *worker_hdl = NULL; GPR_TIMER_END("pollset_work", 0); GRPC_LOG_IF_ERROR("pollset_work", GRPC_ERROR_REF(error)); return error; } static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_closure *closure) { GPR_ASSERT(!pollset->shutting_down); pollset->shutting_down = 1; pollset->shutdown_done = closure; pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST); if (!pollset_has_workers(pollset)) { grpc_closure_list_sched(exec_ctx, &pollset->idle_jobs); } if (!pollset->called_shutdown && !pollset_has_observers(pollset)) { pollset->called_shutdown = 1; finish_shutdown(exec_ctx, pollset); } } static int poll_deadline_to_millis_timeout(gpr_timespec deadline, gpr_timespec now) { gpr_timespec timeout; static const int64_t max_spin_polling_us = 10; if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) == 0) { return -1; } if (gpr_time_cmp(deadline, gpr_time_add(now, gpr_time_from_micros( max_spin_polling_us, GPR_TIMESPAN))) <= 0) { return 0; } timeout = gpr_time_sub(deadline, now); return gpr_time_to_millis(gpr_time_add( timeout, gpr_time_from_nanos(GPR_NS_PER_MS - 1, GPR_TIMESPAN))); } /******************************************************************************* * pollset_set_posix.c */ static grpc_pollset_set *pollset_set_create(void) { grpc_pollset_set *pollset_set = gpr_zalloc(sizeof(*pollset_set)); gpr_mu_init(&pollset_set->mu); return pollset_set; } static void pollset_set_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set) { size_t i; gpr_mu_destroy(&pollset_set->mu); for (i = 0; i < pollset_set->fd_count; i++) { GRPC_FD_UNREF(pollset_set->fds[i], "pollset_set"); } for (i = 0; i < pollset_set->pollset_count; i++) { grpc_pollset *pollset = pollset_set->pollsets[i]; gpr_mu_lock(&pollset->mu); pollset->pollset_set_count--; /* check shutdown */ if (pollset->shutting_down && !pollset->called_shutdown && !pollset_has_observers(pollset)) { pollset->called_shutdown = 1; gpr_mu_unlock(&pollset->mu); finish_shutdown(exec_ctx, pollset); } else { gpr_mu_unlock(&pollset->mu); } } gpr_free(pollset_set->pollsets); gpr_free(pollset_set->pollset_sets); gpr_free(pollset_set->fds); gpr_free(pollset_set); } static void pollset_set_add_pollset(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set, grpc_pollset *pollset) { size_t i, j; gpr_mu_lock(&pollset->mu); pollset->pollset_set_count++; gpr_mu_unlock(&pollset->mu); gpr_mu_lock(&pollset_set->mu); if (pollset_set->pollset_count == pollset_set->pollset_capacity) { pollset_set->pollset_capacity = GPR_MAX(8, 2 * pollset_set->pollset_capacity); pollset_set->pollsets = gpr_realloc(pollset_set->pollsets, pollset_set->pollset_capacity * sizeof(*pollset_set->pollsets)); } pollset_set->pollsets[pollset_set->pollset_count++] = pollset; for (i = 0, j = 0; i < pollset_set->fd_count; i++) { if (fd_is_orphaned(pollset_set->fds[i])) { GRPC_FD_UNREF(pollset_set->fds[i], "pollset_set"); } else { pollset_add_fd(exec_ctx, pollset, pollset_set->fds[i]); pollset_set->fds[j++] = pollset_set->fds[i]; } } pollset_set->fd_count = j; gpr_mu_unlock(&pollset_set->mu); } static void pollset_set_del_pollset(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set, grpc_pollset *pollset) { size_t i; gpr_mu_lock(&pollset_set->mu); for (i = 0; i < pollset_set->pollset_count; i++) { if (pollset_set->pollsets[i] == pollset) { pollset_set->pollset_count--; GPR_SWAP(grpc_pollset *, pollset_set->pollsets[i], pollset_set->pollsets[pollset_set->pollset_count]); break; } } gpr_mu_unlock(&pollset_set->mu); gpr_mu_lock(&pollset->mu); pollset->pollset_set_count--; /* check shutdown */ if (pollset->shutting_down && !pollset->called_shutdown && !pollset_has_observers(pollset)) { pollset->called_shutdown = 1; gpr_mu_unlock(&pollset->mu); finish_shutdown(exec_ctx, pollset); } else { gpr_mu_unlock(&pollset->mu); } } static void pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx, grpc_pollset_set *bag, grpc_pollset_set *item) { size_t i, j; gpr_mu_lock(&bag->mu); if (bag->pollset_set_count == bag->pollset_set_capacity) { bag->pollset_set_capacity = GPR_MAX(8, 2 * bag->pollset_set_capacity); bag->pollset_sets = gpr_realloc(bag->pollset_sets, bag->pollset_set_capacity * sizeof(*bag->pollset_sets)); } bag->pollset_sets[bag->pollset_set_count++] = item; for (i = 0, j = 0; i < bag->fd_count; i++) { if (fd_is_orphaned(bag->fds[i])) { GRPC_FD_UNREF(bag->fds[i], "pollset_set"); } else { pollset_set_add_fd(exec_ctx, item, bag->fds[i]); bag->fds[j++] = bag->fds[i]; } } bag->fd_count = j; gpr_mu_unlock(&bag->mu); } static void pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx, grpc_pollset_set *bag, grpc_pollset_set *item) { size_t i; gpr_mu_lock(&bag->mu); for (i = 0; i < bag->pollset_set_count; i++) { if (bag->pollset_sets[i] == item) { bag->pollset_set_count--; GPR_SWAP(grpc_pollset_set *, bag->pollset_sets[i], bag->pollset_sets[bag->pollset_set_count]); break; } } gpr_mu_unlock(&bag->mu); } static void pollset_set_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set, grpc_fd *fd) { size_t i; gpr_mu_lock(&pollset_set->mu); if (pollset_set->fd_count == pollset_set->fd_capacity) { pollset_set->fd_capacity = GPR_MAX(8, 2 * pollset_set->fd_capacity); pollset_set->fds = gpr_realloc( pollset_set->fds, pollset_set->fd_capacity * sizeof(*pollset_set->fds)); } GRPC_FD_REF(fd, "pollset_set"); pollset_set->fds[pollset_set->fd_count++] = fd; for (i = 0; i < pollset_set->pollset_count; i++) { pollset_add_fd(exec_ctx, pollset_set->pollsets[i], fd); } for (i = 0; i < pollset_set->pollset_set_count; i++) { pollset_set_add_fd(exec_ctx, pollset_set->pollset_sets[i], fd); } gpr_mu_unlock(&pollset_set->mu); } static void pollset_set_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set, grpc_fd *fd) { size_t i; gpr_mu_lock(&pollset_set->mu); for (i = 0; i < pollset_set->fd_count; i++) { if (pollset_set->fds[i] == fd) { pollset_set->fd_count--; GPR_SWAP(grpc_fd *, pollset_set->fds[i], pollset_set->fds[pollset_set->fd_count]); GRPC_FD_UNREF(fd, "pollset_set"); break; } } for (i = 0; i < pollset_set->pollset_set_count; i++) { pollset_set_del_fd(exec_ctx, pollset_set->pollset_sets[i], fd); } gpr_mu_unlock(&pollset_set->mu); } /******************************************************************************* * workqueue stubs */ #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG static grpc_workqueue *workqueue_ref(grpc_workqueue *workqueue, const char *file, int line, const char *reason) { return workqueue; } static void workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, const char *file, int line, const char *reason) {} #else static grpc_workqueue *workqueue_ref(grpc_workqueue *workqueue) { return workqueue; } static void workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) {} #endif static grpc_closure_scheduler *workqueue_scheduler(grpc_workqueue *workqueue) { return grpc_schedule_on_exec_ctx; } /******************************************************************************* * Condition Variable polling extensions */ static void decref_poll_args(poll_args *args) { if (gpr_unref(&args->refcount)) { gpr_free(args->fds); gpr_cv_destroy(args->cv); gpr_free(args->cv); gpr_free(args); } } // Poll in a background thread static void run_poll(void *arg) { int timeout, retval; poll_args *pargs = (poll_args *)arg; while (gpr_atm_no_barrier_load(&pargs->status) == INPROGRESS) { if (pargs->timeout < 0) { timeout = CV_POLL_PERIOD_MS; } else { timeout = GPR_MIN(CV_POLL_PERIOD_MS, pargs->timeout); pargs->timeout -= timeout; } retval = g_cvfds.poll(pargs->fds, pargs->nfds, timeout); if (retval != 0 || pargs->timeout == 0) { pargs->retval = retval; pargs->err = errno; break; } } gpr_mu_lock(&g_cvfds.mu); if (gpr_atm_no_barrier_load(&pargs->status) == INPROGRESS) { // Signal main thread that the poll completed gpr_atm_no_barrier_store(&pargs->status, COMPLETED); gpr_cv_signal(pargs->cv); } decref_poll_args(pargs); g_cvfds.pollcount--; if (g_cvfds.shutdown && g_cvfds.pollcount == 0) { gpr_cv_signal(&g_cvfds.shutdown_complete); } gpr_mu_unlock(&g_cvfds.mu); } // This function overrides poll() to handle condition variable wakeup fds static int cvfd_poll(struct pollfd *fds, nfds_t nfds, int timeout) { unsigned int i; int res, idx; gpr_cv *pollcv; cv_node *cvn, *prev; int skip_poll = 0; nfds_t nsockfds = 0; gpr_thd_id t_id; gpr_thd_options opt; poll_args *pargs = NULL; gpr_mu_lock(&g_cvfds.mu); pollcv = gpr_malloc(sizeof(gpr_cv)); gpr_cv_init(pollcv); for (i = 0; i < nfds; i++) { fds[i].revents = 0; if (fds[i].fd < 0 && (fds[i].events & POLLIN)) { idx = FD_TO_IDX(fds[i].fd); cvn = gpr_malloc(sizeof(cv_node)); cvn->cv = pollcv; cvn->next = g_cvfds.cvfds[idx].cvs; g_cvfds.cvfds[idx].cvs = cvn; // Don't bother polling if a wakeup fd is ready if (g_cvfds.cvfds[idx].is_set) { skip_poll = 1; } } else if (fds[i].fd >= 0) { nsockfds++; } } res = 0; if (!skip_poll && nsockfds > 0) { pargs = gpr_malloc(sizeof(struct poll_args)); // Both the main thread and calling thread get a reference gpr_ref_init(&pargs->refcount, 2); pargs->cv = pollcv; pargs->fds = gpr_malloc(sizeof(struct pollfd) * nsockfds); pargs->nfds = nsockfds; pargs->timeout = timeout; pargs->retval = 0; pargs->err = 0; gpr_atm_no_barrier_store(&pargs->status, INPROGRESS); idx = 0; for (i = 0; i < nfds; i++) { if (fds[i].fd >= 0) { pargs->fds[idx].fd = fds[i].fd; pargs->fds[idx].events = fds[i].events; pargs->fds[idx].revents = 0; idx++; } } g_cvfds.pollcount++; opt = gpr_thd_options_default(); gpr_thd_options_set_detached(&opt); GPR_ASSERT(gpr_thd_new(&t_id, &run_poll, pargs, &opt)); // We want the poll() thread to trigger the deadline, so wait forever here gpr_cv_wait(pollcv, &g_cvfds.mu, gpr_inf_future(GPR_CLOCK_MONOTONIC)); if (gpr_atm_no_barrier_load(&pargs->status) == COMPLETED) { res = pargs->retval; errno = pargs->err; } else { errno = 0; gpr_atm_no_barrier_store(&pargs->status, CANCELLED); } } else if (!skip_poll) { gpr_timespec deadline = gpr_now(GPR_CLOCK_REALTIME); deadline = gpr_time_add(deadline, gpr_time_from_millis(timeout, GPR_TIMESPAN)); gpr_cv_wait(pollcv, &g_cvfds.mu, deadline); } idx = 0; for (i = 0; i < nfds; i++) { if (fds[i].fd < 0 && (fds[i].events & POLLIN)) { cvn = g_cvfds.cvfds[FD_TO_IDX(fds[i].fd)].cvs; prev = NULL; while (cvn->cv != pollcv) { prev = cvn; cvn = cvn->next; GPR_ASSERT(cvn); } if (!prev) { g_cvfds.cvfds[FD_TO_IDX(fds[i].fd)].cvs = cvn->next; } else { prev->next = cvn->next; } gpr_free(cvn); if (g_cvfds.cvfds[FD_TO_IDX(fds[i].fd)].is_set) { fds[i].revents = POLLIN; if (res >= 0) res++; } } else if (!skip_poll && fds[i].fd >= 0 && gpr_atm_no_barrier_load(&pargs->status) == COMPLETED) { fds[i].revents = pargs->fds[idx].revents; idx++; } } if (pargs) { decref_poll_args(pargs); } else { gpr_cv_destroy(pollcv); gpr_free(pollcv); } gpr_mu_unlock(&g_cvfds.mu); return res; } static void global_cv_fd_table_init() { gpr_mu_init(&g_cvfds.mu); gpr_mu_lock(&g_cvfds.mu); gpr_cv_init(&g_cvfds.shutdown_complete); g_cvfds.shutdown = 0; g_cvfds.pollcount = 0; g_cvfds.size = CV_DEFAULT_TABLE_SIZE; g_cvfds.cvfds = gpr_malloc(sizeof(fd_node) * CV_DEFAULT_TABLE_SIZE); g_cvfds.free_fds = NULL; for (int i = 0; i < CV_DEFAULT_TABLE_SIZE; i++) { g_cvfds.cvfds[i].is_set = 0; g_cvfds.cvfds[i].cvs = NULL; g_cvfds.cvfds[i].next_free = g_cvfds.free_fds; g_cvfds.free_fds = &g_cvfds.cvfds[i]; } // Override the poll function with one that supports cvfds g_cvfds.poll = grpc_poll_function; grpc_poll_function = &cvfd_poll; gpr_mu_unlock(&g_cvfds.mu); } static void global_cv_fd_table_shutdown() { gpr_mu_lock(&g_cvfds.mu); g_cvfds.shutdown = 1; // Attempt to wait for all abandoned poll() threads to terminate // Not doing so will result in reported memory leaks if (g_cvfds.pollcount > 0) { int res = gpr_cv_wait(&g_cvfds.shutdown_complete, &g_cvfds.mu, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(3, GPR_TIMESPAN))); GPR_ASSERT(res == 0); } gpr_cv_destroy(&g_cvfds.shutdown_complete); grpc_poll_function = g_cvfds.poll; gpr_free(g_cvfds.cvfds); gpr_mu_unlock(&g_cvfds.mu); gpr_mu_destroy(&g_cvfds.mu); } /******************************************************************************* * event engine binding */ static void shutdown_engine(void) { pollset_global_shutdown(); if (grpc_cv_wakeup_fds_enabled()) { global_cv_fd_table_shutdown(); } } static const grpc_event_engine_vtable vtable = { .pollset_size = sizeof(grpc_pollset), .fd_create = fd_create, .fd_wrapped_fd = fd_wrapped_fd, .fd_orphan = fd_orphan, .fd_shutdown = fd_shutdown, .fd_is_shutdown = fd_is_shutdown, .fd_notify_on_read = fd_notify_on_read, .fd_notify_on_write = fd_notify_on_write, .fd_get_read_notifier_pollset = fd_get_read_notifier_pollset, .fd_get_workqueue = fd_get_workqueue, .pollset_init = pollset_init, .pollset_shutdown = pollset_shutdown, .pollset_destroy = pollset_destroy, .pollset_work = pollset_work, .pollset_kick = pollset_kick, .pollset_add_fd = pollset_add_fd, .pollset_set_create = pollset_set_create, .pollset_set_destroy = pollset_set_destroy, .pollset_set_add_pollset = pollset_set_add_pollset, .pollset_set_del_pollset = pollset_set_del_pollset, .pollset_set_add_pollset_set = pollset_set_add_pollset_set, .pollset_set_del_pollset_set = pollset_set_del_pollset_set, .pollset_set_add_fd = pollset_set_add_fd, .pollset_set_del_fd = pollset_set_del_fd, .kick_poller = kick_poller, .workqueue_ref = workqueue_ref, .workqueue_unref = workqueue_unref, .workqueue_scheduler = workqueue_scheduler, .shutdown_engine = shutdown_engine, }; const grpc_event_engine_vtable *grpc_init_poll_posix(void) { if (!grpc_has_wakeup_fd()) { return NULL; } if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) { return NULL; } return &vtable; } const grpc_event_engine_vtable *grpc_init_poll_cv_posix(void) { global_cv_fd_table_init(); grpc_enable_cv_wakeup_fds(1); if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) { global_cv_fd_table_shutdown(); grpc_enable_cv_wakeup_fds(0); return NULL; } return &vtable; } #endif grpc-1.3.2/src/core/lib/iomgr/ev_poll_posix.h000066400000000000000000000035271310511640000211030ustar00rootroot00000000000000/* * * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_EV_POLL_POSIX_H #define GRPC_CORE_LIB_IOMGR_EV_POLL_POSIX_H #include "src/core/lib/iomgr/ev_posix.h" const grpc_event_engine_vtable *grpc_init_poll_posix(void); const grpc_event_engine_vtable *grpc_init_poll_cv_posix(void); #endif /* GRPC_CORE_LIB_IOMGR_EV_POLL_POSIX_H */ grpc-1.3.2/src/core/lib/iomgr/ev_posix.c000066400000000000000000000225031310511640000200430ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_POSIX_SOCKET #include "src/core/lib/iomgr/ev_posix.h" #include #include #include #include #include #include "src/core/lib/iomgr/ev_epoll_linux.h" #include "src/core/lib/iomgr/ev_poll_posix.h" #include "src/core/lib/support/env.h" /** Default poll() function - a pointer so that it can be overridden by some * tests */ grpc_poll_function_type grpc_poll_function = poll; grpc_wakeup_fd grpc_global_wakeup_fd; static const grpc_event_engine_vtable *g_event_engine; static const char *g_poll_strategy_name = NULL; typedef const grpc_event_engine_vtable *(*event_engine_factory_fn)(void); typedef struct { const char *name; event_engine_factory_fn factory; } event_engine_factory; static const event_engine_factory g_factories[] = { {"epoll", grpc_init_epoll_linux}, {"poll", grpc_init_poll_posix}, {"poll-cv", grpc_init_poll_cv_posix}, }; static void add(const char *beg, const char *end, char ***ss, size_t *ns) { size_t n = *ns; size_t np = n + 1; char *s; size_t len; GPR_ASSERT(end >= beg); len = (size_t)(end - beg); s = gpr_malloc(len + 1); memcpy(s, beg, len); s[len] = 0; *ss = gpr_realloc(*ss, sizeof(char **) * np); (*ss)[n] = s; *ns = np; } static void split(const char *s, char ***ss, size_t *ns) { const char *c = strchr(s, ','); if (c == NULL) { add(s, s + strlen(s), ss, ns); } else { add(s, c, ss, ns); split(c + 1, ss, ns); } } static bool is(const char *want, const char *have) { return 0 == strcmp(want, "all") || 0 == strcmp(want, have); } static void try_engine(const char *engine) { for (size_t i = 0; i < GPR_ARRAY_SIZE(g_factories); i++) { if (is(engine, g_factories[i].name)) { if ((g_event_engine = g_factories[i].factory())) { g_poll_strategy_name = g_factories[i].name; gpr_log(GPR_DEBUG, "Using polling engine: %s", g_factories[i].name); return; } } } } /* This should be used for testing purposes ONLY */ void grpc_set_event_engine_test_only( const grpc_event_engine_vtable *ev_engine) { g_event_engine = ev_engine; } /* Call this only after calling grpc_event_engine_init() */ const char *grpc_get_poll_strategy_name() { return g_poll_strategy_name; } void grpc_event_engine_init(void) { char *s = gpr_getenv("GRPC_POLL_STRATEGY"); if (s == NULL) { s = gpr_strdup("all"); } char **strings = NULL; size_t nstrings = 0; split(s, &strings, &nstrings); for (size_t i = 0; g_event_engine == NULL && i < nstrings; i++) { try_engine(strings[i]); } for (size_t i = 0; i < nstrings; i++) { gpr_free(strings[i]); } gpr_free(strings); gpr_free(s); if (g_event_engine == NULL) { gpr_log(GPR_ERROR, "No event engine could be initialized"); abort(); } } void grpc_event_engine_shutdown(void) { g_event_engine->shutdown_engine(); g_event_engine = NULL; } grpc_fd *grpc_fd_create(int fd, const char *name) { return g_event_engine->fd_create(fd, name); } grpc_workqueue *grpc_fd_get_workqueue(grpc_fd *fd) { return g_event_engine->fd_get_workqueue(fd); } int grpc_fd_wrapped_fd(grpc_fd *fd) { return g_event_engine->fd_wrapped_fd(fd); } void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done, int *release_fd, const char *reason) { g_event_engine->fd_orphan(exec_ctx, fd, on_done, release_fd, reason); } void grpc_fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why) { g_event_engine->fd_shutdown(exec_ctx, fd, why); } bool grpc_fd_is_shutdown(grpc_fd *fd) { return g_event_engine->fd_is_shutdown(fd); } void grpc_fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *closure) { g_event_engine->fd_notify_on_read(exec_ctx, fd, closure); } void grpc_fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *closure) { g_event_engine->fd_notify_on_write(exec_ctx, fd, closure); } size_t grpc_pollset_size(void) { return g_event_engine->pollset_size; } void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu) { g_event_engine->pollset_init(pollset, mu); } void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_closure *closure) { g_event_engine->pollset_shutdown(exec_ctx, pollset, closure); } void grpc_pollset_destroy(grpc_pollset *pollset) { g_event_engine->pollset_destroy(pollset); } grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker **worker, gpr_timespec now, gpr_timespec deadline) { return g_event_engine->pollset_work(exec_ctx, pollset, worker, now, deadline); } grpc_error *grpc_pollset_kick(grpc_pollset *pollset, grpc_pollset_worker *specific_worker) { return g_event_engine->pollset_kick(pollset, specific_worker); } void grpc_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, struct grpc_fd *fd) { g_event_engine->pollset_add_fd(exec_ctx, pollset, fd); } grpc_pollset_set *grpc_pollset_set_create(void) { return g_event_engine->pollset_set_create(); } void grpc_pollset_set_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set) { g_event_engine->pollset_set_destroy(exec_ctx, pollset_set); } void grpc_pollset_set_add_pollset(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set, grpc_pollset *pollset) { g_event_engine->pollset_set_add_pollset(exec_ctx, pollset_set, pollset); } void grpc_pollset_set_del_pollset(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set, grpc_pollset *pollset) { g_event_engine->pollset_set_del_pollset(exec_ctx, pollset_set, pollset); } void grpc_pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx, grpc_pollset_set *bag, grpc_pollset_set *item) { g_event_engine->pollset_set_add_pollset_set(exec_ctx, bag, item); } void grpc_pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx, grpc_pollset_set *bag, grpc_pollset_set *item) { g_event_engine->pollset_set_del_pollset_set(exec_ctx, bag, item); } void grpc_pollset_set_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set, grpc_fd *fd) { g_event_engine->pollset_set_add_fd(exec_ctx, pollset_set, fd); } void grpc_pollset_set_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set, grpc_fd *fd) { g_event_engine->pollset_set_del_fd(exec_ctx, pollset_set, fd); } grpc_error *grpc_kick_poller(void) { return g_event_engine->kick_poller(); } #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG grpc_workqueue *grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line, const char *reason) { return g_event_engine->workqueue_ref(workqueue, file, line, reason); } void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, const char *file, int line, const char *reason) { g_event_engine->workqueue_unref(exec_ctx, workqueue, file, line, reason); } #else grpc_workqueue *grpc_workqueue_ref(grpc_workqueue *workqueue) { return g_event_engine->workqueue_ref(workqueue); } void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { g_event_engine->workqueue_unref(exec_ctx, workqueue); } #endif grpc_closure_scheduler *grpc_workqueue_scheduler(grpc_workqueue *workqueue) { return g_event_engine->workqueue_scheduler(workqueue); } #endif // GRPC_POSIX_SOCKET grpc-1.3.2/src/core/lib/iomgr/ev_posix.h000066400000000000000000000207601310511640000200530ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_EV_POSIX_H #define GRPC_CORE_LIB_IOMGR_EV_POSIX_H #include #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/pollset_set.h" #include "src/core/lib/iomgr/wakeup_fd_posix.h" #include "src/core/lib/iomgr/workqueue.h" typedef struct grpc_fd grpc_fd; typedef struct grpc_event_engine_vtable { size_t pollset_size; grpc_fd *(*fd_create)(int fd, const char *name); int (*fd_wrapped_fd)(grpc_fd *fd); void (*fd_orphan)(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done, int *release_fd, const char *reason); void (*fd_shutdown)(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why); void (*fd_notify_on_read)(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *closure); void (*fd_notify_on_write)(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *closure); bool (*fd_is_shutdown)(grpc_fd *fd); grpc_workqueue *(*fd_get_workqueue)(grpc_fd *fd); grpc_pollset *(*fd_get_read_notifier_pollset)(grpc_exec_ctx *exec_ctx, grpc_fd *fd); void (*pollset_init)(grpc_pollset *pollset, gpr_mu **mu); void (*pollset_shutdown)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_closure *closure); void (*pollset_destroy)(grpc_pollset *pollset); grpc_error *(*pollset_work)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker **worker, gpr_timespec now, gpr_timespec deadline); grpc_error *(*pollset_kick)(grpc_pollset *pollset, grpc_pollset_worker *specific_worker); void (*pollset_add_fd)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, struct grpc_fd *fd); grpc_pollset_set *(*pollset_set_create)(void); void (*pollset_set_destroy)(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set); void (*pollset_set_add_pollset)(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set, grpc_pollset *pollset); void (*pollset_set_del_pollset)(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set, grpc_pollset *pollset); void (*pollset_set_add_pollset_set)(grpc_exec_ctx *exec_ctx, grpc_pollset_set *bag, grpc_pollset_set *item); void (*pollset_set_del_pollset_set)(grpc_exec_ctx *exec_ctx, grpc_pollset_set *bag, grpc_pollset_set *item); void (*pollset_set_add_fd)(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set, grpc_fd *fd); void (*pollset_set_del_fd)(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set, grpc_fd *fd); grpc_error *(*kick_poller)(void); void (*shutdown_engine)(void); #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG grpc_workqueue *(*workqueue_ref)(grpc_workqueue *workqueue, const char *file, int line, const char *reason); void (*workqueue_unref)(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, const char *file, int line, const char *reason); #else grpc_workqueue *(*workqueue_ref)(grpc_workqueue *workqueue); void (*workqueue_unref)(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue); #endif grpc_closure_scheduler *(*workqueue_scheduler)(grpc_workqueue *workqueue); } grpc_event_engine_vtable; void grpc_event_engine_init(void); void grpc_event_engine_shutdown(void); /* Return the name of the poll strategy */ const char *grpc_get_poll_strategy_name(); /* Create a wrapped file descriptor. Requires fd is a non-blocking file descriptor. This takes ownership of closing fd. */ grpc_fd *grpc_fd_create(int fd, const char *name); /* Get a workqueue that's associated with this fd */ grpc_workqueue *grpc_fd_get_workqueue(grpc_fd *fd); /* Return the wrapped fd, or -1 if it has been released or closed. */ int grpc_fd_wrapped_fd(grpc_fd *fd); /* Releases fd to be asynchronously destroyed. on_done is called when the underlying file descriptor is definitely close()d. If on_done is NULL, no callback will be made. If release_fd is not NULL, it's set to fd and fd will not be closed. Requires: *fd initialized; no outstanding notify_on_read or notify_on_write. MUST NOT be called with a pollset lock taken */ void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done, int *release_fd, const char *reason); /* Has grpc_fd_shutdown been called on an fd? */ bool grpc_fd_is_shutdown(grpc_fd *fd); /* Cause any current and future callbacks to fail. */ void grpc_fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why); /* Register read interest, causing read_cb to be called once when fd becomes readable, on deadline specified by deadline, or on shutdown triggered by grpc_fd_shutdown. read_cb will be called with read_cb_arg when *fd becomes readable. read_cb is Called with status of GRPC_CALLBACK_SUCCESS if readable, GRPC_CALLBACK_TIMED_OUT if the call timed out, and CANCELLED if the call was cancelled. Requires:This method must not be called before the read_cb for any previous call runs. Edge triggered events are used whenever they are supported by the underlying platform. This means that users must drain fd in read_cb before calling notify_on_read again. Users are also expected to handle spurious events, i.e read_cb is called while nothing can be readable from fd */ void grpc_fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *closure); /* Exactly the same semantics as above, except based on writable events. */ void grpc_fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *closure); /* Return the read notifier pollset from the fd */ grpc_pollset *grpc_fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx, grpc_fd *fd); /* pollset_posix functions */ /* Add an fd to a pollset */ void grpc_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, struct grpc_fd *fd); /* pollset_set_posix functions */ void grpc_pollset_set_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set, grpc_fd *fd); void grpc_pollset_set_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set, grpc_fd *fd); /* override to allow tests to hook poll() usage */ typedef int (*grpc_poll_function_type)(struct pollfd *, nfds_t, int); extern grpc_poll_function_type grpc_poll_function; /* This should be used for testing purposes ONLY */ void grpc_set_event_engine_test_only(const grpc_event_engine_vtable *); #endif /* GRPC_CORE_LIB_IOMGR_EV_POSIX_H */ grpc-1.3.2/src/core/lib/iomgr/exec_ctx.c000066400000000000000000000101421310511640000200050ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/exec_ctx.h" #include #include #include #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/workqueue.h" #include "src/core/lib/profiling/timers.h" bool grpc_exec_ctx_ready_to_finish(grpc_exec_ctx *exec_ctx) { if ((exec_ctx->flags & GRPC_EXEC_CTX_FLAG_IS_FINISHED) == 0) { if (exec_ctx->check_ready_to_finish(exec_ctx, exec_ctx->check_ready_to_finish_arg)) { exec_ctx->flags |= GRPC_EXEC_CTX_FLAG_IS_FINISHED; return true; } return false; } else { return true; } } bool grpc_never_ready_to_finish(grpc_exec_ctx *exec_ctx, void *arg_ignored) { return false; } bool grpc_always_ready_to_finish(grpc_exec_ctx *exec_ctx, void *arg_ignored) { return true; } bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) { bool did_something = 0; GPR_TIMER_BEGIN("grpc_exec_ctx_flush", 0); for (;;) { if (!grpc_closure_list_empty(exec_ctx->closure_list)) { grpc_closure *c = exec_ctx->closure_list.head; exec_ctx->closure_list.head = exec_ctx->closure_list.tail = NULL; while (c != NULL) { grpc_closure *next = c->next_data.next; grpc_error *error = c->error_data.error; did_something = true; #ifndef NDEBUG c->scheduled = false; #endif c->cb(exec_ctx, c->cb_arg, error); GRPC_ERROR_UNREF(error); c = next; } } else if (!grpc_combiner_continue_exec_ctx(exec_ctx)) { break; } } GPR_ASSERT(exec_ctx->active_combiner == NULL); GPR_TIMER_END("grpc_exec_ctx_flush", 0); return did_something; } void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx) { exec_ctx->flags |= GRPC_EXEC_CTX_FLAG_IS_FINISHED; grpc_exec_ctx_flush(exec_ctx); } static void exec_ctx_run(grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_error *error) { #ifndef NDEBUG closure->scheduled = false; #endif closure->cb(exec_ctx, closure->cb_arg, error); GRPC_ERROR_UNREF(error); } static void exec_ctx_sched(grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_error *error) { grpc_closure_list_append(&exec_ctx->closure_list, closure, error); } void grpc_exec_ctx_global_init(void) {} void grpc_exec_ctx_global_shutdown(void) {} static const grpc_closure_scheduler_vtable exec_ctx_scheduler_vtable = { exec_ctx_run, exec_ctx_sched, "exec_ctx"}; static grpc_closure_scheduler exec_ctx_scheduler = {&exec_ctx_scheduler_vtable}; grpc_closure_scheduler *grpc_schedule_on_exec_ctx = &exec_ctx_scheduler; grpc-1.3.2/src/core/lib/iomgr/exec_ctx.h000066400000000000000000000124001310511640000200110ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_EXEC_CTX_H #define GRPC_CORE_LIB_IOMGR_EXEC_CTX_H #include "src/core/lib/iomgr/closure.h" /* #define GRPC_EXECUTION_CONTEXT_SANITIZER 1 */ /** A workqueue represents a list of work to be executed asynchronously. Forward declared here to avoid a circular dependency with workqueue.h. */ typedef struct grpc_workqueue grpc_workqueue; typedef struct grpc_combiner grpc_combiner; /* This exec_ctx is ready to return: either pre-populated, or cached as soon as the finish_check returns true */ #define GRPC_EXEC_CTX_FLAG_IS_FINISHED 1 /* The exec_ctx's thread is (potentially) owned by a call or channel: care should be given to not delete said call/channel from this exec_ctx */ #define GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP 2 /** Execution context. * A bag of data that collects information along a callstack. * Generally created at public API entry points, and passed down as * pointer to child functions that manipulate it. * * Specific responsibilities (this may grow in the future): * - track a list of work that needs to be delayed until the top of the * call stack (this provides a convenient mechanism to run callbacks * without worrying about locking issues) * - provide a decision maker (via grpc_exec_ctx_ready_to_finish) that provides * signal as to whether a borrowed thread should continue to do work or * should actively try to finish up and get this thread back to its owner * * CONVENTIONS: * - Instance of this must ALWAYS be constructed on the stack, never * heap allocated. * - Instances and pointers to them must always be called exec_ctx. * - Instances are always passed as the first argument to a function that * takes it, and always as a pointer (grpc_exec_ctx is never copied). */ struct grpc_exec_ctx { grpc_closure_list closure_list; /** currently active combiner: updated only via combiner.c */ grpc_combiner *active_combiner; /** last active combiner in the active combiner list */ grpc_combiner *last_combiner; uintptr_t flags; void *check_ready_to_finish_arg; bool (*check_ready_to_finish)(grpc_exec_ctx *exec_ctx, void *arg); }; /* initializer for grpc_exec_ctx: prefer to use GRPC_EXEC_CTX_INIT whenever possible */ #define GRPC_EXEC_CTX_INITIALIZER(flags, finish_check, finish_check_arg) \ { GRPC_CLOSURE_LIST_INIT, NULL, NULL, flags, finish_check_arg, finish_check } /* initialize an execution context at the top level of an API call into grpc (this is safe to use elsewhere, though possibly not as efficient) */ #define GRPC_EXEC_CTX_INIT \ GRPC_EXEC_CTX_INITIALIZER(GRPC_EXEC_CTX_FLAG_IS_FINISHED, NULL, NULL) extern grpc_closure_scheduler *grpc_schedule_on_exec_ctx; /** Flush any work that has been enqueued onto this grpc_exec_ctx. * Caller must guarantee that no interfering locks are held. * Returns true if work was performed, false otherwise. */ bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx); /** Finish any pending work for a grpc_exec_ctx. Must be called before * the instance is destroyed, or work may be lost. */ void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx); /** Returns true if we'd like to leave this execution context as soon as possible: useful for deciding whether to do something more or not depending on outside context */ bool grpc_exec_ctx_ready_to_finish(grpc_exec_ctx *exec_ctx); /** A finish check that is never ready to finish */ bool grpc_never_ready_to_finish(grpc_exec_ctx *exec_ctx, void *arg_ignored); /** A finish check that is always ready to finish */ bool grpc_always_ready_to_finish(grpc_exec_ctx *exec_ctx, void *arg_ignored); void grpc_exec_ctx_global_init(void); void grpc_exec_ctx_global_init(void); void grpc_exec_ctx_global_shutdown(void); #endif /* GRPC_CORE_LIB_IOMGR_EXEC_CTX_H */ grpc-1.3.2/src/core/lib/iomgr/executor.c000066400000000000000000000134131310511640000200450ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/executor.h" #include #include #include #include #include #include "src/core/lib/iomgr/exec_ctx.h" typedef struct grpc_executor_data { int busy; /**< is the thread currently running? */ int shutting_down; /**< has \a grpc_shutdown() been invoked? */ int pending_join; /**< has the thread finished but not been joined? */ grpc_closure_list closures; /**< collection of pending work */ gpr_thd_id tid; /**< thread id of the thread, only valid if \a busy or \a pending_join are true */ gpr_thd_options options; gpr_mu mu; } grpc_executor; static grpc_executor g_executor; void grpc_executor_init() { memset(&g_executor, 0, sizeof(grpc_executor)); gpr_mu_init(&g_executor.mu); g_executor.options = gpr_thd_options_default(); gpr_thd_options_set_joinable(&g_executor.options); } /* thread body */ static void closure_exec_thread_func(void *ignored) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; while (1) { gpr_mu_lock(&g_executor.mu); if (g_executor.shutting_down != 0) { gpr_mu_unlock(&g_executor.mu); break; } if (grpc_closure_list_empty(g_executor.closures)) { /* no more work, time to die */ GPR_ASSERT(g_executor.busy == 1); g_executor.busy = 0; gpr_mu_unlock(&g_executor.mu); break; } else { grpc_closure *c = g_executor.closures.head; grpc_closure_list_init(&g_executor.closures); gpr_mu_unlock(&g_executor.mu); while (c != NULL) { grpc_closure *next = c->next_data.next; grpc_error *error = c->error_data.error; #ifndef NDEBUG c->scheduled = false; #endif c->cb(&exec_ctx, c->cb_arg, error); GRPC_ERROR_UNREF(error); c = next; } grpc_exec_ctx_flush(&exec_ctx); } } grpc_exec_ctx_finish(&exec_ctx); } /* Spawn the thread if new work has arrived a no thread is up */ static void maybe_spawn_locked() { if (grpc_closure_list_empty(g_executor.closures) == 1) { return; } if (g_executor.shutting_down == 1) { return; } if (g_executor.busy != 0) { /* Thread still working. New work will be picked up by already running * thread. Not spawning anything. */ return; } else if (g_executor.pending_join != 0) { /* Pickup the remains of the previous incarnations of the thread. */ gpr_thd_join(g_executor.tid); g_executor.pending_join = 0; } /* All previous instances of the thread should have been joined at this point. * Spawn time! */ g_executor.busy = 1; GPR_ASSERT(gpr_thd_new(&g_executor.tid, closure_exec_thread_func, NULL, &g_executor.options)); g_executor.pending_join = 1; } static void executor_push(grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_error *error) { gpr_mu_lock(&g_executor.mu); if (g_executor.shutting_down == 0) { grpc_closure_list_append(&g_executor.closures, closure, error); maybe_spawn_locked(); } gpr_mu_unlock(&g_executor.mu); } void grpc_executor_shutdown(grpc_exec_ctx *exec_ctx) { int pending_join; gpr_mu_lock(&g_executor.mu); pending_join = g_executor.pending_join; g_executor.shutting_down = 1; gpr_mu_unlock(&g_executor.mu); /* we can release the lock at this point despite the access to the closure * list below because we aren't accepting new work */ /* Execute pending callbacks, some may be performing cleanups */ grpc_closure *c = g_executor.closures.head; grpc_closure_list_init(&g_executor.closures); while (c != NULL) { grpc_closure *next = c->next_data.next; grpc_error *error = c->error_data.error; #ifndef NDEBUG c->scheduled = false; #endif c->cb(exec_ctx, c->cb_arg, error); GRPC_ERROR_UNREF(error); c = next; } grpc_exec_ctx_flush(exec_ctx); GPR_ASSERT(grpc_closure_list_empty(g_executor.closures)); if (pending_join) { gpr_thd_join(g_executor.tid); } gpr_mu_destroy(&g_executor.mu); } static const grpc_closure_scheduler_vtable executor_vtable = { executor_push, executor_push, "executor"}; static grpc_closure_scheduler executor_scheduler = {&executor_vtable}; grpc_closure_scheduler *grpc_executor_scheduler = &executor_scheduler; grpc-1.3.2/src/core/lib/iomgr/executor.h000066400000000000000000000042021310511640000200460ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_EXECUTOR_H #define GRPC_CORE_LIB_IOMGR_EXECUTOR_H #include "src/core/lib/iomgr/closure.h" /** Initialize the global executor. * * This mechanism is meant to outsource work (grpc_closure instances) to a * thread, for those cases where blocking isn't an option but there isn't a * non-blocking solution available. */ void grpc_executor_init(); extern grpc_closure_scheduler *grpc_executor_scheduler; /** Shutdown the executor, running all pending work as part of the call */ void grpc_executor_shutdown(grpc_exec_ctx *exec_ctx); #endif /* GRPC_CORE_LIB_IOMGR_EXECUTOR_H */ grpc-1.3.2/src/core/lib/iomgr/iocp_windows.c000066400000000000000000000133121310511640000207110ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_WINSOCK_SOCKET #include #include #include #include #include #include "src/core/lib/iomgr/iocp_windows.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/socket_windows.h" #include "src/core/lib/iomgr/timer.h" static ULONG g_iocp_kick_token; static OVERLAPPED g_iocp_custom_overlap; static gpr_atm g_custom_events = 0; static HANDLE g_iocp; static DWORD deadline_to_millis_timeout(gpr_timespec deadline, gpr_timespec now) { gpr_timespec timeout; static const int64_t max_spin_polling_us = 10; if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) == 0) { return INFINITE; } if (gpr_time_cmp(deadline, gpr_time_add(now, gpr_time_from_micros( max_spin_polling_us, GPR_TIMESPAN))) <= 0) { return 0; } timeout = gpr_time_sub(deadline, now); return (DWORD)gpr_time_to_millis(gpr_time_add( timeout, gpr_time_from_nanos(GPR_NS_PER_MS - 1, GPR_TIMESPAN))); } grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx, gpr_timespec deadline) { BOOL success; DWORD bytes = 0; DWORD flags = 0; ULONG_PTR completion_key; LPOVERLAPPED overlapped; grpc_winsocket *socket; grpc_winsocket_callback_info *info; success = GetQueuedCompletionStatus( g_iocp, &bytes, &completion_key, &overlapped, deadline_to_millis_timeout(deadline, gpr_now(deadline.clock_type))); if (success == 0 && overlapped == NULL) { return GRPC_IOCP_WORK_TIMEOUT; } GPR_ASSERT(completion_key && overlapped); if (overlapped == &g_iocp_custom_overlap) { gpr_atm_full_fetch_add(&g_custom_events, -1); if (completion_key == (ULONG_PTR)&g_iocp_kick_token) { /* We were awoken from a kick. */ return GRPC_IOCP_WORK_KICK; } gpr_log(GPR_ERROR, "Unknown custom completion key."); abort(); } socket = (grpc_winsocket *)completion_key; if (overlapped == &socket->write_info.overlapped) { info = &socket->write_info; } else if (overlapped == &socket->read_info.overlapped) { info = &socket->read_info; } else { abort(); } success = WSAGetOverlappedResult(socket->socket, &info->overlapped, &bytes, FALSE, &flags); info->bytes_transfered = bytes; info->wsa_error = success ? 0 : WSAGetLastError(); GPR_ASSERT(overlapped == &info->overlapped); grpc_socket_become_ready(exec_ctx, socket, info); return GRPC_IOCP_WORK_WORK; } void grpc_iocp_init(void) { g_iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (ULONG_PTR)NULL, 0); GPR_ASSERT(g_iocp); } void grpc_iocp_kick(void) { BOOL success; gpr_atm_full_fetch_add(&g_custom_events, 1); success = PostQueuedCompletionStatus(g_iocp, 0, (ULONG_PTR)&g_iocp_kick_token, &g_iocp_custom_overlap); GPR_ASSERT(success); } void grpc_iocp_flush(void) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_iocp_work_status work_status; do { work_status = grpc_iocp_work(&exec_ctx, gpr_inf_past(GPR_CLOCK_MONOTONIC)); } while (work_status == GRPC_IOCP_WORK_KICK || grpc_exec_ctx_flush(&exec_ctx)); } void grpc_iocp_shutdown(void) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; while (gpr_atm_acq_load(&g_custom_events)) { grpc_iocp_work(&exec_ctx, gpr_inf_future(GPR_CLOCK_MONOTONIC)); grpc_exec_ctx_flush(&exec_ctx); } grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(CloseHandle(g_iocp)); } void grpc_iocp_add_socket(grpc_winsocket *socket) { HANDLE ret; if (socket->added_to_iocp) return; ret = CreateIoCompletionPort((HANDLE)socket->socket, g_iocp, (uintptr_t)socket, 0); if (!ret) { char *utf8_message = gpr_format_message(WSAGetLastError()); gpr_log(GPR_ERROR, "Unable to add socket to iocp: %s", utf8_message); gpr_free(utf8_message); __debugbreak(); abort(); } socket->added_to_iocp = 1; GPR_ASSERT(ret == g_iocp); } #endif /* GRPC_WINSOCK_SOCKET */ grpc-1.3.2/src/core/lib/iomgr/iocp_windows.h000066400000000000000000000042031310511640000207150ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_IOCP_WINDOWS_H #define GRPC_CORE_LIB_IOMGR_IOCP_WINDOWS_H #include #include "src/core/lib/iomgr/socket_windows.h" typedef enum { GRPC_IOCP_WORK_WORK, GRPC_IOCP_WORK_TIMEOUT, GRPC_IOCP_WORK_KICK } grpc_iocp_work_status; grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx, gpr_timespec deadline); void grpc_iocp_init(void); void grpc_iocp_kick(void); void grpc_iocp_flush(void); void grpc_iocp_shutdown(void); void grpc_iocp_add_socket(grpc_winsocket *); #endif /* GRPC_CORE_LIB_IOMGR_IOCP_WINDOWS_H */ grpc-1.3.2/src/core/lib/iomgr/iomgr.c000066400000000000000000000140611310511640000173240ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/iomgr.h" #include #include #include #include #include #include #include #include #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/network_status_tracker.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" static gpr_mu g_mu; static gpr_cv g_rcv; static int g_shutdown; static grpc_iomgr_object g_root_object; void grpc_iomgr_init(void) { g_shutdown = 0; gpr_mu_init(&g_mu); gpr_cv_init(&g_rcv); grpc_exec_ctx_global_init(); grpc_timer_list_init(gpr_now(GPR_CLOCK_MONOTONIC)); g_root_object.next = g_root_object.prev = &g_root_object; g_root_object.name = "root"; grpc_network_status_init(); grpc_iomgr_platform_init(); } static size_t count_objects(void) { grpc_iomgr_object *obj; size_t n = 0; for (obj = g_root_object.next; obj != &g_root_object; obj = obj->next) { n++; } return n; } static void dump_objects(const char *kind) { grpc_iomgr_object *obj; for (obj = g_root_object.next; obj != &g_root_object; obj = obj->next) { gpr_log(GPR_DEBUG, "%s OBJECT: %s %p", kind, obj->name, obj); } } void grpc_iomgr_shutdown(grpc_exec_ctx *exec_ctx) { gpr_timespec shutdown_deadline = gpr_time_add( gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(10, GPR_TIMESPAN)); gpr_timespec last_warning_time = gpr_now(GPR_CLOCK_REALTIME); grpc_iomgr_platform_flush(); gpr_mu_lock(&g_mu); g_shutdown = 1; while (g_root_object.next != &g_root_object) { if (gpr_time_cmp( gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), last_warning_time), gpr_time_from_seconds(1, GPR_TIMESPAN)) >= 0) { if (g_root_object.next != &g_root_object) { gpr_log(GPR_DEBUG, "Waiting for %" PRIuPTR " iomgr objects to be destroyed", count_objects()); } last_warning_time = gpr_now(GPR_CLOCK_REALTIME); } if (grpc_timer_check(exec_ctx, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL)) { gpr_mu_unlock(&g_mu); grpc_exec_ctx_flush(exec_ctx); grpc_iomgr_platform_flush(); gpr_mu_lock(&g_mu); continue; } if (g_root_object.next != &g_root_object) { if (grpc_iomgr_abort_on_leaks()) { gpr_log(GPR_DEBUG, "Failed to free %" PRIuPTR " iomgr objects before shutdown deadline: " "memory leaks are likely", count_objects()); dump_objects("LEAKED"); abort(); } gpr_timespec short_deadline = gpr_time_add( gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(100, GPR_TIMESPAN)); if (gpr_cv_wait(&g_rcv, &g_mu, short_deadline)) { if (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), shutdown_deadline) > 0) { if (g_root_object.next != &g_root_object) { gpr_log(GPR_DEBUG, "Failed to free %" PRIuPTR " iomgr objects before shutdown deadline: " "memory leaks are likely", count_objects()); dump_objects("LEAKED"); } break; } } } } gpr_mu_unlock(&g_mu); grpc_timer_list_shutdown(exec_ctx); grpc_exec_ctx_flush(exec_ctx); /* ensure all threads have left g_mu */ gpr_mu_lock(&g_mu); gpr_mu_unlock(&g_mu); grpc_iomgr_platform_shutdown(); grpc_exec_ctx_global_shutdown(); grpc_network_status_shutdown(); gpr_mu_destroy(&g_mu); gpr_cv_destroy(&g_rcv); } void grpc_iomgr_register_object(grpc_iomgr_object *obj, const char *name) { obj->name = gpr_strdup(name); gpr_mu_lock(&g_mu); obj->next = &g_root_object; obj->prev = g_root_object.prev; obj->next->prev = obj->prev->next = obj; gpr_mu_unlock(&g_mu); } void grpc_iomgr_unregister_object(grpc_iomgr_object *obj) { gpr_mu_lock(&g_mu); obj->next->prev = obj->prev; obj->prev->next = obj->next; gpr_cv_signal(&g_rcv); gpr_mu_unlock(&g_mu); gpr_free(obj->name); } bool grpc_iomgr_abort_on_leaks(void) { char *env = gpr_getenv("GRPC_ABORT_ON_LEAKS"); if (env == NULL) return false; static const char *truthy[] = {"yes", "Yes", "YES", "true", "True", "TRUE", "1"}; bool should_we = false; for (size_t i = 0; i < GPR_ARRAY_SIZE(truthy); i++) { if (0 == strcmp(env, truthy[i])) should_we = true; } gpr_free(env); return should_we; } grpc-1.3.2/src/core/lib/iomgr/iomgr.h000066400000000000000000000036621310511640000173360ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_IOMGR_H #define GRPC_CORE_LIB_IOMGR_IOMGR_H #include #include "src/core/lib/iomgr/port.h" /** Initializes the iomgr. */ void grpc_iomgr_init(void); /** Signals the intention to shutdown the iomgr. Expects to be able to flush * exec_ctx. */ void grpc_iomgr_shutdown(grpc_exec_ctx *exec_ctx); #endif /* GRPC_CORE_LIB_IOMGR_IOMGR_H */ grpc-1.3.2/src/core/lib/iomgr/iomgr_internal.h000066400000000000000000000044121310511640000212240ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_IOMGR_INTERNAL_H #define GRPC_CORE_LIB_IOMGR_IOMGR_INTERNAL_H #include #include "src/core/lib/iomgr/iomgr.h" typedef struct grpc_iomgr_object { char *name; struct grpc_iomgr_object *next; struct grpc_iomgr_object *prev; } grpc_iomgr_object; void grpc_iomgr_register_object(grpc_iomgr_object *obj, const char *name); void grpc_iomgr_unregister_object(grpc_iomgr_object *obj); void grpc_iomgr_platform_init(void); /** flush any globally queued work from iomgr */ void grpc_iomgr_platform_flush(void); /** tear down all platform specific global iomgr structures */ void grpc_iomgr_platform_shutdown(void); bool grpc_iomgr_abort_on_leaks(void); #endif /* GRPC_CORE_LIB_IOMGR_IOMGR_INTERNAL_H */ grpc-1.3.2/src/core/lib/iomgr/iomgr_posix.c000066400000000000000000000041251310511640000205460ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_POSIX_SOCKET #include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/iomgr_posix.h" #include "src/core/lib/iomgr/tcp_posix.h" void grpc_iomgr_platform_init(void) { grpc_wakeup_fd_global_init(); grpc_event_engine_init(); grpc_register_tracer("tcp", &grpc_tcp_trace); } void grpc_iomgr_platform_flush(void) {} void grpc_iomgr_platform_shutdown(void) { grpc_event_engine_shutdown(); grpc_wakeup_fd_global_destroy(); } #endif /* GRPC_POSIX_SOCKET */ grpc-1.3.2/src/core/lib/iomgr/iomgr_posix.h000066400000000000000000000033261310511640000205550ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_IOMGR_POSIX_H #define GRPC_CORE_LIB_IOMGR_IOMGR_POSIX_H #include "src/core/lib/iomgr/iomgr_internal.h" #endif /* GRPC_CORE_LIB_IOMGR_IOMGR_POSIX_H */ grpc-1.3.2/src/core/lib/iomgr/iomgr_uv.c000066400000000000000000000037211310511640000200370ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_UV #include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/pollset_uv.h" #include "src/core/lib/iomgr/tcp_uv.h" void grpc_iomgr_platform_init(void) { grpc_pollset_global_init(); grpc_register_tracer("tcp", &grpc_tcp_trace); } void grpc_iomgr_platform_flush(void) {} void grpc_iomgr_platform_shutdown(void) { grpc_pollset_global_shutdown(); } #endif /* GRPC_UV */ grpc-1.3.2/src/core/lib/iomgr/iomgr_windows.c000066400000000000000000000051261310511640000211000ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_WINSOCK_SOCKET #include "src/core/lib/iomgr/sockaddr_windows.h" #include #include "src/core/lib/iomgr/iocp_windows.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/pollset_windows.h" #include "src/core/lib/iomgr/socket_windows.h" /* Windows' io manager is going to be fully designed using IO completion ports. All of what we're doing here is basically make sure that Windows sockets are initialized in and out. */ static void winsock_init(void) { WSADATA wsaData; int status = WSAStartup(MAKEWORD(2, 0), &wsaData); GPR_ASSERT(status == 0); } static void winsock_shutdown(void) { int status = WSACleanup(); GPR_ASSERT(status == 0); } void grpc_iomgr_platform_init(void) { winsock_init(); grpc_iocp_init(); grpc_pollset_global_init(); } void grpc_iomgr_platform_flush(void) { grpc_iocp_flush(); } void grpc_iomgr_platform_shutdown(void) { grpc_pollset_global_shutdown(); grpc_iocp_shutdown(); winsock_shutdown(); } #endif /* GRPC_WINSOCK_SOCKET */ grpc-1.3.2/src/core/lib/iomgr/load_file.c000066400000000000000000000065361310511640000201350ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/load_file.h" #include #include #include #include #include #include "src/core/lib/support/block_annotate.h" #include "src/core/lib/support/string.h" grpc_error *grpc_load_file(const char *filename, int add_null_terminator, grpc_slice *output) { unsigned char *contents = NULL; size_t contents_size = 0; grpc_slice result = grpc_empty_slice(); FILE *file; size_t bytes_read = 0; grpc_error *error = GRPC_ERROR_NONE; GRPC_SCHEDULING_START_BLOCKING_REGION; file = fopen(filename, "rb"); if (file == NULL) { error = GRPC_OS_ERROR(errno, "fopen"); goto end; } fseek(file, 0, SEEK_END); /* Converting to size_t on the assumption that it will not fail */ contents_size = (size_t)ftell(file); fseek(file, 0, SEEK_SET); contents = gpr_malloc(contents_size + (add_null_terminator ? 1 : 0)); bytes_read = fread(contents, 1, contents_size, file); if (bytes_read < contents_size) { error = GRPC_OS_ERROR(errno, "fread"); GPR_ASSERT(ferror(file)); goto end; } if (add_null_terminator) { contents[contents_size++] = 0; } result = grpc_slice_new(contents, contents_size, gpr_free); end: *output = result; if (file != NULL) fclose(file); if (error != GRPC_ERROR_NONE) { grpc_error *error_out = grpc_error_set_str(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Failed to load file", &error, 1), GRPC_ERROR_STR_FILENAME, grpc_slice_from_copied_string( filename)); // TODO(ncteisen), always static? GRPC_ERROR_UNREF(error); error = error_out; } GRPC_SCHEDULING_END_BLOCKING_REGION; return error; } grpc-1.3.2/src/core/lib/iomgr/load_file.h000066400000000000000000000040421310511640000201300ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_LOAD_FILE_H #define GRPC_CORE_LIB_IOMGR_LOAD_FILE_H #include #include #include "src/core/lib/iomgr/error.h" #ifdef __cplusplus extern "C" { #endif /* Loads the content of a file into a slice. add_null_terminator will add a NULL terminator if non-zero. */ grpc_error *grpc_load_file(const char *filename, int add_null_terminator, grpc_slice *slice); #ifdef __cplusplus } #endif #endif /* GRPC_CORE_LIB_IOMGR_LOAD_FILE_H */ grpc-1.3.2/src/core/lib/iomgr/lockfree_event.c000066400000000000000000000216271310511640000212100ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/lockfree_event.h" #include /* 'state' holds the to call when the fd is readable or writable respectively. It can contain one of the following values: CLOSURE_READY : The fd has an I/O event of interest but there is no closure yet to execute CLOSURE_NOT_READY : The fd has no I/O event of interest closure ptr : The closure to be executed when the fd has an I/O event of interest shutdown_error | FD_SHUTDOWN_BIT : 'shutdown_error' field ORed with FD_SHUTDOWN_BIT. This indicates that the fd is shutdown. Since all memory allocations are word-aligned, the lower two bits of the shutdown_error pointer are always 0. So it is safe to OR these with FD_SHUTDOWN_BIT Valid state transitions: <-----3------ CLOSURE_NOT_READY ----1----> CLOSURE_READY | | ^ | ^ | | | | | | | | | | +--------------4----------+ 6 +---------2---------------+ | | | | | v | +-----5-------> [shutdown_error | FD_SHUTDOWN_BIT] <----7---------+ For 1, 4 : See grpc_lfev_set_ready() function For 2, 3 : See grpc_lfev_notify_on() function For 5,6,7: See grpc_lfev_set_shutdown() function */ #define CLOSURE_NOT_READY ((gpr_atm)0) #define CLOSURE_READY ((gpr_atm)2) #define FD_SHUTDOWN_BIT ((gpr_atm)1) void grpc_lfev_init(gpr_atm *state) { gpr_atm_no_barrier_store(state, CLOSURE_NOT_READY); } void grpc_lfev_destroy(gpr_atm *state) { gpr_atm curr = gpr_atm_no_barrier_load(state); if (curr & FD_SHUTDOWN_BIT) { GRPC_ERROR_UNREF((grpc_error *)(curr & ~FD_SHUTDOWN_BIT)); } else { GPR_ASSERT(curr == CLOSURE_NOT_READY || curr == CLOSURE_READY); } } bool grpc_lfev_is_shutdown(gpr_atm *state) { gpr_atm curr = gpr_atm_no_barrier_load(state); return (curr & FD_SHUTDOWN_BIT) != 0; } void grpc_lfev_notify_on(grpc_exec_ctx *exec_ctx, gpr_atm *state, grpc_closure *closure) { while (true) { gpr_atm curr = gpr_atm_no_barrier_load(state); switch (curr) { case CLOSURE_NOT_READY: { /* CLOSURE_NOT_READY -> . We're guaranteed by API that there's an acquire barrier before here, so there's no need to double-dip and this can be a release-only. The release itself pairs with the acquire half of a set_ready full barrier. */ if (gpr_atm_rel_cas(state, CLOSURE_NOT_READY, (gpr_atm)closure)) { return; /* Successful. Return */ } break; /* retry */ } case CLOSURE_READY: { /* Change the state to CLOSURE_NOT_READY. Schedule the closure if successful. If not, the state most likely transitioned to shutdown. We should retry. This can be a no-barrier cas since the state is being transitioned to CLOSURE_NOT_READY; set_ready and set_shutdown do not schedule any closure when transitioning out of CLOSURE_NO_READY state (i.e there is no other code that needs to 'happen-after' this) */ if (gpr_atm_no_barrier_cas(state, CLOSURE_READY, CLOSURE_NOT_READY)) { grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_NONE); return; /* Successful. Return */ } break; /* retry */ } default: { /* 'curr' is either a closure or the fd is shutdown(in which case 'curr' contains a pointer to the shutdown-error). If the fd is shutdown, schedule the closure with the shutdown error */ if ((curr & FD_SHUTDOWN_BIT) > 0) { grpc_error *shutdown_err = (grpc_error *)(curr & ~FD_SHUTDOWN_BIT); grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "FD Shutdown", &shutdown_err, 1)); return; } /* There is already a closure!. This indicates a bug in the code */ gpr_log(GPR_ERROR, "notify_on called with a previous callback still pending"); abort(); } } } GPR_UNREACHABLE_CODE(return ); } bool grpc_lfev_set_shutdown(grpc_exec_ctx *exec_ctx, gpr_atm *state, grpc_error *shutdown_err) { gpr_atm new_state = (gpr_atm)shutdown_err | FD_SHUTDOWN_BIT; while (true) { gpr_atm curr = gpr_atm_no_barrier_load(state); switch (curr) { case CLOSURE_READY: case CLOSURE_NOT_READY: /* Need a full barrier here so that the initial load in notify_on doesn't need a barrier */ if (gpr_atm_full_cas(state, curr, new_state)) { return true; /* early out */ } break; /* retry */ default: { /* 'curr' is either a closure or the fd is already shutdown */ /* If fd is already shutdown, we are done */ if ((curr & FD_SHUTDOWN_BIT) > 0) { GRPC_ERROR_UNREF(shutdown_err); return false; } /* Fd is not shutdown. Schedule the closure and move the state to shutdown state. Needs an acquire to pair with setting the closure (and get a happens-after on that edge), and a release to pair with anything loading the shutdown state. */ if (gpr_atm_full_cas(state, curr, new_state)) { grpc_closure_sched(exec_ctx, (grpc_closure *)curr, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "FD Shutdown", &shutdown_err, 1)); return true; } /* 'curr' was a closure but now changed to a different state. We will have to retry */ break; } } } GPR_UNREACHABLE_CODE(return false); } void grpc_lfev_set_ready(grpc_exec_ctx *exec_ctx, gpr_atm *state) { while (true) { gpr_atm curr = gpr_atm_no_barrier_load(state); switch (curr) { case CLOSURE_READY: { /* Already ready. We are done here */ return; } case CLOSURE_NOT_READY: { /* No barrier required as we're transitioning to a state that does not involve a closure */ if (gpr_atm_no_barrier_cas(state, CLOSURE_NOT_READY, CLOSURE_READY)) { return; /* early out */ } break; /* retry */ } default: { /* 'curr' is either a closure or the fd is shutdown */ if ((curr & FD_SHUTDOWN_BIT) > 0) { /* The fd is shutdown. Do nothing */ return; } /* Full cas: acquire pairs with this cas' release in the event of a spurious set_ready; release pairs with this or the acquire in notify_on (or set_shutdown) */ else if (gpr_atm_full_cas(state, curr, CLOSURE_NOT_READY)) { grpc_closure_sched(exec_ctx, (grpc_closure *)curr, GRPC_ERROR_NONE); return; } /* else the state changed again (only possible by either a racing set_ready or set_shutdown functions. In both these cases, the closure would have been scheduled for execution. So we are done here */ return; } } } } grpc-1.3.2/src/core/lib/iomgr/lockfree_event.h000066400000000000000000000044161310511640000212120ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_LOCKFREE_EVENT_H #define GRPC_CORE_LIB_IOMGR_LOCKFREE_EVENT_H /* Lock free event notification for file descriptors */ #include #include "src/core/lib/iomgr/exec_ctx.h" void grpc_lfev_init(gpr_atm *state); void grpc_lfev_destroy(gpr_atm *state); bool grpc_lfev_is_shutdown(gpr_atm *state); void grpc_lfev_notify_on(grpc_exec_ctx *exec_ctx, gpr_atm *state, grpc_closure *closure); /* Returns true on first successful shutdown */ bool grpc_lfev_set_shutdown(grpc_exec_ctx *exec_ctx, gpr_atm *state, grpc_error *shutdown_err); void grpc_lfev_set_ready(grpc_exec_ctx *exec_ctx, gpr_atm *state); #endif /* GRPC_CORE_LIB_IOMGR_LOCKFREE_EVENT_H */ grpc-1.3.2/src/core/lib/iomgr/network_status_tracker.c000066400000000000000000000037531310511640000230240ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/endpoint.h" void grpc_network_status_shutdown(void) {} void grpc_network_status_init(void) { // TODO(makarandd): Install callback with OS to monitor network status. } void grpc_destroy_network_status_monitor() {} void grpc_network_status_register_endpoint(grpc_endpoint *ep) { (void)ep; } void grpc_network_status_unregister_endpoint(grpc_endpoint *ep) { (void)ep; } void grpc_network_status_shutdown_all_endpoints() {} grpc-1.3.2/src/core/lib/iomgr/network_status_tracker.h000066400000000000000000000037631310511640000230320ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_NETWORK_STATUS_TRACKER_H #define GRPC_CORE_LIB_IOMGR_NETWORK_STATUS_TRACKER_H #include "src/core/lib/iomgr/endpoint.h" void grpc_network_status_init(void); void grpc_network_status_shutdown(void); void grpc_network_status_register_endpoint(grpc_endpoint *ep); void grpc_network_status_unregister_endpoint(grpc_endpoint *ep); void grpc_network_status_shutdown_all_endpoints(); #endif /* GRPC_CORE_LIB_IOMGR_NETWORK_STATUS_TRACKER_H */ grpc-1.3.2/src/core/lib/iomgr/polling_entity.c000066400000000000000000000077101310511640000212520ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include "src/core/lib/iomgr/polling_entity.h" grpc_polling_entity grpc_polling_entity_create_from_pollset_set( grpc_pollset_set *pollset_set) { grpc_polling_entity pollent; pollent.pollent.pollset_set = pollset_set; pollent.tag = POPS_POLLSET_SET; return pollent; } grpc_polling_entity grpc_polling_entity_create_from_pollset( grpc_pollset *pollset) { grpc_polling_entity pollent; pollent.pollent.pollset = pollset; pollent.tag = POPS_POLLSET; return pollent; } grpc_pollset *grpc_polling_entity_pollset(grpc_polling_entity *pollent) { if (pollent->tag == POPS_POLLSET) { return pollent->pollent.pollset; } return NULL; } grpc_pollset_set *grpc_polling_entity_pollset_set( grpc_polling_entity *pollent) { if (pollent->tag == POPS_POLLSET_SET) { return pollent->pollent.pollset_set; } return NULL; } bool grpc_polling_entity_is_empty(const grpc_polling_entity *pollent) { return pollent->tag == POPS_NONE; } void grpc_polling_entity_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_polling_entity *pollent, grpc_pollset_set *pss_dst) { if (pollent->tag == POPS_POLLSET) { GPR_ASSERT(pollent->pollent.pollset != NULL); grpc_pollset_set_add_pollset(exec_ctx, pss_dst, pollent->pollent.pollset); } else if (pollent->tag == POPS_POLLSET_SET) { GPR_ASSERT(pollent->pollent.pollset_set != NULL); grpc_pollset_set_add_pollset_set(exec_ctx, pss_dst, pollent->pollent.pollset_set); } else { gpr_log(GPR_ERROR, "Invalid grpc_polling_entity tag '%d'", pollent->tag); abort(); } } void grpc_polling_entity_del_from_pollset_set(grpc_exec_ctx *exec_ctx, grpc_polling_entity *pollent, grpc_pollset_set *pss_dst) { if (pollent->tag == POPS_POLLSET) { GPR_ASSERT(pollent->pollent.pollset != NULL); grpc_pollset_set_del_pollset(exec_ctx, pss_dst, pollent->pollent.pollset); } else if (pollent->tag == POPS_POLLSET_SET) { GPR_ASSERT(pollent->pollent.pollset_set != NULL); grpc_pollset_set_del_pollset_set(exec_ctx, pss_dst, pollent->pollent.pollset_set); } else { gpr_log(GPR_ERROR, "Invalid grpc_polling_entity tag '%d'", pollent->tag); abort(); } } grpc-1.3.2/src/core/lib/iomgr/polling_entity.h000066400000000000000000000065741310511640000212660ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_POLLING_ENTITY_H #define GRPC_CORE_LIB_IOMGR_POLLING_ENTITY_H #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/pollset_set.h" /* A grpc_polling_entity is a pollset-or-pollset_set container. It allows * functions that * accept a pollset XOR a pollset_set to do so through an abstract interface. * No ownership is taken. */ typedef struct grpc_polling_entity { union { grpc_pollset *pollset; grpc_pollset_set *pollset_set; } pollent; enum pops_tag { POPS_NONE, POPS_POLLSET, POPS_POLLSET_SET } tag; } grpc_polling_entity; grpc_polling_entity grpc_polling_entity_create_from_pollset_set( grpc_pollset_set *pollset_set); grpc_polling_entity grpc_polling_entity_create_from_pollset( grpc_pollset *pollset); /** If \a pollent contains a pollset, return it. Otherwise, return NULL */ grpc_pollset *grpc_polling_entity_pollset(grpc_polling_entity *pollent); /** If \a pollent contains a pollset_set, return it. Otherwise, return NULL */ grpc_pollset_set *grpc_polling_entity_pollset_set(grpc_polling_entity *pollent); bool grpc_polling_entity_is_empty(const grpc_polling_entity *pollent); /** Add the pollset or pollset_set in \a pollent to the destination pollset_set * \a * pss_dst */ void grpc_polling_entity_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_polling_entity *pollent, grpc_pollset_set *pss_dst); /** Delete the pollset or pollset_set in \a pollent from the destination * pollset_set \a * pss_dst */ void grpc_polling_entity_del_from_pollset_set(grpc_exec_ctx *exec_ctx, grpc_polling_entity *pollent, grpc_pollset_set *pss_dst); /* pollset_set specific */ #endif /* GRPC_CORE_LIB_IOMGR_POLLING_ENTITY_H */ grpc-1.3.2/src/core/lib/iomgr/pollset.h000066400000000000000000000104401310511640000176730ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_POLLSET_H #define GRPC_CORE_LIB_IOMGR_POLLSET_H #include #include #include #include "src/core/lib/iomgr/exec_ctx.h" #define GRPC_POLLSET_KICK_BROADCAST ((grpc_pollset_worker *)1) /* A grpc_pollset is a set of file descriptors that a higher level item is interested in. For example: - a server will typically keep a pollset containing all connected channels, so that it can find new calls to service - a completion queue might keep a pollset with an entry for each transport that is servicing a call that it's tracking */ typedef struct grpc_pollset grpc_pollset; typedef struct grpc_pollset_worker grpc_pollset_worker; size_t grpc_pollset_size(void); /* Initialize a pollset: assumes *pollset contains all zeros */ void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu); /* Begin shutting down the pollset, and call closure when done. * pollset's mutex must be held */ void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_closure *closure); void grpc_pollset_destroy(grpc_pollset *pollset); /* Do some work on a pollset. May involve invoking asynchronous callbacks, or actually polling file descriptors. Requires pollset's mutex locked. May unlock its mutex during its execution. worker is a (platform-specific) handle that can be used to wake up from grpc_pollset_work before any events are received and before the timeout has expired. It is both initialized and destroyed by grpc_pollset_work. Initialization of worker is guaranteed to occur BEFORE the pollset's mutex is released for the first time by grpc_pollset_work and it is guaranteed that it will not be released by grpc_pollset_work AFTER worker has been destroyed. It's legal for worker to be NULL: in that case, this specific thread can not be directly woken with a kick, but maybe be indirectly (with a kick against the pollset as a whole). Tries not to block past deadline. May call grpc_closure_list_run on grpc_closure_list, without holding the pollset lock */ grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker **worker, gpr_timespec now, gpr_timespec deadline) GRPC_MUST_USE_RESULT; /* Break one polling thread out of polling work for this pollset. If specific_worker is GRPC_POLLSET_KICK_BROADCAST, kick ALL the workers. Otherwise, if specific_worker is non-NULL, then kick that worker. */ grpc_error *grpc_pollset_kick(grpc_pollset *pollset, grpc_pollset_worker *specific_worker) GRPC_MUST_USE_RESULT; #endif /* GRPC_CORE_LIB_IOMGR_POLLSET_H */ grpc-1.3.2/src/core/lib/iomgr/pollset_set.h000066400000000000000000000056471310511640000205630ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_POLLSET_SET_H #define GRPC_CORE_LIB_IOMGR_POLLSET_SET_H #include "src/core/lib/iomgr/pollset.h" /* A grpc_pollset_set is a set of pollsets that are interested in an action. Adding a pollset to a pollset_set automatically adds any fd's (etc) that have been registered with the set_set to that pollset. Registering fd's automatically adds them to all current pollsets. */ typedef struct grpc_pollset_set grpc_pollset_set; grpc_pollset_set *grpc_pollset_set_create(void); void grpc_pollset_set_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set); void grpc_pollset_set_add_pollset(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set, grpc_pollset *pollset); void grpc_pollset_set_del_pollset(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set, grpc_pollset *pollset); void grpc_pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx, grpc_pollset_set *bag, grpc_pollset_set *item); void grpc_pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx, grpc_pollset_set *bag, grpc_pollset_set *item); #endif /* GRPC_CORE_LIB_IOMGR_POLLSET_SET_H */ grpc-1.3.2/src/core/lib/iomgr/pollset_set_uv.c000066400000000000000000000051511310511640000212560ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_UV #include "src/core/lib/iomgr/pollset_set.h" grpc_pollset_set* grpc_pollset_set_create(void) { return (grpc_pollset_set*)((intptr_t)0xdeafbeef); } void grpc_pollset_set_destroy(grpc_exec_ctx* exec_ctx, grpc_pollset_set* pollset_set) {} void grpc_pollset_set_add_pollset(grpc_exec_ctx* exec_ctx, grpc_pollset_set* pollset_set, grpc_pollset* pollset) {} void grpc_pollset_set_del_pollset(grpc_exec_ctx* exec_ctx, grpc_pollset_set* pollset_set, grpc_pollset* pollset) {} void grpc_pollset_set_add_pollset_set(grpc_exec_ctx* exec_ctx, grpc_pollset_set* bag, grpc_pollset_set* item) {} void grpc_pollset_set_del_pollset_set(grpc_exec_ctx* exec_ctx, grpc_pollset_set* bag, grpc_pollset_set* item) {} #endif /* GRPC_UV */ grpc-1.3.2/src/core/lib/iomgr/pollset_set_windows.c000066400000000000000000000052351310511640000223210ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "src/core/lib/iomgr/port.h" #ifdef GRPC_WINSOCK_SOCKET #include "src/core/lib/iomgr/pollset_set_windows.h" grpc_pollset_set* grpc_pollset_set_create(void) { return (grpc_pollset_set*)((intptr_t)0xdeafbeef); } void grpc_pollset_set_destroy(grpc_exec_ctx* exec_ctx, grpc_pollset_set* pollset_set) {} void grpc_pollset_set_add_pollset(grpc_exec_ctx* exec_ctx, grpc_pollset_set* pollset_set, grpc_pollset* pollset) {} void grpc_pollset_set_del_pollset(grpc_exec_ctx* exec_ctx, grpc_pollset_set* pollset_set, grpc_pollset* pollset) {} void grpc_pollset_set_add_pollset_set(grpc_exec_ctx* exec_ctx, grpc_pollset_set* bag, grpc_pollset_set* item) {} void grpc_pollset_set_del_pollset_set(grpc_exec_ctx* exec_ctx, grpc_pollset_set* bag, grpc_pollset_set* item) {} #endif /* GRPC_WINSOCK_SOCKET */ grpc-1.3.2/src/core/lib/iomgr/pollset_set_windows.h000066400000000000000000000033531310511640000223250ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_POLLSET_SET_WINDOWS_H #define GRPC_CORE_LIB_IOMGR_POLLSET_SET_WINDOWS_H #include "src/core/lib/iomgr/pollset_set.h" #endif /* GRPC_CORE_LIB_IOMGR_POLLSET_SET_WINDOWS_H */ grpc-1.3.2/src/core/lib/iomgr/pollset_uv.c000066400000000000000000000125601310511640000204050ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_UV #include #include #include #include #include #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/pollset_uv.h" struct grpc_pollset { uv_timer_t timer; int shutting_down; }; /* Indicates that grpc_pollset_work should run an iteration of the UV loop before running callbacks. This defaults to 1, and should be disabled if grpc_pollset_work will be called within the callstack of uv_run */ int grpc_pollset_work_run_loop; gpr_mu grpc_polling_mu; /* This is used solely to kick the uv loop, by setting a callback to be run immediately in the next loop iteration. Note: In the future, if there is a bug that involves missing wakeups in the future, try adding a uv_async_t to kick the loop differently */ uv_timer_t *dummy_uv_handle; size_t grpc_pollset_size() { return sizeof(grpc_pollset); } void dummy_timer_cb(uv_timer_t *handle) {} void dummy_handle_close_cb(uv_handle_t *handle) { gpr_free(handle); } void grpc_pollset_global_init(void) { gpr_mu_init(&grpc_polling_mu); dummy_uv_handle = gpr_malloc(sizeof(uv_timer_t)); uv_timer_init(uv_default_loop(), dummy_uv_handle); grpc_pollset_work_run_loop = 1; } void grpc_pollset_global_shutdown(void) { gpr_mu_destroy(&grpc_polling_mu); uv_close((uv_handle_t *)dummy_uv_handle, dummy_handle_close_cb); } static void timer_run_cb(uv_timer_t *timer) {} static void timer_close_cb(uv_handle_t *handle) { handle->data = (void *)1; } void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu) { *mu = &grpc_polling_mu; uv_timer_init(uv_default_loop(), &pollset->timer); pollset->shutting_down = 0; } void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_closure *closure) { GPR_ASSERT(!pollset->shutting_down); pollset->shutting_down = 1; if (grpc_pollset_work_run_loop) { // Drain any pending UV callbacks without blocking uv_run(uv_default_loop(), UV_RUN_NOWAIT); } else { // kick the loop once uv_timer_start(dummy_uv_handle, dummy_timer_cb, 0, 0); } grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_NONE); } void grpc_pollset_destroy(grpc_pollset *pollset) { uv_close((uv_handle_t *)&pollset->timer, timer_close_cb); // timer.data is a boolean indicating that the timer has finished closing pollset->timer.data = (void *)0; if (grpc_pollset_work_run_loop) { while (!pollset->timer.data) { uv_run(uv_default_loop(), UV_RUN_NOWAIT); } } } grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker **worker_hdl, gpr_timespec now, gpr_timespec deadline) { uint64_t timeout; gpr_mu_unlock(&grpc_polling_mu); if (grpc_pollset_work_run_loop) { if (gpr_time_cmp(deadline, now) >= 0) { timeout = (uint64_t)gpr_time_to_millis(gpr_time_sub(deadline, now)); } else { timeout = 0; } /* We special-case timeout=0 so that we don't bother with the timer when the loop won't block anyway */ if (timeout > 0) { uv_timer_start(&pollset->timer, timer_run_cb, timeout, 0); /* Run until there is some I/O activity or the timer triggers. It doesn't matter which happens */ uv_run(uv_default_loop(), UV_RUN_ONCE); uv_timer_stop(&pollset->timer); } else { uv_run(uv_default_loop(), UV_RUN_NOWAIT); } } if (!grpc_closure_list_empty(exec_ctx->closure_list)) { grpc_exec_ctx_flush(exec_ctx); } gpr_mu_lock(&grpc_polling_mu); return GRPC_ERROR_NONE; } grpc_error *grpc_pollset_kick(grpc_pollset *pollset, grpc_pollset_worker *specific_worker) { uv_timer_start(dummy_uv_handle, dummy_timer_cb, 0, 0); return GRPC_ERROR_NONE; } #endif /* GRPC_UV */ grpc-1.3.2/src/core/lib/iomgr/pollset_uv.h000066400000000000000000000034321310511640000204100ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_POLLSET_UV_H #define GRPC_CORE_LIB_IOMGR_POLLSET_UV_H extern int grpc_pollset_work_run_loop; void grpc_pollset_global_init(void); void grpc_pollset_global_shutdown(void); #endif /* GRPC_CORE_LIB_IOMGR_POLLSET_UV_H */ grpc-1.3.2/src/core/lib/iomgr/pollset_windows.c000066400000000000000000000205651310511640000214510ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_WINSOCK_SOCKET #include #include #include "src/core/lib/iomgr/iocp_windows.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/pollset_windows.h" gpr_mu grpc_polling_mu; static grpc_pollset_worker *g_active_poller; static grpc_pollset_worker g_global_root_worker; void grpc_pollset_global_init(void) { gpr_mu_init(&grpc_polling_mu); g_active_poller = NULL; g_global_root_worker.links[GRPC_POLLSET_WORKER_LINK_GLOBAL].next = g_global_root_worker.links[GRPC_POLLSET_WORKER_LINK_GLOBAL].prev = &g_global_root_worker; } void grpc_pollset_global_shutdown(void) { gpr_mu_destroy(&grpc_polling_mu); } static void remove_worker(grpc_pollset_worker *worker, grpc_pollset_worker_link_type type) { worker->links[type].prev->links[type].next = worker->links[type].next; worker->links[type].next->links[type].prev = worker->links[type].prev; worker->links[type].next = worker->links[type].prev = worker; } static int has_workers(grpc_pollset_worker *root, grpc_pollset_worker_link_type type) { return root->links[type].next != root; } static grpc_pollset_worker *pop_front_worker( grpc_pollset_worker *root, grpc_pollset_worker_link_type type) { if (has_workers(root, type)) { grpc_pollset_worker *w = root->links[type].next; remove_worker(w, type); return w; } else { return NULL; } } static void push_front_worker(grpc_pollset_worker *root, grpc_pollset_worker_link_type type, grpc_pollset_worker *worker) { worker->links[type].prev = root; worker->links[type].next = worker->links[type].prev->links[type].next; worker->links[type].prev->links[type].next = worker->links[type].next->links[type].prev = worker; } size_t grpc_pollset_size(void) { return sizeof(grpc_pollset); } /* There isn't really any such thing as a pollset under Windows, due to the nature of the IO completion ports. We're still going to provide a minimal set of features for the sake of the rest of grpc. But grpc_pollset_work won't actually do any polling, and return as quickly as possible. */ void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu) { *mu = &grpc_polling_mu; pollset->root_worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].next = pollset->root_worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].prev = &pollset->root_worker; } void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_closure *closure) { pollset->shutting_down = 1; grpc_pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST); if (!pollset->is_iocp_worker) { grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_NONE); } else { pollset->on_shutdown = closure; } } void grpc_pollset_destroy(grpc_pollset *pollset) {} grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker **worker_hdl, gpr_timespec now, gpr_timespec deadline) { grpc_pollset_worker worker; if (worker_hdl) *worker_hdl = &worker; int added_worker = 0; worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].next = worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].prev = worker.links[GRPC_POLLSET_WORKER_LINK_GLOBAL].next = worker.links[GRPC_POLLSET_WORKER_LINK_GLOBAL].prev = NULL; worker.kicked = 0; worker.pollset = pollset; gpr_cv_init(&worker.cv); if (!pollset->kicked_without_pollers && !pollset->shutting_down) { if (g_active_poller == NULL) { grpc_pollset_worker *next_worker; /* become poller */ pollset->is_iocp_worker = 1; g_active_poller = &worker; gpr_mu_unlock(&grpc_polling_mu); grpc_iocp_work(exec_ctx, deadline); grpc_exec_ctx_flush(exec_ctx); gpr_mu_lock(&grpc_polling_mu); pollset->is_iocp_worker = 0; g_active_poller = NULL; /* try to get a worker from this pollsets worker list */ next_worker = pop_front_worker(&pollset->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET); if (next_worker == NULL) { /* try to get a worker from the global list */ next_worker = pop_front_worker(&g_global_root_worker, GRPC_POLLSET_WORKER_LINK_GLOBAL); } if (next_worker != NULL) { next_worker->kicked = 1; gpr_cv_signal(&next_worker->cv); } if (pollset->shutting_down && pollset->on_shutdown != NULL) { grpc_closure_sched(exec_ctx, pollset->on_shutdown, GRPC_ERROR_NONE); pollset->on_shutdown = NULL; } goto done; } push_front_worker(&g_global_root_worker, GRPC_POLLSET_WORKER_LINK_GLOBAL, &worker); push_front_worker(&pollset->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET, &worker); added_worker = 1; while (!worker.kicked) { if (gpr_cv_wait(&worker.cv, &grpc_polling_mu, deadline)) { break; } } } else { pollset->kicked_without_pollers = 0; } done: if (!grpc_closure_list_empty(exec_ctx->closure_list)) { gpr_mu_unlock(&grpc_polling_mu); grpc_exec_ctx_flush(exec_ctx); gpr_mu_lock(&grpc_polling_mu); } if (added_worker) { remove_worker(&worker, GRPC_POLLSET_WORKER_LINK_GLOBAL); remove_worker(&worker, GRPC_POLLSET_WORKER_LINK_POLLSET); } gpr_cv_destroy(&worker.cv); if (worker_hdl) *worker_hdl = NULL; return GRPC_ERROR_NONE; } grpc_error *grpc_pollset_kick(grpc_pollset *p, grpc_pollset_worker *specific_worker) { if (specific_worker != NULL) { if (specific_worker == GRPC_POLLSET_KICK_BROADCAST) { for (specific_worker = p->root_worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].next; specific_worker != &p->root_worker; specific_worker = specific_worker->links[GRPC_POLLSET_WORKER_LINK_POLLSET].next) { specific_worker->kicked = 1; gpr_cv_signal(&specific_worker->cv); } p->kicked_without_pollers = 1; if (p->is_iocp_worker) { grpc_iocp_kick(); } } else { if (p->is_iocp_worker && g_active_poller == specific_worker) { grpc_iocp_kick(); } else { specific_worker->kicked = 1; gpr_cv_signal(&specific_worker->cv); } } } else { specific_worker = pop_front_worker(&p->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET); if (specific_worker != NULL) { grpc_pollset_kick(p, specific_worker); } else if (p->is_iocp_worker) { grpc_iocp_kick(); } else { p->kicked_without_pollers = 1; } } return GRPC_ERROR_NONE; } void grpc_kick_poller(void) { grpc_iocp_kick(); } #endif /* GRPC_WINSOCK_SOCKET */ grpc-1.3.2/src/core/lib/iomgr/pollset_windows.h000066400000000000000000000054561310511640000214600ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_POLLSET_WINDOWS_H #define GRPC_CORE_LIB_IOMGR_POLLSET_WINDOWS_H #include #include "src/core/lib/iomgr/socket_windows.h" /* There isn't really any such thing as a pollset under Windows, due to the nature of the IO completion ports. A Windows "pollset" is merely a mutex used to synchronize with the IOCP, and workers are condition variables used to block threads until work is ready. */ typedef enum { GRPC_POLLSET_WORKER_LINK_POLLSET = 0, GRPC_POLLSET_WORKER_LINK_GLOBAL, GRPC_POLLSET_WORKER_LINK_TYPES } grpc_pollset_worker_link_type; typedef struct grpc_pollset_worker_link { struct grpc_pollset_worker *next; struct grpc_pollset_worker *prev; } grpc_pollset_worker_link; struct grpc_pollset; typedef struct grpc_pollset grpc_pollset; typedef struct grpc_pollset_worker { gpr_cv cv; int kicked; struct grpc_pollset *pollset; grpc_pollset_worker_link links[GRPC_POLLSET_WORKER_LINK_TYPES]; } grpc_pollset_worker; struct grpc_pollset { int shutting_down; int kicked_without_pollers; int is_iocp_worker; grpc_pollset_worker root_worker; grpc_closure *on_shutdown; }; void grpc_pollset_global_init(void); void grpc_pollset_global_shutdown(void); #endif /* GRPC_CORE_LIB_IOMGR_POLLSET_WINDOWS_H */ grpc-1.3.2/src/core/lib/iomgr/port.h000066400000000000000000000110671310511640000172030ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifndef GRPC_CORE_LIB_IOMGR_PORT_H #define GRPC_CORE_LIB_IOMGR_PORT_H #if defined(GRPC_UV) // Do nothing #elif defined(GPR_MANYLINUX1) #define GRPC_HAVE_IFADDRS 1 #define GRPC_HAVE_IPV6_RECVPKTINFO 1 #define GRPC_HAVE_IP_PKTINFO 1 #define GRPC_HAVE_MSG_NOSIGNAL 1 #define GRPC_HAVE_UNIX_SOCKET 1 #define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1 #define GRPC_POSIX_SOCKET 1 #define GRPC_POSIX_SOCKETADDR 1 #define GRPC_POSIX_SOCKETUTILS 1 #define GRPC_POSIX_WAKEUP_FD 1 #define GRPC_TIMER_USE_GENERIC 1 #elif defined(GPR_WINDOWS) #define GRPC_TIMER_USE_GENERIC 1 #define GRPC_WINSOCK_SOCKET 1 #define GRPC_WINDOWS_SOCKETUTILS 1 #elif defined(GPR_ANDROID) #define GRPC_HAVE_IPV6_RECVPKTINFO 1 #define GRPC_HAVE_IP_PKTINFO 1 #define GRPC_HAVE_MSG_NOSIGNAL 1 #define GRPC_HAVE_UNIX_SOCKET 1 #define GRPC_LINUX_EVENTFD 1 #define GRPC_POSIX_SOCKET 1 #define GRPC_POSIX_SOCKETADDR 1 #define GRPC_POSIX_SOCKETUTILS 1 #define GRPC_POSIX_WAKEUP_FD 1 #define GRPC_TIMER_USE_GENERIC 1 #elif defined(GPR_LINUX) #define GRPC_HAVE_IFADDRS 1 #define GRPC_HAVE_IPV6_RECVPKTINFO 1 #define GRPC_HAVE_IP_PKTINFO 1 #define GRPC_HAVE_MSG_NOSIGNAL 1 #define GRPC_HAVE_UNIX_SOCKET 1 #define GRPC_LINUX_MULTIPOLL_WITH_EPOLL 1 #define GRPC_POSIX_SOCKET 1 #define GRPC_POSIX_SOCKETADDR 1 #define GRPC_POSIX_WAKEUP_FD 1 #define GRPC_TIMER_USE_GENERIC 1 #ifdef __GLIBC_PREREQ #if __GLIBC_PREREQ(2, 9) #define GRPC_LINUX_EPOLL 1 #define GRPC_LINUX_EVENTFD 1 #endif #if __GLIBC_PREREQ(2, 10) #define GRPC_LINUX_SOCKETUTILS 1 #endif #endif #ifndef __GLIBC__ #define GRPC_LINUX_EPOLL 1 #define GRPC_LINUX_EVENTFD 1 #define GRPC_MSG_IOVLEN_TYPE int #endif #ifndef GRPC_LINUX_EVENTFD #define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1 #endif #ifndef GRPC_LINUX_SOCKETUTILS #define GRPC_POSIX_SOCKETUTILS #endif #elif defined(GPR_APPLE) #define GRPC_HAVE_IFADDRS 1 #define GRPC_HAVE_SO_NOSIGPIPE 1 #define GRPC_HAVE_UNIX_SOCKET 1 #define GRPC_MSG_IOVLEN_TYPE int #define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1 #define GRPC_POSIX_SOCKET 1 #define GRPC_POSIX_SOCKETADDR 1 #define GRPC_POSIX_SOCKETUTILS 1 #define GRPC_POSIX_WAKEUP_FD 1 #define GRPC_TIMER_USE_GENERIC 1 #elif defined(GPR_FREEBSD) #define GRPC_HAVE_IFADDRS 1 #define GRPC_HAVE_IPV6_RECVPKTINFO 1 #define GRPC_HAVE_SO_NOSIGPIPE 1 #define GRPC_HAVE_UNIX_SOCKET 1 #define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1 #define GRPC_POSIX_SOCKET 1 #define GRPC_POSIX_SOCKETADDR 1 #define GRPC_POSIX_SOCKETUTILS 1 #define GRPC_POSIX_WAKEUP_FD 1 #define GRPC_TIMER_USE_GENERIC 1 #elif defined(GPR_NACL) #define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1 #define GRPC_POSIX_SOCKET 1 #define GRPC_POSIX_SOCKETADDR 1 #define GRPC_POSIX_SOCKETUTILS 1 #define GRPC_POSIX_WAKEUP_FD 1 #define GRPC_TIMER_USE_GENERIC 1 #elif !defined(GPR_NO_AUTODETECT_PLATFORM) #error "Platform not recognized" #endif #if defined(GRPC_POSIX_SOCKET) + defined(GRPC_WINSOCK_SOCKET) + \ defined(GRPC_CUSTOM_SOCKET) + defined(GRPC_UV) != \ 1 #error Must define exactly one of GRPC_POSIX_SOCKET, GRPC_WINSOCK_SOCKET, GPR_CUSTOM_SOCKET #endif #endif /* GRPC_CORE_LIB_IOMGR_PORT_H */ grpc-1.3.2/src/core/lib/iomgr/resolve_address.h000066400000000000000000000056041310511640000214030ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_RESOLVE_ADDRESS_H #define GRPC_CORE_LIB_IOMGR_RESOLVE_ADDRESS_H #include #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/pollset_set.h" #define GRPC_MAX_SOCKADDR_SIZE 128 typedef struct { char addr[GRPC_MAX_SOCKADDR_SIZE]; size_t len; } grpc_resolved_address; typedef struct { size_t naddrs; grpc_resolved_address *addrs; } grpc_resolved_addresses; /* Asynchronously resolve addr. Use default_port if a port isn't designated in addr, otherwise use the port in addr. */ /* TODO(ctiller): add a timeout here */ extern void (*grpc_resolve_address)(grpc_exec_ctx *exec_ctx, const char *addr, const char *default_port, grpc_pollset_set *interested_parties, grpc_closure *on_done, grpc_resolved_addresses **addresses); /* Destroy resolved addresses */ void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addresses); /* Resolve addr in a blocking fashion. Returns NULL on failure. On success, result must be freed with grpc_resolved_addresses_destroy. */ extern grpc_error *(*grpc_blocking_resolve_address)( const char *name, const char *default_port, grpc_resolved_addresses **addresses); #endif /* GRPC_CORE_LIB_IOMGR_RESOLVE_ADDRESS_H */ grpc-1.3.2/src/core/lib/iomgr/resolve_address_posix.c000066400000000000000000000157371310511640000226300ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_POSIX_SOCKET #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/resolve_address.h" #include #include #include #include #include #include #include #include #include #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" #include "src/core/lib/support/block_annotate.h" #include "src/core/lib/support/string.h" static grpc_error *blocking_resolve_address_impl( const char *name, const char *default_port, grpc_resolved_addresses **addresses) { struct addrinfo hints; struct addrinfo *result = NULL, *resp; char *host; char *port; int s; size_t i; grpc_error *err; if (name[0] == 'u' && name[1] == 'n' && name[2] == 'i' && name[3] == 'x' && name[4] == ':' && name[5] != 0) { return grpc_resolve_unix_domain_address(name + 5, addresses); } /* parse name, splitting it into host and port parts */ gpr_split_host_port(name, &host, &port); if (host == NULL) { err = grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("unparseable host:port"), GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name)); goto done; } if (port == NULL) { if (default_port == NULL) { err = grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("no port in name"), GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name)); goto done; } port = gpr_strdup(default_port); } /* Call getaddrinfo */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; /* ipv4 or ipv6 */ hints.ai_socktype = SOCK_STREAM; /* stream socket */ hints.ai_flags = AI_PASSIVE; /* for wildcard IP address */ GRPC_SCHEDULING_START_BLOCKING_REGION; s = getaddrinfo(host, port, &hints, &result); GRPC_SCHEDULING_END_BLOCKING_REGION; if (s != 0) { /* Retry if well-known service name is recognized */ char *svc[][2] = {{"http", "80"}, {"https", "443"}}; for (i = 0; i < GPR_ARRAY_SIZE(svc); i++) { if (strcmp(port, svc[i][0]) == 0) { GRPC_SCHEDULING_START_BLOCKING_REGION; s = getaddrinfo(host, svc[i][1], &hints, &result); GRPC_SCHEDULING_END_BLOCKING_REGION; break; } } } if (s != 0) { err = grpc_error_set_str( grpc_error_set_str( grpc_error_set_str( grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING("OS Error"), GRPC_ERROR_INT_ERRNO, s), GRPC_ERROR_STR_OS_ERROR, grpc_slice_from_static_string(gai_strerror(s))), GRPC_ERROR_STR_SYSCALL, grpc_slice_from_static_string("getaddrinfo")), GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name)); goto done; } /* Success path: set addrs non-NULL, fill it in */ *addresses = gpr_malloc(sizeof(grpc_resolved_addresses)); (*addresses)->naddrs = 0; for (resp = result; resp != NULL; resp = resp->ai_next) { (*addresses)->naddrs++; } (*addresses)->addrs = gpr_malloc(sizeof(grpc_resolved_address) * (*addresses)->naddrs); i = 0; for (resp = result; resp != NULL; resp = resp->ai_next) { memcpy(&(*addresses)->addrs[i].addr, resp->ai_addr, resp->ai_addrlen); (*addresses)->addrs[i].len = resp->ai_addrlen; i++; } err = GRPC_ERROR_NONE; done: gpr_free(host); gpr_free(port); if (result) { freeaddrinfo(result); } return err; } grpc_error *(*grpc_blocking_resolve_address)( const char *name, const char *default_port, grpc_resolved_addresses **addresses) = blocking_resolve_address_impl; typedef struct { char *name; char *default_port; grpc_closure *on_done; grpc_resolved_addresses **addrs_out; grpc_closure request_closure; void *arg; } request; /* Callback to be passed to grpc_executor to asynch-ify * grpc_blocking_resolve_address */ static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp, grpc_error *error) { request *r = rp; grpc_closure_sched( exec_ctx, r->on_done, grpc_blocking_resolve_address(r->name, r->default_port, r->addrs_out)); gpr_free(r->name); gpr_free(r->default_port); gpr_free(r); } void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) { if (addrs != NULL) { gpr_free(addrs->addrs); } gpr_free(addrs); } static void resolve_address_impl(grpc_exec_ctx *exec_ctx, const char *name, const char *default_port, grpc_pollset_set *interested_parties, grpc_closure *on_done, grpc_resolved_addresses **addrs) { request *r = gpr_malloc(sizeof(request)); grpc_closure_init(&r->request_closure, do_request_thread, r, grpc_executor_scheduler); r->name = gpr_strdup(name); r->default_port = gpr_strdup(default_port); r->on_done = on_done; r->addrs_out = addrs; grpc_closure_sched(exec_ctx, &r->request_closure, GRPC_ERROR_NONE); } void (*grpc_resolve_address)( grpc_exec_ctx *exec_ctx, const char *name, const char *default_port, grpc_pollset_set *interested_parties, grpc_closure *on_done, grpc_resolved_addresses **addrs) = resolve_address_impl; #endif grpc-1.3.2/src/core/lib/iomgr/resolve_address_uv.c000066400000000000000000000223251310511640000221070ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_UV #include #include #include #include #include #include #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include typedef struct request { grpc_closure *on_done; grpc_resolved_addresses **addresses; struct addrinfo *hints; char *host; char *port; } request; static int retry_named_port_failure(int status, request *r, uv_getaddrinfo_cb getaddrinfo_cb) { if (status != 0) { // This loop is copied from resolve_address_posix.c char *svc[][2] = {{"http", "80"}, {"https", "443"}}; for (size_t i = 0; i < GPR_ARRAY_SIZE(svc); i++) { if (strcmp(r->port, svc[i][0]) == 0) { int retry_status; uv_getaddrinfo_t *req = gpr_malloc(sizeof(uv_getaddrinfo_t)); req->data = r; r->port = svc[i][1]; retry_status = uv_getaddrinfo(uv_default_loop(), req, getaddrinfo_cb, r->host, r->port, r->hints); if (retry_status < 0 || getaddrinfo_cb == NULL) { // The callback will not be called gpr_free(req); } return retry_status; } } } /* If this function calls uv_getaddrinfo, it will return that function's return value. That function only returns numbers <=0, so we can safely return 1 to indicate that we never retried */ return 1; } static grpc_error *handle_addrinfo_result(int status, struct addrinfo *result, grpc_resolved_addresses **addresses) { struct addrinfo *resp; size_t i; if (status != 0) { grpc_error *error; *addresses = NULL; error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("getaddrinfo failed"); error = grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, grpc_slice_from_static_string(uv_strerror(status))); return error; } (*addresses) = gpr_malloc(sizeof(grpc_resolved_addresses)); (*addresses)->naddrs = 0; for (resp = result; resp != NULL; resp = resp->ai_next) { (*addresses)->naddrs++; } (*addresses)->addrs = gpr_malloc(sizeof(grpc_resolved_address) * (*addresses)->naddrs); i = 0; for (resp = result; resp != NULL; resp = resp->ai_next) { memcpy(&(*addresses)->addrs[i].addr, resp->ai_addr, resp->ai_addrlen); (*addresses)->addrs[i].len = resp->ai_addrlen; i++; } { for (i = 0; i < (*addresses)->naddrs; i++) { char *buf; grpc_sockaddr_to_string(&buf, &(*addresses)->addrs[i], 0); gpr_free(buf); } } return GRPC_ERROR_NONE; } static void getaddrinfo_callback(uv_getaddrinfo_t *req, int status, struct addrinfo *res) { request *r = (request *)req->data; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_error *error; int retry_status; gpr_free(req); retry_status = retry_named_port_failure(status, r, getaddrinfo_callback); if (retry_status == 0) { // The request is being retried. Nothing should be done here return; } /* Either no retry was attempted, or the retry failed. Either way, the original error probably has more interesting information */ error = handle_addrinfo_result(status, res, r->addresses); grpc_closure_sched(&exec_ctx, r->on_done, error); grpc_exec_ctx_finish(&exec_ctx); gpr_free(r->hints); gpr_free(r); uv_freeaddrinfo(res); } static grpc_error *try_split_host_port(const char *name, const char *default_port, char **host, char **port) { /* parse name, splitting it into host and port parts */ grpc_error *error; gpr_split_host_port(name, host, port); if (*host == NULL) { char *msg; gpr_asprintf(&msg, "unparseable host:port: '%s'", name); error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return error; } if (*port == NULL) { // TODO(murgatroid99): add tests for this case if (default_port == NULL) { char *msg; gpr_asprintf(&msg, "no port in name '%s'", name); error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return error; } *port = gpr_strdup(default_port); } return GRPC_ERROR_NONE; } static grpc_error *blocking_resolve_address_impl( const char *name, const char *default_port, grpc_resolved_addresses **addresses) { char *host; char *port; struct addrinfo hints; uv_getaddrinfo_t req; int s; grpc_error *err; int retry_status; req.addrinfo = NULL; err = try_split_host_port(name, default_port, &host, &port); if (err != GRPC_ERROR_NONE) { goto done; } /* Call getaddrinfo */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; /* ipv4 or ipv6 */ hints.ai_socktype = SOCK_STREAM; /* stream socket */ hints.ai_flags = AI_PASSIVE; /* for wildcard IP address */ s = uv_getaddrinfo(uv_default_loop(), &req, NULL, host, port, &hints); request r = { .addresses = addresses, .hints = &hints, .host = host, .port = port}; retry_status = retry_named_port_failure(s, &r, NULL); if (retry_status <= 0) { s = retry_status; } err = handle_addrinfo_result(s, req.addrinfo, addresses); done: gpr_free(host); gpr_free(port); if (req.addrinfo) { uv_freeaddrinfo(req.addrinfo); } return err; } grpc_error *(*grpc_blocking_resolve_address)( const char *name, const char *default_port, grpc_resolved_addresses **addresses) = blocking_resolve_address_impl; void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) { if (addrs != NULL) { gpr_free(addrs->addrs); } gpr_free(addrs); } static void resolve_address_impl(grpc_exec_ctx *exec_ctx, const char *name, const char *default_port, grpc_pollset_set *interested_parties, grpc_closure *on_done, grpc_resolved_addresses **addrs) { uv_getaddrinfo_t *req; request *r; struct addrinfo *hints; char *host; char *port; grpc_error *err; int s; err = try_split_host_port(name, default_port, &host, &port); if (err != GRPC_ERROR_NONE) { grpc_closure_sched(exec_ctx, on_done, err); return; } r = gpr_malloc(sizeof(request)); r->on_done = on_done; r->addresses = addrs; r->host = host; r->port = port; req = gpr_malloc(sizeof(uv_getaddrinfo_t)); req->data = r; /* Call getaddrinfo */ hints = gpr_malloc(sizeof(struct addrinfo)); memset(hints, 0, sizeof(struct addrinfo)); hints->ai_family = AF_UNSPEC; /* ipv4 or ipv6 */ hints->ai_socktype = SOCK_STREAM; /* stream socket */ hints->ai_flags = AI_PASSIVE; /* for wildcard IP address */ r->hints = hints; s = uv_getaddrinfo(uv_default_loop(), req, getaddrinfo_callback, host, port, hints); if (s != 0) { *addrs = NULL; err = GRPC_ERROR_CREATE_FROM_STATIC_STRING("getaddrinfo failed"); err = grpc_error_set_str(err, GRPC_ERROR_STR_OS_ERROR, grpc_slice_from_static_string(uv_strerror(s))); grpc_closure_sched(exec_ctx, on_done, err); gpr_free(r); gpr_free(req); gpr_free(hints); gpr_free(host); gpr_free(port); } } void (*grpc_resolve_address)( grpc_exec_ctx *exec_ctx, const char *name, const char *default_port, grpc_pollset_set *interested_parties, grpc_closure *on_done, grpc_resolved_addresses **addrs) = resolve_address_impl; #endif /* GRPC_UV */ grpc-1.3.2/src/core/lib/iomgr/resolve_address_windows.c000066400000000000000000000142151310511640000231460ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_WINSOCK_SOCKET #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/resolve_address.h" #include #include #include #include #include #include #include #include #include #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/support/block_annotate.h" #include "src/core/lib/support/string.h" typedef struct { char *name; char *default_port; grpc_closure request_closure; grpc_closure *on_done; grpc_resolved_addresses **addresses; } request; static grpc_error *blocking_resolve_address_impl( const char *name, const char *default_port, grpc_resolved_addresses **addresses) { struct addrinfo hints; struct addrinfo *result = NULL, *resp; char *host; char *port; int s; size_t i; grpc_error *error = GRPC_ERROR_NONE; /* parse name, splitting it into host and port parts */ gpr_split_host_port(name, &host, &port); if (host == NULL) { char *msg; gpr_asprintf(&msg, "unparseable host:port: '%s'", name); error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); goto done; } if (port == NULL) { if (default_port == NULL) { char *msg; gpr_asprintf(&msg, "no port in name '%s'", name); error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); goto done; } port = gpr_strdup(default_port); } /* Call getaddrinfo */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; /* ipv4 or ipv6 */ hints.ai_socktype = SOCK_STREAM; /* stream socket */ hints.ai_flags = AI_PASSIVE; /* for wildcard IP address */ GRPC_SCHEDULING_START_BLOCKING_REGION; s = getaddrinfo(host, port, &hints, &result); GRPC_SCHEDULING_END_BLOCKING_REGION; if (s != 0) { error = GRPC_WSA_ERROR(WSAGetLastError(), "getaddrinfo"); goto done; } /* Success path: set addrs non-NULL, fill it in */ (*addresses) = gpr_malloc(sizeof(grpc_resolved_addresses)); (*addresses)->naddrs = 0; for (resp = result; resp != NULL; resp = resp->ai_next) { (*addresses)->naddrs++; } (*addresses)->addrs = gpr_malloc(sizeof(grpc_resolved_address) * (*addresses)->naddrs); i = 0; for (resp = result; resp != NULL; resp = resp->ai_next) { memcpy(&(*addresses)->addrs[i].addr, resp->ai_addr, resp->ai_addrlen); (*addresses)->addrs[i].len = resp->ai_addrlen; i++; } { for (i = 0; i < (*addresses)->naddrs; i++) { char *buf; grpc_sockaddr_to_string(&buf, &(*addresses)->addrs[i], 0); gpr_free(buf); } } done: gpr_free(host); gpr_free(port); if (result) { freeaddrinfo(result); } return error; } grpc_error *(*grpc_blocking_resolve_address)( const char *name, const char *default_port, grpc_resolved_addresses **addresses) = blocking_resolve_address_impl; /* Callback to be passed to grpc_executor to asynch-ify * grpc_blocking_resolve_address */ static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp, grpc_error *error) { request *r = rp; if (error == GRPC_ERROR_NONE) { error = grpc_blocking_resolve_address(r->name, r->default_port, r->addresses); } else { GRPC_ERROR_REF(error); } grpc_closure_sched(exec_ctx, r->on_done, error); gpr_free(r->name); gpr_free(r->default_port); gpr_free(r); } void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) { if (addrs != NULL) { gpr_free(addrs->addrs); } gpr_free(addrs); } static void resolve_address_impl(grpc_exec_ctx *exec_ctx, const char *name, const char *default_port, grpc_pollset_set *interested_parties, grpc_closure *on_done, grpc_resolved_addresses **addresses) { request *r = gpr_malloc(sizeof(request)); grpc_closure_init(&r->request_closure, do_request_thread, r, grpc_executor_scheduler); r->name = gpr_strdup(name); r->default_port = gpr_strdup(default_port); r->on_done = on_done; r->addresses = addresses; grpc_closure_sched(exec_ctx, &r->request_closure, GRPC_ERROR_NONE); } void (*grpc_resolve_address)( grpc_exec_ctx *exec_ctx, const char *name, const char *default_port, grpc_pollset_set *interested_parties, grpc_closure *on_done, grpc_resolved_addresses **addresses) = resolve_address_impl; #endif grpc-1.3.2/src/core/lib/iomgr/resource_quota.c000066400000000000000000001032041310511640000212450ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/resource_quota.h" #include #include #include #include #include #include #include #include "src/core/lib/iomgr/combiner.h" int grpc_resource_quota_trace = 0; #define MEMORY_USAGE_ESTIMATION_MAX 65536 /* Internal linked list pointers for a resource user */ typedef struct { grpc_resource_user *next; grpc_resource_user *prev; } grpc_resource_user_link; /* Resource users are kept in (potentially) several intrusive linked lists at once. These are the list names. */ typedef enum { /* Resource users that are waiting for an allocation */ GRPC_RULIST_AWAITING_ALLOCATION, /* Resource users that have free memory available for internal reclamation */ GRPC_RULIST_NON_EMPTY_FREE_POOL, /* Resource users that have published a benign reclamation is available */ GRPC_RULIST_RECLAIMER_BENIGN, /* Resource users that have published a destructive reclamation is available */ GRPC_RULIST_RECLAIMER_DESTRUCTIVE, /* Number of lists: must be last */ GRPC_RULIST_COUNT } grpc_rulist; struct grpc_resource_user { /* The quota this resource user consumes from */ grpc_resource_quota *resource_quota; /* Closure to schedule an allocation under the resource quota combiner lock */ grpc_closure allocate_closure; /* Closure to publish a non empty free pool under the resource quota combiner lock */ grpc_closure add_to_free_pool_closure; /* one ref for each ref call (released by grpc_resource_user_unref), and one ref for each byte allocated (released by grpc_resource_user_free) */ gpr_atm refs; /* is this resource user unlocked? starts at 0, increases for each shutdown call */ gpr_atm shutdown; gpr_mu mu; /* The amount of memory (in bytes) this user has cached for its own use: to avoid quota contention, each resource user can keep some memory in addition to what it is immediately using (e.g., for caching), and the quota can pull it back under memory pressure. This value can become negative if more memory has been requested than existed in the free pool, at which point the quota is consulted to bring this value non-negative (asynchronously). */ int64_t free_pool; /* A list of closures to call once free_pool becomes non-negative - ie when all outstanding allocations have been granted. */ grpc_closure_list on_allocated; /* True if we are currently trying to allocate from the quota, false if not */ bool allocating; /* True if we are currently trying to add ourselves to the non-free quota list, false otherwise */ bool added_to_free_pool; /* Reclaimers: index 0 is the benign reclaimer, 1 is the destructive reclaimer */ grpc_closure *reclaimers[2]; /* Reclaimers just posted: once we're in the combiner lock, we'll move them to the array above */ grpc_closure *new_reclaimers[2]; /* Trampoline closures to finish reclamation and re-enter the quota combiner lock */ grpc_closure post_reclaimer_closure[2]; /* Closure to execute under the quota combiner to de-register and shutdown the resource user */ grpc_closure destroy_closure; /* Links in the various grpc_rulist lists */ grpc_resource_user_link links[GRPC_RULIST_COUNT]; /* The name of this resource user, for debugging/tracing */ char *name; }; struct grpc_resource_quota { /* refcount */ gpr_refcount refs; /* estimate of current memory usage scaled to the range [0..RESOURCE_USAGE_ESTIMATION_MAX] */ gpr_atm memory_usage_estimation; /* Master combiner lock: all activity on a quota executes under this combiner * (so no mutex is needed for this data structure) */ grpc_combiner *combiner; /* Size of the resource quota */ int64_t size; /* Amount of free memory in the resource quota */ int64_t free_pool; gpr_atm last_size; /* Has rq_step been scheduled to occur? */ bool step_scheduled; /* Are we currently reclaiming memory */ bool reclaiming; /* Closure around rq_step */ grpc_closure rq_step_closure; /* Closure around rq_reclamation_done */ grpc_closure rq_reclamation_done_closure; /* This is only really usable for debugging: it's always a stale pointer, but a stale pointer that might just be fresh enough to guide us to where the reclamation system is stuck */ grpc_closure *debug_only_last_initiated_reclaimer; grpc_resource_user *debug_only_last_reclaimer_resource_user; /* Roots of all resource user lists */ grpc_resource_user *roots[GRPC_RULIST_COUNT]; char *name; }; /******************************************************************************* * list management */ static void rulist_add_head(grpc_resource_user *resource_user, grpc_rulist list) { grpc_resource_quota *resource_quota = resource_user->resource_quota; grpc_resource_user **root = &resource_quota->roots[list]; if (*root == NULL) { *root = resource_user; resource_user->links[list].next = resource_user->links[list].prev = resource_user; } else { resource_user->links[list].next = *root; resource_user->links[list].prev = (*root)->links[list].prev; resource_user->links[list].next->links[list].prev = resource_user->links[list].prev->links[list].next = resource_user; *root = resource_user; } } static void rulist_add_tail(grpc_resource_user *resource_user, grpc_rulist list) { grpc_resource_quota *resource_quota = resource_user->resource_quota; grpc_resource_user **root = &resource_quota->roots[list]; if (*root == NULL) { *root = resource_user; resource_user->links[list].next = resource_user->links[list].prev = resource_user; } else { resource_user->links[list].next = (*root)->links[list].next; resource_user->links[list].prev = *root; resource_user->links[list].next->links[list].prev = resource_user->links[list].prev->links[list].next = resource_user; } } static bool rulist_empty(grpc_resource_quota *resource_quota, grpc_rulist list) { return resource_quota->roots[list] == NULL; } static grpc_resource_user *rulist_pop_head(grpc_resource_quota *resource_quota, grpc_rulist list) { grpc_resource_user **root = &resource_quota->roots[list]; grpc_resource_user *resource_user = *root; if (resource_user == NULL) { return NULL; } if (resource_user->links[list].next == resource_user) { *root = NULL; } else { resource_user->links[list].next->links[list].prev = resource_user->links[list].prev; resource_user->links[list].prev->links[list].next = resource_user->links[list].next; *root = resource_user->links[list].next; } resource_user->links[list].next = resource_user->links[list].prev = NULL; return resource_user; } static void rulist_remove(grpc_resource_user *resource_user, grpc_rulist list) { if (resource_user->links[list].next == NULL) return; grpc_resource_quota *resource_quota = resource_user->resource_quota; if (resource_quota->roots[list] == resource_user) { resource_quota->roots[list] = resource_user->links[list].next; if (resource_quota->roots[list] == resource_user) { resource_quota->roots[list] = NULL; } } resource_user->links[list].next->links[list].prev = resource_user->links[list].prev; resource_user->links[list].prev->links[list].next = resource_user->links[list].next; resource_user->links[list].next = resource_user->links[list].prev = NULL; } /******************************************************************************* * resource quota state machine */ static bool rq_alloc(grpc_exec_ctx *exec_ctx, grpc_resource_quota *resource_quota); static bool rq_reclaim_from_per_user_free_pool( grpc_exec_ctx *exec_ctx, grpc_resource_quota *resource_quota); static bool rq_reclaim(grpc_exec_ctx *exec_ctx, grpc_resource_quota *resource_quota, bool destructive); static void rq_step(grpc_exec_ctx *exec_ctx, void *rq, grpc_error *error) { grpc_resource_quota *resource_quota = rq; resource_quota->step_scheduled = false; do { if (rq_alloc(exec_ctx, resource_quota)) goto done; } while (rq_reclaim_from_per_user_free_pool(exec_ctx, resource_quota)); if (!rq_reclaim(exec_ctx, resource_quota, false)) { rq_reclaim(exec_ctx, resource_quota, true); } done: grpc_resource_quota_unref_internal(exec_ctx, resource_quota); } static void rq_step_sched(grpc_exec_ctx *exec_ctx, grpc_resource_quota *resource_quota) { if (resource_quota->step_scheduled) return; resource_quota->step_scheduled = true; grpc_resource_quota_ref_internal(resource_quota); grpc_closure_sched(exec_ctx, &resource_quota->rq_step_closure, GRPC_ERROR_NONE); } /* update the atomically available resource estimate - use no barriers since timeliness of delivery really doesn't matter much */ static void rq_update_estimate(grpc_resource_quota *resource_quota) { gpr_atm memory_usage_estimation = MEMORY_USAGE_ESTIMATION_MAX; if (resource_quota->size != 0) { memory_usage_estimation = GPR_CLAMP((gpr_atm)((1.0 - ((double)resource_quota->free_pool) / ((double)resource_quota->size)) * MEMORY_USAGE_ESTIMATION_MAX), 0, MEMORY_USAGE_ESTIMATION_MAX); } gpr_atm_no_barrier_store(&resource_quota->memory_usage_estimation, memory_usage_estimation); } /* returns true if all allocations are completed */ static bool rq_alloc(grpc_exec_ctx *exec_ctx, grpc_resource_quota *resource_quota) { grpc_resource_user *resource_user; while ((resource_user = rulist_pop_head(resource_quota, GRPC_RULIST_AWAITING_ALLOCATION))) { gpr_mu_lock(&resource_user->mu); if (resource_user->free_pool < 0 && -resource_user->free_pool <= resource_quota->free_pool) { int64_t amt = -resource_user->free_pool; resource_user->free_pool = 0; resource_quota->free_pool -= amt; rq_update_estimate(resource_quota); if (grpc_resource_quota_trace) { gpr_log(GPR_DEBUG, "RQ %s %s: grant alloc %" PRId64 " bytes; rq_free_pool -> %" PRId64, resource_quota->name, resource_user->name, amt, resource_quota->free_pool); } } else if (grpc_resource_quota_trace && resource_user->free_pool >= 0) { gpr_log(GPR_DEBUG, "RQ %s %s: discard already satisfied alloc request", resource_quota->name, resource_user->name); } if (resource_user->free_pool >= 0) { resource_user->allocating = false; grpc_closure_list_sched(exec_ctx, &resource_user->on_allocated); gpr_mu_unlock(&resource_user->mu); } else { rulist_add_head(resource_user, GRPC_RULIST_AWAITING_ALLOCATION); gpr_mu_unlock(&resource_user->mu); return false; } } return true; } /* returns true if any memory could be reclaimed from buffers */ static bool rq_reclaim_from_per_user_free_pool( grpc_exec_ctx *exec_ctx, grpc_resource_quota *resource_quota) { grpc_resource_user *resource_user; while ((resource_user = rulist_pop_head(resource_quota, GRPC_RULIST_NON_EMPTY_FREE_POOL))) { gpr_mu_lock(&resource_user->mu); if (resource_user->free_pool > 0) { int64_t amt = resource_user->free_pool; resource_user->free_pool = 0; resource_quota->free_pool += amt; rq_update_estimate(resource_quota); if (grpc_resource_quota_trace) { gpr_log(GPR_DEBUG, "RQ %s %s: reclaim_from_per_user_free_pool %" PRId64 " bytes; rq_free_pool -> %" PRId64, resource_quota->name, resource_user->name, amt, resource_quota->free_pool); } gpr_mu_unlock(&resource_user->mu); return true; } else { gpr_mu_unlock(&resource_user->mu); } } return false; } /* returns true if reclamation is proceeding */ static bool rq_reclaim(grpc_exec_ctx *exec_ctx, grpc_resource_quota *resource_quota, bool destructive) { if (resource_quota->reclaiming) return true; grpc_rulist list = destructive ? GRPC_RULIST_RECLAIMER_DESTRUCTIVE : GRPC_RULIST_RECLAIMER_BENIGN; grpc_resource_user *resource_user = rulist_pop_head(resource_quota, list); if (resource_user == NULL) return false; if (grpc_resource_quota_trace) { gpr_log(GPR_DEBUG, "RQ %s %s: initiate %s reclamation", resource_quota->name, resource_user->name, destructive ? "destructive" : "benign"); } resource_quota->reclaiming = true; grpc_resource_quota_ref_internal(resource_quota); grpc_closure *c = resource_user->reclaimers[destructive]; GPR_ASSERT(c); resource_quota->debug_only_last_reclaimer_resource_user = resource_user; resource_quota->debug_only_last_initiated_reclaimer = c; resource_user->reclaimers[destructive] = NULL; grpc_closure_run(exec_ctx, c, GRPC_ERROR_NONE); return true; } /******************************************************************************* * ru_slice: a slice implementation that is backed by a grpc_resource_user */ typedef struct { grpc_slice_refcount base; gpr_refcount refs; grpc_resource_user *resource_user; size_t size; } ru_slice_refcount; static void ru_slice_ref(void *p) { ru_slice_refcount *rc = p; gpr_ref(&rc->refs); } static void ru_slice_unref(grpc_exec_ctx *exec_ctx, void *p) { ru_slice_refcount *rc = p; if (gpr_unref(&rc->refs)) { grpc_resource_user_free(exec_ctx, rc->resource_user, rc->size); gpr_free(rc); } } static const grpc_slice_refcount_vtable ru_slice_vtable = { ru_slice_ref, ru_slice_unref, grpc_slice_default_eq_impl, grpc_slice_default_hash_impl}; static grpc_slice ru_slice_create(grpc_resource_user *resource_user, size_t size) { ru_slice_refcount *rc = gpr_malloc(sizeof(ru_slice_refcount) + size); rc->base.vtable = &ru_slice_vtable; rc->base.sub_refcount = &rc->base; gpr_ref_init(&rc->refs, 1); rc->resource_user = resource_user; rc->size = size; grpc_slice slice; slice.refcount = &rc->base; slice.data.refcounted.bytes = (uint8_t *)(rc + 1); slice.data.refcounted.length = size; return slice; } /******************************************************************************* * grpc_resource_quota internal implementation: resource user manipulation under * the combiner */ static void ru_allocate(grpc_exec_ctx *exec_ctx, void *ru, grpc_error *error) { grpc_resource_user *resource_user = ru; if (rulist_empty(resource_user->resource_quota, GRPC_RULIST_AWAITING_ALLOCATION)) { rq_step_sched(exec_ctx, resource_user->resource_quota); } rulist_add_tail(resource_user, GRPC_RULIST_AWAITING_ALLOCATION); } static void ru_add_to_free_pool(grpc_exec_ctx *exec_ctx, void *ru, grpc_error *error) { grpc_resource_user *resource_user = ru; if (!rulist_empty(resource_user->resource_quota, GRPC_RULIST_AWAITING_ALLOCATION) && rulist_empty(resource_user->resource_quota, GRPC_RULIST_NON_EMPTY_FREE_POOL)) { rq_step_sched(exec_ctx, resource_user->resource_quota); } rulist_add_tail(resource_user, GRPC_RULIST_NON_EMPTY_FREE_POOL); } static bool ru_post_reclaimer(grpc_exec_ctx *exec_ctx, grpc_resource_user *resource_user, bool destructive) { grpc_closure *closure = resource_user->new_reclaimers[destructive]; GPR_ASSERT(closure != NULL); resource_user->new_reclaimers[destructive] = NULL; GPR_ASSERT(resource_user->reclaimers[destructive] == NULL); if (gpr_atm_acq_load(&resource_user->shutdown) > 0) { grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_CANCELLED); return false; } resource_user->reclaimers[destructive] = closure; return true; } static void ru_post_benign_reclaimer(grpc_exec_ctx *exec_ctx, void *ru, grpc_error *error) { grpc_resource_user *resource_user = ru; if (!ru_post_reclaimer(exec_ctx, resource_user, false)) return; if (!rulist_empty(resource_user->resource_quota, GRPC_RULIST_AWAITING_ALLOCATION) && rulist_empty(resource_user->resource_quota, GRPC_RULIST_NON_EMPTY_FREE_POOL) && rulist_empty(resource_user->resource_quota, GRPC_RULIST_RECLAIMER_BENIGN)) { rq_step_sched(exec_ctx, resource_user->resource_quota); } rulist_add_tail(resource_user, GRPC_RULIST_RECLAIMER_BENIGN); } static void ru_post_destructive_reclaimer(grpc_exec_ctx *exec_ctx, void *ru, grpc_error *error) { grpc_resource_user *resource_user = ru; if (!ru_post_reclaimer(exec_ctx, resource_user, true)) return; if (!rulist_empty(resource_user->resource_quota, GRPC_RULIST_AWAITING_ALLOCATION) && rulist_empty(resource_user->resource_quota, GRPC_RULIST_NON_EMPTY_FREE_POOL) && rulist_empty(resource_user->resource_quota, GRPC_RULIST_RECLAIMER_BENIGN) && rulist_empty(resource_user->resource_quota, GRPC_RULIST_RECLAIMER_DESTRUCTIVE)) { rq_step_sched(exec_ctx, resource_user->resource_quota); } rulist_add_tail(resource_user, GRPC_RULIST_RECLAIMER_DESTRUCTIVE); } static void ru_shutdown(grpc_exec_ctx *exec_ctx, void *ru, grpc_error *error) { grpc_resource_user *resource_user = ru; grpc_closure_sched(exec_ctx, resource_user->reclaimers[0], GRPC_ERROR_CANCELLED); grpc_closure_sched(exec_ctx, resource_user->reclaimers[1], GRPC_ERROR_CANCELLED); resource_user->reclaimers[0] = NULL; resource_user->reclaimers[1] = NULL; rulist_remove(resource_user, GRPC_RULIST_RECLAIMER_BENIGN); rulist_remove(resource_user, GRPC_RULIST_RECLAIMER_DESTRUCTIVE); } static void ru_destroy(grpc_exec_ctx *exec_ctx, void *ru, grpc_error *error) { grpc_resource_user *resource_user = ru; GPR_ASSERT(gpr_atm_no_barrier_load(&resource_user->refs) == 0); for (int i = 0; i < GRPC_RULIST_COUNT; i++) { rulist_remove(resource_user, (grpc_rulist)i); } grpc_closure_sched(exec_ctx, resource_user->reclaimers[0], GRPC_ERROR_CANCELLED); grpc_closure_sched(exec_ctx, resource_user->reclaimers[1], GRPC_ERROR_CANCELLED); if (resource_user->free_pool != 0) { resource_user->resource_quota->free_pool += resource_user->free_pool; rq_step_sched(exec_ctx, resource_user->resource_quota); } grpc_resource_quota_unref_internal(exec_ctx, resource_user->resource_quota); gpr_mu_destroy(&resource_user->mu); gpr_free(resource_user->name); gpr_free(resource_user); } static void ru_allocated_slices(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_resource_user_slice_allocator *slice_allocator = arg; if (error == GRPC_ERROR_NONE) { for (size_t i = 0; i < slice_allocator->count; i++) { grpc_slice_buffer_add_indexed( slice_allocator->dest, ru_slice_create(slice_allocator->resource_user, slice_allocator->length)); } } grpc_closure_run(exec_ctx, &slice_allocator->on_done, GRPC_ERROR_REF(error)); } /******************************************************************************* * grpc_resource_quota internal implementation: quota manipulation under the * combiner */ typedef struct { int64_t size; grpc_resource_quota *resource_quota; grpc_closure closure; } rq_resize_args; static void rq_resize(grpc_exec_ctx *exec_ctx, void *args, grpc_error *error) { rq_resize_args *a = args; int64_t delta = a->size - a->resource_quota->size; a->resource_quota->size += delta; a->resource_quota->free_pool += delta; rq_update_estimate(a->resource_quota); rq_step_sched(exec_ctx, a->resource_quota); grpc_resource_quota_unref_internal(exec_ctx, a->resource_quota); gpr_free(a); } static void rq_reclamation_done(grpc_exec_ctx *exec_ctx, void *rq, grpc_error *error) { grpc_resource_quota *resource_quota = rq; resource_quota->reclaiming = false; rq_step_sched(exec_ctx, resource_quota); grpc_resource_quota_unref_internal(exec_ctx, resource_quota); } /******************************************************************************* * grpc_resource_quota api */ /* Public API */ grpc_resource_quota *grpc_resource_quota_create(const char *name) { grpc_resource_quota *resource_quota = gpr_malloc(sizeof(*resource_quota)); gpr_ref_init(&resource_quota->refs, 1); resource_quota->combiner = grpc_combiner_create(NULL); resource_quota->free_pool = INT64_MAX; resource_quota->size = INT64_MAX; gpr_atm_no_barrier_store(&resource_quota->last_size, GPR_ATM_MAX); resource_quota->step_scheduled = false; resource_quota->reclaiming = false; gpr_atm_no_barrier_store(&resource_quota->memory_usage_estimation, 0); if (name != NULL) { resource_quota->name = gpr_strdup(name); } else { gpr_asprintf(&resource_quota->name, "anonymous_pool_%" PRIxPTR, (intptr_t)resource_quota); } grpc_closure_init( &resource_quota->rq_step_closure, rq_step, resource_quota, grpc_combiner_finally_scheduler(resource_quota->combiner, true)); grpc_closure_init(&resource_quota->rq_reclamation_done_closure, rq_reclamation_done, resource_quota, grpc_combiner_scheduler(resource_quota->combiner, false)); for (int i = 0; i < GRPC_RULIST_COUNT; i++) { resource_quota->roots[i] = NULL; } return resource_quota; } void grpc_resource_quota_unref_internal(grpc_exec_ctx *exec_ctx, grpc_resource_quota *resource_quota) { if (gpr_unref(&resource_quota->refs)) { GRPC_COMBINER_UNREF(exec_ctx, resource_quota->combiner, "resource_quota"); gpr_free(resource_quota->name); gpr_free(resource_quota); } } /* Public API */ void grpc_resource_quota_unref(grpc_resource_quota *resource_quota) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); grpc_exec_ctx_finish(&exec_ctx); } grpc_resource_quota *grpc_resource_quota_ref_internal( grpc_resource_quota *resource_quota) { gpr_ref(&resource_quota->refs); return resource_quota; } /* Public API */ void grpc_resource_quota_ref(grpc_resource_quota *resource_quota) { grpc_resource_quota_ref_internal(resource_quota); } double grpc_resource_quota_get_memory_pressure( grpc_resource_quota *resource_quota) { return ((double)(gpr_atm_no_barrier_load( &resource_quota->memory_usage_estimation))) / ((double)MEMORY_USAGE_ESTIMATION_MAX); } /* Public API */ void grpc_resource_quota_resize(grpc_resource_quota *resource_quota, size_t size) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; rq_resize_args *a = gpr_malloc(sizeof(*a)); a->resource_quota = grpc_resource_quota_ref_internal(resource_quota); a->size = (int64_t)size; gpr_atm_no_barrier_store(&resource_quota->last_size, (gpr_atm)GPR_MIN((size_t)GPR_ATM_MAX, size)); grpc_closure_init(&a->closure, rq_resize, a, grpc_schedule_on_exec_ctx); grpc_closure_sched(&exec_ctx, &a->closure, GRPC_ERROR_NONE); grpc_exec_ctx_finish(&exec_ctx); } size_t grpc_resource_quota_peek_size(grpc_resource_quota *resource_quota) { return (size_t)gpr_atm_no_barrier_load(&resource_quota->last_size); } /******************************************************************************* * grpc_resource_user channel args api */ grpc_resource_quota *grpc_resource_quota_from_channel_args( const grpc_channel_args *channel_args) { for (size_t i = 0; i < channel_args->num_args; i++) { if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_RESOURCE_QUOTA)) { if (channel_args->args[i].type == GRPC_ARG_POINTER) { return grpc_resource_quota_ref_internal( channel_args->args[i].value.pointer.p); } else { gpr_log(GPR_DEBUG, GRPC_ARG_RESOURCE_QUOTA " should be a pointer"); } } } return grpc_resource_quota_create(NULL); } static void *rq_copy(void *rq) { grpc_resource_quota_ref(rq); return rq; } static void rq_destroy(grpc_exec_ctx *exec_ctx, void *rq) { grpc_resource_quota_unref_internal(exec_ctx, rq); } static int rq_cmp(void *a, void *b) { return GPR_ICMP(a, b); } const grpc_arg_pointer_vtable *grpc_resource_quota_arg_vtable(void) { static const grpc_arg_pointer_vtable vtable = {rq_copy, rq_destroy, rq_cmp}; return &vtable; } /******************************************************************************* * grpc_resource_user api */ grpc_resource_user *grpc_resource_user_create( grpc_resource_quota *resource_quota, const char *name) { grpc_resource_user *resource_user = gpr_malloc(sizeof(*resource_user)); resource_user->resource_quota = grpc_resource_quota_ref_internal(resource_quota); grpc_closure_init(&resource_user->allocate_closure, &ru_allocate, resource_user, grpc_combiner_scheduler(resource_quota->combiner, false)); grpc_closure_init(&resource_user->add_to_free_pool_closure, &ru_add_to_free_pool, resource_user, grpc_combiner_scheduler(resource_quota->combiner, false)); grpc_closure_init(&resource_user->post_reclaimer_closure[0], &ru_post_benign_reclaimer, resource_user, grpc_combiner_scheduler(resource_quota->combiner, false)); grpc_closure_init(&resource_user->post_reclaimer_closure[1], &ru_post_destructive_reclaimer, resource_user, grpc_combiner_scheduler(resource_quota->combiner, false)); grpc_closure_init(&resource_user->destroy_closure, &ru_destroy, resource_user, grpc_combiner_scheduler(resource_quota->combiner, false)); gpr_mu_init(&resource_user->mu); gpr_atm_rel_store(&resource_user->refs, 1); gpr_atm_rel_store(&resource_user->shutdown, 0); resource_user->free_pool = 0; grpc_closure_list_init(&resource_user->on_allocated); resource_user->allocating = false; resource_user->added_to_free_pool = false; resource_user->reclaimers[0] = NULL; resource_user->reclaimers[1] = NULL; resource_user->new_reclaimers[0] = NULL; resource_user->new_reclaimers[1] = NULL; for (int i = 0; i < GRPC_RULIST_COUNT; i++) { resource_user->links[i].next = resource_user->links[i].prev = NULL; } if (name != NULL) { resource_user->name = gpr_strdup(name); } else { gpr_asprintf(&resource_user->name, "anonymous_resource_user_%" PRIxPTR, (intptr_t)resource_user); } return resource_user; } grpc_resource_quota *grpc_resource_user_quota( grpc_resource_user *resource_user) { return resource_user->resource_quota; } static void ru_ref_by(grpc_resource_user *resource_user, gpr_atm amount) { GPR_ASSERT(amount > 0); GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&resource_user->refs, amount) != 0); } static void ru_unref_by(grpc_exec_ctx *exec_ctx, grpc_resource_user *resource_user, gpr_atm amount) { GPR_ASSERT(amount > 0); gpr_atm old = gpr_atm_full_fetch_add(&resource_user->refs, -amount); GPR_ASSERT(old >= amount); if (old == amount) { grpc_closure_sched(exec_ctx, &resource_user->destroy_closure, GRPC_ERROR_NONE); } } void grpc_resource_user_ref(grpc_resource_user *resource_user) { ru_ref_by(resource_user, 1); } void grpc_resource_user_unref(grpc_exec_ctx *exec_ctx, grpc_resource_user *resource_user) { ru_unref_by(exec_ctx, resource_user, 1); } void grpc_resource_user_shutdown(grpc_exec_ctx *exec_ctx, grpc_resource_user *resource_user) { if (gpr_atm_full_fetch_add(&resource_user->shutdown, 1) == 0) { grpc_closure_sched(exec_ctx, grpc_closure_create( ru_shutdown, resource_user, grpc_combiner_scheduler( resource_user->resource_quota->combiner, false)), GRPC_ERROR_NONE); } } void grpc_resource_user_alloc(grpc_exec_ctx *exec_ctx, grpc_resource_user *resource_user, size_t size, grpc_closure *optional_on_done) { gpr_mu_lock(&resource_user->mu); ru_ref_by(resource_user, (gpr_atm)size); resource_user->free_pool -= (int64_t)size; if (grpc_resource_quota_trace) { gpr_log(GPR_DEBUG, "RQ %s %s: alloc %" PRIdPTR "; free_pool -> %" PRId64, resource_user->resource_quota->name, resource_user->name, size, resource_user->free_pool); } if (resource_user->free_pool < 0) { grpc_closure_list_append(&resource_user->on_allocated, optional_on_done, GRPC_ERROR_NONE); if (!resource_user->allocating) { resource_user->allocating = true; grpc_closure_sched(exec_ctx, &resource_user->allocate_closure, GRPC_ERROR_NONE); } } else { grpc_closure_sched(exec_ctx, optional_on_done, GRPC_ERROR_NONE); } gpr_mu_unlock(&resource_user->mu); } void grpc_resource_user_free(grpc_exec_ctx *exec_ctx, grpc_resource_user *resource_user, size_t size) { gpr_mu_lock(&resource_user->mu); bool was_zero_or_negative = resource_user->free_pool <= 0; resource_user->free_pool += (int64_t)size; if (grpc_resource_quota_trace) { gpr_log(GPR_DEBUG, "RQ %s %s: free %" PRIdPTR "; free_pool -> %" PRId64, resource_user->resource_quota->name, resource_user->name, size, resource_user->free_pool); } bool is_bigger_than_zero = resource_user->free_pool > 0; if (is_bigger_than_zero && was_zero_or_negative && !resource_user->added_to_free_pool) { resource_user->added_to_free_pool = true; grpc_closure_sched(exec_ctx, &resource_user->add_to_free_pool_closure, GRPC_ERROR_NONE); } gpr_mu_unlock(&resource_user->mu); ru_unref_by(exec_ctx, resource_user, (gpr_atm)size); } void grpc_resource_user_post_reclaimer(grpc_exec_ctx *exec_ctx, grpc_resource_user *resource_user, bool destructive, grpc_closure *closure) { GPR_ASSERT(resource_user->new_reclaimers[destructive] == NULL); resource_user->new_reclaimers[destructive] = closure; grpc_closure_sched(exec_ctx, &resource_user->post_reclaimer_closure[destructive], GRPC_ERROR_NONE); } void grpc_resource_user_finish_reclamation(grpc_exec_ctx *exec_ctx, grpc_resource_user *resource_user) { if (grpc_resource_quota_trace) { gpr_log(GPR_DEBUG, "RQ %s %s: reclamation complete", resource_user->resource_quota->name, resource_user->name); } grpc_closure_sched( exec_ctx, &resource_user->resource_quota->rq_reclamation_done_closure, GRPC_ERROR_NONE); } void grpc_resource_user_slice_allocator_init( grpc_resource_user_slice_allocator *slice_allocator, grpc_resource_user *resource_user, grpc_iomgr_cb_func cb, void *p) { grpc_closure_init(&slice_allocator->on_allocated, ru_allocated_slices, slice_allocator, grpc_schedule_on_exec_ctx); grpc_closure_init(&slice_allocator->on_done, cb, p, grpc_schedule_on_exec_ctx); slice_allocator->resource_user = resource_user; } void grpc_resource_user_alloc_slices( grpc_exec_ctx *exec_ctx, grpc_resource_user_slice_allocator *slice_allocator, size_t length, size_t count, grpc_slice_buffer *dest) { slice_allocator->length = length; slice_allocator->count = count; slice_allocator->dest = dest; grpc_resource_user_alloc(exec_ctx, slice_allocator->resource_user, count * length, &slice_allocator->on_allocated); } grpc_slice grpc_resource_user_slice_malloc(grpc_exec_ctx *exec_ctx, grpc_resource_user *resource_user, size_t size) { grpc_resource_user_alloc(exec_ctx, resource_user, size, NULL); return ru_slice_create(resource_user, size); } grpc-1.3.2/src/core/lib/iomgr/resource_quota.h000066400000000000000000000173171310511640000212630ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_RESOURCE_QUOTA_H #define GRPC_CORE_LIB_IOMGR_RESOURCE_QUOTA_H #include #include "src/core/lib/iomgr/exec_ctx.h" /** \file Tracks resource usage against a pool. The current implementation tracks only memory usage, but in the future this may be extended to (for example) threads and file descriptors. A grpc_resource_quota represents the pooled resources, and grpc_resource_user instances attach to the quota and consume those resources. They also offer a vector for reclamation: if we become resource constrained, grpc_resource_user instances are asked (in turn) to free up whatever they can so that the system as a whole can make progress. There are three kinds of reclamation that take place, in order of increasing invasiveness: - an internal reclamation, where cached resource at the resource user level is returned to the quota - a benign reclamation phase, whereby resources that are in use but are not helping anything make progress are reclaimed - a destructive reclamation, whereby resources that are helping something make progress may be enacted so that at least one part of the system can complete. Only one reclamation will be outstanding for a given quota at a given time. On each reclamation attempt, the kinds of reclamation are tried in order of increasing invasiveness, stopping at the first one that succeeds. Thus, on a given reclamation attempt, if internal and benign reclamation both fail, it will wind up doing a destructive reclamation. However, the next reclamation attempt may then be able to get what it needs via internal or benign reclamation, due to resources that may have been freed up by the destructive reclamation in the previous attempt. Future work will be to expose the current resource pressure so that back pressure can be applied to avoid reclamation phases starting. Resource users own references to resource quotas, and resource quotas maintain lists of users (which users arrange to leave before they are destroyed) */ extern int grpc_resource_quota_trace; grpc_resource_quota *grpc_resource_quota_ref_internal( grpc_resource_quota *resource_quota); void grpc_resource_quota_unref_internal(grpc_exec_ctx *exec_ctx, grpc_resource_quota *resource_quota); grpc_resource_quota *grpc_resource_quota_from_channel_args( const grpc_channel_args *channel_args); /* Return a number indicating current memory pressure: 0.0 ==> no memory usage 1.0 ==> maximum memory usage */ double grpc_resource_quota_get_memory_pressure( grpc_resource_quota *resource_quota); size_t grpc_resource_quota_peek_size(grpc_resource_quota *resource_quota); typedef struct grpc_resource_user grpc_resource_user; grpc_resource_user *grpc_resource_user_create( grpc_resource_quota *resource_quota, const char *name); /* Returns a borrowed reference to the underlying resource quota for this resource user. */ grpc_resource_quota *grpc_resource_user_quota( grpc_resource_user *resource_user); void grpc_resource_user_ref(grpc_resource_user *resource_user); void grpc_resource_user_unref(grpc_exec_ctx *exec_ctx, grpc_resource_user *resource_user); void grpc_resource_user_shutdown(grpc_exec_ctx *exec_ctx, grpc_resource_user *resource_user); /* Allocate from the resource user (and its quota). If optional_on_done is NULL, then allocate immediately. This may push the quota over-limit, at which point reclamation will kick in. If optional_on_done is non-NULL, it will be scheduled when the allocation has been granted by the quota. */ void grpc_resource_user_alloc(grpc_exec_ctx *exec_ctx, grpc_resource_user *resource_user, size_t size, grpc_closure *optional_on_done); /* Release memory back to the quota */ void grpc_resource_user_free(grpc_exec_ctx *exec_ctx, grpc_resource_user *resource_user, size_t size); /* Post a memory reclaimer to the resource user. Only one benign and one destructive reclaimer can be posted at once. When executed, the reclaimer MUST call grpc_resource_user_finish_reclamation before it completes, to return control to the resource quota. */ void grpc_resource_user_post_reclaimer(grpc_exec_ctx *exec_ctx, grpc_resource_user *resource_user, bool destructive, grpc_closure *closure); /* Finish a reclamation step */ void grpc_resource_user_finish_reclamation(grpc_exec_ctx *exec_ctx, grpc_resource_user *resource_user); /* Helper to allocate slices from a resource user */ typedef struct grpc_resource_user_slice_allocator { /* Closure for when a resource user allocation completes */ grpc_closure on_allocated; /* Closure to call when slices have been allocated */ grpc_closure on_done; /* Length of slices to allocate on the current request */ size_t length; /* Number of slices to allocate on the current request */ size_t count; /* Destination for slices to allocate on the current request */ grpc_slice_buffer *dest; /* Parent resource user */ grpc_resource_user *resource_user; } grpc_resource_user_slice_allocator; /* Initialize a slice allocator. When an allocation is completed, calls \a cb with arg \p. */ void grpc_resource_user_slice_allocator_init( grpc_resource_user_slice_allocator *slice_allocator, grpc_resource_user *resource_user, grpc_iomgr_cb_func cb, void *p); /* Allocate \a count slices of length \a length into \a dest. Only one request can be outstanding at a time. */ void grpc_resource_user_alloc_slices( grpc_exec_ctx *exec_ctx, grpc_resource_user_slice_allocator *slice_allocator, size_t length, size_t count, grpc_slice_buffer *dest); /* Allocate one slice of length \a size synchronously. */ grpc_slice grpc_resource_user_slice_malloc(grpc_exec_ctx *exec_ctx, grpc_resource_user *resource_user, size_t size); #endif /* GRPC_CORE_LIB_IOMGR_RESOURCE_QUOTA_H */ grpc-1.3.2/src/core/lib/iomgr/sockaddr.h000066400000000000000000000041071310511640000200060ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* This header transitively includes other headers that care about include * order, so it should be included first. As a consequence, it should not be * included in any other header. */ #ifndef GRPC_CORE_LIB_IOMGR_SOCKADDR_H #define GRPC_CORE_LIB_IOMGR_SOCKADDR_H #include "src/core/lib/iomgr/port.h" #ifdef GRPC_UV #include #endif #ifdef GPR_WINDOWS #include "src/core/lib/iomgr/sockaddr_windows.h" #endif #ifdef GRPC_POSIX_SOCKETADDR #include "src/core/lib/iomgr/sockaddr_posix.h" #endif #endif /* GRPC_CORE_LIB_IOMGR_SOCKADDR_H */ grpc-1.3.2/src/core/lib/iomgr/sockaddr_posix.h000066400000000000000000000034651310511640000212360ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_SOCKADDR_POSIX_H #define GRPC_CORE_LIB_IOMGR_SOCKADDR_POSIX_H #include #include #include #include #include #include #endif /* GRPC_CORE_LIB_IOMGR_SOCKADDR_POSIX_H */ grpc-1.3.2/src/core/lib/iomgr/sockaddr_utils.c000066400000000000000000000236711310511640000212300ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/sockaddr_utils.h" #include #include #include #include #include #include #include #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/socket_utils.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" #include "src/core/lib/support/string.h" static const uint8_t kV4MappedPrefix[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}; int grpc_sockaddr_is_v4mapped(const grpc_resolved_address *resolved_addr, grpc_resolved_address *resolved_addr4_out) { GPR_ASSERT(resolved_addr != resolved_addr4_out); const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr; struct sockaddr_in *addr4_out = resolved_addr4_out == NULL ? NULL : (struct sockaddr_in *)resolved_addr4_out->addr; if (addr->sa_family == AF_INET6) { const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr; if (memcmp(addr6->sin6_addr.s6_addr, kV4MappedPrefix, sizeof(kV4MappedPrefix)) == 0) { if (resolved_addr4_out != NULL) { /* Normalize ::ffff:0.0.0.0/96 to IPv4. */ memset(resolved_addr4_out, 0, sizeof(*resolved_addr4_out)); addr4_out->sin_family = AF_INET; /* s6_addr32 would be nice, but it's non-standard. */ memcpy(&addr4_out->sin_addr, &addr6->sin6_addr.s6_addr[12], 4); addr4_out->sin_port = addr6->sin6_port; resolved_addr4_out->len = sizeof(struct sockaddr_in); } return 1; } } return 0; } int grpc_sockaddr_to_v4mapped(const grpc_resolved_address *resolved_addr, grpc_resolved_address *resolved_addr6_out) { GPR_ASSERT(resolved_addr != resolved_addr6_out); const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr; struct sockaddr_in6 *addr6_out = (struct sockaddr_in6 *)resolved_addr6_out->addr; if (addr->sa_family == AF_INET) { const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr; memset(resolved_addr6_out, 0, sizeof(*resolved_addr6_out)); addr6_out->sin6_family = AF_INET6; memcpy(&addr6_out->sin6_addr.s6_addr[0], kV4MappedPrefix, 12); memcpy(&addr6_out->sin6_addr.s6_addr[12], &addr4->sin_addr, 4); addr6_out->sin6_port = addr4->sin_port; resolved_addr6_out->len = sizeof(struct sockaddr_in6); return 1; } return 0; } int grpc_sockaddr_is_wildcard(const grpc_resolved_address *resolved_addr, int *port_out) { const struct sockaddr *addr; grpc_resolved_address addr4_normalized; if (grpc_sockaddr_is_v4mapped(resolved_addr, &addr4_normalized)) { resolved_addr = &addr4_normalized; } addr = (const struct sockaddr *)resolved_addr->addr; if (addr->sa_family == AF_INET) { /* Check for 0.0.0.0 */ const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr; if (addr4->sin_addr.s_addr != 0) { return 0; } *port_out = ntohs(addr4->sin_port); return 1; } else if (addr->sa_family == AF_INET6) { /* Check for :: */ const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr; int i; for (i = 0; i < 16; i++) { if (addr6->sin6_addr.s6_addr[i] != 0) { return 0; } } *port_out = ntohs(addr6->sin6_port); return 1; } else { return 0; } } void grpc_sockaddr_make_wildcards(int port, grpc_resolved_address *wild4_out, grpc_resolved_address *wild6_out) { grpc_sockaddr_make_wildcard4(port, wild4_out); grpc_sockaddr_make_wildcard6(port, wild6_out); } void grpc_sockaddr_make_wildcard4(int port, grpc_resolved_address *resolved_wild_out) { struct sockaddr_in *wild_out = (struct sockaddr_in *)resolved_wild_out->addr; GPR_ASSERT(port >= 0 && port < 65536); memset(resolved_wild_out, 0, sizeof(*resolved_wild_out)); wild_out->sin_family = AF_INET; wild_out->sin_port = htons((uint16_t)port); resolved_wild_out->len = sizeof(struct sockaddr_in); } void grpc_sockaddr_make_wildcard6(int port, grpc_resolved_address *resolved_wild_out) { struct sockaddr_in6 *wild_out = (struct sockaddr_in6 *)resolved_wild_out->addr; GPR_ASSERT(port >= 0 && port < 65536); memset(resolved_wild_out, 0, sizeof(*resolved_wild_out)); wild_out->sin6_family = AF_INET6; wild_out->sin6_port = htons((uint16_t)port); resolved_wild_out->len = sizeof(struct sockaddr_in6); } int grpc_sockaddr_to_string(char **out, const grpc_resolved_address *resolved_addr, int normalize) { const struct sockaddr *addr; const int save_errno = errno; grpc_resolved_address addr_normalized; char ntop_buf[INET6_ADDRSTRLEN]; const void *ip = NULL; int port; uint32_t sin6_scope_id = 0; int ret; *out = NULL; if (normalize && grpc_sockaddr_is_v4mapped(resolved_addr, &addr_normalized)) { resolved_addr = &addr_normalized; } addr = (const struct sockaddr *)resolved_addr->addr; if (addr->sa_family == AF_INET) { const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr; ip = &addr4->sin_addr; port = ntohs(addr4->sin_port); } else if (addr->sa_family == AF_INET6) { const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr; ip = &addr6->sin6_addr; port = ntohs(addr6->sin6_port); sin6_scope_id = addr6->sin6_scope_id; } if (ip != NULL && grpc_inet_ntop(addr->sa_family, ip, ntop_buf, sizeof(ntop_buf)) != NULL) { if (sin6_scope_id != 0) { char *host_with_scope; /* Enclose sin6_scope_id with the format defined in RFC 6784 section 2. */ gpr_asprintf(&host_with_scope, "%s%%25%" PRIu32, ntop_buf, sin6_scope_id); ret = gpr_join_host_port(out, host_with_scope, port); gpr_free(host_with_scope); } else { ret = gpr_join_host_port(out, ntop_buf, port); } } else { ret = gpr_asprintf(out, "(sockaddr family=%d)", addr->sa_family); } /* This is probably redundant, but we wouldn't want to log the wrong error. */ errno = save_errno; return ret; } char *grpc_sockaddr_to_uri(const grpc_resolved_address *resolved_addr) { grpc_resolved_address addr_normalized; if (grpc_sockaddr_is_v4mapped(resolved_addr, &addr_normalized)) { resolved_addr = &addr_normalized; } const char *scheme = grpc_sockaddr_get_uri_scheme(resolved_addr); if (scheme == NULL || strcmp("unix", scheme) == 0) { return grpc_sockaddr_to_uri_unix_if_possible(resolved_addr); } char *path = NULL; char *uri_str = NULL; if (grpc_sockaddr_to_string(&path, resolved_addr, false /* suppress errors */) && scheme != NULL) { gpr_asprintf(&uri_str, "%s:%s", scheme, path); } gpr_free(path); return uri_str != NULL ? uri_str : NULL; } const char *grpc_sockaddr_get_uri_scheme( const grpc_resolved_address *resolved_addr) { const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr; switch (addr->sa_family) { case AF_INET: return "ipv4"; case AF_INET6: return "ipv6"; case AF_UNIX: return "unix"; } return NULL; } int grpc_sockaddr_get_port(const grpc_resolved_address *resolved_addr) { const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr; switch (addr->sa_family) { case AF_INET: return ntohs(((struct sockaddr_in *)addr)->sin_port); case AF_INET6: return ntohs(((struct sockaddr_in6 *)addr)->sin6_port); default: if (grpc_is_unix_socket(resolved_addr)) { return 1; } gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_get_port", addr->sa_family); return 0; } } int grpc_sockaddr_set_port(const grpc_resolved_address *resolved_addr, int port) { const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr; switch (addr->sa_family) { case AF_INET: GPR_ASSERT(port >= 0 && port < 65536); ((struct sockaddr_in *)addr)->sin_port = htons((uint16_t)port); return 1; case AF_INET6: GPR_ASSERT(port >= 0 && port < 65536); ((struct sockaddr_in6 *)addr)->sin6_port = htons((uint16_t)port); return 1; default: gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_set_port", addr->sa_family); return 0; } } grpc-1.3.2/src/core/lib/iomgr/sockaddr_utils.h000066400000000000000000000101211310511640000212170ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_SOCKADDR_UTILS_H #define GRPC_CORE_LIB_IOMGR_SOCKADDR_UTILS_H #include "src/core/lib/iomgr/resolve_address.h" /* Returns true if addr is an IPv4-mapped IPv6 address within the ::ffff:0.0.0.0/96 range, or false otherwise. If addr4_out is non-NULL, the inner IPv4 address will be copied here when returning true. */ int grpc_sockaddr_is_v4mapped(const grpc_resolved_address *addr, grpc_resolved_address *addr4_out); /* If addr is an AF_INET address, writes the corresponding ::ffff:0.0.0.0/96 address to addr6_out and returns true. Otherwise returns false. */ int grpc_sockaddr_to_v4mapped(const grpc_resolved_address *addr, grpc_resolved_address *addr6_out); /* If addr is ::, 0.0.0.0, or ::ffff:0.0.0.0, writes the port number to *port_out (if not NULL) and returns true, otherwise returns false. */ int grpc_sockaddr_is_wildcard(const grpc_resolved_address *addr, int *port_out); /* Writes 0.0.0.0:port and [::]:port to separate sockaddrs. */ void grpc_sockaddr_make_wildcards(int port, grpc_resolved_address *wild4_out, grpc_resolved_address *wild6_out); /* Writes 0.0.0.0:port. */ void grpc_sockaddr_make_wildcard4(int port, grpc_resolved_address *wild_out); /* Writes [::]:port. */ void grpc_sockaddr_make_wildcard6(int port, grpc_resolved_address *wild_out); /* Return the IP port number of a sockaddr */ int grpc_sockaddr_get_port(const grpc_resolved_address *addr); /* Set IP port number of a sockaddr */ int grpc_sockaddr_set_port(const grpc_resolved_address *addr, int port); /* Converts a sockaddr into a newly-allocated human-readable string. Currently, only the AF_INET and AF_INET6 families are recognized. If the normalize flag is enabled, ::ffff:0.0.0.0/96 IPv6 addresses are displayed as plain IPv4. Usage is similar to gpr_asprintf: returns the number of bytes written (excluding the final '\0'), and *out points to a string which must later be destroyed using gpr_free(). In the unlikely event of an error, returns -1 and sets *out to NULL. The existing value of errno is always preserved. */ int grpc_sockaddr_to_string(char **out, const grpc_resolved_address *addr, int normalize); /* Returns the URI string corresponding to \a addr */ char *grpc_sockaddr_to_uri(const grpc_resolved_address *addr); /* Returns the URI scheme corresponding to \a addr */ const char *grpc_sockaddr_get_uri_scheme(const grpc_resolved_address *addr); #endif /* GRPC_CORE_LIB_IOMGR_SOCKADDR_UTILS_H */ grpc-1.3.2/src/core/lib/iomgr/sockaddr_windows.h000066400000000000000000000034341310511640000215620ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_SOCKADDR_WINDOWS_H #define GRPC_CORE_LIB_IOMGR_SOCKADDR_WINDOWS_H #include #include // must be included after the above #include #endif /* GRPC_CORE_LIB_IOMGR_SOCKADDR_WINDOWS_H */ grpc-1.3.2/src/core/lib/iomgr/socket_factory_posix.c000066400000000000000000000073461310511640000224600ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_POSIX_SOCKET #include "src/core/lib/iomgr/socket_factory_posix.h" #include #include #include void grpc_socket_factory_init(grpc_socket_factory *factory, const grpc_socket_factory_vtable *vtable) { factory->vtable = vtable; gpr_ref_init(&factory->refcount, 1); } int grpc_socket_factory_socket(grpc_socket_factory *factory, int domain, int type, int protocol) { return factory->vtable->socket(factory, domain, type, protocol); } int grpc_socket_factory_bind(grpc_socket_factory *factory, int sockfd, const grpc_resolved_address *addr) { return factory->vtable->bind(factory, sockfd, addr); } int grpc_socket_factory_compare(grpc_socket_factory *a, grpc_socket_factory *b) { int c = GPR_ICMP(a, b); if (c != 0) { grpc_socket_factory *sma = a; grpc_socket_factory *smb = b; c = GPR_ICMP(sma->vtable, smb->vtable); if (c == 0) { c = sma->vtable->compare(sma, smb); } } return c; } grpc_socket_factory *grpc_socket_factory_ref(grpc_socket_factory *factory) { gpr_ref(&factory->refcount); return factory; } void grpc_socket_factory_unref(grpc_socket_factory *factory) { if (gpr_unref(&factory->refcount)) { factory->vtable->destroy(factory); } } static void *socket_factory_arg_copy(void *p) { return grpc_socket_factory_ref(p); } static void socket_factory_arg_destroy(grpc_exec_ctx *exec_ctx, void *p) { grpc_socket_factory_unref(p); } static int socket_factory_cmp(void *a, void *b) { return grpc_socket_factory_compare((grpc_socket_factory *)a, (grpc_socket_factory *)b); } static const grpc_arg_pointer_vtable socket_factory_arg_vtable = { socket_factory_arg_copy, socket_factory_arg_destroy, socket_factory_cmp}; grpc_arg grpc_socket_factory_to_arg(grpc_socket_factory *factory) { grpc_arg arg; arg.type = GRPC_ARG_POINTER; arg.key = GRPC_ARG_SOCKET_FACTORY; arg.value.pointer.vtable = &socket_factory_arg_vtable; arg.value.pointer.p = factory; return arg; } #endif grpc-1.3.2/src/core/lib/iomgr/socket_factory_posix.h000066400000000000000000000071431310511640000224600ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_SOCKET_FACTORY_POSIX_H #define GRPC_CORE_LIB_IOMGR_SOCKET_FACTORY_POSIX_H #include #include #include "src/core/lib/iomgr/resolve_address.h" #ifdef __cplusplus extern "C" { #endif /** The virtual table of grpc_socket_factory */ typedef struct { /** Replacement for socket(2) */ int (*socket)(grpc_socket_factory *factory, int domain, int type, int protocol); /** Replacement for bind(2) */ int (*bind)(grpc_socket_factory *factory, int sockfd, const grpc_resolved_address *addr); /** Compare socket factory \a a and \a b */ int (*compare)(grpc_socket_factory *a, grpc_socket_factory *b); /** Destroys the socket factory instance */ void (*destroy)(grpc_socket_factory *factory); } grpc_socket_factory_vtable; /** The Socket Factory interface allows changes on socket options */ struct grpc_socket_factory { const grpc_socket_factory_vtable *vtable; gpr_refcount refcount; }; /** called by concrete implementations to initialize the base struct */ void grpc_socket_factory_init(grpc_socket_factory *factory, const grpc_socket_factory_vtable *vtable); /** Wrap \a factory as a grpc_arg */ grpc_arg grpc_socket_factory_to_arg(grpc_socket_factory *factory); /** Perform the equivalent of a socket(2) operation using \a factory */ int grpc_socket_factory_socket(grpc_socket_factory *factory, int domain, int type, int protocol); /** Perform the equivalent of a bind(2) operation using \a factory */ int grpc_socket_factory_bind(grpc_socket_factory *factory, int sockfd, const grpc_resolved_address *addr); /** Compare if \a a and \a b are the same factory or have same settings */ int grpc_socket_factory_compare(grpc_socket_factory *a, grpc_socket_factory *b); grpc_socket_factory *grpc_socket_factory_ref(grpc_socket_factory *factory); void grpc_socket_factory_unref(grpc_socket_factory *factory); #ifdef __cplusplus } #endif #endif /* GRPC_CORE_LIB_IOMGR_SOCKET_FACTORY_POSIX_H */ grpc-1.3.2/src/core/lib/iomgr/socket_mutator.c000066400000000000000000000066151310511640000212600ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/socket_mutator.h" #include #include #include void grpc_socket_mutator_init(grpc_socket_mutator *mutator, const grpc_socket_mutator_vtable *vtable) { mutator->vtable = vtable; gpr_ref_init(&mutator->refcount, 1); } grpc_socket_mutator *grpc_socket_mutator_ref(grpc_socket_mutator *mutator) { gpr_ref(&mutator->refcount); return mutator; } bool grpc_socket_mutator_mutate_fd(grpc_socket_mutator *mutator, int fd) { return mutator->vtable->mutate_fd(fd, mutator); } int grpc_socket_mutator_compare(grpc_socket_mutator *a, grpc_socket_mutator *b) { int c = GPR_ICMP(a, b); if (c != 0) { grpc_socket_mutator *sma = a; grpc_socket_mutator *smb = b; c = GPR_ICMP(sma->vtable, smb->vtable); if (c == 0) { c = sma->vtable->compare(sma, smb); } } return c; } void grpc_socket_mutator_unref(grpc_socket_mutator *mutator) { if (gpr_unref(&mutator->refcount)) { mutator->vtable->destory(mutator); } } static void *socket_mutator_arg_copy(void *p) { return grpc_socket_mutator_ref(p); } static void socket_mutator_arg_destroy(grpc_exec_ctx *exec_ctx, void *p) { grpc_socket_mutator_unref(p); } static int socket_mutator_cmp(void *a, void *b) { return grpc_socket_mutator_compare((grpc_socket_mutator *)a, (grpc_socket_mutator *)b); } static const grpc_arg_pointer_vtable socket_mutator_arg_vtable = { socket_mutator_arg_copy, socket_mutator_arg_destroy, socket_mutator_cmp}; grpc_arg grpc_socket_mutator_to_arg(grpc_socket_mutator *mutator) { grpc_arg arg; arg.type = GRPC_ARG_POINTER; arg.key = GRPC_ARG_SOCKET_MUTATOR; arg.value.pointer.vtable = &socket_mutator_arg_vtable; arg.value.pointer.p = mutator; return arg; } grpc-1.3.2/src/core/lib/iomgr/socket_mutator.h000066400000000000000000000061671310511640000212670ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_SOCKET_MUTATOR_H #define GRPC_CORE_LIB_IOMGR_SOCKET_MUTATOR_H #include #include #ifdef __cplusplus extern "C" { #endif /** The virtual table of grpc_socket_mutator */ typedef struct { /** Mutates the socket opitons of \a fd */ bool (*mutate_fd)(int fd, grpc_socket_mutator *mutator); /** Compare socket mutator \a a and \a b */ int (*compare)(grpc_socket_mutator *a, grpc_socket_mutator *b); /** Destroys the socket mutator instance */ void (*destory)(grpc_socket_mutator *mutator); } grpc_socket_mutator_vtable; /** The Socket Mutator interface allows changes on socket options */ struct grpc_socket_mutator { const grpc_socket_mutator_vtable *vtable; gpr_refcount refcount; }; /** called by concrete implementations to initialize the base struct */ void grpc_socket_mutator_init(grpc_socket_mutator *mutator, const grpc_socket_mutator_vtable *vtable); /** Wrap \a mutator as a grpc_arg */ grpc_arg grpc_socket_mutator_to_arg(grpc_socket_mutator *mutator); /** Perform the file descriptor mutation operation of \a mutator on \a fd */ bool grpc_socket_mutator_mutate_fd(grpc_socket_mutator *mutator, int fd); /** Compare if \a a and \a b are the same mutator or have same settings */ int grpc_socket_mutator_compare(grpc_socket_mutator *a, grpc_socket_mutator *b); grpc_socket_mutator *grpc_socket_mutator_ref(grpc_socket_mutator *mutator); void grpc_socket_mutator_unref(grpc_socket_mutator *mutator); #ifdef __cplusplus } #endif #endif /* GRPC_CORE_LIB_IOMGR_SOCKET_MUTATOR_H */ grpc-1.3.2/src/core/lib/iomgr/socket_utils.h000066400000000000000000000035331310511640000207260ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_H #define GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_H #include /* A wrapper for inet_ntop on POSIX systems and InetNtop on Windows systems */ const char *grpc_inet_ntop(int af, const void *src, char *dst, size_t size); #endif /* GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_H */ grpc-1.3.2/src/core/lib/iomgr/socket_utils_common_posix.c000066400000000000000000000253721310511640000235200ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_POSIX_SOCKET #include "src/core/lib/iomgr/socket_utils.h" #include "src/core/lib/iomgr/socket_utils_posix.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/support/string.h" /* set a socket to non blocking mode */ grpc_error *grpc_set_socket_nonblocking(int fd, int non_blocking) { int oldflags = fcntl(fd, F_GETFL, 0); if (oldflags < 0) { return GRPC_OS_ERROR(errno, "fcntl"); } if (non_blocking) { oldflags |= O_NONBLOCK; } else { oldflags &= ~O_NONBLOCK; } if (fcntl(fd, F_SETFL, oldflags) != 0) { return GRPC_OS_ERROR(errno, "fcntl"); } return GRPC_ERROR_NONE; } grpc_error *grpc_set_socket_no_sigpipe_if_possible(int fd) { #ifdef GRPC_HAVE_SO_NOSIGPIPE int val = 1; int newval; socklen_t intlen = sizeof(newval); if (0 != setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(val))) { return GRPC_OS_ERROR(errno, "setsockopt(SO_NOSIGPIPE)"); } if (0 != getsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &newval, &intlen)) { return GRPC_OS_ERROR(errno, "getsockopt(SO_NOSIGPIPE)"); } if ((newval != 0) != (val != 0)) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to set SO_NOSIGPIPE"); } #endif return GRPC_ERROR_NONE; } grpc_error *grpc_set_socket_ip_pktinfo_if_possible(int fd) { #ifdef GRPC_HAVE_IP_PKTINFO int get_local_ip = 1; if (0 != setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &get_local_ip, sizeof(get_local_ip))) { return GRPC_OS_ERROR(errno, "setsockopt(IP_PKTINFO)"); } #endif return GRPC_ERROR_NONE; } grpc_error *grpc_set_socket_ipv6_recvpktinfo_if_possible(int fd) { #ifdef GRPC_HAVE_IPV6_RECVPKTINFO int get_local_ip = 1; if (0 != setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &get_local_ip, sizeof(get_local_ip))) { return GRPC_OS_ERROR(errno, "setsockopt(IPV6_RECVPKTINFO)"); } #endif return GRPC_ERROR_NONE; } grpc_error *grpc_set_socket_sndbuf(int fd, int buffer_size_bytes) { return 0 == setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffer_size_bytes, sizeof(buffer_size_bytes)) ? GRPC_ERROR_NONE : GRPC_OS_ERROR(errno, "setsockopt(SO_SNDBUF)"); } grpc_error *grpc_set_socket_rcvbuf(int fd, int buffer_size_bytes) { return 0 == setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buffer_size_bytes, sizeof(buffer_size_bytes)) ? GRPC_ERROR_NONE : GRPC_OS_ERROR(errno, "setsockopt(SO_RCVBUF)"); } /* set a socket to close on exec */ grpc_error *grpc_set_socket_cloexec(int fd, int close_on_exec) { int oldflags = fcntl(fd, F_GETFD, 0); if (oldflags < 0) { return GRPC_OS_ERROR(errno, "fcntl"); } if (close_on_exec) { oldflags |= FD_CLOEXEC; } else { oldflags &= ~FD_CLOEXEC; } if (fcntl(fd, F_SETFD, oldflags) != 0) { return GRPC_OS_ERROR(errno, "fcntl"); } return GRPC_ERROR_NONE; } /* set a socket to reuse old addresses */ grpc_error *grpc_set_socket_reuse_addr(int fd, int reuse) { int val = (reuse != 0); int newval; socklen_t intlen = sizeof(newval); if (0 != setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))) { return GRPC_OS_ERROR(errno, "setsockopt(SO_REUSEADDR)"); } if (0 != getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &newval, &intlen)) { return GRPC_OS_ERROR(errno, "getsockopt(SO_REUSEADDR)"); } if ((newval != 0) != val) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to set SO_REUSEADDR"); } return GRPC_ERROR_NONE; } /* set a socket to reuse old addresses */ grpc_error *grpc_set_socket_reuse_port(int fd, int reuse) { #ifndef SO_REUSEPORT return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "SO_REUSEPORT unavailable on compiling system"); #else int val = (reuse != 0); int newval; socklen_t intlen = sizeof(newval); if (0 != setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val))) { return GRPC_OS_ERROR(errno, "setsockopt(SO_REUSEPORT)"); } if (0 != getsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &newval, &intlen)) { return GRPC_OS_ERROR(errno, "getsockopt(SO_REUSEPORT)"); } if ((newval != 0) != val) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to set SO_REUSEPORT"); } return GRPC_ERROR_NONE; #endif } /* disable nagle */ grpc_error *grpc_set_socket_low_latency(int fd, int low_latency) { int val = (low_latency != 0); int newval; socklen_t intlen = sizeof(newval); if (0 != setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val))) { return GRPC_OS_ERROR(errno, "setsockopt(TCP_NODELAY)"); } if (0 != getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &newval, &intlen)) { return GRPC_OS_ERROR(errno, "getsockopt(TCP_NODELAY)"); } if ((newval != 0) != val) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to set TCP_NODELAY"); } return GRPC_ERROR_NONE; } /* set a socket using a grpc_socket_mutator */ grpc_error *grpc_set_socket_with_mutator(int fd, grpc_socket_mutator *mutator) { GPR_ASSERT(mutator); if (!grpc_socket_mutator_mutate_fd(mutator, fd)) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("grpc_socket_mutator failed."); } return GRPC_ERROR_NONE; } static gpr_once g_probe_ipv6_once = GPR_ONCE_INIT; static int g_ipv6_loopback_available; static void probe_ipv6_once(void) { int fd = socket(AF_INET6, SOCK_STREAM, 0); g_ipv6_loopback_available = 0; if (fd < 0) { gpr_log(GPR_INFO, "Disabling AF_INET6 sockets because socket() failed."); } else { struct sockaddr_in6 addr; memset(&addr, 0, sizeof(addr)); addr.sin6_family = AF_INET6; addr.sin6_addr.s6_addr[15] = 1; /* [::1]:0 */ if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == 0) { g_ipv6_loopback_available = 1; } else { gpr_log(GPR_INFO, "Disabling AF_INET6 sockets because ::1 is not available."); } close(fd); } } int grpc_ipv6_loopback_available(void) { gpr_once_init(&g_probe_ipv6_once, probe_ipv6_once); return g_ipv6_loopback_available; } /* This should be 0 in production, but it may be enabled for testing or debugging purposes, to simulate an environment where IPv6 sockets can't also speak IPv4. */ int grpc_forbid_dualstack_sockets_for_testing = 0; static int set_socket_dualstack(int fd) { if (!grpc_forbid_dualstack_sockets_for_testing) { const int off = 0; return 0 == setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off)); } else { /* Force an IPv6-only socket, for testing purposes. */ const int on = 1; setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); return 0; } } static grpc_error *error_for_fd(int fd, const grpc_resolved_address *addr) { if (fd >= 0) return GRPC_ERROR_NONE; char *addr_str; grpc_sockaddr_to_string(&addr_str, addr, 0); grpc_error *err = grpc_error_set_str(GRPC_OS_ERROR(errno, "socket"), GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(addr_str)); gpr_free(addr_str); return err; } grpc_error *grpc_create_dualstack_socket( const grpc_resolved_address *resolved_addr, int type, int protocol, grpc_dualstack_mode *dsmode, int *newfd) { return grpc_create_dualstack_socket_using_factory(NULL, resolved_addr, type, protocol, dsmode, newfd); } static int create_socket(grpc_socket_factory *factory, int domain, int type, int protocol) { return (factory != NULL) ? grpc_socket_factory_socket(factory, domain, type, protocol) : socket(domain, type, protocol); } grpc_error *grpc_create_dualstack_socket_using_factory( grpc_socket_factory *factory, const grpc_resolved_address *resolved_addr, int type, int protocol, grpc_dualstack_mode *dsmode, int *newfd) { const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr; int family = addr->sa_family; if (family == AF_INET6) { if (grpc_ipv6_loopback_available()) { *newfd = create_socket(factory, family, type, protocol); } else { *newfd = -1; errno = EAFNOSUPPORT; } /* Check if we've got a valid dualstack socket. */ if (*newfd >= 0 && set_socket_dualstack(*newfd)) { *dsmode = GRPC_DSMODE_DUALSTACK; return GRPC_ERROR_NONE; } /* If this isn't an IPv4 address, then return whatever we've got. */ if (!grpc_sockaddr_is_v4mapped(resolved_addr, NULL)) { *dsmode = GRPC_DSMODE_IPV6; return error_for_fd(*newfd, resolved_addr); } /* Fall back to AF_INET. */ if (*newfd >= 0) { close(*newfd); } family = AF_INET; } *dsmode = family == AF_INET ? GRPC_DSMODE_IPV4 : GRPC_DSMODE_NONE; *newfd = create_socket(factory, family, type, protocol); return error_for_fd(*newfd, resolved_addr); } const char *grpc_inet_ntop(int af, const void *src, char *dst, size_t size) { GPR_ASSERT(size <= (socklen_t)-1); return inet_ntop(af, src, dst, (socklen_t)size); } #endif grpc-1.3.2/src/core/lib/iomgr/socket_utils_linux.c000066400000000000000000000043211310511640000221340ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_LINUX_SOCKETUTILS #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/socket_utils_posix.h" #include #include #include int grpc_accept4(int sockfd, grpc_resolved_address *resolved_addr, int nonblock, int cloexec) { int flags = 0; GPR_ASSERT(sizeof(socklen_t) <= sizeof(size_t)); GPR_ASSERT(resolved_addr->len <= (socklen_t)-1); flags |= nonblock ? SOCK_NONBLOCK : 0; flags |= cloexec ? SOCK_CLOEXEC : 0; return accept4(sockfd, (struct sockaddr *)resolved_addr->addr, (socklen_t *)&resolved_addr->len, flags); } #endif grpc-1.3.2/src/core/lib/iomgr/socket_utils_posix.c000066400000000000000000000051341310511640000221420ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_POSIX_SOCKETUTILS #include "src/core/lib/iomgr/socket_utils_posix.h" #include #include #include #include #include "src/core/lib/iomgr/sockaddr.h" int grpc_accept4(int sockfd, grpc_resolved_address *resolved_addr, int nonblock, int cloexec) { int fd, flags; GPR_ASSERT(sizeof(socklen_t) <= sizeof(size_t)); GPR_ASSERT(resolved_addr->len <= (socklen_t)-1); fd = accept(sockfd, (struct sockaddr *)resolved_addr->addr, (socklen_t *)&resolved_addr->len); if (fd >= 0) { if (nonblock) { flags = fcntl(fd, F_GETFL, 0); if (flags < 0) goto close_and_error; if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) != 0) goto close_and_error; } if (cloexec) { flags = fcntl(fd, F_GETFD, 0); if (flags < 0) goto close_and_error; if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) != 0) goto close_and_error; } } return fd; close_and_error: close(fd); return -1; } #endif /* GRPC_POSIX_SOCKETUTILS */ grpc-1.3.2/src/core/lib/iomgr/socket_utils_posix.h000066400000000000000000000143301310511640000221450ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_POSIX_H #define GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_POSIX_H #include "src/core/lib/iomgr/resolve_address.h" #include #include #include #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/socket_factory_posix.h" #include "src/core/lib/iomgr/socket_mutator.h" /* a wrapper for accept or accept4 */ int grpc_accept4(int sockfd, grpc_resolved_address *resolved_addr, int nonblock, int cloexec); /* set a socket to non blocking mode */ grpc_error *grpc_set_socket_nonblocking(int fd, int non_blocking); /* set a socket to close on exec */ grpc_error *grpc_set_socket_cloexec(int fd, int close_on_exec); /* set a socket to reuse old addresses */ grpc_error *grpc_set_socket_reuse_addr(int fd, int reuse); /* disable nagle */ grpc_error *grpc_set_socket_low_latency(int fd, int low_latency); /* set SO_REUSEPORT */ grpc_error *grpc_set_socket_reuse_port(int fd, int reuse); /* Returns true if this system can create AF_INET6 sockets bound to ::1. The value is probed once, and cached for the life of the process. This is more restrictive than checking for socket(AF_INET6) to succeed, because Linux with "net.ipv6.conf.all.disable_ipv6 = 1" is able to create and bind IPv6 sockets, but cannot connect to a getsockname() of [::]:port without a valid loopback interface. Rather than expose this half-broken state to library users, we turn off IPv6 sockets. */ int grpc_ipv6_loopback_available(void); /* Tries to set SO_NOSIGPIPE if available on this platform. If SO_NO_SIGPIPE is not available, returns 1. */ grpc_error *grpc_set_socket_no_sigpipe_if_possible(int fd); /* Tries to set IP_PKTINFO if available on this platform. If IP_PKTINFO is not available, returns 1. */ grpc_error *grpc_set_socket_ip_pktinfo_if_possible(int fd); /* Tries to set IPV6_RECVPKTINFO if available on this platform. If IPV6_RECVPKTINFO is not available, returns 1. */ grpc_error *grpc_set_socket_ipv6_recvpktinfo_if_possible(int fd); /* Tries to set the socket's send buffer to given size. */ grpc_error *grpc_set_socket_sndbuf(int fd, int buffer_size_bytes); /* Tries to set the socket's receive buffer to given size. */ grpc_error *grpc_set_socket_rcvbuf(int fd, int buffer_size_bytes); /* Tries to set the socket using a grpc_socket_mutator */ grpc_error *grpc_set_socket_with_mutator(int fd, grpc_socket_mutator *mutator); /* An enum to keep track of IPv4/IPv6 socket modes. Currently, this information is only used when a socket is first created, but in the future we may wish to store it alongside the fd. This would let calls like sendto() know which family to use without asking the kernel first. */ typedef enum grpc_dualstack_mode { /* Uninitialized, or a non-IP socket. */ GRPC_DSMODE_NONE, /* AF_INET only. */ GRPC_DSMODE_IPV4, /* AF_INET6 only, because IPV6_V6ONLY could not be cleared. */ GRPC_DSMODE_IPV6, /* AF_INET6, which also supports ::ffff-mapped IPv4 addresses. */ GRPC_DSMODE_DUALSTACK } grpc_dualstack_mode; /* Only tests should use this flag. */ extern int grpc_forbid_dualstack_sockets_for_testing; /* Creates a new socket for connecting to (or listening on) an address. If addr is AF_INET6, this creates an IPv6 socket first. If that fails, and addr is within ::ffff:0.0.0.0/96, then it automatically falls back to an IPv4 socket. If addr is AF_INET, AF_UNIX, or anything else, then this is similar to calling socket() directly. Returns an fd on success, otherwise returns -1 with errno set to the result of a failed socket() call. The *dsmode output indicates which address family was actually created. The recommended way to use this is: - First convert to IPv6 using grpc_sockaddr_to_v4mapped(). - Create the socket. - If *dsmode is IPV4, use grpc_sockaddr_is_v4mapped() to convert back to IPv4, so that bind() or connect() see the correct family. Also, it's important to distinguish between DUALSTACK and IPV6 when listening on the [::] wildcard address. */ grpc_error *grpc_create_dualstack_socket(const grpc_resolved_address *addr, int type, int protocol, grpc_dualstack_mode *dsmode, int *newfd); /* Same as grpc_create_dualstack_socket(), but use the given socket factory (if non-null) to create the socket, rather than calling socket() directly. */ grpc_error *grpc_create_dualstack_socket_using_factory( grpc_socket_factory *factory, const grpc_resolved_address *addr, int type, int protocol, grpc_dualstack_mode *dsmode, int *newfd); #endif /* GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_POSIX_H */ grpc-1.3.2/src/core/lib/iomgr/socket_utils_uv.c000066400000000000000000000035161310511640000214340ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_UV #include #include "src/core/lib/iomgr/socket_utils.h" #include const char *grpc_inet_ntop(int af, const void *src, char *dst, size_t size) { uv_inet_ntop(af, src, dst, size); return dst; } #endif /* GRPC_UV */ grpc-1.3.2/src/core/lib/iomgr/socket_utils_windows.c000066400000000000000000000040411310511640000224660ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_WINDOWS_SOCKETUTILS #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/socket_utils.h" #include const char *grpc_inet_ntop(int af, const void *src, char *dst, size_t size) { #ifdef GPR_WIN_INET_NTOP return inet_ntop(af, src, dst, size); #else /* Windows InetNtopA wants a mutable ip pointer */ return InetNtopA(af, (void *)src, dst, size); #endif /* GPR_WIN_INET_NTOP */ } #endif /* GRPC_WINDOWS_SOCKETUTILS */ grpc-1.3.2/src/core/lib/iomgr/socket_windows.c000066400000000000000000000140771310511640000212600ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_WINSOCK_SOCKET #include // must be included after winsock2.h #include #include #include #include #include #include "src/core/lib/iomgr/iocp_windows.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/pollset_windows.h" #include "src/core/lib/iomgr/socket_windows.h" grpc_winsocket *grpc_winsocket_create(SOCKET socket, const char *name) { char *final_name; grpc_winsocket *r = gpr_malloc(sizeof(grpc_winsocket)); memset(r, 0, sizeof(grpc_winsocket)); r->socket = socket; gpr_mu_init(&r->state_mu); gpr_asprintf(&final_name, "%s:socket=0x%p", name, r); grpc_iomgr_register_object(&r->iomgr_object, final_name); gpr_free(final_name); grpc_iocp_add_socket(r); return r; } /* Schedule a shutdown of the socket operations. Will call the pending operations to abort them. We need to do that this way because of the various callsites of that function, which happens to be in various mutex hold states, and that'd be unsafe to call them directly. */ void grpc_winsocket_shutdown(grpc_winsocket *winsocket) { /* Grab the function pointer for DisconnectEx for that specific socket. It may change depending on the interface. */ int status; GUID guid = WSAID_DISCONNECTEX; LPFN_DISCONNECTEX DisconnectEx; DWORD ioctl_num_bytes; gpr_mu_lock(&winsocket->state_mu); if (winsocket->shutdown_called) { gpr_mu_unlock(&winsocket->state_mu); return; } winsocket->shutdown_called = true; gpr_mu_unlock(&winsocket->state_mu); status = WSAIoctl(winsocket->socket, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid), &DisconnectEx, sizeof(DisconnectEx), &ioctl_num_bytes, NULL, NULL); if (status == 0) { DisconnectEx(winsocket->socket, NULL, 0, 0); } else { char *utf8_message = gpr_format_message(WSAGetLastError()); gpr_log(GPR_INFO, "Unable to retrieve DisconnectEx pointer : %s", utf8_message); gpr_free(utf8_message); } closesocket(winsocket->socket); } static void destroy(grpc_winsocket *winsocket) { grpc_iomgr_unregister_object(&winsocket->iomgr_object); gpr_mu_destroy(&winsocket->state_mu); gpr_free(winsocket); } static bool check_destroyable(grpc_winsocket *winsocket) { return winsocket->destroy_called == true && winsocket->write_info.closure == NULL && winsocket->read_info.closure == NULL; } void grpc_winsocket_destroy(grpc_winsocket *winsocket) { gpr_mu_lock(&winsocket->state_mu); GPR_ASSERT(!winsocket->destroy_called); winsocket->destroy_called = true; bool should_destroy = check_destroyable(winsocket); gpr_mu_unlock(&winsocket->state_mu); if (should_destroy) destroy(winsocket); } /* Calling notify_on_read or write means either of two things: -) The IOCP already completed in the background, and we need to call the callback now. -) The IOCP hasn't completed yet, and we're queuing it for later. */ static void socket_notify_on_iocp(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket, grpc_closure *closure, grpc_winsocket_callback_info *info) { GPR_ASSERT(info->closure == NULL); gpr_mu_lock(&socket->state_mu); if (info->has_pending_iocp) { info->has_pending_iocp = 0; grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_NONE); } else { info->closure = closure; } gpr_mu_unlock(&socket->state_mu); } void grpc_socket_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket, grpc_closure *closure) { socket_notify_on_iocp(exec_ctx, socket, closure, &socket->write_info); } void grpc_socket_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket, grpc_closure *closure) { socket_notify_on_iocp(exec_ctx, socket, closure, &socket->read_info); } void grpc_socket_become_ready(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket, grpc_winsocket_callback_info *info) { GPR_ASSERT(!info->has_pending_iocp); gpr_mu_lock(&socket->state_mu); if (info->closure) { grpc_closure_sched(exec_ctx, info->closure, GRPC_ERROR_NONE); info->closure = NULL; } else { info->has_pending_iocp = 1; } bool should_destroy = check_destroyable(socket); gpr_mu_unlock(&socket->state_mu); if (should_destroy) destroy(socket); } #endif /* GRPC_WINSOCK_SOCKET */ grpc-1.3.2/src/core/lib/iomgr/socket_windows.h000066400000000000000000000126561310511640000212660ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_SOCKET_WINDOWS_H #define GRPC_CORE_LIB_IOMGR_SOCKET_WINDOWS_H #include #include #include #include #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/iomgr_internal.h" /* This holds the data for an outstanding read or write on a socket. The mutex to protect the concurrent access to that data is the one inside the winsocket wrapper. */ typedef struct grpc_winsocket_callback_info { /* This is supposed to be a WSAOVERLAPPED, but in order to get that definition, we need to include ws2tcpip.h, which needs to be included from the top, otherwise it'll clash with a previous inclusion of windows.h that in turns includes winsock.h. If anyone knows a way to do it properly, feel free to send a patch. */ OVERLAPPED overlapped; /* The callback information for the pending operation. May be empty if the caller hasn't registered a callback yet. */ grpc_closure *closure; /* A boolean to describe if the IO Completion Port got a notification for that operation. This will happen if the operation completed before the called had time to register a callback. We could avoid that behavior altogether by forcing the caller to always register its callback before proceeding queue an operation, but it is frequent for an IO Completion Port to trigger quickly. This way we avoid a context switch for calling the callback. We also simplify the read / write operations to avoid having to hold a mutex for a long amount of time. */ int has_pending_iocp; /* The results of the overlapped operation. */ DWORD bytes_transfered; int wsa_error; } grpc_winsocket_callback_info; /* This is a wrapper to a Windows socket. A socket can have one outstanding read, and one outstanding write. Doing an asynchronous accept means waiting for a read operation. Doing an asynchronous connect means waiting for a write operation. These are completely arbitrary ties between the operation and the kind of event, because we can have one overlapped per pending operation, whichever its nature is. So we could have more dedicated pending operation callbacks for connect and listen. But given the scope of listen and accept, we don't need to go to that extent and waste memory. Also, this is closer to what happens in posix world. */ typedef struct grpc_winsocket { SOCKET socket; bool destroy_called; grpc_winsocket_callback_info write_info; grpc_winsocket_callback_info read_info; gpr_mu state_mu; bool shutdown_called; /* You can't add the same socket twice to the same IO Completion Port. This prevents that. */ int added_to_iocp; grpc_closure shutdown_closure; /* A label for iomgr to track outstanding objects */ grpc_iomgr_object iomgr_object; } grpc_winsocket; /* Create a wrapped windows handle. This takes ownership of it, meaning that it will be responsible for closing it. */ grpc_winsocket *grpc_winsocket_create(SOCKET socket, const char *name); /* Initiate an asynchronous shutdown of the socket. Will call off any pending operation to cancel them. */ void grpc_winsocket_shutdown(grpc_winsocket *socket); /* Destroy a socket. Should only be called if there's no pending operation. */ void grpc_winsocket_destroy(grpc_winsocket *socket); void grpc_socket_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_winsocket *winsocket, grpc_closure *closure); void grpc_socket_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_winsocket *winsocket, grpc_closure *closure); void grpc_socket_become_ready(grpc_exec_ctx *exec_ctx, grpc_winsocket *winsocket, grpc_winsocket_callback_info *ci); #endif /* GRPC_CORE_LIB_IOMGR_SOCKET_WINDOWS_H */ grpc-1.3.2/src/core/lib/iomgr/tcp_client.h000066400000000000000000000050771310511640000203470ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_TCP_CLIENT_H #define GRPC_CORE_LIB_IOMGR_TCP_CLIENT_H #include #include #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/pollset_set.h" #include "src/core/lib/iomgr/resolve_address.h" /* Asynchronously connect to an address (specified as (addr, len)), and call cb with arg and the completed connection when done (or call cb with arg and NULL on failure). interested_parties points to a set of pollsets that would be interested in this connection being established (in order to continue their work) */ void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *on_connect, grpc_endpoint **endpoint, grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args, const grpc_resolved_address *addr, gpr_timespec deadline); #endif /* GRPC_CORE_LIB_IOMGR_TCP_CLIENT_H */ grpc-1.3.2/src/core/lib/iomgr/tcp_client_posix.c000066400000000000000000000301501310511640000215520ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_POSIX_SOCKET #include "src/core/lib/iomgr/tcp_client_posix.h" #include #include #include #include #include #include #include #include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/iomgr_posix.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/socket_mutator.h" #include "src/core/lib/iomgr/socket_utils_posix.h" #include "src/core/lib/iomgr/tcp_posix.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" #include "src/core/lib/support/string.h" extern int grpc_tcp_trace; typedef struct { gpr_mu mu; grpc_fd *fd; gpr_timespec deadline; grpc_timer alarm; grpc_closure on_alarm; int refs; grpc_closure write_closure; grpc_pollset_set *interested_parties; char *addr_str; grpc_endpoint **ep; grpc_closure *closure; grpc_channel_args *channel_args; } async_connect; static grpc_error *prepare_socket(const grpc_resolved_address *addr, int fd, const grpc_channel_args *channel_args) { grpc_error *err = GRPC_ERROR_NONE; GPR_ASSERT(fd >= 0); err = grpc_set_socket_nonblocking(fd, 1); if (err != GRPC_ERROR_NONE) goto error; err = grpc_set_socket_cloexec(fd, 1); if (err != GRPC_ERROR_NONE) goto error; if (!grpc_is_unix_socket(addr)) { err = grpc_set_socket_low_latency(fd, 1); if (err != GRPC_ERROR_NONE) goto error; } err = grpc_set_socket_no_sigpipe_if_possible(fd); if (err != GRPC_ERROR_NONE) goto error; if (channel_args) { for (size_t i = 0; i < channel_args->num_args; i++) { if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_SOCKET_MUTATOR)) { GPR_ASSERT(channel_args->args[i].type == GRPC_ARG_POINTER); grpc_socket_mutator *mutator = channel_args->args[i].value.pointer.p; err = grpc_set_socket_with_mutator(fd, mutator); if (err != GRPC_ERROR_NONE) goto error; } } } goto done; error: if (fd >= 0) { close(fd); } done: return err; } static void tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) { int done; async_connect *ac = acp; if (grpc_tcp_trace) { const char *str = grpc_error_string(error); gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: error=%s", ac->addr_str, str); } gpr_mu_lock(&ac->mu); if (ac->fd != NULL) { grpc_fd_shutdown(exec_ctx, ac->fd, GRPC_ERROR_CREATE_FROM_STATIC_STRING( "connect() timed out")); } done = (--ac->refs == 0); gpr_mu_unlock(&ac->mu); if (done) { gpr_mu_destroy(&ac->mu); gpr_free(ac->addr_str); grpc_channel_args_destroy(exec_ctx, ac->channel_args); gpr_free(ac); } } grpc_endpoint *grpc_tcp_client_create_from_fd( grpc_exec_ctx *exec_ctx, grpc_fd *fd, const grpc_channel_args *channel_args, const char *addr_str) { return grpc_tcp_create(exec_ctx, fd, channel_args, addr_str); } static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) { async_connect *ac = acp; int so_error = 0; socklen_t so_error_size; int err; int done; grpc_endpoint **ep = ac->ep; grpc_closure *closure = ac->closure; grpc_fd *fd; GRPC_ERROR_REF(error); if (grpc_tcp_trace) { const char *str = grpc_error_string(error); gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_writable: error=%s", ac->addr_str, str); } gpr_mu_lock(&ac->mu); GPR_ASSERT(ac->fd); fd = ac->fd; ac->fd = NULL; gpr_mu_unlock(&ac->mu); grpc_timer_cancel(exec_ctx, &ac->alarm); gpr_mu_lock(&ac->mu); if (error != GRPC_ERROR_NONE) { error = grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, grpc_slice_from_static_string("Timeout occurred")); goto finish; } do { so_error_size = sizeof(so_error); err = getsockopt(grpc_fd_wrapped_fd(fd), SOL_SOCKET, SO_ERROR, &so_error, &so_error_size); } while (err < 0 && errno == EINTR); if (err < 0) { error = GRPC_OS_ERROR(errno, "getsockopt"); goto finish; } switch (so_error) { case 0: grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd); *ep = grpc_tcp_client_create_from_fd(exec_ctx, fd, ac->channel_args, ac->addr_str); fd = NULL; break; case ENOBUFS: /* We will get one of these errors if we have run out of memory in the kernel for the data structures allocated when you connect a socket. If this happens it is very likely that if we wait a little bit then try again the connection will work (since other programs or this program will close their network connections and free up memory). This does _not_ indicate that there is anything wrong with the server we are connecting to, this is a local problem. If you are looking at this code, then chances are that your program or another program on the same computer opened too many network connections. The "easy" fix: don't do that! */ gpr_log(GPR_ERROR, "kernel out of buffers"); gpr_mu_unlock(&ac->mu); grpc_fd_notify_on_write(exec_ctx, fd, &ac->write_closure); return; case ECONNREFUSED: /* This error shouldn't happen for anything other than connect(). */ error = GRPC_OS_ERROR(so_error, "connect"); break; default: /* We don't really know which syscall triggered the problem here, so punt by reporting getsockopt(). */ error = GRPC_OS_ERROR(so_error, "getsockopt(SO_ERROR)"); break; } finish: if (fd != NULL) { grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd); grpc_fd_orphan(exec_ctx, fd, NULL, NULL, "tcp_client_orphan"); fd = NULL; } done = (--ac->refs == 0); gpr_mu_unlock(&ac->mu); if (error != GRPC_ERROR_NONE) { char *error_descr; grpc_slice str; bool ret = grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &str); GPR_ASSERT(ret); char *desc = grpc_slice_to_c_string(str); gpr_asprintf(&error_descr, "Failed to connect to remote host: %s", desc); error = grpc_error_set_str(error, GRPC_ERROR_STR_DESCRIPTION, grpc_slice_from_copied_string(error_descr)); gpr_free(error_descr); gpr_free(desc); error = grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(ac->addr_str)); } if (done) { gpr_mu_destroy(&ac->mu); gpr_free(ac->addr_str); grpc_channel_args_destroy(exec_ctx, ac->channel_args); gpr_free(ac); } grpc_closure_sched(exec_ctx, closure, error); } static void tcp_client_connect_impl(grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep, grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args, const grpc_resolved_address *addr, gpr_timespec deadline) { int fd; grpc_dualstack_mode dsmode; int err; async_connect *ac; grpc_resolved_address addr6_v4mapped; grpc_resolved_address addr4_copy; grpc_fd *fdobj; char *name; char *addr_str; grpc_error *error; *ep = NULL; /* Use dualstack sockets where available. */ if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) { addr = &addr6_v4mapped; } error = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd); if (error != GRPC_ERROR_NONE) { grpc_closure_sched(exec_ctx, closure, error); return; } if (dsmode == GRPC_DSMODE_IPV4) { /* If we got an AF_INET socket, map the address back to IPv4. */ GPR_ASSERT(grpc_sockaddr_is_v4mapped(addr, &addr4_copy)); addr = &addr4_copy; } if ((error = prepare_socket(addr, fd, channel_args)) != GRPC_ERROR_NONE) { grpc_closure_sched(exec_ctx, closure, error); return; } do { GPR_ASSERT(addr->len < ~(socklen_t)0); err = connect(fd, (const struct sockaddr *)addr->addr, (socklen_t)addr->len); } while (err < 0 && errno == EINTR); addr_str = grpc_sockaddr_to_uri(addr); gpr_asprintf(&name, "tcp-client:%s", addr_str); fdobj = grpc_fd_create(fd, name); if (err >= 0) { *ep = grpc_tcp_client_create_from_fd(exec_ctx, fdobj, channel_args, addr_str); grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_NONE); goto done; } if (errno != EWOULDBLOCK && errno != EINPROGRESS) { grpc_fd_orphan(exec_ctx, fdobj, NULL, NULL, "tcp_client_connect_error"); grpc_closure_sched(exec_ctx, closure, GRPC_OS_ERROR(errno, "connect")); goto done; } grpc_pollset_set_add_fd(exec_ctx, interested_parties, fdobj); ac = gpr_malloc(sizeof(async_connect)); ac->closure = closure; ac->ep = ep; ac->fd = fdobj; ac->interested_parties = interested_parties; ac->addr_str = addr_str; addr_str = NULL; gpr_mu_init(&ac->mu); ac->refs = 2; grpc_closure_init(&ac->write_closure, on_writable, ac, grpc_schedule_on_exec_ctx); ac->channel_args = grpc_channel_args_copy(channel_args); if (grpc_tcp_trace) { gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: asynchronously connecting", ac->addr_str); } gpr_mu_lock(&ac->mu); grpc_closure_init(&ac->on_alarm, tc_on_alarm, ac, grpc_schedule_on_exec_ctx); grpc_timer_init(exec_ctx, &ac->alarm, gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC), &ac->on_alarm, gpr_now(GPR_CLOCK_MONOTONIC)); grpc_fd_notify_on_write(exec_ctx, ac->fd, &ac->write_closure); gpr_mu_unlock(&ac->mu); done: gpr_free(name); gpr_free(addr_str); } // overridden by api_fuzzer.c void (*grpc_tcp_client_connect_impl)( grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep, grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args, const grpc_resolved_address *addr, gpr_timespec deadline) = tcp_client_connect_impl; void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep, grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args, const grpc_resolved_address *addr, gpr_timespec deadline) { grpc_tcp_client_connect_impl(exec_ctx, closure, ep, interested_parties, channel_args, addr, deadline); } #endif grpc-1.3.2/src/core/lib/iomgr/tcp_client_posix.h000066400000000000000000000037171310511640000215700ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_TCP_CLIENT_POSIX_H #define GRPC_CORE_LIB_IOMGR_TCP_CLIENT_POSIX_H #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/tcp_client.h" grpc_endpoint *grpc_tcp_client_create_from_fd( grpc_exec_ctx *exec_ctx, grpc_fd *fd, const grpc_channel_args *channel_args, const char *addr_str); #endif /* GRPC_CORE_LIB_IOMGR_TCP_CLIENT_POSIX_H */ grpc-1.3.2/src/core/lib/iomgr/tcp_client_uv.c000066400000000000000000000165561310511640000210600ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_UV #include #include #include #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/iomgr/tcp_uv.h" #include "src/core/lib/iomgr/timer.h" extern int grpc_tcp_trace; typedef struct grpc_uv_tcp_connect { uv_connect_t connect_req; grpc_timer alarm; grpc_closure on_alarm; uv_tcp_t *tcp_handle; grpc_closure *closure; grpc_endpoint **endpoint; int refs; char *addr_name; grpc_resource_quota *resource_quota; } grpc_uv_tcp_connect; static void uv_tcp_connect_cleanup(grpc_exec_ctx *exec_ctx, grpc_uv_tcp_connect *connect) { grpc_resource_quota_unref_internal(exec_ctx, connect->resource_quota); gpr_free(connect); } static void tcp_close_callback(uv_handle_t *handle) { gpr_free(handle); } static void uv_tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) { int done; grpc_uv_tcp_connect *connect = acp; if (grpc_tcp_trace) { const char *str = grpc_error_string(error); gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: error=%s", connect->addr_name, str); } if (error == GRPC_ERROR_NONE) { /* error == NONE implies that the timer ran out, and wasn't cancelled. If it was cancelled, then the handler that cancelled it also should close the handle, if applicable */ uv_close((uv_handle_t *)connect->tcp_handle, tcp_close_callback); } done = (--connect->refs == 0); if (done) { uv_tcp_connect_cleanup(exec_ctx, connect); } } static void uv_tc_on_connect(uv_connect_t *req, int status) { grpc_uv_tcp_connect *connect = req->data; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_error *error = GRPC_ERROR_NONE; int done; grpc_closure *closure = connect->closure; grpc_timer_cancel(&exec_ctx, &connect->alarm); if (status == 0) { *connect->endpoint = grpc_tcp_create( connect->tcp_handle, connect->resource_quota, connect->addr_name); } else { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Failed to connect to remote host"); error = grpc_error_set_int(error, GRPC_ERROR_INT_ERRNO, -status); error = grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, grpc_slice_from_static_string(uv_strerror(status))); if (status == UV_ECANCELED) { error = grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, grpc_slice_from_static_string("Timeout occurred")); // This should only happen if the handle is already closed } else { error = grpc_error_set_str( error, GRPC_ERROR_STR_OS_ERROR, grpc_slice_from_static_string(uv_strerror(status))); uv_close((uv_handle_t *)connect->tcp_handle, tcp_close_callback); } } done = (--connect->refs == 0); if (done) { uv_tcp_connect_cleanup(&exec_ctx, connect); } grpc_closure_sched(&exec_ctx, closure, error); grpc_exec_ctx_finish(&exec_ctx); } static void tcp_client_connect_impl(grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep, grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args, const grpc_resolved_address *resolved_addr, gpr_timespec deadline) { grpc_uv_tcp_connect *connect; grpc_resource_quota *resource_quota = grpc_resource_quota_create(NULL); (void)channel_args; (void)interested_parties; if (channel_args != NULL) { for (size_t i = 0; i < channel_args->num_args; i++) { if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_RESOURCE_QUOTA)) { grpc_resource_quota_unref_internal(exec_ctx, resource_quota); resource_quota = grpc_resource_quota_ref_internal( channel_args->args[i].value.pointer.p); } } } connect = gpr_zalloc(sizeof(grpc_uv_tcp_connect)); connect->closure = closure; connect->endpoint = ep; connect->tcp_handle = gpr_malloc(sizeof(uv_tcp_t)); connect->addr_name = grpc_sockaddr_to_uri(resolved_addr); connect->resource_quota = resource_quota; uv_tcp_init(uv_default_loop(), connect->tcp_handle); connect->connect_req.data = connect; if (grpc_tcp_trace) { gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: asynchronously connecting", connect->addr_name); } // TODO(murgatroid99): figure out what the return value here means uv_tcp_connect(&connect->connect_req, connect->tcp_handle, (const struct sockaddr *)resolved_addr->addr, uv_tc_on_connect); grpc_closure_init(&connect->on_alarm, uv_tc_on_alarm, connect, grpc_schedule_on_exec_ctx); grpc_timer_init(exec_ctx, &connect->alarm, gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC), &connect->on_alarm, gpr_now(GPR_CLOCK_MONOTONIC)); } // overridden by api_fuzzer.c void (*grpc_tcp_client_connect_impl)( grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep, grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args, const grpc_resolved_address *addr, gpr_timespec deadline) = tcp_client_connect_impl; void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep, grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args, const grpc_resolved_address *addr, gpr_timespec deadline) { grpc_tcp_client_connect_impl(exec_ctx, closure, ep, interested_parties, channel_args, addr, deadline); } #endif /* GRPC_UV */ grpc-1.3.2/src/core/lib/iomgr/tcp_client_windows.c000066400000000000000000000216011310511640000221030ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_WINSOCK_SOCKET #include "src/core/lib/iomgr/sockaddr_windows.h" #include #include #include #include #include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/iocp_windows.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/socket_windows.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/iomgr/tcp_windows.h" #include "src/core/lib/iomgr/timer.h" typedef struct { grpc_closure *on_done; gpr_mu mu; grpc_winsocket *socket; gpr_timespec deadline; grpc_timer alarm; grpc_closure on_alarm; char *addr_name; int refs; grpc_closure on_connect; grpc_endpoint **endpoint; grpc_channel_args *channel_args; } async_connect; static void async_connect_unlock_and_cleanup(grpc_exec_ctx *exec_ctx, async_connect *ac, grpc_winsocket *socket) { int done = (--ac->refs == 0); gpr_mu_unlock(&ac->mu); if (done) { grpc_channel_args_destroy(exec_ctx, ac->channel_args); gpr_mu_destroy(&ac->mu); gpr_free(ac->addr_name); gpr_free(ac); } if (socket != NULL) grpc_winsocket_destroy(socket); } static void on_alarm(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) { async_connect *ac = acp; gpr_mu_lock(&ac->mu); grpc_winsocket *socket = ac->socket; ac->socket = NULL; if (socket != NULL) { grpc_winsocket_shutdown(socket); } async_connect_unlock_and_cleanup(exec_ctx, ac, socket); } static void on_connect(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) { async_connect *ac = acp; grpc_endpoint **ep = ac->endpoint; GPR_ASSERT(*ep == NULL); grpc_closure *on_done = ac->on_done; GRPC_ERROR_REF(error); gpr_mu_lock(&ac->mu); grpc_winsocket *socket = ac->socket; ac->socket = NULL; gpr_mu_unlock(&ac->mu); grpc_timer_cancel(exec_ctx, &ac->alarm); gpr_mu_lock(&ac->mu); if (error == GRPC_ERROR_NONE) { if (socket != NULL) { DWORD transfered_bytes = 0; DWORD flags; BOOL wsa_success = WSAGetOverlappedResult(socket->socket, &socket->write_info.overlapped, &transfered_bytes, FALSE, &flags); GPR_ASSERT(transfered_bytes == 0); if (!wsa_success) { error = GRPC_WSA_ERROR(WSAGetLastError(), "ConnectEx"); } else { *ep = grpc_tcp_create(exec_ctx, socket, ac->channel_args, ac->addr_name); socket = NULL; } } else { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("socket is null"); } } async_connect_unlock_and_cleanup(exec_ctx, ac, socket); /* If the connection was aborted, the callback was already called when the deadline was met. */ grpc_closure_sched(exec_ctx, on_done, error); } /* Tries to issue one async connection, then schedules both an IOCP notification request for the connection, and one timeout alert. */ static void tcp_client_connect_impl( grpc_exec_ctx *exec_ctx, grpc_closure *on_done, grpc_endpoint **endpoint, grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args, const grpc_resolved_address *addr, gpr_timespec deadline) { SOCKET sock = INVALID_SOCKET; BOOL success; int status; grpc_resolved_address addr6_v4mapped; grpc_resolved_address local_address; async_connect *ac; grpc_winsocket *socket = NULL; LPFN_CONNECTEX ConnectEx; GUID guid = WSAID_CONNECTEX; DWORD ioctl_num_bytes; grpc_winsocket_callback_info *info; grpc_error *error = GRPC_ERROR_NONE; *endpoint = NULL; /* Use dualstack sockets where available. */ if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) { addr = &addr6_v4mapped; } sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); if (sock == INVALID_SOCKET) { error = GRPC_WSA_ERROR(WSAGetLastError(), "WSASocket"); goto failure; } error = grpc_tcp_prepare_socket(sock); if (error != GRPC_ERROR_NONE) { goto failure; } /* Grab the function pointer for ConnectEx for that specific socket. It may change depending on the interface. */ status = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid), &ConnectEx, sizeof(ConnectEx), &ioctl_num_bytes, NULL, NULL); if (status != 0) { error = GRPC_WSA_ERROR(WSAGetLastError(), "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER)"); goto failure; } grpc_sockaddr_make_wildcard6(0, &local_address); status = bind(sock, (struct sockaddr *)&local_address.addr, (int)local_address.len); if (status != 0) { error = GRPC_WSA_ERROR(WSAGetLastError(), "bind"); goto failure; } socket = grpc_winsocket_create(sock, "client"); info = &socket->write_info; success = ConnectEx(sock, (struct sockaddr *)&addr->addr, (int)addr->len, NULL, 0, NULL, &info->overlapped); /* It wouldn't be unusual to get a success immediately. But we'll still get an IOCP notification, so let's ignore it. */ if (!success) { int last_error = WSAGetLastError(); if (last_error != ERROR_IO_PENDING) { error = GRPC_WSA_ERROR(last_error, "ConnectEx"); goto failure; } } ac = gpr_malloc(sizeof(async_connect)); ac->on_done = on_done; ac->socket = socket; gpr_mu_init(&ac->mu); ac->refs = 2; ac->addr_name = grpc_sockaddr_to_uri(addr); ac->endpoint = endpoint; ac->channel_args = grpc_channel_args_copy(channel_args); grpc_closure_init(&ac->on_connect, on_connect, ac, grpc_schedule_on_exec_ctx); grpc_closure_init(&ac->on_alarm, on_alarm, ac, grpc_schedule_on_exec_ctx); grpc_timer_init(exec_ctx, &ac->alarm, deadline, &ac->on_alarm, gpr_now(GPR_CLOCK_MONOTONIC)); grpc_socket_notify_on_write(exec_ctx, socket, &ac->on_connect); return; failure: GPR_ASSERT(error != GRPC_ERROR_NONE); char *target_uri = grpc_sockaddr_to_uri(addr); grpc_error *final_error = grpc_error_set_str( GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Failed to connect", &error, 1), GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(target_uri)); GRPC_ERROR_UNREF(error); if (socket != NULL) { grpc_winsocket_destroy(socket); } else if (sock != INVALID_SOCKET) { closesocket(sock); } grpc_closure_sched(exec_ctx, on_done, final_error); } // overridden by api_fuzzer.c void (*grpc_tcp_client_connect_impl)( grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep, grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args, const grpc_resolved_address *addr, gpr_timespec deadline) = tcp_client_connect_impl; void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep, grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args, const grpc_resolved_address *addr, gpr_timespec deadline) { grpc_tcp_client_connect_impl(exec_ctx, closure, ep, interested_parties, channel_args, addr, deadline); } #endif /* GRPC_WINSOCK_SOCKET */ grpc-1.3.2/src/core/lib/iomgr/tcp_posix.c000066400000000000000000000557741310511640000202370ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_POSIX_SOCKET #include "src/core/lib/iomgr/network_status_tracker.h" #include "src/core/lib/iomgr/tcp_posix.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/string.h" #ifdef GRPC_HAVE_MSG_NOSIGNAL #define SENDMSG_FLAGS MSG_NOSIGNAL #else #define SENDMSG_FLAGS 0 #endif #ifdef GRPC_MSG_IOVLEN_TYPE typedef GRPC_MSG_IOVLEN_TYPE msg_iovlen_type; #else typedef size_t msg_iovlen_type; #endif int grpc_tcp_trace = 0; typedef struct { grpc_endpoint base; grpc_fd *em_fd; int fd; bool finished_edge; msg_iovlen_type iov_size; /* Number of slices to allocate per read attempt */ double target_length; double bytes_read_this_round; gpr_refcount refcount; gpr_atm shutdown_count; int min_read_chunk_size; int max_read_chunk_size; /* garbage after the last read */ grpc_slice_buffer last_read_buffer; grpc_slice_buffer *incoming_buffer; grpc_slice_buffer *outgoing_buffer; /** slice within outgoing_buffer to write next */ size_t outgoing_slice_idx; /** byte within outgoing_buffer->slices[outgoing_slice_idx] to write next */ size_t outgoing_byte_idx; grpc_closure *read_cb; grpc_closure *write_cb; grpc_closure *release_fd_cb; int *release_fd; grpc_closure read_closure; grpc_closure write_closure; char *peer_string; grpc_resource_user *resource_user; grpc_resource_user_slice_allocator slice_allocator; } grpc_tcp; static void add_to_estimate(grpc_tcp *tcp, size_t bytes) { tcp->bytes_read_this_round += (double)bytes; } static void finish_estimate(grpc_tcp *tcp) { /* If we read >80% of the target buffer in one read loop, increase the size of the target buffer to either the amount read, or twice its previous value */ if (tcp->bytes_read_this_round > tcp->target_length * 0.8) { tcp->target_length = GPR_MAX(2 * tcp->target_length, tcp->bytes_read_this_round); } else { tcp->target_length = 0.99 * tcp->target_length + 0.01 * tcp->bytes_read_this_round; } tcp->bytes_read_this_round = 0; } static size_t get_target_read_size(grpc_tcp *tcp) { grpc_resource_quota *rq = grpc_resource_user_quota(tcp->resource_user); double pressure = grpc_resource_quota_get_memory_pressure(rq); double target = tcp->target_length * (pressure > 0.8 ? (1.0 - pressure) / 0.2 : 1.0); size_t sz = (((size_t)GPR_CLAMP(target, tcp->min_read_chunk_size, tcp->max_read_chunk_size)) + 255) & ~(size_t)255; /* don't use more than 1/16th of the overall resource quota for a single read * alloc */ size_t rqmax = grpc_resource_quota_peek_size(rq); if (sz > rqmax / 16 && rqmax > 1024) { sz = rqmax / 16; } return sz; } static grpc_error *tcp_annotate_error(grpc_error *src_error, grpc_tcp *tcp) { return grpc_error_set_str( grpc_error_set_int(src_error, GRPC_ERROR_INT_FD, tcp->fd), GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(tcp->peer_string)); } static void tcp_handle_read(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */, grpc_error *error); static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */, grpc_error *error); static void tcp_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_error *why) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_fd_shutdown(exec_ctx, tcp->em_fd, why); grpc_resource_user_shutdown(exec_ctx, tcp->resource_user); } static void tcp_free(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) { grpc_fd_orphan(exec_ctx, tcp->em_fd, tcp->release_fd_cb, tcp->release_fd, "tcp_unref_orphan"); grpc_slice_buffer_destroy_internal(exec_ctx, &tcp->last_read_buffer); grpc_resource_user_unref(exec_ctx, tcp->resource_user); gpr_free(tcp->peer_string); gpr_free(tcp); } /*#define GRPC_TCP_REFCOUNT_DEBUG*/ #ifdef GRPC_TCP_REFCOUNT_DEBUG #define TCP_UNREF(cl, tcp, reason) \ tcp_unref((cl), (tcp), (reason), __FILE__, __LINE__) #define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__) static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp, const char *reason, const char *file, int line) { gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp, reason, tcp->refcount.count, tcp->refcount.count - 1); if (gpr_unref(&tcp->refcount)) { tcp_free(exec_ctx, tcp); } } static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file, int line) { gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP ref %p : %s %d -> %d", tcp, reason, tcp->refcount.count, tcp->refcount.count + 1); gpr_ref(&tcp->refcount); } #else #define TCP_UNREF(cl, tcp, reason) tcp_unref((cl), (tcp)) #define TCP_REF(tcp, reason) tcp_ref((tcp)) static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) { if (gpr_unref(&tcp->refcount)) { tcp_free(exec_ctx, tcp); } } static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); } #endif static void tcp_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) { grpc_network_status_unregister_endpoint(ep); grpc_tcp *tcp = (grpc_tcp *)ep; grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &tcp->last_read_buffer); TCP_UNREF(exec_ctx, tcp, "destroy"); } static void call_read_cb(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp, grpc_error *error) { grpc_closure *cb = tcp->read_cb; if (grpc_tcp_trace) { size_t i; const char *str = grpc_error_string(error); gpr_log(GPR_DEBUG, "read: error=%s", str); for (i = 0; i < tcp->incoming_buffer->count; i++) { char *dump = grpc_dump_slice(tcp->incoming_buffer->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "READ %p (peer=%s): %s", tcp, tcp->peer_string, dump); gpr_free(dump); } } tcp->read_cb = NULL; tcp->incoming_buffer = NULL; grpc_closure_run(exec_ctx, cb, error); } #define MAX_READ_IOVEC 4 static void tcp_do_read(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) { struct msghdr msg; struct iovec iov[MAX_READ_IOVEC]; ssize_t read_bytes; size_t i; GPR_ASSERT(!tcp->finished_edge); GPR_ASSERT(tcp->iov_size <= MAX_READ_IOVEC); GPR_ASSERT(tcp->incoming_buffer->count <= MAX_READ_IOVEC); GPR_TIMER_BEGIN("tcp_continue_read", 0); for (i = 0; i < tcp->incoming_buffer->count; i++) { iov[i].iov_base = GRPC_SLICE_START_PTR(tcp->incoming_buffer->slices[i]); iov[i].iov_len = GRPC_SLICE_LENGTH(tcp->incoming_buffer->slices[i]); } msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = tcp->iov_size; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_flags = 0; GPR_TIMER_BEGIN("recvmsg", 0); do { read_bytes = recvmsg(tcp->fd, &msg, 0); } while (read_bytes < 0 && errno == EINTR); GPR_TIMER_END("recvmsg", read_bytes >= 0); if (read_bytes < 0) { /* NB: After calling call_read_cb a parallel call of the read handler may * be running. */ if (errno == EAGAIN) { finish_estimate(tcp); /* We've consumed the edge, request a new one */ grpc_fd_notify_on_read(exec_ctx, tcp->em_fd, &tcp->read_closure); } else { grpc_slice_buffer_reset_and_unref_internal(exec_ctx, tcp->incoming_buffer); call_read_cb(exec_ctx, tcp, tcp_annotate_error(GRPC_OS_ERROR(errno, "recvmsg"), tcp)); TCP_UNREF(exec_ctx, tcp, "read"); } } else if (read_bytes == 0) { /* 0 read size ==> end of stream */ grpc_slice_buffer_reset_and_unref_internal(exec_ctx, tcp->incoming_buffer); call_read_cb( exec_ctx, tcp, tcp_annotate_error( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Socket closed"), tcp)); TCP_UNREF(exec_ctx, tcp, "read"); } else { add_to_estimate(tcp, (size_t)read_bytes); GPR_ASSERT((size_t)read_bytes <= tcp->incoming_buffer->length); if ((size_t)read_bytes < tcp->incoming_buffer->length) { grpc_slice_buffer_trim_end( tcp->incoming_buffer, tcp->incoming_buffer->length - (size_t)read_bytes, &tcp->last_read_buffer); } GPR_ASSERT((size_t)read_bytes == tcp->incoming_buffer->length); call_read_cb(exec_ctx, tcp, GRPC_ERROR_NONE); TCP_UNREF(exec_ctx, tcp, "read"); } GPR_TIMER_END("tcp_continue_read", 0); } static void tcp_read_allocation_done(grpc_exec_ctx *exec_ctx, void *tcpp, grpc_error *error) { grpc_tcp *tcp = tcpp; if (error != GRPC_ERROR_NONE) { grpc_slice_buffer_reset_and_unref_internal(exec_ctx, tcp->incoming_buffer); grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &tcp->last_read_buffer); call_read_cb(exec_ctx, tcp, GRPC_ERROR_REF(error)); TCP_UNREF(exec_ctx, tcp, "read"); } else { tcp_do_read(exec_ctx, tcp); } } static void tcp_continue_read(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) { size_t target_read_size = get_target_read_size(tcp); if (tcp->incoming_buffer->length < target_read_size && tcp->incoming_buffer->count < MAX_READ_IOVEC) { grpc_resource_user_alloc_slices(exec_ctx, &tcp->slice_allocator, target_read_size, 1, tcp->incoming_buffer); } else { tcp_do_read(exec_ctx, tcp); } } static void tcp_handle_read(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */, grpc_error *error) { grpc_tcp *tcp = (grpc_tcp *)arg; GPR_ASSERT(!tcp->finished_edge); if (error != GRPC_ERROR_NONE) { grpc_slice_buffer_reset_and_unref_internal(exec_ctx, tcp->incoming_buffer); grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &tcp->last_read_buffer); call_read_cb(exec_ctx, tcp, GRPC_ERROR_REF(error)); TCP_UNREF(exec_ctx, tcp, "read"); } else { tcp_continue_read(exec_ctx, tcp); } } static void tcp_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_slice_buffer *incoming_buffer, grpc_closure *cb) { grpc_tcp *tcp = (grpc_tcp *)ep; GPR_ASSERT(tcp->read_cb == NULL); tcp->read_cb = cb; tcp->incoming_buffer = incoming_buffer; grpc_slice_buffer_reset_and_unref_internal(exec_ctx, incoming_buffer); grpc_slice_buffer_swap(incoming_buffer, &tcp->last_read_buffer); TCP_REF(tcp, "read"); if (tcp->finished_edge) { tcp->finished_edge = false; grpc_fd_notify_on_read(exec_ctx, tcp->em_fd, &tcp->read_closure); } else { grpc_closure_sched(exec_ctx, &tcp->read_closure, GRPC_ERROR_NONE); } } /* returns true if done, false if pending; if returning true, *error is set */ #define MAX_WRITE_IOVEC 1000 static bool tcp_flush(grpc_tcp *tcp, grpc_error **error) { struct msghdr msg; struct iovec iov[MAX_WRITE_IOVEC]; msg_iovlen_type iov_size; ssize_t sent_length; size_t sending_length; size_t trailing; size_t unwind_slice_idx; size_t unwind_byte_idx; for (;;) { sending_length = 0; unwind_slice_idx = tcp->outgoing_slice_idx; unwind_byte_idx = tcp->outgoing_byte_idx; for (iov_size = 0; tcp->outgoing_slice_idx != tcp->outgoing_buffer->count && iov_size != MAX_WRITE_IOVEC; iov_size++) { iov[iov_size].iov_base = GRPC_SLICE_START_PTR( tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]) + tcp->outgoing_byte_idx; iov[iov_size].iov_len = GRPC_SLICE_LENGTH( tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]) - tcp->outgoing_byte_idx; sending_length += iov[iov_size].iov_len; tcp->outgoing_slice_idx++; tcp->outgoing_byte_idx = 0; } GPR_ASSERT(iov_size > 0); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = iov_size; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_flags = 0; GPR_TIMER_BEGIN("sendmsg", 1); do { /* TODO(klempner): Cork if this is a partial write */ sent_length = sendmsg(tcp->fd, &msg, SENDMSG_FLAGS); } while (sent_length < 0 && errno == EINTR); GPR_TIMER_END("sendmsg", 0); if (sent_length < 0) { if (errno == EAGAIN) { tcp->outgoing_slice_idx = unwind_slice_idx; tcp->outgoing_byte_idx = unwind_byte_idx; return false; } else if (errno == EPIPE) { *error = grpc_error_set_int(GRPC_OS_ERROR(errno, "sendmsg"), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); return true; } else { *error = tcp_annotate_error(GRPC_OS_ERROR(errno, "sendmsg"), tcp); return true; } } GPR_ASSERT(tcp->outgoing_byte_idx == 0); trailing = sending_length - (size_t)sent_length; while (trailing > 0) { size_t slice_length; tcp->outgoing_slice_idx--; slice_length = GRPC_SLICE_LENGTH( tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]); if (slice_length > trailing) { tcp->outgoing_byte_idx = slice_length - trailing; break; } else { trailing -= slice_length; } } if (tcp->outgoing_slice_idx == tcp->outgoing_buffer->count) { *error = GRPC_ERROR_NONE; return true; } }; } static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */, grpc_error *error) { grpc_tcp *tcp = (grpc_tcp *)arg; grpc_closure *cb; if (error != GRPC_ERROR_NONE) { cb = tcp->write_cb; tcp->write_cb = NULL; cb->cb(exec_ctx, cb->cb_arg, error); TCP_UNREF(exec_ctx, tcp, "write"); return; } if (!tcp_flush(tcp, &error)) { if (grpc_tcp_trace) { gpr_log(GPR_DEBUG, "write: delayed"); } grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure); } else { cb = tcp->write_cb; tcp->write_cb = NULL; if (grpc_tcp_trace) { const char *str = grpc_error_string(error); gpr_log(GPR_DEBUG, "write: %s", str); } grpc_closure_run(exec_ctx, cb, error); TCP_UNREF(exec_ctx, tcp, "write"); } } static void tcp_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_slice_buffer *buf, grpc_closure *cb) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_error *error = GRPC_ERROR_NONE; if (grpc_tcp_trace) { size_t i; for (i = 0; i < buf->count; i++) { char *data = grpc_dump_slice(buf->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "WRITE %p (peer=%s): %s", tcp, tcp->peer_string, data); gpr_free(data); } } GPR_TIMER_BEGIN("tcp_write", 0); GPR_ASSERT(tcp->write_cb == NULL); if (buf->length == 0) { GPR_TIMER_END("tcp_write", 0); grpc_closure_sched( exec_ctx, cb, grpc_fd_is_shutdown(tcp->em_fd) ? tcp_annotate_error(GRPC_ERROR_CREATE_FROM_STATIC_STRING("EOF"), tcp) : GRPC_ERROR_NONE); return; } tcp->outgoing_buffer = buf; tcp->outgoing_slice_idx = 0; tcp->outgoing_byte_idx = 0; if (!tcp_flush(tcp, &error)) { TCP_REF(tcp, "write"); tcp->write_cb = cb; if (grpc_tcp_trace) { gpr_log(GPR_DEBUG, "write: delayed"); } grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure); } else { if (grpc_tcp_trace) { const char *str = grpc_error_string(error); gpr_log(GPR_DEBUG, "write: %s", str); } grpc_closure_sched(exec_ctx, cb, error); } GPR_TIMER_END("tcp_write", 0); } static void tcp_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_pollset *pollset) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_pollset_add_fd(exec_ctx, pollset, tcp->em_fd); } static void tcp_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_pollset_set *pollset_set) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_pollset_set_add_fd(exec_ctx, pollset_set, tcp->em_fd); } static char *tcp_get_peer(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; return gpr_strdup(tcp->peer_string); } static int tcp_get_fd(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; return tcp->fd; } static grpc_workqueue *tcp_get_workqueue(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; return grpc_fd_get_workqueue(tcp->em_fd); } static grpc_resource_user *tcp_get_resource_user(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; return tcp->resource_user; } static const grpc_endpoint_vtable vtable = {tcp_read, tcp_write, tcp_get_workqueue, tcp_add_to_pollset, tcp_add_to_pollset_set, tcp_shutdown, tcp_destroy, tcp_get_resource_user, tcp_get_peer, tcp_get_fd}; #define MAX_CHUNK_SIZE 32 * 1024 * 1024 grpc_endpoint *grpc_tcp_create(grpc_exec_ctx *exec_ctx, grpc_fd *em_fd, const grpc_channel_args *channel_args, const char *peer_string) { int tcp_read_chunk_size = GRPC_TCP_DEFAULT_READ_SLICE_SIZE; int tcp_max_read_chunk_size = 4 * 1024 * 1024; int tcp_min_read_chunk_size = 256; grpc_resource_quota *resource_quota = grpc_resource_quota_create(NULL); if (channel_args != NULL) { for (size_t i = 0; i < channel_args->num_args; i++) { if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_TCP_READ_CHUNK_SIZE)) { grpc_integer_options options = {(int)tcp_read_chunk_size, 1, MAX_CHUNK_SIZE}; tcp_read_chunk_size = grpc_channel_arg_get_integer(&channel_args->args[i], options); } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_TCP_MIN_READ_CHUNK_SIZE)) { grpc_integer_options options = {(int)tcp_read_chunk_size, 1, MAX_CHUNK_SIZE}; tcp_min_read_chunk_size = grpc_channel_arg_get_integer(&channel_args->args[i], options); } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_TCP_MAX_READ_CHUNK_SIZE)) { grpc_integer_options options = {(int)tcp_read_chunk_size, 1, MAX_CHUNK_SIZE}; tcp_max_read_chunk_size = grpc_channel_arg_get_integer(&channel_args->args[i], options); } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_RESOURCE_QUOTA)) { grpc_resource_quota_unref_internal(exec_ctx, resource_quota); resource_quota = grpc_resource_quota_ref_internal( channel_args->args[i].value.pointer.p); } } } if (tcp_min_read_chunk_size > tcp_max_read_chunk_size) { tcp_min_read_chunk_size = tcp_max_read_chunk_size; } tcp_read_chunk_size = GPR_CLAMP(tcp_read_chunk_size, tcp_min_read_chunk_size, tcp_max_read_chunk_size); grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp)); tcp->base.vtable = &vtable; tcp->peer_string = gpr_strdup(peer_string); tcp->fd = grpc_fd_wrapped_fd(em_fd); tcp->read_cb = NULL; tcp->write_cb = NULL; tcp->release_fd_cb = NULL; tcp->release_fd = NULL; tcp->incoming_buffer = NULL; tcp->target_length = (double)tcp_read_chunk_size; tcp->min_read_chunk_size = tcp_min_read_chunk_size; tcp->max_read_chunk_size = tcp_max_read_chunk_size; tcp->bytes_read_this_round = 0; tcp->iov_size = 1; tcp->finished_edge = true; /* paired with unref in grpc_tcp_destroy */ gpr_ref_init(&tcp->refcount, 1); gpr_atm_no_barrier_store(&tcp->shutdown_count, 0); tcp->em_fd = em_fd; grpc_closure_init(&tcp->read_closure, tcp_handle_read, tcp, grpc_schedule_on_exec_ctx); grpc_closure_init(&tcp->write_closure, tcp_handle_write, tcp, grpc_schedule_on_exec_ctx); grpc_slice_buffer_init(&tcp->last_read_buffer); tcp->resource_user = grpc_resource_user_create(resource_quota, peer_string); grpc_resource_user_slice_allocator_init( &tcp->slice_allocator, tcp->resource_user, tcp_read_allocation_done, tcp); /* Tell network status tracker about new endpoint */ grpc_network_status_register_endpoint(&tcp->base); grpc_resource_quota_unref_internal(exec_ctx, resource_quota); return &tcp->base; } int grpc_tcp_fd(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; GPR_ASSERT(ep->vtable == &vtable); return grpc_fd_wrapped_fd(tcp->em_fd); } void grpc_tcp_destroy_and_release_fd(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, int *fd, grpc_closure *done) { grpc_network_status_unregister_endpoint(ep); grpc_tcp *tcp = (grpc_tcp *)ep; GPR_ASSERT(ep->vtable == &vtable); tcp->release_fd = fd; tcp->release_fd_cb = done; grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &tcp->last_read_buffer); TCP_UNREF(exec_ctx, tcp, "destroy"); } #endif grpc-1.3.2/src/core/lib/iomgr/tcp_posix.h000066400000000000000000000055521310511640000202310ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_TCP_POSIX_H #define GRPC_CORE_LIB_IOMGR_TCP_POSIX_H /* Low level TCP "bottom half" implementation, for use by transports built on top of a TCP connection. Note that this file does not (yet) include APIs for creating the socket in the first place. All calls passing slice transfer ownership of a slice refcount unless otherwise specified. */ #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/ev_posix.h" extern int grpc_tcp_trace; /* Create a tcp endpoint given a file desciptor and a read slice size. Takes ownership of fd. */ grpc_endpoint *grpc_tcp_create(grpc_exec_ctx *exec_ctx, grpc_fd *fd, const grpc_channel_args *args, const char *peer_string); /* Return the tcp endpoint's fd, or -1 if this is not available. Does not release the fd. Requires: ep must be a tcp endpoint. */ int grpc_tcp_fd(grpc_endpoint *ep); /* Destroy the tcp endpoint without closing its fd. *fd will be set and done * will be called when the endpoint is destroyed. * Requires: ep must be a tcp endpoint and fd must not be NULL. */ void grpc_tcp_destroy_and_release_fd(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, int *fd, grpc_closure *done); #endif /* GRPC_CORE_LIB_IOMGR_TCP_POSIX_H */ grpc-1.3.2/src/core/lib/iomgr/tcp_server.h000066400000000000000000000124031310511640000203660ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_TCP_SERVER_H #define GRPC_CORE_LIB_IOMGR_TCP_SERVER_H #include #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/resolve_address.h" /* Forward decl of grpc_tcp_server */ typedef struct grpc_tcp_server grpc_tcp_server; typedef struct grpc_tcp_server_acceptor { /* grpc_tcp_server_cb functions share a ref on from_server that is valid until the function returns. */ grpc_tcp_server *from_server; /* Indices that may be passed to grpc_tcp_server_port_fd(). */ unsigned port_index; unsigned fd_index; } grpc_tcp_server_acceptor; /* Called for newly connected TCP connections. Takes ownership of acceptor. */ typedef void (*grpc_tcp_server_cb)(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *ep, grpc_pollset *accepting_pollset, grpc_tcp_server_acceptor *acceptor); /* Create a server, initially not bound to any ports. The caller owns one ref. If shutdown_complete is not NULL, it will be used by grpc_tcp_server_unref() when the ref count reaches zero. */ grpc_error *grpc_tcp_server_create(grpc_exec_ctx *exec_ctx, grpc_closure *shutdown_complete, const grpc_channel_args *args, grpc_tcp_server **server); /* Start listening to bound ports */ void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *server, grpc_pollset **pollsets, size_t pollset_count, grpc_tcp_server_cb on_accept_cb, void *cb_arg); /* Add a port to the server, returning the newly allocated port on success, or -1 on failure. The :: and 0.0.0.0 wildcard addresses are treated identically, accepting both IPv4 and IPv6 connections, but :: is the preferred style. This usually creates one socket, but possibly two on systems which support IPv6, but not dualstack sockets. */ /* TODO(ctiller): deprecate this, and make grpc_tcp_server_add_ports to handle all of the multiple socket port matching logic in one place */ grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s, const grpc_resolved_address *addr, int *out_port); /* Number of fds at the given port_index, or 0 if port_index is out of bounds. */ unsigned grpc_tcp_server_port_fd_count(grpc_tcp_server *s, unsigned port_index); /* Returns the file descriptor of the Mth (fd_index) listening socket of the Nth (port_index) call to add_port() on this server, or -1 if the indices are out of bounds. The file descriptor remains owned by the server, and will be cleaned up when the ref count reaches zero. */ int grpc_tcp_server_port_fd(grpc_tcp_server *s, unsigned port_index, unsigned fd_index); /* Ref s and return s. */ grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s); /* shutdown_starting is called when ref count has reached zero and the server is about to be destroyed. The server will be deleted after it returns. Calling grpc_tcp_server_ref() from it has no effect. */ void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s, grpc_closure *shutdown_starting); /* If the refcount drops to zero, enqueue calls on exec_ctx to shutdown_listeners and delete s. */ void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s); /* Shutdown the fds of listeners. */ void grpc_tcp_server_shutdown_listeners(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s); #endif /* GRPC_CORE_LIB_IOMGR_TCP_SERVER_H */ grpc-1.3.2/src/core/lib/iomgr/tcp_server_posix.c000066400000000000000000000453671310511640000216220ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* FIXME: "posix" files shouldn't be depending on _GNU_SOURCE */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include "src/core/lib/iomgr/port.h" #ifdef GRPC_POSIX_SOCKET #include "src/core/lib/iomgr/tcp_server.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/socket_utils_posix.h" #include "src/core/lib/iomgr/tcp_posix.h" #include "src/core/lib/iomgr/tcp_server_utils_posix.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" #include "src/core/lib/support/string.h" static gpr_once check_init = GPR_ONCE_INIT; static bool has_so_reuseport = false; static void init(void) { #ifndef GPR_MANYLINUX1 int s = socket(AF_INET, SOCK_STREAM, 0); if (s >= 0) { has_so_reuseport = GRPC_LOG_IF_ERROR("check for SO_REUSEPORT", grpc_set_socket_reuse_port(s, 1)); close(s); } #endif } grpc_error *grpc_tcp_server_create(grpc_exec_ctx *exec_ctx, grpc_closure *shutdown_complete, const grpc_channel_args *args, grpc_tcp_server **server) { gpr_once_init(&check_init, init); grpc_tcp_server *s = gpr_zalloc(sizeof(grpc_tcp_server)); s->so_reuseport = has_so_reuseport; s->expand_wildcard_addrs = false; for (size_t i = 0; i < (args == NULL ? 0 : args->num_args); i++) { if (0 == strcmp(GRPC_ARG_ALLOW_REUSEPORT, args->args[i].key)) { if (args->args[i].type == GRPC_ARG_INTEGER) { s->so_reuseport = has_so_reuseport && (args->args[i].value.integer != 0); } else { gpr_free(s); return GRPC_ERROR_CREATE_FROM_STATIC_STRING(GRPC_ARG_ALLOW_REUSEPORT " must be an integer"); } } else if (0 == strcmp(GRPC_ARG_EXPAND_WILDCARD_ADDRS, args->args[i].key)) { if (args->args[i].type == GRPC_ARG_INTEGER) { s->expand_wildcard_addrs = (args->args[i].value.integer != 0); } else { gpr_free(s); return GRPC_ERROR_CREATE_FROM_STATIC_STRING( GRPC_ARG_EXPAND_WILDCARD_ADDRS " must be an integer"); } } } gpr_ref_init(&s->refs, 1); gpr_mu_init(&s->mu); s->active_ports = 0; s->destroyed_ports = 0; s->shutdown = false; s->shutdown_starting.head = NULL; s->shutdown_starting.tail = NULL; s->shutdown_complete = shutdown_complete; s->on_accept_cb = NULL; s->on_accept_cb_arg = NULL; s->head = NULL; s->tail = NULL; s->nports = 0; s->channel_args = grpc_channel_args_copy(args); gpr_atm_no_barrier_store(&s->next_pollset_to_assign, 0); *server = s; return GRPC_ERROR_NONE; } static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { gpr_mu_lock(&s->mu); GPR_ASSERT(s->shutdown); gpr_mu_unlock(&s->mu); if (s->shutdown_complete != NULL) { grpc_closure_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE); } gpr_mu_destroy(&s->mu); while (s->head) { grpc_tcp_listener *sp = s->head; s->head = sp->next; gpr_free(sp); } grpc_channel_args_destroy(exec_ctx, s->channel_args); gpr_free(s); } static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server, grpc_error *error) { grpc_tcp_server *s = server; gpr_mu_lock(&s->mu); s->destroyed_ports++; if (s->destroyed_ports == s->nports) { gpr_mu_unlock(&s->mu); finish_shutdown(exec_ctx, s); } else { GPR_ASSERT(s->destroyed_ports < s->nports); gpr_mu_unlock(&s->mu); } } /* called when all listening endpoints have been shutdown, so no further events will be received on them - at this point it's safe to destroy things */ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { /* delete ALL the things */ gpr_mu_lock(&s->mu); GPR_ASSERT(s->shutdown); if (s->head) { grpc_tcp_listener *sp; for (sp = s->head; sp; sp = sp->next) { grpc_unlink_if_unix_domain_socket(&sp->addr); grpc_closure_init(&sp->destroyed_closure, destroyed_port, s, grpc_schedule_on_exec_ctx); grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL, "tcp_listener_shutdown"); } gpr_mu_unlock(&s->mu); } else { gpr_mu_unlock(&s->mu); finish_shutdown(exec_ctx, s); } } static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { gpr_mu_lock(&s->mu); GPR_ASSERT(!s->shutdown); s->shutdown = true; /* shutdown all fd's */ if (s->active_ports) { grpc_tcp_listener *sp; for (sp = s->head; sp; sp = sp->next) { grpc_fd_shutdown(exec_ctx, sp->emfd, GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Server destroyed")); } gpr_mu_unlock(&s->mu); } else { gpr_mu_unlock(&s->mu); deactivated_all_ports(exec_ctx, s); } } /* event manager callback when reads are ready */ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *err) { grpc_tcp_listener *sp = arg; if (err != GRPC_ERROR_NONE) { goto error; } grpc_pollset *read_notifier_pollset = sp->server->pollsets[(size_t)gpr_atm_no_barrier_fetch_add( &sp->server->next_pollset_to_assign, 1) % sp->server->pollset_count]; /* loop until accept4 returns EAGAIN, and then re-arm notification */ for (;;) { grpc_resolved_address addr; char *addr_str; char *name; addr.len = sizeof(struct sockaddr_storage); /* Note: If we ever decide to return this address to the user, remember to strip off the ::ffff:0.0.0.0/96 prefix first. */ int fd = grpc_accept4(sp->fd, &addr, 1, 1); if (fd < 0) { switch (errno) { case EINTR: continue; case EAGAIN: grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure); return; default: gpr_mu_lock(&sp->server->mu); if (!sp->server->shutdown_listeners) { gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno)); } else { /* if we have shutdown listeners, accept4 could fail, and we needn't notify users */ } gpr_mu_unlock(&sp->server->mu); goto error; } } grpc_set_socket_no_sigpipe_if_possible(fd); addr_str = grpc_sockaddr_to_uri(&addr); gpr_asprintf(&name, "tcp-server-connection:%s", addr_str); if (grpc_tcp_trace) { gpr_log(GPR_DEBUG, "SERVER_CONNECT: incoming connection: %s", addr_str); } grpc_fd *fdobj = grpc_fd_create(fd, name); grpc_pollset_add_fd(exec_ctx, read_notifier_pollset, fdobj); // Create acceptor. grpc_tcp_server_acceptor *acceptor = gpr_malloc(sizeof(*acceptor)); acceptor->from_server = sp->server; acceptor->port_index = sp->port_index; acceptor->fd_index = sp->fd_index; sp->server->on_accept_cb( exec_ctx, sp->server->on_accept_cb_arg, grpc_tcp_create(exec_ctx, fdobj, sp->server->channel_args, addr_str), read_notifier_pollset, acceptor); gpr_free(name); gpr_free(addr_str); } GPR_UNREACHABLE_CODE(return ); error: gpr_mu_lock(&sp->server->mu); if (0 == --sp->server->active_ports && sp->server->shutdown) { gpr_mu_unlock(&sp->server->mu); deactivated_all_ports(exec_ctx, sp->server); } else { gpr_mu_unlock(&sp->server->mu); } } /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */ static grpc_error *add_wildcard_addrs_to_server(grpc_tcp_server *s, unsigned port_index, int requested_port, int *out_port) { grpc_resolved_address wild4; grpc_resolved_address wild6; unsigned fd_index = 0; grpc_dualstack_mode dsmode; grpc_tcp_listener *sp = NULL; grpc_tcp_listener *sp2 = NULL; grpc_error *v6_err = GRPC_ERROR_NONE; grpc_error *v4_err = GRPC_ERROR_NONE; *out_port = -1; if (grpc_tcp_server_have_ifaddrs() && s->expand_wildcard_addrs) { return grpc_tcp_server_add_all_local_addrs(s, port_index, requested_port, out_port); } grpc_sockaddr_make_wildcards(requested_port, &wild4, &wild6); /* Try listening on IPv6 first. */ if ((v6_err = grpc_tcp_server_add_addr(s, &wild6, port_index, fd_index, &dsmode, &sp)) == GRPC_ERROR_NONE) { ++fd_index; requested_port = *out_port = sp->port; if (dsmode == GRPC_DSMODE_DUALSTACK || dsmode == GRPC_DSMODE_IPV4) { return GRPC_ERROR_NONE; } } /* If we got a v6-only socket or nothing, try adding 0.0.0.0. */ grpc_sockaddr_set_port(&wild4, requested_port); if ((v4_err = grpc_tcp_server_add_addr(s, &wild4, port_index, fd_index, &dsmode, &sp2)) == GRPC_ERROR_NONE) { *out_port = sp2->port; if (sp != NULL) { sp2->is_sibling = 1; sp->sibling = sp2; } } if (*out_port > 0) { if (v6_err != GRPC_ERROR_NONE) { gpr_log(GPR_INFO, "Failed to add :: listener, " "the environment may not support IPv6: %s", grpc_error_string(v6_err)); GRPC_ERROR_UNREF(v6_err); } if (v4_err != GRPC_ERROR_NONE) { gpr_log(GPR_INFO, "Failed to add 0.0.0.0 listener, " "the environment may not support IPv4: %s", grpc_error_string(v4_err)); GRPC_ERROR_UNREF(v4_err); } return GRPC_ERROR_NONE; } else { grpc_error *root_err = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Failed to add any wildcard listeners"); GPR_ASSERT(v6_err != GRPC_ERROR_NONE && v4_err != GRPC_ERROR_NONE); root_err = grpc_error_add_child(root_err, v6_err); root_err = grpc_error_add_child(root_err, v4_err); return root_err; } } static grpc_error *clone_port(grpc_tcp_listener *listener, unsigned count) { grpc_tcp_listener *sp = NULL; char *addr_str; char *name; grpc_error *err; for (grpc_tcp_listener *l = listener->next; l && l->is_sibling; l = l->next) { l->fd_index += count; } for (unsigned i = 0; i < count; i++) { int fd = -1; int port = -1; grpc_dualstack_mode dsmode; err = grpc_create_dualstack_socket(&listener->addr, SOCK_STREAM, 0, &dsmode, &fd); if (err != GRPC_ERROR_NONE) return err; err = grpc_tcp_server_prepare_socket(fd, &listener->addr, true, &port); if (err != GRPC_ERROR_NONE) return err; listener->server->nports++; grpc_sockaddr_to_string(&addr_str, &listener->addr, 1); gpr_asprintf(&name, "tcp-server-listener:%s/clone-%d", addr_str, i); sp = gpr_malloc(sizeof(grpc_tcp_listener)); sp->next = listener->next; listener->next = sp; /* sp (the new listener) is a sibling of 'listener' (the original listener). */ sp->is_sibling = 1; sp->sibling = listener->sibling; listener->sibling = sp; sp->server = listener->server; sp->fd = fd; sp->emfd = grpc_fd_create(fd, name); memcpy(&sp->addr, &listener->addr, sizeof(grpc_resolved_address)); sp->port = port; sp->port_index = listener->port_index; sp->fd_index = listener->fd_index + count - i; GPR_ASSERT(sp->emfd); while (listener->server->tail->next != NULL) { listener->server->tail = listener->server->tail->next; } gpr_free(addr_str); gpr_free(name); } return GRPC_ERROR_NONE; } grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s, const grpc_resolved_address *addr, int *out_port) { grpc_tcp_listener *sp; grpc_resolved_address sockname_temp; grpc_resolved_address addr6_v4mapped; int requested_port = grpc_sockaddr_get_port(addr); unsigned port_index = 0; grpc_dualstack_mode dsmode; grpc_error *err; *out_port = -1; if (s->tail != NULL) { port_index = s->tail->port_index + 1; } grpc_unlink_if_unix_domain_socket(addr); /* Check if this is a wildcard port, and if so, try to keep the port the same as some previously created listener. */ if (requested_port == 0) { for (sp = s->head; sp; sp = sp->next) { sockname_temp.len = sizeof(struct sockaddr_storage); if (0 == getsockname(sp->fd, (struct sockaddr *)&sockname_temp.addr, (socklen_t *)&sockname_temp.len)) { int used_port = grpc_sockaddr_get_port(&sockname_temp); if (used_port > 0) { memcpy(&sockname_temp, addr, sizeof(grpc_resolved_address)); grpc_sockaddr_set_port(&sockname_temp, used_port); requested_port = used_port; addr = &sockname_temp; break; } } } } if (grpc_sockaddr_is_wildcard(addr, &requested_port)) { return add_wildcard_addrs_to_server(s, port_index, requested_port, out_port); } if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) { addr = &addr6_v4mapped; } if ((err = grpc_tcp_server_add_addr(s, addr, port_index, 0, &dsmode, &sp)) == GRPC_ERROR_NONE) { *out_port = sp->port; } return err; } /* Return listener at port_index or NULL. Should only be called with s->mu locked. */ static grpc_tcp_listener *get_port_index(grpc_tcp_server *s, unsigned port_index) { unsigned num_ports = 0; grpc_tcp_listener *sp; for (sp = s->head; sp; sp = sp->next) { if (!sp->is_sibling) { if (++num_ports > port_index) { return sp; } } } return NULL; } unsigned grpc_tcp_server_port_fd_count(grpc_tcp_server *s, unsigned port_index) { unsigned num_fds = 0; gpr_mu_lock(&s->mu); grpc_tcp_listener *sp = get_port_index(s, port_index); for (; sp; sp = sp->sibling) { ++num_fds; } gpr_mu_unlock(&s->mu); return num_fds; } int grpc_tcp_server_port_fd(grpc_tcp_server *s, unsigned port_index, unsigned fd_index) { gpr_mu_lock(&s->mu); grpc_tcp_listener *sp = get_port_index(s, port_index); for (; sp; sp = sp->sibling, --fd_index) { if (fd_index == 0) { gpr_mu_unlock(&s->mu); return sp->fd; } } gpr_mu_unlock(&s->mu); return -1; } void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s, grpc_pollset **pollsets, size_t pollset_count, grpc_tcp_server_cb on_accept_cb, void *on_accept_cb_arg) { size_t i; grpc_tcp_listener *sp; GPR_ASSERT(on_accept_cb); gpr_mu_lock(&s->mu); GPR_ASSERT(!s->on_accept_cb); GPR_ASSERT(s->active_ports == 0); s->on_accept_cb = on_accept_cb; s->on_accept_cb_arg = on_accept_cb_arg; s->pollsets = pollsets; s->pollset_count = pollset_count; sp = s->head; while (sp != NULL) { if (s->so_reuseport && !grpc_is_unix_socket(&sp->addr) && pollset_count > 1) { GPR_ASSERT(GRPC_LOG_IF_ERROR( "clone_port", clone_port(sp, (unsigned)(pollset_count - 1)))); for (i = 0; i < pollset_count; i++) { grpc_pollset_add_fd(exec_ctx, pollsets[i], sp->emfd); grpc_closure_init(&sp->read_closure, on_read, sp, grpc_schedule_on_exec_ctx); grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure); s->active_ports++; sp = sp->next; } } else { for (i = 0; i < pollset_count; i++) { grpc_pollset_add_fd(exec_ctx, pollsets[i], sp->emfd); } grpc_closure_init(&sp->read_closure, on_read, sp, grpc_schedule_on_exec_ctx); grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure); s->active_ports++; sp = sp->next; } } gpr_mu_unlock(&s->mu); } grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) { gpr_ref_non_zero(&s->refs); return s; } void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s, grpc_closure *shutdown_starting) { gpr_mu_lock(&s->mu); grpc_closure_list_append(&s->shutdown_starting, shutdown_starting, GRPC_ERROR_NONE); gpr_mu_unlock(&s->mu); } void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { if (gpr_unref(&s->refs)) { grpc_tcp_server_shutdown_listeners(exec_ctx, s); gpr_mu_lock(&s->mu); grpc_closure_list_sched(exec_ctx, &s->shutdown_starting); gpr_mu_unlock(&s->mu); tcp_server_destroy(exec_ctx, s); } } void grpc_tcp_server_shutdown_listeners(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { gpr_mu_lock(&s->mu); s->shutdown_listeners = true; /* shutdown all fd's */ if (s->active_ports) { grpc_tcp_listener *sp; for (sp = s->head; sp; sp = sp->next) { grpc_fd_shutdown(exec_ctx, sp->emfd, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Server shutdown")); } } gpr_mu_unlock(&s->mu); } #endif grpc-1.3.2/src/core/lib/iomgr/tcp_server_utils_posix.h000066400000000000000000000124021310511640000230270ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_TCP_SERVER_UTILS_POSIX_H #define GRPC_CORE_LIB_IOMGR_TCP_SERVER_UTILS_POSIX_H #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/socket_utils_posix.h" #include "src/core/lib/iomgr/tcp_server.h" /* one listening port */ typedef struct grpc_tcp_listener { int fd; grpc_fd *emfd; grpc_tcp_server *server; grpc_resolved_address addr; int port; unsigned port_index; unsigned fd_index; grpc_closure read_closure; grpc_closure destroyed_closure; struct grpc_tcp_listener *next; /* sibling is a linked list of all listeners for a given port. add_port and clone_port place all new listeners in the same sibling list. A member of the 'sibling' list is also a member of the 'next' list. The head of each sibling list has is_sibling==0, and subsequent members of sibling lists have is_sibling==1. is_sibling allows separate sibling lists to be identified while iterating through 'next'. */ struct grpc_tcp_listener *sibling; int is_sibling; } grpc_tcp_listener; /* the overall server */ struct grpc_tcp_server { gpr_refcount refs; /* Called whenever accept() succeeds on a server port. */ grpc_tcp_server_cb on_accept_cb; void *on_accept_cb_arg; gpr_mu mu; /* active port count: how many ports are actually still listening */ size_t active_ports; /* destroyed port count: how many ports are completely destroyed */ size_t destroyed_ports; /* is this server shutting down? */ bool shutdown; /* have listeners been shutdown? */ bool shutdown_listeners; /* use SO_REUSEPORT */ bool so_reuseport; /* expand wildcard addresses to a list of all local addresses */ bool expand_wildcard_addrs; /* linked list of server ports */ grpc_tcp_listener *head; grpc_tcp_listener *tail; unsigned nports; /* List of closures passed to shutdown_starting_add(). */ grpc_closure_list shutdown_starting; /* shutdown callback */ grpc_closure *shutdown_complete; /* all pollsets interested in new connections */ grpc_pollset **pollsets; /* number of pollsets in the pollsets array */ size_t pollset_count; /* next pollset to assign a channel to */ gpr_atm next_pollset_to_assign; /* channel args for this server */ grpc_channel_args *channel_args; }; /* If successful, add a listener to \a s for \a addr, set \a dsmode for the socket, and return the \a listener. */ grpc_error *grpc_tcp_server_add_addr(grpc_tcp_server *s, const grpc_resolved_address *addr, unsigned port_index, unsigned fd_index, grpc_dualstack_mode *dsmode, grpc_tcp_listener **listener); /* Get all addresses assigned to network interfaces on the machine and create a listener for each. requested_port is the port to use for every listener, or 0 to select one random port that will be used for every listener. Set *out_port to the port selected. Return GRPC_ERROR_NONE only if all listeners were added. */ grpc_error *grpc_tcp_server_add_all_local_addrs(grpc_tcp_server *s, unsigned port_index, int requested_port, int *out_port); /* Prepare a recently-created socket for listening. */ grpc_error *grpc_tcp_server_prepare_socket(int fd, const grpc_resolved_address *addr, bool so_reuseport, int *port); /* Ruturn true if the platform supports ifaddrs */ bool grpc_tcp_server_have_ifaddrs(void); #endif /* GRPC_CORE_LIB_IOMGR_TCP_SERVER_UTILS_POSIX_H */ grpc-1.3.2/src/core/lib/iomgr/tcp_server_utils_posix_common.c000066400000000000000000000161031310511640000243740ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_POSIX_SOCKET #include "src/core/lib/iomgr/tcp_server_utils_posix.h" #include #include #include #include #include #include #include #include #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" #define MIN_SAFE_ACCEPT_QUEUE_SIZE 100 static gpr_once s_init_max_accept_queue_size; static int s_max_accept_queue_size; /* get max listen queue size on linux */ static void init_max_accept_queue_size(void) { int n = SOMAXCONN; char buf[64]; FILE *fp = fopen("/proc/sys/net/core/somaxconn", "r"); if (fp == NULL) { /* 2.4 kernel. */ s_max_accept_queue_size = SOMAXCONN; return; } if (fgets(buf, sizeof buf, fp)) { char *end; long i = strtol(buf, &end, 10); if (i > 0 && i <= INT_MAX && end && *end == 0) { n = (int)i; } } fclose(fp); s_max_accept_queue_size = n; if (s_max_accept_queue_size < MIN_SAFE_ACCEPT_QUEUE_SIZE) { gpr_log(GPR_INFO, "Suspiciously small accept queue (%d) will probably lead to " "connection drops", s_max_accept_queue_size); } } static int get_max_accept_queue_size(void) { gpr_once_init(&s_init_max_accept_queue_size, init_max_accept_queue_size); return s_max_accept_queue_size; } static grpc_error *add_socket_to_server(grpc_tcp_server *s, int fd, const grpc_resolved_address *addr, unsigned port_index, unsigned fd_index, grpc_tcp_listener **listener) { grpc_tcp_listener *sp = NULL; int port = -1; char *addr_str; char *name; grpc_error *err = grpc_tcp_server_prepare_socket(fd, addr, s->so_reuseport, &port); if (err == GRPC_ERROR_NONE) { GPR_ASSERT(port > 0); grpc_sockaddr_to_string(&addr_str, addr, 1); gpr_asprintf(&name, "tcp-server-listener:%s", addr_str); gpr_mu_lock(&s->mu); s->nports++; GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server"); sp = gpr_malloc(sizeof(grpc_tcp_listener)); sp->next = NULL; if (s->head == NULL) { s->head = sp; } else { s->tail->next = sp; } s->tail = sp; sp->server = s; sp->fd = fd; sp->emfd = grpc_fd_create(fd, name); memcpy(&sp->addr, addr, sizeof(grpc_resolved_address)); sp->port = port; sp->port_index = port_index; sp->fd_index = fd_index; sp->is_sibling = 0; sp->sibling = NULL; GPR_ASSERT(sp->emfd); gpr_mu_unlock(&s->mu); gpr_free(addr_str); gpr_free(name); } *listener = sp; return err; } /* If successful, add a listener to s for addr, set *dsmode for the socket, and return the *listener. */ grpc_error *grpc_tcp_server_add_addr(grpc_tcp_server *s, const grpc_resolved_address *addr, unsigned port_index, unsigned fd_index, grpc_dualstack_mode *dsmode, grpc_tcp_listener **listener) { grpc_resolved_address addr4_copy; int fd; grpc_error *err = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, dsmode, &fd); if (err != GRPC_ERROR_NONE) { return err; } if (*dsmode == GRPC_DSMODE_IPV4 && grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) { addr = &addr4_copy; } return add_socket_to_server(s, fd, addr, port_index, fd_index, listener); } /* Prepare a recently-created socket for listening. */ grpc_error *grpc_tcp_server_prepare_socket(int fd, const grpc_resolved_address *addr, bool so_reuseport, int *port) { grpc_resolved_address sockname_temp; grpc_error *err = GRPC_ERROR_NONE; GPR_ASSERT(fd >= 0); if (so_reuseport && !grpc_is_unix_socket(addr)) { err = grpc_set_socket_reuse_port(fd, 1); if (err != GRPC_ERROR_NONE) goto error; } err = grpc_set_socket_nonblocking(fd, 1); if (err != GRPC_ERROR_NONE) goto error; err = grpc_set_socket_cloexec(fd, 1); if (err != GRPC_ERROR_NONE) goto error; if (!grpc_is_unix_socket(addr)) { err = grpc_set_socket_low_latency(fd, 1); if (err != GRPC_ERROR_NONE) goto error; err = grpc_set_socket_reuse_addr(fd, 1); if (err != GRPC_ERROR_NONE) goto error; } err = grpc_set_socket_no_sigpipe_if_possible(fd); if (err != GRPC_ERROR_NONE) goto error; GPR_ASSERT(addr->len < ~(socklen_t)0); if (bind(fd, (struct sockaddr *)addr->addr, (socklen_t)addr->len) < 0) { err = GRPC_OS_ERROR(errno, "bind"); goto error; } if (listen(fd, get_max_accept_queue_size()) < 0) { err = GRPC_OS_ERROR(errno, "listen"); goto error; } sockname_temp.len = sizeof(struct sockaddr_storage); if (getsockname(fd, (struct sockaddr *)sockname_temp.addr, (socklen_t *)&sockname_temp.len) < 0) { err = GRPC_OS_ERROR(errno, "getsockname"); goto error; } *port = grpc_sockaddr_get_port(&sockname_temp); return GRPC_ERROR_NONE; error: GPR_ASSERT(err != GRPC_ERROR_NONE); if (fd >= 0) { close(fd); } grpc_error *ret = grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Unable to configure socket", &err, 1), GRPC_ERROR_INT_FD, fd); GRPC_ERROR_UNREF(err); return ret; } #endif /* GRPC_POSIX_SOCKET */ grpc-1.3.2/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c000066400000000000000000000156151310511640000245270ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_HAVE_IFADDRS #include "src/core/lib/iomgr/tcp_server_utils_posix.h" #include #include #include #include #include #include #include #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" /* Return the listener in s with address addr or NULL. */ static grpc_tcp_listener *find_listener_with_addr(grpc_tcp_server *s, grpc_resolved_address *addr) { grpc_tcp_listener *l; gpr_mu_lock(&s->mu); for (l = s->head; l != NULL; l = l->next) { if (l->addr.len != addr->len) { continue; } if (memcmp(l->addr.addr, addr->addr, addr->len) == 0) { break; } } gpr_mu_unlock(&s->mu); return l; } /* Bind to "::" to get a port number not used by any address. */ static grpc_error *get_unused_port(int *port) { grpc_resolved_address wild; grpc_sockaddr_make_wildcard6(0, &wild); grpc_dualstack_mode dsmode; int fd; grpc_error *err = grpc_create_dualstack_socket(&wild, SOCK_STREAM, 0, &dsmode, &fd); if (err != GRPC_ERROR_NONE) { return err; } if (dsmode == GRPC_DSMODE_IPV4) { grpc_sockaddr_make_wildcard4(0, &wild); } if (bind(fd, (const struct sockaddr *)wild.addr, (socklen_t)wild.len) != 0) { err = GRPC_OS_ERROR(errno, "bind"); close(fd); return err; } if (getsockname(fd, (struct sockaddr *)wild.addr, (socklen_t *)&wild.len) != 0) { err = GRPC_OS_ERROR(errno, "getsockname"); close(fd); return err; } close(fd); *port = grpc_sockaddr_get_port(&wild); return *port <= 0 ? GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad port") : GRPC_ERROR_NONE; } grpc_error *grpc_tcp_server_add_all_local_addrs(grpc_tcp_server *s, unsigned port_index, int requested_port, int *out_port) { struct ifaddrs *ifa = NULL; struct ifaddrs *ifa_it; unsigned fd_index = 0; grpc_tcp_listener *sp = NULL; grpc_error *err = GRPC_ERROR_NONE; if (requested_port == 0) { /* Note: There could be a race where some local addrs can listen on the selected port and some can't. The sane way to handle this would be to retry by recreating the whole grpc_tcp_server. Backing out individual listeners and orphaning the FDs looks like too much trouble. */ if ((err = get_unused_port(&requested_port)) != GRPC_ERROR_NONE) { return err; } else if (requested_port <= 0) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad get_unused_port()"); } gpr_log(GPR_DEBUG, "Picked unused port %d", requested_port); } if (getifaddrs(&ifa) != 0 || ifa == NULL) { return GRPC_OS_ERROR(errno, "getifaddrs"); } for (ifa_it = ifa; ifa_it != NULL; ifa_it = ifa_it->ifa_next) { grpc_resolved_address addr; char *addr_str = NULL; grpc_dualstack_mode dsmode; grpc_tcp_listener *new_sp = NULL; const char *ifa_name = (ifa_it->ifa_name ? ifa_it->ifa_name : ""); if (ifa_it->ifa_addr == NULL) { continue; } else if (ifa_it->ifa_addr->sa_family == AF_INET) { addr.len = sizeof(struct sockaddr_in); } else if (ifa_it->ifa_addr->sa_family == AF_INET6) { addr.len = sizeof(struct sockaddr_in6); } else { continue; } memcpy(addr.addr, ifa_it->ifa_addr, addr.len); if (!grpc_sockaddr_set_port(&addr, requested_port)) { /* Should never happen, because we check sa_family above. */ err = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to set port"); break; } if (grpc_sockaddr_to_string(&addr_str, &addr, 0) < 0) { addr_str = gpr_strdup(""); } gpr_log(GPR_DEBUG, "Adding local addr from interface %s flags 0x%x to server: %s", ifa_name, ifa_it->ifa_flags, addr_str); /* We could have multiple interfaces with the same address (e.g., bonding), so look for duplicates. */ if (find_listener_with_addr(s, &addr) != NULL) { gpr_log(GPR_DEBUG, "Skipping duplicate addr %s on interface %s", addr_str, ifa_name); gpr_free(addr_str); continue; } if ((err = grpc_tcp_server_add_addr(s, &addr, port_index, fd_index, &dsmode, &new_sp)) != GRPC_ERROR_NONE) { char *err_str = NULL; grpc_error *root_err; if (gpr_asprintf(&err_str, "Failed to add listener: %s", addr_str) < 0) { err_str = gpr_strdup("Failed to add listener"); } root_err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(err_str); gpr_free(err_str); gpr_free(addr_str); err = grpc_error_add_child(root_err, err); break; } else { GPR_ASSERT(requested_port == new_sp->port); ++fd_index; if (sp != NULL) { new_sp->is_sibling = 1; sp->sibling = new_sp; } sp = new_sp; } gpr_free(addr_str); } freeifaddrs(ifa); if (err != GRPC_ERROR_NONE) { return err; } else if (sp == NULL) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("No local addresses"); } else { *out_port = sp->port; return GRPC_ERROR_NONE; } } bool grpc_tcp_server_have_ifaddrs(void) { return true; } #endif /* GRPC_HAVE_IFADDRS */ grpc-1.3.2/src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c000066400000000000000000000042311310511640000250540ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #if defined(GRPC_POSIX_SOCKET) && !defined(GRPC_HAVE_IFADDRS) #include "src/core/lib/iomgr/tcp_server_utils_posix.h" grpc_error *grpc_tcp_server_add_all_local_addrs(grpc_tcp_server *s, unsigned port_index, int requested_port, int *out_port) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("no ifaddrs available"); } bool grpc_tcp_server_have_ifaddrs(void) { return false; } #endif /* defined(GRPC_POSIX_SOCKET) && !defined(GRPC_HAVE_IFADDRS) */ grpc-1.3.2/src/core/lib/iomgr/tcp_server_uv.c000066400000000000000000000322531310511640000211000ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_UV #include #include #include #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/tcp_server.h" #include "src/core/lib/iomgr/tcp_uv.h" /* one listening port */ typedef struct grpc_tcp_listener grpc_tcp_listener; struct grpc_tcp_listener { uv_tcp_t *handle; grpc_tcp_server *server; unsigned port_index; int port; /* linked list */ struct grpc_tcp_listener *next; bool closed; }; struct grpc_tcp_server { gpr_refcount refs; /* Called whenever accept() succeeds on a server port. */ grpc_tcp_server_cb on_accept_cb; void *on_accept_cb_arg; int open_ports; /* linked list of server ports */ grpc_tcp_listener *head; grpc_tcp_listener *tail; /* List of closures passed to shutdown_starting_add(). */ grpc_closure_list shutdown_starting; /* shutdown callback */ grpc_closure *shutdown_complete; bool shutdown; grpc_resource_quota *resource_quota; }; grpc_error *grpc_tcp_server_create(grpc_exec_ctx *exec_ctx, grpc_closure *shutdown_complete, const grpc_channel_args *args, grpc_tcp_server **server) { grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server)); s->resource_quota = grpc_resource_quota_create(NULL); for (size_t i = 0; i < (args == NULL ? 0 : args->num_args); i++) { if (0 == strcmp(GRPC_ARG_RESOURCE_QUOTA, args->args[i].key)) { if (args->args[i].type == GRPC_ARG_POINTER) { grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota); s->resource_quota = grpc_resource_quota_ref_internal(args->args[i].value.pointer.p); } else { grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota); gpr_free(s); return GRPC_ERROR_CREATE_FROM_STATIC_STRING( GRPC_ARG_RESOURCE_QUOTA " must be a pointer to a buffer pool"); } } } gpr_ref_init(&s->refs, 1); s->on_accept_cb = NULL; s->on_accept_cb_arg = NULL; s->open_ports = 0; s->head = NULL; s->tail = NULL; s->shutdown_starting.head = NULL; s->shutdown_starting.tail = NULL; s->shutdown_complete = shutdown_complete; s->shutdown = false; *server = s; return GRPC_ERROR_NONE; } grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) { gpr_ref(&s->refs); return s; } void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s, grpc_closure *shutdown_starting) { grpc_closure_list_append(&s->shutdown_starting, shutdown_starting, GRPC_ERROR_NONE); } static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { GPR_ASSERT(s->shutdown); if (s->shutdown_complete != NULL) { grpc_closure_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE); } while (s->head) { grpc_tcp_listener *sp = s->head; s->head = sp->next; sp->next = NULL; gpr_free(sp->handle); gpr_free(sp); } grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota); gpr_free(s); } static void handle_close_callback(uv_handle_t *handle) { grpc_tcp_listener *sp = (grpc_tcp_listener *)handle->data; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; sp->server->open_ports--; if (sp->server->open_ports == 0 && sp->server->shutdown) { finish_shutdown(&exec_ctx, sp->server); } grpc_exec_ctx_finish(&exec_ctx); } static void close_listener(grpc_tcp_listener *sp) { if (!sp->closed) { sp->closed = true; uv_close((uv_handle_t *)sp->handle, handle_close_callback); } } static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { int immediately_done = 0; grpc_tcp_listener *sp; GPR_ASSERT(!s->shutdown); s->shutdown = true; if (s->open_ports == 0) { immediately_done = 1; } for (sp = s->head; sp; sp = sp->next) { close_listener(sp); } if (immediately_done) { finish_shutdown(exec_ctx, s); } } void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { if (gpr_unref(&s->refs)) { /* Complete shutdown_starting work before destroying. */ grpc_exec_ctx local_exec_ctx = GRPC_EXEC_CTX_INIT; grpc_closure_list_sched(&local_exec_ctx, &s->shutdown_starting); if (exec_ctx == NULL) { grpc_exec_ctx_flush(&local_exec_ctx); tcp_server_destroy(&local_exec_ctx, s); grpc_exec_ctx_finish(&local_exec_ctx); } else { grpc_exec_ctx_finish(&local_exec_ctx); tcp_server_destroy(exec_ctx, s); } } } static void accepted_connection_close_cb(uv_handle_t *handle) { gpr_free(handle); } static void on_connect(uv_stream_t *server, int status) { grpc_tcp_listener *sp = (grpc_tcp_listener *)server->data; uv_tcp_t *client; grpc_endpoint *ep = NULL; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resolved_address peer_name; char *peer_name_string; int err; if (status < 0) { switch (status) { case UV_EINTR: case UV_EAGAIN: return; default: close_listener(sp); return; } } client = gpr_malloc(sizeof(uv_tcp_t)); uv_tcp_init(uv_default_loop(), client); // UV documentation says this is guaranteed to succeed uv_accept((uv_stream_t *)server, (uv_stream_t *)client); // If the server has not been started, we discard incoming connections if (sp->server->on_accept_cb == NULL) { uv_close((uv_handle_t *)client, accepted_connection_close_cb); } else { peer_name_string = NULL; memset(&peer_name, 0, sizeof(grpc_resolved_address)); peer_name.len = sizeof(struct sockaddr_storage); err = uv_tcp_getpeername(client, (struct sockaddr *)&peer_name.addr, (int *)&peer_name.len); if (err == 0) { peer_name_string = grpc_sockaddr_to_uri(&peer_name); } else { gpr_log(GPR_INFO, "uv_tcp_getpeername error: %s", uv_strerror(status)); } ep = grpc_tcp_create(client, sp->server->resource_quota, peer_name_string); // Create acceptor. grpc_tcp_server_acceptor *acceptor = gpr_malloc(sizeof(*acceptor)); acceptor->from_server = sp->server; acceptor->port_index = sp->port_index; acceptor->fd_index = 0; sp->server->on_accept_cb(&exec_ctx, sp->server->on_accept_cb_arg, ep, NULL, acceptor); grpc_exec_ctx_finish(&exec_ctx); } } static grpc_error *add_socket_to_server(grpc_tcp_server *s, uv_tcp_t *handle, const grpc_resolved_address *addr, unsigned port_index, grpc_tcp_listener **listener) { grpc_tcp_listener *sp = NULL; int port = -1; int status; grpc_error *error; grpc_resolved_address sockname_temp; // The last argument to uv_tcp_bind is flags status = uv_tcp_bind(handle, (struct sockaddr *)addr->addr, 0); if (status != 0) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to bind to port"); error = grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, grpc_slice_from_static_string(uv_strerror(status))); return error; } status = uv_listen((uv_stream_t *)handle, SOMAXCONN, on_connect); if (status != 0) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to listen to port"); error = grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, grpc_slice_from_static_string(uv_strerror(status))); return error; } sockname_temp.len = (int)sizeof(struct sockaddr_storage); status = uv_tcp_getsockname(handle, (struct sockaddr *)&sockname_temp.addr, (int *)&sockname_temp.len); if (status != 0) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("getsockname failed"); error = grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, grpc_slice_from_static_string(uv_strerror(status))); return error; } port = grpc_sockaddr_get_port(&sockname_temp); GPR_ASSERT(port >= 0); GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server"); sp = gpr_malloc(sizeof(grpc_tcp_listener)); sp->next = NULL; if (s->head == NULL) { s->head = sp; } else { s->tail->next = sp; } s->tail = sp; sp->server = s; sp->handle = handle; sp->port = port; sp->port_index = port_index; sp->closed = false; handle->data = sp; s->open_ports++; GPR_ASSERT(sp->handle); *listener = sp; return GRPC_ERROR_NONE; } grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s, const grpc_resolved_address *addr, int *port) { // This function is mostly copied from tcp_server_windows.c grpc_tcp_listener *sp = NULL; uv_tcp_t *handle; grpc_resolved_address addr6_v4mapped; grpc_resolved_address wildcard; grpc_resolved_address *allocated_addr = NULL; grpc_resolved_address sockname_temp; unsigned port_index = 0; int status; grpc_error *error = GRPC_ERROR_NONE; if (s->tail != NULL) { port_index = s->tail->port_index + 1; } /* Check if this is a wildcard port, and if so, try to keep the port the same as some previously created listener. */ if (grpc_sockaddr_get_port(addr) == 0) { for (sp = s->head; sp; sp = sp->next) { sockname_temp.len = sizeof(struct sockaddr_storage); if (0 == uv_tcp_getsockname(sp->handle, (struct sockaddr *)&sockname_temp.addr, (int *)&sockname_temp.len)) { *port = grpc_sockaddr_get_port(&sockname_temp); if (*port > 0) { allocated_addr = gpr_malloc(sizeof(grpc_resolved_address)); memcpy(allocated_addr, addr, sizeof(grpc_resolved_address)); grpc_sockaddr_set_port(allocated_addr, *port); addr = allocated_addr; break; } } } } if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) { addr = &addr6_v4mapped; } /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */ if (grpc_sockaddr_is_wildcard(addr, port)) { grpc_sockaddr_make_wildcard6(*port, &wildcard); addr = &wildcard; } handle = gpr_malloc(sizeof(uv_tcp_t)); status = uv_tcp_init(uv_default_loop(), handle); if (status == 0) { error = add_socket_to_server(s, handle, addr, port_index, &sp); } else { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Failed to initialize UV tcp handle"); error = grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, grpc_slice_from_static_string(uv_strerror(status))); } gpr_free(allocated_addr); if (error != GRPC_ERROR_NONE) { grpc_error *error_out = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Failed to add port to server", &error, 1); GRPC_ERROR_UNREF(error); error = error_out; *port = -1; } else { GPR_ASSERT(sp != NULL); *port = sp->port; } return error; } void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *server, grpc_pollset **pollsets, size_t pollset_count, grpc_tcp_server_cb on_accept_cb, void *cb_arg) { grpc_tcp_listener *sp; (void)pollsets; (void)pollset_count; GPR_ASSERT(on_accept_cb); GPR_ASSERT(!server->on_accept_cb); server->on_accept_cb = on_accept_cb; server->on_accept_cb_arg = cb_arg; for (sp = server->head; sp; sp = sp->next) { GPR_ASSERT(uv_listen((uv_stream_t *)sp->handle, SOMAXCONN, on_connect) == 0); } } void grpc_tcp_server_shutdown_listeners(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {} #endif /* GRPC_UV */ grpc-1.3.2/src/core/lib/iomgr/tcp_server_windows.c000066400000000000000000000447771310511640000221560ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_WINSOCK_SOCKET #include "src/core/lib/iomgr/sockaddr.h" #include #include #include #include #include #include #include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/iocp_windows.h" #include "src/core/lib/iomgr/pollset_windows.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/socket_windows.h" #include "src/core/lib/iomgr/tcp_server.h" #include "src/core/lib/iomgr/tcp_windows.h" #define MIN_SAFE_ACCEPT_QUEUE_SIZE 100 /* one listening port */ typedef struct grpc_tcp_listener grpc_tcp_listener; struct grpc_tcp_listener { /* This seemingly magic number comes from AcceptEx's documentation. each address buffer needs to have at least 16 more bytes at their end. */ uint8_t addresses[(sizeof(struct sockaddr_in6) + 16) * 2]; /* This will hold the socket for the next accept. */ SOCKET new_socket; /* The listener winsocket. */ grpc_winsocket *socket; /* The actual TCP port number. */ int port; unsigned port_index; grpc_tcp_server *server; /* The cached AcceptEx for that port. */ LPFN_ACCEPTEX AcceptEx; int shutting_down; int outstanding_calls; /* closure for socket notification of accept being ready */ grpc_closure on_accept; /* linked list */ struct grpc_tcp_listener *next; }; /* the overall server */ struct grpc_tcp_server { gpr_refcount refs; /* Called whenever accept() succeeds on a server port. */ grpc_tcp_server_cb on_accept_cb; void *on_accept_cb_arg; gpr_mu mu; /* active port count: how many ports are actually still listening */ int active_ports; /* linked list of server ports */ grpc_tcp_listener *head; grpc_tcp_listener *tail; /* List of closures passed to shutdown_starting_add(). */ grpc_closure_list shutdown_starting; /* shutdown callback */ grpc_closure *shutdown_complete; grpc_channel_args *channel_args; }; /* Public function. Allocates the proper data structures to hold a grpc_tcp_server. */ grpc_error *grpc_tcp_server_create(grpc_exec_ctx *exec_ctx, grpc_closure *shutdown_complete, const grpc_channel_args *args, grpc_tcp_server **server) { grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server)); s->channel_args = grpc_channel_args_copy(args); gpr_ref_init(&s->refs, 1); gpr_mu_init(&s->mu); s->active_ports = 0; s->on_accept_cb = NULL; s->on_accept_cb_arg = NULL; s->head = NULL; s->tail = NULL; s->shutdown_starting.head = NULL; s->shutdown_starting.tail = NULL; s->shutdown_complete = shutdown_complete; *server = s; return GRPC_ERROR_NONE; } static void destroy_server(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_tcp_server *s = arg; /* Now that the accepts have been aborted, we can destroy the sockets. The IOCP won't get notified on these, so we can flag them as already closed by the system. */ while (s->head) { grpc_tcp_listener *sp = s->head; s->head = sp->next; sp->next = NULL; grpc_winsocket_destroy(sp->socket); gpr_free(sp); } grpc_channel_args_destroy(exec_ctx, s->channel_args); gpr_free(s); } static void finish_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { if (s->shutdown_complete != NULL) { grpc_closure_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE); } grpc_closure_sched(exec_ctx, grpc_closure_create(destroy_server, s, grpc_schedule_on_exec_ctx), GRPC_ERROR_NONE); } grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) { gpr_ref_non_zero(&s->refs); return s; } void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s, grpc_closure *shutdown_starting) { gpr_mu_lock(&s->mu); grpc_closure_list_append(&s->shutdown_starting, shutdown_starting, GRPC_ERROR_NONE); gpr_mu_unlock(&s->mu); } static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { grpc_tcp_listener *sp; gpr_mu_lock(&s->mu); /* First, shutdown all fd's. This will queue abortion calls for all of the pending accepts due to the normal operation mechanism. */ if (s->active_ports == 0) { finish_shutdown_locked(exec_ctx, s); } else { for (sp = s->head; sp; sp = sp->next) { sp->shutting_down = 1; grpc_winsocket_shutdown(sp->socket); } } gpr_mu_unlock(&s->mu); } void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { if (gpr_unref(&s->refs)) { grpc_tcp_server_shutdown_listeners(exec_ctx, s); gpr_mu_lock(&s->mu); grpc_closure_list_sched(exec_ctx, &s->shutdown_starting); gpr_mu_unlock(&s->mu); tcp_server_destroy(exec_ctx, s); } } /* Prepare (bind) a recently-created socket for listening. */ static grpc_error *prepare_socket(SOCKET sock, const grpc_resolved_address *addr, int *port) { grpc_resolved_address sockname_temp; grpc_error *error = GRPC_ERROR_NONE; error = grpc_tcp_prepare_socket(sock); if (error != GRPC_ERROR_NONE) { goto failure; } if (bind(sock, (const struct sockaddr *)addr->addr, (int)addr->len) == SOCKET_ERROR) { error = GRPC_WSA_ERROR(WSAGetLastError(), "bind"); goto failure; } if (listen(sock, SOMAXCONN) == SOCKET_ERROR) { error = GRPC_WSA_ERROR(WSAGetLastError(), "listen"); goto failure; } int sockname_temp_len = sizeof(struct sockaddr_storage); if (getsockname(sock, (struct sockaddr *)sockname_temp.addr, &sockname_temp_len) == SOCKET_ERROR) { error = GRPC_WSA_ERROR(WSAGetLastError(), "getsockname"); goto failure; } sockname_temp.len = (size_t)sockname_temp_len; *port = grpc_sockaddr_get_port(&sockname_temp); return GRPC_ERROR_NONE; failure: GPR_ASSERT(error != GRPC_ERROR_NONE); char *tgtaddr = grpc_sockaddr_to_uri(addr); grpc_error_set_int( grpc_error_set_str(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Failed to prepare server socket", &error, 1), GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(tgtaddr)), GRPC_ERROR_INT_FD, (intptr_t)sock); gpr_free(tgtaddr); GRPC_ERROR_UNREF(error); if (sock != INVALID_SOCKET) closesocket(sock); return error; } static void decrement_active_ports_and_notify_locked(grpc_exec_ctx *exec_ctx, grpc_tcp_listener *sp) { sp->shutting_down = 0; GPR_ASSERT(sp->server->active_ports > 0); if (0 == --sp->server->active_ports) { finish_shutdown_locked(exec_ctx, sp->server); } } /* In order to do an async accept, we need to create a socket first which will be the one assigned to the new incoming connection. */ static grpc_error *start_accept_locked(grpc_exec_ctx *exec_ctx, grpc_tcp_listener *port) { SOCKET sock = INVALID_SOCKET; BOOL success; DWORD addrlen = sizeof(struct sockaddr_in6) + 16; DWORD bytes_received = 0; grpc_error *error = GRPC_ERROR_NONE; if (port->shutting_down) { return GRPC_ERROR_NONE; } sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); if (sock == INVALID_SOCKET) { error = GRPC_WSA_ERROR(WSAGetLastError(), "WSASocket"); goto failure; } error = grpc_tcp_prepare_socket(sock); if (error != GRPC_ERROR_NONE) goto failure; /* Start the "accept" asynchronously. */ success = port->AcceptEx(port->socket->socket, sock, port->addresses, 0, addrlen, addrlen, &bytes_received, &port->socket->read_info.overlapped); /* It is possible to get an accept immediately without delay. However, we will still get an IOCP notification for it. So let's just ignore it. */ if (!success) { int last_error = WSAGetLastError(); if (last_error != ERROR_IO_PENDING) { error = GRPC_WSA_ERROR(last_error, "AcceptEx"); goto failure; } } /* We're ready to do the accept. Calling grpc_socket_notify_on_read may immediately process an accept that happened in the meantime. */ port->new_socket = sock; grpc_socket_notify_on_read(exec_ctx, port->socket, &port->on_accept); port->outstanding_calls++; return error; failure: GPR_ASSERT(error != GRPC_ERROR_NONE); if (sock != INVALID_SOCKET) closesocket(sock); return error; } /* Event manager callback when reads are ready. */ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_tcp_listener *sp = arg; SOCKET sock = sp->new_socket; grpc_winsocket_callback_info *info = &sp->socket->read_info; grpc_endpoint *ep = NULL; grpc_resolved_address peer_name; char *peer_name_string; char *fd_name; DWORD transfered_bytes; DWORD flags; BOOL wsa_success; int err; gpr_mu_lock(&sp->server->mu); peer_name.len = sizeof(struct sockaddr_storage); /* The general mechanism for shutting down is to queue abortion calls. While this is necessary in the read/write case, it's useless for the accept case. We only need to adjust the pending callback count */ if (error != GRPC_ERROR_NONE) { const char *msg = grpc_error_string(error); gpr_log(GPR_INFO, "Skipping on_accept due to error: %s", msg); gpr_mu_unlock(&sp->server->mu); return; } /* The IOCP notified us of a completed operation. Let's grab the results, and act accordingly. */ transfered_bytes = 0; wsa_success = WSAGetOverlappedResult(sock, &info->overlapped, &transfered_bytes, FALSE, &flags); if (!wsa_success) { if (!sp->shutting_down) { char *utf8_message = gpr_format_message(WSAGetLastError()); gpr_log(GPR_ERROR, "on_accept error: %s", utf8_message); gpr_free(utf8_message); } closesocket(sock); } else { if (!sp->shutting_down) { peer_name_string = NULL; err = setsockopt(sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&sp->socket->socket, sizeof(sp->socket->socket)); if (err) { char *utf8_message = gpr_format_message(WSAGetLastError()); gpr_log(GPR_ERROR, "setsockopt error: %s", utf8_message); gpr_free(utf8_message); } int peer_name_len = (int)peer_name.len; err = getpeername(sock, (struct sockaddr *)peer_name.addr, &peer_name_len); peer_name.len = (size_t)peer_name_len; if (!err) { peer_name_string = grpc_sockaddr_to_uri(&peer_name); } else { char *utf8_message = gpr_format_message(WSAGetLastError()); gpr_log(GPR_ERROR, "getpeername error: %s", utf8_message); gpr_free(utf8_message); } gpr_asprintf(&fd_name, "tcp_server:%s", peer_name_string); ep = grpc_tcp_create(exec_ctx, grpc_winsocket_create(sock, fd_name), sp->server->channel_args, peer_name_string); gpr_free(fd_name); gpr_free(peer_name_string); } else { closesocket(sock); } } /* The only time we should call our callback, is where we successfully managed to accept a connection, and created an endpoint. */ if (ep) { // Create acceptor. grpc_tcp_server_acceptor *acceptor = gpr_malloc(sizeof(*acceptor)); acceptor->from_server = sp->server; acceptor->port_index = sp->port_index; acceptor->fd_index = 0; sp->server->on_accept_cb(exec_ctx, sp->server->on_accept_cb_arg, ep, NULL, acceptor); } /* As we were notified from the IOCP of one and exactly one accept, the former socked we created has now either been destroy or assigned to the new connection. We need to create a new one for the next connection. */ GPR_ASSERT( GRPC_LOG_IF_ERROR("start_accept", start_accept_locked(exec_ctx, sp))); if (0 == --sp->outstanding_calls) { decrement_active_ports_and_notify_locked(exec_ctx, sp); } gpr_mu_unlock(&sp->server->mu); } static grpc_error *add_socket_to_server(grpc_tcp_server *s, SOCKET sock, const grpc_resolved_address *addr, unsigned port_index, grpc_tcp_listener **listener) { grpc_tcp_listener *sp = NULL; int port = -1; int status; GUID guid = WSAID_ACCEPTEX; DWORD ioctl_num_bytes; LPFN_ACCEPTEX AcceptEx; grpc_error *error = GRPC_ERROR_NONE; /* We need to grab the AcceptEx pointer for that port, as it may be interface-dependent. We'll cache it to avoid doing that again. */ status = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid), &AcceptEx, sizeof(AcceptEx), &ioctl_num_bytes, NULL, NULL); if (status != 0) { char *utf8_message = gpr_format_message(WSAGetLastError()); gpr_log(GPR_ERROR, "on_connect error: %s", utf8_message); gpr_free(utf8_message); closesocket(sock); return NULL; } error = prepare_socket(sock, addr, &port); if (error != GRPC_ERROR_NONE) { return error; } GPR_ASSERT(port >= 0); gpr_mu_lock(&s->mu); GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server"); sp = gpr_malloc(sizeof(grpc_tcp_listener)); sp->next = NULL; if (s->head == NULL) { s->head = sp; } else { s->tail->next = sp; } s->tail = sp; sp->server = s; sp->socket = grpc_winsocket_create(sock, "listener"); sp->shutting_down = 0; sp->outstanding_calls = 0; sp->AcceptEx = AcceptEx; sp->new_socket = INVALID_SOCKET; sp->port = port; sp->port_index = port_index; grpc_closure_init(&sp->on_accept, on_accept, sp, grpc_schedule_on_exec_ctx); GPR_ASSERT(sp->socket); gpr_mu_unlock(&s->mu); *listener = sp; return GRPC_ERROR_NONE; } grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s, const grpc_resolved_address *addr, int *port) { grpc_tcp_listener *sp = NULL; SOCKET sock; grpc_resolved_address addr6_v4mapped; grpc_resolved_address wildcard; grpc_resolved_address *allocated_addr = NULL; grpc_resolved_address sockname_temp; unsigned port_index = 0; grpc_error *error = GRPC_ERROR_NONE; if (s->tail != NULL) { port_index = s->tail->port_index + 1; } /* Check if this is a wildcard port, and if so, try to keep the port the same as some previously created listener. */ if (grpc_sockaddr_get_port(addr) == 0) { for (sp = s->head; sp; sp = sp->next) { int sockname_temp_len = sizeof(struct sockaddr_storage); if (0 == getsockname(sp->socket->socket, (struct sockaddr *)sockname_temp.addr, &sockname_temp_len)) { sockname_temp.len = (size_t)sockname_temp_len; *port = grpc_sockaddr_get_port(&sockname_temp); if (*port > 0) { allocated_addr = gpr_malloc(sizeof(grpc_resolved_address)); memcpy(allocated_addr, addr, sizeof(grpc_resolved_address)); grpc_sockaddr_set_port(allocated_addr, *port); addr = allocated_addr; break; } } } } if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) { addr = &addr6_v4mapped; } /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */ if (grpc_sockaddr_is_wildcard(addr, port)) { grpc_sockaddr_make_wildcard6(*port, &wildcard); addr = &wildcard; } sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); if (sock == INVALID_SOCKET) { error = GRPC_WSA_ERROR(WSAGetLastError(), "WSASocket"); goto done; } error = add_socket_to_server(s, sock, addr, port_index, &sp); done: gpr_free(allocated_addr); if (error != GRPC_ERROR_NONE) { grpc_error *error_out = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Failed to add port to server", &error, 1); GRPC_ERROR_UNREF(error); error = error_out; *port = -1; } else { GPR_ASSERT(sp != NULL); *port = sp->port; } return error; } void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s, grpc_pollset **pollset, size_t pollset_count, grpc_tcp_server_cb on_accept_cb, void *on_accept_cb_arg) { grpc_tcp_listener *sp; GPR_ASSERT(on_accept_cb); gpr_mu_lock(&s->mu); GPR_ASSERT(!s->on_accept_cb); GPR_ASSERT(s->active_ports == 0); s->on_accept_cb = on_accept_cb; s->on_accept_cb_arg = on_accept_cb_arg; for (sp = s->head; sp; sp = sp->next) { GPR_ASSERT( GRPC_LOG_IF_ERROR("start_accept", start_accept_locked(exec_ctx, sp))); s->active_ports++; } gpr_mu_unlock(&s->mu); } void grpc_tcp_server_shutdown_listeners(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {} #endif /* GRPC_WINSOCK_SOCKET */ grpc-1.3.2/src/core/lib/iomgr/tcp_uv.c000066400000000000000000000305351310511640000175130ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_UV #include #include #include #include #include #include #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/network_status_tracker.h" #include "src/core/lib/iomgr/resource_quota.h" #include "src/core/lib/iomgr/tcp_uv.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/string.h" int grpc_tcp_trace = 0; typedef struct { grpc_endpoint base; gpr_refcount refcount; uv_write_t write_req; uv_shutdown_t shutdown_req; uv_tcp_t *handle; grpc_closure *read_cb; grpc_closure *write_cb; grpc_slice read_slice; grpc_slice_buffer *read_slices; grpc_slice_buffer *write_slices; uv_buf_t *write_buffers; grpc_resource_user *resource_user; bool shutting_down; char *peer_string; grpc_pollset *pollset; } grpc_tcp; static void tcp_free(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) { grpc_resource_user_unref(exec_ctx, tcp->resource_user); gpr_free(tcp); } /*#define GRPC_TCP_REFCOUNT_DEBUG*/ #ifdef GRPC_TCP_REFCOUNT_DEBUG #define TCP_UNREF(exec_ctx, tcp, reason) \ tcp_unref((exec_ctx), (tcp), (reason), __FILE__, __LINE__) #define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__) static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp, const char *reason, const char *file, int line) { gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %" PRIiPTR " -> %" PRIiPTR, tcp, reason, tcp->refcount.count, tcp->refcount.count - 1); if (gpr_unref(&tcp->refcount)) { tcp_free(exec_ctx, tcp); } } static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file, int line) { gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP ref %p : %s %" PRIiPTR " -> %" PRIiPTR, tcp, reason, tcp->refcount.count, tcp->refcount.count + 1); gpr_ref(&tcp->refcount); } #else #define TCP_UNREF(exec_ctx, tcp, reason) tcp_unref((exec_ctx), (tcp)) #define TCP_REF(tcp, reason) tcp_ref((tcp)) static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) { if (gpr_unref(&tcp->refcount)) { tcp_free(exec_ctx, tcp); } } static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); } #endif static void uv_close_callback(uv_handle_t *handle) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_tcp *tcp = handle->data; TCP_UNREF(&exec_ctx, tcp, "destroy"); grpc_exec_ctx_finish(&exec_ctx); } static void alloc_uv_buf(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_tcp *tcp = handle->data; (void)suggested_size; tcp->read_slice = grpc_resource_user_slice_malloc( &exec_ctx, tcp->resource_user, GRPC_TCP_DEFAULT_READ_SLICE_SIZE); buf->base = (char *)GRPC_SLICE_START_PTR(tcp->read_slice); buf->len = GRPC_SLICE_LENGTH(tcp->read_slice); grpc_exec_ctx_finish(&exec_ctx); } static void read_callback(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) { grpc_slice sub; grpc_error *error; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_tcp *tcp = stream->data; grpc_closure *cb = tcp->read_cb; if (nread == 0) { // Nothing happened. Wait for the next callback return; } TCP_UNREF(&exec_ctx, tcp, "read"); tcp->read_cb = NULL; // TODO(murgatroid99): figure out what the return value here means uv_read_stop(stream); if (nread == UV_EOF) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("EOF"); } else if (nread > 0) { // Successful read sub = grpc_slice_sub_no_ref(tcp->read_slice, 0, (size_t)nread); grpc_slice_buffer_add(tcp->read_slices, sub); error = GRPC_ERROR_NONE; if (grpc_tcp_trace) { size_t i; const char *str = grpc_error_string(error); gpr_log(GPR_DEBUG, "read: error=%s", str); for (i = 0; i < tcp->read_slices->count; i++) { char *dump = grpc_dump_slice(tcp->read_slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "READ %p (peer=%s): %s", tcp, tcp->peer_string, dump); gpr_free(dump); } } } else { // nread < 0: Error error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("TCP Read failed"); } grpc_closure_sched(&exec_ctx, cb, error); grpc_exec_ctx_finish(&exec_ctx); } static void uv_endpoint_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_slice_buffer *read_slices, grpc_closure *cb) { grpc_tcp *tcp = (grpc_tcp *)ep; int status; grpc_error *error = GRPC_ERROR_NONE; GPR_ASSERT(tcp->read_cb == NULL); tcp->read_cb = cb; tcp->read_slices = read_slices; grpc_slice_buffer_reset_and_unref_internal(exec_ctx, read_slices); TCP_REF(tcp, "read"); // TODO(murgatroid99): figure out what the return value here means status = uv_read_start((uv_stream_t *)tcp->handle, alloc_uv_buf, read_callback); if (status != 0) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("TCP Read failed at start"); error = grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, grpc_slice_from_static_string(uv_strerror(status))); grpc_closure_sched(exec_ctx, cb, error); } if (grpc_tcp_trace) { const char *str = grpc_error_string(error); gpr_log(GPR_DEBUG, "Initiating read on %p: error=%s", tcp, str); } } static void write_callback(uv_write_t *req, int status) { grpc_tcp *tcp = req->data; grpc_error *error; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_closure *cb = tcp->write_cb; tcp->write_cb = NULL; TCP_UNREF(&exec_ctx, tcp, "write"); if (status == 0) { error = GRPC_ERROR_NONE; } else { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("TCP Write failed"); } if (grpc_tcp_trace) { const char *str = grpc_error_string(error); gpr_log(GPR_DEBUG, "write complete on %p: error=%s", tcp, str); } gpr_free(tcp->write_buffers); grpc_resource_user_free(&exec_ctx, tcp->resource_user, sizeof(uv_buf_t) * tcp->write_slices->count); grpc_closure_sched(&exec_ctx, cb, error); grpc_exec_ctx_finish(&exec_ctx); } static void uv_endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_slice_buffer *write_slices, grpc_closure *cb) { grpc_tcp *tcp = (grpc_tcp *)ep; uv_buf_t *buffers; unsigned int buffer_count; unsigned int i; grpc_slice *slice; uv_write_t *write_req; if (grpc_tcp_trace) { size_t j; for (j = 0; j < write_slices->count; j++) { char *data = grpc_dump_slice(write_slices->slices[j], GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "WRITE %p (peer=%s): %s", tcp, tcp->peer_string, data); gpr_free(data); } } if (tcp->shutting_down) { grpc_closure_sched(exec_ctx, cb, GRPC_ERROR_CREATE_FROM_STATIC_STRING( "TCP socket is shutting down")); return; } GPR_ASSERT(tcp->write_cb == NULL); tcp->write_slices = write_slices; GPR_ASSERT(tcp->write_slices->count <= UINT_MAX); if (tcp->write_slices->count == 0) { // No slices means we don't have to do anything, // and libuv doesn't like empty writes grpc_closure_sched(exec_ctx, cb, GRPC_ERROR_NONE); return; } tcp->write_cb = cb; buffer_count = (unsigned int)tcp->write_slices->count; buffers = gpr_malloc(sizeof(uv_buf_t) * buffer_count); grpc_resource_user_alloc(exec_ctx, tcp->resource_user, sizeof(uv_buf_t) * buffer_count, NULL); for (i = 0; i < buffer_count; i++) { slice = &tcp->write_slices->slices[i]; buffers[i].base = (char *)GRPC_SLICE_START_PTR(*slice); buffers[i].len = GRPC_SLICE_LENGTH(*slice); } tcp->write_buffers = buffers; write_req = &tcp->write_req; write_req->data = tcp; TCP_REF(tcp, "write"); // TODO(murgatroid99): figure out what the return value here means uv_write(write_req, (uv_stream_t *)tcp->handle, buffers, buffer_count, write_callback); } static void uv_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_pollset *pollset) { // No-op. We're ignoring pollsets currently (void)exec_ctx; (void)ep; (void)pollset; grpc_tcp *tcp = (grpc_tcp *)ep; tcp->pollset = pollset; } static void uv_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_pollset_set *pollset) { // No-op. We're ignoring pollsets currently (void)exec_ctx; (void)ep; (void)pollset; } static void shutdown_callback(uv_shutdown_t *req, int status) {} static void uv_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_error *why) { grpc_tcp *tcp = (grpc_tcp *)ep; if (!tcp->shutting_down) { tcp->shutting_down = true; uv_shutdown_t *req = &tcp->shutdown_req; uv_shutdown(req, (uv_stream_t *)tcp->handle, shutdown_callback); grpc_resource_user_shutdown(exec_ctx, tcp->resource_user); } GRPC_ERROR_UNREF(why); } static void uv_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) { grpc_network_status_unregister_endpoint(ep); grpc_tcp *tcp = (grpc_tcp *)ep; uv_close((uv_handle_t *)tcp->handle, uv_close_callback); } static char *uv_get_peer(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; return gpr_strdup(tcp->peer_string); } static grpc_resource_user *uv_get_resource_user(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; return tcp->resource_user; } static grpc_workqueue *uv_get_workqueue(grpc_endpoint *ep) { return NULL; } static int uv_get_fd(grpc_endpoint *ep) { return -1; } static grpc_endpoint_vtable vtable = { uv_endpoint_read, uv_endpoint_write, uv_get_workqueue, uv_add_to_pollset, uv_add_to_pollset_set, uv_endpoint_shutdown, uv_destroy, uv_get_resource_user, uv_get_peer, uv_get_fd}; grpc_endpoint *grpc_tcp_create(uv_tcp_t *handle, grpc_resource_quota *resource_quota, char *peer_string) { grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp)); if (grpc_tcp_trace) { gpr_log(GPR_DEBUG, "Creating TCP endpoint %p", tcp); } /* Disable Nagle's Algorithm */ uv_tcp_nodelay(handle, 1); memset(tcp, 0, sizeof(grpc_tcp)); tcp->base.vtable = &vtable; tcp->handle = handle; handle->data = tcp; gpr_ref_init(&tcp->refcount, 1); tcp->peer_string = gpr_strdup(peer_string); tcp->shutting_down = false; tcp->resource_user = grpc_resource_user_create(resource_quota, peer_string); /* Tell network status tracking code about the new endpoint */ grpc_network_status_register_endpoint(&tcp->base); #ifndef GRPC_UV_TCP_HOLD_LOOP uv_unref((uv_handle_t *)handle); #endif return &tcp->base; } #endif /* GRPC_UV */ grpc-1.3.2/src/core/lib/iomgr/tcp_uv.h000066400000000000000000000043731310511640000175210ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_TCP_UV_H #define GRPC_CORE_LIB_IOMGR_TCP_UV_H /* Low level TCP "bottom half" implementation, for use by transports built on top of a TCP connection. Note that this file does not (yet) include APIs for creating the socket in the first place. All calls passing slice transfer ownership of a slice refcount unless otherwise specified. */ #include "src/core/lib/iomgr/endpoint.h" #include extern int grpc_tcp_trace; #define GRPC_TCP_DEFAULT_READ_SLICE_SIZE 8192 grpc_endpoint *grpc_tcp_create(uv_tcp_t *handle, grpc_resource_quota *resource_quota, char *peer_string); #endif /* GRPC_CORE_LIB_IOMGR_TCP_UV_H */ grpc-1.3.2/src/core/lib/iomgr/tcp_windows.c000066400000000000000000000400011310511640000205400ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_WINSOCK_SOCKET #include #include "src/core/lib/iomgr/network_status_tracker.h" #include "src/core/lib/iomgr/sockaddr_windows.h" #include #include #include #include #include #include #include "src/core/lib/iomgr/iocp_windows.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/socket_windows.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/slice/slice_internal.h" #if defined(__MSYS__) && defined(GPR_ARCH_64) /* Nasty workaround for nasty bug when using the 64 bits msys compiler in conjunction with Microsoft Windows headers. */ #define GRPC_FIONBIO _IOW('f', 126, uint32_t) #else #define GRPC_FIONBIO FIONBIO #endif static grpc_error *set_non_block(SOCKET sock) { int status; uint32_t param = 1; DWORD ret; status = WSAIoctl(sock, GRPC_FIONBIO, ¶m, sizeof(param), NULL, 0, &ret, NULL, NULL); return status == 0 ? GRPC_ERROR_NONE : GRPC_WSA_ERROR(WSAGetLastError(), "WSAIoctl(GRPC_FIONBIO)"); } static grpc_error *set_dualstack(SOCKET sock) { int status; unsigned long param = 0; status = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)¶m, sizeof(param)); return status == 0 ? GRPC_ERROR_NONE : GRPC_WSA_ERROR(WSAGetLastError(), "setsockopt(IPV6_V6ONLY)"); } grpc_error *grpc_tcp_prepare_socket(SOCKET sock) { grpc_error *err; err = set_non_block(sock); if (err != GRPC_ERROR_NONE) return err; err = set_dualstack(sock); if (err != GRPC_ERROR_NONE) return err; return GRPC_ERROR_NONE; } typedef struct grpc_tcp { /* This is our C++ class derivation emulation. */ grpc_endpoint base; /* The one socket this endpoint is using. */ grpc_winsocket *socket; /* Refcounting how many operations are in progress. */ gpr_refcount refcount; grpc_closure on_read; grpc_closure on_write; grpc_closure *read_cb; grpc_closure *write_cb; grpc_slice read_slice; grpc_slice_buffer *write_slices; grpc_slice_buffer *read_slices; grpc_resource_user *resource_user; /* The IO Completion Port runs from another thread. We need some mechanism to protect ourselves when requesting a shutdown. */ gpr_mu mu; int shutting_down; grpc_error *shutdown_error; char *peer_string; } grpc_tcp; static void tcp_free(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) { grpc_winsocket_destroy(tcp->socket); gpr_mu_destroy(&tcp->mu); gpr_free(tcp->peer_string); grpc_resource_user_unref(exec_ctx, tcp->resource_user); if (tcp->shutting_down) GRPC_ERROR_UNREF(tcp->shutdown_error); gpr_free(tcp); } /*#define GRPC_TCP_REFCOUNT_DEBUG*/ #ifdef GRPC_TCP_REFCOUNT_DEBUG #define TCP_UNREF(exec_ctx, tcp, reason) \ tcp_unref((exec_ctx), (tcp), (reason), __FILE__, __LINE__) #define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__) static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp, const char *reason, const char *file, int line) { gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp, reason, tcp->refcount.count, tcp->refcount.count - 1); if (gpr_unref(&tcp->refcount)) { tcp_free(exec_ctx, tcp); } } static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file, int line) { gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP ref %p : %s %d -> %d", tcp, reason, tcp->refcount.count, tcp->refcount.count + 1); gpr_ref(&tcp->refcount); } #else #define TCP_UNREF(exec_ctx, tcp, reason) tcp_unref((exec_ctx), (tcp)) #define TCP_REF(tcp, reason) tcp_ref((tcp)) static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) { if (gpr_unref(&tcp->refcount)) { tcp_free(exec_ctx, tcp); } } static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); } #endif /* Asynchronous callback from the IOCP, or the background thread. */ static void on_read(grpc_exec_ctx *exec_ctx, void *tcpp, grpc_error *error) { grpc_tcp *tcp = tcpp; grpc_closure *cb = tcp->read_cb; grpc_winsocket *socket = tcp->socket; grpc_slice sub; grpc_winsocket_callback_info *info = &socket->read_info; GRPC_ERROR_REF(error); if (error == GRPC_ERROR_NONE) { if (info->wsa_error != 0 && !tcp->shutting_down) { char *utf8_message = gpr_format_message(info->wsa_error); error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(utf8_message); gpr_free(utf8_message); grpc_slice_unref_internal(exec_ctx, tcp->read_slice); } else { if (info->bytes_transfered != 0 && !tcp->shutting_down) { sub = grpc_slice_sub_no_ref(tcp->read_slice, 0, info->bytes_transfered); grpc_slice_buffer_add(tcp->read_slices, sub); } else { grpc_slice_unref_internal(exec_ctx, tcp->read_slice); error = tcp->shutting_down ? GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "TCP stream shutting down", &tcp->shutdown_error, 1) : GRPC_ERROR_CREATE_FROM_STATIC_STRING("End of TCP stream"); } } } tcp->read_cb = NULL; TCP_UNREF(exec_ctx, tcp, "read"); grpc_closure_sched(exec_ctx, cb, error); } static void win_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_slice_buffer *read_slices, grpc_closure *cb) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_winsocket *handle = tcp->socket; grpc_winsocket_callback_info *info = &handle->read_info; int status; DWORD bytes_read = 0; DWORD flags = 0; WSABUF buffer; if (tcp->shutting_down) { grpc_closure_sched( exec_ctx, cb, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "TCP socket is shutting down", &tcp->shutdown_error, 1)); return; } tcp->read_cb = cb; tcp->read_slices = read_slices; grpc_slice_buffer_reset_and_unref_internal(exec_ctx, read_slices); tcp->read_slice = grpc_slice_malloc(8192); buffer.len = (ULONG)GRPC_SLICE_LENGTH( tcp->read_slice); // we know slice size fits in 32bit. buffer.buf = (char *)GRPC_SLICE_START_PTR(tcp->read_slice); TCP_REF(tcp, "read"); /* First let's try a synchronous, non-blocking read. */ status = WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags, NULL, NULL); info->wsa_error = status == 0 ? 0 : WSAGetLastError(); /* Did we get data immediately ? Yay. */ if (info->wsa_error != WSAEWOULDBLOCK) { info->bytes_transfered = bytes_read; grpc_closure_sched(exec_ctx, &tcp->on_read, GRPC_ERROR_NONE); return; } /* Otherwise, let's retry, by queuing a read. */ memset(&tcp->socket->read_info.overlapped, 0, sizeof(OVERLAPPED)); status = WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags, &info->overlapped, NULL); if (status != 0) { int wsa_error = WSAGetLastError(); if (wsa_error != WSA_IO_PENDING) { info->wsa_error = wsa_error; grpc_closure_sched(exec_ctx, &tcp->on_read, GRPC_WSA_ERROR(info->wsa_error, "WSARecv")); return; } } grpc_socket_notify_on_read(exec_ctx, tcp->socket, &tcp->on_read); } /* Asynchronous callback from the IOCP, or the background thread. */ static void on_write(grpc_exec_ctx *exec_ctx, void *tcpp, grpc_error *error) { grpc_tcp *tcp = (grpc_tcp *)tcpp; grpc_winsocket *handle = tcp->socket; grpc_winsocket_callback_info *info = &handle->write_info; grpc_closure *cb; GRPC_ERROR_REF(error); gpr_mu_lock(&tcp->mu); cb = tcp->write_cb; tcp->write_cb = NULL; gpr_mu_unlock(&tcp->mu); if (error == GRPC_ERROR_NONE) { if (info->wsa_error != 0) { error = GRPC_WSA_ERROR(info->wsa_error, "WSASend"); } else { GPR_ASSERT(info->bytes_transfered == tcp->write_slices->length); } } TCP_UNREF(exec_ctx, tcp, "write"); grpc_closure_sched(exec_ctx, cb, error); } /* Initiates a write. */ static void win_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_slice_buffer *slices, grpc_closure *cb) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_winsocket *socket = tcp->socket; grpc_winsocket_callback_info *info = &socket->write_info; unsigned i; DWORD bytes_sent; int status; WSABUF local_buffers[16]; WSABUF *allocated = NULL; WSABUF *buffers = local_buffers; size_t len; if (tcp->shutting_down) { grpc_closure_sched( exec_ctx, cb, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "TCP socket is shutting down", &tcp->shutdown_error, 1)); return; } tcp->write_cb = cb; tcp->write_slices = slices; GPR_ASSERT(tcp->write_slices->count <= UINT_MAX); if (tcp->write_slices->count > GPR_ARRAY_SIZE(local_buffers)) { buffers = (WSABUF *)gpr_malloc(sizeof(WSABUF) * tcp->write_slices->count); allocated = buffers; } for (i = 0; i < tcp->write_slices->count; i++) { len = GRPC_SLICE_LENGTH(tcp->write_slices->slices[i]); GPR_ASSERT(len <= ULONG_MAX); buffers[i].len = (ULONG)len; buffers[i].buf = (char *)GRPC_SLICE_START_PTR(tcp->write_slices->slices[i]); } /* First, let's try a synchronous, non-blocking write. */ status = WSASend(socket->socket, buffers, (DWORD)tcp->write_slices->count, &bytes_sent, 0, NULL, NULL); info->wsa_error = status == 0 ? 0 : WSAGetLastError(); /* We would kind of expect to get a WSAEWOULDBLOCK here, especially on a busy connection that has its send queue filled up. But if we don't, then we can avoid doing an async write operation at all. */ if (info->wsa_error != WSAEWOULDBLOCK) { grpc_error *error = status == 0 ? GRPC_ERROR_NONE : GRPC_WSA_ERROR(info->wsa_error, "WSASend"); grpc_closure_sched(exec_ctx, cb, error); if (allocated) gpr_free(allocated); return; } TCP_REF(tcp, "write"); /* If we got a WSAEWOULDBLOCK earlier, then we need to re-do the same operation, this time asynchronously. */ memset(&socket->write_info.overlapped, 0, sizeof(OVERLAPPED)); status = WSASend(socket->socket, buffers, (DWORD)tcp->write_slices->count, &bytes_sent, 0, &socket->write_info.overlapped, NULL); if (allocated) gpr_free(allocated); if (status != 0) { int wsa_error = WSAGetLastError(); if (wsa_error != WSA_IO_PENDING) { TCP_UNREF(exec_ctx, tcp, "write"); grpc_closure_sched(exec_ctx, cb, GRPC_WSA_ERROR(wsa_error, "WSASend")); return; } } /* As all is now setup, we can now ask for the IOCP notification. It may trigger the callback immediately however, but no matter. */ grpc_socket_notify_on_write(exec_ctx, socket, &tcp->on_write); } static void win_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_pollset *ps) { grpc_tcp *tcp; (void)ps; tcp = (grpc_tcp *)ep; grpc_iocp_add_socket(tcp->socket); } static void win_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_pollset_set *pss) { grpc_tcp *tcp; (void)pss; tcp = (grpc_tcp *)ep; grpc_iocp_add_socket(tcp->socket); } /* Initiates a shutdown of the TCP endpoint. This will queue abort callbacks for the potential read and write operations. It is up to the caller to guarantee this isn't called in parallel to a read or write request, so we're not going to protect against these. However the IO Completion Port callback will happen from another thread, so we need to protect against concurrent access of the data structure in that regard. */ static void win_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_error *why) { grpc_tcp *tcp = (grpc_tcp *)ep; gpr_mu_lock(&tcp->mu); /* At that point, what may happen is that we're already inside the IOCP callback. See the comments in on_read and on_write. */ if (!tcp->shutting_down) { tcp->shutting_down = 1; tcp->shutdown_error = why; } else { GRPC_ERROR_UNREF(why); } grpc_winsocket_shutdown(tcp->socket); gpr_mu_unlock(&tcp->mu); grpc_resource_user_shutdown(exec_ctx, tcp->resource_user); } static void win_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) { grpc_network_status_unregister_endpoint(ep); grpc_tcp *tcp = (grpc_tcp *)ep; TCP_UNREF(exec_ctx, tcp, "destroy"); } static char *win_get_peer(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; return gpr_strdup(tcp->peer_string); } static grpc_workqueue *win_get_workqueue(grpc_endpoint *ep) { return NULL; } static grpc_resource_user *win_get_resource_user(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; return tcp->resource_user; } static int win_get_fd(grpc_endpoint *ep) { return -1; } static grpc_endpoint_vtable vtable = {win_read, win_write, win_get_workqueue, win_add_to_pollset, win_add_to_pollset_set, win_shutdown, win_destroy, win_get_resource_user, win_get_peer, win_get_fd}; grpc_endpoint *grpc_tcp_create(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket, grpc_channel_args *channel_args, char *peer_string) { grpc_resource_quota *resource_quota = grpc_resource_quota_create(NULL); if (channel_args != NULL) { for (size_t i = 0; i < channel_args->num_args; i++) { if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_RESOURCE_QUOTA)) { grpc_resource_quota_unref_internal(exec_ctx, resource_quota); resource_quota = grpc_resource_quota_ref_internal( channel_args->args[i].value.pointer.p); } } } grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp)); memset(tcp, 0, sizeof(grpc_tcp)); tcp->base.vtable = &vtable; tcp->socket = socket; gpr_mu_init(&tcp->mu); gpr_ref_init(&tcp->refcount, 1); grpc_closure_init(&tcp->on_read, on_read, tcp, grpc_schedule_on_exec_ctx); grpc_closure_init(&tcp->on_write, on_write, tcp, grpc_schedule_on_exec_ctx); tcp->peer_string = gpr_strdup(peer_string); tcp->resource_user = grpc_resource_user_create(resource_quota, peer_string); /* Tell network status tracking code about the new endpoint */ grpc_network_status_register_endpoint(&tcp->base); return &tcp->base; } #endif /* GRPC_WINSOCK_SOCKET */ grpc-1.3.2/src/core/lib/iomgr/tcp_windows.h000066400000000000000000000046021310511640000205540ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_TCP_WINDOWS_H #define GRPC_CORE_LIB_IOMGR_TCP_WINDOWS_H /* Low level TCP "bottom half" implementation, for use by transports built on top of a TCP connection. Note that this file does not (yet) include APIs for creating the socket in the first place. All calls passing slice transfer ownership of a slice refcount unless otherwise specified. */ #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/socket_windows.h" /* Create a tcp endpoint given a winsock handle. * Takes ownership of the handle. */ grpc_endpoint *grpc_tcp_create(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket, grpc_channel_args *channel_args, char *peer_string); grpc_error *grpc_tcp_prepare_socket(SOCKET sock); #endif /* GRPC_CORE_LIB_IOMGR_TCP_WINDOWS_H */ grpc-1.3.2/src/core/lib/iomgr/time_averaged_stats.c000066400000000000000000000063161310511640000222250ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/time_averaged_stats.h" void grpc_time_averaged_stats_init(grpc_time_averaged_stats* stats, double init_avg, double regress_weight, double persistence_factor) { stats->init_avg = init_avg; stats->regress_weight = regress_weight; stats->persistence_factor = persistence_factor; stats->batch_total_value = 0; stats->batch_num_samples = 0; stats->aggregate_total_weight = 0; stats->aggregate_weighted_avg = init_avg; } void grpc_time_averaged_stats_add_sample(grpc_time_averaged_stats* stats, double value) { stats->batch_total_value += value; ++stats->batch_num_samples; } double grpc_time_averaged_stats_update_average( grpc_time_averaged_stats* stats) { /* Start with the current batch: */ double weighted_sum = stats->batch_total_value; double total_weight = stats->batch_num_samples; if (stats->regress_weight > 0) { /* Add in the regression towards init_avg_: */ weighted_sum += stats->regress_weight * stats->init_avg; total_weight += stats->regress_weight; } if (stats->persistence_factor > 0) { /* Add in the persistence: */ const double prev_sample_weight = stats->persistence_factor * stats->aggregate_total_weight; weighted_sum += prev_sample_weight * stats->aggregate_weighted_avg; total_weight += prev_sample_weight; } stats->aggregate_weighted_avg = (total_weight > 0) ? (weighted_sum / total_weight) : stats->init_avg; stats->aggregate_total_weight = total_weight; stats->batch_num_samples = 0; stats->batch_total_value = 0; return stats->aggregate_weighted_avg; } grpc-1.3.2/src/core/lib/iomgr/time_averaged_stats.h000066400000000000000000000105771310511640000222360ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_TIME_AVERAGED_STATS_H #define GRPC_CORE_LIB_IOMGR_TIME_AVERAGED_STATS_H /* This tracks a time-decaying weighted average. It works by collecting batches of samples and then mixing their average into a time-decaying weighted mean. It is designed for batch operations where we do many adds before updating the average. */ typedef struct { /* The initial average value. This is the reported average until the first grpc_time_averaged_stats_update_average call. If a positive regress_weight is used, we also regress towards this value on each update. */ double init_avg; /* The sample weight of "init_avg" that is mixed in with each call to grpc_time_averaged_stats_update_average. If the calls to grpc_time_averaged_stats_add_sample stop, this will cause the average to regress back to the mean. This should be non-negative. Set it to 0 to disable the bias. A value of 1 has the effect of adding in 1 bonus sample with value init_avg to each sample period. */ double regress_weight; /* This determines the rate of decay of the time-averaging from one period to the next by scaling the aggregate_total_weight of samples from prior periods when combining with the latest period. It should be in the range [0,1]. A higher value adapts more slowly. With a value of 0.5, if the batches each have k samples, the samples_in_avg_ will grow to 2 k, so the weighting of the time average will eventually be 1/3 new batch and 2/3 old average. */ double persistence_factor; /* The total value of samples since the last UpdateAverage(). */ double batch_total_value; /* The number of samples since the last UpdateAverage(). */ double batch_num_samples; /* The time-decayed sum of batch_num_samples_ over previous batches. This is the "weight" of the old aggregate_weighted_avg_ when updating the average. */ double aggregate_total_weight; /* A time-decayed average of the (batch_total_value_ / batch_num_samples_), computed by decaying the samples_in_avg_ weight in the weighted average. */ double aggregate_weighted_avg; } grpc_time_averaged_stats; /* See the comments on the members above for an explanation of init_avg, regress_weight, and persistence_factor. */ void grpc_time_averaged_stats_init(grpc_time_averaged_stats* stats, double init_avg, double regress_weight, double persistence_factor); /* Add a sample to the current batch. */ void grpc_time_averaged_stats_add_sample(grpc_time_averaged_stats* stats, double value); /* Complete a batch and compute the new estimate of the average sample value. */ double grpc_time_averaged_stats_update_average(grpc_time_averaged_stats* stats); #endif /* GRPC_CORE_LIB_IOMGR_TIME_AVERAGED_STATS_H */ grpc-1.3.2/src/core/lib/iomgr/timer.h000066400000000000000000000114231310511640000173330ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_TIMER_H #define GRPC_CORE_LIB_IOMGR_TIMER_H #include "src/core/lib/iomgr/port.h" #ifdef GRPC_UV #include "src/core/lib/iomgr/timer_uv.h" #else #include "src/core/lib/iomgr/timer_generic.h" #endif /* GRPC_UV */ #include #include #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/iomgr.h" typedef struct grpc_timer grpc_timer; /* Initialize *timer. When expired or canceled, closure will be called with error set to indicate if it expired (GRPC_ERROR_NONE) or was canceled (GRPC_ERROR_CANCELLED). timer_cb is guaranteed to be called exactly once, and application code should check the error to determine how it was invoked. The application callback is also responsible for maintaining information about when to free up any user-level state. */ void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer, gpr_timespec deadline, grpc_closure *closure, gpr_timespec now); /* Note that there is no timer destroy function. This is because the timer is a one-time occurrence with a guarantee that the callback will be called exactly once, either at expiration or cancellation. Thus, all the internal timer event management state is destroyed just before that callback is invoked. If the user has additional state associated with the timer, the user is responsible for determining when it is safe to destroy that state. */ /* Cancel an *timer. There are three cases: 1. We normally cancel the timer 2. The timer has already run 3. We can't cancel the timer because it is "in flight". In all of these cases, the cancellation is still considered successful. They are essentially distinguished in that the timer_cb will be run exactly once from either the cancellation (with error GRPC_ERROR_CANCELLED) or from the activation (with error GRPC_ERROR_NONE). Note carefully that the callback function MAY occur in the same callstack as grpc_timer_cancel. It's expected that most timers will be cancelled (their primary use is to implement deadlines), and so this code is optimized such that cancellation costs as little as possible. Making callbacks run inline matches this aim. Requires: cancel() must happen after init() on a given timer */ void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer); /* iomgr internal api for dealing with timers */ /* Check for timers to be run, and run them. Return true if timer callbacks were executed. If next is non-null, TRY to update *next with the next running timer IF that timer occurs before *next current value. *next is never guaranteed to be updated on any given execution; however, with high probability at least one thread in the system will see an update at any time slice. */ bool grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now, gpr_timespec *next); void grpc_timer_list_init(gpr_timespec now); void grpc_timer_list_shutdown(grpc_exec_ctx *exec_ctx); /* Consume a kick issued by grpc_kick_poller */ void grpc_timer_consume_kick(void); /* the following must be implemented by each iomgr implementation */ void grpc_kick_poller(void); #endif /* GRPC_CORE_LIB_IOMGR_TIMER_H */ grpc-1.3.2/src/core/lib/iomgr/timer_generic.c000066400000000000000000000477651310511640000210440ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_TIMER_USE_GENERIC #include "src/core/lib/iomgr/timer.h" #include #include #include #include #include #include #include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/time_averaged_stats.h" #include "src/core/lib/iomgr/timer_heap.h" #include "src/core/lib/support/spinlock.h" #define INVALID_HEAP_INDEX 0xffffffffu #define LOG2_NUM_SHARDS 5 #define NUM_SHARDS (1 << LOG2_NUM_SHARDS) #define ADD_DEADLINE_SCALE 0.33 #define MIN_QUEUE_WINDOW_DURATION 0.01 #define MAX_QUEUE_WINDOW_DURATION 1 int grpc_timer_trace = 0; int grpc_timer_check_trace = 0; typedef struct { gpr_mu mu; grpc_time_averaged_stats stats; /* All and only timers with deadlines <= this will be in the heap. */ gpr_atm queue_deadline_cap; gpr_atm min_deadline; /* Index in the g_shard_queue */ uint32_t shard_queue_index; /* This holds all timers with deadlines < queue_deadline_cap. Timers in this list have the top bit of their deadline set to 0. */ grpc_timer_heap heap; /* This holds timers whose deadline is >= queue_deadline_cap. */ grpc_timer list; } shard_type; struct shared_mutables { gpr_atm min_timer; /* Allow only one run_some_expired_timers at once */ gpr_spinlock checker_mu; bool initialized; /* Protects g_shard_queue */ gpr_mu mu; } GPR_ALIGN_STRUCT(GPR_CACHELINE_SIZE); static struct shared_mutables g_shared_mutables = { .checker_mu = GPR_SPINLOCK_STATIC_INITIALIZER, .initialized = false, }; static gpr_clock_type g_clock_type; static shard_type g_shards[NUM_SHARDS]; /* Protected by g_shared_mutables.mu */ static shard_type *g_shard_queue[NUM_SHARDS]; static gpr_timespec g_start_time; GPR_TLS_DECL(g_last_seen_min_timer); static gpr_atm saturating_add(gpr_atm a, gpr_atm b) { if (a > GPR_ATM_MAX - b) { return GPR_ATM_MAX; } return a + b; } static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_atm now, gpr_atm *next, grpc_error *error); static gpr_timespec dbl_to_ts(double d) { gpr_timespec ts; ts.tv_sec = (int64_t)d; ts.tv_nsec = (int32_t)(1e9 * (d - (double)ts.tv_sec)); ts.clock_type = GPR_TIMESPAN; return ts; } static gpr_atm timespec_to_atm_round_up(gpr_timespec ts) { ts = gpr_time_sub(ts, g_start_time); double x = GPR_MS_PER_SEC * (double)ts.tv_sec + (double)ts.tv_nsec / GPR_NS_PER_MS + (double)(GPR_NS_PER_SEC - 1) / (double)GPR_NS_PER_SEC; if (x < 0) return 0; if (x > GPR_ATM_MAX) return GPR_ATM_MAX; return (gpr_atm)x; } static gpr_atm timespec_to_atm_round_down(gpr_timespec ts) { ts = gpr_time_sub(ts, g_start_time); double x = GPR_MS_PER_SEC * (double)ts.tv_sec + (double)ts.tv_nsec / GPR_NS_PER_MS; if (x < 0) return 0; if (x > GPR_ATM_MAX) return GPR_ATM_MAX; return (gpr_atm)x; } static gpr_timespec atm_to_timespec(gpr_atm x) { return gpr_time_add(g_start_time, dbl_to_ts((double)x / 1000.0)); } static gpr_atm compute_min_deadline(shard_type *shard) { return grpc_timer_heap_is_empty(&shard->heap) ? saturating_add(shard->queue_deadline_cap, 1) : grpc_timer_heap_top(&shard->heap)->deadline; } void grpc_timer_list_init(gpr_timespec now) { uint32_t i; g_shared_mutables.initialized = true; gpr_mu_init(&g_shared_mutables.mu); g_clock_type = now.clock_type; g_start_time = now; g_shared_mutables.min_timer = timespec_to_atm_round_down(now); gpr_tls_init(&g_last_seen_min_timer); gpr_tls_set(&g_last_seen_min_timer, 0); grpc_register_tracer("timer", &grpc_timer_trace); grpc_register_tracer("timer_check", &grpc_timer_check_trace); for (i = 0; i < NUM_SHARDS; i++) { shard_type *shard = &g_shards[i]; gpr_mu_init(&shard->mu); grpc_time_averaged_stats_init(&shard->stats, 1.0 / ADD_DEADLINE_SCALE, 0.1, 0.5); shard->queue_deadline_cap = g_shared_mutables.min_timer; shard->shard_queue_index = i; grpc_timer_heap_init(&shard->heap); shard->list.next = shard->list.prev = &shard->list; shard->min_deadline = compute_min_deadline(shard); g_shard_queue[i] = shard; } } void grpc_timer_list_shutdown(grpc_exec_ctx *exec_ctx) { int i; run_some_expired_timers( exec_ctx, GPR_ATM_MAX, NULL, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Timer list shutdown")); for (i = 0; i < NUM_SHARDS; i++) { shard_type *shard = &g_shards[i]; gpr_mu_destroy(&shard->mu); grpc_timer_heap_destroy(&shard->heap); } gpr_mu_destroy(&g_shared_mutables.mu); gpr_tls_destroy(&g_last_seen_min_timer); g_shared_mutables.initialized = false; } static double ts_to_dbl(gpr_timespec ts) { return (double)ts.tv_sec + 1e-9 * ts.tv_nsec; } /* returns true if the first element in the list */ static void list_join(grpc_timer *head, grpc_timer *timer) { timer->next = head; timer->prev = head->prev; timer->next->prev = timer->prev->next = timer; } static void list_remove(grpc_timer *timer) { timer->next->prev = timer->prev; timer->prev->next = timer->next; } static void swap_adjacent_shards_in_queue(uint32_t first_shard_queue_index) { shard_type *temp; temp = g_shard_queue[first_shard_queue_index]; g_shard_queue[first_shard_queue_index] = g_shard_queue[first_shard_queue_index + 1]; g_shard_queue[first_shard_queue_index + 1] = temp; g_shard_queue[first_shard_queue_index]->shard_queue_index = first_shard_queue_index; g_shard_queue[first_shard_queue_index + 1]->shard_queue_index = first_shard_queue_index + 1; } static void note_deadline_change(shard_type *shard) { while (shard->shard_queue_index > 0 && shard->min_deadline < g_shard_queue[shard->shard_queue_index - 1]->min_deadline) { swap_adjacent_shards_in_queue(shard->shard_queue_index - 1); } while (shard->shard_queue_index < NUM_SHARDS - 1 && shard->min_deadline > g_shard_queue[shard->shard_queue_index + 1]->min_deadline) { swap_adjacent_shards_in_queue(shard->shard_queue_index); } } void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer, gpr_timespec deadline, grpc_closure *closure, gpr_timespec now) { int is_first_timer = 0; shard_type *shard = &g_shards[GPR_HASH_POINTER(timer, NUM_SHARDS)]; GPR_ASSERT(deadline.clock_type == g_clock_type); GPR_ASSERT(now.clock_type == g_clock_type); timer->closure = closure; timer->deadline = timespec_to_atm_round_up(deadline); if (grpc_timer_trace) { gpr_log(GPR_DEBUG, "TIMER %p: SET %" PRId64 ".%09d [%" PRIdPTR "] now %" PRId64 ".%09d [%" PRIdPTR "] call %p[%p]", timer, deadline.tv_sec, deadline.tv_nsec, timer->deadline, now.tv_sec, now.tv_nsec, timespec_to_atm_round_down(now), closure, closure->cb); } if (!g_shared_mutables.initialized) { timer->pending = false; grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Attempt to create timer before initialization")); return; } gpr_mu_lock(&shard->mu); timer->pending = true; if (gpr_time_cmp(deadline, now) <= 0) { timer->pending = false; grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_NONE); gpr_mu_unlock(&shard->mu); /* early out */ return; } grpc_time_averaged_stats_add_sample(&shard->stats, ts_to_dbl(gpr_time_sub(deadline, now))); if (timer->deadline < shard->queue_deadline_cap) { is_first_timer = grpc_timer_heap_add(&shard->heap, timer); } else { timer->heap_index = INVALID_HEAP_INDEX; list_join(&shard->list, timer); } if (grpc_timer_trace) { gpr_log(GPR_DEBUG, " .. add to shard %d with queue_deadline_cap=%" PRIdPTR " => is_first_timer=%s", (int)(shard - g_shards), shard->queue_deadline_cap, is_first_timer ? "true" : "false"); } gpr_mu_unlock(&shard->mu); /* Deadline may have decreased, we need to adjust the master queue. Note that there is a potential racy unlocked region here. There could be a reordering of multiple grpc_timer_init calls, at this point, but the < test below should ensure that we err on the side of caution. There could also be a race with grpc_timer_check, which might beat us to the lock. In that case, it is possible that the timer that we added will have already run by the time we hold the lock, but that too is a safe error. Finally, it's possible that the grpc_timer_check that intervened failed to trigger the new timer because the min_deadline hadn't yet been reduced. In that case, the timer will simply have to wait for the next grpc_timer_check. */ if (is_first_timer) { gpr_mu_lock(&g_shared_mutables.mu); if (grpc_timer_trace) { gpr_log(GPR_DEBUG, " .. old shard min_deadline=%" PRIdPTR, shard->min_deadline); } if (timer->deadline < shard->min_deadline) { gpr_atm old_min_deadline = g_shard_queue[0]->min_deadline; shard->min_deadline = timer->deadline; note_deadline_change(shard); if (shard->shard_queue_index == 0 && timer->deadline < old_min_deadline) { gpr_atm_no_barrier_store(&g_shared_mutables.min_timer, timer->deadline); grpc_kick_poller(); } } gpr_mu_unlock(&g_shared_mutables.mu); } } void grpc_timer_consume_kick(void) { /* force re-evaluation of last seeen min */ gpr_tls_set(&g_last_seen_min_timer, 0); } void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) { if (!g_shared_mutables.initialized) { /* must have already been cancelled, also the shard mutex is invalid */ return; } shard_type *shard = &g_shards[GPR_HASH_POINTER(timer, NUM_SHARDS)]; gpr_mu_lock(&shard->mu); if (grpc_timer_trace) { gpr_log(GPR_DEBUG, "TIMER %p: CANCEL pending=%s", timer, timer->pending ? "true" : "false"); } if (timer->pending) { grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_CANCELLED); timer->pending = false; if (timer->heap_index == INVALID_HEAP_INDEX) { list_remove(timer); } else { grpc_timer_heap_remove(&shard->heap, timer); } } gpr_mu_unlock(&shard->mu); } /* This is called when the queue is empty and "now" has reached the queue_deadline_cap. We compute a new queue deadline and then scan the map for timers that fall at or under it. Returns true if the queue is no longer empty. REQUIRES: shard->mu locked */ static int refill_queue(shard_type *shard, gpr_atm now) { /* Compute the new queue window width and bound by the limits: */ double computed_deadline_delta = grpc_time_averaged_stats_update_average(&shard->stats) * ADD_DEADLINE_SCALE; double deadline_delta = GPR_CLAMP(computed_deadline_delta, MIN_QUEUE_WINDOW_DURATION, MAX_QUEUE_WINDOW_DURATION); grpc_timer *timer, *next; /* Compute the new cap and put all timers under it into the queue: */ shard->queue_deadline_cap = saturating_add(GPR_MAX(now, shard->queue_deadline_cap), (gpr_atm)(deadline_delta * 1000.0)); if (grpc_timer_check_trace) { gpr_log(GPR_DEBUG, " .. shard[%d]->queue_deadline_cap --> %" PRIdPTR, (int)(shard - g_shards), shard->queue_deadline_cap); } for (timer = shard->list.next; timer != &shard->list; timer = next) { next = timer->next; if (timer->deadline < shard->queue_deadline_cap) { if (grpc_timer_check_trace) { gpr_log(GPR_DEBUG, " .. add timer with deadline %" PRIdPTR " to heap", timer->deadline); } list_remove(timer); grpc_timer_heap_add(&shard->heap, timer); } } return !grpc_timer_heap_is_empty(&shard->heap); } /* This pops the next non-cancelled timer with deadline <= now from the queue, or returns NULL if there isn't one. REQUIRES: shard->mu locked */ static grpc_timer *pop_one(shard_type *shard, gpr_atm now) { grpc_timer *timer; for (;;) { if (grpc_timer_check_trace) { gpr_log(GPR_DEBUG, " .. shard[%d]: heap_empty=%s", (int)(shard - g_shards), grpc_timer_heap_is_empty(&shard->heap) ? "true" : "false"); } if (grpc_timer_heap_is_empty(&shard->heap)) { if (now < shard->queue_deadline_cap) return NULL; if (!refill_queue(shard, now)) return NULL; } timer = grpc_timer_heap_top(&shard->heap); if (grpc_timer_check_trace) { gpr_log(GPR_DEBUG, " .. check top timer deadline=%" PRIdPTR " now=%" PRIdPTR, timer->deadline, now); } if (timer->deadline > now) return NULL; if (grpc_timer_trace) { gpr_log(GPR_DEBUG, "TIMER %p: FIRE %" PRIdPTR "ms late", timer, now - timer->deadline); } timer->pending = false; grpc_timer_heap_pop(&shard->heap); return timer; } } /* REQUIRES: shard->mu unlocked */ static size_t pop_timers(grpc_exec_ctx *exec_ctx, shard_type *shard, gpr_atm now, gpr_atm *new_min_deadline, grpc_error *error) { size_t n = 0; grpc_timer *timer; gpr_mu_lock(&shard->mu); while ((timer = pop_one(shard, now))) { grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_REF(error)); n++; } *new_min_deadline = compute_min_deadline(shard); gpr_mu_unlock(&shard->mu); return n; } static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_atm now, gpr_atm *next, grpc_error *error) { size_t n = 0; gpr_atm min_timer = gpr_atm_no_barrier_load(&g_shared_mutables.min_timer); gpr_tls_set(&g_last_seen_min_timer, min_timer); if (now < min_timer) { if (next != NULL) *next = GPR_MIN(*next, min_timer); return 0; } if (gpr_spinlock_trylock(&g_shared_mutables.checker_mu)) { gpr_mu_lock(&g_shared_mutables.mu); if (grpc_timer_check_trace) { gpr_log(GPR_DEBUG, " .. shard[%d]->min_deadline = %" PRIdPTR, (int)(g_shard_queue[0] - g_shards), g_shard_queue[0]->min_deadline); } while (g_shard_queue[0]->min_deadline < now || (now != GPR_ATM_MAX && g_shard_queue[0]->min_deadline == now)) { gpr_atm new_min_deadline; /* For efficiency, we pop as many available timers as we can from the shard. This may violate perfect timer deadline ordering, but that shouldn't be a big deal because we don't make ordering guarantees. */ n += pop_timers(exec_ctx, g_shard_queue[0], now, &new_min_deadline, error); if (grpc_timer_check_trace) { gpr_log(GPR_DEBUG, " .. popped --> %" PRIdPTR ", shard[%d]->min_deadline %" PRIdPTR " --> %" PRIdPTR ", now=%" PRIdPTR, n, (int)(g_shard_queue[0] - g_shards), g_shard_queue[0]->min_deadline, new_min_deadline, now); } /* An grpc_timer_init() on the shard could intervene here, adding a new timer that is earlier than new_min_deadline. However, grpc_timer_init() will block on the master_lock before it can call set_min_deadline, so this one will complete first and then the Addtimer will reduce the min_deadline (perhaps unnecessarily). */ g_shard_queue[0]->min_deadline = new_min_deadline; note_deadline_change(g_shard_queue[0]); } if (next) { *next = GPR_MIN(*next, g_shard_queue[0]->min_deadline); } gpr_atm_no_barrier_store(&g_shared_mutables.min_timer, g_shard_queue[0]->min_deadline); gpr_mu_unlock(&g_shared_mutables.mu); gpr_spinlock_unlock(&g_shared_mutables.checker_mu); } else if (next != NULL) { /* TODO(ctiller): this forces calling code to do an short poll, and then retry the timer check (because this time through the timer list was contended). We could reduce the cost here dramatically by keeping a count of how many currently active pollers got through the uncontended case above successfully, and waking up other pollers IFF that count drops to zero. Once that count is in place, this entire else branch could disappear. */ *next = GPR_MIN(*next, now + 1); } GRPC_ERROR_UNREF(error); return (int)n; } bool grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now, gpr_timespec *next) { // prelude GPR_ASSERT(now.clock_type == g_clock_type); gpr_atm now_atm = timespec_to_atm_round_down(now); /* fetch from a thread-local first: this avoids contention on a globally mutable cacheline in the common case */ gpr_atm min_timer = gpr_tls_get(&g_last_seen_min_timer); if (now_atm < min_timer) { if (next != NULL) { *next = atm_to_timespec(GPR_MIN(timespec_to_atm_round_up(*next), min_timer)); } if (grpc_timer_check_trace) { gpr_log(GPR_DEBUG, "TIMER CHECK SKIP: now_atm=%" PRIdPTR " min_timer=%" PRIdPTR, now_atm, min_timer); } return 0; } grpc_error *shutdown_error = gpr_time_cmp(now, gpr_inf_future(now.clock_type)) != 0 ? GRPC_ERROR_NONE : GRPC_ERROR_CREATE_FROM_STATIC_STRING("Shutting down timer system"); // tracing if (grpc_timer_check_trace) { char *next_str; if (next == NULL) { next_str = gpr_strdup("NULL"); } else { gpr_asprintf(&next_str, "%" PRId64 ".%09d [%" PRIdPTR "]", next->tv_sec, next->tv_nsec, timespec_to_atm_round_down(*next)); } gpr_log(GPR_DEBUG, "TIMER CHECK BEGIN: now=%" PRId64 ".%09d [%" PRIdPTR "] next=%s tls_min=%" PRIdPTR " glob_min=%" PRIdPTR, now.tv_sec, now.tv_nsec, now_atm, next_str, gpr_tls_get(&g_last_seen_min_timer), gpr_atm_no_barrier_load(&g_shared_mutables.min_timer)); gpr_free(next_str); } // actual code bool r; gpr_atm next_atm; if (next == NULL) { r = run_some_expired_timers(exec_ctx, now_atm, NULL, shutdown_error); } else { next_atm = timespec_to_atm_round_down(*next); r = run_some_expired_timers(exec_ctx, now_atm, &next_atm, shutdown_error); *next = atm_to_timespec(next_atm); } // tracing if (grpc_timer_check_trace) { char *next_str; if (next == NULL) { next_str = gpr_strdup("NULL"); } else { gpr_asprintf(&next_str, "%" PRId64 ".%09d [%" PRIdPTR "]", next->tv_sec, next->tv_nsec, next_atm); } gpr_log(GPR_DEBUG, "TIMER CHECK END: %d timers triggered; next=%s", r, next_str); gpr_free(next_str); } return r > 0; } #endif /* GRPC_TIMER_USE_GENERIC */ grpc-1.3.2/src/core/lib/iomgr/timer_generic.h000066400000000000000000000036771310511640000210430ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_TIMER_GENERIC_H #define GRPC_CORE_LIB_IOMGR_TIMER_GENERIC_H #include #include "src/core/lib/iomgr/exec_ctx.h" struct grpc_timer { gpr_atm deadline; uint32_t heap_index; /* INVALID_HEAP_INDEX if not in heap */ bool pending; struct grpc_timer *next; struct grpc_timer *prev; grpc_closure *closure; }; #endif /* GRPC_CORE_LIB_IOMGR_TIMER_GENERIC_H */ grpc-1.3.2/src/core/lib/iomgr/timer_heap.c000066400000000000000000000123121310511640000203210ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_TIMER_USE_GENERIC #include "src/core/lib/iomgr/timer_heap.h" #include #include #include /* Adjusts a heap so as to move a hole at position i closer to the root, until a suitable position is found for element t. Then, copies t into that position. This functor is called each time immediately after modifying a value in the underlying container, with the offset of the modified element as its argument. */ static void adjust_upwards(grpc_timer **first, uint32_t i, grpc_timer *t) { while (i > 0) { uint32_t parent = (uint32_t)(((int)i - 1) / 2); if (first[parent]->deadline <= t->deadline) break; first[i] = first[parent]; first[i]->heap_index = i; i = parent; } first[i] = t; t->heap_index = i; } /* Adjusts a heap so as to move a hole at position i farther away from the root, until a suitable position is found for element t. Then, copies t into that position. */ static void adjust_downwards(grpc_timer **first, uint32_t i, uint32_t length, grpc_timer *t) { for (;;) { uint32_t left_child = 1u + 2u * i; if (left_child >= length) break; uint32_t right_child = left_child + 1; uint32_t next_i = right_child < length && first[left_child]->deadline > first[right_child]->deadline ? right_child : left_child; if (t->deadline <= first[next_i]->deadline) break; first[i] = first[next_i]; first[i]->heap_index = i; i = next_i; } first[i] = t; t->heap_index = i; } #define SHRINK_MIN_ELEMS 8 #define SHRINK_FULLNESS_FACTOR 2 static void maybe_shrink(grpc_timer_heap *heap) { if (heap->timer_count >= 8 && heap->timer_count <= heap->timer_capacity / SHRINK_FULLNESS_FACTOR / 2) { heap->timer_capacity = heap->timer_count * SHRINK_FULLNESS_FACTOR; heap->timers = gpr_realloc(heap->timers, heap->timer_capacity * sizeof(grpc_timer *)); } } static void note_changed_priority(grpc_timer_heap *heap, grpc_timer *timer) { uint32_t i = timer->heap_index; uint32_t parent = (uint32_t)(((int)i - 1) / 2); if (heap->timers[parent]->deadline > timer->deadline) { adjust_upwards(heap->timers, i, timer); } else { adjust_downwards(heap->timers, i, heap->timer_count, timer); } } void grpc_timer_heap_init(grpc_timer_heap *heap) { memset(heap, 0, sizeof(*heap)); } void grpc_timer_heap_destroy(grpc_timer_heap *heap) { gpr_free(heap->timers); } int grpc_timer_heap_add(grpc_timer_heap *heap, grpc_timer *timer) { if (heap->timer_count == heap->timer_capacity) { heap->timer_capacity = GPR_MAX(heap->timer_capacity + 1, heap->timer_capacity * 3 / 2); heap->timers = gpr_realloc(heap->timers, heap->timer_capacity * sizeof(grpc_timer *)); } timer->heap_index = heap->timer_count; adjust_upwards(heap->timers, heap->timer_count, timer); heap->timer_count++; return timer->heap_index == 0; } void grpc_timer_heap_remove(grpc_timer_heap *heap, grpc_timer *timer) { uint32_t i = timer->heap_index; if (i == heap->timer_count - 1) { heap->timer_count--; maybe_shrink(heap); return; } heap->timers[i] = heap->timers[heap->timer_count - 1]; heap->timers[i]->heap_index = i; heap->timer_count--; maybe_shrink(heap); note_changed_priority(heap, heap->timers[i]); } int grpc_timer_heap_is_empty(grpc_timer_heap *heap) { return heap->timer_count == 0; } grpc_timer *grpc_timer_heap_top(grpc_timer_heap *heap) { return heap->timers[0]; } void grpc_timer_heap_pop(grpc_timer_heap *heap) { grpc_timer_heap_remove(heap, grpc_timer_heap_top(heap)); } #endif /* GRPC_TIMER_USE_GENERIC */ grpc-1.3.2/src/core/lib/iomgr/timer_heap.h000066400000000000000000000044131310511640000203310ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_TIMER_HEAP_H #define GRPC_CORE_LIB_IOMGR_TIMER_HEAP_H #include "src/core/lib/iomgr/timer.h" typedef struct { grpc_timer **timers; uint32_t timer_count; uint32_t timer_capacity; } grpc_timer_heap; /* return 1 if the new timer is the first timer in the heap */ int grpc_timer_heap_add(grpc_timer_heap *heap, grpc_timer *timer); void grpc_timer_heap_init(grpc_timer_heap *heap); void grpc_timer_heap_destroy(grpc_timer_heap *heap); void grpc_timer_heap_remove(grpc_timer_heap *heap, grpc_timer *timer); grpc_timer *grpc_timer_heap_top(grpc_timer_heap *heap); void grpc_timer_heap_pop(grpc_timer_heap *heap); int grpc_timer_heap_is_empty(grpc_timer_heap *heap); #endif /* GRPC_CORE_LIB_IOMGR_TIMER_HEAP_H */ grpc-1.3.2/src/core/lib/iomgr/timer_uv.c000066400000000000000000000072411310511640000200430ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #if GRPC_UV #include #include #include "src/core/lib/iomgr/timer.h" #include static void timer_close_callback(uv_handle_t *handle) { gpr_free(handle); } static void stop_uv_timer(uv_timer_t *handle) { uv_timer_stop(handle); uv_unref((uv_handle_t *)handle); uv_close((uv_handle_t *)handle, timer_close_callback); } void run_expired_timer(uv_timer_t *handle) { grpc_timer *timer = (grpc_timer *)handle->data; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GPR_ASSERT(timer->pending); timer->pending = 0; grpc_closure_sched(&exec_ctx, timer->closure, GRPC_ERROR_NONE); stop_uv_timer(handle); grpc_exec_ctx_finish(&exec_ctx); } void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer, gpr_timespec deadline, grpc_closure *closure, gpr_timespec now) { uint64_t timeout; uv_timer_t *uv_timer; timer->closure = closure; if (gpr_time_cmp(deadline, now) <= 0) { timer->pending = 0; grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_NONE); return; } timer->pending = 1; timeout = (uint64_t)gpr_time_to_millis(gpr_time_sub(deadline, now)); uv_timer = gpr_malloc(sizeof(uv_timer_t)); uv_timer_init(uv_default_loop(), uv_timer); uv_timer->data = timer; timer->uv_timer = uv_timer; uv_timer_start(uv_timer, run_expired_timer, timeout, 0); /* We assume that gRPC timers are only used alongside other active gRPC objects, and that there will therefore always be something else keeping the uv loop alive whenever there is a timer */ uv_unref((uv_handle_t *)uv_timer); } void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) { if (timer->pending) { timer->pending = 0; grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_CANCELLED); stop_uv_timer((uv_timer_t *)timer->uv_timer); } } bool grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now, gpr_timespec *next) { return false; } void grpc_timer_list_init(gpr_timespec now) {} void grpc_timer_list_shutdown(grpc_exec_ctx *exec_ctx) {} #endif /* GRPC_UV */ grpc-1.3.2/src/core/lib/iomgr/timer_uv.h000066400000000000000000000036011310511640000200440ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_TIMER_UV_H #define GRPC_CORE_LIB_IOMGR_TIMER_UV_H #include "src/core/lib/iomgr/exec_ctx.h" struct grpc_timer { grpc_closure *closure; /* This is actually a uv_timer_t*, but we want to keep platform-specific types out of headers */ void *uv_timer; int pending; }; #endif /* GRPC_CORE_LIB_IOMGR_TIMER_UV_H */ grpc-1.3.2/src/core/lib/iomgr/udp_server.c000066400000000000000000000401661310511640000203720ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* FIXME: "posix" files shouldn't be depending on _GNU_SOURCE */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include "src/core/lib/iomgr/port.h" #ifdef GRPC_POSIX_SOCKET #include "src/core/lib/iomgr/udp_server.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/socket_factory_posix.h" #include "src/core/lib/iomgr/socket_utils_posix.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" #include "src/core/lib/support/string.h" /* one listening port */ typedef struct grpc_udp_listener grpc_udp_listener; struct grpc_udp_listener { int fd; grpc_fd *emfd; grpc_udp_server *server; grpc_resolved_address addr; grpc_closure read_closure; grpc_closure write_closure; grpc_closure destroyed_closure; grpc_udp_server_read_cb read_cb; grpc_udp_server_write_cb write_cb; grpc_udp_server_orphan_cb orphan_cb; struct grpc_udp_listener *next; }; /* the overall server */ struct grpc_udp_server { gpr_mu mu; /* factory to use for creating and binding sockets, or NULL */ grpc_socket_factory *socket_factory; /* active port count: how many ports are actually still listening */ size_t active_ports; /* destroyed port count: how many ports are completely destroyed */ size_t destroyed_ports; /* is this server shutting down? (boolean) */ int shutdown; /* linked list of server ports */ grpc_udp_listener *head; grpc_udp_listener *tail; unsigned nports; /* shutdown callback */ grpc_closure *shutdown_complete; /* all pollsets interested in new connections */ grpc_pollset **pollsets; /* number of pollsets in the pollsets array */ size_t pollset_count; /* opaque object to pass to callbacks */ void *user_data; }; static grpc_socket_factory *get_socket_factory(const grpc_channel_args *args) { if (args) { const grpc_arg *arg = grpc_channel_args_find(args, GRPC_ARG_SOCKET_FACTORY); if (arg) { GPR_ASSERT(arg->type == GRPC_ARG_POINTER); return arg->value.pointer.p; } } return NULL; } grpc_udp_server *grpc_udp_server_create(const grpc_channel_args *args) { grpc_udp_server *s = gpr_malloc(sizeof(grpc_udp_server)); gpr_mu_init(&s->mu); s->socket_factory = get_socket_factory(args); if (s->socket_factory) { grpc_socket_factory_ref(s->socket_factory); } s->active_ports = 0; s->destroyed_ports = 0; s->shutdown = 0; s->head = NULL; s->tail = NULL; s->nports = 0; return s; } static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) { if (s->shutdown_complete != NULL) { grpc_closure_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE); } gpr_mu_destroy(&s->mu); while (s->head) { grpc_udp_listener *sp = s->head; s->head = sp->next; gpr_free(sp); } if (s->socket_factory) { grpc_socket_factory_unref(s->socket_factory); } gpr_free(s); } static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server, grpc_error *error) { grpc_udp_server *s = server; gpr_mu_lock(&s->mu); s->destroyed_ports++; if (s->destroyed_ports == s->nports) { gpr_mu_unlock(&s->mu); finish_shutdown(exec_ctx, s); } else { gpr_mu_unlock(&s->mu); } } /* called when all listening endpoints have been shutdown, so no further events will be received on them - at this point it's safe to destroy things */ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) { /* delete ALL the things */ gpr_mu_lock(&s->mu); GPR_ASSERT(s->shutdown); if (s->head) { grpc_udp_listener *sp; for (sp = s->head; sp; sp = sp->next) { grpc_unlink_if_unix_domain_socket(&sp->addr); grpc_closure_init(&sp->destroyed_closure, destroyed_port, s, grpc_schedule_on_exec_ctx); /* Call the orphan_cb to signal that the FD is about to be closed and * should no longer be used. */ GPR_ASSERT(sp->orphan_cb); sp->orphan_cb(exec_ctx, sp->emfd, sp->server->user_data); grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL, "udp_listener_shutdown"); } gpr_mu_unlock(&s->mu); } else { gpr_mu_unlock(&s->mu); finish_shutdown(exec_ctx, s); } } void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *s, grpc_closure *on_done) { grpc_udp_listener *sp; gpr_mu_lock(&s->mu); GPR_ASSERT(!s->shutdown); s->shutdown = 1; s->shutdown_complete = on_done; /* shutdown all fd's */ if (s->active_ports) { for (sp = s->head; sp; sp = sp->next) { GPR_ASSERT(sp->orphan_cb); sp->orphan_cb(exec_ctx, sp->emfd, sp->server->user_data); grpc_fd_shutdown(exec_ctx, sp->emfd, GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Server destroyed")); } gpr_mu_unlock(&s->mu); } else { gpr_mu_unlock(&s->mu); deactivated_all_ports(exec_ctx, s); } } static int bind_socket(grpc_socket_factory *socket_factory, int sockfd, const grpc_resolved_address *addr) { return (socket_factory != NULL) ? grpc_socket_factory_bind(socket_factory, sockfd, addr) : bind(sockfd, (struct sockaddr *)addr->addr, (socklen_t)addr->len); } /* Prepare a recently-created socket for listening. */ static int prepare_socket(grpc_socket_factory *socket_factory, int fd, const grpc_resolved_address *addr) { grpc_resolved_address sockname_temp; struct sockaddr *addr_ptr = (struct sockaddr *)addr->addr; /* Set send/receive socket buffers to 1 MB */ int buffer_size_bytes = 1024 * 1024; if (fd < 0) { goto error; } if (grpc_set_socket_nonblocking(fd, 1) != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Unable to set nonblocking %d: %s", fd, strerror(errno)); goto error; } if (grpc_set_socket_cloexec(fd, 1) != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Unable to set cloexec %d: %s", fd, strerror(errno)); goto error; } if (grpc_set_socket_ip_pktinfo_if_possible(fd) != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Unable to set ip_pktinfo."); goto error; } else if (addr_ptr->sa_family == AF_INET6) { if (grpc_set_socket_ipv6_recvpktinfo_if_possible(fd) != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Unable to set ipv6_recvpktinfo."); goto error; } } GPR_ASSERT(addr->len < ~(socklen_t)0); if (bind_socket(socket_factory, fd, addr) < 0) { char *addr_str; grpc_sockaddr_to_string(&addr_str, addr, 0); gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, strerror(errno)); gpr_free(addr_str); goto error; } sockname_temp.len = sizeof(struct sockaddr_storage); if (getsockname(fd, (struct sockaddr *)sockname_temp.addr, (socklen_t *)&sockname_temp.len) < 0) { goto error; } if (grpc_set_socket_sndbuf(fd, buffer_size_bytes) != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Failed to set send buffer size to %d bytes", buffer_size_bytes); goto error; } if (grpc_set_socket_rcvbuf(fd, buffer_size_bytes) != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Failed to set receive buffer size to %d bytes", buffer_size_bytes); goto error; } return grpc_sockaddr_get_port(&sockname_temp); error: if (fd >= 0) { close(fd); } return -1; } /* event manager callback when reads are ready */ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_udp_listener *sp = arg; gpr_mu_lock(&sp->server->mu); if (error != GRPC_ERROR_NONE) { if (0 == --sp->server->active_ports && sp->server->shutdown) { gpr_mu_unlock(&sp->server->mu); deactivated_all_ports(exec_ctx, sp->server); } else { gpr_mu_unlock(&sp->server->mu); } return; } /* Tell the registered callback that data is available to read. */ GPR_ASSERT(sp->read_cb); sp->read_cb(exec_ctx, sp->emfd, sp->server->user_data); /* Re-arm the notification event so we get another chance to read. */ grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure); gpr_mu_unlock(&sp->server->mu); } static void on_write(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_udp_listener *sp = arg; gpr_mu_lock(&(sp->server->mu)); if (error != GRPC_ERROR_NONE) { if (0 == --sp->server->active_ports && sp->server->shutdown) { gpr_mu_unlock(&sp->server->mu); deactivated_all_ports(exec_ctx, sp->server); } else { gpr_mu_unlock(&sp->server->mu); } return; } /* Tell the registered callback that the socket is writeable. */ GPR_ASSERT(sp->write_cb); sp->write_cb(exec_ctx, sp->emfd, sp->server->user_data); /* Re-arm the notification event so we get another chance to write. */ grpc_fd_notify_on_write(exec_ctx, sp->emfd, &sp->write_closure); gpr_mu_unlock(&sp->server->mu); } static int add_socket_to_server(grpc_udp_server *s, int fd, const grpc_resolved_address *addr, grpc_udp_server_read_cb read_cb, grpc_udp_server_write_cb write_cb, grpc_udp_server_orphan_cb orphan_cb) { grpc_udp_listener *sp; int port; char *addr_str; char *name; port = prepare_socket(s->socket_factory, fd, addr); if (port >= 0) { grpc_sockaddr_to_string(&addr_str, addr, 1); gpr_asprintf(&name, "udp-server-listener:%s", addr_str); gpr_free(addr_str); gpr_mu_lock(&s->mu); s->nports++; sp = gpr_malloc(sizeof(grpc_udp_listener)); sp->next = NULL; if (s->head == NULL) { s->head = sp; } else { s->tail->next = sp; } s->tail = sp; sp->server = s; sp->fd = fd; sp->emfd = grpc_fd_create(fd, name); memcpy(&sp->addr, addr, sizeof(grpc_resolved_address)); sp->read_cb = read_cb; sp->write_cb = write_cb; sp->orphan_cb = orphan_cb; GPR_ASSERT(sp->emfd); gpr_mu_unlock(&s->mu); gpr_free(name); } return port; } int grpc_udp_server_add_port(grpc_udp_server *s, const grpc_resolved_address *addr, grpc_udp_server_read_cb read_cb, grpc_udp_server_write_cb write_cb, grpc_udp_server_orphan_cb orphan_cb) { grpc_udp_listener *sp; int allocated_port1 = -1; int allocated_port2 = -1; int fd; grpc_dualstack_mode dsmode; grpc_resolved_address addr6_v4mapped; grpc_resolved_address wild4; grpc_resolved_address wild6; grpc_resolved_address addr4_copy; grpc_resolved_address *allocated_addr = NULL; grpc_resolved_address sockname_temp; int port; /* Check if this is a wildcard port, and if so, try to keep the port the same as some previously created listener. */ if (grpc_sockaddr_get_port(addr) == 0) { for (sp = s->head; sp; sp = sp->next) { sockname_temp.len = sizeof(struct sockaddr_storage); if (0 == getsockname(sp->fd, (struct sockaddr *)sockname_temp.addr, (socklen_t *)&sockname_temp.len)) { port = grpc_sockaddr_get_port(&sockname_temp); if (port > 0) { allocated_addr = gpr_malloc(sizeof(grpc_resolved_address)); memcpy(allocated_addr, addr, sizeof(grpc_resolved_address)); grpc_sockaddr_set_port(allocated_addr, port); addr = allocated_addr; break; } } } } if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) { addr = &addr6_v4mapped; } /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */ if (grpc_sockaddr_is_wildcard(addr, &port)) { grpc_sockaddr_make_wildcards(port, &wild4, &wild6); /* Try listening on IPv6 first. */ addr = &wild6; // TODO(rjshade): Test and propagate the returned grpc_error*: GRPC_ERROR_UNREF(grpc_create_dualstack_socket_using_factory( s->socket_factory, addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd)); allocated_port1 = add_socket_to_server(s, fd, addr, read_cb, write_cb, orphan_cb); if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) { goto done; } /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */ if (port == 0 && allocated_port1 > 0) { grpc_sockaddr_set_port(&wild4, allocated_port1); } addr = &wild4; } // TODO(rjshade): Test and propagate the returned grpc_error*: GRPC_ERROR_UNREF(grpc_create_dualstack_socket_using_factory( s->socket_factory, addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd)); if (fd < 0) { gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno)); } if (dsmode == GRPC_DSMODE_IPV4 && grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) { addr = &addr4_copy; } allocated_port2 = add_socket_to_server(s, fd, addr, read_cb, write_cb, orphan_cb); done: gpr_free(allocated_addr); return allocated_port1 >= 0 ? allocated_port1 : allocated_port2; } int grpc_udp_server_get_fd(grpc_udp_server *s, unsigned port_index) { grpc_udp_listener *sp; if (port_index >= s->nports) { return -1; } for (sp = s->head; sp && port_index != 0; sp = sp->next) { --port_index; } return sp->fd; } void grpc_udp_server_start(grpc_exec_ctx *exec_ctx, grpc_udp_server *s, grpc_pollset **pollsets, size_t pollset_count, void *user_data) { size_t i; gpr_mu_lock(&s->mu); grpc_udp_listener *sp; GPR_ASSERT(s->active_ports == 0); s->pollsets = pollsets; s->user_data = user_data; sp = s->head; while (sp != NULL) { for (i = 0; i < pollset_count; i++) { grpc_pollset_add_fd(exec_ctx, pollsets[i], sp->emfd); } grpc_closure_init(&sp->read_closure, on_read, sp, grpc_schedule_on_exec_ctx); grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure); grpc_closure_init(&sp->write_closure, on_write, sp, grpc_schedule_on_exec_ctx); grpc_fd_notify_on_write(exec_ctx, sp->emfd, &sp->write_closure); /* Registered for both read and write callbacks: increment active_ports * twice to account for this, and delay free-ing of memory until both * on_read and on_write have fired. */ s->active_ports += 2; sp = sp->next; } gpr_mu_unlock(&s->mu); } #endif grpc-1.3.2/src/core/lib/iomgr/udp_server.h000066400000000000000000000077501310511640000204010ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_UDP_SERVER_H #define GRPC_CORE_LIB_IOMGR_UDP_SERVER_H #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/resolve_address.h" /* Forward decl of struct grpc_server */ /* This is not typedef'ed to avoid a typedef-redefinition error */ struct grpc_server; /* Forward decl of grpc_udp_server */ typedef struct grpc_udp_server grpc_udp_server; /* Called when data is available to read from the socket. */ typedef void (*grpc_udp_server_read_cb)(grpc_exec_ctx *exec_ctx, grpc_fd *emfd, void *user_data); /* Called when the socket is writeable. */ typedef void (*grpc_udp_server_write_cb)(grpc_exec_ctx *exec_ctx, grpc_fd *emfd, void *user_data); /* Called when the grpc_fd is about to be orphaned (and the FD closed). */ typedef void (*grpc_udp_server_orphan_cb)(grpc_exec_ctx *exec_ctx, grpc_fd *emfd, void *user_data); /* Create a server, initially not bound to any ports */ grpc_udp_server *grpc_udp_server_create(const grpc_channel_args *args); /* Start listening to bound ports. user_data is passed to callbacks. */ void grpc_udp_server_start(grpc_exec_ctx *exec_ctx, grpc_udp_server *udp_server, grpc_pollset **pollsets, size_t pollset_count, void *user_data); int grpc_udp_server_get_fd(grpc_udp_server *s, unsigned port_index); /* Add a port to the server, returning port number on success, or negative on failure. The :: and 0.0.0.0 wildcard addresses are treated identically, accepting both IPv4 and IPv6 connections, but :: is the preferred style. This usually creates one socket, but possibly two on systems which support IPv6, but not dualstack sockets. */ /* TODO(ctiller): deprecate this, and make grpc_udp_server_add_ports to handle all of the multiple socket port matching logic in one place */ int grpc_udp_server_add_port(grpc_udp_server *s, const grpc_resolved_address *addr, grpc_udp_server_read_cb read_cb, grpc_udp_server_write_cb write_cb, grpc_udp_server_orphan_cb orphan_cb); void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *server, grpc_closure *on_done); #endif /* GRPC_CORE_LIB_IOMGR_UDP_SERVER_H */ grpc-1.3.2/src/core/lib/iomgr/unix_sockets_posix.c000066400000000000000000000074571310511640000221620ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_HAVE_UNIX_SOCKET #include "src/core/lib/iomgr/sockaddr.h" #include #include #include #include #include "src/core/lib/iomgr/unix_sockets_posix.h" #include #include #include void grpc_create_socketpair_if_unix(int sv[2]) { GPR_ASSERT(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == 0); } grpc_error *grpc_resolve_unix_domain_address(const char *name, grpc_resolved_addresses **addrs) { struct sockaddr_un *un; if (strlen(name) > GPR_ARRAY_SIZE(((struct sockaddr_un *)0)->sun_path) - 1) { char *err_msg; grpc_error *err; gpr_asprintf(&err_msg, "Path name should not have more than %" PRIuPTR " characters.", GPR_ARRAY_SIZE(un->sun_path) - 1); err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(err_msg); gpr_free(err_msg); return err; } *addrs = gpr_malloc(sizeof(grpc_resolved_addresses)); (*addrs)->naddrs = 1; (*addrs)->addrs = gpr_malloc(sizeof(grpc_resolved_address)); un = (struct sockaddr_un *)(*addrs)->addrs->addr; un->sun_family = AF_UNIX; strcpy(un->sun_path, name); (*addrs)->addrs->len = strlen(un->sun_path) + sizeof(un->sun_family) + 1; return GRPC_ERROR_NONE; } int grpc_is_unix_socket(const grpc_resolved_address *resolved_addr) { const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr; return addr->sa_family == AF_UNIX; } void grpc_unlink_if_unix_domain_socket( const grpc_resolved_address *resolved_addr) { const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr; if (addr->sa_family != AF_UNIX) { return; } struct sockaddr_un *un = (struct sockaddr_un *)resolved_addr->addr; struct stat st; if (stat(un->sun_path, &st) == 0 && (st.st_mode & S_IFMT) == S_IFSOCK) { unlink(un->sun_path); } } char *grpc_sockaddr_to_uri_unix_if_possible( const grpc_resolved_address *resolved_addr) { const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr; if (addr->sa_family != AF_UNIX) { return NULL; } char *result; gpr_asprintf(&result, "unix:%s", ((struct sockaddr_un *)addr)->sun_path); return result; } #endif grpc-1.3.2/src/core/lib/iomgr/unix_sockets_posix.h000066400000000000000000000043241310511640000221550ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_UNIX_SOCKETS_POSIX_H #define GRPC_CORE_LIB_IOMGR_UNIX_SOCKETS_POSIX_H #include "src/core/lib/iomgr/port.h" #include #include "src/core/lib/iomgr/resolve_address.h" void grpc_create_socketpair_if_unix(int sv[2]); grpc_error *grpc_resolve_unix_domain_address( const char *name, grpc_resolved_addresses **addresses); int grpc_is_unix_socket(const grpc_resolved_address *resolved_addr); void grpc_unlink_if_unix_domain_socket( const grpc_resolved_address *resolved_addr); char *grpc_sockaddr_to_uri_unix_if_possible( const grpc_resolved_address *resolved_addr); #endif /* GRPC_CORE_LIB_IOMGR_UNIX_SOCKETS_POSIX_H */ grpc-1.3.2/src/core/lib/iomgr/unix_sockets_posix_noop.c000066400000000000000000000046261310511640000232100ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/unix_sockets_posix.h" #ifndef GRPC_HAVE_UNIX_SOCKET #include void grpc_create_socketpair_if_unix(int sv[2]) { // TODO: Either implement this for the non-Unix socket case or make // sure that it is never called in any such case. Until then, leave an // assertion to notify if this gets called inadvertently GPR_ASSERT(0); } grpc_error *grpc_resolve_unix_domain_address( const char *name, grpc_resolved_addresses **addresses) { *addresses = NULL; return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Unix domain sockets are not supported on Windows"); } int grpc_is_unix_socket(const grpc_resolved_address *addr) { return false; } void grpc_unlink_if_unix_domain_socket(const grpc_resolved_address *addr) {} char *grpc_sockaddr_to_uri_unix_if_possible(const grpc_resolved_address *addr) { return NULL; } #endif grpc-1.3.2/src/core/lib/iomgr/wakeup_fd_cv.c000066400000000000000000000076401310511640000206510ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_POSIX_WAKEUP_FD #include "src/core/lib/iomgr/wakeup_fd_cv.h" #include #include #include #include #include #include #include #include #define MAX_TABLE_RESIZE 256 extern cv_fd_table g_cvfds; static grpc_error* cv_fd_init(grpc_wakeup_fd* fd_info) { unsigned int i, newsize; int idx; gpr_mu_lock(&g_cvfds.mu); if (!g_cvfds.free_fds) { newsize = GPR_MIN(g_cvfds.size * 2, g_cvfds.size + MAX_TABLE_RESIZE); g_cvfds.cvfds = gpr_realloc(g_cvfds.cvfds, sizeof(fd_node) * newsize); for (i = g_cvfds.size; i < newsize; i++) { g_cvfds.cvfds[i].is_set = 0; g_cvfds.cvfds[i].cvs = NULL; g_cvfds.cvfds[i].next_free = g_cvfds.free_fds; g_cvfds.free_fds = &g_cvfds.cvfds[i]; } g_cvfds.size = newsize; } idx = (int)(g_cvfds.free_fds - g_cvfds.cvfds); g_cvfds.free_fds = g_cvfds.free_fds->next_free; g_cvfds.cvfds[idx].cvs = NULL; g_cvfds.cvfds[idx].is_set = 0; fd_info->read_fd = IDX_TO_FD(idx); fd_info->write_fd = -1; gpr_mu_unlock(&g_cvfds.mu); return GRPC_ERROR_NONE; } static grpc_error* cv_fd_wakeup(grpc_wakeup_fd* fd_info) { cv_node* cvn; gpr_mu_lock(&g_cvfds.mu); g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)].is_set = 1; cvn = g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)].cvs; while (cvn) { gpr_cv_signal(cvn->cv); cvn = cvn->next; } gpr_mu_unlock(&g_cvfds.mu); return GRPC_ERROR_NONE; } static grpc_error* cv_fd_consume(grpc_wakeup_fd* fd_info) { gpr_mu_lock(&g_cvfds.mu); g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)].is_set = 0; gpr_mu_unlock(&g_cvfds.mu); return GRPC_ERROR_NONE; } static void cv_fd_destroy(grpc_wakeup_fd* fd_info) { if (fd_info->read_fd == 0) { return; } gpr_mu_lock(&g_cvfds.mu); // Assert that there are no active pollers GPR_ASSERT(!g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)].cvs); g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)].next_free = g_cvfds.free_fds; g_cvfds.free_fds = &g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)]; gpr_mu_unlock(&g_cvfds.mu); } static int cv_check_availability(void) { return 1; } const grpc_wakeup_fd_vtable grpc_cv_wakeup_fd_vtable = { cv_fd_init, cv_fd_consume, cv_fd_wakeup, cv_fd_destroy, cv_check_availability}; #endif /* GRPC_POSIX_WAKUP_FD */ grpc-1.3.2/src/core/lib/iomgr/wakeup_fd_cv.h000066400000000000000000000052661310511640000206600ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* * wakeup_fd_cv uses condition variables to implement wakeup fds. * * It is intended for use only in cases when eventfd() and pipe() are not * available. It can only be used with the "poll" engine. * * Implementation: * A global table of cv wakeup fds is mantained. A cv wakeup fd is a negative * file descriptor. poll() is then run in a background thread with only the * real socket fds while we wait on a condition variable trigged by either the * poll() completion or a wakeup_fd() call. * */ #ifndef GRPC_CORE_LIB_IOMGR_WAKEUP_FD_CV_H #define GRPC_CORE_LIB_IOMGR_WAKEUP_FD_CV_H #include #include "src/core/lib/iomgr/ev_posix.h" #define FD_TO_IDX(fd) (-(fd)-1) #define IDX_TO_FD(idx) (-(idx)-1) typedef struct cv_node { gpr_cv* cv; struct cv_node* next; } cv_node; typedef struct fd_node { int is_set; cv_node* cvs; struct fd_node* next_free; } fd_node; typedef struct cv_fd_table { gpr_mu mu; int pollcount; int shutdown; gpr_cv shutdown_complete; fd_node* cvfds; fd_node* free_fds; unsigned int size; grpc_poll_function_type poll; } cv_fd_table; #endif /* GRPC_CORE_LIB_IOMGR_WAKEUP_FD_CV_H */ grpc-1.3.2/src/core/lib/iomgr/wakeup_fd_eventfd.c000066400000000000000000000062221310511640000216670ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_LINUX_EVENTFD #include #include #include #include #include "src/core/lib/iomgr/wakeup_fd_posix.h" #include "src/core/lib/profiling/timers.h" static grpc_error* eventfd_create(grpc_wakeup_fd* fd_info) { int efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); if (efd < 0) { return GRPC_OS_ERROR(errno, "eventfd"); } fd_info->read_fd = efd; fd_info->write_fd = -1; return GRPC_ERROR_NONE; } static grpc_error* eventfd_consume(grpc_wakeup_fd* fd_info) { eventfd_t value; int err; do { err = eventfd_read(fd_info->read_fd, &value); } while (err < 0 && errno == EINTR); if (err < 0 && errno != EAGAIN) { return GRPC_OS_ERROR(errno, "eventfd_read"); } return GRPC_ERROR_NONE; } static grpc_error* eventfd_wakeup(grpc_wakeup_fd* fd_info) { int err; GPR_TIMER_BEGIN("eventfd_wakeup", 0); do { err = eventfd_write(fd_info->read_fd, 1); } while (err < 0 && errno == EINTR); if (err < 0) { return GRPC_OS_ERROR(errno, "eventfd_write"); } GPR_TIMER_END("eventfd_wakeup", 0); return GRPC_ERROR_NONE; } static void eventfd_destroy(grpc_wakeup_fd* fd_info) { if (fd_info->read_fd != 0) close(fd_info->read_fd); } static int eventfd_check_availability(void) { const int efd = eventfd(0, 0); const int is_available = efd >= 0; if (is_available) close(efd); return is_available; } const grpc_wakeup_fd_vtable grpc_specialized_wakeup_fd_vtable = { eventfd_create, eventfd_consume, eventfd_wakeup, eventfd_destroy, eventfd_check_availability}; #endif /* GRPC_LINUX_EVENTFD */ grpc-1.3.2/src/core/lib/iomgr/wakeup_fd_nospecial.c000066400000000000000000000040351310511640000222110ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* * This is a dummy file to provide an invalid specialized_wakeup_fd_vtable on * systems without anything better than pipe. */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_POSIX_NO_SPECIAL_WAKEUP_FD #include #include "src/core/lib/iomgr/wakeup_fd_posix.h" static int check_availability_invalid(void) { return 0; } const grpc_wakeup_fd_vtable grpc_specialized_wakeup_fd_vtable = { NULL, NULL, NULL, NULL, check_availability_invalid}; #endif /* GRPC_POSIX_NO_SPECIAL_WAKEUP_FD */ grpc-1.3.2/src/core/lib/iomgr/wakeup_fd_pipe.c000066400000000000000000000066431310511640000212000ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_POSIX_WAKEUP_FD #include "src/core/lib/iomgr/wakeup_fd_posix.h" #include #include #include #include #include "src/core/lib/iomgr/socket_utils_posix.h" static grpc_error* pipe_init(grpc_wakeup_fd* fd_info) { int pipefd[2]; int r = pipe(pipefd); if (0 != r) { gpr_log(GPR_ERROR, "pipe creation failed (%d): %s", errno, strerror(errno)); return GRPC_OS_ERROR(errno, "pipe"); } grpc_error* err; err = grpc_set_socket_nonblocking(pipefd[0], 1); if (err != GRPC_ERROR_NONE) return err; err = grpc_set_socket_nonblocking(pipefd[1], 1); if (err != GRPC_ERROR_NONE) return err; fd_info->read_fd = pipefd[0]; fd_info->write_fd = pipefd[1]; return GRPC_ERROR_NONE; } static grpc_error* pipe_consume(grpc_wakeup_fd* fd_info) { char buf[128]; ssize_t r; for (;;) { r = read(fd_info->read_fd, buf, sizeof(buf)); if (r > 0) continue; if (r == 0) return GRPC_ERROR_NONE; switch (errno) { case EAGAIN: return GRPC_ERROR_NONE; case EINTR: continue; default: return GRPC_OS_ERROR(errno, "read"); } } } static grpc_error* pipe_wakeup(grpc_wakeup_fd* fd_info) { char c = 0; while (write(fd_info->write_fd, &c, 1) != 1 && errno == EINTR) ; return GRPC_ERROR_NONE; } static void pipe_destroy(grpc_wakeup_fd* fd_info) { if (fd_info->read_fd != 0) close(fd_info->read_fd); if (fd_info->write_fd != 0) close(fd_info->write_fd); } static int pipe_check_availability(void) { grpc_wakeup_fd fd; fd.read_fd = fd.write_fd = -1; if (pipe_init(&fd) == GRPC_ERROR_NONE) { pipe_destroy(&fd); return 1; } else { return 0; } } const grpc_wakeup_fd_vtable grpc_pipe_wakeup_fd_vtable = { pipe_init, pipe_consume, pipe_wakeup, pipe_destroy, pipe_check_availability}; #endif /* GPR_POSIX_WAKUP_FD */ grpc-1.3.2/src/core/lib/iomgr/wakeup_fd_pipe.h000066400000000000000000000034321310511640000211760ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_WAKEUP_FD_PIPE_H #define GRPC_CORE_LIB_IOMGR_WAKEUP_FD_PIPE_H #include "src/core/lib/iomgr/wakeup_fd_posix.h" extern grpc_wakeup_fd_vtable grpc_pipe_wakeup_fd_vtable; #endif /* GRPC_CORE_LIB_IOMGR_WAKEUP_FD_PIPE_H */ grpc-1.3.2/src/core/lib/iomgr/wakeup_fd_posix.c000066400000000000000000000067531310511640000214070ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_POSIX_WAKEUP_FD #include #include "src/core/lib/iomgr/wakeup_fd_cv.h" #include "src/core/lib/iomgr/wakeup_fd_pipe.h" #include "src/core/lib/iomgr/wakeup_fd_posix.h" extern grpc_wakeup_fd_vtable grpc_cv_wakeup_fd_vtable; static const grpc_wakeup_fd_vtable *wakeup_fd_vtable = NULL; int grpc_allow_specialized_wakeup_fd = 1; int grpc_allow_pipe_wakeup_fd = 1; int has_real_wakeup_fd = 1; int cv_wakeup_fds_enabled = 0; void grpc_wakeup_fd_global_init(void) { if (grpc_allow_specialized_wakeup_fd && grpc_specialized_wakeup_fd_vtable.check_availability()) { wakeup_fd_vtable = &grpc_specialized_wakeup_fd_vtable; } else if (grpc_allow_pipe_wakeup_fd && grpc_pipe_wakeup_fd_vtable.check_availability()) { wakeup_fd_vtable = &grpc_pipe_wakeup_fd_vtable; } else { has_real_wakeup_fd = 0; } } void grpc_wakeup_fd_global_destroy(void) { wakeup_fd_vtable = NULL; } int grpc_has_wakeup_fd(void) { return has_real_wakeup_fd; } int grpc_cv_wakeup_fds_enabled(void) { return cv_wakeup_fds_enabled; } void grpc_enable_cv_wakeup_fds(int enable) { cv_wakeup_fds_enabled = enable; } grpc_error *grpc_wakeup_fd_init(grpc_wakeup_fd *fd_info) { if (cv_wakeup_fds_enabled) { return grpc_cv_wakeup_fd_vtable.init(fd_info); } return wakeup_fd_vtable->init(fd_info); } grpc_error *grpc_wakeup_fd_consume_wakeup(grpc_wakeup_fd *fd_info) { if (cv_wakeup_fds_enabled) { return grpc_cv_wakeup_fd_vtable.consume(fd_info); } return wakeup_fd_vtable->consume(fd_info); } grpc_error *grpc_wakeup_fd_wakeup(grpc_wakeup_fd *fd_info) { if (cv_wakeup_fds_enabled) { return grpc_cv_wakeup_fd_vtable.wakeup(fd_info); } return wakeup_fd_vtable->wakeup(fd_info); } void grpc_wakeup_fd_destroy(grpc_wakeup_fd *fd_info) { if (cv_wakeup_fds_enabled) { grpc_cv_wakeup_fd_vtable.destroy(fd_info); } else { wakeup_fd_vtable->destroy(fd_info); } } #endif /* GRPC_POSIX_WAKEUP_FD */ grpc-1.3.2/src/core/lib/iomgr/wakeup_fd_posix.h000066400000000000000000000106151310511640000214040ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* * wakeup_fd abstracts the concept of a file descriptor for the purpose of * waking up a thread in select()/poll()/epoll_wait()/etc. * The poll() family of system calls provide a way for a thread to block until * there is activity on one (or more) of a set of file descriptors. An * application may wish to wake up this thread to do non file related work. The * typical way to do this is to add a pipe to the set of file descriptors, then * write to the pipe to wake up the thread in poll(). * * Linux has a lighter weight eventfd specifically designed for this purpose. * wakeup_fd abstracts the difference between the two. * * Setup: * 1. Before calling anything, call global_init() at least once. * 1. Call grpc_wakeup_fd_init() to set up a wakeup_fd. * 2. Add the result of GRPC_WAKEUP_FD_FD to the set of monitored file * descriptors for the poll() style API you are using. Monitor the file * descriptor for readability. * 3. To tear down, call grpc_wakeup_fd_destroy(). This closes the underlying * file descriptor. * * Usage: * 1. To wake up a polling thread, call grpc_wakeup_fd_wakeup() on a wakeup_fd * it is monitoring. * 2. If the polling thread was awakened by a wakeup_fd event, call * grpc_wakeup_fd_consume_wakeup() on it. */ #ifndef GRPC_CORE_LIB_IOMGR_WAKEUP_FD_POSIX_H #define GRPC_CORE_LIB_IOMGR_WAKEUP_FD_POSIX_H #include "src/core/lib/iomgr/error.h" void grpc_wakeup_fd_global_init(void); void grpc_wakeup_fd_global_destroy(void); /* Force using the fallback implementation. This is intended for testing * purposes only.*/ void grpc_wakeup_fd_global_init_force_fallback(void); int grpc_has_wakeup_fd(void); int grpc_cv_wakeup_fds_enabled(void); void grpc_enable_cv_wakeup_fds(int enable); typedef struct grpc_wakeup_fd grpc_wakeup_fd; typedef struct grpc_wakeup_fd_vtable { grpc_error* (*init)(grpc_wakeup_fd* fd_info); grpc_error* (*consume)(grpc_wakeup_fd* fd_info); grpc_error* (*wakeup)(grpc_wakeup_fd* fd_info); void (*destroy)(grpc_wakeup_fd* fd_info); /* Must be called before calling any other functions */ int (*check_availability)(void); } grpc_wakeup_fd_vtable; struct grpc_wakeup_fd { int read_fd; int write_fd; }; extern int grpc_allow_specialized_wakeup_fd; extern int grpc_allow_pipe_wakeup_fd; #define GRPC_WAKEUP_FD_GET_READ_FD(fd_info) ((fd_info)->read_fd) grpc_error* grpc_wakeup_fd_init(grpc_wakeup_fd* fd_info) GRPC_MUST_USE_RESULT; grpc_error* grpc_wakeup_fd_consume_wakeup(grpc_wakeup_fd* fd_info) GRPC_MUST_USE_RESULT; grpc_error* grpc_wakeup_fd_wakeup(grpc_wakeup_fd* fd_info) GRPC_MUST_USE_RESULT; void grpc_wakeup_fd_destroy(grpc_wakeup_fd* fd_info); /* Defined in some specialized implementation's .c file, or by * wakeup_fd_nospecial.c if no such implementation exists. */ extern const grpc_wakeup_fd_vtable grpc_specialized_wakeup_fd_vtable; #endif /* GRPC_CORE_LIB_IOMGR_WAKEUP_FD_POSIX_H */ grpc-1.3.2/src/core/lib/iomgr/workqueue.h000066400000000000000000000075261310511640000202530ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_WORKQUEUE_H #define GRPC_CORE_LIB_IOMGR_WORKQUEUE_H #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/pollset_set.h" #include "src/core/lib/iomgr/port.h" #ifdef GPR_WINDOWS #include "src/core/lib/iomgr/workqueue_windows.h" #endif /* grpc_workqueue is forward declared in exec_ctx.h */ /* Reference counting functions. Use the macro's always (GRPC_WORKQUEUE_{REF,UNREF}). Pass in a descriptive reason string for reffing/unreffing as the last argument to each macro. When GRPC_WORKQUEUE_REFCOUNT_DEBUG is defined, that string will be printed alongside the refcount. When it is not defined, the string will be discarded at compilation time. */ /*#define GRPC_WORKQUEUE_REFCOUNT_DEBUG*/ #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG #define GRPC_WORKQUEUE_REF(p, r) \ grpc_workqueue_ref((p), __FILE__, __LINE__, (r)) #define GRPC_WORKQUEUE_UNREF(exec_ctx, p, r) \ grpc_workqueue_unref((exec_ctx), (p), __FILE__, __LINE__, (r)) grpc_workqueue *grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line, const char *reason); void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, const char *file, int line, const char *reason); #else #define GRPC_WORKQUEUE_REF(p, r) grpc_workqueue_ref((p)) #define GRPC_WORKQUEUE_UNREF(cl, p, r) grpc_workqueue_unref((cl), (p)) grpc_workqueue *grpc_workqueue_ref(grpc_workqueue *workqueue); void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue); #endif /** Fetch the workqueue closure scheduler. Items added to a work queue will be started in approximately the order they were enqueued, on some thread that may or may not be the current thread. Successive closures enqueued onto a workqueue MAY be executed concurrently. It is generally more expensive to add a closure to a workqueue than to the execution context, both in terms of CPU work and in execution latency. Use work queues when it's important that other threads be given a chance to tackle some workload. */ grpc_closure_scheduler *grpc_workqueue_scheduler(grpc_workqueue *workqueue); #endif /* GRPC_CORE_LIB_IOMGR_WORKQUEUE_H */ grpc-1.3.2/src/core/lib/iomgr/workqueue_uv.c000066400000000000000000000051311310511640000207460ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_UV #include "src/core/lib/iomgr/workqueue.h" // Minimal implementation of grpc_workqueue for libuv // Works by directly enqueuing workqueue items onto the current execution // context, which is at least correct, if not performant or in the spirit of // workqueues. void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) {} #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG grpc_workqueue *grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line, const char *reason) { return workqueue; } void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, const char *file, int line, const char *reason) {} #else grpc_workqueue *grpc_workqueue_ref(grpc_workqueue *workqueue) { return workqueue; } void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) {} #endif grpc_closure_scheduler *grpc_workqueue_scheduler(grpc_workqueue *workqueue) { return grpc_schedule_on_exec_ctx; } #endif /* GPR_UV */ grpc-1.3.2/src/core/lib/iomgr/workqueue_uv.h000066400000000000000000000032511310511640000207540ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_WORKQUEUE_UV_H #define GRPC_CORE_LIB_IOMGR_WORKQUEUE_UV_H #endif /* GRPC_CORE_LIB_IOMGR_WORKQUEUE_UV_H */ grpc-1.3.2/src/core/lib/iomgr/workqueue_windows.c000066400000000000000000000050251310511640000220100ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifdef GPR_WINDOWS #include "src/core/lib/iomgr/workqueue.h" // Minimal implementation of grpc_workqueue for Windows // Works by directly enqueuing workqueue items onto the current execution // context, which is at least correct, if not performant or in the spirit of // workqueues. #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG grpc_workqueue *grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line, const char *reason) { return workqueue; } void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, const char *file, int line, const char *reason) {} #else grpc_workqueue *grpc_workqueue_ref(grpc_workqueue *workqueue) { return workqueue; } void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) {} #endif grpc_closure_scheduler *grpc_workqueue_scheduler(grpc_workqueue *workqueue) { return grpc_schedule_on_exec_ctx; } #endif /* GPR_WINDOWS */ grpc-1.3.2/src/core/lib/iomgr/workqueue_windows.h000066400000000000000000000032701310511640000220150ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_IOMGR_WORKQUEUE_WINDOWS_H #define GRPC_CORE_LIB_IOMGR_WORKQUEUE_WINDOWS_H #endif /* GRPC_CORE_LIB_IOMGR_WORKQUEUE_WINDOWS_H */ grpc-1.3.2/src/core/lib/json/000077500000000000000000000000001310511640000156755ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/json/json.c000066400000000000000000000041011310511640000170060ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include "src/core/lib/json/json.h" grpc_json* grpc_json_create(grpc_json_type type) { grpc_json* json = gpr_zalloc(sizeof(*json)); json->type = type; return json; } void grpc_json_destroy(grpc_json* json) { while (json->child) { grpc_json_destroy(json->child); } if (json->next) { json->next->prev = json->prev; } if (json->prev) { json->prev->next = json->next; } else if (json->parent) { json->parent->child = json->next; } gpr_free(json); } grpc-1.3.2/src/core/lib/json/json.h000066400000000000000000000065461310511640000170320ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_JSON_JSON_H #define GRPC_CORE_LIB_JSON_JSON_H #include #include "src/core/lib/json/json_common.h" /* A tree-like structure to hold json values. The key and value pointers * are not owned by it. */ typedef struct grpc_json { struct grpc_json* next; struct grpc_json* prev; struct grpc_json* child; struct grpc_json* parent; grpc_json_type type; const char* key; const char* value; } grpc_json; /* The next two functions are going to parse the input string, and * modify it in the process, in order to use its space to store * all of the keys and values for the returned object tree. * * They assume UTF-8 input stream, and will output UTF-8 encoded * strings in the tree. The input stream's UTF-8 isn't validated, * as in, what you input is what you get as an output. * * All the keys and values in the grpc_json objects will be strings * pointing at your input buffer. * * Delete the allocated tree afterward using grpc_json_destroy(). */ grpc_json* grpc_json_parse_string_with_len(char* input, size_t size); grpc_json* grpc_json_parse_string(char* input); /* This function will create a new string using gpr_realloc, and will * deserialize the grpc_json tree into it. It'll be zero-terminated, * but will be allocated in chunks of 256 bytes. * * The indent parameter controls the way the output is formatted. * If indent is 0, then newlines will be suppressed as well, and the * output will be condensed at its maximum. */ char* grpc_json_dump_to_string(grpc_json* json, int indent); /* Use these to create or delete a grpc_json object. * Deletion is recursive. We will not attempt to free any of the strings * in any of the objects of that tree. */ grpc_json* grpc_json_create(grpc_json_type type); void grpc_json_destroy(grpc_json* json); #endif /* GRPC_CORE_LIB_JSON_JSON_H */ grpc-1.3.2/src/core/lib/json/json_common.h000066400000000000000000000035771310511640000204030ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_JSON_JSON_COMMON_H #define GRPC_CORE_LIB_JSON_JSON_COMMON_H /* The various json types. */ typedef enum { GRPC_JSON_OBJECT, GRPC_JSON_ARRAY, GRPC_JSON_STRING, GRPC_JSON_NUMBER, GRPC_JSON_TRUE, GRPC_JSON_FALSE, GRPC_JSON_NULL, GRPC_JSON_TOP_LEVEL } grpc_json_type; #endif /* GRPC_CORE_LIB_JSON_JSON_COMMON_H */ grpc-1.3.2/src/core/lib/json/json_reader.c000066400000000000000000000554461310511640000203520ustar00rootroot00000000000000/* * * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include "src/core/lib/json/json_reader.h" static void json_reader_string_clear(grpc_json_reader *reader) { reader->vtable->string_clear(reader->userdata); } static void json_reader_string_add_char(grpc_json_reader *reader, uint32_t c) { reader->vtable->string_add_char(reader->userdata, c); } static void json_reader_string_add_utf32(grpc_json_reader *reader, uint32_t utf32) { reader->vtable->string_add_utf32(reader->userdata, utf32); } static uint32_t grpc_json_reader_read_char(grpc_json_reader *reader) { return reader->vtable->read_char(reader->userdata); } static void json_reader_container_begins(grpc_json_reader *reader, grpc_json_type type) { reader->vtable->container_begins(reader->userdata, type); } static grpc_json_type grpc_json_reader_container_ends( grpc_json_reader *reader) { return reader->vtable->container_ends(reader->userdata); } static void json_reader_set_key(grpc_json_reader *reader) { reader->vtable->set_key(reader->userdata); } static void json_reader_set_string(grpc_json_reader *reader) { reader->vtable->set_string(reader->userdata); } static int json_reader_set_number(grpc_json_reader *reader) { return reader->vtable->set_number(reader->userdata); } static void json_reader_set_true(grpc_json_reader *reader) { reader->vtable->set_true(reader->userdata); } static void json_reader_set_false(grpc_json_reader *reader) { reader->vtable->set_false(reader->userdata); } static void json_reader_set_null(grpc_json_reader *reader) { reader->vtable->set_null(reader->userdata); } /* Call this function to initialize the reader structure. */ void grpc_json_reader_init(grpc_json_reader *reader, grpc_json_reader_vtable *vtable, void *userdata) { memset(reader, 0, sizeof(*reader)); reader->vtable = vtable; reader->userdata = userdata; json_reader_string_clear(reader); reader->state = GRPC_JSON_STATE_VALUE_BEGIN; } int grpc_json_reader_is_complete(grpc_json_reader *reader) { return ((reader->depth == 0) && ((reader->state == GRPC_JSON_STATE_END) || (reader->state == GRPC_JSON_STATE_VALUE_END))); } grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) { uint32_t c, success; /* This state-machine is a strict implementation of ECMA-404 */ for (;;) { c = grpc_json_reader_read_char(reader); switch (c) { /* Let's process the error cases first. */ case GRPC_JSON_READ_CHAR_ERROR: return GRPC_JSON_READ_ERROR; case GRPC_JSON_READ_CHAR_EAGAIN: return GRPC_JSON_EAGAIN; case GRPC_JSON_READ_CHAR_EOF: if (grpc_json_reader_is_complete(reader)) { return GRPC_JSON_DONE; } else { return GRPC_JSON_PARSE_ERROR; } break; /* Processing whitespaces. */ case ' ': case '\t': case '\n': case '\r': switch (reader->state) { case GRPC_JSON_STATE_OBJECT_KEY_BEGIN: case GRPC_JSON_STATE_OBJECT_KEY_END: case GRPC_JSON_STATE_VALUE_BEGIN: case GRPC_JSON_STATE_VALUE_END: case GRPC_JSON_STATE_END: break; case GRPC_JSON_STATE_OBJECT_KEY_STRING: case GRPC_JSON_STATE_VALUE_STRING: if (c != ' ') return GRPC_JSON_PARSE_ERROR; if (reader->unicode_high_surrogate != 0) return GRPC_JSON_PARSE_ERROR; json_reader_string_add_char(reader, c); break; case GRPC_JSON_STATE_VALUE_NUMBER: case GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL: case GRPC_JSON_STATE_VALUE_NUMBER_ZERO: case GRPC_JSON_STATE_VALUE_NUMBER_EPM: success = (uint32_t)json_reader_set_number(reader); if (!success) return GRPC_JSON_PARSE_ERROR; json_reader_string_clear(reader); reader->state = GRPC_JSON_STATE_VALUE_END; break; default: return GRPC_JSON_PARSE_ERROR; } break; /* Value, object or array terminations. */ case ',': case '}': case ']': switch (reader->state) { case GRPC_JSON_STATE_OBJECT_KEY_STRING: case GRPC_JSON_STATE_VALUE_STRING: if (reader->unicode_high_surrogate != 0) { return GRPC_JSON_PARSE_ERROR; } json_reader_string_add_char(reader, c); break; case GRPC_JSON_STATE_VALUE_NUMBER: case GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL: case GRPC_JSON_STATE_VALUE_NUMBER_ZERO: case GRPC_JSON_STATE_VALUE_NUMBER_EPM: if (reader->depth == 0) { return GRPC_JSON_PARSE_ERROR; } else if ((c == '}') && !reader->in_object) { return GRPC_JSON_PARSE_ERROR; } else if ((c == ']') && !reader->in_array) { return GRPC_JSON_PARSE_ERROR; } success = (uint32_t)json_reader_set_number(reader); if (!success) return GRPC_JSON_PARSE_ERROR; json_reader_string_clear(reader); reader->state = GRPC_JSON_STATE_VALUE_END; /* The missing break here is intentional. */ case GRPC_JSON_STATE_VALUE_END: case GRPC_JSON_STATE_OBJECT_KEY_BEGIN: case GRPC_JSON_STATE_VALUE_BEGIN: if (c == ',') { if (reader->state != GRPC_JSON_STATE_VALUE_END) { return GRPC_JSON_PARSE_ERROR; } if (reader->in_object) { reader->state = GRPC_JSON_STATE_OBJECT_KEY_BEGIN; } else if (reader->in_array) { reader->state = GRPC_JSON_STATE_VALUE_BEGIN; } else { return GRPC_JSON_PARSE_ERROR; } } else { if (reader->depth-- == 0) return GRPC_JSON_PARSE_ERROR; if ((c == '}') && !reader->in_object) { return GRPC_JSON_PARSE_ERROR; } if ((c == '}') && (reader->state == GRPC_JSON_STATE_OBJECT_KEY_BEGIN) && !reader->container_just_begun) { return GRPC_JSON_PARSE_ERROR; } if ((c == ']') && !reader->in_array) return GRPC_JSON_PARSE_ERROR; if ((c == ']') && (reader->state == GRPC_JSON_STATE_VALUE_BEGIN) && !reader->container_just_begun) { return GRPC_JSON_PARSE_ERROR; } reader->state = GRPC_JSON_STATE_VALUE_END; switch (grpc_json_reader_container_ends(reader)) { case GRPC_JSON_OBJECT: reader->in_object = 1; reader->in_array = 0; break; case GRPC_JSON_ARRAY: reader->in_object = 0; reader->in_array = 1; break; case GRPC_JSON_TOP_LEVEL: GPR_ASSERT(reader->depth == 0); reader->in_object = 0; reader->in_array = 0; reader->state = GRPC_JSON_STATE_END; break; default: GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR); } } break; default: return GRPC_JSON_PARSE_ERROR; } break; /* In-string escaping. */ case '\\': switch (reader->state) { case GRPC_JSON_STATE_OBJECT_KEY_STRING: reader->escaped_string_was_key = 1; reader->state = GRPC_JSON_STATE_STRING_ESCAPE; break; case GRPC_JSON_STATE_VALUE_STRING: reader->escaped_string_was_key = 0; reader->state = GRPC_JSON_STATE_STRING_ESCAPE; break; /* This is the \\ case. */ case GRPC_JSON_STATE_STRING_ESCAPE: if (reader->unicode_high_surrogate != 0) return GRPC_JSON_PARSE_ERROR; json_reader_string_add_char(reader, '\\'); if (reader->escaped_string_was_key) { reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING; } else { reader->state = GRPC_JSON_STATE_VALUE_STRING; } break; default: return GRPC_JSON_PARSE_ERROR; } break; default: reader->container_just_begun = 0; switch (reader->state) { case GRPC_JSON_STATE_OBJECT_KEY_BEGIN: if (c != '"') return GRPC_JSON_PARSE_ERROR; reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING; break; case GRPC_JSON_STATE_OBJECT_KEY_STRING: if (reader->unicode_high_surrogate != 0) { return GRPC_JSON_PARSE_ERROR; } if (c == '"') { reader->state = GRPC_JSON_STATE_OBJECT_KEY_END; json_reader_set_key(reader); json_reader_string_clear(reader); } else { if (c < 32) return GRPC_JSON_PARSE_ERROR; json_reader_string_add_char(reader, c); } break; case GRPC_JSON_STATE_VALUE_STRING: if (reader->unicode_high_surrogate != 0) { return GRPC_JSON_PARSE_ERROR; } if (c == '"') { reader->state = GRPC_JSON_STATE_VALUE_END; json_reader_set_string(reader); json_reader_string_clear(reader); } else { if (c < 32) return GRPC_JSON_PARSE_ERROR; json_reader_string_add_char(reader, c); } break; case GRPC_JSON_STATE_OBJECT_KEY_END: if (c != ':') return GRPC_JSON_PARSE_ERROR; reader->state = GRPC_JSON_STATE_VALUE_BEGIN; break; case GRPC_JSON_STATE_VALUE_BEGIN: switch (c) { case 't': reader->state = GRPC_JSON_STATE_VALUE_TRUE_R; break; case 'f': reader->state = GRPC_JSON_STATE_VALUE_FALSE_A; break; case 'n': reader->state = GRPC_JSON_STATE_VALUE_NULL_U; break; case '"': reader->state = GRPC_JSON_STATE_VALUE_STRING; break; case '0': json_reader_string_add_char(reader, c); reader->state = GRPC_JSON_STATE_VALUE_NUMBER_ZERO; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': json_reader_string_add_char(reader, c); reader->state = GRPC_JSON_STATE_VALUE_NUMBER; break; case '{': reader->container_just_begun = 1; json_reader_container_begins(reader, GRPC_JSON_OBJECT); reader->depth++; reader->state = GRPC_JSON_STATE_OBJECT_KEY_BEGIN; reader->in_object = 1; reader->in_array = 0; break; case '[': reader->container_just_begun = 1; json_reader_container_begins(reader, GRPC_JSON_ARRAY); reader->depth++; reader->in_object = 0; reader->in_array = 1; break; default: return GRPC_JSON_PARSE_ERROR; } break; case GRPC_JSON_STATE_STRING_ESCAPE: if (reader->escaped_string_was_key) { reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING; } else { reader->state = GRPC_JSON_STATE_VALUE_STRING; } if (reader->unicode_high_surrogate && c != 'u') { return GRPC_JSON_PARSE_ERROR; } switch (c) { case '"': case '/': json_reader_string_add_char(reader, c); break; case 'b': json_reader_string_add_char(reader, '\b'); break; case 'f': json_reader_string_add_char(reader, '\f'); break; case 'n': json_reader_string_add_char(reader, '\n'); break; case 'r': json_reader_string_add_char(reader, '\r'); break; case 't': json_reader_string_add_char(reader, '\t'); break; case 'u': reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U1; reader->unicode_char = 0; break; default: return GRPC_JSON_PARSE_ERROR; } break; case GRPC_JSON_STATE_STRING_ESCAPE_U1: case GRPC_JSON_STATE_STRING_ESCAPE_U2: case GRPC_JSON_STATE_STRING_ESCAPE_U3: case GRPC_JSON_STATE_STRING_ESCAPE_U4: if ((c >= '0') && (c <= '9')) { c -= '0'; } else if ((c >= 'A') && (c <= 'F')) { c -= 'A' - 10; } else if ((c >= 'a') && (c <= 'f')) { c -= 'a' - 10; } else { return GRPC_JSON_PARSE_ERROR; } reader->unicode_char = (uint16_t)(reader->unicode_char << 4); reader->unicode_char = (uint16_t)(reader->unicode_char | c); switch (reader->state) { case GRPC_JSON_STATE_STRING_ESCAPE_U1: reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U2; break; case GRPC_JSON_STATE_STRING_ESCAPE_U2: reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U3; break; case GRPC_JSON_STATE_STRING_ESCAPE_U3: reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U4; break; case GRPC_JSON_STATE_STRING_ESCAPE_U4: /* See grpc_json_writer_escape_string to have a description * of what's going on here. */ if ((reader->unicode_char & 0xfc00) == 0xd800) { /* high surrogate utf-16 */ if (reader->unicode_high_surrogate != 0) return GRPC_JSON_PARSE_ERROR; reader->unicode_high_surrogate = reader->unicode_char; } else if ((reader->unicode_char & 0xfc00) == 0xdc00) { /* low surrogate utf-16 */ uint32_t utf32; if (reader->unicode_high_surrogate == 0) return GRPC_JSON_PARSE_ERROR; utf32 = 0x10000; utf32 += (uint32_t)( (reader->unicode_high_surrogate - 0xd800) * 0x400); utf32 += (uint32_t)(reader->unicode_char - 0xdc00); json_reader_string_add_utf32(reader, utf32); reader->unicode_high_surrogate = 0; } else { /* anything else */ if (reader->unicode_high_surrogate != 0) return GRPC_JSON_PARSE_ERROR; json_reader_string_add_utf32(reader, reader->unicode_char); } if (reader->escaped_string_was_key) { reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING; } else { reader->state = GRPC_JSON_STATE_VALUE_STRING; } break; default: GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR); } break; case GRPC_JSON_STATE_VALUE_NUMBER: json_reader_string_add_char(reader, c); switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': break; case 'e': case 'E': reader->state = GRPC_JSON_STATE_VALUE_NUMBER_E; break; case '.': reader->state = GRPC_JSON_STATE_VALUE_NUMBER_DOT; break; default: return GRPC_JSON_PARSE_ERROR; } break; case GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL: json_reader_string_add_char(reader, c); switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': break; case 'e': case 'E': reader->state = GRPC_JSON_STATE_VALUE_NUMBER_E; break; default: return GRPC_JSON_PARSE_ERROR; } break; case GRPC_JSON_STATE_VALUE_NUMBER_ZERO: if (c != '.') return GRPC_JSON_PARSE_ERROR; json_reader_string_add_char(reader, c); reader->state = GRPC_JSON_STATE_VALUE_NUMBER_DOT; break; case GRPC_JSON_STATE_VALUE_NUMBER_DOT: json_reader_string_add_char(reader, c); switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': reader->state = GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL; break; default: return GRPC_JSON_PARSE_ERROR; } break; case GRPC_JSON_STATE_VALUE_NUMBER_E: json_reader_string_add_char(reader, c); switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '+': case '-': reader->state = GRPC_JSON_STATE_VALUE_NUMBER_EPM; break; default: return GRPC_JSON_PARSE_ERROR; } break; case GRPC_JSON_STATE_VALUE_NUMBER_EPM: json_reader_string_add_char(reader, c); switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': break; default: return GRPC_JSON_PARSE_ERROR; } break; case GRPC_JSON_STATE_VALUE_TRUE_R: if (c != 'r') return GRPC_JSON_PARSE_ERROR; reader->state = GRPC_JSON_STATE_VALUE_TRUE_U; break; case GRPC_JSON_STATE_VALUE_TRUE_U: if (c != 'u') return GRPC_JSON_PARSE_ERROR; reader->state = GRPC_JSON_STATE_VALUE_TRUE_E; break; case GRPC_JSON_STATE_VALUE_TRUE_E: if (c != 'e') return GRPC_JSON_PARSE_ERROR; json_reader_set_true(reader); reader->state = GRPC_JSON_STATE_VALUE_END; break; case GRPC_JSON_STATE_VALUE_FALSE_A: if (c != 'a') return GRPC_JSON_PARSE_ERROR; reader->state = GRPC_JSON_STATE_VALUE_FALSE_L; break; case GRPC_JSON_STATE_VALUE_FALSE_L: if (c != 'l') return GRPC_JSON_PARSE_ERROR; reader->state = GRPC_JSON_STATE_VALUE_FALSE_S; break; case GRPC_JSON_STATE_VALUE_FALSE_S: if (c != 's') return GRPC_JSON_PARSE_ERROR; reader->state = GRPC_JSON_STATE_VALUE_FALSE_E; break; case GRPC_JSON_STATE_VALUE_FALSE_E: if (c != 'e') return GRPC_JSON_PARSE_ERROR; json_reader_set_false(reader); reader->state = GRPC_JSON_STATE_VALUE_END; break; case GRPC_JSON_STATE_VALUE_NULL_U: if (c != 'u') return GRPC_JSON_PARSE_ERROR; reader->state = GRPC_JSON_STATE_VALUE_NULL_L1; break; case GRPC_JSON_STATE_VALUE_NULL_L1: if (c != 'l') return GRPC_JSON_PARSE_ERROR; reader->state = GRPC_JSON_STATE_VALUE_NULL_L2; break; case GRPC_JSON_STATE_VALUE_NULL_L2: if (c != 'l') return GRPC_JSON_PARSE_ERROR; json_reader_set_null(reader); reader->state = GRPC_JSON_STATE_VALUE_END; break; /* All of the VALUE_END cases are handled in the specialized case * above. */ case GRPC_JSON_STATE_VALUE_END: switch (c) { case ',': case '}': case ']': GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR); break; default: return GRPC_JSON_PARSE_ERROR; } break; case GRPC_JSON_STATE_END: return GRPC_JSON_PARSE_ERROR; } } } GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR); } grpc-1.3.2/src/core/lib/json/json_reader.h000066400000000000000000000146711310511640000203520ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_JSON_JSON_READER_H #define GRPC_CORE_LIB_JSON_JSON_READER_H #include #include "src/core/lib/json/json_common.h" typedef enum { GRPC_JSON_STATE_OBJECT_KEY_BEGIN, GRPC_JSON_STATE_OBJECT_KEY_STRING, GRPC_JSON_STATE_OBJECT_KEY_END, GRPC_JSON_STATE_VALUE_BEGIN, GRPC_JSON_STATE_VALUE_STRING, GRPC_JSON_STATE_STRING_ESCAPE, GRPC_JSON_STATE_STRING_ESCAPE_U1, GRPC_JSON_STATE_STRING_ESCAPE_U2, GRPC_JSON_STATE_STRING_ESCAPE_U3, GRPC_JSON_STATE_STRING_ESCAPE_U4, GRPC_JSON_STATE_VALUE_NUMBER, GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL, GRPC_JSON_STATE_VALUE_NUMBER_ZERO, GRPC_JSON_STATE_VALUE_NUMBER_DOT, GRPC_JSON_STATE_VALUE_NUMBER_E, GRPC_JSON_STATE_VALUE_NUMBER_EPM, GRPC_JSON_STATE_VALUE_TRUE_R, GRPC_JSON_STATE_VALUE_TRUE_U, GRPC_JSON_STATE_VALUE_TRUE_E, GRPC_JSON_STATE_VALUE_FALSE_A, GRPC_JSON_STATE_VALUE_FALSE_L, GRPC_JSON_STATE_VALUE_FALSE_S, GRPC_JSON_STATE_VALUE_FALSE_E, GRPC_JSON_STATE_VALUE_NULL_U, GRPC_JSON_STATE_VALUE_NULL_L1, GRPC_JSON_STATE_VALUE_NULL_L2, GRPC_JSON_STATE_VALUE_END, GRPC_JSON_STATE_END } grpc_json_reader_state; enum { /* The first non-unicode value is 0x110000. But let's pick * a value high enough to start our error codes from. These * values are safe to return from the read_char function. */ GRPC_JSON_READ_CHAR_EOF = 0x7ffffff0, GRPC_JSON_READ_CHAR_EAGAIN, GRPC_JSON_READ_CHAR_ERROR }; struct grpc_json_reader; typedef struct grpc_json_reader_vtable { /* Clears your internal string scratchpad. */ void (*string_clear)(void *userdata); /* Adds a char to the string scratchpad. */ void (*string_add_char)(void *userdata, uint32_t c); /* Adds a utf32 char to the string scratchpad. */ void (*string_add_utf32)(void *userdata, uint32_t c); /* Reads a character from your input. May be utf-8, 16 or 32. */ uint32_t (*read_char)(void *userdata); /* Starts a container of type GRPC_JSON_ARRAY or GRPC_JSON_OBJECT. */ void (*container_begins)(void *userdata, grpc_json_type type); /* Ends the current container. Must return the type of its parent. */ grpc_json_type (*container_ends)(void *userdata); /* Your internal string scratchpad is an object's key. */ void (*set_key)(void *userdata); /* Your internal string scratchpad is a string value. */ void (*set_string)(void *userdata); /* Your internal string scratchpad is a numerical value. Return 1 if valid. */ int (*set_number)(void *userdata); /* Sets the values true, false or null. */ void (*set_true)(void *userdata); void (*set_false)(void *userdata); void (*set_null)(void *userdata); } grpc_json_reader_vtable; typedef struct grpc_json_reader { /* That structure is fully private, and initialized by grpc_json_reader_init. * The definition is public so you can put it on your stack. */ void *userdata; grpc_json_reader_vtable *vtable; int depth; int in_object; int in_array; int escaped_string_was_key; int container_just_begun; uint16_t unicode_char, unicode_high_surrogate; grpc_json_reader_state state; } grpc_json_reader; /* The return type of the parser. */ typedef enum { GRPC_JSON_DONE, /* The parser finished successfully. */ GRPC_JSON_EAGAIN, /* The parser yields to get more data. */ GRPC_JSON_READ_ERROR, /* The parser passes through a read error. */ GRPC_JSON_PARSE_ERROR, /* The parser found an error in the json stream. */ GRPC_JSON_INTERNAL_ERROR /* The parser got an internal error. */ } grpc_json_reader_status; /* Call this function to start parsing the input. It will return the following: * . GRPC_JSON_DONE if the input got eof, and the parsing finished * successfully. * . GRPC_JSON_EAGAIN if the read_char function returned again. Call the * parser again as needed. It is okay to call the parser in polling mode, * although a bit dull. * . GRPC_JSON_READ_ERROR if the read_char function returned an error. The * state isn't broken however, and the function can be called again if the * error has been corrected. But please use the EAGAIN feature instead for * consistency. * . GRPC_JSON_PARSE_ERROR if the input was somehow invalid. * . GRPC_JSON_INTERNAL_ERROR if the parser somehow ended into an invalid * internal state. */ grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader); /* Call this function to initialize the reader structure. */ void grpc_json_reader_init(grpc_json_reader *reader, grpc_json_reader_vtable *vtable, void *userdata); /* You may call this from the read_char callback if you don't know where is the * end of your input stream, and you'd like the json reader to hint you that it * has completed reading its input, so you can return an EOF to it. Note that * there might still be trailing whitespaces after that point. */ int grpc_json_reader_is_complete(grpc_json_reader *reader); #endif /* GRPC_CORE_LIB_JSON_JSON_READER_H */ grpc-1.3.2/src/core/lib/json/json_string.c000066400000000000000000000303531310511640000204040ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include "src/core/lib/json/json.h" #include "src/core/lib/json/json_reader.h" #include "src/core/lib/json/json_writer.h" /* The json reader will construct a bunch of grpc_json objects and * link them all up together in a tree-like structure that will represent * the json data in memory. * * It also uses its own input as a scratchpad to store all of the decoded, * unescaped strings. So we need to keep track of all these pointers in * that opaque structure the reader will carry for us. * * Note that this works because the act of parsing json always reduces its * input size, and never expands it. */ typedef struct { grpc_json *top; grpc_json *current_container; grpc_json *current_value; uint8_t *input; uint8_t *key; uint8_t *string; uint8_t *string_ptr; size_t remaining_input; } json_reader_userdata; /* This json writer will put everything in a big string. * The point is that we allocate that string in chunks of 256 bytes. */ typedef struct { char *output; size_t free_space; size_t string_len; size_t allocated; } json_writer_userdata; /* This function checks if there's enough space left in the output buffer, * and will enlarge it if necessary. We're only allocating chunks of 256 * bytes at a time (or multiples thereof). */ static void json_writer_output_check(void *userdata, size_t needed) { json_writer_userdata *state = userdata; if (state->free_space >= needed) return; needed -= state->free_space; /* Round up by 256 bytes. */ needed = (needed + 0xff) & ~0xffU; state->output = gpr_realloc(state->output, state->allocated + needed); state->free_space += needed; state->allocated += needed; } /* These are needed by the writer's implementation. */ static void json_writer_output_char(void *userdata, char c) { json_writer_userdata *state = userdata; json_writer_output_check(userdata, 1); state->output[state->string_len++] = c; state->free_space--; } static void json_writer_output_string_with_len(void *userdata, const char *str, size_t len) { json_writer_userdata *state = userdata; json_writer_output_check(userdata, len); memcpy(state->output + state->string_len, str, len); state->string_len += len; state->free_space -= len; } static void json_writer_output_string(void *userdata, const char *str) { size_t len = strlen(str); json_writer_output_string_with_len(userdata, str, len); } /* The reader asks us to clear our scratchpad. In our case, we'll simply mark * the end of the current string, and advance our output pointer. */ static void json_reader_string_clear(void *userdata) { json_reader_userdata *state = userdata; if (state->string) { GPR_ASSERT(state->string_ptr < state->input); *state->string_ptr++ = 0; } state->string = state->string_ptr; } static void json_reader_string_add_char(void *userdata, uint32_t c) { json_reader_userdata *state = userdata; GPR_ASSERT(state->string_ptr < state->input); GPR_ASSERT(c <= 0xff); *state->string_ptr++ = (uint8_t)c; } /* We are converting a UTF-32 character into UTF-8 here, * as described by RFC3629. */ static void json_reader_string_add_utf32(void *userdata, uint32_t c) { if (c <= 0x7f) { json_reader_string_add_char(userdata, c); } else if (c <= 0x7ff) { uint32_t b1 = 0xc0 | ((c >> 6) & 0x1f); uint32_t b2 = 0x80 | (c & 0x3f); json_reader_string_add_char(userdata, b1); json_reader_string_add_char(userdata, b2); } else if (c <= 0xffff) { uint32_t b1 = 0xe0 | ((c >> 12) & 0x0f); uint32_t b2 = 0x80 | ((c >> 6) & 0x3f); uint32_t b3 = 0x80 | (c & 0x3f); json_reader_string_add_char(userdata, b1); json_reader_string_add_char(userdata, b2); json_reader_string_add_char(userdata, b3); } else if (c <= 0x1fffff) { uint32_t b1 = 0xf0 | ((c >> 18) & 0x07); uint32_t b2 = 0x80 | ((c >> 12) & 0x3f); uint32_t b3 = 0x80 | ((c >> 6) & 0x3f); uint32_t b4 = 0x80 | (c & 0x3f); json_reader_string_add_char(userdata, b1); json_reader_string_add_char(userdata, b2); json_reader_string_add_char(userdata, b3); json_reader_string_add_char(userdata, b4); } } /* We consider that the input may be a zero-terminated string. So we * can end up hitting eof before the end of the alleged string length. */ static uint32_t json_reader_read_char(void *userdata) { uint32_t r; json_reader_userdata *state = userdata; if (state->remaining_input == 0) return GRPC_JSON_READ_CHAR_EOF; r = *state->input++; state->remaining_input--; if (r == 0) { state->remaining_input = 0; return GRPC_JSON_READ_CHAR_EOF; } return r; } /* Helper function to create a new grpc_json object and link it into * our tree-in-progress inside our opaque structure. */ static grpc_json *json_create_and_link(void *userdata, grpc_json_type type) { json_reader_userdata *state = userdata; grpc_json *json = grpc_json_create(type); json->parent = state->current_container; json->prev = state->current_value; state->current_value = json; if (json->prev) { json->prev->next = json; } if (json->parent) { if (!json->parent->child) { json->parent->child = json; } if (json->parent->type == GRPC_JSON_OBJECT) { json->key = (char *)state->key; } } if (!state->top) { state->top = json; } return json; } static void json_reader_container_begins(void *userdata, grpc_json_type type) { json_reader_userdata *state = userdata; grpc_json *container; GPR_ASSERT(type == GRPC_JSON_ARRAY || type == GRPC_JSON_OBJECT); container = json_create_and_link(userdata, type); state->current_container = container; state->current_value = NULL; } /* It's important to remember that the reader is mostly stateless, so it * isn't trying to remember what the container was prior the one that just * ends. Since we're keeping track of these for our own purpose, we are * able to return that information back, which is useful for it to validate * the input json stream. * * Also note that if we're at the top of the tree, and the last container * ends, we have to return GRPC_JSON_TOP_LEVEL. */ static grpc_json_type json_reader_container_ends(void *userdata) { grpc_json_type container_type = GRPC_JSON_TOP_LEVEL; json_reader_userdata *state = userdata; GPR_ASSERT(state->current_container); state->current_value = state->current_container; state->current_container = state->current_container->parent; if (state->current_container) { container_type = state->current_container->type; } return container_type; } /* The next 3 functions basically are the reader asking us to use our string * scratchpad for one of these 3 purposes. * * Note that in the set_number case, we're not going to try interpreting it. * We'll keep it as a string, and leave it to the caller to evaluate it. */ static void json_reader_set_key(void *userdata) { json_reader_userdata *state = userdata; state->key = state->string; } static void json_reader_set_string(void *userdata) { json_reader_userdata *state = userdata; grpc_json *json = json_create_and_link(userdata, GRPC_JSON_STRING); json->value = (char *)state->string; } static int json_reader_set_number(void *userdata) { json_reader_userdata *state = userdata; grpc_json *json = json_create_and_link(userdata, GRPC_JSON_NUMBER); json->value = (char *)state->string; return 1; } /* The object types true, false and null are self-sufficient, and don't need * any more information beside their type. */ static void json_reader_set_true(void *userdata) { json_create_and_link(userdata, GRPC_JSON_TRUE); } static void json_reader_set_false(void *userdata) { json_create_and_link(userdata, GRPC_JSON_FALSE); } static void json_reader_set_null(void *userdata) { json_create_and_link(userdata, GRPC_JSON_NULL); } static grpc_json_reader_vtable reader_vtable = { json_reader_string_clear, json_reader_string_add_char, json_reader_string_add_utf32, json_reader_read_char, json_reader_container_begins, json_reader_container_ends, json_reader_set_key, json_reader_set_string, json_reader_set_number, json_reader_set_true, json_reader_set_false, json_reader_set_null}; /* And finally, let's define our public API. */ grpc_json *grpc_json_parse_string_with_len(char *input, size_t size) { grpc_json_reader reader; json_reader_userdata state; grpc_json *json = NULL; grpc_json_reader_status status; if (!input) return NULL; state.top = state.current_container = state.current_value = NULL; state.string = state.key = NULL; state.string_ptr = state.input = (uint8_t *)input; state.remaining_input = size; grpc_json_reader_init(&reader, &reader_vtable, &state); status = grpc_json_reader_run(&reader); json = state.top; if ((status != GRPC_JSON_DONE) && json) { grpc_json_destroy(json); json = NULL; } return json; } #define UNBOUND_JSON_STRING_LENGTH 0x7fffffff grpc_json *grpc_json_parse_string(char *input) { return grpc_json_parse_string_with_len(input, UNBOUND_JSON_STRING_LENGTH); } static void json_dump_recursive(grpc_json_writer *writer, grpc_json *json, int in_object) { while (json) { if (in_object) grpc_json_writer_object_key(writer, json->key); switch (json->type) { case GRPC_JSON_OBJECT: case GRPC_JSON_ARRAY: grpc_json_writer_container_begins(writer, json->type); if (json->child) json_dump_recursive(writer, json->child, json->type == GRPC_JSON_OBJECT); grpc_json_writer_container_ends(writer, json->type); break; case GRPC_JSON_STRING: grpc_json_writer_value_string(writer, json->value); break; case GRPC_JSON_NUMBER: grpc_json_writer_value_raw(writer, json->value); break; case GRPC_JSON_TRUE: grpc_json_writer_value_raw_with_len(writer, "true", 4); break; case GRPC_JSON_FALSE: grpc_json_writer_value_raw_with_len(writer, "false", 5); break; case GRPC_JSON_NULL: grpc_json_writer_value_raw_with_len(writer, "null", 4); break; default: GPR_UNREACHABLE_CODE(abort()); } json = json->next; } } static grpc_json_writer_vtable writer_vtable = { json_writer_output_char, json_writer_output_string, json_writer_output_string_with_len}; char *grpc_json_dump_to_string(grpc_json *json, int indent) { grpc_json_writer writer; json_writer_userdata state; state.output = NULL; state.free_space = state.string_len = state.allocated = 0; grpc_json_writer_init(&writer, indent, &writer_vtable, &state); json_dump_recursive(&writer, json, 0); json_writer_output_char(&state, 0); return state.output; } grpc-1.3.2/src/core/lib/json/json_writer.c000066400000000000000000000222671310511640000204170ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include "src/core/lib/json/json_writer.h" static void json_writer_output_char(grpc_json_writer *writer, char c) { writer->vtable->output_char(writer->userdata, c); } static void json_writer_output_string(grpc_json_writer *writer, const char *str) { writer->vtable->output_string(writer->userdata, str); } static void json_writer_output_string_with_len(grpc_json_writer *writer, const char *str, size_t len) { writer->vtable->output_string_with_len(writer->userdata, str, len); } void grpc_json_writer_init(grpc_json_writer *writer, int indent, grpc_json_writer_vtable *vtable, void *userdata) { memset(writer, 0, sizeof(*writer)); writer->container_empty = 1; writer->indent = indent; writer->vtable = vtable; writer->userdata = userdata; } static void json_writer_output_indent(grpc_json_writer *writer) { static const char spacesstr[] = " " " " " " " "; unsigned spaces = (unsigned)(writer->depth * writer->indent); if (writer->indent == 0) return; if (writer->got_key) { json_writer_output_char(writer, ' '); return; } while (spaces >= (sizeof(spacesstr) - 1)) { json_writer_output_string_with_len(writer, spacesstr, sizeof(spacesstr) - 1); spaces -= (unsigned)(sizeof(spacesstr) - 1); } if (spaces == 0) return; json_writer_output_string_with_len( writer, spacesstr + sizeof(spacesstr) - 1 - spaces, spaces); } static void json_writer_value_end(grpc_json_writer *writer) { if (writer->container_empty) { writer->container_empty = 0; if ((writer->indent == 0) || (writer->depth == 0)) return; json_writer_output_char(writer, '\n'); } else { json_writer_output_char(writer, ','); if (writer->indent == 0) return; json_writer_output_char(writer, '\n'); } } static void json_writer_escape_utf16(grpc_json_writer *writer, uint16_t utf16) { static const char hex[] = "0123456789abcdef"; json_writer_output_string_with_len(writer, "\\u", 2); json_writer_output_char(writer, hex[(utf16 >> 12) & 0x0f]); json_writer_output_char(writer, hex[(utf16 >> 8) & 0x0f]); json_writer_output_char(writer, hex[(utf16 >> 4) & 0x0f]); json_writer_output_char(writer, hex[(utf16)&0x0f]); } static void json_writer_escape_string(grpc_json_writer *writer, const char *string) { json_writer_output_char(writer, '"'); for (;;) { uint8_t c = (uint8_t)*string++; if (c == 0) { break; } else if ((c >= 32) && (c <= 126)) { if ((c == '\\') || (c == '"')) json_writer_output_char(writer, '\\'); json_writer_output_char(writer, (char)c); } else if ((c < 32) || (c == 127)) { switch (c) { case '\b': json_writer_output_string_with_len(writer, "\\b", 2); break; case '\f': json_writer_output_string_with_len(writer, "\\f", 2); break; case '\n': json_writer_output_string_with_len(writer, "\\n", 2); break; case '\r': json_writer_output_string_with_len(writer, "\\r", 2); break; case '\t': json_writer_output_string_with_len(writer, "\\t", 2); break; default: json_writer_escape_utf16(writer, c); break; } } else { uint32_t utf32 = 0; int extra = 0; int i; int valid = 1; if ((c & 0xe0) == 0xc0) { utf32 = c & 0x1f; extra = 1; } else if ((c & 0xf0) == 0xe0) { utf32 = c & 0x0f; extra = 2; } else if ((c & 0xf8) == 0xf0) { utf32 = c & 0x07; extra = 3; } else { break; } for (i = 0; i < extra; i++) { utf32 <<= 6; c = (uint8_t)(*string++); /* Breaks out and bail on any invalid UTF-8 sequence, including \0. */ if ((c & 0xc0) != 0x80) { valid = 0; break; } utf32 |= c & 0x3f; } if (!valid) break; /* The range 0xd800 - 0xdfff is reserved by the surrogates ad vitam. * Any other range is technically reserved for future usage, so if we * don't want the software to break in the future, we have to allow * anything else. The first non-unicode character is 0x110000. */ if (((utf32 >= 0xd800) && (utf32 <= 0xdfff)) || (utf32 >= 0x110000)) break; if (utf32 >= 0x10000) { /* If utf32 contains a character that is above 0xffff, it needs to be * broken down into a utf-16 surrogate pair. A surrogate pair is first * a high surrogate, followed by a low surrogate. Each surrogate holds * 10 bits of usable data, thus allowing a total of 20 bits of data. * The high surrogate marker is 0xd800, while the low surrogate marker * is 0xdc00. The low 10 bits of each will be the usable data. * * After re-combining the 20 bits of data, one has to add 0x10000 to * the resulting value, in order to obtain the original character. * This is obviously because the range 0x0000 - 0xffff can be written * without any special trick. * * Since 0x10ffff is the highest allowed character, we're working in * the range 0x00000 - 0xfffff after we decrement it by 0x10000. * That range is exactly 20 bits. */ utf32 -= 0x10000; json_writer_escape_utf16(writer, (uint16_t)(0xd800 | (utf32 >> 10))); json_writer_escape_utf16(writer, (uint16_t)(0xdc00 | (utf32 & 0x3ff))); } else { json_writer_escape_utf16(writer, (uint16_t)utf32); } } } json_writer_output_char(writer, '"'); } void grpc_json_writer_container_begins(grpc_json_writer *writer, grpc_json_type type) { if (!writer->got_key) json_writer_value_end(writer); json_writer_output_indent(writer); json_writer_output_char(writer, type == GRPC_JSON_OBJECT ? '{' : '['); writer->container_empty = 1; writer->got_key = 0; writer->depth++; } void grpc_json_writer_container_ends(grpc_json_writer *writer, grpc_json_type type) { if (writer->indent && !writer->container_empty) json_writer_output_char(writer, '\n'); writer->depth--; if (!writer->container_empty) json_writer_output_indent(writer); json_writer_output_char(writer, type == GRPC_JSON_OBJECT ? '}' : ']'); writer->container_empty = 0; writer->got_key = 0; } void grpc_json_writer_object_key(grpc_json_writer *writer, const char *string) { json_writer_value_end(writer); json_writer_output_indent(writer); json_writer_escape_string(writer, string); json_writer_output_char(writer, ':'); writer->got_key = 1; } void grpc_json_writer_value_raw(grpc_json_writer *writer, const char *string) { if (!writer->got_key) json_writer_value_end(writer); json_writer_output_indent(writer); json_writer_output_string(writer, string); writer->got_key = 0; } void grpc_json_writer_value_raw_with_len(grpc_json_writer *writer, const char *string, size_t len) { if (!writer->got_key) json_writer_value_end(writer); json_writer_output_indent(writer); json_writer_output_string_with_len(writer, string, len); writer->got_key = 0; } void grpc_json_writer_value_string(grpc_json_writer *writer, const char *string) { if (!writer->got_key) json_writer_value_end(writer); json_writer_output_indent(writer); json_writer_escape_string(writer, string); writer->got_key = 0; } grpc-1.3.2/src/core/lib/json/json_writer.h000066400000000000000000000103721310511640000204160ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* The idea of the writer is basically symmetrical of the reader. While the * reader emits various calls to your code, the writer takes basically the * same calls and emit json out of it. It doesn't try to make any check on * the order of the calls you do on it. Meaning you can theorically force * it to generate invalid json. * * Also, unlike the reader, the writer expects UTF-8 encoded input strings. * These strings will be UTF-8 validated, and any invalid character will * cut the conversion short, before any invalid UTF-8 sequence, thus forming * a valid UTF-8 string overall. */ #ifndef GRPC_CORE_LIB_JSON_JSON_WRITER_H #define GRPC_CORE_LIB_JSON_JSON_WRITER_H #include #include "src/core/lib/json/json_common.h" typedef struct grpc_json_writer_vtable { /* Adds a character to the output stream. */ void (*output_char)(void *userdata, char); /* Adds a zero-terminated string to the output stream. */ void (*output_string)(void *userdata, const char *str); /* Adds a fixed-length string to the output stream. */ void (*output_string_with_len)(void *userdata, const char *str, size_t len); } grpc_json_writer_vtable; typedef struct grpc_json_writer { void *userdata; grpc_json_writer_vtable *vtable; int indent; int depth; int container_empty; int got_key; } grpc_json_writer; /* Call this to initialize your writer structure. The indent parameter is * specifying the number of spaces to use for indenting the output. If you * use indent=0, then the output will not have any newlines either, thus * emitting a condensed json output. */ void grpc_json_writer_init(grpc_json_writer *writer, int indent, grpc_json_writer_vtable *vtable, void *userdata); /* Signals the beginning of a container. */ void grpc_json_writer_container_begins(grpc_json_writer *writer, grpc_json_type type); /* Signals the end of a container. */ void grpc_json_writer_container_ends(grpc_json_writer *writer, grpc_json_type type); /* Writes down an object key for the next value. */ void grpc_json_writer_object_key(grpc_json_writer *writer, const char *string); /* Sets a raw value. Useful for numbers. */ void grpc_json_writer_value_raw(grpc_json_writer *writer, const char *string); /* Sets a raw value with its length. Useful for values like true or false. */ void grpc_json_writer_value_raw_with_len(grpc_json_writer *writer, const char *string, size_t len); /* Sets a string value. It'll be escaped, and utf-8 validated. */ void grpc_json_writer_value_string(grpc_json_writer *writer, const char *string); #endif /* GRPC_CORE_LIB_JSON_JSON_WRITER_H */ grpc-1.3.2/src/core/lib/profiling/000077500000000000000000000000001310511640000167155ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/profiling/basic_timers.c000066400000000000000000000205041310511640000215260ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifdef GRPC_BASIC_PROFILER #include "src/core/lib/profiling/timers.h" #include #include #include #include #include #include #include #include "src/core/lib/support/env.h" typedef enum { BEGIN = '{', END = '}', MARK = '.' } marker_type; typedef struct gpr_timer_entry { gpr_timespec tm; const char *tagstr; const char *file; short line; char type; uint8_t important; int thd; } gpr_timer_entry; #define MAX_COUNT 1000000 typedef struct gpr_timer_log { size_t num_entries; struct gpr_timer_log *next; struct gpr_timer_log *prev; gpr_timer_entry log[MAX_COUNT]; } gpr_timer_log; typedef struct gpr_timer_log_list { gpr_timer_log *head; /* valid iff head!=NULL */ gpr_timer_log *tail; } gpr_timer_log_list; static __thread gpr_timer_log *g_thread_log; static gpr_once g_once_init = GPR_ONCE_INIT; static FILE *output_file; static const char *output_filename_or_null = NULL; static pthread_mutex_t g_mu; static pthread_cond_t g_cv; static gpr_timer_log_list g_in_progress_logs; static gpr_timer_log_list g_done_logs; static int g_shutdown; static gpr_thd_id g_writing_thread; static __thread int g_thread_id; static int g_next_thread_id; static int g_writing_enabled = 1; static const char *output_filename() { if (output_filename_or_null == NULL) { output_filename_or_null = gpr_getenv("LATENCY_TRACE"); if (output_filename_or_null == NULL || strlen(output_filename_or_null) == 0) { output_filename_or_null = "latency_trace.txt"; } } return output_filename_or_null; } static int timer_log_push_back(gpr_timer_log_list *list, gpr_timer_log *log) { if (list->head == NULL) { list->head = list->tail = log; log->next = log->prev = NULL; return 1; } else { log->prev = list->tail; log->next = NULL; list->tail->next = log; list->tail = log; return 0; } } static gpr_timer_log *timer_log_pop_front(gpr_timer_log_list *list) { gpr_timer_log *out = list->head; if (out != NULL) { list->head = out->next; if (list->head != NULL) { list->head->prev = NULL; } else { list->tail = NULL; } } return out; } static void timer_log_remove(gpr_timer_log_list *list, gpr_timer_log *log) { if (log->prev == NULL) { list->head = log->next; if (list->head != NULL) { list->head->prev = NULL; } } else { log->prev->next = log->next; } if (log->next == NULL) { list->tail = log->prev; if (list->tail != NULL) { list->tail->next = NULL; } } else { log->next->prev = log->prev; } } static void write_log(gpr_timer_log *log) { size_t i; if (output_file == NULL) { output_file = fopen(output_filename(), "w"); } for (i = 0; i < log->num_entries; i++) { gpr_timer_entry *entry = &(log->log[i]); if (gpr_time_cmp(entry->tm, gpr_time_0(entry->tm.clock_type)) < 0) { entry->tm = gpr_time_0(entry->tm.clock_type); } fprintf(output_file, "{\"t\": %" PRId64 ".%09d, \"thd\": \"%d\", \"type\": \"%c\", \"tag\": " "\"%s\", \"file\": \"%s\", \"line\": %d, \"imp\": %d}\n", entry->tm.tv_sec, entry->tm.tv_nsec, entry->thd, entry->type, entry->tagstr, entry->file, entry->line, entry->important); } } static void writing_thread(void *unused) { gpr_timer_log *log; pthread_mutex_lock(&g_mu); for (;;) { while ((log = timer_log_pop_front(&g_done_logs)) == NULL && !g_shutdown) { pthread_cond_wait(&g_cv, &g_mu); } if (log != NULL) { pthread_mutex_unlock(&g_mu); write_log(log); free(log); pthread_mutex_lock(&g_mu); } if (g_shutdown) { pthread_mutex_unlock(&g_mu); return; } } } static void flush_logs(gpr_timer_log_list *list) { gpr_timer_log *log; while ((log = timer_log_pop_front(list)) != NULL) { write_log(log); free(log); } } static void finish_writing(void) { pthread_mutex_lock(&g_mu); g_shutdown = 1; pthread_cond_signal(&g_cv); pthread_mutex_unlock(&g_mu); gpr_thd_join(g_writing_thread); gpr_log(GPR_INFO, "flushing logs"); pthread_mutex_lock(&g_mu); flush_logs(&g_done_logs); flush_logs(&g_in_progress_logs); pthread_mutex_unlock(&g_mu); if (output_file) { fclose(output_file); } } void gpr_timers_set_log_filename(const char *filename) { output_filename_or_null = filename; } static void init_output() { gpr_thd_options options = gpr_thd_options_default(); gpr_thd_options_set_joinable(&options); GPR_ASSERT(gpr_thd_new(&g_writing_thread, writing_thread, NULL, &options)); atexit(finish_writing); } static void rotate_log() { /* Using malloc here, as this code could end up being called by gpr_malloc */ gpr_timer_log *new = malloc(sizeof(*new)); gpr_once_init(&g_once_init, init_output); new->num_entries = 0; pthread_mutex_lock(&g_mu); if (g_thread_log != NULL) { timer_log_remove(&g_in_progress_logs, g_thread_log); if (timer_log_push_back(&g_done_logs, g_thread_log)) { pthread_cond_signal(&g_cv); } } else { g_thread_id = g_next_thread_id++; } timer_log_push_back(&g_in_progress_logs, new); pthread_mutex_unlock(&g_mu); g_thread_log = new; } static void gpr_timers_log_add(const char *tagstr, marker_type type, int important, const char *file, int line) { gpr_timer_entry *entry; if (!g_writing_enabled) { return; } if (g_thread_log == NULL || g_thread_log->num_entries == MAX_COUNT) { rotate_log(); } entry = &g_thread_log->log[g_thread_log->num_entries++]; entry->tm = gpr_now(GPR_CLOCK_PRECISE); entry->tagstr = tagstr; entry->type = type; entry->file = file; entry->line = (short)line; entry->important = important != 0; entry->thd = g_thread_id; } /* Latency profiler API implementation. */ void gpr_timer_add_mark(const char *tagstr, int important, const char *file, int line) { gpr_timers_log_add(tagstr, MARK, important, file, line); } void gpr_timer_begin(const char *tagstr, int important, const char *file, int line) { gpr_timers_log_add(tagstr, BEGIN, important, file, line); } void gpr_timer_end(const char *tagstr, int important, const char *file, int line) { gpr_timers_log_add(tagstr, END, important, file, line); } void gpr_timer_set_enabled(int enabled) { g_writing_enabled = enabled; } /* Basic profiler specific API functions. */ void gpr_timers_global_init(void) {} void gpr_timers_global_destroy(void) {} #else /* !GRPC_BASIC_PROFILER */ void gpr_timers_global_init(void) {} void gpr_timers_global_destroy(void) {} void gpr_timers_set_log_filename(const char *filename) {} void gpr_timer_set_enabled(int enabled) {} #endif /* GRPC_BASIC_PROFILER */ grpc-1.3.2/src/core/lib/profiling/stap_probes.d000066400000000000000000000002231310511640000214000ustar00rootroot00000000000000provider _stap { probe add_mark(int tag); probe add_important_mark(int tag); probe timing_ns_begin(int tag); probe timing_ns_end(int tag); }; grpc-1.3.2/src/core/lib/profiling/stap_timers.c000066400000000000000000000046571310511640000214270ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifdef GRPC_STAP_PROFILER #include "src/core/lib/profiling/timers.h" #include /* Generated from src/core/profiling/stap_probes.d */ #include "src/core/lib/profiling/stap_probes.h" /* Latency profiler API implementation. */ void gpr_timer_add_mark(int tag, const char *tagstr, void *id, const char *file, int line) { _STAP_ADD_MARK(tag); } void gpr_timer_add_important_mark(int tag, const char *tagstr, void *id, const char *file, int line) { _STAP_ADD_IMPORTANT_MARK(tag); } void gpr_timer_begin(int tag, const char *tagstr, void *id, const char *file, int line) { _STAP_TIMING_NS_BEGIN(tag); } void gpr_timer_end(int tag, const char *tagstr, void *id, const char *file, int line) { _STAP_TIMING_NS_END(tag); } #endif /* GRPC_STAP_PROFILER */ grpc-1.3.2/src/core/lib/profiling/timers.h000066400000000000000000000076301310511640000203770ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_PROFILING_TIMERS_H #define GRPC_CORE_LIB_PROFILING_TIMERS_H #ifdef __cplusplus extern "C" { #endif void gpr_timers_global_init(void); void gpr_timers_global_destroy(void); void gpr_timer_add_mark(const char *tagstr, int important, const char *file, int line); void gpr_timer_begin(const char *tagstr, int important, const char *file, int line); void gpr_timer_end(const char *tagstr, int important, const char *file, int line); void gpr_timers_set_log_filename(const char *filename); void gpr_timer_set_enabled(int enabled); #if !(defined(GRPC_STAP_PROFILER) + defined(GRPC_BASIC_PROFILER)) /* No profiling. No-op all the things. */ #define GPR_TIMER_MARK(tag, important) \ do { \ } while (0) #define GPR_TIMER_BEGIN(tag, important) \ do { \ } while (0) #define GPR_TIMER_END(tag, important) \ do { \ } while (0) #else /* at least one profiler requested... */ /* ... hopefully only one. */ #if defined(GRPC_STAP_PROFILER) && defined(GRPC_BASIC_PROFILER) #error "GRPC_STAP_PROFILER and GRPC_BASIC_PROFILER are mutually exclusive." #endif /* Generic profiling interface. */ #define GPR_TIMER_MARK(tag, important) \ gpr_timer_add_mark(tag, important, __FILE__, __LINE__); #define GPR_TIMER_BEGIN(tag, important) \ gpr_timer_begin(tag, important, __FILE__, __LINE__); #define GPR_TIMER_END(tag, important) \ gpr_timer_end(tag, important, __FILE__, __LINE__); #ifdef GRPC_STAP_PROFILER /* Empty placeholder for now. */ #endif /* GRPC_STAP_PROFILER */ #ifdef GRPC_BASIC_PROFILER /* Empty placeholder for now. */ #endif /* GRPC_BASIC_PROFILER */ #endif /* at least one profiler requested. */ #ifdef __cplusplus } #if (defined(GRPC_STAP_PROFILER) + defined(GRPC_BASIC_PROFILER)) namespace grpc { class ProfileScope { public: ProfileScope(const char *desc, bool important) : desc_(desc) { GPR_TIMER_BEGIN(desc_, important ? 1 : 0); } ~ProfileScope() { GPR_TIMER_END(desc_, 0); } private: const char *const desc_; }; } #define GPR_TIMER_SCOPE(tag, important) \ ::grpc::ProfileScope _profile_scope_##__LINE__((tag), (important)) #else #define GPR_TIMER_SCOPE(tag, important) \ do { \ } while (false) #endif #endif #endif /* GRPC_CORE_LIB_PROFILING_TIMERS_H */ grpc-1.3.2/src/core/lib/security/000077500000000000000000000000001310511640000165735ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/security/context/000077500000000000000000000000001310511640000202575ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/security/context/security_context.c000066400000000000000000000312251310511640000240410ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/support/string.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/call.h" #include #include #include #include /* --- grpc_call --- */ grpc_call_error grpc_call_set_credentials(grpc_call *call, grpc_call_credentials *creds) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_client_security_context *ctx = NULL; GRPC_API_TRACE("grpc_call_set_credentials(call=%p, creds=%p)", 2, (call, creds)); if (!grpc_call_is_client(call)) { gpr_log(GPR_ERROR, "Method is client-side only."); return GRPC_CALL_ERROR_NOT_ON_SERVER; } ctx = (grpc_client_security_context *)grpc_call_context_get( call, GRPC_CONTEXT_SECURITY); if (ctx == NULL) { ctx = grpc_client_security_context_create(); ctx->creds = grpc_call_credentials_ref(creds); grpc_call_context_set(call, GRPC_CONTEXT_SECURITY, ctx, grpc_client_security_context_destroy); } else { grpc_call_credentials_unref(&exec_ctx, ctx->creds); ctx->creds = grpc_call_credentials_ref(creds); } grpc_exec_ctx_finish(&exec_ctx); return GRPC_CALL_OK; } grpc_auth_context *grpc_call_auth_context(grpc_call *call) { void *sec_ctx = grpc_call_context_get(call, GRPC_CONTEXT_SECURITY); GRPC_API_TRACE("grpc_call_auth_context(call=%p)", 1, (call)); if (sec_ctx == NULL) return NULL; return grpc_call_is_client(call) ? GRPC_AUTH_CONTEXT_REF( ((grpc_client_security_context *)sec_ctx)->auth_context, "grpc_call_auth_context client") : GRPC_AUTH_CONTEXT_REF( ((grpc_server_security_context *)sec_ctx)->auth_context, "grpc_call_auth_context server"); } void grpc_auth_context_release(grpc_auth_context *context) { GRPC_API_TRACE("grpc_auth_context_release(context=%p)", 1, (context)); GRPC_AUTH_CONTEXT_UNREF(context, "grpc_auth_context_unref"); } /* --- grpc_client_security_context --- */ grpc_client_security_context *grpc_client_security_context_create(void) { return gpr_zalloc(sizeof(grpc_client_security_context)); } void grpc_client_security_context_destroy(void *ctx) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_client_security_context *c = (grpc_client_security_context *)ctx; grpc_call_credentials_unref(&exec_ctx, c->creds); GRPC_AUTH_CONTEXT_UNREF(c->auth_context, "client_security_context"); if (c->extension.instance != NULL && c->extension.destroy != NULL) { c->extension.destroy(c->extension.instance); } gpr_free(ctx); grpc_exec_ctx_finish(&exec_ctx); } /* --- grpc_server_security_context --- */ grpc_server_security_context *grpc_server_security_context_create(void) { return gpr_zalloc(sizeof(grpc_server_security_context)); } void grpc_server_security_context_destroy(void *ctx) { grpc_server_security_context *c = (grpc_server_security_context *)ctx; GRPC_AUTH_CONTEXT_UNREF(c->auth_context, "server_security_context"); if (c->extension.instance != NULL && c->extension.destroy != NULL) { c->extension.destroy(c->extension.instance); } gpr_free(ctx); } /* --- grpc_auth_context --- */ static grpc_auth_property_iterator empty_iterator = {NULL, 0, NULL}; grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained) { grpc_auth_context *ctx = gpr_zalloc(sizeof(grpc_auth_context)); gpr_ref_init(&ctx->refcount, 1); if (chained != NULL) { ctx->chained = GRPC_AUTH_CONTEXT_REF(chained, "chained"); ctx->peer_identity_property_name = ctx->chained->peer_identity_property_name; } return ctx; } #ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *ctx, const char *file, int line, const char *reason) { if (ctx == NULL) return NULL; gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "AUTH_CONTEXT:%p ref %d -> %d %s", ctx, (int)ctx->refcount.count, (int)ctx->refcount.count + 1, reason); #else grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *ctx) { if (ctx == NULL) return NULL; #endif gpr_ref(&ctx->refcount); return ctx; } #ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG void grpc_auth_context_unref(grpc_auth_context *ctx, const char *file, int line, const char *reason) { if (ctx == NULL) return; gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "AUTH_CONTEXT:%p unref %d -> %d %s", ctx, (int)ctx->refcount.count, (int)ctx->refcount.count - 1, reason); #else void grpc_auth_context_unref(grpc_auth_context *ctx) { if (ctx == NULL) return; #endif if (gpr_unref(&ctx->refcount)) { size_t i; GRPC_AUTH_CONTEXT_UNREF(ctx->chained, "chained"); if (ctx->properties.array != NULL) { for (i = 0; i < ctx->properties.count; i++) { grpc_auth_property_reset(&ctx->properties.array[i]); } gpr_free(ctx->properties.array); } gpr_free(ctx); } } const char *grpc_auth_context_peer_identity_property_name( const grpc_auth_context *ctx) { GRPC_API_TRACE("grpc_auth_context_peer_identity_property_name(ctx=%p)", 1, (ctx)); return ctx->peer_identity_property_name; } int grpc_auth_context_set_peer_identity_property_name(grpc_auth_context *ctx, const char *name) { grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(ctx, name); const grpc_auth_property *prop = grpc_auth_property_iterator_next(&it); GRPC_API_TRACE( "grpc_auth_context_set_peer_identity_property_name(ctx=%p, name=%s)", 2, (ctx, name)); if (prop == NULL) { gpr_log(GPR_ERROR, "Property name %s not found in auth context.", name != NULL ? name : "NULL"); return 0; } ctx->peer_identity_property_name = prop->name; return 1; } int grpc_auth_context_peer_is_authenticated(const grpc_auth_context *ctx) { GRPC_API_TRACE("grpc_auth_context_peer_is_authenticated(ctx=%p)", 1, (ctx)); return ctx->peer_identity_property_name == NULL ? 0 : 1; } grpc_auth_property_iterator grpc_auth_context_property_iterator( const grpc_auth_context *ctx) { grpc_auth_property_iterator it = empty_iterator; GRPC_API_TRACE("grpc_auth_context_property_iterator(ctx=%p)", 1, (ctx)); if (ctx == NULL) return it; it.ctx = ctx; return it; } const grpc_auth_property *grpc_auth_property_iterator_next( grpc_auth_property_iterator *it) { GRPC_API_TRACE("grpc_auth_property_iterator_next(it=%p)", 1, (it)); if (it == NULL || it->ctx == NULL) return NULL; while (it->index == it->ctx->properties.count) { if (it->ctx->chained == NULL) return NULL; it->ctx = it->ctx->chained; it->index = 0; } if (it->name == NULL) { return &it->ctx->properties.array[it->index++]; } else { while (it->index < it->ctx->properties.count) { const grpc_auth_property *prop = &it->ctx->properties.array[it->index++]; GPR_ASSERT(prop->name != NULL); if (strcmp(it->name, prop->name) == 0) { return prop; } } /* We could not find the name, try another round. */ return grpc_auth_property_iterator_next(it); } } grpc_auth_property_iterator grpc_auth_context_find_properties_by_name( const grpc_auth_context *ctx, const char *name) { grpc_auth_property_iterator it = empty_iterator; GRPC_API_TRACE("grpc_auth_context_find_properties_by_name(ctx=%p, name=%s)", 2, (ctx, name)); if (ctx == NULL || name == NULL) return empty_iterator; it.ctx = ctx; it.name = name; return it; } grpc_auth_property_iterator grpc_auth_context_peer_identity( const grpc_auth_context *ctx) { GRPC_API_TRACE("grpc_auth_context_peer_identity(ctx=%p)", 1, (ctx)); if (ctx == NULL) return empty_iterator; return grpc_auth_context_find_properties_by_name( ctx, ctx->peer_identity_property_name); } static void ensure_auth_context_capacity(grpc_auth_context *ctx) { if (ctx->properties.count == ctx->properties.capacity) { ctx->properties.capacity = GPR_MAX(ctx->properties.capacity + 8, ctx->properties.capacity * 2); ctx->properties.array = gpr_realloc(ctx->properties.array, ctx->properties.capacity * sizeof(grpc_auth_property)); } } void grpc_auth_context_add_property(grpc_auth_context *ctx, const char *name, const char *value, size_t value_length) { grpc_auth_property *prop; GRPC_API_TRACE( "grpc_auth_context_add_property(ctx=%p, name=%s, value=%*.*s, " "value_length=%lu)", 6, (ctx, name, (int)value_length, (int)value_length, value, (unsigned long)value_length)); ensure_auth_context_capacity(ctx); prop = &ctx->properties.array[ctx->properties.count++]; prop->name = gpr_strdup(name); prop->value = gpr_malloc(value_length + 1); memcpy(prop->value, value, value_length); prop->value[value_length] = '\0'; prop->value_length = value_length; } void grpc_auth_context_add_cstring_property(grpc_auth_context *ctx, const char *name, const char *value) { grpc_auth_property *prop; GRPC_API_TRACE( "grpc_auth_context_add_cstring_property(ctx=%p, name=%s, value=%s)", 3, (ctx, name, value)); ensure_auth_context_capacity(ctx); prop = &ctx->properties.array[ctx->properties.count++]; prop->name = gpr_strdup(name); prop->value = gpr_strdup(value); prop->value_length = strlen(value); } void grpc_auth_property_reset(grpc_auth_property *property) { gpr_free(property->name); gpr_free(property->value); memset(property, 0, sizeof(grpc_auth_property)); } static void auth_context_pointer_arg_destroy(grpc_exec_ctx *exec_ctx, void *p) { GRPC_AUTH_CONTEXT_UNREF(p, "auth_context_pointer_arg"); } static void *auth_context_pointer_arg_copy(void *p) { return GRPC_AUTH_CONTEXT_REF(p, "auth_context_pointer_arg"); } static int auth_context_pointer_cmp(void *a, void *b) { return GPR_ICMP(a, b); } static const grpc_arg_pointer_vtable auth_context_pointer_vtable = { auth_context_pointer_arg_copy, auth_context_pointer_arg_destroy, auth_context_pointer_cmp}; grpc_arg grpc_auth_context_to_arg(grpc_auth_context *p) { grpc_arg arg; memset(&arg, 0, sizeof(grpc_arg)); arg.type = GRPC_ARG_POINTER; arg.key = GRPC_AUTH_CONTEXT_ARG; arg.value.pointer.p = p; arg.value.pointer.vtable = &auth_context_pointer_vtable; return arg; } grpc_auth_context *grpc_auth_context_from_arg(const grpc_arg *arg) { if (strcmp(arg->key, GRPC_AUTH_CONTEXT_ARG) != 0) return NULL; if (arg->type != GRPC_ARG_POINTER) { gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type, GRPC_AUTH_CONTEXT_ARG); return NULL; } return arg->value.pointer.p; } grpc_auth_context *grpc_find_auth_context_in_args( const grpc_channel_args *args) { size_t i; if (args == NULL) return NULL; for (i = 0; i < args->num_args; i++) { grpc_auth_context *p = grpc_auth_context_from_arg(&args->args[i]); if (p != NULL) return p; } return NULL; } grpc-1.3.2/src/core/lib/security/context/security_context.h000066400000000000000000000111321310511640000240410ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SECURITY_CONTEXT_SECURITY_CONTEXT_H #define GRPC_CORE_LIB_SECURITY_CONTEXT_SECURITY_CONTEXT_H #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/security/credentials/credentials.h" #ifdef __cplusplus extern "C" { #endif /* --- grpc_auth_context --- High level authentication context object. Can optionally be chained. */ /* Property names are always NULL terminated. */ typedef struct { grpc_auth_property *array; size_t count; size_t capacity; } grpc_auth_property_array; struct grpc_auth_context { struct grpc_auth_context *chained; grpc_auth_property_array properties; gpr_refcount refcount; const char *peer_identity_property_name; grpc_pollset *pollset; }; /* Creation. */ grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained); /* Refcounting. */ #ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG #define GRPC_AUTH_CONTEXT_REF(p, r) \ grpc_auth_context_ref((p), __FILE__, __LINE__, (r)) #define GRPC_AUTH_CONTEXT_UNREF(p, r) \ grpc_auth_context_unref((p), __FILE__, __LINE__, (r)) grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *policy, const char *file, int line, const char *reason); void grpc_auth_context_unref(grpc_auth_context *policy, const char *file, int line, const char *reason); #else #define GRPC_AUTH_CONTEXT_REF(p, r) grpc_auth_context_ref((p)) #define GRPC_AUTH_CONTEXT_UNREF(p, r) grpc_auth_context_unref((p)) grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *policy); void grpc_auth_context_unref(grpc_auth_context *policy); #endif void grpc_auth_property_reset(grpc_auth_property *property); /* --- grpc_security_context_extension --- Extension to the security context that may be set in a filter and accessed later by a higher level method on a grpc_call object. */ typedef struct { void *instance; void (*destroy)(void *); } grpc_security_context_extension; /* --- grpc_client_security_context --- Internal client-side security context. */ typedef struct { grpc_call_credentials *creds; grpc_auth_context *auth_context; grpc_security_context_extension extension; } grpc_client_security_context; grpc_client_security_context *grpc_client_security_context_create(void); void grpc_client_security_context_destroy(void *ctx); /* --- grpc_server_security_context --- Internal server-side security context. */ typedef struct { grpc_auth_context *auth_context; grpc_security_context_extension extension; } grpc_server_security_context; grpc_server_security_context *grpc_server_security_context_create(void); void grpc_server_security_context_destroy(void *ctx); /* --- Channel args for auth context --- */ #define GRPC_AUTH_CONTEXT_ARG "grpc.auth_context" grpc_arg grpc_auth_context_to_arg(grpc_auth_context *c); grpc_auth_context *grpc_auth_context_from_arg(const grpc_arg *arg); grpc_auth_context *grpc_find_auth_context_in_args( const grpc_channel_args *args); #ifdef __cplusplus } #endif #endif /* GRPC_CORE_LIB_SECURITY_CONTEXT_SECURITY_CONTEXT_H */ grpc-1.3.2/src/core/lib/security/credentials/000077500000000000000000000000001310511640000210705ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/security/credentials/composite/000077500000000000000000000000001310511640000230725ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/security/credentials/composite/composite_credentials.c000066400000000000000000000256461310511640000276320ustar00rootroot00000000000000/* * * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/security/credentials/composite/composite_credentials.h" #include #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/surface/api_trace.h" #include #include #include /* -- Composite call credentials. -- */ typedef struct { grpc_composite_call_credentials *composite_creds; size_t creds_index; grpc_credentials_md_store *md_elems; grpc_auth_metadata_context auth_md_context; void *user_data; grpc_polling_entity *pollent; grpc_credentials_metadata_cb cb; } grpc_composite_call_credentials_metadata_context; static void composite_call_destruct(grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds) { grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds; size_t i; for (i = 0; i < c->inner.num_creds; i++) { grpc_call_credentials_unref(exec_ctx, c->inner.creds_array[i]); } gpr_free(c->inner.creds_array); } static void composite_call_md_context_destroy( grpc_exec_ctx *exec_ctx, grpc_composite_call_credentials_metadata_context *ctx) { grpc_credentials_md_store_unref(exec_ctx, ctx->md_elems); gpr_free(ctx); } static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems, size_t num_md, grpc_credentials_status status, const char *error_details) { grpc_composite_call_credentials_metadata_context *ctx = (grpc_composite_call_credentials_metadata_context *)user_data; if (status != GRPC_CREDENTIALS_OK) { ctx->cb(exec_ctx, ctx->user_data, NULL, 0, status, error_details); return; } /* Copy the metadata in the context. */ if (num_md > 0) { size_t i; for (i = 0; i < num_md; i++) { grpc_credentials_md_store_add(ctx->md_elems, md_elems[i].key, md_elems[i].value); } } /* See if we need to get some more metadata. */ if (ctx->creds_index < ctx->composite_creds->inner.num_creds) { grpc_call_credentials *inner_creds = ctx->composite_creds->inner.creds_array[ctx->creds_index++]; grpc_call_credentials_get_request_metadata( exec_ctx, inner_creds, ctx->pollent, ctx->auth_md_context, composite_call_metadata_cb, ctx); return; } /* We're done!. */ ctx->cb(exec_ctx, ctx->user_data, ctx->md_elems->entries, ctx->md_elems->num_entries, GRPC_CREDENTIALS_OK, NULL); composite_call_md_context_destroy(exec_ctx, ctx); } static void composite_call_get_request_metadata( grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_polling_entity *pollent, grpc_auth_metadata_context auth_md_context, grpc_credentials_metadata_cb cb, void *user_data) { grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds; grpc_composite_call_credentials_metadata_context *ctx; ctx = gpr_zalloc(sizeof(grpc_composite_call_credentials_metadata_context)); ctx->auth_md_context = auth_md_context; ctx->user_data = user_data; ctx->cb = cb; ctx->composite_creds = c; ctx->pollent = pollent; ctx->md_elems = grpc_credentials_md_store_create(c->inner.num_creds); grpc_call_credentials_get_request_metadata( exec_ctx, c->inner.creds_array[ctx->creds_index++], ctx->pollent, auth_md_context, composite_call_metadata_cb, ctx); } static grpc_call_credentials_vtable composite_call_credentials_vtable = { composite_call_destruct, composite_call_get_request_metadata}; static grpc_call_credentials_array get_creds_array( grpc_call_credentials **creds_addr) { grpc_call_credentials_array result; grpc_call_credentials *creds = *creds_addr; result.creds_array = creds_addr; result.num_creds = 1; if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) { result = *grpc_composite_call_credentials_get_credentials(creds); } return result; } grpc_call_credentials *grpc_composite_call_credentials_create( grpc_call_credentials *creds1, grpc_call_credentials *creds2, void *reserved) { size_t i; size_t creds_array_byte_size; grpc_call_credentials_array creds1_array; grpc_call_credentials_array creds2_array; grpc_composite_call_credentials *c; GRPC_API_TRACE( "grpc_composite_call_credentials_create(creds1=%p, creds2=%p, " "reserved=%p)", 3, (creds1, creds2, reserved)); GPR_ASSERT(reserved == NULL); GPR_ASSERT(creds1 != NULL); GPR_ASSERT(creds2 != NULL); c = gpr_zalloc(sizeof(grpc_composite_call_credentials)); c->base.type = GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE; c->base.vtable = &composite_call_credentials_vtable; gpr_ref_init(&c->base.refcount, 1); creds1_array = get_creds_array(&creds1); creds2_array = get_creds_array(&creds2); c->inner.num_creds = creds1_array.num_creds + creds2_array.num_creds; creds_array_byte_size = c->inner.num_creds * sizeof(grpc_call_credentials *); c->inner.creds_array = gpr_zalloc(creds_array_byte_size); for (i = 0; i < creds1_array.num_creds; i++) { grpc_call_credentials *cur_creds = creds1_array.creds_array[i]; c->inner.creds_array[i] = grpc_call_credentials_ref(cur_creds); } for (i = 0; i < creds2_array.num_creds; i++) { grpc_call_credentials *cur_creds = creds2_array.creds_array[i]; c->inner.creds_array[i + creds1_array.num_creds] = grpc_call_credentials_ref(cur_creds); } return &c->base; } const grpc_call_credentials_array * grpc_composite_call_credentials_get_credentials(grpc_call_credentials *creds) { const grpc_composite_call_credentials *c = (const grpc_composite_call_credentials *)creds; GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0); return &c->inner; } grpc_call_credentials *grpc_credentials_contains_type( grpc_call_credentials *creds, const char *type, grpc_call_credentials **composite_creds) { size_t i; if (strcmp(creds->type, type) == 0) { if (composite_creds != NULL) *composite_creds = NULL; return creds; } else if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) { const grpc_call_credentials_array *inner_creds_array = grpc_composite_call_credentials_get_credentials(creds); for (i = 0; i < inner_creds_array->num_creds; i++) { if (strcmp(type, inner_creds_array->creds_array[i]->type) == 0) { if (composite_creds != NULL) *composite_creds = creds; return inner_creds_array->creds_array[i]; } } } return NULL; } /* -- Composite channel credentials. -- */ static void composite_channel_destruct(grpc_exec_ctx *exec_ctx, grpc_channel_credentials *creds) { grpc_composite_channel_credentials *c = (grpc_composite_channel_credentials *)creds; grpc_channel_credentials_unref(exec_ctx, c->inner_creds); grpc_call_credentials_unref(exec_ctx, c->call_creds); } static grpc_security_status composite_channel_create_security_connector( grpc_exec_ctx *exec_ctx, grpc_channel_credentials *creds, grpc_call_credentials *call_creds, const char *target, const grpc_channel_args *args, grpc_channel_security_connector **sc, grpc_channel_args **new_args) { grpc_composite_channel_credentials *c = (grpc_composite_channel_credentials *)creds; grpc_security_status status = GRPC_SECURITY_ERROR; GPR_ASSERT(c->inner_creds != NULL && c->call_creds != NULL && c->inner_creds->vtable != NULL && c->inner_creds->vtable->create_security_connector != NULL); /* If we are passed a call_creds, create a call composite to pass it downstream. */ if (call_creds != NULL) { grpc_call_credentials *composite_call_creds = grpc_composite_call_credentials_create(c->call_creds, call_creds, NULL); status = c->inner_creds->vtable->create_security_connector( exec_ctx, c->inner_creds, composite_call_creds, target, args, sc, new_args); grpc_call_credentials_unref(exec_ctx, composite_call_creds); } else { status = c->inner_creds->vtable->create_security_connector( exec_ctx, c->inner_creds, c->call_creds, target, args, sc, new_args); } return status; } static grpc_channel_credentials * composite_channel_duplicate_without_call_credentials( grpc_channel_credentials *creds) { grpc_composite_channel_credentials *c = (grpc_composite_channel_credentials *)creds; return grpc_channel_credentials_ref(c->inner_creds); } static grpc_channel_credentials_vtable composite_channel_credentials_vtable = { composite_channel_destruct, composite_channel_create_security_connector, composite_channel_duplicate_without_call_credentials}; grpc_channel_credentials *grpc_composite_channel_credentials_create( grpc_channel_credentials *channel_creds, grpc_call_credentials *call_creds, void *reserved) { grpc_composite_channel_credentials *c = gpr_zalloc(sizeof(*c)); GPR_ASSERT(channel_creds != NULL && call_creds != NULL && reserved == NULL); GRPC_API_TRACE( "grpc_composite_channel_credentials_create(channel_creds=%p, " "call_creds=%p, reserved=%p)", 3, (channel_creds, call_creds, reserved)); c->base.type = channel_creds->type; c->base.vtable = &composite_channel_credentials_vtable; gpr_ref_init(&c->base.refcount, 1); c->inner_creds = grpc_channel_credentials_ref(channel_creds); c->call_creds = grpc_call_credentials_ref(call_creds); return &c->base; } grpc-1.3.2/src/core/lib/security/credentials/composite/composite_credentials.h000066400000000000000000000055311310511640000276260ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_COMPOSITE_COMPOSITE_CREDENTIALS_H #define GRPC_CORE_LIB_SECURITY_CREDENTIALS_COMPOSITE_COMPOSITE_CREDENTIALS_H #include "src/core/lib/security/credentials/credentials.h" typedef struct { grpc_call_credentials **creds_array; size_t num_creds; } grpc_call_credentials_array; const grpc_call_credentials_array * grpc_composite_call_credentials_get_credentials( grpc_call_credentials *composite_creds); /* Returns creds if creds is of the specified type or the inner creds of the specified type (if found), if the creds is of type COMPOSITE. If composite_creds is not NULL, *composite_creds will point to creds if of type COMPOSITE in case of success. */ grpc_call_credentials *grpc_credentials_contains_type( grpc_call_credentials *creds, const char *type, grpc_call_credentials **composite_creds); /* -- Composite channel credentials. -- */ typedef struct { grpc_channel_credentials base; grpc_channel_credentials *inner_creds; grpc_call_credentials *call_creds; } grpc_composite_channel_credentials; /* -- Composite call credentials. -- */ typedef struct { grpc_call_credentials base; grpc_call_credentials_array inner; } grpc_composite_call_credentials; #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_COMPOSITE_COMPOSITE_CREDENTIALS_H \ */ grpc-1.3.2/src/core/lib/security/credentials/credentials.c000066400000000000000000000251261310511640000235370ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/security/credentials/credentials.h" #include #include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/http_client_filter.h" #include "src/core/lib/http/httpcli.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/json/json.h" #include "src/core/lib/support/string.h" #include "src/core/lib/surface/api_trace.h" #include #include #include #include #include /* -- Common. -- */ grpc_credentials_metadata_request *grpc_credentials_metadata_request_create( grpc_call_credentials *creds, grpc_credentials_metadata_cb cb, void *user_data) { grpc_credentials_metadata_request *r = gpr_zalloc(sizeof(grpc_credentials_metadata_request)); r->creds = grpc_call_credentials_ref(creds); r->cb = cb; r->user_data = user_data; return r; } void grpc_credentials_metadata_request_destroy( grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *r) { grpc_call_credentials_unref(exec_ctx, r->creds); grpc_http_response_destroy(&r->response); gpr_free(r); } grpc_channel_credentials *grpc_channel_credentials_ref( grpc_channel_credentials *creds) { if (creds == NULL) return NULL; gpr_ref(&creds->refcount); return creds; } void grpc_channel_credentials_unref(grpc_exec_ctx *exec_ctx, grpc_channel_credentials *creds) { if (creds == NULL) return; if (gpr_unref(&creds->refcount)) { if (creds->vtable->destruct != NULL) { creds->vtable->destruct(exec_ctx, creds); } gpr_free(creds); } } void grpc_channel_credentials_release(grpc_channel_credentials *creds) { GRPC_API_TRACE("grpc_channel_credentials_release(creds=%p)", 1, (creds)); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_channel_credentials_unref(&exec_ctx, creds); grpc_exec_ctx_finish(&exec_ctx); } grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds) { if (creds == NULL) return NULL; gpr_ref(&creds->refcount); return creds; } void grpc_call_credentials_unref(grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds) { if (creds == NULL) return; if (gpr_unref(&creds->refcount)) { if (creds->vtable->destruct != NULL) { creds->vtable->destruct(exec_ctx, creds); } gpr_free(creds); } } void grpc_call_credentials_release(grpc_call_credentials *creds) { GRPC_API_TRACE("grpc_call_credentials_release(creds=%p)", 1, (creds)); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_call_credentials_unref(&exec_ctx, creds); grpc_exec_ctx_finish(&exec_ctx); } void grpc_call_credentials_get_request_metadata( grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_polling_entity *pollent, grpc_auth_metadata_context context, grpc_credentials_metadata_cb cb, void *user_data) { if (creds == NULL || creds->vtable->get_request_metadata == NULL) { if (cb != NULL) { cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK, NULL); } return; } creds->vtable->get_request_metadata(exec_ctx, creds, pollent, context, cb, user_data); } grpc_security_status grpc_channel_credentials_create_security_connector( grpc_exec_ctx *exec_ctx, grpc_channel_credentials *channel_creds, const char *target, const grpc_channel_args *args, grpc_channel_security_connector **sc, grpc_channel_args **new_args) { *new_args = NULL; if (channel_creds == NULL) { return GRPC_SECURITY_ERROR; } GPR_ASSERT(channel_creds->vtable->create_security_connector != NULL); return channel_creds->vtable->create_security_connector( exec_ctx, channel_creds, NULL, target, args, sc, new_args); } grpc_channel_credentials * grpc_channel_credentials_duplicate_without_call_credentials( grpc_channel_credentials *channel_creds) { if (channel_creds != NULL && channel_creds->vtable != NULL && channel_creds->vtable->duplicate_without_call_credentials != NULL) { return channel_creds->vtable->duplicate_without_call_credentials( channel_creds); } else { return grpc_channel_credentials_ref(channel_creds); } } static void credentials_pointer_arg_destroy(grpc_exec_ctx *exec_ctx, void *p) { grpc_channel_credentials_unref(exec_ctx, p); } static void *credentials_pointer_arg_copy(void *p) { return grpc_channel_credentials_ref(p); } static int credentials_pointer_cmp(void *a, void *b) { return GPR_ICMP(a, b); } static const grpc_arg_pointer_vtable credentials_pointer_vtable = { credentials_pointer_arg_copy, credentials_pointer_arg_destroy, credentials_pointer_cmp}; grpc_arg grpc_channel_credentials_to_arg( grpc_channel_credentials *credentials) { grpc_arg result; result.type = GRPC_ARG_POINTER; result.key = GRPC_ARG_CHANNEL_CREDENTIALS; result.value.pointer.vtable = &credentials_pointer_vtable; result.value.pointer.p = credentials; return result; } grpc_channel_credentials *grpc_channel_credentials_from_arg( const grpc_arg *arg) { if (strcmp(arg->key, GRPC_ARG_CHANNEL_CREDENTIALS)) return NULL; if (arg->type != GRPC_ARG_POINTER) { gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type, GRPC_ARG_CHANNEL_CREDENTIALS); return NULL; } return arg->value.pointer.p; } grpc_channel_credentials *grpc_channel_credentials_find_in_args( const grpc_channel_args *args) { size_t i; if (args == NULL) return NULL; for (i = 0; i < args->num_args; i++) { grpc_channel_credentials *credentials = grpc_channel_credentials_from_arg(&args->args[i]); if (credentials != NULL) return credentials; } return NULL; } grpc_server_credentials *grpc_server_credentials_ref( grpc_server_credentials *creds) { if (creds == NULL) return NULL; gpr_ref(&creds->refcount); return creds; } void grpc_server_credentials_unref(grpc_exec_ctx *exec_ctx, grpc_server_credentials *creds) { if (creds == NULL) return; if (gpr_unref(&creds->refcount)) { if (creds->vtable->destruct != NULL) { creds->vtable->destruct(exec_ctx, creds); } if (creds->processor.destroy != NULL && creds->processor.state != NULL) { creds->processor.destroy(creds->processor.state); } gpr_free(creds); } } void grpc_server_credentials_release(grpc_server_credentials *creds) { GRPC_API_TRACE("grpc_server_credentials_release(creds=%p)", 1, (creds)); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_server_credentials_unref(&exec_ctx, creds); grpc_exec_ctx_finish(&exec_ctx); } grpc_security_status grpc_server_credentials_create_security_connector( grpc_exec_ctx *exec_ctx, grpc_server_credentials *creds, grpc_server_security_connector **sc) { if (creds == NULL || creds->vtable->create_security_connector == NULL) { gpr_log(GPR_ERROR, "Server credentials cannot create security context."); return GRPC_SECURITY_ERROR; } return creds->vtable->create_security_connector(exec_ctx, creds, sc); } void grpc_server_credentials_set_auth_metadata_processor( grpc_server_credentials *creds, grpc_auth_metadata_processor processor) { GRPC_API_TRACE( "grpc_server_credentials_set_auth_metadata_processor(" "creds=%p, " "processor=grpc_auth_metadata_processor { process: %p, state: %p })", 3, (creds, (void *)(intptr_t)processor.process, processor.state)); if (creds == NULL) return; if (creds->processor.destroy != NULL && creds->processor.state != NULL) { creds->processor.destroy(creds->processor.state); } creds->processor = processor; } static void server_credentials_pointer_arg_destroy(grpc_exec_ctx *exec_ctx, void *p) { grpc_server_credentials_unref(exec_ctx, p); } static void *server_credentials_pointer_arg_copy(void *p) { return grpc_server_credentials_ref(p); } static int server_credentials_pointer_cmp(void *a, void *b) { return GPR_ICMP(a, b); } static const grpc_arg_pointer_vtable cred_ptr_vtable = { server_credentials_pointer_arg_copy, server_credentials_pointer_arg_destroy, server_credentials_pointer_cmp}; grpc_arg grpc_server_credentials_to_arg(grpc_server_credentials *p) { grpc_arg arg; memset(&arg, 0, sizeof(grpc_arg)); arg.type = GRPC_ARG_POINTER; arg.key = GRPC_SERVER_CREDENTIALS_ARG; arg.value.pointer.p = p; arg.value.pointer.vtable = &cred_ptr_vtable; return arg; } grpc_server_credentials *grpc_server_credentials_from_arg(const grpc_arg *arg) { if (strcmp(arg->key, GRPC_SERVER_CREDENTIALS_ARG) != 0) return NULL; if (arg->type != GRPC_ARG_POINTER) { gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type, GRPC_SERVER_CREDENTIALS_ARG); return NULL; } return arg->value.pointer.p; } grpc_server_credentials *grpc_find_server_credentials_in_args( const grpc_channel_args *args) { size_t i; if (args == NULL) return NULL; for (i = 0; i < args->num_args; i++) { grpc_server_credentials *p = grpc_server_credentials_from_arg(&args->args[i]); if (p != NULL) return p; } return NULL; } grpc-1.3.2/src/core/lib/security/credentials/credentials.h000066400000000000000000000243701310511640000235440ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_CREDENTIALS_H #define GRPC_CORE_LIB_SECURITY_CREDENTIALS_CREDENTIALS_H #include #include #include #include "src/core/lib/transport/metadata_batch.h" #include "src/core/lib/http/httpcli.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/security/transport/security_connector.h" struct grpc_http_response; /* --- Constants. --- */ typedef enum { GRPC_CREDENTIALS_OK = 0, GRPC_CREDENTIALS_ERROR } grpc_credentials_status; #define GRPC_FAKE_TRANSPORT_SECURITY_TYPE "fake" #define GRPC_CHANNEL_CREDENTIALS_TYPE_SSL "Ssl" #define GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY \ "FakeTransportSecurity" #define GRPC_CALL_CREDENTIALS_TYPE_OAUTH2 "Oauth2" #define GRPC_CALL_CREDENTIALS_TYPE_JWT "Jwt" #define GRPC_CALL_CREDENTIALS_TYPE_IAM "Iam" #define GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE "Composite" #define GRPC_AUTHORIZATION_METADATA_KEY "authorization" #define GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY \ "x-goog-iam-authorization-token" #define GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY "x-goog-iam-authority-selector" #define GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS 60 #define GRPC_COMPUTE_ENGINE_METADATA_HOST "metadata.google.internal" #define GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH \ "/computeMetadata/v1/instance/service-accounts/default/token" #define GRPC_GOOGLE_OAUTH2_SERVICE_HOST "www.googleapis.com" #define GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH "/oauth2/v3/token" #define GRPC_SERVICE_ACCOUNT_POST_BODY_PREFIX \ "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&" \ "assertion=" #define GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING \ "client_id=%s&client_secret=%s&refresh_token=%s&grant_type=refresh_token" /* --- Google utils --- */ /* It is the caller's responsibility to gpr_free the result if not NULL. */ char *grpc_get_well_known_google_credentials_file_path(void); /* Implementation function for the different platforms. */ char *grpc_get_well_known_google_credentials_file_path_impl(void); /* Override for testing only. Not thread-safe */ typedef char *(*grpc_well_known_credentials_path_getter)(void); void grpc_override_well_known_credentials_path_getter( grpc_well_known_credentials_path_getter getter); /* --- grpc_channel_credentials. --- */ #define GRPC_ARG_CHANNEL_CREDENTIALS "grpc.channel_credentials" typedef struct { void (*destruct)(grpc_exec_ctx *exec_ctx, grpc_channel_credentials *c); grpc_security_status (*create_security_connector)( grpc_exec_ctx *exec_ctx, grpc_channel_credentials *c, grpc_call_credentials *call_creds, const char *target, const grpc_channel_args *args, grpc_channel_security_connector **sc, grpc_channel_args **new_args); grpc_channel_credentials *(*duplicate_without_call_credentials)( grpc_channel_credentials *c); } grpc_channel_credentials_vtable; struct grpc_channel_credentials { const grpc_channel_credentials_vtable *vtable; const char *type; gpr_refcount refcount; }; grpc_channel_credentials *grpc_channel_credentials_ref( grpc_channel_credentials *creds); void grpc_channel_credentials_unref(grpc_exec_ctx *exec_ctx, grpc_channel_credentials *creds); /* Creates a security connector for the channel. May also create new channel args for the channel to be used in place of the passed in const args if returned non NULL. In that case the caller is responsible for destroying new_args after channel creation. */ grpc_security_status grpc_channel_credentials_create_security_connector( grpc_exec_ctx *exec_ctx, grpc_channel_credentials *creds, const char *target, const grpc_channel_args *args, grpc_channel_security_connector **sc, grpc_channel_args **new_args); /* Creates a version of the channel credentials without any attached call credentials. This can be used in order to open a channel to a non-trusted gRPC load balancer. */ grpc_channel_credentials * grpc_channel_credentials_duplicate_without_call_credentials( grpc_channel_credentials *creds); /* Util to encapsulate the channel credentials in a channel arg. */ grpc_arg grpc_channel_credentials_to_arg(grpc_channel_credentials *credentials); /* Util to get the channel credentials from a channel arg. */ grpc_channel_credentials *grpc_channel_credentials_from_arg( const grpc_arg *arg); /* Util to find the channel credentials from channel args. */ grpc_channel_credentials *grpc_channel_credentials_find_in_args( const grpc_channel_args *args); /* --- grpc_credentials_md. --- */ typedef struct { grpc_slice key; grpc_slice value; } grpc_credentials_md; typedef struct { grpc_credentials_md *entries; size_t num_entries; size_t allocated; gpr_refcount refcount; } grpc_credentials_md_store; grpc_credentials_md_store *grpc_credentials_md_store_create( size_t initial_capacity); /* Will ref key and value. */ void grpc_credentials_md_store_add(grpc_credentials_md_store *store, grpc_slice key, grpc_slice value); void grpc_credentials_md_store_add_cstrings(grpc_credentials_md_store *store, const char *key, const char *value); grpc_credentials_md_store *grpc_credentials_md_store_ref( grpc_credentials_md_store *store); void grpc_credentials_md_store_unref(grpc_exec_ctx *exec_ctx, grpc_credentials_md_store *store); /* --- grpc_call_credentials. --- */ /* error_details must be NULL if status is GRPC_CREDENTIALS_OK. */ typedef void (*grpc_credentials_metadata_cb)( grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems, size_t num_md, grpc_credentials_status status, const char *error_details); typedef struct { void (*destruct)(grpc_exec_ctx *exec_ctx, grpc_call_credentials *c); void (*get_request_metadata)(grpc_exec_ctx *exec_ctx, grpc_call_credentials *c, grpc_polling_entity *pollent, grpc_auth_metadata_context context, grpc_credentials_metadata_cb cb, void *user_data); } grpc_call_credentials_vtable; struct grpc_call_credentials { const grpc_call_credentials_vtable *vtable; const char *type; gpr_refcount refcount; }; grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds); void grpc_call_credentials_unref(grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds); void grpc_call_credentials_get_request_metadata( grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_polling_entity *pollent, grpc_auth_metadata_context context, grpc_credentials_metadata_cb cb, void *user_data); /* Metadata-only credentials with the specified key and value where asynchronicity can be simulated for testing. */ grpc_call_credentials *grpc_md_only_test_credentials_create( const char *md_key, const char *md_value, int is_async); /* --- grpc_server_credentials. --- */ typedef struct { void (*destruct)(grpc_exec_ctx *exec_ctx, grpc_server_credentials *c); grpc_security_status (*create_security_connector)( grpc_exec_ctx *exec_ctx, grpc_server_credentials *c, grpc_server_security_connector **sc); } grpc_server_credentials_vtable; struct grpc_server_credentials { const grpc_server_credentials_vtable *vtable; const char *type; gpr_refcount refcount; grpc_auth_metadata_processor processor; }; grpc_security_status grpc_server_credentials_create_security_connector( grpc_exec_ctx *exec_ctx, grpc_server_credentials *creds, grpc_server_security_connector **sc); grpc_server_credentials *grpc_server_credentials_ref( grpc_server_credentials *creds); void grpc_server_credentials_unref(grpc_exec_ctx *exec_ctx, grpc_server_credentials *creds); #define GRPC_SERVER_CREDENTIALS_ARG "grpc.server_credentials" grpc_arg grpc_server_credentials_to_arg(grpc_server_credentials *c); grpc_server_credentials *grpc_server_credentials_from_arg(const grpc_arg *arg); grpc_server_credentials *grpc_find_server_credentials_in_args( const grpc_channel_args *args); /* -- Credentials Metadata Request. -- */ typedef struct { grpc_call_credentials *creds; grpc_credentials_metadata_cb cb; grpc_http_response response; void *user_data; } grpc_credentials_metadata_request; grpc_credentials_metadata_request *grpc_credentials_metadata_request_create( grpc_call_credentials *creds, grpc_credentials_metadata_cb cb, void *user_data); void grpc_credentials_metadata_request_destroy( grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *r); #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_CREDENTIALS_H */ grpc-1.3.2/src/core/lib/security/credentials/credentials_metadata.c000066400000000000000000000075721310511640000254040ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/security/credentials/credentials.h" #include #include #include "src/core/lib/slice/slice_internal.h" static void store_ensure_capacity(grpc_credentials_md_store *store) { if (store->num_entries == store->allocated) { store->allocated = (store->allocated == 0) ? 1 : store->allocated * 2; store->entries = gpr_realloc( store->entries, store->allocated * sizeof(grpc_credentials_md)); } } grpc_credentials_md_store *grpc_credentials_md_store_create( size_t initial_capacity) { grpc_credentials_md_store *store = gpr_zalloc(sizeof(grpc_credentials_md_store)); if (initial_capacity > 0) { store->entries = gpr_malloc(initial_capacity * sizeof(grpc_credentials_md)); store->allocated = initial_capacity; } gpr_ref_init(&store->refcount, 1); return store; } void grpc_credentials_md_store_add(grpc_credentials_md_store *store, grpc_slice key, grpc_slice value) { if (store == NULL) return; store_ensure_capacity(store); store->entries[store->num_entries].key = grpc_slice_ref_internal(key); store->entries[store->num_entries].value = grpc_slice_ref_internal(value); store->num_entries++; } void grpc_credentials_md_store_add_cstrings(grpc_credentials_md_store *store, const char *key, const char *value) { if (store == NULL) return; store_ensure_capacity(store); store->entries[store->num_entries].key = grpc_slice_from_copied_string(key); store->entries[store->num_entries].value = grpc_slice_from_copied_string(value); store->num_entries++; } grpc_credentials_md_store *grpc_credentials_md_store_ref( grpc_credentials_md_store *store) { if (store == NULL) return NULL; gpr_ref(&store->refcount); return store; } void grpc_credentials_md_store_unref(grpc_exec_ctx *exec_ctx, grpc_credentials_md_store *store) { if (store == NULL) return; if (gpr_unref(&store->refcount)) { if (store->entries != NULL) { size_t i; for (i = 0; i < store->num_entries; i++) { grpc_slice_unref_internal(exec_ctx, store->entries[i].key); grpc_slice_unref_internal(exec_ctx, store->entries[i].value); } gpr_free(store->entries); } gpr_free(store); } } grpc-1.3.2/src/core/lib/security/credentials/fake/000077500000000000000000000000001310511640000217765ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/security/credentials/fake/fake_credentials.c000066400000000000000000000133651310511640000254350ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/security/credentials/fake/fake_credentials.h" #include #include #include #include #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/support/string.h" /* -- Fake transport security credentials. -- */ static grpc_security_status fake_transport_security_create_security_connector( grpc_exec_ctx *exec_ctx, grpc_channel_credentials *c, grpc_call_credentials *call_creds, const char *target, const grpc_channel_args *args, grpc_channel_security_connector **sc, grpc_channel_args **new_args) { *sc = grpc_fake_channel_security_connector_create(call_creds, target, args); return GRPC_SECURITY_OK; } static grpc_security_status fake_transport_security_server_create_security_connector( grpc_exec_ctx *exec_ctx, grpc_server_credentials *c, grpc_server_security_connector **sc) { *sc = grpc_fake_server_security_connector_create(); return GRPC_SECURITY_OK; } static grpc_channel_credentials_vtable fake_transport_security_credentials_vtable = { NULL, fake_transport_security_create_security_connector, NULL}; static grpc_server_credentials_vtable fake_transport_security_server_credentials_vtable = { NULL, fake_transport_security_server_create_security_connector}; grpc_channel_credentials *grpc_fake_transport_security_credentials_create( void) { grpc_channel_credentials *c = gpr_zalloc(sizeof(grpc_channel_credentials)); c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY; c->vtable = &fake_transport_security_credentials_vtable; gpr_ref_init(&c->refcount, 1); return c; } grpc_server_credentials *grpc_fake_transport_security_server_credentials_create( void) { grpc_server_credentials *c = gpr_malloc(sizeof(grpc_server_credentials)); memset(c, 0, sizeof(grpc_server_credentials)); c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY; gpr_ref_init(&c->refcount, 1); c->vtable = &fake_transport_security_server_credentials_vtable; return c; } /* -- Metadata-only test credentials. -- */ static void md_only_test_destruct(grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds) { grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds; grpc_credentials_md_store_unref(exec_ctx, c->md_store); } static void on_simulated_token_fetch_done(grpc_exec_ctx *exec_ctx, void *user_data, grpc_error *error) { grpc_credentials_metadata_request *r = (grpc_credentials_metadata_request *)user_data; grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)r->creds; r->cb(exec_ctx, r->user_data, c->md_store->entries, c->md_store->num_entries, GRPC_CREDENTIALS_OK, NULL); grpc_credentials_metadata_request_destroy(exec_ctx, r); } static void md_only_test_get_request_metadata( grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_polling_entity *pollent, grpc_auth_metadata_context context, grpc_credentials_metadata_cb cb, void *user_data) { grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds; if (c->is_async) { grpc_credentials_metadata_request *cb_arg = grpc_credentials_metadata_request_create(creds, cb, user_data); grpc_closure_sched(exec_ctx, grpc_closure_create(on_simulated_token_fetch_done, cb_arg, grpc_executor_scheduler), GRPC_ERROR_NONE); } else { cb(exec_ctx, user_data, c->md_store->entries, 1, GRPC_CREDENTIALS_OK, NULL); } } static grpc_call_credentials_vtable md_only_test_vtable = { md_only_test_destruct, md_only_test_get_request_metadata}; grpc_call_credentials *grpc_md_only_test_credentials_create( const char *md_key, const char *md_value, int is_async) { grpc_md_only_test_credentials *c = gpr_zalloc(sizeof(grpc_md_only_test_credentials)); c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2; c->base.vtable = &md_only_test_vtable; gpr_ref_init(&c->base.refcount, 1); c->md_store = grpc_credentials_md_store_create(1); grpc_credentials_md_store_add_cstrings(c->md_store, md_key, md_value); c->is_async = is_async; return &c->base; } grpc-1.3.2/src/core/lib/security/credentials/fake/fake_credentials.h000066400000000000000000000056211310511640000254360ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_FAKE_FAKE_CREDENTIALS_H #define GRPC_CORE_LIB_SECURITY_CREDENTIALS_FAKE_FAKE_CREDENTIALS_H #include "src/core/lib/security/credentials/credentials.h" /* -- Fake transport security credentials. -- */ /* Used to verify the target names given to the fake transport security * connector. * * Its syntax by example: * For LB channels: * "backend_target_1,backend_target_2,...;lb_target_1,lb_target_2,..." * For regular channels: * "backend_taget_1,backend_target_2,..." * * That is to say, LB channels have a heading list of LB targets separated from * the list of backend targets by a semicolon. For non-LB channels, only the * latter is present. */ #define GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS \ "grpc.test_only.fake_security.expected_target" /* Creates a fake transport security credentials object for testing. */ grpc_channel_credentials *grpc_fake_transport_security_credentials_create(void); /* Creates a fake server transport security credentials object for testing. */ grpc_server_credentials *grpc_fake_transport_security_server_credentials_create( void); /* -- Metadata-only Test credentials. -- */ typedef struct { grpc_call_credentials base; grpc_credentials_md_store *md_store; int is_async; } grpc_md_only_test_credentials; #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_FAKE_FAKE_CREDENTIALS_H */ grpc-1.3.2/src/core/lib/security/credentials/google_default/000077500000000000000000000000001310511640000240505ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/security/credentials/google_default/credentials_generic.c000066400000000000000000000043441310511640000302120ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/security/credentials/google_default/google_default_credentials.h" #include #include #include #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" char *grpc_get_well_known_google_credentials_file_path_impl(void) { char *result = NULL; char *base = gpr_getenv(GRPC_GOOGLE_CREDENTIALS_PATH_ENV_VAR); if (base == NULL) { gpr_log(GPR_ERROR, "Could not get " GRPC_GOOGLE_CREDENTIALS_ENV_VAR " environment variable."); return NULL; } gpr_asprintf(&result, "%s/%s", base, GRPC_GOOGLE_CREDENTIALS_PATH_SUFFIX); gpr_free(base); return result; } grpc-1.3.2/src/core/lib/security/credentials/google_default/google_default_credentials.c000066400000000000000000000301361310511640000315540ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/security/credentials/credentials.h" #include #include #include #include #include "src/core/lib/http/httpcli.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/iomgr/load_file.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/security/credentials/jwt/jwt_credentials.h" #include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" #include "src/core/lib/surface/api_trace.h" /* -- Constants. -- */ #define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal" /* -- Default credentials. -- */ static grpc_channel_credentials *default_credentials = NULL; static int compute_engine_detection_done = 0; static gpr_mu g_state_mu; static gpr_mu *g_polling_mu; static gpr_once g_once = GPR_ONCE_INIT; static void init_default_credentials(void) { gpr_mu_init(&g_state_mu); } typedef struct { grpc_polling_entity pollent; int is_done; int success; grpc_http_response response; } compute_engine_detector; static void on_compute_engine_detection_http_response(grpc_exec_ctx *exec_ctx, void *user_data, grpc_error *error) { compute_engine_detector *detector = (compute_engine_detector *)user_data; if (error == GRPC_ERROR_NONE && detector->response.status == 200 && detector->response.hdr_count > 0) { /* Internet providers can return a generic response to all requests, so it is necessary to check that metadata header is present also. */ size_t i; for (i = 0; i < detector->response.hdr_count; i++) { grpc_http_header *header = &detector->response.hdrs[i]; if (strcmp(header->key, "Metadata-Flavor") == 0 && strcmp(header->value, "Google") == 0) { detector->success = 1; break; } } } gpr_mu_lock(g_polling_mu); detector->is_done = 1; GRPC_LOG_IF_ERROR( "Pollset kick", grpc_pollset_kick(grpc_polling_entity_pollset(&detector->pollent), NULL)); gpr_mu_unlock(g_polling_mu); } static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, grpc_error *e) { grpc_pollset_destroy(p); } static int is_stack_running_on_compute_engine(grpc_exec_ctx *exec_ctx) { compute_engine_detector detector; grpc_httpcli_request request; grpc_httpcli_context context; grpc_closure destroy_closure; /* The http call is local. If it takes more than one sec, it is for sure not on compute engine. */ gpr_timespec max_detection_delay = gpr_time_from_seconds(1, GPR_TIMESPAN); grpc_pollset *pollset = gpr_zalloc(grpc_pollset_size()); grpc_pollset_init(pollset, &g_polling_mu); detector.pollent = grpc_polling_entity_create_from_pollset(pollset); detector.is_done = 0; detector.success = 0; memset(&detector.response, 0, sizeof(detector.response)); memset(&request, 0, sizeof(grpc_httpcli_request)); request.host = GRPC_COMPUTE_ENGINE_DETECTION_HOST; request.http.path = "/"; grpc_httpcli_context_init(&context); grpc_resource_quota *resource_quota = grpc_resource_quota_create("google_default_credentials"); grpc_httpcli_get( exec_ctx, &context, &detector.pollent, resource_quota, &request, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), max_detection_delay), grpc_closure_create(on_compute_engine_detection_http_response, &detector, grpc_schedule_on_exec_ctx), &detector.response); grpc_resource_quota_unref_internal(exec_ctx, resource_quota); grpc_exec_ctx_flush(exec_ctx); /* Block until we get the response. This is not ideal but this should only be called once for the lifetime of the process by the default credentials. */ gpr_mu_lock(g_polling_mu); while (!detector.is_done) { grpc_pollset_worker *worker = NULL; if (!GRPC_LOG_IF_ERROR( "pollset_work", grpc_pollset_work(exec_ctx, grpc_polling_entity_pollset(&detector.pollent), &worker, gpr_now(GPR_CLOCK_MONOTONIC), gpr_inf_future(GPR_CLOCK_MONOTONIC)))) { detector.is_done = 1; detector.success = 0; } } gpr_mu_unlock(g_polling_mu); grpc_httpcli_context_destroy(exec_ctx, &context); grpc_closure_init(&destroy_closure, destroy_pollset, grpc_polling_entity_pollset(&detector.pollent), grpc_schedule_on_exec_ctx); grpc_pollset_shutdown(exec_ctx, grpc_polling_entity_pollset(&detector.pollent), &destroy_closure); g_polling_mu = NULL; grpc_exec_ctx_flush(exec_ctx); gpr_free(grpc_polling_entity_pollset(&detector.pollent)); grpc_http_response_destroy(&detector.response); return detector.success; } /* Takes ownership of creds_path if not NULL. */ static grpc_error *create_default_creds_from_path( grpc_exec_ctx *exec_ctx, char *creds_path, grpc_call_credentials **creds) { grpc_json *json = NULL; grpc_auth_json_key key; grpc_auth_refresh_token token; grpc_call_credentials *result = NULL; grpc_slice creds_data = grpc_empty_slice(); grpc_error *error = GRPC_ERROR_NONE; if (creds_path == NULL) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("creds_path unset"); goto end; } error = grpc_load_file(creds_path, 0, &creds_data); if (error != GRPC_ERROR_NONE) { goto end; } json = grpc_json_parse_string_with_len( (char *)GRPC_SLICE_START_PTR(creds_data), GRPC_SLICE_LENGTH(creds_data)); if (json == NULL) { error = grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to parse JSON"), GRPC_ERROR_STR_RAW_BYTES, grpc_slice_ref_internal(creds_data)); goto end; } /* First, try an auth json key. */ key = grpc_auth_json_key_create_from_json(json); if (grpc_auth_json_key_is_valid(&key)) { result = grpc_service_account_jwt_access_credentials_create_from_auth_json_key( exec_ctx, key, grpc_max_auth_token_lifetime()); if (result == NULL) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "grpc_service_account_jwt_access_credentials_create_from_auth_json_" "key failed"); } goto end; } /* Then try a refresh token if the auth json key was invalid. */ token = grpc_auth_refresh_token_create_from_json(json); if (grpc_auth_refresh_token_is_valid(&token)) { result = grpc_refresh_token_credentials_create_from_auth_refresh_token(token); if (result == NULL) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "grpc_refresh_token_credentials_create_from_auth_refresh_token " "failed"); } goto end; } end: GPR_ASSERT((result == NULL) + (error == GRPC_ERROR_NONE) == 1); if (creds_path != NULL) gpr_free(creds_path); grpc_slice_unref_internal(exec_ctx, creds_data); if (json != NULL) grpc_json_destroy(json); *creds = result; return error; } grpc_channel_credentials *grpc_google_default_credentials_create(void) { grpc_channel_credentials *result = NULL; grpc_call_credentials *call_creds = NULL; grpc_error *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Failed to create Google credentials"); grpc_error *err; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE("grpc_google_default_credentials_create(void)", 0, ()); gpr_once_init(&g_once, init_default_credentials); gpr_mu_lock(&g_state_mu); if (default_credentials != NULL) { result = grpc_channel_credentials_ref(default_credentials); goto end; } /* First, try the environment variable. */ err = create_default_creds_from_path( &exec_ctx, gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR), &call_creds); if (err == GRPC_ERROR_NONE) goto end; error = grpc_error_add_child(error, err); /* Then the well-known file. */ err = create_default_creds_from_path( &exec_ctx, grpc_get_well_known_google_credentials_file_path(), &call_creds); if (err == GRPC_ERROR_NONE) goto end; error = grpc_error_add_child(error, err); /* At last try to see if we're on compute engine (do the detection only once since it requires a network test). */ if (!compute_engine_detection_done) { int need_compute_engine_creds = is_stack_running_on_compute_engine(&exec_ctx); compute_engine_detection_done = 1; if (need_compute_engine_creds) { call_creds = grpc_google_compute_engine_credentials_create(NULL); if (call_creds == NULL) { error = grpc_error_add_child( error, GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Failed to get credentials from network")); } } } end: if (result == NULL) { if (call_creds != NULL) { /* Blend with default ssl credentials and add a global reference so that it can be cached and re-served. */ grpc_channel_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL, NULL); default_credentials = grpc_channel_credentials_ref( grpc_composite_channel_credentials_create(ssl_creds, call_creds, NULL)); GPR_ASSERT(default_credentials != NULL); grpc_channel_credentials_unref(&exec_ctx, ssl_creds); grpc_call_credentials_unref(&exec_ctx, call_creds); result = default_credentials; } else { gpr_log(GPR_ERROR, "Could not create google default credentials."); } } gpr_mu_unlock(&g_state_mu); if (result == NULL) { GRPC_LOG_IF_ERROR("grpc_google_default_credentials_create", error); } else { GRPC_ERROR_UNREF(error); } grpc_exec_ctx_finish(&exec_ctx); return result; } void grpc_flush_cached_google_default_credentials(void) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; gpr_once_init(&g_once, init_default_credentials); gpr_mu_lock(&g_state_mu); if (default_credentials != NULL) { grpc_channel_credentials_unref(&exec_ctx, default_credentials); default_credentials = NULL; } compute_engine_detection_done = 0; gpr_mu_unlock(&g_state_mu); grpc_exec_ctx_finish(&exec_ctx); } /* -- Well known credentials path. -- */ static grpc_well_known_credentials_path_getter creds_path_getter = NULL; char *grpc_get_well_known_google_credentials_file_path(void) { if (creds_path_getter != NULL) return creds_path_getter(); return grpc_get_well_known_google_credentials_file_path_impl(); } void grpc_override_well_known_credentials_path_getter( grpc_well_known_credentials_path_getter getter) { creds_path_getter = getter; } grpc-1.3.2/src/core/lib/security/credentials/google_default/google_default_credentials.h000066400000000000000000000050341310511640000315600ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_GOOGLE_DEFAULT_GOOGLE_DEFAULT_CREDENTIALS_H #define GRPC_CORE_LIB_SECURITY_CREDENTIALS_GOOGLE_DEFAULT_GOOGLE_DEFAULT_CREDENTIALS_H #include #include "src/core/lib/security/credentials/credentials.h" #define GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY "gcloud" #define GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE \ "application_default_credentials.json" #ifdef GPR_WINDOWS #define GRPC_GOOGLE_CREDENTIALS_PATH_ENV_VAR "APPDATA" #define GRPC_GOOGLE_CREDENTIALS_PATH_SUFFIX \ GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY \ "/" GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE #else #define GRPC_GOOGLE_CREDENTIALS_PATH_ENV_VAR "HOME" #define GRPC_GOOGLE_CREDENTIALS_PATH_SUFFIX \ ".config/" GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY \ "/" GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE #endif void grpc_flush_cached_google_default_credentials(void); #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_GOOGLE_DEFAULT_GOOGLE_DEFAULT_CREDENTIALS_H \ */ grpc-1.3.2/src/core/lib/security/credentials/iam/000077500000000000000000000000001310511640000216365ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/security/credentials/iam/iam_credentials.c000066400000000000000000000071611310511640000251320ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/security/credentials/iam/iam_credentials.h" #include #include "src/core/lib/surface/api_trace.h" #include #include #include #include static void iam_destruct(grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds) { grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds; grpc_credentials_md_store_unref(exec_ctx, c->iam_md); } static void iam_get_request_metadata(grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_polling_entity *pollent, grpc_auth_metadata_context context, grpc_credentials_metadata_cb cb, void *user_data) { grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds; cb(exec_ctx, user_data, c->iam_md->entries, c->iam_md->num_entries, GRPC_CREDENTIALS_OK, NULL); } static grpc_call_credentials_vtable iam_vtable = {iam_destruct, iam_get_request_metadata}; grpc_call_credentials *grpc_google_iam_credentials_create( const char *token, const char *authority_selector, void *reserved) { grpc_google_iam_credentials *c; GRPC_API_TRACE( "grpc_iam_credentials_create(token=%s, authority_selector=%s, " "reserved=%p)", 3, (token, authority_selector, reserved)); GPR_ASSERT(reserved == NULL); GPR_ASSERT(token != NULL); GPR_ASSERT(authority_selector != NULL); c = gpr_zalloc(sizeof(grpc_google_iam_credentials)); c->base.type = GRPC_CALL_CREDENTIALS_TYPE_IAM; c->base.vtable = &iam_vtable; gpr_ref_init(&c->base.refcount, 1); c->iam_md = grpc_credentials_md_store_create(2); grpc_credentials_md_store_add_cstrings( c->iam_md, GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, token); grpc_credentials_md_store_add_cstrings( c->iam_md, GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, authority_selector); return &c->base; } grpc-1.3.2/src/core/lib/security/credentials/iam/iam_credentials.h000066400000000000000000000036331310511640000251370ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_IAM_IAM_CREDENTIALS_H #define GRPC_CORE_LIB_SECURITY_CREDENTIALS_IAM_IAM_CREDENTIALS_H #include "src/core/lib/security/credentials/credentials.h" typedef struct { grpc_call_credentials base; grpc_credentials_md_store *iam_md; } grpc_google_iam_credentials; #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_IAM_IAM_CREDENTIALS_H */ grpc-1.3.2/src/core/lib/security/credentials/jwt/000077500000000000000000000000001310511640000216745ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/security/credentials/jwt/json_token.c000066400000000000000000000253221310511640000242150ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/security/credentials/jwt/json_token.h" #include #include #include #include #include #include "src/core/lib/security/util/json_util.h" #include "src/core/lib/slice/b64.h" #include "src/core/lib/support/string.h" #include #include #include /* --- Constants. --- */ /* 1 hour max. */ gpr_timespec grpc_max_auth_token_lifetime() { gpr_timespec out; out.tv_sec = 3600; out.tv_nsec = 0; out.clock_type = GPR_TIMESPAN; return out; } #define GRPC_JWT_RSA_SHA256_ALGORITHM "RS256" #define GRPC_JWT_TYPE "JWT" /* --- Override for testing. --- */ static grpc_jwt_encode_and_sign_override g_jwt_encode_and_sign_override = NULL; /* --- grpc_auth_json_key. --- */ int grpc_auth_json_key_is_valid(const grpc_auth_json_key *json_key) { return (json_key != NULL) && strcmp(json_key->type, GRPC_AUTH_JSON_TYPE_INVALID); } grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json *json) { grpc_auth_json_key result; BIO *bio = NULL; const char *prop_value; int success = 0; memset(&result, 0, sizeof(grpc_auth_json_key)); result.type = GRPC_AUTH_JSON_TYPE_INVALID; if (json == NULL) { gpr_log(GPR_ERROR, "Invalid json."); goto end; } prop_value = grpc_json_get_string_property(json, "type"); if (prop_value == NULL || strcmp(prop_value, GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT)) { goto end; } result.type = GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT; if (!grpc_copy_json_string_property(json, "private_key_id", &result.private_key_id) || !grpc_copy_json_string_property(json, "client_id", &result.client_id) || !grpc_copy_json_string_property(json, "client_email", &result.client_email)) { goto end; } prop_value = grpc_json_get_string_property(json, "private_key"); if (prop_value == NULL) { goto end; } bio = BIO_new(BIO_s_mem()); success = BIO_puts(bio, prop_value); if ((success < 0) || ((size_t)success != strlen(prop_value))) { gpr_log(GPR_ERROR, "Could not write into openssl BIO."); goto end; } result.private_key = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, ""); if (result.private_key == NULL) { gpr_log(GPR_ERROR, "Could not deserialize private key."); goto end; } success = 1; end: if (bio != NULL) BIO_free(bio); if (!success) grpc_auth_json_key_destruct(&result); return result; } grpc_auth_json_key grpc_auth_json_key_create_from_string( const char *json_string) { char *scratchpad = gpr_strdup(json_string); grpc_json *json = grpc_json_parse_string(scratchpad); grpc_auth_json_key result = grpc_auth_json_key_create_from_json(json); if (json != NULL) grpc_json_destroy(json); gpr_free(scratchpad); return result; } void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key) { if (json_key == NULL) return; json_key->type = GRPC_AUTH_JSON_TYPE_INVALID; if (json_key->client_id != NULL) { gpr_free(json_key->client_id); json_key->client_id = NULL; } if (json_key->private_key_id != NULL) { gpr_free(json_key->private_key_id); json_key->private_key_id = NULL; } if (json_key->client_email != NULL) { gpr_free(json_key->client_email); json_key->client_email = NULL; } if (json_key->private_key != NULL) { RSA_free(json_key->private_key); json_key->private_key = NULL; } } /* --- jwt encoding and signature. --- */ static grpc_json *create_child(grpc_json *brother, grpc_json *parent, const char *key, const char *value, grpc_json_type type) { grpc_json *child = grpc_json_create(type); if (brother) brother->next = child; if (!parent->child) parent->child = child; child->parent = parent; child->value = value; child->key = key; return child; } static char *encoded_jwt_header(const char *key_id, const char *algorithm) { grpc_json *json = grpc_json_create(GRPC_JSON_OBJECT); grpc_json *child = NULL; char *json_str = NULL; char *result = NULL; child = create_child(NULL, json, "alg", algorithm, GRPC_JSON_STRING); child = create_child(child, json, "typ", GRPC_JWT_TYPE, GRPC_JSON_STRING); create_child(child, json, "kid", key_id, GRPC_JSON_STRING); json_str = grpc_json_dump_to_string(json, 0); result = grpc_base64_encode(json_str, strlen(json_str), 1, 0); gpr_free(json_str); grpc_json_destroy(json); return result; } static char *encoded_jwt_claim(const grpc_auth_json_key *json_key, const char *audience, gpr_timespec token_lifetime, const char *scope) { grpc_json *json = grpc_json_create(GRPC_JSON_OBJECT); grpc_json *child = NULL; char *json_str = NULL; char *result = NULL; gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); gpr_timespec expiration = gpr_time_add(now, token_lifetime); char now_str[GPR_LTOA_MIN_BUFSIZE]; char expiration_str[GPR_LTOA_MIN_BUFSIZE]; if (gpr_time_cmp(token_lifetime, grpc_max_auth_token_lifetime()) > 0) { gpr_log(GPR_INFO, "Cropping token lifetime to maximum allowed value."); expiration = gpr_time_add(now, grpc_max_auth_token_lifetime()); } int64_ttoa(now.tv_sec, now_str); int64_ttoa(expiration.tv_sec, expiration_str); child = create_child(NULL, json, "iss", json_key->client_email, GRPC_JSON_STRING); if (scope != NULL) { child = create_child(child, json, "scope", scope, GRPC_JSON_STRING); } else { /* Unscoped JWTs need a sub field. */ child = create_child(child, json, "sub", json_key->client_email, GRPC_JSON_STRING); } child = create_child(child, json, "aud", audience, GRPC_JSON_STRING); child = create_child(child, json, "iat", now_str, GRPC_JSON_NUMBER); create_child(child, json, "exp", expiration_str, GRPC_JSON_NUMBER); json_str = grpc_json_dump_to_string(json, 0); result = grpc_base64_encode(json_str, strlen(json_str), 1, 0); gpr_free(json_str); grpc_json_destroy(json); return result; } static char *dot_concat_and_free_strings(char *str1, char *str2) { size_t str1_len = strlen(str1); size_t str2_len = strlen(str2); size_t result_len = str1_len + 1 /* dot */ + str2_len; char *result = gpr_malloc(result_len + 1 /* NULL terminated */); char *current = result; memcpy(current, str1, str1_len); current += str1_len; *(current++) = '.'; memcpy(current, str2, str2_len); current += str2_len; GPR_ASSERT(current >= result); GPR_ASSERT((uintptr_t)(current - result) == result_len); *current = '\0'; gpr_free(str1); gpr_free(str2); return result; } const EVP_MD *openssl_digest_from_algorithm(const char *algorithm) { if (strcmp(algorithm, GRPC_JWT_RSA_SHA256_ALGORITHM) == 0) { return EVP_sha256(); } else { gpr_log(GPR_ERROR, "Unknown algorithm %s.", algorithm); return NULL; } } char *compute_and_encode_signature(const grpc_auth_json_key *json_key, const char *signature_algorithm, const char *to_sign) { const EVP_MD *md = openssl_digest_from_algorithm(signature_algorithm); EVP_MD_CTX *md_ctx = NULL; EVP_PKEY *key = EVP_PKEY_new(); size_t sig_len = 0; unsigned char *sig = NULL; char *result = NULL; if (md == NULL) return NULL; md_ctx = EVP_MD_CTX_create(); if (md_ctx == NULL) { gpr_log(GPR_ERROR, "Could not create MD_CTX"); goto end; } EVP_PKEY_set1_RSA(key, json_key->private_key); if (EVP_DigestSignInit(md_ctx, NULL, md, NULL, key) != 1) { gpr_log(GPR_ERROR, "DigestInit failed."); goto end; } if (EVP_DigestSignUpdate(md_ctx, to_sign, strlen(to_sign)) != 1) { gpr_log(GPR_ERROR, "DigestUpdate failed."); goto end; } if (EVP_DigestSignFinal(md_ctx, NULL, &sig_len) != 1) { gpr_log(GPR_ERROR, "DigestFinal (get signature length) failed."); goto end; } sig = gpr_malloc(sig_len); if (EVP_DigestSignFinal(md_ctx, sig, &sig_len) != 1) { gpr_log(GPR_ERROR, "DigestFinal (signature compute) failed."); goto end; } result = grpc_base64_encode(sig, sig_len, 1, 0); end: if (key != NULL) EVP_PKEY_free(key); if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx); if (sig != NULL) gpr_free(sig); return result; } char *grpc_jwt_encode_and_sign(const grpc_auth_json_key *json_key, const char *audience, gpr_timespec token_lifetime, const char *scope) { if (g_jwt_encode_and_sign_override != NULL) { return g_jwt_encode_and_sign_override(json_key, audience, token_lifetime, scope); } else { const char *sig_algo = GRPC_JWT_RSA_SHA256_ALGORITHM; char *to_sign = dot_concat_and_free_strings( encoded_jwt_header(json_key->private_key_id, sig_algo), encoded_jwt_claim(json_key, audience, token_lifetime, scope)); char *sig = compute_and_encode_signature(json_key, sig_algo, to_sign); if (sig == NULL) { gpr_free(to_sign); return NULL; } return dot_concat_and_free_strings(to_sign, sig); } } void grpc_jwt_encode_and_sign_set_override( grpc_jwt_encode_and_sign_override func) { g_jwt_encode_and_sign_override = func; } grpc-1.3.2/src/core/lib/security/credentials/jwt/json_token.h000066400000000000000000000066661310511640000242340ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JSON_TOKEN_H #define GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JSON_TOKEN_H #include #include #include "src/core/lib/json/json.h" /* --- Constants. --- */ #define GRPC_JWT_OAUTH2_AUDIENCE "https://www.googleapis.com/oauth2/v3/token" /* --- auth_json_key parsing. --- */ typedef struct { const char *type; char *private_key_id; char *client_id; char *client_email; RSA *private_key; } grpc_auth_json_key; /* Returns 1 if the object is valid, 0 otherwise. */ int grpc_auth_json_key_is_valid(const grpc_auth_json_key *json_key); /* Creates a json_key object from string. Returns an invalid object if a parsing error has been encountered. */ grpc_auth_json_key grpc_auth_json_key_create_from_string( const char *json_string); /* Creates a json_key object from parsed json. Returns an invalid object if a parsing error has been encountered. */ grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json *json); /* Destructs the object. */ void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key); /* --- json token encoding and signing. --- */ /* Caller is responsible for calling gpr_free on the returned value. May return NULL on invalid input. The scope parameter may be NULL. */ char *grpc_jwt_encode_and_sign(const grpc_auth_json_key *json_key, const char *audience, gpr_timespec token_lifetime, const char *scope); /* Override encode_and_sign function for testing. */ typedef char *(*grpc_jwt_encode_and_sign_override)( const grpc_auth_json_key *json_key, const char *audience, gpr_timespec token_lifetime, const char *scope); /* Set a custom encode_and_sign override for testing. */ void grpc_jwt_encode_and_sign_set_override( grpc_jwt_encode_and_sign_override func); #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JSON_TOKEN_H */ grpc-1.3.2/src/core/lib/security/credentials/jwt/jwt_credentials.c000066400000000000000000000163741310511640000252340ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/security/credentials/jwt/jwt_credentials.h" #include #include "src/core/lib/surface/api_trace.h" #include #include #include #include static void jwt_reset_cache(grpc_exec_ctx *exec_ctx, grpc_service_account_jwt_access_credentials *c) { if (c->cached.jwt_md != NULL) { grpc_credentials_md_store_unref(exec_ctx, c->cached.jwt_md); c->cached.jwt_md = NULL; } if (c->cached.service_url != NULL) { gpr_free(c->cached.service_url); c->cached.service_url = NULL; } c->cached.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME); } static void jwt_destruct(grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds) { grpc_service_account_jwt_access_credentials *c = (grpc_service_account_jwt_access_credentials *)creds; grpc_auth_json_key_destruct(&c->key); jwt_reset_cache(exec_ctx, c); gpr_mu_destroy(&c->cache_mu); } static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_polling_entity *pollent, grpc_auth_metadata_context context, grpc_credentials_metadata_cb cb, void *user_data) { grpc_service_account_jwt_access_credentials *c = (grpc_service_account_jwt_access_credentials *)creds; gpr_timespec refresh_threshold = gpr_time_from_seconds( GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN); /* See if we can return a cached jwt. */ grpc_credentials_md_store *jwt_md = NULL; { gpr_mu_lock(&c->cache_mu); if (c->cached.service_url != NULL && strcmp(c->cached.service_url, context.service_url) == 0 && c->cached.jwt_md != NULL && (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration, gpr_now(GPR_CLOCK_REALTIME)), refresh_threshold) > 0)) { jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md); } gpr_mu_unlock(&c->cache_mu); } if (jwt_md == NULL) { char *jwt = NULL; /* Generate a new jwt. */ gpr_mu_lock(&c->cache_mu); jwt_reset_cache(exec_ctx, c); jwt = grpc_jwt_encode_and_sign(&c->key, context.service_url, c->jwt_lifetime, NULL); if (jwt != NULL) { char *md_value; gpr_asprintf(&md_value, "Bearer %s", jwt); gpr_free(jwt); c->cached.jwt_expiration = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c->jwt_lifetime); c->cached.service_url = gpr_strdup(context.service_url); c->cached.jwt_md = grpc_credentials_md_store_create(1); grpc_credentials_md_store_add_cstrings( c->cached.jwt_md, GRPC_AUTHORIZATION_METADATA_KEY, md_value); gpr_free(md_value); jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md); } gpr_mu_unlock(&c->cache_mu); } if (jwt_md != NULL) { cb(exec_ctx, user_data, jwt_md->entries, jwt_md->num_entries, GRPC_CREDENTIALS_OK, NULL); grpc_credentials_md_store_unref(exec_ctx, jwt_md); } else { cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_ERROR, "Could not generate JWT."); } } static grpc_call_credentials_vtable jwt_vtable = {jwt_destruct, jwt_get_request_metadata}; grpc_call_credentials * grpc_service_account_jwt_access_credentials_create_from_auth_json_key( grpc_exec_ctx *exec_ctx, grpc_auth_json_key key, gpr_timespec token_lifetime) { grpc_service_account_jwt_access_credentials *c; if (!grpc_auth_json_key_is_valid(&key)) { gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation"); return NULL; } c = gpr_zalloc(sizeof(grpc_service_account_jwt_access_credentials)); c->base.type = GRPC_CALL_CREDENTIALS_TYPE_JWT; gpr_ref_init(&c->base.refcount, 1); c->base.vtable = &jwt_vtable; c->key = key; c->jwt_lifetime = token_lifetime; gpr_mu_init(&c->cache_mu); jwt_reset_cache(exec_ctx, c); return &c->base; } static char *redact_private_key(const char *json_key) { char *json_copy = gpr_strdup(json_key); grpc_json *json = grpc_json_parse_string(json_copy); if (!json) { gpr_free(json_copy); return gpr_strdup(""); } const char *redacted = ""; grpc_json *current = json->child; while (current) { if (current->type == GRPC_JSON_STRING && strcmp(current->key, "private_key") == 0) { current->value = (char *)redacted; break; } current = current->next; } char *clean_json = grpc_json_dump_to_string(json, 2); gpr_free(json_copy); grpc_json_destroy(json); return clean_json; } grpc_call_credentials *grpc_service_account_jwt_access_credentials_create( const char *json_key, gpr_timespec token_lifetime, void *reserved) { if (grpc_api_trace) { char *clean_json = redact_private_key(json_key); gpr_log(GPR_INFO, "grpc_service_account_jwt_access_credentials_create(" "json_key=%s, " "token_lifetime=" "gpr_timespec { tv_sec: %" PRId64 ", tv_nsec: %d, clock_type: %d }, " "reserved=%p)", clean_json, token_lifetime.tv_sec, token_lifetime.tv_nsec, (int)token_lifetime.clock_type, reserved); gpr_free(clean_json); } GPR_ASSERT(reserved == NULL); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_call_credentials *creds = grpc_service_account_jwt_access_credentials_create_from_auth_json_key( &exec_ctx, grpc_auth_json_key_create_from_string(json_key), token_lifetime); grpc_exec_ctx_finish(&exec_ctx); return creds; } grpc-1.3.2/src/core/lib/security/credentials/jwt/jwt_credentials.h000066400000000000000000000050541310511640000252320ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JWT_CREDENTIALS_H #define GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JWT_CREDENTIALS_H #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/credentials/jwt/json_token.h" typedef struct { grpc_call_credentials base; // Have a simple cache for now with just 1 entry. We could have a map based on // the service_url for a more sophisticated one. gpr_mu cache_mu; struct { grpc_credentials_md_store *jwt_md; char *service_url; gpr_timespec jwt_expiration; } cached; grpc_auth_json_key key; gpr_timespec jwt_lifetime; } grpc_service_account_jwt_access_credentials; // Private constructor for jwt credentials from an already parsed json key. // Takes ownership of the key. grpc_call_credentials * grpc_service_account_jwt_access_credentials_create_from_auth_json_key( grpc_exec_ctx *exec_ctx, grpc_auth_json_key key, gpr_timespec token_lifetime); #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JWT_CREDENTIALS_H */ grpc-1.3.2/src/core/lib/security/credentials/jwt/jwt_verifier.c000066400000000000000000000750271310511640000245520ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/security/credentials/jwt/jwt_verifier.h" #include #include #include #include #include #include #include #include #include "src/core/lib/http/httpcli.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/slice/b64.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/support/string.h" #include "src/core/tsi/ssl_types.h" /* --- Utils. --- */ const char *grpc_jwt_verifier_status_to_string( grpc_jwt_verifier_status status) { switch (status) { case GRPC_JWT_VERIFIER_OK: return "OK"; case GRPC_JWT_VERIFIER_BAD_SIGNATURE: return "BAD_SIGNATURE"; case GRPC_JWT_VERIFIER_BAD_FORMAT: return "BAD_FORMAT"; case GRPC_JWT_VERIFIER_BAD_AUDIENCE: return "BAD_AUDIENCE"; case GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR: return "KEY_RETRIEVAL_ERROR"; case GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE: return "TIME_CONSTRAINT_FAILURE"; case GRPC_JWT_VERIFIER_GENERIC_ERROR: return "GENERIC_ERROR"; default: return "UNKNOWN"; } } static const EVP_MD *evp_md_from_alg(const char *alg) { if (strcmp(alg, "RS256") == 0) { return EVP_sha256(); } else if (strcmp(alg, "RS384") == 0) { return EVP_sha384(); } else if (strcmp(alg, "RS512") == 0) { return EVP_sha512(); } else { return NULL; } } static grpc_json *parse_json_part_from_jwt(grpc_exec_ctx *exec_ctx, const char *str, size_t len, grpc_slice *buffer) { grpc_json *json; *buffer = grpc_base64_decode_with_len(exec_ctx, str, len, 1); if (GRPC_SLICE_IS_EMPTY(*buffer)) { gpr_log(GPR_ERROR, "Invalid base64."); return NULL; } json = grpc_json_parse_string_with_len((char *)GRPC_SLICE_START_PTR(*buffer), GRPC_SLICE_LENGTH(*buffer)); if (json == NULL) { grpc_slice_unref_internal(exec_ctx, *buffer); gpr_log(GPR_ERROR, "JSON parsing error."); } return json; } static const char *validate_string_field(const grpc_json *json, const char *key) { if (json->type != GRPC_JSON_STRING) { gpr_log(GPR_ERROR, "Invalid %s field [%s]", key, json->value); return NULL; } return json->value; } static gpr_timespec validate_time_field(const grpc_json *json, const char *key) { gpr_timespec result = gpr_time_0(GPR_CLOCK_REALTIME); if (json->type != GRPC_JSON_NUMBER) { gpr_log(GPR_ERROR, "Invalid %s field [%s]", key, json->value); return result; } result.tv_sec = strtol(json->value, NULL, 10); return result; } /* --- JOSE header. see http://tools.ietf.org/html/rfc7515#section-4 --- */ typedef struct { const char *alg; const char *kid; const char *typ; /* TODO(jboeuf): Add others as needed (jku, jwk, x5u, x5c and so on...). */ grpc_slice buffer; } jose_header; static void jose_header_destroy(grpc_exec_ctx *exec_ctx, jose_header *h) { grpc_slice_unref_internal(exec_ctx, h->buffer); gpr_free(h); } /* Takes ownership of json and buffer. */ static jose_header *jose_header_from_json(grpc_exec_ctx *exec_ctx, grpc_json *json, grpc_slice buffer) { grpc_json *cur; jose_header *h = gpr_zalloc(sizeof(jose_header)); h->buffer = buffer; for (cur = json->child; cur != NULL; cur = cur->next) { if (strcmp(cur->key, "alg") == 0) { /* We only support RSA-1.5 signatures for now. Beware of this if we add HMAC support: https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/ */ if (cur->type != GRPC_JSON_STRING || strncmp(cur->value, "RS", 2) || evp_md_from_alg(cur->value) == NULL) { gpr_log(GPR_ERROR, "Invalid alg field [%s]", cur->value); goto error; } h->alg = cur->value; } else if (strcmp(cur->key, "typ") == 0) { h->typ = validate_string_field(cur, "typ"); if (h->typ == NULL) goto error; } else if (strcmp(cur->key, "kid") == 0) { h->kid = validate_string_field(cur, "kid"); if (h->kid == NULL) goto error; } } if (h->alg == NULL) { gpr_log(GPR_ERROR, "Missing alg field."); goto error; } grpc_json_destroy(json); h->buffer = buffer; return h; error: grpc_json_destroy(json); jose_header_destroy(exec_ctx, h); return NULL; } /* --- JWT claims. see http://tools.ietf.org/html/rfc7519#section-4.1 */ struct grpc_jwt_claims { /* Well known properties already parsed. */ const char *sub; const char *iss; const char *aud; const char *jti; gpr_timespec iat; gpr_timespec exp; gpr_timespec nbf; grpc_json *json; grpc_slice buffer; }; void grpc_jwt_claims_destroy(grpc_exec_ctx *exec_ctx, grpc_jwt_claims *claims) { grpc_json_destroy(claims->json); grpc_slice_unref_internal(exec_ctx, claims->buffer); gpr_free(claims); } const grpc_json *grpc_jwt_claims_json(const grpc_jwt_claims *claims) { if (claims == NULL) return NULL; return claims->json; } const char *grpc_jwt_claims_subject(const grpc_jwt_claims *claims) { if (claims == NULL) return NULL; return claims->sub; } const char *grpc_jwt_claims_issuer(const grpc_jwt_claims *claims) { if (claims == NULL) return NULL; return claims->iss; } const char *grpc_jwt_claims_id(const grpc_jwt_claims *claims) { if (claims == NULL) return NULL; return claims->jti; } const char *grpc_jwt_claims_audience(const grpc_jwt_claims *claims) { if (claims == NULL) return NULL; return claims->aud; } gpr_timespec grpc_jwt_claims_issued_at(const grpc_jwt_claims *claims) { if (claims == NULL) return gpr_inf_past(GPR_CLOCK_REALTIME); return claims->iat; } gpr_timespec grpc_jwt_claims_expires_at(const grpc_jwt_claims *claims) { if (claims == NULL) return gpr_inf_future(GPR_CLOCK_REALTIME); return claims->exp; } gpr_timespec grpc_jwt_claims_not_before(const grpc_jwt_claims *claims) { if (claims == NULL) return gpr_inf_past(GPR_CLOCK_REALTIME); return claims->nbf; } /* Takes ownership of json and buffer even in case of failure. */ grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_exec_ctx *exec_ctx, grpc_json *json, grpc_slice buffer) { grpc_json *cur; grpc_jwt_claims *claims = gpr_malloc(sizeof(grpc_jwt_claims)); memset(claims, 0, sizeof(grpc_jwt_claims)); claims->json = json; claims->buffer = buffer; claims->iat = gpr_inf_past(GPR_CLOCK_REALTIME); claims->nbf = gpr_inf_past(GPR_CLOCK_REALTIME); claims->exp = gpr_inf_future(GPR_CLOCK_REALTIME); /* Per the spec, all fields are optional. */ for (cur = json->child; cur != NULL; cur = cur->next) { if (strcmp(cur->key, "sub") == 0) { claims->sub = validate_string_field(cur, "sub"); if (claims->sub == NULL) goto error; } else if (strcmp(cur->key, "iss") == 0) { claims->iss = validate_string_field(cur, "iss"); if (claims->iss == NULL) goto error; } else if (strcmp(cur->key, "aud") == 0) { claims->aud = validate_string_field(cur, "aud"); if (claims->aud == NULL) goto error; } else if (strcmp(cur->key, "jti") == 0) { claims->jti = validate_string_field(cur, "jti"); if (claims->jti == NULL) goto error; } else if (strcmp(cur->key, "iat") == 0) { claims->iat = validate_time_field(cur, "iat"); if (gpr_time_cmp(claims->iat, gpr_time_0(GPR_CLOCK_REALTIME)) == 0) goto error; } else if (strcmp(cur->key, "exp") == 0) { claims->exp = validate_time_field(cur, "exp"); if (gpr_time_cmp(claims->exp, gpr_time_0(GPR_CLOCK_REALTIME)) == 0) goto error; } else if (strcmp(cur->key, "nbf") == 0) { claims->nbf = validate_time_field(cur, "nbf"); if (gpr_time_cmp(claims->nbf, gpr_time_0(GPR_CLOCK_REALTIME)) == 0) goto error; } } return claims; error: grpc_jwt_claims_destroy(exec_ctx, claims); return NULL; } grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims, const char *audience) { gpr_timespec skewed_now; int audience_ok; GPR_ASSERT(claims != NULL); skewed_now = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew); if (gpr_time_cmp(skewed_now, claims->nbf) < 0) { gpr_log(GPR_ERROR, "JWT is not valid yet."); return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE; } skewed_now = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew); if (gpr_time_cmp(skewed_now, claims->exp) > 0) { gpr_log(GPR_ERROR, "JWT is expired."); return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE; } /* This should be probably up to the upper layer to decide but let's harcode the 99% use case here for email issuers, where the JWT must be self issued. */ if (grpc_jwt_issuer_email_domain(claims->iss) != NULL && claims->sub != NULL && strcmp(claims->iss, claims->sub) != 0) { gpr_log(GPR_ERROR, "Email issuer (%s) cannot assert another subject (%s) than itself.", claims->iss, claims->sub); return GRPC_JWT_VERIFIER_BAD_SUBJECT; } if (audience == NULL) { audience_ok = claims->aud == NULL; } else { audience_ok = claims->aud != NULL && strcmp(audience, claims->aud) == 0; } if (!audience_ok) { gpr_log(GPR_ERROR, "Audience mismatch: expected %s and found %s.", audience == NULL ? "NULL" : audience, claims->aud == NULL ? "NULL" : claims->aud); return GRPC_JWT_VERIFIER_BAD_AUDIENCE; } return GRPC_JWT_VERIFIER_OK; } /* --- verifier_cb_ctx object. --- */ typedef enum { HTTP_RESPONSE_OPENID = 0, HTTP_RESPONSE_KEYS, HTTP_RESPONSE_COUNT /* must be last */ } http_response_index; typedef struct { grpc_jwt_verifier *verifier; grpc_polling_entity pollent; jose_header *header; grpc_jwt_claims *claims; char *audience; grpc_slice signature; grpc_slice signed_data; void *user_data; grpc_jwt_verification_done_cb user_cb; grpc_http_response responses[HTTP_RESPONSE_COUNT]; } verifier_cb_ctx; /* Takes ownership of the header, claims and signature. */ static verifier_cb_ctx *verifier_cb_ctx_create( grpc_jwt_verifier *verifier, grpc_pollset *pollset, jose_header *header, grpc_jwt_claims *claims, const char *audience, grpc_slice signature, const char *signed_jwt, size_t signed_jwt_len, void *user_data, grpc_jwt_verification_done_cb cb) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; verifier_cb_ctx *ctx = gpr_zalloc(sizeof(verifier_cb_ctx)); ctx->verifier = verifier; ctx->pollent = grpc_polling_entity_create_from_pollset(pollset); ctx->header = header; ctx->audience = gpr_strdup(audience); ctx->claims = claims; ctx->signature = signature; ctx->signed_data = grpc_slice_from_copied_buffer(signed_jwt, signed_jwt_len); ctx->user_data = user_data; ctx->user_cb = cb; grpc_exec_ctx_finish(&exec_ctx); return ctx; } void verifier_cb_ctx_destroy(grpc_exec_ctx *exec_ctx, verifier_cb_ctx *ctx) { if (ctx->audience != NULL) gpr_free(ctx->audience); if (ctx->claims != NULL) grpc_jwt_claims_destroy(exec_ctx, ctx->claims); grpc_slice_unref_internal(exec_ctx, ctx->signature); grpc_slice_unref_internal(exec_ctx, ctx->signed_data); jose_header_destroy(exec_ctx, ctx->header); for (size_t i = 0; i < HTTP_RESPONSE_COUNT; i++) { grpc_http_response_destroy(&ctx->responses[i]); } /* TODO: see what to do with claims... */ gpr_free(ctx); } /* --- grpc_jwt_verifier object. --- */ /* Clock skew defaults to one minute. */ gpr_timespec grpc_jwt_verifier_clock_skew = {60, 0, GPR_TIMESPAN}; /* Max delay defaults to one minute. */ gpr_timespec grpc_jwt_verifier_max_delay = {60, 0, GPR_TIMESPAN}; typedef struct { char *email_domain; char *key_url_prefix; } email_key_mapping; struct grpc_jwt_verifier { email_key_mapping *mappings; size_t num_mappings; /* Should be very few, linear search ok. */ size_t allocated_mappings; grpc_httpcli_context http_ctx; }; static grpc_json *json_from_http(const grpc_httpcli_response *response) { grpc_json *json = NULL; if (response == NULL) { gpr_log(GPR_ERROR, "HTTP response is NULL."); return NULL; } if (response->status != 200) { gpr_log(GPR_ERROR, "Call to http server failed with error %d.", response->status); return NULL; } json = grpc_json_parse_string_with_len(response->body, response->body_length); if (json == NULL) { gpr_log(GPR_ERROR, "Invalid JSON found in response."); } return json; } static const grpc_json *find_property_by_name(const grpc_json *json, const char *name) { const grpc_json *cur; for (cur = json->child; cur != NULL; cur = cur->next) { if (strcmp(cur->key, name) == 0) return cur; } return NULL; } static EVP_PKEY *extract_pkey_from_x509(const char *x509_str) { X509 *x509 = NULL; EVP_PKEY *result = NULL; BIO *bio = BIO_new(BIO_s_mem()); size_t len = strlen(x509_str); GPR_ASSERT(len < INT_MAX); BIO_write(bio, x509_str, (int)len); x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); if (x509 == NULL) { gpr_log(GPR_ERROR, "Unable to parse x509 cert."); goto end; } result = X509_get_pubkey(x509); if (result == NULL) { gpr_log(GPR_ERROR, "Cannot find public key in X509 cert."); } end: BIO_free(bio); if (x509 != NULL) X509_free(x509); return result; } static BIGNUM *bignum_from_base64(grpc_exec_ctx *exec_ctx, const char *b64) { BIGNUM *result = NULL; grpc_slice bin; if (b64 == NULL) return NULL; bin = grpc_base64_decode(exec_ctx, b64, 1); if (GRPC_SLICE_IS_EMPTY(bin)) { gpr_log(GPR_ERROR, "Invalid base64 for big num."); return NULL; } result = BN_bin2bn(GRPC_SLICE_START_PTR(bin), TSI_SIZE_AS_SIZE(GRPC_SLICE_LENGTH(bin)), NULL); grpc_slice_unref_internal(exec_ctx, bin); return result; } static EVP_PKEY *pkey_from_jwk(grpc_exec_ctx *exec_ctx, const grpc_json *json, const char *kty) { const grpc_json *key_prop; RSA *rsa = NULL; EVP_PKEY *result = NULL; GPR_ASSERT(kty != NULL && json != NULL); if (strcmp(kty, "RSA") != 0) { gpr_log(GPR_ERROR, "Unsupported key type %s.", kty); goto end; } rsa = RSA_new(); if (rsa == NULL) { gpr_log(GPR_ERROR, "Could not create rsa key."); goto end; } for (key_prop = json->child; key_prop != NULL; key_prop = key_prop->next) { if (strcmp(key_prop->key, "n") == 0) { rsa->n = bignum_from_base64(exec_ctx, validate_string_field(key_prop, "n")); if (rsa->n == NULL) goto end; } else if (strcmp(key_prop->key, "e") == 0) { rsa->e = bignum_from_base64(exec_ctx, validate_string_field(key_prop, "e")); if (rsa->e == NULL) goto end; } } if (rsa->e == NULL || rsa->n == NULL) { gpr_log(GPR_ERROR, "Missing RSA public key field."); goto end; } result = EVP_PKEY_new(); EVP_PKEY_set1_RSA(result, rsa); /* uprefs rsa. */ end: if (rsa != NULL) RSA_free(rsa); return result; } static EVP_PKEY *find_verification_key(grpc_exec_ctx *exec_ctx, const grpc_json *json, const char *header_alg, const char *header_kid) { const grpc_json *jkey; const grpc_json *jwk_keys; /* Try to parse the json as a JWK set: https://tools.ietf.org/html/rfc7517#section-5. */ jwk_keys = find_property_by_name(json, "keys"); if (jwk_keys == NULL) { /* Use the google proprietary format which is: { : , : , ... } */ const grpc_json *cur = find_property_by_name(json, header_kid); if (cur == NULL) return NULL; return extract_pkey_from_x509(cur->value); } if (jwk_keys->type != GRPC_JSON_ARRAY) { gpr_log(GPR_ERROR, "Unexpected value type of keys property in jwks key set."); return NULL; } /* Key format is specified in: https://tools.ietf.org/html/rfc7518#section-6. */ for (jkey = jwk_keys->child; jkey != NULL; jkey = jkey->next) { grpc_json *key_prop; const char *alg = NULL; const char *kid = NULL; const char *kty = NULL; if (jkey->type != GRPC_JSON_OBJECT) continue; for (key_prop = jkey->child; key_prop != NULL; key_prop = key_prop->next) { if (strcmp(key_prop->key, "alg") == 0 && key_prop->type == GRPC_JSON_STRING) { alg = key_prop->value; } else if (strcmp(key_prop->key, "kid") == 0 && key_prop->type == GRPC_JSON_STRING) { kid = key_prop->value; } else if (strcmp(key_prop->key, "kty") == 0 && key_prop->type == GRPC_JSON_STRING) { kty = key_prop->value; } } if (alg != NULL && kid != NULL && kty != NULL && strcmp(kid, header_kid) == 0 && strcmp(alg, header_alg) == 0) { return pkey_from_jwk(exec_ctx, jkey, kty); } } gpr_log(GPR_ERROR, "Could not find matching key in key set for kid=%s and alg=%s", header_kid, header_alg); return NULL; } static int verify_jwt_signature(EVP_PKEY *key, const char *alg, grpc_slice signature, grpc_slice signed_data) { EVP_MD_CTX *md_ctx = EVP_MD_CTX_create(); const EVP_MD *md = evp_md_from_alg(alg); int result = 0; GPR_ASSERT(md != NULL); /* Checked before. */ if (md_ctx == NULL) { gpr_log(GPR_ERROR, "Could not create EVP_MD_CTX."); goto end; } if (EVP_DigestVerifyInit(md_ctx, NULL, md, NULL, key) != 1) { gpr_log(GPR_ERROR, "EVP_DigestVerifyInit failed."); goto end; } if (EVP_DigestVerifyUpdate(md_ctx, GRPC_SLICE_START_PTR(signed_data), GRPC_SLICE_LENGTH(signed_data)) != 1) { gpr_log(GPR_ERROR, "EVP_DigestVerifyUpdate failed."); goto end; } if (EVP_DigestVerifyFinal(md_ctx, GRPC_SLICE_START_PTR(signature), GRPC_SLICE_LENGTH(signature)) != 1) { gpr_log(GPR_ERROR, "JWT signature verification failed."); goto end; } result = 1; end: if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx); return result; } static void on_keys_retrieved(grpc_exec_ctx *exec_ctx, void *user_data, grpc_error *error) { verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data; grpc_json *json = json_from_http(&ctx->responses[HTTP_RESPONSE_KEYS]); EVP_PKEY *verification_key = NULL; grpc_jwt_verifier_status status = GRPC_JWT_VERIFIER_GENERIC_ERROR; grpc_jwt_claims *claims = NULL; if (json == NULL) { status = GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR; goto end; } verification_key = find_verification_key(exec_ctx, json, ctx->header->alg, ctx->header->kid); if (verification_key == NULL) { gpr_log(GPR_ERROR, "Could not find verification key with kid %s.", ctx->header->kid); status = GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR; goto end; } if (!verify_jwt_signature(verification_key, ctx->header->alg, ctx->signature, ctx->signed_data)) { status = GRPC_JWT_VERIFIER_BAD_SIGNATURE; goto end; } status = grpc_jwt_claims_check(ctx->claims, ctx->audience); if (status == GRPC_JWT_VERIFIER_OK) { /* Pass ownership. */ claims = ctx->claims; ctx->claims = NULL; } end: if (json != NULL) grpc_json_destroy(json); if (verification_key != NULL) EVP_PKEY_free(verification_key); ctx->user_cb(exec_ctx, ctx->user_data, status, claims); verifier_cb_ctx_destroy(exec_ctx, ctx); } static void on_openid_config_retrieved(grpc_exec_ctx *exec_ctx, void *user_data, grpc_error *error) { const grpc_json *cur; verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data; const grpc_http_response *response = &ctx->responses[HTTP_RESPONSE_OPENID]; grpc_json *json = json_from_http(response); grpc_httpcli_request req; const char *jwks_uri; /* TODO(jboeuf): Cache the jwks_uri in order to avoid this hop next time. */ if (json == NULL) goto error; cur = find_property_by_name(json, "jwks_uri"); if (cur == NULL) { gpr_log(GPR_ERROR, "Could not find jwks_uri in openid config."); goto error; } jwks_uri = validate_string_field(cur, "jwks_uri"); if (jwks_uri == NULL) goto error; if (strstr(jwks_uri, "https://") != jwks_uri) { gpr_log(GPR_ERROR, "Invalid non https jwks_uri: %s.", jwks_uri); goto error; } jwks_uri += 8; req.handshaker = &grpc_httpcli_ssl; req.host = gpr_strdup(jwks_uri); req.http.path = strchr(jwks_uri, '/'); if (req.http.path == NULL) { req.http.path = ""; } else { *(req.host + (req.http.path - jwks_uri)) = '\0'; } /* TODO(ctiller): Carry the resource_quota in ctx and share it with the host channel. This would allow us to cancel an authentication query when under extreme memory pressure. */ grpc_resource_quota *resource_quota = grpc_resource_quota_create("jwt_verifier"); grpc_httpcli_get( exec_ctx, &ctx->verifier->http_ctx, &ctx->pollent, resource_quota, &req, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay), grpc_closure_create(on_keys_retrieved, ctx, grpc_schedule_on_exec_ctx), &ctx->responses[HTTP_RESPONSE_KEYS]); grpc_resource_quota_unref_internal(exec_ctx, resource_quota); grpc_json_destroy(json); gpr_free(req.host); return; error: if (json != NULL) grpc_json_destroy(json); ctx->user_cb(exec_ctx, ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL); verifier_cb_ctx_destroy(exec_ctx, ctx); } static email_key_mapping *verifier_get_mapping(grpc_jwt_verifier *v, const char *email_domain) { size_t i; if (v->mappings == NULL) return NULL; for (i = 0; i < v->num_mappings; i++) { if (strcmp(email_domain, v->mappings[i].email_domain) == 0) { return &v->mappings[i]; } } return NULL; } static void verifier_put_mapping(grpc_jwt_verifier *v, const char *email_domain, const char *key_url_prefix) { email_key_mapping *mapping = verifier_get_mapping(v, email_domain); GPR_ASSERT(v->num_mappings < v->allocated_mappings); if (mapping != NULL) { gpr_free(mapping->key_url_prefix); mapping->key_url_prefix = gpr_strdup(key_url_prefix); return; } v->mappings[v->num_mappings].email_domain = gpr_strdup(email_domain); v->mappings[v->num_mappings].key_url_prefix = gpr_strdup(key_url_prefix); v->num_mappings++; GPR_ASSERT(v->num_mappings <= v->allocated_mappings); } /* Very non-sophisticated way to detect an email address. Should be good enough for now... */ const char *grpc_jwt_issuer_email_domain(const char *issuer) { const char *at_sign = strchr(issuer, '@'); if (at_sign == NULL) return NULL; const char *email_domain = at_sign + 1; if (*email_domain == '\0') return NULL; const char *dot = strrchr(email_domain, '.'); if (dot == NULL || dot == email_domain) return email_domain; GPR_ASSERT(dot > email_domain); /* There may be a subdomain, we just want the domain. */ dot = gpr_memrchr(email_domain, '.', (size_t)(dot - email_domain)); if (dot == NULL) return email_domain; return dot + 1; } /* Takes ownership of ctx. */ static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx, verifier_cb_ctx *ctx) { const char *email_domain; grpc_closure *http_cb; char *path_prefix = NULL; const char *iss; grpc_httpcli_request req; memset(&req, 0, sizeof(grpc_httpcli_request)); req.handshaker = &grpc_httpcli_ssl; http_response_index rsp_idx; GPR_ASSERT(ctx != NULL && ctx->header != NULL && ctx->claims != NULL); iss = ctx->claims->iss; if (ctx->header->kid == NULL) { gpr_log(GPR_ERROR, "Missing kid in jose header."); goto error; } if (iss == NULL) { gpr_log(GPR_ERROR, "Missing iss in claims."); goto error; } /* This code relies on: https://openid.net/specs/openid-connect-discovery-1_0.html Nobody seems to implement the account/email/webfinger part 2. of the spec so we will rely instead on email/url mappings if we detect such an issuer. Part 4, on the other hand is implemented by both google and salesforce. */ email_domain = grpc_jwt_issuer_email_domain(iss); if (email_domain != NULL) { email_key_mapping *mapping; GPR_ASSERT(ctx->verifier != NULL); mapping = verifier_get_mapping(ctx->verifier, email_domain); if (mapping == NULL) { gpr_log(GPR_ERROR, "Missing mapping for issuer email."); goto error; } req.host = gpr_strdup(mapping->key_url_prefix); path_prefix = strchr(req.host, '/'); if (path_prefix == NULL) { gpr_asprintf(&req.http.path, "/%s", iss); } else { *(path_prefix++) = '\0'; gpr_asprintf(&req.http.path, "/%s/%s", path_prefix, iss); } http_cb = grpc_closure_create(on_keys_retrieved, ctx, grpc_schedule_on_exec_ctx); rsp_idx = HTTP_RESPONSE_KEYS; } else { req.host = gpr_strdup(strstr(iss, "https://") == iss ? iss + 8 : iss); path_prefix = strchr(req.host, '/'); if (path_prefix == NULL) { req.http.path = gpr_strdup(GRPC_OPENID_CONFIG_URL_SUFFIX); } else { *(path_prefix++) = 0; gpr_asprintf(&req.http.path, "/%s%s", path_prefix, GRPC_OPENID_CONFIG_URL_SUFFIX); } http_cb = grpc_closure_create(on_openid_config_retrieved, ctx, grpc_schedule_on_exec_ctx); rsp_idx = HTTP_RESPONSE_OPENID; } /* TODO(ctiller): Carry the resource_quota in ctx and share it with the host channel. This would allow us to cancel an authentication query when under extreme memory pressure. */ grpc_resource_quota *resource_quota = grpc_resource_quota_create("jwt_verifier"); grpc_httpcli_get( exec_ctx, &ctx->verifier->http_ctx, &ctx->pollent, resource_quota, &req, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay), http_cb, &ctx->responses[rsp_idx]); grpc_resource_quota_unref_internal(exec_ctx, resource_quota); gpr_free(req.host); gpr_free(req.http.path); return; error: ctx->user_cb(exec_ctx, ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL); verifier_cb_ctx_destroy(exec_ctx, ctx); } void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx, grpc_jwt_verifier *verifier, grpc_pollset *pollset, const char *jwt, const char *audience, grpc_jwt_verification_done_cb cb, void *user_data) { const char *dot = NULL; grpc_json *json; jose_header *header = NULL; grpc_jwt_claims *claims = NULL; grpc_slice header_buffer; grpc_slice claims_buffer; grpc_slice signature; size_t signed_jwt_len; const char *cur = jwt; GPR_ASSERT(verifier != NULL && jwt != NULL && audience != NULL && cb != NULL); dot = strchr(cur, '.'); if (dot == NULL) goto error; json = parse_json_part_from_jwt(exec_ctx, cur, (size_t)(dot - cur), &header_buffer); if (json == NULL) goto error; header = jose_header_from_json(exec_ctx, json, header_buffer); if (header == NULL) goto error; cur = dot + 1; dot = strchr(cur, '.'); if (dot == NULL) goto error; json = parse_json_part_from_jwt(exec_ctx, cur, (size_t)(dot - cur), &claims_buffer); if (json == NULL) goto error; claims = grpc_jwt_claims_from_json(exec_ctx, json, claims_buffer); if (claims == NULL) goto error; signed_jwt_len = (size_t)(dot - jwt); cur = dot + 1; signature = grpc_base64_decode(exec_ctx, cur, 1); if (GRPC_SLICE_IS_EMPTY(signature)) goto error; retrieve_key_and_verify( exec_ctx, verifier_cb_ctx_create(verifier, pollset, header, claims, audience, signature, jwt, signed_jwt_len, user_data, cb)); return; error: if (header != NULL) jose_header_destroy(exec_ctx, header); if (claims != NULL) grpc_jwt_claims_destroy(exec_ctx, claims); cb(exec_ctx, user_data, GRPC_JWT_VERIFIER_BAD_FORMAT, NULL); } grpc_jwt_verifier *grpc_jwt_verifier_create( const grpc_jwt_verifier_email_domain_key_url_mapping *mappings, size_t num_mappings) { grpc_jwt_verifier *v = gpr_zalloc(sizeof(grpc_jwt_verifier)); grpc_httpcli_context_init(&v->http_ctx); /* We know at least of one mapping. */ v->allocated_mappings = 1 + num_mappings; v->mappings = gpr_malloc(v->allocated_mappings * sizeof(email_key_mapping)); verifier_put_mapping(v, GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN, GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX); /* User-Provided mappings. */ if (mappings != NULL) { size_t i; for (i = 0; i < num_mappings; i++) { verifier_put_mapping(v, mappings[i].email_domain, mappings[i].key_url_prefix); } } return v; } void grpc_jwt_verifier_destroy(grpc_exec_ctx *exec_ctx, grpc_jwt_verifier *v) { size_t i; if (v == NULL) return; grpc_httpcli_context_destroy(exec_ctx, &v->http_ctx); if (v->mappings != NULL) { for (i = 0; i < v->num_mappings; i++) { gpr_free(v->mappings[i].email_domain); gpr_free(v->mappings[i].key_url_prefix); } gpr_free(v->mappings); } gpr_free(v); } grpc-1.3.2/src/core/lib/security/credentials/jwt/jwt_verifier.h000066400000000000000000000137101310511640000245460ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JWT_VERIFIER_H #define GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JWT_VERIFIER_H #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/json/json.h" #include #include /* --- Constants. --- */ #define GRPC_OPENID_CONFIG_URL_SUFFIX "/.well-known/openid-configuration" #define GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN "gserviceaccount.com" #define GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX \ "www.googleapis.com/robot/v1/metadata/x509" /* --- grpc_jwt_verifier_status. --- */ typedef enum { GRPC_JWT_VERIFIER_OK = 0, GRPC_JWT_VERIFIER_BAD_SIGNATURE, GRPC_JWT_VERIFIER_BAD_FORMAT, GRPC_JWT_VERIFIER_BAD_AUDIENCE, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE, GRPC_JWT_VERIFIER_BAD_SUBJECT, GRPC_JWT_VERIFIER_GENERIC_ERROR } grpc_jwt_verifier_status; const char *grpc_jwt_verifier_status_to_string(grpc_jwt_verifier_status status); /* --- grpc_jwt_claims. --- */ typedef struct grpc_jwt_claims grpc_jwt_claims; void grpc_jwt_claims_destroy(grpc_exec_ctx *exec_ctx, grpc_jwt_claims *claims); /* Returns the whole JSON tree of the claims. */ const grpc_json *grpc_jwt_claims_json(const grpc_jwt_claims *claims); /* Access to registered claims in https://tools.ietf.org/html/rfc7519#page-9 */ const char *grpc_jwt_claims_subject(const grpc_jwt_claims *claims); const char *grpc_jwt_claims_issuer(const grpc_jwt_claims *claims); const char *grpc_jwt_claims_id(const grpc_jwt_claims *claims); const char *grpc_jwt_claims_audience(const grpc_jwt_claims *claims); gpr_timespec grpc_jwt_claims_issued_at(const grpc_jwt_claims *claims); gpr_timespec grpc_jwt_claims_expires_at(const grpc_jwt_claims *claims); gpr_timespec grpc_jwt_claims_not_before(const grpc_jwt_claims *claims); /* --- grpc_jwt_verifier. --- */ typedef struct grpc_jwt_verifier grpc_jwt_verifier; typedef struct { /* The email domain is the part after the @ sign. */ const char *email_domain; /* The key url prefix will be used to get the public key from the issuer: https:/// Therefore the key_url_prefix must NOT contain https://. */ const char *key_url_prefix; } grpc_jwt_verifier_email_domain_key_url_mapping; /* Globals to control the verifier. Not thread-safe. */ extern gpr_timespec grpc_jwt_verifier_clock_skew; extern gpr_timespec grpc_jwt_verifier_max_delay; /* The verifier can be created with some custom mappings to help with key discovery in the case where the issuer is an email address. mappings can be NULL in which case num_mappings MUST be 0. A verifier object has one built-in mapping (unless overridden): GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN -> GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX.*/ grpc_jwt_verifier *grpc_jwt_verifier_create( const grpc_jwt_verifier_email_domain_key_url_mapping *mappings, size_t num_mappings); /*The verifier must not be destroyed if there are still outstanding callbacks.*/ void grpc_jwt_verifier_destroy(grpc_exec_ctx *exec_ctx, grpc_jwt_verifier *verifier); /* User provided callback that will be called when the verification of the JWT is done (maybe in another thread). It is the responsibility of the callee to call grpc_jwt_claims_destroy on the claims. */ typedef void (*grpc_jwt_verification_done_cb)(grpc_exec_ctx *exec_ctx, void *user_data, grpc_jwt_verifier_status status, grpc_jwt_claims *claims); /* Verifies for the JWT for the given expected audience. */ void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx, grpc_jwt_verifier *verifier, grpc_pollset *pollset, const char *jwt, const char *audience, grpc_jwt_verification_done_cb cb, void *user_data); /* --- TESTING ONLY exposed functions. --- */ grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_exec_ctx *exec_ctx, grpc_json *json, grpc_slice buffer); grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims, const char *audience); const char *grpc_jwt_issuer_email_domain(const char *issuer); #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JWT_VERIFIER_H */ grpc-1.3.2/src/core/lib/security/credentials/oauth2/000077500000000000000000000000001310511640000222725ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/security/credentials/oauth2/oauth2_credentials.c000066400000000000000000000433171310511640000262250ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h" #include #include "src/core/lib/security/util/json_util.h" #include "src/core/lib/surface/api_trace.h" #include #include #include // // Auth Refresh Token. // int grpc_auth_refresh_token_is_valid( const grpc_auth_refresh_token *refresh_token) { return (refresh_token != NULL) && strcmp(refresh_token->type, GRPC_AUTH_JSON_TYPE_INVALID); } grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json( const grpc_json *json) { grpc_auth_refresh_token result; const char *prop_value; int success = 0; memset(&result, 0, sizeof(grpc_auth_refresh_token)); result.type = GRPC_AUTH_JSON_TYPE_INVALID; if (json == NULL) { gpr_log(GPR_ERROR, "Invalid json."); goto end; } prop_value = grpc_json_get_string_property(json, "type"); if (prop_value == NULL || strcmp(prop_value, GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER)) { goto end; } result.type = GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER; if (!grpc_copy_json_string_property(json, "client_secret", &result.client_secret) || !grpc_copy_json_string_property(json, "client_id", &result.client_id) || !grpc_copy_json_string_property(json, "refresh_token", &result.refresh_token)) { goto end; } success = 1; end: if (!success) grpc_auth_refresh_token_destruct(&result); return result; } grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string( const char *json_string) { char *scratchpad = gpr_strdup(json_string); grpc_json *json = grpc_json_parse_string(scratchpad); grpc_auth_refresh_token result = grpc_auth_refresh_token_create_from_json(json); if (json != NULL) grpc_json_destroy(json); gpr_free(scratchpad); return result; } void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token) { if (refresh_token == NULL) return; refresh_token->type = GRPC_AUTH_JSON_TYPE_INVALID; if (refresh_token->client_id != NULL) { gpr_free(refresh_token->client_id); refresh_token->client_id = NULL; } if (refresh_token->client_secret != NULL) { gpr_free(refresh_token->client_secret); refresh_token->client_secret = NULL; } if (refresh_token->refresh_token != NULL) { gpr_free(refresh_token->refresh_token); refresh_token->refresh_token = NULL; } } // // Oauth2 Token Fetcher credentials. // static void oauth2_token_fetcher_destruct(grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds) { grpc_oauth2_token_fetcher_credentials *c = (grpc_oauth2_token_fetcher_credentials *)creds; grpc_credentials_md_store_unref(exec_ctx, c->access_token_md); gpr_mu_destroy(&c->mu); grpc_httpcli_context_destroy(exec_ctx, &c->httpcli_context); } grpc_credentials_status grpc_oauth2_token_fetcher_credentials_parse_server_response( grpc_exec_ctx *exec_ctx, const grpc_http_response *response, grpc_credentials_md_store **token_md, gpr_timespec *token_lifetime) { char *null_terminated_body = NULL; char *new_access_token = NULL; grpc_credentials_status status = GRPC_CREDENTIALS_OK; grpc_json *json = NULL; if (response == NULL) { gpr_log(GPR_ERROR, "Received NULL response."); status = GRPC_CREDENTIALS_ERROR; goto end; } if (response->body_length > 0) { null_terminated_body = gpr_malloc(response->body_length + 1); null_terminated_body[response->body_length] = '\0'; memcpy(null_terminated_body, response->body, response->body_length); } if (response->status != 200) { gpr_log(GPR_ERROR, "Call to http server ended with error %d [%s].", response->status, null_terminated_body != NULL ? null_terminated_body : ""); status = GRPC_CREDENTIALS_ERROR; goto end; } else { grpc_json *access_token = NULL; grpc_json *token_type = NULL; grpc_json *expires_in = NULL; grpc_json *ptr; json = grpc_json_parse_string(null_terminated_body); if (json == NULL) { gpr_log(GPR_ERROR, "Could not parse JSON from %s", null_terminated_body); status = GRPC_CREDENTIALS_ERROR; goto end; } if (json->type != GRPC_JSON_OBJECT) { gpr_log(GPR_ERROR, "Response should be a JSON object"); status = GRPC_CREDENTIALS_ERROR; goto end; } for (ptr = json->child; ptr; ptr = ptr->next) { if (strcmp(ptr->key, "access_token") == 0) { access_token = ptr; } else if (strcmp(ptr->key, "token_type") == 0) { token_type = ptr; } else if (strcmp(ptr->key, "expires_in") == 0) { expires_in = ptr; } } if (access_token == NULL || access_token->type != GRPC_JSON_STRING) { gpr_log(GPR_ERROR, "Missing or invalid access_token in JSON."); status = GRPC_CREDENTIALS_ERROR; goto end; } if (token_type == NULL || token_type->type != GRPC_JSON_STRING) { gpr_log(GPR_ERROR, "Missing or invalid token_type in JSON."); status = GRPC_CREDENTIALS_ERROR; goto end; } if (expires_in == NULL || expires_in->type != GRPC_JSON_NUMBER) { gpr_log(GPR_ERROR, "Missing or invalid expires_in in JSON."); status = GRPC_CREDENTIALS_ERROR; goto end; } gpr_asprintf(&new_access_token, "%s %s", token_type->value, access_token->value); token_lifetime->tv_sec = strtol(expires_in->value, NULL, 10); token_lifetime->tv_nsec = 0; token_lifetime->clock_type = GPR_TIMESPAN; if (*token_md != NULL) grpc_credentials_md_store_unref(exec_ctx, *token_md); *token_md = grpc_credentials_md_store_create(1); grpc_credentials_md_store_add_cstrings( *token_md, GRPC_AUTHORIZATION_METADATA_KEY, new_access_token); status = GRPC_CREDENTIALS_OK; } end: if (status != GRPC_CREDENTIALS_OK && (*token_md != NULL)) { grpc_credentials_md_store_unref(exec_ctx, *token_md); *token_md = NULL; } if (null_terminated_body != NULL) gpr_free(null_terminated_body); if (new_access_token != NULL) gpr_free(new_access_token); if (json != NULL) grpc_json_destroy(json); return status; } static void on_oauth2_token_fetcher_http_response(grpc_exec_ctx *exec_ctx, void *user_data, grpc_error *error) { grpc_credentials_metadata_request *r = (grpc_credentials_metadata_request *)user_data; grpc_oauth2_token_fetcher_credentials *c = (grpc_oauth2_token_fetcher_credentials *)r->creds; gpr_timespec token_lifetime; grpc_credentials_status status; GRPC_LOG_IF_ERROR("oauth_fetch", GRPC_ERROR_REF(error)); gpr_mu_lock(&c->mu); status = grpc_oauth2_token_fetcher_credentials_parse_server_response( exec_ctx, &r->response, &c->access_token_md, &token_lifetime); if (status == GRPC_CREDENTIALS_OK) { c->token_expiration = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime); r->cb(exec_ctx, r->user_data, c->access_token_md->entries, c->access_token_md->num_entries, GRPC_CREDENTIALS_OK, NULL); } else { c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME); r->cb(exec_ctx, r->user_data, NULL, 0, status, "Error occured when fetching oauth2 token."); } gpr_mu_unlock(&c->mu); grpc_credentials_metadata_request_destroy(exec_ctx, r); } static void oauth2_token_fetcher_get_request_metadata( grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_polling_entity *pollent, grpc_auth_metadata_context context, grpc_credentials_metadata_cb cb, void *user_data) { grpc_oauth2_token_fetcher_credentials *c = (grpc_oauth2_token_fetcher_credentials *)creds; gpr_timespec refresh_threshold = gpr_time_from_seconds( GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN); grpc_credentials_md_store *cached_access_token_md = NULL; { gpr_mu_lock(&c->mu); if (c->access_token_md != NULL && (gpr_time_cmp( gpr_time_sub(c->token_expiration, gpr_now(GPR_CLOCK_REALTIME)), refresh_threshold) > 0)) { cached_access_token_md = grpc_credentials_md_store_ref(c->access_token_md); } gpr_mu_unlock(&c->mu); } if (cached_access_token_md != NULL) { cb(exec_ctx, user_data, cached_access_token_md->entries, cached_access_token_md->num_entries, GRPC_CREDENTIALS_OK, NULL); grpc_credentials_md_store_unref(exec_ctx, cached_access_token_md); } else { c->fetch_func( exec_ctx, grpc_credentials_metadata_request_create(creds, cb, user_data), &c->httpcli_context, pollent, on_oauth2_token_fetcher_http_response, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), refresh_threshold)); } } static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c, grpc_fetch_oauth2_func fetch_func) { memset(c, 0, sizeof(grpc_oauth2_token_fetcher_credentials)); c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2; gpr_ref_init(&c->base.refcount, 1); gpr_mu_init(&c->mu); c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME); c->fetch_func = fetch_func; grpc_httpcli_context_init(&c->httpcli_context); } // // Google Compute Engine credentials. // static grpc_call_credentials_vtable compute_engine_vtable = { oauth2_token_fetcher_destruct, oauth2_token_fetcher_get_request_metadata}; static void compute_engine_fetch_oauth2( grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req, grpc_httpcli_context *httpcli_context, grpc_polling_entity *pollent, grpc_iomgr_cb_func response_cb, gpr_timespec deadline) { grpc_http_header header = {"Metadata-Flavor", "Google"}; grpc_httpcli_request request; memset(&request, 0, sizeof(grpc_httpcli_request)); request.host = GRPC_COMPUTE_ENGINE_METADATA_HOST; request.http.path = GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH; request.http.hdr_count = 1; request.http.hdrs = &header; /* TODO(ctiller): Carry the resource_quota in ctx and share it with the host channel. This would allow us to cancel an authentication query when under extreme memory pressure. */ grpc_resource_quota *resource_quota = grpc_resource_quota_create("oauth2_credentials"); grpc_httpcli_get( exec_ctx, httpcli_context, pollent, resource_quota, &request, deadline, grpc_closure_create(response_cb, metadata_req, grpc_schedule_on_exec_ctx), &metadata_req->response); grpc_resource_quota_unref_internal(exec_ctx, resource_quota); } grpc_call_credentials *grpc_google_compute_engine_credentials_create( void *reserved) { grpc_oauth2_token_fetcher_credentials *c = gpr_malloc(sizeof(grpc_oauth2_token_fetcher_credentials)); GRPC_API_TRACE("grpc_compute_engine_credentials_create(reserved=%p)", 1, (reserved)); GPR_ASSERT(reserved == NULL); init_oauth2_token_fetcher(c, compute_engine_fetch_oauth2); c->base.vtable = &compute_engine_vtable; return &c->base; } // // Google Refresh Token credentials. // static void refresh_token_destruct(grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds) { grpc_google_refresh_token_credentials *c = (grpc_google_refresh_token_credentials *)creds; grpc_auth_refresh_token_destruct(&c->refresh_token); oauth2_token_fetcher_destruct(exec_ctx, &c->base.base); } static grpc_call_credentials_vtable refresh_token_vtable = { refresh_token_destruct, oauth2_token_fetcher_get_request_metadata}; static void refresh_token_fetch_oauth2( grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req, grpc_httpcli_context *httpcli_context, grpc_polling_entity *pollent, grpc_iomgr_cb_func response_cb, gpr_timespec deadline) { grpc_google_refresh_token_credentials *c = (grpc_google_refresh_token_credentials *)metadata_req->creds; grpc_http_header header = {"Content-Type", "application/x-www-form-urlencoded"}; grpc_httpcli_request request; char *body = NULL; gpr_asprintf(&body, GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING, c->refresh_token.client_id, c->refresh_token.client_secret, c->refresh_token.refresh_token); memset(&request, 0, sizeof(grpc_httpcli_request)); request.host = GRPC_GOOGLE_OAUTH2_SERVICE_HOST; request.http.path = GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH; request.http.hdr_count = 1; request.http.hdrs = &header; request.handshaker = &grpc_httpcli_ssl; /* TODO(ctiller): Carry the resource_quota in ctx and share it with the host channel. This would allow us to cancel an authentication query when under extreme memory pressure. */ grpc_resource_quota *resource_quota = grpc_resource_quota_create("oauth2_credentials_refresh"); grpc_httpcli_post( exec_ctx, httpcli_context, pollent, resource_quota, &request, body, strlen(body), deadline, grpc_closure_create(response_cb, metadata_req, grpc_schedule_on_exec_ctx), &metadata_req->response); grpc_resource_quota_unref_internal(exec_ctx, resource_quota); gpr_free(body); } grpc_call_credentials * grpc_refresh_token_credentials_create_from_auth_refresh_token( grpc_auth_refresh_token refresh_token) { grpc_google_refresh_token_credentials *c; if (!grpc_auth_refresh_token_is_valid(&refresh_token)) { gpr_log(GPR_ERROR, "Invalid input for refresh token credentials creation"); return NULL; } c = gpr_zalloc(sizeof(grpc_google_refresh_token_credentials)); init_oauth2_token_fetcher(&c->base, refresh_token_fetch_oauth2); c->base.base.vtable = &refresh_token_vtable; c->refresh_token = refresh_token; return &c->base.base; } static char *create_loggable_refresh_token(grpc_auth_refresh_token *token) { if (strcmp(token->type, GRPC_AUTH_JSON_TYPE_INVALID) == 0) { return gpr_strdup(""); } char *loggable_token = NULL; gpr_asprintf(&loggable_token, "{\n type: %s\n client_id: %s\n client_secret: " "\n refresh_token: \n}", token->type, token->client_id); return loggable_token; } grpc_call_credentials *grpc_google_refresh_token_credentials_create( const char *json_refresh_token, void *reserved) { grpc_auth_refresh_token token = grpc_auth_refresh_token_create_from_string(json_refresh_token); if (grpc_api_trace) { char *loggable_token = create_loggable_refresh_token(&token); gpr_log(GPR_INFO, "grpc_refresh_token_credentials_create(json_refresh_token=%s, " "reserved=%p)", loggable_token, reserved); gpr_free(loggable_token); } GPR_ASSERT(reserved == NULL); return grpc_refresh_token_credentials_create_from_auth_refresh_token(token); } // // Oauth2 Access Token credentials. // static void access_token_destruct(grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds) { grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds; grpc_credentials_md_store_unref(exec_ctx, c->access_token_md); } static void access_token_get_request_metadata( grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_polling_entity *pollent, grpc_auth_metadata_context context, grpc_credentials_metadata_cb cb, void *user_data) { grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds; cb(exec_ctx, user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK, NULL); } static grpc_call_credentials_vtable access_token_vtable = { access_token_destruct, access_token_get_request_metadata}; grpc_call_credentials *grpc_access_token_credentials_create( const char *access_token, void *reserved) { grpc_access_token_credentials *c = gpr_zalloc(sizeof(grpc_access_token_credentials)); char *token_md_value; GRPC_API_TRACE( "grpc_access_token_credentials_create(access_token=, " "reserved=%p)", 1, (reserved)); GPR_ASSERT(reserved == NULL); c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2; c->base.vtable = &access_token_vtable; gpr_ref_init(&c->base.refcount, 1); c->access_token_md = grpc_credentials_md_store_create(1); gpr_asprintf(&token_md_value, "Bearer %s", access_token); grpc_credentials_md_store_add_cstrings( c->access_token_md, GRPC_AUTHORIZATION_METADATA_KEY, token_md_value); gpr_free(token_md_value); return &c->base; } grpc-1.3.2/src/core/lib/security/credentials/oauth2/oauth2_credentials.h000066400000000000000000000104661310511640000262310ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_OAUTH2_OAUTH2_CREDENTIALS_H #define GRPC_CORE_LIB_SECURITY_CREDENTIALS_OAUTH2_OAUTH2_CREDENTIALS_H #include "src/core/lib/json/json.h" #include "src/core/lib/security/credentials/credentials.h" // auth_refresh_token parsing. typedef struct { const char *type; char *client_id; char *client_secret; char *refresh_token; } grpc_auth_refresh_token; /// Returns 1 if the object is valid, 0 otherwise. int grpc_auth_refresh_token_is_valid( const grpc_auth_refresh_token *refresh_token); /// Creates a refresh token object from string. Returns an invalid object if a /// parsing error has been encountered. grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string( const char *json_string); /// Creates a refresh token object from parsed json. Returns an invalid object /// if a parsing error has been encountered. grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json( const grpc_json *json); /// Destructs the object. void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token); // -- Oauth2 Token Fetcher credentials -- // // This object is a base for credentials that need to acquire an oauth2 token // from an http service. typedef void (*grpc_fetch_oauth2_func)(grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *req, grpc_httpcli_context *http_context, grpc_polling_entity *pollent, grpc_iomgr_cb_func cb, gpr_timespec deadline); typedef struct { grpc_call_credentials base; gpr_mu mu; grpc_credentials_md_store *access_token_md; gpr_timespec token_expiration; grpc_httpcli_context httpcli_context; grpc_fetch_oauth2_func fetch_func; } grpc_oauth2_token_fetcher_credentials; // Google refresh token credentials. typedef struct { grpc_oauth2_token_fetcher_credentials base; grpc_auth_refresh_token refresh_token; } grpc_google_refresh_token_credentials; // Access token credentials. typedef struct { grpc_call_credentials base; grpc_credentials_md_store *access_token_md; } grpc_access_token_credentials; // Private constructor for refresh token credentials from an already parsed // refresh token. Takes ownership of the refresh token. grpc_call_credentials * grpc_refresh_token_credentials_create_from_auth_refresh_token( grpc_auth_refresh_token token); // Exposed for testing only. grpc_credentials_status grpc_oauth2_token_fetcher_credentials_parse_server_response( grpc_exec_ctx *exec_ctx, const struct grpc_http_response *response, grpc_credentials_md_store **token_md, gpr_timespec *token_lifetime); #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_OAUTH2_OAUTH2_CREDENTIALS_H */ grpc-1.3.2/src/core/lib/security/credentials/plugin/000077500000000000000000000000001310511640000223665ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/security/credentials/plugin/plugin_credentials.c000066400000000000000000000142061310511640000264100ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/security/credentials/plugin/plugin_credentials.h" #include #include #include #include #include #include #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/validate_metadata.h" typedef struct { void *user_data; grpc_credentials_metadata_cb cb; } grpc_metadata_plugin_request; static void plugin_destruct(grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds) { grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds; if (c->plugin.state != NULL && c->plugin.destroy != NULL) { c->plugin.destroy(c->plugin.state); } } static void plugin_md_request_metadata_ready(void *request, const grpc_metadata *md, size_t num_md, grpc_status_code status, const char *error_details) { /* called from application code */ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INITIALIZER( GRPC_EXEC_CTX_FLAG_IS_FINISHED | GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP, NULL, NULL); grpc_metadata_plugin_request *r = (grpc_metadata_plugin_request *)request; if (status != GRPC_STATUS_OK) { if (error_details != NULL) { gpr_log(GPR_ERROR, "Getting metadata from plugin failed with error: %s", error_details); } r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR, error_details); } else { size_t i; bool seen_illegal_header = false; grpc_credentials_md *md_array = NULL; for (i = 0; i < num_md; i++) { if (!GRPC_LOG_IF_ERROR("validate_metadata_from_plugin", grpc_validate_header_key_is_legal(md[i].key))) { seen_illegal_header = true; break; } else if (!grpc_is_binary_header(md[i].key) && !GRPC_LOG_IF_ERROR( "validate_metadata_from_plugin", grpc_validate_header_nonbin_value_is_legal(md[i].value))) { gpr_log(GPR_ERROR, "Plugin added invalid metadata value."); seen_illegal_header = true; break; } } if (seen_illegal_header) { r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR, "Illegal metadata"); } else if (num_md > 0) { md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md)); for (i = 0; i < num_md; i++) { md_array[i].key = grpc_slice_ref_internal(md[i].key); md_array[i].value = grpc_slice_ref_internal(md[i].value); } r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK, NULL); for (i = 0; i < num_md; i++) { grpc_slice_unref_internal(&exec_ctx, md_array[i].key); grpc_slice_unref_internal(&exec_ctx, md_array[i].value); } gpr_free(md_array); } else if (num_md == 0) { r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_OK, NULL); } } gpr_free(r); grpc_exec_ctx_finish(&exec_ctx); } static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, grpc_polling_entity *pollent, grpc_auth_metadata_context context, grpc_credentials_metadata_cb cb, void *user_data) { grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds; if (c->plugin.get_metadata != NULL) { grpc_metadata_plugin_request *request = gpr_zalloc(sizeof(*request)); request->user_data = user_data; request->cb = cb; c->plugin.get_metadata(c->plugin.state, context, plugin_md_request_metadata_ready, request); } else { cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK, NULL); } } static grpc_call_credentials_vtable plugin_vtable = { plugin_destruct, plugin_get_request_metadata}; grpc_call_credentials *grpc_metadata_credentials_create_from_plugin( grpc_metadata_credentials_plugin plugin, void *reserved) { grpc_plugin_credentials *c = gpr_zalloc(sizeof(*c)); GRPC_API_TRACE("grpc_metadata_credentials_create_from_plugin(reserved=%p)", 1, (reserved)); GPR_ASSERT(reserved == NULL); c->base.type = plugin.type; c->base.vtable = &plugin_vtable; gpr_ref_init(&c->base.refcount, 1); c->plugin = plugin; return &c->base; } grpc-1.3.2/src/core/lib/security/credentials/plugin/plugin_credentials.h000066400000000000000000000037271310511640000264230ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_PLUGIN_PLUGIN_CREDENTIALS_H #define GRPC_CORE_LIB_SECURITY_CREDENTIALS_PLUGIN_PLUGIN_CREDENTIALS_H #include "src/core/lib/security/credentials/credentials.h" typedef struct { grpc_call_credentials base; grpc_metadata_credentials_plugin plugin; grpc_credentials_md_store *plugin_md; } grpc_plugin_credentials; #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_PLUGIN_PLUGIN_CREDENTIALS_H */ grpc-1.3.2/src/core/lib/security/credentials/ssl/000077500000000000000000000000001310511640000216715ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/security/credentials/ssl/ssl_credentials.c000066400000000000000000000230321310511640000252130ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/security/credentials/ssl/ssl_credentials.h" #include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/http_client_filter.h" #include "src/core/lib/surface/api_trace.h" #include #include // // Utils // static void ssl_copy_key_material(const char *input, unsigned char **output, size_t *output_size) { *output_size = strlen(input); *output = gpr_malloc(*output_size); memcpy(*output, input, *output_size); } // // SSL Channel Credentials. // static void ssl_destruct(grpc_exec_ctx *exec_ctx, grpc_channel_credentials *creds) { grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds; if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs); if (c->config.pem_private_key != NULL) gpr_free(c->config.pem_private_key); if (c->config.pem_cert_chain != NULL) gpr_free(c->config.pem_cert_chain); } static grpc_security_status ssl_create_security_connector( grpc_exec_ctx *exec_ctx, grpc_channel_credentials *creds, grpc_call_credentials *call_creds, const char *target, const grpc_channel_args *args, grpc_channel_security_connector **sc, grpc_channel_args **new_args) { grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds; grpc_security_status status = GRPC_SECURITY_OK; size_t i = 0; const char *overridden_target_name = NULL; grpc_arg new_arg; for (i = 0; args && i < args->num_args; i++) { grpc_arg *arg = &args->args[i]; if (strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) == 0 && arg->type == GRPC_ARG_STRING) { overridden_target_name = arg->value.string; break; } } status = grpc_ssl_channel_security_connector_create( exec_ctx, call_creds, &c->config, target, overridden_target_name, sc); if (status != GRPC_SECURITY_OK) { return status; } new_arg.type = GRPC_ARG_STRING; new_arg.key = GRPC_ARG_HTTP2_SCHEME; new_arg.value.string = "https"; *new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1); return status; } static grpc_channel_credentials_vtable ssl_vtable = { ssl_destruct, ssl_create_security_connector, NULL}; static void ssl_build_config(const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair, grpc_ssl_config *config) { if (pem_root_certs != NULL) { ssl_copy_key_material(pem_root_certs, &config->pem_root_certs, &config->pem_root_certs_size); } if (pem_key_cert_pair != NULL) { GPR_ASSERT(pem_key_cert_pair->private_key != NULL); GPR_ASSERT(pem_key_cert_pair->cert_chain != NULL); ssl_copy_key_material(pem_key_cert_pair->private_key, &config->pem_private_key, &config->pem_private_key_size); ssl_copy_key_material(pem_key_cert_pair->cert_chain, &config->pem_cert_chain, &config->pem_cert_chain_size); } } grpc_channel_credentials *grpc_ssl_credentials_create( const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair, void *reserved) { grpc_ssl_credentials *c = gpr_zalloc(sizeof(grpc_ssl_credentials)); GRPC_API_TRACE( "grpc_ssl_credentials_create(pem_root_certs=%s, " "pem_key_cert_pair=%p, " "reserved=%p)", 3, (pem_root_certs, pem_key_cert_pair, reserved)); GPR_ASSERT(reserved == NULL); c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL; c->base.vtable = &ssl_vtable; gpr_ref_init(&c->base.refcount, 1); ssl_build_config(pem_root_certs, pem_key_cert_pair, &c->config); return &c->base; } // // SSL Server Credentials. // static void ssl_server_destruct(grpc_exec_ctx *exec_ctx, grpc_server_credentials *creds) { grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds; size_t i; for (i = 0; i < c->config.num_key_cert_pairs; i++) { if (c->config.pem_private_keys[i] != NULL) { gpr_free(c->config.pem_private_keys[i]); } if (c->config.pem_cert_chains[i] != NULL) { gpr_free(c->config.pem_cert_chains[i]); } } if (c->config.pem_private_keys != NULL) gpr_free(c->config.pem_private_keys); if (c->config.pem_private_keys_sizes != NULL) { gpr_free(c->config.pem_private_keys_sizes); } if (c->config.pem_cert_chains != NULL) gpr_free(c->config.pem_cert_chains); if (c->config.pem_cert_chains_sizes != NULL) { gpr_free(c->config.pem_cert_chains_sizes); } if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs); } static grpc_security_status ssl_server_create_security_connector( grpc_exec_ctx *exec_ctx, grpc_server_credentials *creds, grpc_server_security_connector **sc) { grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds; return grpc_ssl_server_security_connector_create(exec_ctx, &c->config, sc); } static grpc_server_credentials_vtable ssl_server_vtable = { ssl_server_destruct, ssl_server_create_security_connector}; static void ssl_build_server_config( const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, size_t num_key_cert_pairs, grpc_ssl_client_certificate_request_type client_certificate_request, grpc_ssl_server_config *config) { size_t i; config->client_certificate_request = client_certificate_request; if (pem_root_certs != NULL) { ssl_copy_key_material(pem_root_certs, &config->pem_root_certs, &config->pem_root_certs_size); } if (num_key_cert_pairs > 0) { GPR_ASSERT(pem_key_cert_pairs != NULL); config->pem_private_keys = gpr_malloc(num_key_cert_pairs * sizeof(unsigned char *)); config->pem_cert_chains = gpr_malloc(num_key_cert_pairs * sizeof(unsigned char *)); config->pem_private_keys_sizes = gpr_malloc(num_key_cert_pairs * sizeof(size_t)); config->pem_cert_chains_sizes = gpr_malloc(num_key_cert_pairs * sizeof(size_t)); } config->num_key_cert_pairs = num_key_cert_pairs; for (i = 0; i < num_key_cert_pairs; i++) { GPR_ASSERT(pem_key_cert_pairs[i].private_key != NULL); GPR_ASSERT(pem_key_cert_pairs[i].cert_chain != NULL); ssl_copy_key_material(pem_key_cert_pairs[i].private_key, &config->pem_private_keys[i], &config->pem_private_keys_sizes[i]); ssl_copy_key_material(pem_key_cert_pairs[i].cert_chain, &config->pem_cert_chains[i], &config->pem_cert_chains_sizes[i]); } } grpc_server_credentials *grpc_ssl_server_credentials_create( const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, size_t num_key_cert_pairs, int force_client_auth, void *reserved) { return grpc_ssl_server_credentials_create_ex( pem_root_certs, pem_key_cert_pairs, num_key_cert_pairs, force_client_auth ? GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY : GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, reserved); } grpc_server_credentials *grpc_ssl_server_credentials_create_ex( const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, size_t num_key_cert_pairs, grpc_ssl_client_certificate_request_type client_certificate_request, void *reserved) { grpc_ssl_server_credentials *c = gpr_zalloc(sizeof(grpc_ssl_server_credentials)); GRPC_API_TRACE( "grpc_ssl_server_credentials_create_ex(" "pem_root_certs=%s, pem_key_cert_pairs=%p, num_key_cert_pairs=%lu, " "client_certificate_request=%d, reserved=%p)", 5, (pem_root_certs, pem_key_cert_pairs, (unsigned long)num_key_cert_pairs, client_certificate_request, reserved)); GPR_ASSERT(reserved == NULL); c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL; gpr_ref_init(&c->base.refcount, 1); c->base.vtable = &ssl_server_vtable; ssl_build_server_config(pem_root_certs, pem_key_cert_pairs, num_key_cert_pairs, client_certificate_request, &c->config); return &c->base; } grpc-1.3.2/src/core/lib/security/credentials/ssl/ssl_credentials.h000066400000000000000000000037751310511640000252340ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_SSL_SSL_CREDENTIALS_H #define GRPC_CORE_LIB_SECURITY_CREDENTIALS_SSL_SSL_CREDENTIALS_H #include "src/core/lib/security/credentials/credentials.h" typedef struct { grpc_channel_credentials base; grpc_ssl_config config; } grpc_ssl_credentials; typedef struct { grpc_server_credentials base; grpc_ssl_server_config config; } grpc_ssl_server_credentials; #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_SSL_SSL_CREDENTIALS_H */ grpc-1.3.2/src/core/lib/security/transport/000077500000000000000000000000001310511640000206275ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/security/transport/auth_filters.h000066400000000000000000000035661310511640000235030ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SECURITY_TRANSPORT_AUTH_FILTERS_H #define GRPC_CORE_LIB_SECURITY_TRANSPORT_AUTH_FILTERS_H #include "src/core/lib/channel/channel_stack.h" extern const grpc_channel_filter grpc_client_auth_filter; extern const grpc_channel_filter grpc_server_auth_filter; #endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_AUTH_FILTERS_H */ grpc-1.3.2/src/core/lib/security/transport/client_auth_filter.c000066400000000000000000000360701310511640000246450ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/security/transport/auth_filters.h" #include #include #include #include #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/transport/security_connector.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/string.h" #include "src/core/lib/surface/call.h" #include "src/core/lib/transport/static_metadata.h" #define MAX_CREDENTIALS_METADATA_COUNT 4 /* We can have a per-call credentials. */ typedef struct { grpc_call_credentials *creds; bool have_host; bool have_method; grpc_slice host; grpc_slice method; /* pollset{_set} bound to this call; if we need to make external network requests, they should be done under a pollset added to this pollset_set so that work can progress when this call wants work to progress */ grpc_polling_entity *pollent; grpc_transport_stream_op_batch op; uint8_t security_context_set; grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT]; grpc_auth_metadata_context auth_md_context; } call_data; /* We can have a per-channel credentials. */ typedef struct { grpc_channel_security_connector *security_connector; grpc_auth_context *auth_context; } channel_data; static void reset_auth_metadata_context( grpc_auth_metadata_context *auth_md_context) { if (auth_md_context->service_url != NULL) { gpr_free((char *)auth_md_context->service_url); auth_md_context->service_url = NULL; } if (auth_md_context->method_name != NULL) { gpr_free((char *)auth_md_context->method_name); auth_md_context->method_name = NULL; } GRPC_AUTH_CONTEXT_UNREF( (grpc_auth_context *)auth_md_context->channel_auth_context, "grpc_auth_metadata_context"); auth_md_context->channel_auth_context = NULL; } static void add_error(grpc_error **combined, grpc_error *error) { if (error == GRPC_ERROR_NONE) return; if (*combined == GRPC_ERROR_NONE) { *combined = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Client auth metadata plugin error"); } *combined = grpc_error_add_child(*combined, error); } static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems, size_t num_md, grpc_credentials_status status, const char *error_details) { grpc_call_element *elem = (grpc_call_element *)user_data; call_data *calld = elem->call_data; grpc_transport_stream_op_batch *op = &calld->op; grpc_metadata_batch *mdb; size_t i; reset_auth_metadata_context(&calld->auth_md_context); grpc_error *error = GRPC_ERROR_NONE; if (status != GRPC_CREDENTIALS_OK) { error = grpc_error_set_int( GRPC_ERROR_CREATE_FROM_COPIED_STRING( error_details != NULL && strlen(error_details) > 0 ? error_details : "Credentials failed to get metadata."), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAUTHENTICATED); } else { GPR_ASSERT(num_md <= MAX_CREDENTIALS_METADATA_COUNT); GPR_ASSERT(op->send_initial_metadata); mdb = op->payload->send_initial_metadata.send_initial_metadata; for (i = 0; i < num_md; i++) { add_error(&error, grpc_metadata_batch_add_tail( exec_ctx, mdb, &calld->md_links[i], grpc_mdelem_from_slices( exec_ctx, grpc_slice_ref_internal(md_elems[i].key), grpc_slice_ref_internal(md_elems[i].value)))); } } if (error == GRPC_ERROR_NONE) { grpc_call_next_op(exec_ctx, elem, op); } else { grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, op, error); } } void build_auth_metadata_context(grpc_security_connector *sc, grpc_auth_context *auth_context, call_data *calld) { char *service = grpc_slice_to_c_string(calld->method); char *last_slash = strrchr(service, '/'); char *method_name = NULL; char *service_url = NULL; reset_auth_metadata_context(&calld->auth_md_context); if (last_slash == NULL) { gpr_log(GPR_ERROR, "No '/' found in fully qualified method name"); service[0] = '\0'; } else if (last_slash == service) { /* No service part in fully qualified method name: will just be "/". */ service[1] = '\0'; } else { *last_slash = '\0'; method_name = gpr_strdup(last_slash + 1); } if (method_name == NULL) method_name = gpr_strdup(""); char *host = grpc_slice_to_c_string(calld->host); gpr_asprintf(&service_url, "%s://%s%s", sc->url_scheme == NULL ? "" : sc->url_scheme, host, service); calld->auth_md_context.service_url = service_url; calld->auth_md_context.method_name = method_name; calld->auth_md_context.channel_auth_context = GRPC_AUTH_CONTEXT_REF(auth_context, "grpc_auth_metadata_context"); gpr_free(service); gpr_free(host); } static void send_security_metadata(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op_batch *op) { call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; grpc_client_security_context *ctx = (grpc_client_security_context *)op->payload ->context[GRPC_CONTEXT_SECURITY] .value; grpc_call_credentials *channel_call_creds = chand->security_connector->request_metadata_creds; int call_creds_has_md = (ctx != NULL) && (ctx->creds != NULL); if (channel_call_creds == NULL && !call_creds_has_md) { /* Skip sending metadata altogether. */ grpc_call_next_op(exec_ctx, elem, op); return; } if (channel_call_creds != NULL && call_creds_has_md) { calld->creds = grpc_composite_call_credentials_create(channel_call_creds, ctx->creds, NULL); if (calld->creds == NULL) { grpc_transport_stream_op_batch_finish_with_failure( exec_ctx, op, grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Incompatible credentials set on channel and call."), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAUTHENTICATED)); return; } } else { calld->creds = grpc_call_credentials_ref( call_creds_has_md ? ctx->creds : channel_call_creds); } build_auth_metadata_context(&chand->security_connector->base, chand->auth_context, calld); calld->op = *op; /* Copy op (originates from the caller's stack). */ GPR_ASSERT(calld->pollent != NULL); grpc_call_credentials_get_request_metadata( exec_ctx, calld->creds, calld->pollent, calld->auth_md_context, on_credentials_metadata, elem); } static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data, grpc_security_status status) { grpc_call_element *elem = (grpc_call_element *)user_data; call_data *calld = elem->call_data; if (status == GRPC_SECURITY_OK) { send_security_metadata(exec_ctx, elem, &calld->op); } else { char *error_msg; char *host = grpc_slice_to_c_string(calld->host); gpr_asprintf(&error_msg, "Invalid host %s set in :authority metadata.", host); gpr_free(host); grpc_call_element_signal_error( exec_ctx, elem, grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAUTHENTICATED)); gpr_free(error_msg); } } /* Called either: - in response to an API call (or similar) from above, to send something - a network event (or similar) from below, to receive something op contains type and call direction information, in addition to the data that is being sent or received. */ static void auth_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op_batch *op) { GPR_TIMER_BEGIN("auth_start_transport_op", 0); /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; grpc_linked_mdelem *l; grpc_client_security_context *sec_ctx = NULL; if (calld->security_context_set == 0 && !op->cancel_stream) { calld->security_context_set = 1; GPR_ASSERT(op->payload->context != NULL); if (op->payload->context[GRPC_CONTEXT_SECURITY].value == NULL) { op->payload->context[GRPC_CONTEXT_SECURITY].value = grpc_client_security_context_create(); op->payload->context[GRPC_CONTEXT_SECURITY].destroy = grpc_client_security_context_destroy; } sec_ctx = op->payload->context[GRPC_CONTEXT_SECURITY].value; GRPC_AUTH_CONTEXT_UNREF(sec_ctx->auth_context, "client auth filter"); sec_ctx->auth_context = GRPC_AUTH_CONTEXT_REF(chand->auth_context, "client_auth_filter"); } if (op->send_initial_metadata) { for (l = op->payload->send_initial_metadata.send_initial_metadata->list .head; l != NULL; l = l->next) { grpc_mdelem md = l->md; /* Pointer comparison is OK for md_elems created from the same context. */ if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_AUTHORITY)) { if (calld->have_host) { grpc_slice_unref_internal(exec_ctx, calld->host); } calld->host = grpc_slice_ref_internal(GRPC_MDVALUE(md)); calld->have_host = true; } else if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_PATH)) { if (calld->have_method) { grpc_slice_unref_internal(exec_ctx, calld->method); } calld->method = grpc_slice_ref_internal(GRPC_MDVALUE(md)); calld->have_method = true; } } if (calld->have_host) { char *call_host = grpc_slice_to_c_string(calld->host); calld->op = *op; /* Copy op (originates from the caller's stack). */ grpc_channel_security_connector_check_call_host( exec_ctx, chand->security_connector, call_host, chand->auth_context, on_host_checked, elem); gpr_free(call_host); GPR_TIMER_END("auth_start_transport_op", 0); return; /* early exit */ } } /* pass control down the stack */ grpc_call_next_op(exec_ctx, elem, op); GPR_TIMER_END("auth_start_transport_op", 0); } /* Constructor for call_data */ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_element_args *args) { call_data *calld = elem->call_data; memset(calld, 0, sizeof(*calld)); return GRPC_ERROR_NONE; } static void set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_polling_entity *pollent) { call_data *calld = elem->call_data; calld->pollent = pollent; } /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, grpc_closure *ignored) { call_data *calld = elem->call_data; grpc_call_credentials_unref(exec_ctx, calld->creds); if (calld->have_host) { grpc_slice_unref_internal(exec_ctx, calld->host); } if (calld->have_method) { grpc_slice_unref_internal(exec_ctx, calld->method); } reset_auth_metadata_context(&calld->auth_md_context); } /* Constructor for channel_data */ static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_channel_element_args *args) { grpc_security_connector *sc = grpc_security_connector_find_in_args(args->channel_args); grpc_auth_context *auth_context = grpc_find_auth_context_in_args(args->channel_args); /* grab pointers to our data from the channel element */ channel_data *chand = elem->channel_data; /* The first and the last filters tend to be implemented differently to handle the case that there's no 'next' filter to call on the up or down path */ GPR_ASSERT(!args->is_last); GPR_ASSERT(sc != NULL); GPR_ASSERT(auth_context != NULL); /* initialize members */ chand->security_connector = (grpc_channel_security_connector *)GRPC_SECURITY_CONNECTOR_REF( sc, "client_auth_filter"); chand->auth_context = GRPC_AUTH_CONTEXT_REF(auth_context, "client_auth_filter"); return GRPC_ERROR_NONE; } /* Destructor for channel data */ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) { /* grab pointers to our data from the channel element */ channel_data *chand = elem->channel_data; grpc_channel_security_connector *sc = chand->security_connector; if (sc != NULL) { GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, &sc->base, "client_auth_filter"); } GRPC_AUTH_CONTEXT_UNREF(chand->auth_context, "client_auth_filter"); } const grpc_channel_filter grpc_client_auth_filter = { auth_start_transport_op, grpc_channel_next_op, sizeof(call_data), init_call_elem, set_pollset_or_pollset_set, destroy_call_elem, sizeof(channel_data), init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer, grpc_channel_next_get_info, "client-auth"}; grpc-1.3.2/src/core/lib/security/transport/lb_targets_info.c000066400000000000000000000056101310511640000241360ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/security/transport/lb_targets_info.h" /* Channel arg key for the mapping of LB server addresses to their names for * secure naming purposes. */ #define GRPC_ARG_LB_SECURE_NAMING_MAP "grpc.lb_secure_naming_map" static void *targets_info_copy(void *p) { return grpc_slice_hash_table_ref(p); } static void targets_info_destroy(grpc_exec_ctx *exec_ctx, void *p) { grpc_slice_hash_table_unref(exec_ctx, p); } static int targets_info_cmp(void *a, void *b) { return GPR_ICMP(a, b); } static const grpc_arg_pointer_vtable server_to_balancer_names_vtable = { targets_info_copy, targets_info_destroy, targets_info_cmp}; grpc_arg grpc_lb_targets_info_create_channel_arg( grpc_slice_hash_table *targets_info) { grpc_arg arg; arg.type = GRPC_ARG_POINTER; arg.key = GRPC_ARG_LB_SECURE_NAMING_MAP; arg.value.pointer.p = targets_info; arg.value.pointer.vtable = &server_to_balancer_names_vtable; return arg; } grpc_slice_hash_table *grpc_lb_targets_info_find_in_args( const grpc_channel_args *args) { const grpc_arg *targets_info_arg = grpc_channel_args_find(args, GRPC_ARG_LB_SECURE_NAMING_MAP); if (targets_info_arg != NULL) { GPR_ASSERT(targets_info_arg->type == GRPC_ARG_POINTER); return targets_info_arg->value.pointer.p; } return NULL; } grpc-1.3.2/src/core/lib/security/transport/lb_targets_info.h000066400000000000000000000041021310511640000241360ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SECURITY_TRANSPORT_LB_TARGETS_INFO_H #define GRPC_CORE_LIB_SECURITY_TRANSPORT_LB_TARGETS_INFO_H #include "src/core/lib/slice/slice_hash_table.h" /** Return a channel argument containing \a targets_info. */ grpc_arg grpc_lb_targets_info_create_channel_arg( grpc_slice_hash_table *targets_info); /** Return the instance of targets info in \a args or NULL */ grpc_slice_hash_table *grpc_lb_targets_info_find_in_args( const grpc_channel_args *args); #endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_LB_TARGETS_INFO_H */ grpc-1.3.2/src/core/lib/security/transport/secure_endpoint.c000066400000000000000000000410471310511640000241670ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when using that endpoint. Because of various transitive includes in uv.h, including windows.h on Windows, uv.h must be included before other system headers. Therefore, sockaddr.h must always be included first */ #include "src/core/lib/iomgr/sockaddr.h" #include #include #include #include #include #include "src/core/lib/debug/trace.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/security/transport/secure_endpoint.h" #include "src/core/lib/security/transport/tsi_error.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/string.h" #include "src/core/tsi/transport_security_interface.h" #define STAGING_BUFFER_SIZE 8192 typedef struct { grpc_endpoint base; grpc_endpoint *wrapped_ep; struct tsi_frame_protector *protector; gpr_mu protector_mu; /* saved upper level callbacks and user_data. */ grpc_closure *read_cb; grpc_closure *write_cb; grpc_closure on_read; grpc_slice_buffer *read_buffer; grpc_slice_buffer source_buffer; /* saved handshaker leftover data to unprotect. */ grpc_slice_buffer leftover_bytes; /* buffers for read and write */ grpc_slice read_staging_buffer; grpc_slice write_staging_buffer; grpc_slice_buffer output_buffer; gpr_refcount ref; } secure_endpoint; int grpc_trace_secure_endpoint = 0; static void destroy(grpc_exec_ctx *exec_ctx, secure_endpoint *secure_ep) { secure_endpoint *ep = secure_ep; grpc_endpoint_destroy(exec_ctx, ep->wrapped_ep); tsi_frame_protector_destroy(ep->protector); grpc_slice_buffer_destroy_internal(exec_ctx, &ep->leftover_bytes); grpc_slice_unref_internal(exec_ctx, ep->read_staging_buffer); grpc_slice_unref_internal(exec_ctx, ep->write_staging_buffer); grpc_slice_buffer_destroy_internal(exec_ctx, &ep->output_buffer); grpc_slice_buffer_destroy_internal(exec_ctx, &ep->source_buffer); gpr_mu_destroy(&ep->protector_mu); gpr_free(ep); } /*#define GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG*/ #ifdef GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG #define SECURE_ENDPOINT_UNREF(exec_ctx, ep, reason) \ secure_endpoint_unref((exec_ctx), (ep), (reason), __FILE__, __LINE__) #define SECURE_ENDPOINT_REF(ep, reason) \ secure_endpoint_ref((ep), (reason), __FILE__, __LINE__) static void secure_endpoint_unref(secure_endpoint *ep, grpc_closure_list *closure_list, const char *reason, const char *file, int line) { gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP unref %p : %s %d -> %d", ep, reason, ep->ref.count, ep->ref.count - 1); if (gpr_unref(&ep->ref)) { destroy(exec_ctx, ep); } } static void secure_endpoint_ref(secure_endpoint *ep, const char *reason, const char *file, int line) { gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP ref %p : %s %d -> %d", ep, reason, ep->ref.count, ep->ref.count + 1); gpr_ref(&ep->ref); } #else #define SECURE_ENDPOINT_UNREF(exec_ctx, ep, reason) \ secure_endpoint_unref((exec_ctx), (ep)) #define SECURE_ENDPOINT_REF(ep, reason) secure_endpoint_ref((ep)) static void secure_endpoint_unref(grpc_exec_ctx *exec_ctx, secure_endpoint *ep) { if (gpr_unref(&ep->ref)) { destroy(exec_ctx, ep); } } static void secure_endpoint_ref(secure_endpoint *ep) { gpr_ref(&ep->ref); } #endif static void flush_read_staging_buffer(secure_endpoint *ep, uint8_t **cur, uint8_t **end) { grpc_slice_buffer_add(ep->read_buffer, ep->read_staging_buffer); ep->read_staging_buffer = grpc_slice_malloc(STAGING_BUFFER_SIZE); *cur = GRPC_SLICE_START_PTR(ep->read_staging_buffer); *end = GRPC_SLICE_END_PTR(ep->read_staging_buffer); } static void call_read_cb(grpc_exec_ctx *exec_ctx, secure_endpoint *ep, grpc_error *error) { if (grpc_trace_secure_endpoint) { size_t i; for (i = 0; i < ep->read_buffer->count; i++) { char *data = grpc_dump_slice(ep->read_buffer->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "READ %p: %s", ep, data); gpr_free(data); } } ep->read_buffer = NULL; grpc_closure_sched(exec_ctx, ep->read_cb, error); SECURE_ENDPOINT_UNREF(exec_ctx, ep, "read"); } static void on_read(grpc_exec_ctx *exec_ctx, void *user_data, grpc_error *error) { unsigned i; uint8_t keep_looping = 0; tsi_result result = TSI_OK; secure_endpoint *ep = (secure_endpoint *)user_data; uint8_t *cur = GRPC_SLICE_START_PTR(ep->read_staging_buffer); uint8_t *end = GRPC_SLICE_END_PTR(ep->read_staging_buffer); if (error != GRPC_ERROR_NONE) { grpc_slice_buffer_reset_and_unref_internal(exec_ctx, ep->read_buffer); call_read_cb(exec_ctx, ep, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Secure read failed", &error, 1)); return; } /* TODO(yangg) check error, maybe bail out early */ for (i = 0; i < ep->source_buffer.count; i++) { grpc_slice encrypted = ep->source_buffer.slices[i]; uint8_t *message_bytes = GRPC_SLICE_START_PTR(encrypted); size_t message_size = GRPC_SLICE_LENGTH(encrypted); while (message_size > 0 || keep_looping) { size_t unprotected_buffer_size_written = (size_t)(end - cur); size_t processed_message_size = message_size; gpr_mu_lock(&ep->protector_mu); result = tsi_frame_protector_unprotect(ep->protector, message_bytes, &processed_message_size, cur, &unprotected_buffer_size_written); gpr_mu_unlock(&ep->protector_mu); if (result != TSI_OK) { gpr_log(GPR_ERROR, "Decryption error: %s", tsi_result_to_string(result)); break; } message_bytes += processed_message_size; message_size -= processed_message_size; cur += unprotected_buffer_size_written; if (cur == end) { flush_read_staging_buffer(ep, &cur, &end); /* Force to enter the loop again to extract buffered bytes in protector. The bytes could be buffered because of running out of staging_buffer. If this happens at the end of all slices, doing another unprotect avoids leaving data in the protector. */ keep_looping = 1; } else if (unprotected_buffer_size_written > 0) { keep_looping = 1; } else { keep_looping = 0; } } if (result != TSI_OK) break; } if (cur != GRPC_SLICE_START_PTR(ep->read_staging_buffer)) { grpc_slice_buffer_add( ep->read_buffer, grpc_slice_split_head( &ep->read_staging_buffer, (size_t)(cur - GRPC_SLICE_START_PTR(ep->read_staging_buffer)))); } /* TODO(yangg) experiment with moving this block after read_cb to see if it helps latency */ grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &ep->source_buffer); if (result != TSI_OK) { grpc_slice_buffer_reset_and_unref_internal(exec_ctx, ep->read_buffer); call_read_cb( exec_ctx, ep, grpc_set_tsi_error_result( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Unwrap failed"), result)); return; } call_read_cb(exec_ctx, ep, GRPC_ERROR_NONE); } static void endpoint_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep, grpc_slice_buffer *slices, grpc_closure *cb) { secure_endpoint *ep = (secure_endpoint *)secure_ep; ep->read_cb = cb; ep->read_buffer = slices; grpc_slice_buffer_reset_and_unref_internal(exec_ctx, ep->read_buffer); SECURE_ENDPOINT_REF(ep, "read"); if (ep->leftover_bytes.count) { grpc_slice_buffer_swap(&ep->leftover_bytes, &ep->source_buffer); GPR_ASSERT(ep->leftover_bytes.count == 0); on_read(exec_ctx, ep, GRPC_ERROR_NONE); return; } grpc_endpoint_read(exec_ctx, ep->wrapped_ep, &ep->source_buffer, &ep->on_read); } static void flush_write_staging_buffer(secure_endpoint *ep, uint8_t **cur, uint8_t **end) { grpc_slice_buffer_add(&ep->output_buffer, ep->write_staging_buffer); ep->write_staging_buffer = grpc_slice_malloc(STAGING_BUFFER_SIZE); *cur = GRPC_SLICE_START_PTR(ep->write_staging_buffer); *end = GRPC_SLICE_END_PTR(ep->write_staging_buffer); } static void endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep, grpc_slice_buffer *slices, grpc_closure *cb) { GPR_TIMER_BEGIN("secure_endpoint.endpoint_write", 0); unsigned i; tsi_result result = TSI_OK; secure_endpoint *ep = (secure_endpoint *)secure_ep; uint8_t *cur = GRPC_SLICE_START_PTR(ep->write_staging_buffer); uint8_t *end = GRPC_SLICE_END_PTR(ep->write_staging_buffer); grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &ep->output_buffer); if (grpc_trace_secure_endpoint) { for (i = 0; i < slices->count; i++) { char *data = grpc_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "WRITE %p: %s", ep, data); gpr_free(data); } } for (i = 0; i < slices->count; i++) { grpc_slice plain = slices->slices[i]; uint8_t *message_bytes = GRPC_SLICE_START_PTR(plain); size_t message_size = GRPC_SLICE_LENGTH(plain); while (message_size > 0) { size_t protected_buffer_size_to_send = (size_t)(end - cur); size_t processed_message_size = message_size; gpr_mu_lock(&ep->protector_mu); result = tsi_frame_protector_protect(ep->protector, message_bytes, &processed_message_size, cur, &protected_buffer_size_to_send); gpr_mu_unlock(&ep->protector_mu); if (result != TSI_OK) { gpr_log(GPR_ERROR, "Encryption error: %s", tsi_result_to_string(result)); break; } message_bytes += processed_message_size; message_size -= processed_message_size; cur += protected_buffer_size_to_send; if (cur == end) { flush_write_staging_buffer(ep, &cur, &end); } } if (result != TSI_OK) break; } if (result == TSI_OK) { size_t still_pending_size; do { size_t protected_buffer_size_to_send = (size_t)(end - cur); gpr_mu_lock(&ep->protector_mu); result = tsi_frame_protector_protect_flush(ep->protector, cur, &protected_buffer_size_to_send, &still_pending_size); gpr_mu_unlock(&ep->protector_mu); if (result != TSI_OK) break; cur += protected_buffer_size_to_send; if (cur == end) { flush_write_staging_buffer(ep, &cur, &end); } } while (still_pending_size > 0); if (cur != GRPC_SLICE_START_PTR(ep->write_staging_buffer)) { grpc_slice_buffer_add( &ep->output_buffer, grpc_slice_split_head( &ep->write_staging_buffer, (size_t)(cur - GRPC_SLICE_START_PTR(ep->write_staging_buffer)))); } } if (result != TSI_OK) { /* TODO(yangg) do different things according to the error type? */ grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &ep->output_buffer); grpc_closure_sched( exec_ctx, cb, grpc_set_tsi_error_result( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Wrap failed"), result)); GPR_TIMER_END("secure_endpoint.endpoint_write", 0); return; } grpc_endpoint_write(exec_ctx, ep->wrapped_ep, &ep->output_buffer, cb); GPR_TIMER_END("secure_endpoint.endpoint_write", 0); } static void endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep, grpc_error *why) { secure_endpoint *ep = (secure_endpoint *)secure_ep; grpc_endpoint_shutdown(exec_ctx, ep->wrapped_ep, why); } static void endpoint_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep) { secure_endpoint *ep = (secure_endpoint *)secure_ep; SECURE_ENDPOINT_UNREF(exec_ctx, ep, "destroy"); } static void endpoint_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep, grpc_pollset *pollset) { secure_endpoint *ep = (secure_endpoint *)secure_ep; grpc_endpoint_add_to_pollset(exec_ctx, ep->wrapped_ep, pollset); } static void endpoint_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep, grpc_pollset_set *pollset_set) { secure_endpoint *ep = (secure_endpoint *)secure_ep; grpc_endpoint_add_to_pollset_set(exec_ctx, ep->wrapped_ep, pollset_set); } static char *endpoint_get_peer(grpc_endpoint *secure_ep) { secure_endpoint *ep = (secure_endpoint *)secure_ep; return grpc_endpoint_get_peer(ep->wrapped_ep); } static int endpoint_get_fd(grpc_endpoint *secure_ep) { secure_endpoint *ep = (secure_endpoint *)secure_ep; return grpc_endpoint_get_fd(ep->wrapped_ep); } static grpc_workqueue *endpoint_get_workqueue(grpc_endpoint *secure_ep) { secure_endpoint *ep = (secure_endpoint *)secure_ep; return grpc_endpoint_get_workqueue(ep->wrapped_ep); } static grpc_resource_user *endpoint_get_resource_user( grpc_endpoint *secure_ep) { secure_endpoint *ep = (secure_endpoint *)secure_ep; return grpc_endpoint_get_resource_user(ep->wrapped_ep); } static const grpc_endpoint_vtable vtable = {endpoint_read, endpoint_write, endpoint_get_workqueue, endpoint_add_to_pollset, endpoint_add_to_pollset_set, endpoint_shutdown, endpoint_destroy, endpoint_get_resource_user, endpoint_get_peer, endpoint_get_fd}; grpc_endpoint *grpc_secure_endpoint_create( struct tsi_frame_protector *protector, grpc_endpoint *transport, grpc_slice *leftover_slices, size_t leftover_nslices) { size_t i; secure_endpoint *ep = (secure_endpoint *)gpr_malloc(sizeof(secure_endpoint)); ep->base.vtable = &vtable; ep->wrapped_ep = transport; ep->protector = protector; grpc_slice_buffer_init(&ep->leftover_bytes); for (i = 0; i < leftover_nslices; i++) { grpc_slice_buffer_add(&ep->leftover_bytes, grpc_slice_ref_internal(leftover_slices[i])); } ep->write_staging_buffer = grpc_slice_malloc(STAGING_BUFFER_SIZE); ep->read_staging_buffer = grpc_slice_malloc(STAGING_BUFFER_SIZE); grpc_slice_buffer_init(&ep->output_buffer); grpc_slice_buffer_init(&ep->source_buffer); ep->read_buffer = NULL; grpc_closure_init(&ep->on_read, on_read, ep, grpc_schedule_on_exec_ctx); gpr_mu_init(&ep->protector_mu); gpr_ref_init(&ep->ref, 1); return &ep->base; } grpc-1.3.2/src/core/lib/security/transport/secure_endpoint.h000066400000000000000000000041251310511640000241700ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURE_ENDPOINT_H #define GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURE_ENDPOINT_H #include #include "src/core/lib/iomgr/endpoint.h" struct tsi_frame_protector; extern int grpc_trace_secure_endpoint; /* Takes ownership of protector and to_wrap, and refs leftover_slices. */ grpc_endpoint *grpc_secure_endpoint_create( struct tsi_frame_protector *protector, grpc_endpoint *to_wrap, grpc_slice *leftover_slices, size_t leftover_nslices); #endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURE_ENDPOINT_H */ grpc-1.3.2/src/core/lib/security/transport/security_connector.c000066400000000000000000001045161310511640000247230ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/security/transport/security_connector.h" #include #include #include #include #include #include #include #include "src/core/ext/transport/chttp2/alpn/alpn.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/handshaker.h" #include "src/core/lib/iomgr/load_file.h" #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/credentials/fake/fake_credentials.h" #include "src/core/lib/security/transport/lb_targets_info.h" #include "src/core/lib/security/transport/secure_endpoint.h" #include "src/core/lib/security/transport/security_handshaker.h" #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" #include "src/core/tsi/fake_transport_security.h" #include "src/core/tsi/ssl_transport_security.h" /* -- Constants. -- */ #ifndef INSTALL_PREFIX static const char *installed_roots_path = "/usr/share/grpc/roots.pem"; #else static const char *installed_roots_path = INSTALL_PREFIX "/share/grpc/roots.pem"; #endif /* -- Overridden default roots. -- */ static grpc_ssl_roots_override_callback ssl_roots_override_cb = NULL; void grpc_set_ssl_roots_override_callback(grpc_ssl_roots_override_callback cb) { ssl_roots_override_cb = cb; } /* -- Cipher suites. -- */ /* Defines the cipher suites that we accept by default. All these cipher suites are compliant with HTTP2. */ #define GRPC_SSL_CIPHER_SUITES \ "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" \ "SHA384:ECDHE-RSA-AES256-GCM-SHA384" static gpr_once cipher_suites_once = GPR_ONCE_INIT; static const char *cipher_suites = NULL; static void init_cipher_suites(void) { char *overridden = gpr_getenv("GRPC_SSL_CIPHER_SUITES"); cipher_suites = overridden != NULL ? overridden : GRPC_SSL_CIPHER_SUITES; } static const char *ssl_cipher_suites(void) { gpr_once_init(&cipher_suites_once, init_cipher_suites); return cipher_suites; } /* -- Common methods. -- */ /* Returns the first property with that name. */ const tsi_peer_property *tsi_peer_get_property_by_name(const tsi_peer *peer, const char *name) { size_t i; if (peer == NULL) return NULL; for (i = 0; i < peer->property_count; i++) { const tsi_peer_property *property = &peer->properties[i]; if (name == NULL && property->name == NULL) { return property; } if (name != NULL && property->name != NULL && strcmp(property->name, name) == 0) { return property; } } return NULL; } void grpc_channel_security_connector_add_handshakers( grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *connector, grpc_handshake_manager *handshake_mgr) { if (connector != NULL) { connector->add_handshakers(exec_ctx, connector, handshake_mgr); } } void grpc_server_security_connector_add_handshakers( grpc_exec_ctx *exec_ctx, grpc_server_security_connector *connector, grpc_handshake_manager *handshake_mgr) { if (connector != NULL) { connector->add_handshakers(exec_ctx, connector, handshake_mgr); } } void grpc_security_connector_check_peer(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, grpc_auth_context **auth_context, grpc_closure *on_peer_checked) { if (sc == NULL) { grpc_closure_sched(exec_ctx, on_peer_checked, GRPC_ERROR_CREATE_FROM_STATIC_STRING( "cannot check peer -- no security connector")); tsi_peer_destruct(&peer); } else { sc->vtable->check_peer(exec_ctx, sc, peer, auth_context, on_peer_checked); } } void grpc_channel_security_connector_check_call_host( grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, const char *host, grpc_auth_context *auth_context, grpc_security_call_host_check_cb cb, void *user_data) { if (sc == NULL || sc->check_call_host == NULL) { cb(exec_ctx, user_data, GRPC_SECURITY_ERROR); } else { sc->check_call_host(exec_ctx, sc, host, auth_context, cb, user_data); } } #ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG grpc_security_connector *grpc_security_connector_ref( grpc_security_connector *sc, const char *file, int line, const char *reason) { if (sc == NULL) return NULL; gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECURITY_CONNECTOR:%p ref %d -> %d %s", sc, (int)sc->refcount.count, (int)sc->refcount.count + 1, reason); #else grpc_security_connector *grpc_security_connector_ref( grpc_security_connector *sc) { if (sc == NULL) return NULL; #endif gpr_ref(&sc->refcount); return sc; } #ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG void grpc_security_connector_unref(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, const char *file, int line, const char *reason) { if (sc == NULL) return; gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECURITY_CONNECTOR:%p unref %d -> %d %s", sc, (int)sc->refcount.count, (int)sc->refcount.count - 1, reason); #else void grpc_security_connector_unref(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc) { if (sc == NULL) return; #endif if (gpr_unref(&sc->refcount)) sc->vtable->destroy(exec_ctx, sc); } static void connector_pointer_arg_destroy(grpc_exec_ctx *exec_ctx, void *p) { GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, p, "connector_pointer_arg_destroy"); } static void *connector_pointer_arg_copy(void *p) { return GRPC_SECURITY_CONNECTOR_REF(p, "connector_pointer_arg_copy"); } static int connector_pointer_cmp(void *a, void *b) { return GPR_ICMP(a, b); } static const grpc_arg_pointer_vtable connector_pointer_vtable = { connector_pointer_arg_copy, connector_pointer_arg_destroy, connector_pointer_cmp}; grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc) { grpc_arg result; result.type = GRPC_ARG_POINTER; result.key = GRPC_ARG_SECURITY_CONNECTOR; result.value.pointer.vtable = &connector_pointer_vtable; result.value.pointer.p = sc; return result; } grpc_security_connector *grpc_security_connector_from_arg(const grpc_arg *arg) { if (strcmp(arg->key, GRPC_ARG_SECURITY_CONNECTOR)) return NULL; if (arg->type != GRPC_ARG_POINTER) { gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type, GRPC_ARG_SECURITY_CONNECTOR); return NULL; } return arg->value.pointer.p; } grpc_security_connector *grpc_security_connector_find_in_args( const grpc_channel_args *args) { size_t i; if (args == NULL) return NULL; for (i = 0; i < args->num_args; i++) { grpc_security_connector *sc = grpc_security_connector_from_arg(&args->args[i]); if (sc != NULL) return sc; } return NULL; } /* -- Fake implementation. -- */ typedef struct { grpc_channel_security_connector base; char *target; char *expected_targets; bool is_lb_channel; } grpc_fake_channel_security_connector; static void fake_channel_destroy(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc) { grpc_fake_channel_security_connector *c = (grpc_fake_channel_security_connector *)sc; grpc_call_credentials_unref(exec_ctx, c->base.request_metadata_creds); gpr_free(c->target); gpr_free(c->expected_targets); gpr_free(c); } static void fake_server_destroy(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc) { gpr_free(sc); } static bool fake_check_target(const char *target_type, const char *target, const char *set_str) { GPR_ASSERT(target_type != NULL); GPR_ASSERT(target != NULL); char **set = NULL; size_t set_size = 0; gpr_string_split(set_str, ",", &set, &set_size); bool found = false; for (size_t i = 0; i < set_size; ++i) { if (set[i] != NULL && strcmp(target, set[i]) == 0) found = true; } for (size_t i = 0; i < set_size; ++i) { gpr_free(set[i]); } gpr_free(set); return found; } static void fake_secure_name_check(const char *target, const char *expected_targets, bool is_lb_channel) { if (expected_targets == NULL) return; char **lbs_and_backends = NULL; size_t lbs_and_backends_size = 0; bool success = false; gpr_string_split(expected_targets, ";", &lbs_and_backends, &lbs_and_backends_size); if (lbs_and_backends_size > 2 || lbs_and_backends_size == 0) { gpr_log(GPR_ERROR, "Invalid expected targets arg value: '%s'", expected_targets); goto done; } if (is_lb_channel) { if (lbs_and_backends_size != 2) { gpr_log(GPR_ERROR, "Invalid expected targets arg value: '%s'. Expectations for LB " "channels must be of the form 'be1,be2,be3,...;lb1,lb2,...", expected_targets); goto done; } if (!fake_check_target("LB", target, lbs_and_backends[1])) { gpr_log(GPR_ERROR, "LB target '%s' not found in expected set '%s'", target, lbs_and_backends[1]); goto done; } success = true; } else { if (!fake_check_target("Backend", target, lbs_and_backends[0])) { gpr_log(GPR_ERROR, "Backend target '%s' not found in expected set '%s'", target, lbs_and_backends[0]); goto done; } success = true; } done: for (size_t i = 0; i < lbs_and_backends_size; ++i) { gpr_free(lbs_and_backends[i]); } gpr_free(lbs_and_backends); if (!success) abort(); } static void fake_check_peer(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, grpc_auth_context **auth_context, grpc_closure *on_peer_checked) { const char *prop_name; grpc_error *error = GRPC_ERROR_NONE; *auth_context = NULL; if (peer.property_count != 1) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Fake peers should only have 1 property."); goto end; } prop_name = peer.properties[0].name; if (prop_name == NULL || strcmp(prop_name, TSI_CERTIFICATE_TYPE_PEER_PROPERTY)) { char *msg; gpr_asprintf(&msg, "Unexpected property in fake peer: %s.", prop_name == NULL ? "" : prop_name); error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); goto end; } if (strncmp(peer.properties[0].value.data, TSI_FAKE_CERTIFICATE_TYPE, peer.properties[0].value.length)) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Invalid value for cert type property."); goto end; } *auth_context = grpc_auth_context_create(NULL); grpc_auth_context_add_cstring_property( *auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, GRPC_FAKE_TRANSPORT_SECURITY_TYPE); end: grpc_closure_sched(exec_ctx, on_peer_checked, error); tsi_peer_destruct(&peer); } static void fake_channel_check_peer(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, grpc_auth_context **auth_context, grpc_closure *on_peer_checked) { fake_check_peer(exec_ctx, sc, peer, auth_context, on_peer_checked); grpc_fake_channel_security_connector *c = (grpc_fake_channel_security_connector *)sc; fake_secure_name_check(c->target, c->expected_targets, c->is_lb_channel); } static void fake_server_check_peer(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, grpc_auth_context **auth_context, grpc_closure *on_peer_checked) { fake_check_peer(exec_ctx, sc, peer, auth_context, on_peer_checked); } static void fake_channel_check_call_host(grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, const char *host, grpc_auth_context *auth_context, grpc_security_call_host_check_cb cb, void *user_data) { cb(exec_ctx, user_data, GRPC_SECURITY_OK); } static void fake_channel_add_handshakers( grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, grpc_handshake_manager *handshake_mgr) { grpc_handshake_manager_add( handshake_mgr, grpc_security_handshaker_create( exec_ctx, tsi_create_fake_handshaker(true /* is_client */), &sc->base)); } static void fake_server_add_handshakers(grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc, grpc_handshake_manager *handshake_mgr) { grpc_handshake_manager_add( handshake_mgr, grpc_security_handshaker_create( exec_ctx, tsi_create_fake_handshaker(false /* is_client */), &sc->base)); } static grpc_security_connector_vtable fake_channel_vtable = { fake_channel_destroy, fake_channel_check_peer}; static grpc_security_connector_vtable fake_server_vtable = { fake_server_destroy, fake_server_check_peer}; grpc_channel_security_connector *grpc_fake_channel_security_connector_create( grpc_call_credentials *request_metadata_creds, const char *target, const grpc_channel_args *args) { grpc_fake_channel_security_connector *c = gpr_zalloc(sizeof(*c)); gpr_ref_init(&c->base.base.refcount, 1); c->base.base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME; c->base.base.vtable = &fake_channel_vtable; c->base.request_metadata_creds = grpc_call_credentials_ref(request_metadata_creds); c->base.check_call_host = fake_channel_check_call_host; c->base.add_handshakers = fake_channel_add_handshakers; c->target = gpr_strdup(target); const grpc_arg *expected_target_arg = grpc_channel_args_find(args, GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS); if (expected_target_arg != NULL) { GPR_ASSERT(expected_target_arg->type == GRPC_ARG_STRING); c->expected_targets = gpr_strdup(expected_target_arg->value.string); } c->is_lb_channel = (grpc_lb_targets_info_find_in_args(args) != NULL); return &c->base; } grpc_server_security_connector *grpc_fake_server_security_connector_create( void) { grpc_server_security_connector *c = gpr_zalloc(sizeof(grpc_server_security_connector)); gpr_ref_init(&c->base.refcount, 1); c->base.vtable = &fake_server_vtable; c->base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME; c->add_handshakers = fake_server_add_handshakers; return c; } /* --- Ssl implementation. --- */ typedef struct { grpc_channel_security_connector base; tsi_ssl_client_handshaker_factory *handshaker_factory; char *target_name; char *overridden_target_name; } grpc_ssl_channel_security_connector; typedef struct { grpc_server_security_connector base; tsi_ssl_server_handshaker_factory *handshaker_factory; } grpc_ssl_server_security_connector; static void ssl_channel_destroy(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc) { grpc_ssl_channel_security_connector *c = (grpc_ssl_channel_security_connector *)sc; grpc_call_credentials_unref(exec_ctx, c->base.request_metadata_creds); if (c->handshaker_factory != NULL) { tsi_ssl_client_handshaker_factory_destroy(c->handshaker_factory); } if (c->target_name != NULL) gpr_free(c->target_name); if (c->overridden_target_name != NULL) gpr_free(c->overridden_target_name); gpr_free(sc); } static void ssl_server_destroy(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc) { grpc_ssl_server_security_connector *c = (grpc_ssl_server_security_connector *)sc; if (c->handshaker_factory != NULL) { tsi_ssl_server_handshaker_factory_destroy(c->handshaker_factory); } gpr_free(sc); } static void ssl_channel_add_handshakers(grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, grpc_handshake_manager *handshake_mgr) { grpc_ssl_channel_security_connector *c = (grpc_ssl_channel_security_connector *)sc; // Instantiate TSI handshaker. tsi_handshaker *tsi_hs = NULL; tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker( c->handshaker_factory, c->overridden_target_name != NULL ? c->overridden_target_name : c->target_name, &tsi_hs); if (result != TSI_OK) { gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.", tsi_result_to_string(result)); return; } // Create handshakers. grpc_handshake_manager_add(handshake_mgr, grpc_security_handshaker_create( exec_ctx, tsi_hs, &sc->base)); } static void ssl_server_add_handshakers(grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc, grpc_handshake_manager *handshake_mgr) { grpc_ssl_server_security_connector *c = (grpc_ssl_server_security_connector *)sc; // Instantiate TSI handshaker. tsi_handshaker *tsi_hs = NULL; tsi_result result = tsi_ssl_server_handshaker_factory_create_handshaker( c->handshaker_factory, &tsi_hs); if (result != TSI_OK) { gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.", tsi_result_to_string(result)); return; } // Create handshakers. grpc_handshake_manager_add(handshake_mgr, grpc_security_handshaker_create( exec_ctx, tsi_hs, &sc->base)); } static int ssl_host_matches_name(const tsi_peer *peer, const char *peer_name) { char *allocated_name = NULL; int r; if (strchr(peer_name, ':') != NULL) { char *ignored_port; gpr_split_host_port(peer_name, &allocated_name, &ignored_port); gpr_free(ignored_port); peer_name = allocated_name; if (!peer_name) return 0; } r = tsi_ssl_peer_matches_name(peer, peer_name); gpr_free(allocated_name); return r; } grpc_auth_context *tsi_ssl_peer_to_auth_context(const tsi_peer *peer) { size_t i; grpc_auth_context *ctx = NULL; const char *peer_identity_property_name = NULL; /* The caller has checked the certificate type property. */ GPR_ASSERT(peer->property_count >= 1); ctx = grpc_auth_context_create(NULL); grpc_auth_context_add_cstring_property( ctx, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, GRPC_SSL_TRANSPORT_SECURITY_TYPE); for (i = 0; i < peer->property_count; i++) { const tsi_peer_property *prop = &peer->properties[i]; if (prop->name == NULL) continue; if (strcmp(prop->name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) { /* If there is no subject alt name, have the CN as the identity. */ if (peer_identity_property_name == NULL) { peer_identity_property_name = GRPC_X509_CN_PROPERTY_NAME; } grpc_auth_context_add_property(ctx, GRPC_X509_CN_PROPERTY_NAME, prop->value.data, prop->value.length); } else if (strcmp(prop->name, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) { peer_identity_property_name = GRPC_X509_SAN_PROPERTY_NAME; grpc_auth_context_add_property(ctx, GRPC_X509_SAN_PROPERTY_NAME, prop->value.data, prop->value.length); } else if (strcmp(prop->name, TSI_X509_PEM_CERT_PROPERTY) == 0) { grpc_auth_context_add_property(ctx, GRPC_X509_PEM_CERT_PROPERTY_NAME, prop->value.data, prop->value.length); } } if (peer_identity_property_name != NULL) { GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name( ctx, peer_identity_property_name) == 1); } return ctx; } static grpc_error *ssl_check_peer(grpc_security_connector *sc, const char *peer_name, const tsi_peer *peer, grpc_auth_context **auth_context) { /* Check the ALPN. */ const tsi_peer_property *p = tsi_peer_get_property_by_name(peer, TSI_SSL_ALPN_SELECTED_PROTOCOL); if (p == NULL) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Cannot check peer: missing selected ALPN property."); } if (!grpc_chttp2_is_alpn_version_supported(p->value.data, p->value.length)) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Cannot check peer: invalid ALPN value."); } /* Check the peer name if specified. */ if (peer_name != NULL && !ssl_host_matches_name(peer, peer_name)) { char *msg; gpr_asprintf(&msg, "Peer name %s is not in peer certificate", peer_name); grpc_error *error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return error; } *auth_context = tsi_ssl_peer_to_auth_context(peer); return GRPC_ERROR_NONE; } static void ssl_channel_check_peer(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, grpc_auth_context **auth_context, grpc_closure *on_peer_checked) { grpc_ssl_channel_security_connector *c = (grpc_ssl_channel_security_connector *)sc; grpc_error *error = ssl_check_peer(sc, c->overridden_target_name != NULL ? c->overridden_target_name : c->target_name, &peer, auth_context); grpc_closure_sched(exec_ctx, on_peer_checked, error); tsi_peer_destruct(&peer); } static void ssl_server_check_peer(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, grpc_auth_context **auth_context, grpc_closure *on_peer_checked) { grpc_error *error = ssl_check_peer(sc, NULL, &peer, auth_context); tsi_peer_destruct(&peer); grpc_closure_sched(exec_ctx, on_peer_checked, error); } static void add_shallow_auth_property_to_peer(tsi_peer *peer, const grpc_auth_property *prop, const char *tsi_prop_name) { tsi_peer_property *tsi_prop = &peer->properties[peer->property_count++]; tsi_prop->name = (char *)tsi_prop_name; tsi_prop->value.data = prop->value; tsi_prop->value.length = prop->value_length; } tsi_peer tsi_shallow_peer_from_ssl_auth_context( const grpc_auth_context *auth_context) { size_t max_num_props = 0; grpc_auth_property_iterator it; const grpc_auth_property *prop; tsi_peer peer; memset(&peer, 0, sizeof(peer)); it = grpc_auth_context_property_iterator(auth_context); while (grpc_auth_property_iterator_next(&it) != NULL) max_num_props++; if (max_num_props > 0) { peer.properties = gpr_malloc(max_num_props * sizeof(tsi_peer_property)); it = grpc_auth_context_property_iterator(auth_context); while ((prop = grpc_auth_property_iterator_next(&it)) != NULL) { if (strcmp(prop->name, GRPC_X509_SAN_PROPERTY_NAME) == 0) { add_shallow_auth_property_to_peer( &peer, prop, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY); } else if (strcmp(prop->name, GRPC_X509_CN_PROPERTY_NAME) == 0) { add_shallow_auth_property_to_peer( &peer, prop, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY); } else if (strcmp(prop->name, GRPC_X509_PEM_CERT_PROPERTY_NAME) == 0) { add_shallow_auth_property_to_peer(&peer, prop, TSI_X509_PEM_CERT_PROPERTY); } } } return peer; } void tsi_shallow_peer_destruct(tsi_peer *peer) { if (peer->properties != NULL) gpr_free(peer->properties); } static void ssl_channel_check_call_host(grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, const char *host, grpc_auth_context *auth_context, grpc_security_call_host_check_cb cb, void *user_data) { grpc_ssl_channel_security_connector *c = (grpc_ssl_channel_security_connector *)sc; grpc_security_status status = GRPC_SECURITY_ERROR; tsi_peer peer = tsi_shallow_peer_from_ssl_auth_context(auth_context); if (ssl_host_matches_name(&peer, host)) status = GRPC_SECURITY_OK; /* If the target name was overridden, then the original target_name was 'checked' transitively during the previous peer check at the end of the handshake. */ if (c->overridden_target_name != NULL && strcmp(host, c->target_name) == 0) { status = GRPC_SECURITY_OK; } cb(exec_ctx, user_data, status); tsi_shallow_peer_destruct(&peer); } static grpc_security_connector_vtable ssl_channel_vtable = { ssl_channel_destroy, ssl_channel_check_peer}; static grpc_security_connector_vtable ssl_server_vtable = { ssl_server_destroy, ssl_server_check_peer}; static grpc_slice compute_default_pem_root_certs_once(void) { grpc_slice result = grpc_empty_slice(); /* First try to load the roots from the environment. */ char *default_root_certs_path = gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR); if (default_root_certs_path != NULL) { GRPC_LOG_IF_ERROR("load_file", grpc_load_file(default_root_certs_path, 0, &result)); gpr_free(default_root_certs_path); } /* Try overridden roots if needed. */ grpc_ssl_roots_override_result ovrd_res = GRPC_SSL_ROOTS_OVERRIDE_FAIL; if (GRPC_SLICE_IS_EMPTY(result) && ssl_roots_override_cb != NULL) { char *pem_root_certs = NULL; ovrd_res = ssl_roots_override_cb(&pem_root_certs); if (ovrd_res == GRPC_SSL_ROOTS_OVERRIDE_OK) { GPR_ASSERT(pem_root_certs != NULL); result = grpc_slice_new(pem_root_certs, strlen(pem_root_certs), gpr_free); } } /* Fall back to installed certs if needed. */ if (GRPC_SLICE_IS_EMPTY(result) && ovrd_res != GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY) { GRPC_LOG_IF_ERROR("load_file", grpc_load_file(installed_roots_path, 0, &result)); } return result; } static grpc_slice default_pem_root_certs; static void init_default_pem_root_certs(void) { default_pem_root_certs = compute_default_pem_root_certs_once(); } grpc_slice grpc_get_default_ssl_roots_for_testing(void) { return compute_default_pem_root_certs_once(); } static tsi_client_certificate_request_type get_tsi_client_certificate_request_type( grpc_ssl_client_certificate_request_type grpc_request_type) { switch (grpc_request_type) { case GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE: return TSI_DONT_REQUEST_CLIENT_CERTIFICATE; case GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: return TSI_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY; case GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY: return TSI_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY; case GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: return TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY; case GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY: return TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY; default: // Is this a sane default return TSI_DONT_REQUEST_CLIENT_CERTIFICATE; } } size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs) { /* TODO(jboeuf@google.com): Maybe revisit the approach which consists in loading all the roots once for the lifetime of the process. */ static gpr_once once = GPR_ONCE_INIT; gpr_once_init(&once, init_default_pem_root_certs); *pem_root_certs = GRPC_SLICE_START_PTR(default_pem_root_certs); return GRPC_SLICE_LENGTH(default_pem_root_certs); } grpc_security_status grpc_ssl_channel_security_connector_create( grpc_exec_ctx *exec_ctx, grpc_call_credentials *request_metadata_creds, const grpc_ssl_config *config, const char *target_name, const char *overridden_target_name, grpc_channel_security_connector **sc) { size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions(); const unsigned char **alpn_protocol_strings = gpr_malloc(sizeof(const char *) * num_alpn_protocols); unsigned char *alpn_protocol_string_lengths = gpr_malloc(sizeof(unsigned char) * num_alpn_protocols); tsi_result result = TSI_OK; grpc_ssl_channel_security_connector *c; size_t i; const unsigned char *pem_root_certs; size_t pem_root_certs_size; char *port; for (i = 0; i < num_alpn_protocols; i++) { alpn_protocol_strings[i] = (const unsigned char *)grpc_chttp2_get_alpn_version_index(i); alpn_protocol_string_lengths[i] = (unsigned char)strlen(grpc_chttp2_get_alpn_version_index(i)); } if (config == NULL || target_name == NULL) { gpr_log(GPR_ERROR, "An ssl channel needs a config and a target name."); goto error; } if (config->pem_root_certs == NULL) { pem_root_certs_size = grpc_get_default_ssl_roots(&pem_root_certs); if (pem_root_certs == NULL || pem_root_certs_size == 0) { gpr_log(GPR_ERROR, "Could not get default pem root certs."); goto error; } } else { pem_root_certs = config->pem_root_certs; pem_root_certs_size = config->pem_root_certs_size; } c = gpr_zalloc(sizeof(grpc_ssl_channel_security_connector)); gpr_ref_init(&c->base.base.refcount, 1); c->base.base.vtable = &ssl_channel_vtable; c->base.base.url_scheme = GRPC_SSL_URL_SCHEME; c->base.request_metadata_creds = grpc_call_credentials_ref(request_metadata_creds); c->base.check_call_host = ssl_channel_check_call_host; c->base.add_handshakers = ssl_channel_add_handshakers; gpr_split_host_port(target_name, &c->target_name, &port); gpr_free(port); if (overridden_target_name != NULL) { c->overridden_target_name = gpr_strdup(overridden_target_name); } result = tsi_create_ssl_client_handshaker_factory( config->pem_private_key, config->pem_private_key_size, config->pem_cert_chain, config->pem_cert_chain_size, pem_root_certs, pem_root_certs_size, ssl_cipher_suites(), alpn_protocol_strings, alpn_protocol_string_lengths, (uint16_t)num_alpn_protocols, &c->handshaker_factory); if (result != TSI_OK) { gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", tsi_result_to_string(result)); ssl_channel_destroy(exec_ctx, &c->base.base); *sc = NULL; goto error; } *sc = &c->base; gpr_free((void *)alpn_protocol_strings); gpr_free(alpn_protocol_string_lengths); return GRPC_SECURITY_OK; error: gpr_free((void *)alpn_protocol_strings); gpr_free(alpn_protocol_string_lengths); return GRPC_SECURITY_ERROR; } grpc_security_status grpc_ssl_server_security_connector_create( grpc_exec_ctx *exec_ctx, const grpc_ssl_server_config *config, grpc_server_security_connector **sc) { size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions(); const unsigned char **alpn_protocol_strings = gpr_malloc(sizeof(const char *) * num_alpn_protocols); unsigned char *alpn_protocol_string_lengths = gpr_malloc(sizeof(unsigned char) * num_alpn_protocols); tsi_result result = TSI_OK; grpc_ssl_server_security_connector *c; size_t i; for (i = 0; i < num_alpn_protocols; i++) { alpn_protocol_strings[i] = (const unsigned char *)grpc_chttp2_get_alpn_version_index(i); alpn_protocol_string_lengths[i] = (unsigned char)strlen(grpc_chttp2_get_alpn_version_index(i)); } if (config == NULL || config->num_key_cert_pairs == 0) { gpr_log(GPR_ERROR, "An SSL server needs a key and a cert."); goto error; } c = gpr_zalloc(sizeof(grpc_ssl_server_security_connector)); gpr_ref_init(&c->base.base.refcount, 1); c->base.base.url_scheme = GRPC_SSL_URL_SCHEME; c->base.base.vtable = &ssl_server_vtable; result = tsi_create_ssl_server_handshaker_factory_ex( (const unsigned char **)config->pem_private_keys, config->pem_private_keys_sizes, (const unsigned char **)config->pem_cert_chains, config->pem_cert_chains_sizes, config->num_key_cert_pairs, config->pem_root_certs, config->pem_root_certs_size, get_tsi_client_certificate_request_type( config->client_certificate_request), ssl_cipher_suites(), alpn_protocol_strings, alpn_protocol_string_lengths, (uint16_t)num_alpn_protocols, &c->handshaker_factory); if (result != TSI_OK) { gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", tsi_result_to_string(result)); ssl_server_destroy(exec_ctx, &c->base.base); *sc = NULL; goto error; } c->base.add_handshakers = ssl_server_add_handshakers; *sc = &c->base; gpr_free((void *)alpn_protocol_strings); gpr_free(alpn_protocol_string_lengths); return GRPC_SECURITY_OK; error: gpr_free((void *)alpn_protocol_strings); gpr_free(alpn_protocol_string_lengths); return GRPC_SECURITY_ERROR; } grpc-1.3.2/src/core/lib/security/transport/security_connector.h000066400000000000000000000246611310511640000247320ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_CONNECTOR_H #define GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_CONNECTOR_H #include #include "src/core/lib/channel/handshaker.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/tcp_server.h" #include "src/core/tsi/transport_security_interface.h" /* --- status enum. --- */ typedef enum { GRPC_SECURITY_OK = 0, GRPC_SECURITY_ERROR } grpc_security_status; /* --- URL schemes. --- */ #define GRPC_SSL_URL_SCHEME "https" #define GRPC_FAKE_SECURITY_URL_SCHEME "http+fake_security" /* --- security_connector object. --- A security connector object represents away to configure the underlying transport security mechanism and check the resulting trusted peer. */ typedef struct grpc_security_connector grpc_security_connector; #define GRPC_ARG_SECURITY_CONNECTOR "grpc.security_connector" typedef struct { void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc); void (*check_peer)(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, grpc_auth_context **auth_context, grpc_closure *on_peer_checked); } grpc_security_connector_vtable; typedef struct grpc_security_connector_handshake_list { void *handshake; struct grpc_security_connector_handshake_list *next; } grpc_security_connector_handshake_list; struct grpc_security_connector { const grpc_security_connector_vtable *vtable; gpr_refcount refcount; const char *url_scheme; }; /* Refcounting. */ #ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG #define GRPC_SECURITY_CONNECTOR_REF(p, r) \ grpc_security_connector_ref((p), __FILE__, __LINE__, (r)) #define GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, p, r) \ grpc_security_connector_unref((exec_ctx), (p), __FILE__, __LINE__, (r)) grpc_security_connector *grpc_security_connector_ref( grpc_security_connector *policy, const char *file, int line, const char *reason); void grpc_security_connector_unref(grpc_exec_ctx *exec_ctx, grpc_security_connector *policy, const char *file, int line, const char *reason); #else #define GRPC_SECURITY_CONNECTOR_REF(p, r) grpc_security_connector_ref((p)) #define GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, p, r) \ grpc_security_connector_unref((exec_ctx), (p)) grpc_security_connector *grpc_security_connector_ref( grpc_security_connector *policy); void grpc_security_connector_unref(grpc_exec_ctx *exec_ctx, grpc_security_connector *policy); #endif /* Check the peer. Callee takes ownership of the peer object. When done, sets *auth_context and invokes on_peer_checked. */ void grpc_security_connector_check_peer(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, grpc_auth_context **auth_context, grpc_closure *on_peer_checked); /* Util to encapsulate the connector in a channel arg. */ grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc); /* Util to get the connector from a channel arg. */ grpc_security_connector *grpc_security_connector_from_arg(const grpc_arg *arg); /* Util to find the connector from channel args. */ grpc_security_connector *grpc_security_connector_find_in_args( const grpc_channel_args *args); /* --- channel_security_connector object. --- A channel security connector object represents away to configure the underlying transport security mechanism on the client side. */ typedef struct grpc_channel_security_connector grpc_channel_security_connector; typedef void (*grpc_security_call_host_check_cb)(grpc_exec_ctx *exec_ctx, void *user_data, grpc_security_status status); struct grpc_channel_security_connector { grpc_security_connector base; grpc_call_credentials *request_metadata_creds; void (*check_call_host)(grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, const char *host, grpc_auth_context *auth_context, grpc_security_call_host_check_cb cb, void *user_data); void (*add_handshakers)(grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, grpc_handshake_manager *handshake_mgr); }; /* Checks that the host that will be set for a call is acceptable. */ void grpc_channel_security_connector_check_call_host( grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, const char *host, grpc_auth_context *auth_context, grpc_security_call_host_check_cb cb, void *user_data); /* Registers handshakers with \a handshake_mgr. */ void grpc_channel_security_connector_add_handshakers( grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *connector, grpc_handshake_manager *handshake_mgr); /* --- server_security_connector object. --- A server security connector object represents away to configure the underlying transport security mechanism on the server side. */ typedef struct grpc_server_security_connector grpc_server_security_connector; struct grpc_server_security_connector { grpc_security_connector base; void (*add_handshakers)(grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc, grpc_handshake_manager *handshake_mgr); }; void grpc_server_security_connector_add_handshakers( grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc, grpc_handshake_manager *handshake_mgr); /* --- Creation security connectors. --- */ /* For TESTING ONLY! Creates a fake connector that emulates real channel security. */ grpc_channel_security_connector *grpc_fake_channel_security_connector_create( grpc_call_credentials *request_metadata_creds, const char *target, const grpc_channel_args *args); /* For TESTING ONLY! Creates a fake connector that emulates real server security. */ grpc_server_security_connector *grpc_fake_server_security_connector_create( void); /* Config for ssl clients. */ typedef struct { unsigned char *pem_private_key; size_t pem_private_key_size; unsigned char *pem_cert_chain; size_t pem_cert_chain_size; unsigned char *pem_root_certs; size_t pem_root_certs_size; } grpc_ssl_config; /* Creates an SSL channel_security_connector. - request_metadata_creds is the credentials object which metadata will be sent with each request. This parameter can be NULL. - config is the SSL config to be used for the SSL channel establishment. - is_client should be 0 for a server or a non-0 value for a client. - secure_peer_name is the secure peer name that should be checked in grpc_channel_security_connector_check_peer. This parameter may be NULL in which case the peer name will not be checked. Note that if this parameter is not NULL, then, pem_root_certs should not be NULL either. - sc is a pointer on the connector to be created. This function returns GRPC_SECURITY_OK in case of success or a specific error code otherwise. */ grpc_security_status grpc_ssl_channel_security_connector_create( grpc_exec_ctx *exec_ctx, grpc_call_credentials *request_metadata_creds, const grpc_ssl_config *config, const char *target_name, const char *overridden_target_name, grpc_channel_security_connector **sc); /* Gets the default ssl roots. */ size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs); /* Exposed for TESTING ONLY!. */ grpc_slice grpc_get_default_ssl_roots_for_testing(void); /* Config for ssl servers. */ typedef struct { unsigned char **pem_private_keys; size_t *pem_private_keys_sizes; unsigned char **pem_cert_chains; size_t *pem_cert_chains_sizes; size_t num_key_cert_pairs; unsigned char *pem_root_certs; size_t pem_root_certs_size; grpc_ssl_client_certificate_request_type client_certificate_request; } grpc_ssl_server_config; /* Creates an SSL server_security_connector. - config is the SSL config to be used for the SSL channel establishment. - sc is a pointer on the connector to be created. This function returns GRPC_SECURITY_OK in case of success or a specific error code otherwise. */ grpc_security_status grpc_ssl_server_security_connector_create( grpc_exec_ctx *exec_ctx, const grpc_ssl_server_config *config, grpc_server_security_connector **sc); /* Util. */ const tsi_peer_property *tsi_peer_get_property_by_name(const tsi_peer *peer, const char *name); /* Exposed for testing only. */ grpc_auth_context *tsi_ssl_peer_to_auth_context(const tsi_peer *peer); tsi_peer tsi_shallow_peer_from_ssl_auth_context( const grpc_auth_context *auth_context); void tsi_shallow_peer_destruct(tsi_peer *peer); #endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_CONNECTOR_H */ grpc-1.3.2/src/core/lib/security/transport/security_handshaker.c000066400000000000000000000465051310511640000250440ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/security/transport/security_handshaker.h" #include #include #include #include #include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/handshaker.h" #include "src/core/lib/channel/handshaker_registry.h" #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/transport/secure_endpoint.h" #include "src/core/lib/security/transport/tsi_error.h" #include "src/core/lib/slice/slice_internal.h" #define GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE 256 typedef struct { grpc_handshaker base; // State set at creation time. tsi_handshaker *handshaker; grpc_security_connector *connector; gpr_mu mu; gpr_refcount refs; bool shutdown; // Endpoint and read buffer to destroy after a shutdown. grpc_endpoint *endpoint_to_destroy; grpc_slice_buffer *read_buffer_to_destroy; // State saved while performing the handshake. grpc_handshaker_args *args; grpc_closure *on_handshake_done; unsigned char *handshake_buffer; size_t handshake_buffer_size; grpc_slice_buffer left_overs; grpc_slice_buffer outgoing; grpc_closure on_handshake_data_sent_to_peer; grpc_closure on_handshake_data_received_from_peer; grpc_closure on_peer_checked; grpc_auth_context *auth_context; } security_handshaker; static void security_handshaker_unref(grpc_exec_ctx *exec_ctx, security_handshaker *h) { if (gpr_unref(&h->refs)) { gpr_mu_destroy(&h->mu); tsi_handshaker_destroy(h->handshaker); if (h->endpoint_to_destroy != NULL) { grpc_endpoint_destroy(exec_ctx, h->endpoint_to_destroy); } if (h->read_buffer_to_destroy != NULL) { grpc_slice_buffer_destroy_internal(exec_ctx, h->read_buffer_to_destroy); gpr_free(h->read_buffer_to_destroy); } 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_AUTH_CONTEXT_UNREF(h->auth_context, "handshake"); GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, h->connector, "handshake"); gpr_free(h); } } // Set args fields to NULL, saving the endpoint and read buffer for // later destruction. static void cleanup_args_for_failure_locked(grpc_exec_ctx *exec_ctx, security_handshaker *h) { h->endpoint_to_destroy = h->args->endpoint; h->args->endpoint = NULL; h->read_buffer_to_destroy = h->args->read_buffer; h->args->read_buffer = NULL; grpc_channel_args_destroy(exec_ctx, h->args->args); h->args->args = NULL; } // If the handshake failed or we're shutting down, clean up and invoke the // callback with the error. static void security_handshake_failed_locked(grpc_exec_ctx *exec_ctx, security_handshaker *h, grpc_error *error) { if (error == GRPC_ERROR_NONE) { // If we were shut down after the handshake succeeded but before an // endpoint callback was invoked, we need to generate our own error. error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshaker shutdown"); } const char *msg = grpc_error_string(error); gpr_log(GPR_DEBUG, "Security handshake failed: %s", msg); if (!h->shutdown) { // TODO(ctiller): It is currently necessary to shutdown endpoints // before destroying them, even if we know that there are no // pending read/write callbacks. This should be fixed, at which // point this can be removed. grpc_endpoint_shutdown(exec_ctx, h->args->endpoint, GRPC_ERROR_REF(error)); // Not shutting down, so the write failed. Clean up before // invoking the callback. cleanup_args_for_failure_locked(exec_ctx, h); // Set shutdown to true so that subsequent calls to // security_handshaker_shutdown() do nothing. h->shutdown = true; } // Invoke callback. grpc_closure_sched(exec_ctx, h->on_handshake_done, error); } static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { security_handshaker *h = arg; gpr_mu_lock(&h->mu); if (error != GRPC_ERROR_NONE || h->shutdown) { security_handshake_failed_locked(exec_ctx, h, GRPC_ERROR_REF(error)); goto done; } // Get frame protector. tsi_frame_protector *protector; tsi_result result = tsi_handshaker_create_frame_protector(h->handshaker, NULL, &protector); if (result != TSI_OK) { error = grpc_set_tsi_error_result( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Frame protector creation failed"), result); security_handshake_failed_locked(exec_ctx, h, error); goto done; } // Success. // Create secure endpoint. h->args->endpoint = grpc_secure_endpoint_create( protector, h->args->endpoint, h->left_overs.slices, h->left_overs.count); h->left_overs.count = 0; h->left_overs.length = 0; // Clear out the read buffer before it gets passed to the transport, // since any excess bytes were already copied to h->left_overs. grpc_slice_buffer_reset_and_unref_internal(exec_ctx, h->args->read_buffer); // Add auth context to channel args. grpc_arg auth_context_arg = grpc_auth_context_to_arg(h->auth_context); grpc_channel_args *tmp_args = h->args->args; h->args->args = grpc_channel_args_copy_and_add(tmp_args, &auth_context_arg, 1); grpc_channel_args_destroy(exec_ctx, tmp_args); // Invoke callback. grpc_closure_sched(exec_ctx, h->on_handshake_done, GRPC_ERROR_NONE); // Set shutdown to true so that subsequent calls to // security_handshaker_shutdown() do nothing. h->shutdown = true; done: gpr_mu_unlock(&h->mu); security_handshaker_unref(exec_ctx, h); } static grpc_error *check_peer_locked(grpc_exec_ctx *exec_ctx, security_handshaker *h) { tsi_peer peer; tsi_result result = tsi_handshaker_extract_peer(h->handshaker, &peer); if (result != TSI_OK) { return grpc_set_tsi_error_result( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Peer extraction failed"), result); } grpc_security_connector_check_peer(exec_ctx, h->connector, peer, &h->auth_context, &h->on_peer_checked); return GRPC_ERROR_NONE; } static grpc_error *send_handshake_bytes_to_peer_locked(grpc_exec_ctx *exec_ctx, security_handshaker *h) { // Get data to send. tsi_result result = TSI_OK; size_t offset = 0; do { size_t to_send_size = h->handshake_buffer_size - offset; result = tsi_handshaker_get_bytes_to_send_to_peer( h->handshaker, h->handshake_buffer + offset, &to_send_size); offset += to_send_size; if (result == TSI_INCOMPLETE_DATA) { 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) { return grpc_set_tsi_error_result( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake failed"), result); } // Send data. grpc_slice to_send = grpc_slice_from_copied_buffer((const char *)h->handshake_buffer, offset); 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); return GRPC_ERROR_NONE; } static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { security_handshaker *h = arg; gpr_mu_lock(&h->mu); if (error != GRPC_ERROR_NONE || h->shutdown) { security_handshake_failed_locked( exec_ctx, h, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Handshake read failed", &error, 1)); gpr_mu_unlock(&h->mu); security_handshaker_unref(exec_ctx, h); return; } // Process received data. tsi_result result = TSI_OK; size_t consumed_slice_size = 0; size_t i; for (i = 0; i < h->args->read_buffer->count; i++) { consumed_slice_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)) { /* We may need more data. */ if (result == TSI_INCOMPLETE_DATA) { 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) { security_handshake_failed_locked( exec_ctx, h, grpc_set_tsi_error_result( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake failed"), result)); gpr_mu_unlock(&h->mu); 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. error = check_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; } done: gpr_mu_unlock(&h->mu); } static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { security_handshaker *h = arg; gpr_mu_lock(&h->mu); if (error != GRPC_ERROR_NONE || h->shutdown) { security_handshake_failed_locked( exec_ctx, h, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Handshake write failed", &error, 1)); gpr_mu_unlock(&h->mu); security_handshaker_unref(exec_ctx, h); return; } /* We may be done. */ if (tsi_handshaker_is_in_progress(h->handshaker)) { grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer, &h->on_handshake_data_received_from_peer); } else { error = check_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; } } gpr_mu_unlock(&h->mu); } // // public handshaker API // static void security_handshaker_destroy(grpc_exec_ctx *exec_ctx, grpc_handshaker *handshaker) { security_handshaker *h = (security_handshaker *)handshaker; security_handshaker_unref(exec_ctx, h); } static void security_handshaker_shutdown(grpc_exec_ctx *exec_ctx, grpc_handshaker *handshaker, grpc_error *why) { security_handshaker *h = (security_handshaker *)handshaker; gpr_mu_lock(&h->mu); if (!h->shutdown) { h->shutdown = true; grpc_endpoint_shutdown(exec_ctx, h->args->endpoint, GRPC_ERROR_REF(why)); cleanup_args_for_failure_locked(exec_ctx, h); } gpr_mu_unlock(&h->mu); GRPC_ERROR_UNREF(why); } static void security_handshaker_do_handshake(grpc_exec_ctx *exec_ctx, grpc_handshaker *handshaker, grpc_tcp_server_acceptor *acceptor, grpc_closure *on_handshake_done, grpc_handshaker_args *args) { security_handshaker *h = (security_handshaker *)handshaker; gpr_mu_lock(&h->mu); h->args = args; h->on_handshake_done = on_handshake_done; gpr_ref(&h->refs); grpc_error *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; } gpr_mu_unlock(&h->mu); } static const grpc_handshaker_vtable security_handshaker_vtable = { security_handshaker_destroy, security_handshaker_shutdown, security_handshaker_do_handshake}; static grpc_handshaker *security_handshaker_create( grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker, grpc_security_connector *connector) { security_handshaker *h = gpr_zalloc(sizeof(security_handshaker)); grpc_handshaker_init(&security_handshaker_vtable, &h->base); h->handshaker = handshaker; h->connector = GRPC_SECURITY_CONNECTOR_REF(connector, "handshake"); gpr_mu_init(&h->mu); gpr_ref_init(&h->refs, 1); h->handshake_buffer_size = GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE; h->handshake_buffer = gpr_malloc(h->handshake_buffer_size); grpc_closure_init(&h->on_handshake_data_sent_to_peer, on_handshake_data_sent_to_peer, h, grpc_schedule_on_exec_ctx); grpc_closure_init(&h->on_handshake_data_received_from_peer, on_handshake_data_received_from_peer, h, grpc_schedule_on_exec_ctx); grpc_closure_init(&h->on_peer_checked, on_peer_checked, h, grpc_schedule_on_exec_ctx); grpc_slice_buffer_init(&h->left_overs); grpc_slice_buffer_init(&h->outgoing); return &h->base; } // // fail_handshaker // static void fail_handshaker_destroy(grpc_exec_ctx *exec_ctx, grpc_handshaker *handshaker) { gpr_free(handshaker); } static void fail_handshaker_shutdown(grpc_exec_ctx *exec_ctx, grpc_handshaker *handshaker, grpc_error *why) { GRPC_ERROR_UNREF(why); } static void fail_handshaker_do_handshake(grpc_exec_ctx *exec_ctx, grpc_handshaker *handshaker, grpc_tcp_server_acceptor *acceptor, grpc_closure *on_handshake_done, grpc_handshaker_args *args) { grpc_closure_sched(exec_ctx, on_handshake_done, GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Failed to create security handshaker")); } static const grpc_handshaker_vtable fail_handshaker_vtable = { fail_handshaker_destroy, fail_handshaker_shutdown, fail_handshaker_do_handshake}; static grpc_handshaker *fail_handshaker_create() { grpc_handshaker *h = gpr_malloc(sizeof(*h)); grpc_handshaker_init(&fail_handshaker_vtable, h); return h; } // // handshaker factories // static void client_handshaker_factory_add_handshakers( grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory, const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr) { grpc_channel_security_connector *security_connector = (grpc_channel_security_connector *)grpc_security_connector_find_in_args( args); grpc_channel_security_connector_add_handshakers(exec_ctx, security_connector, handshake_mgr); } static void server_handshaker_factory_add_handshakers( grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *hf, const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr) { grpc_server_security_connector *security_connector = (grpc_server_security_connector *)grpc_security_connector_find_in_args( args); grpc_server_security_connector_add_handshakers(exec_ctx, security_connector, handshake_mgr); } static void handshaker_factory_destroy( grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory) {} static const grpc_handshaker_factory_vtable client_handshaker_factory_vtable = { client_handshaker_factory_add_handshakers, handshaker_factory_destroy}; static grpc_handshaker_factory client_handshaker_factory = { &client_handshaker_factory_vtable}; static const grpc_handshaker_factory_vtable server_handshaker_factory_vtable = { server_handshaker_factory_add_handshakers, handshaker_factory_destroy}; static grpc_handshaker_factory server_handshaker_factory = { &server_handshaker_factory_vtable}; // // exported functions // grpc_handshaker *grpc_security_handshaker_create( grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker, grpc_security_connector *connector) { // If no TSI handshaker was created, return a handshaker that always fails. // Otherwise, return a real security handshaker. if (handshaker == NULL) { return fail_handshaker_create(); } else { return security_handshaker_create(exec_ctx, handshaker, connector); } } void grpc_security_register_handshaker_factories() { grpc_handshaker_factory_register(false /* at_start */, HANDSHAKER_CLIENT, &client_handshaker_factory); grpc_handshaker_factory_register(false /* at_start */, HANDSHAKER_SERVER, &server_handshaker_factory); } grpc-1.3.2/src/core/lib/security/transport/security_handshaker.h000066400000000000000000000042521310511640000250420ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_HANDSHAKER_H #define GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_HANDSHAKER_H #include "src/core/lib/channel/handshaker.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/security/transport/security_connector.h" /// Creates a security handshaker using \a handshaker. grpc_handshaker *grpc_security_handshaker_create( grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker, grpc_security_connector *connector); /// Registers security handshaker factories. void grpc_security_register_handshaker_factories(); #endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_HANDSHAKER_H */ grpc-1.3.2/src/core/lib/security/transport/server_auth_filter.c000066400000000000000000000254021310511640000246720ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/transport/auth_filters.h" #include "src/core/lib/slice/slice_internal.h" typedef struct call_data { grpc_metadata_batch *recv_initial_metadata; /* Closure to call when finished with the auth_on_recv hook. */ grpc_closure *on_done_recv; /* Receive closures are chained: we inject this closure as the on_done_recv up-call on transport_op, and remember to call our on_done_recv member after handling it. */ grpc_closure auth_on_recv; grpc_transport_stream_op_batch *transport_op; grpc_metadata_array md; const grpc_metadata *consumed_md; size_t num_consumed_md; grpc_auth_context *auth_context; } call_data; typedef struct channel_data { grpc_auth_context *auth_context; grpc_server_credentials *creds; } channel_data; static grpc_metadata_array metadata_batch_to_md_array( const grpc_metadata_batch *batch) { grpc_linked_mdelem *l; grpc_metadata_array result; grpc_metadata_array_init(&result); for (l = batch->list.head; l != NULL; l = l->next) { grpc_metadata *usr_md = NULL; grpc_mdelem md = l->md; grpc_slice key = GRPC_MDKEY(md); grpc_slice value = GRPC_MDVALUE(md); if (result.count == result.capacity) { result.capacity = GPR_MAX(result.capacity + 8, result.capacity * 2); result.metadata = gpr_realloc(result.metadata, result.capacity * sizeof(grpc_metadata)); } usr_md = &result.metadata[result.count++]; usr_md->key = grpc_slice_ref_internal(key); usr_md->value = grpc_slice_ref_internal(value); } return result; } static grpc_filtered_mdelem remove_consumed_md(grpc_exec_ctx *exec_ctx, void *user_data, grpc_mdelem md) { grpc_call_element *elem = user_data; call_data *calld = elem->call_data; size_t i; for (i = 0; i < calld->num_consumed_md; i++) { const grpc_metadata *consumed_md = &calld->consumed_md[i]; if (grpc_slice_eq(GRPC_MDKEY(md), consumed_md->key) && grpc_slice_eq(GRPC_MDVALUE(md), consumed_md->value)) return GRPC_FILTERED_REMOVE(); } return GRPC_FILTERED_MDELEM(md); } /* called from application code */ static void on_md_processing_done( void *user_data, const grpc_metadata *consumed_md, size_t num_consumed_md, const grpc_metadata *response_md, size_t num_response_md, grpc_status_code status, const char *error_details) { grpc_call_element *elem = user_data; call_data *calld = elem->call_data; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; /* TODO(jboeuf): Implement support for response_md. */ if (response_md != NULL && num_response_md > 0) { gpr_log(GPR_INFO, "response_md in auth metadata processing not supported for now. " "Ignoring..."); } if (status == GRPC_STATUS_OK) { calld->consumed_md = consumed_md; calld->num_consumed_md = num_consumed_md; /* TODO(ctiller): propagate error */ GRPC_LOG_IF_ERROR( "grpc_metadata_batch_filter", grpc_metadata_batch_filter(&exec_ctx, calld->recv_initial_metadata, remove_consumed_md, elem, "Response metadata filtering error")); for (size_t i = 0; i < calld->md.count; i++) { grpc_slice_unref_internal(&exec_ctx, calld->md.metadata[i].key); grpc_slice_unref_internal(&exec_ctx, calld->md.metadata[i].value); } grpc_metadata_array_destroy(&calld->md); grpc_closure_sched(&exec_ctx, calld->on_done_recv, GRPC_ERROR_NONE); } else { for (size_t i = 0; i < calld->md.count; i++) { grpc_slice_unref_internal(&exec_ctx, calld->md.metadata[i].key); grpc_slice_unref_internal(&exec_ctx, calld->md.metadata[i].value); } grpc_metadata_array_destroy(&calld->md); error_details = error_details != NULL ? error_details : "Authentication metadata processing failed."; if (calld->transport_op->send_message) { grpc_byte_stream_destroy( &exec_ctx, calld->transport_op->payload->send_message.send_message); calld->transport_op->payload->send_message.send_message = NULL; } grpc_closure_sched( &exec_ctx, calld->on_done_recv, grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_details), GRPC_ERROR_INT_GRPC_STATUS, status)); } grpc_exec_ctx_finish(&exec_ctx); } static void auth_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, grpc_error *error) { grpc_call_element *elem = user_data; call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; if (error == GRPC_ERROR_NONE) { if (chand->creds != NULL && chand->creds->processor.process != NULL) { calld->md = metadata_batch_to_md_array(calld->recv_initial_metadata); chand->creds->processor.process( chand->creds->processor.state, calld->auth_context, calld->md.metadata, calld->md.count, on_md_processing_done, elem); return; } } grpc_closure_sched(exec_ctx, calld->on_done_recv, GRPC_ERROR_REF(error)); } static void set_recv_ops_md_callbacks(grpc_call_element *elem, grpc_transport_stream_op_batch *op) { call_data *calld = elem->call_data; if (op->recv_initial_metadata) { /* substitute our callback for the higher callback */ calld->recv_initial_metadata = op->payload->recv_initial_metadata.recv_initial_metadata; calld->on_done_recv = op->payload->recv_initial_metadata.recv_initial_metadata_ready; op->payload->recv_initial_metadata.recv_initial_metadata_ready = &calld->auth_on_recv; calld->transport_op = op; } } /* Called either: - in response to an API call (or similar) from above, to send something - a network event (or similar) from below, to receive something op contains type and call direction information, in addition to the data that is being sent or received. */ static void auth_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op_batch *op) { set_recv_ops_md_callbacks(elem, op); grpc_call_next_op(exec_ctx, elem, op); } /* Constructor for call_data */ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_element_args *args) { /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; grpc_server_security_context *server_ctx = NULL; /* initialize members */ memset(calld, 0, sizeof(*calld)); grpc_closure_init(&calld->auth_on_recv, auth_on_recv, elem, grpc_schedule_on_exec_ctx); if (args->context[GRPC_CONTEXT_SECURITY].value != NULL) { args->context[GRPC_CONTEXT_SECURITY].destroy( args->context[GRPC_CONTEXT_SECURITY].value); } server_ctx = grpc_server_security_context_create(); server_ctx->auth_context = grpc_auth_context_create(chand->auth_context); calld->auth_context = server_ctx->auth_context; args->context[GRPC_CONTEXT_SECURITY].value = server_ctx; args->context[GRPC_CONTEXT_SECURITY].destroy = grpc_server_security_context_destroy; return GRPC_ERROR_NONE; } /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, grpc_closure *ignored) {} /* Constructor for channel_data */ static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_channel_element_args *args) { grpc_auth_context *auth_context = grpc_find_auth_context_in_args(args->channel_args); grpc_server_credentials *creds = grpc_find_server_credentials_in_args(args->channel_args); /* grab pointers to our data from the channel element */ channel_data *chand = elem->channel_data; GPR_ASSERT(!args->is_last); GPR_ASSERT(auth_context != NULL); /* initialize members */ chand->auth_context = GRPC_AUTH_CONTEXT_REF(auth_context, "server_auth_filter"); chand->creds = grpc_server_credentials_ref(creds); return GRPC_ERROR_NONE; } /* Destructor for channel data */ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) { /* grab pointers to our data from the channel element */ channel_data *chand = elem->channel_data; GRPC_AUTH_CONTEXT_UNREF(chand->auth_context, "server_auth_filter"); grpc_server_credentials_unref(exec_ctx, chand->creds); } const grpc_channel_filter grpc_server_auth_filter = { auth_start_transport_op, grpc_channel_next_op, sizeof(call_data), init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, destroy_call_elem, sizeof(channel_data), init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer, grpc_channel_next_get_info, "server-auth"}; grpc-1.3.2/src/core/lib/security/transport/tsi_error.c000066400000000000000000000035741310511640000230140ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/security/transport/tsi_error.h" grpc_error *grpc_set_tsi_error_result(grpc_error *error, tsi_result result) { return grpc_error_set_int( grpc_error_set_str( error, GRPC_ERROR_STR_TSI_ERROR, grpc_slice_from_static_string(tsi_result_to_string(result))), GRPC_ERROR_INT_TSI_CODE, result); } grpc-1.3.2/src/core/lib/security/transport/tsi_error.h000066400000000000000000000035631310511640000230170ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SECURITY_TRANSPORT_TSI_ERROR_H #define GRPC_CORE_LIB_SECURITY_TRANSPORT_TSI_ERROR_H #include "src/core/lib/iomgr/error.h" #include "src/core/tsi/transport_security_interface.h" grpc_error *grpc_set_tsi_error_result(grpc_error *error, tsi_result result); #endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_TSI_ERROR_H */ grpc-1.3.2/src/core/lib/security/util/000077500000000000000000000000001310511640000175505ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/security/util/json_util.c000066400000000000000000000047161310511640000217320ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/security/util/json_util.h" #include #include #include const char *grpc_json_get_string_property(const grpc_json *json, const char *prop_name) { grpc_json *child; for (child = json->child; child != NULL; child = child->next) { if (strcmp(child->key, prop_name) == 0) break; } if (child == NULL || child->type != GRPC_JSON_STRING) { gpr_log(GPR_ERROR, "Invalid or missing %s property.", prop_name); return NULL; } return child->value; } bool grpc_copy_json_string_property(const grpc_json *json, const char *prop_name, char **copied_value) { const char *prop_value = grpc_json_get_string_property(json, prop_name); if (prop_value == NULL) return false; *copied_value = gpr_strdup(prop_value); return true; } grpc-1.3.2/src/core/lib/security/util/json_util.h000066400000000000000000000045371310511640000217400ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SECURITY_UTIL_JSON_UTIL_H #define GRPC_CORE_LIB_SECURITY_UTIL_JSON_UTIL_H #include #include "src/core/lib/json/json.h" // Constants. #define GRPC_AUTH_JSON_TYPE_INVALID "invalid" #define GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT "service_account" #define GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER "authorized_user" // Gets a child property from a json node. const char *grpc_json_get_string_property(const grpc_json *json, const char *prop_name); // Copies the value of the json child property specified by prop_name. // Returns false if the property was not found. bool grpc_copy_json_string_property(const grpc_json *json, const char *prop_name, char **copied_value); #endif /* GRPC_CORE_LIB_SECURITY_UTIL_JSON_UTIL_H */ grpc-1.3.2/src/core/lib/slice/000077500000000000000000000000001310511640000160235ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/slice/b64.c000066400000000000000000000217031310511640000165650ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/slice/b64.h" #include #include #include #include #include #include "src/core/lib/slice/slice_internal.h" /* --- Constants. --- */ static const int8_t base64_bytes[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x3E, -1, -1, -1, 0x3F, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, -1, -1, -1, 0x7F, -1, -1, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, -1, -1, -1, -1, -1, -1, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, -1, -1, -1, -1, -1}; static const char base64_url_unsafe_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const char base64_url_safe_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; #define GRPC_BASE64_PAD_CHAR '=' #define GRPC_BASE64_PAD_BYTE 0x7F #define GRPC_BASE64_MULTILINE_LINE_LEN 76 #define GRPC_BASE64_MULTILINE_NUM_BLOCKS (GRPC_BASE64_MULTILINE_LINE_LEN / 4) /* --- base64 functions. --- */ char *grpc_base64_encode(const void *vdata, size_t data_size, int url_safe, int multiline) { size_t result_projected_size = grpc_base64_estimate_encoded_size(data_size, url_safe, multiline); char *result = gpr_malloc(result_projected_size); grpc_base64_encode_core(result, vdata, data_size, url_safe, multiline); return result; } size_t grpc_base64_estimate_encoded_size(size_t data_size, int url_safe, int multiline) { size_t result_projected_size = 4 * ((data_size + 3) / 3) + 2 * (multiline ? (data_size / (3 * GRPC_BASE64_MULTILINE_NUM_BLOCKS)) : 0) + 1; return result_projected_size; } void grpc_base64_encode_core(char *result, const void *vdata, size_t data_size, int url_safe, int multiline) { const unsigned char *data = vdata; const char *base64_chars = url_safe ? base64_url_safe_chars : base64_url_unsafe_chars; const size_t result_projected_size = grpc_base64_estimate_encoded_size(data_size, url_safe, multiline); char *current = result; size_t num_blocks = 0; size_t i = 0; /* Encode each block. */ while (data_size >= 3) { *current++ = base64_chars[(data[i] >> 2) & 0x3F]; *current++ = base64_chars[((data[i] & 0x03) << 4) | ((data[i + 1] >> 4) & 0x0F)]; *current++ = base64_chars[((data[i + 1] & 0x0F) << 2) | ((data[i + 2] >> 6) & 0x03)]; *current++ = base64_chars[data[i + 2] & 0x3F]; data_size -= 3; i += 3; if (multiline && (++num_blocks == GRPC_BASE64_MULTILINE_NUM_BLOCKS)) { *current++ = '\r'; *current++ = '\n'; num_blocks = 0; } } /* Take care of the tail. */ if (data_size == 2) { *current++ = base64_chars[(data[i] >> 2) & 0x3F]; *current++ = base64_chars[((data[i] & 0x03) << 4) | ((data[i + 1] >> 4) & 0x0F)]; *current++ = base64_chars[(data[i + 1] & 0x0F) << 2]; *current++ = GRPC_BASE64_PAD_CHAR; } else if (data_size == 1) { *current++ = base64_chars[(data[i] >> 2) & 0x3F]; *current++ = base64_chars[(data[i] & 0x03) << 4]; *current++ = GRPC_BASE64_PAD_CHAR; *current++ = GRPC_BASE64_PAD_CHAR; } GPR_ASSERT(current >= result); GPR_ASSERT((uintptr_t)(current - result) < result_projected_size); result[current - result] = '\0'; } grpc_slice grpc_base64_decode(grpc_exec_ctx *exec_ctx, const char *b64, int url_safe) { return grpc_base64_decode_with_len(exec_ctx, b64, strlen(b64), url_safe); } static void decode_one_char(const unsigned char *codes, unsigned char *result, size_t *result_offset) { uint32_t packed = ((uint32_t)codes[0] << 2) | ((uint32_t)codes[1] >> 4); result[(*result_offset)++] = (unsigned char)packed; } static void decode_two_chars(const unsigned char *codes, unsigned char *result, size_t *result_offset) { uint32_t packed = ((uint32_t)codes[0] << 10) | ((uint32_t)codes[1] << 4) | ((uint32_t)codes[2] >> 2); result[(*result_offset)++] = (unsigned char)(packed >> 8); result[(*result_offset)++] = (unsigned char)(packed); } static int decode_group(const unsigned char *codes, size_t num_codes, unsigned char *result, size_t *result_offset) { GPR_ASSERT(num_codes <= 4); /* Short end groups that may not have padding. */ if (num_codes == 1) { gpr_log(GPR_ERROR, "Invalid group. Must be at least 2 bytes."); return 0; } if (num_codes == 2) { decode_one_char(codes, result, result_offset); return 1; } if (num_codes == 3) { decode_two_chars(codes, result, result_offset); return 1; } /* Regular 4 byte groups with padding or not. */ GPR_ASSERT(num_codes == 4); if (codes[0] == GRPC_BASE64_PAD_BYTE || codes[1] == GRPC_BASE64_PAD_BYTE) { gpr_log(GPR_ERROR, "Invalid padding detected."); return 0; } if (codes[2] == GRPC_BASE64_PAD_BYTE) { if (codes[3] == GRPC_BASE64_PAD_BYTE) { decode_one_char(codes, result, result_offset); } else { gpr_log(GPR_ERROR, "Invalid padding detected."); return 0; } } else if (codes[3] == GRPC_BASE64_PAD_BYTE) { decode_two_chars(codes, result, result_offset); } else { /* No padding. */ uint32_t packed = ((uint32_t)codes[0] << 18) | ((uint32_t)codes[1] << 12) | ((uint32_t)codes[2] << 6) | codes[3]; result[(*result_offset)++] = (unsigned char)(packed >> 16); result[(*result_offset)++] = (unsigned char)(packed >> 8); result[(*result_offset)++] = (unsigned char)(packed); } return 1; } grpc_slice grpc_base64_decode_with_len(grpc_exec_ctx *exec_ctx, const char *b64, size_t b64_len, int url_safe) { grpc_slice result = grpc_slice_malloc(b64_len); unsigned char *current = GRPC_SLICE_START_PTR(result); size_t result_size = 0; unsigned char codes[4]; size_t num_codes = 0; while (b64_len--) { unsigned char c = (unsigned char)(*b64++); signed char code; if (c >= GPR_ARRAY_SIZE(base64_bytes)) continue; if (url_safe) { if (c == '+' || c == '/') { gpr_log(GPR_ERROR, "Invalid character for url safe base64 %c", c); goto fail; } if (c == '-') { c = '+'; } else if (c == '_') { c = '/'; } } code = base64_bytes[c]; if (code == -1) { if (c != '\r' && c != '\n') { gpr_log(GPR_ERROR, "Invalid character %c", c); goto fail; } } else { codes[num_codes++] = (unsigned char)code; if (num_codes == 4) { if (!decode_group(codes, num_codes, current, &result_size)) goto fail; num_codes = 0; } } } if (num_codes != 0 && !decode_group(codes, num_codes, current, &result_size)) { goto fail; } GRPC_SLICE_SET_LENGTH(result, result_size); return result; fail: grpc_slice_unref_internal(exec_ctx, result); return grpc_empty_slice(); } grpc-1.3.2/src/core/lib/slice/b64.h000066400000000000000000000057631310511640000166020ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SLICE_B64_H #define GRPC_CORE_LIB_SLICE_B64_H #include /* Encodes data using base64. It is the caller's responsability to free the returned char * using gpr_free. Returns NULL on NULL input. TODO(makdharma) : change the flags to bool from int */ char *grpc_base64_encode(const void *data, size_t data_size, int url_safe, int multiline); /* estimate the upper bound on size of base64 encoded data. The actual size * is guaranteed to be less than or equal to the size returned here. */ size_t grpc_base64_estimate_encoded_size(size_t data_size, int url_safe, int multiline); /* Encodes data using base64 and write it to memory pointed to by result. It is * the caller's responsiblity to allocate enough memory in |result| to fit the * encoded data. */ void grpc_base64_encode_core(char *result, const void *vdata, size_t data_size, int url_safe, int multiline); /* Decodes data according to the base64 specification. Returns an empty slice in case of failure. */ grpc_slice grpc_base64_decode(grpc_exec_ctx *exec_ctx, const char *b64, int url_safe); /* Same as above except that the length is provided by the caller. */ grpc_slice grpc_base64_decode_with_len(grpc_exec_ctx *exec_ctx, const char *b64, size_t b64_len, int url_safe); #endif /* GRPC_CORE_LIB_SLICE_B64_H */ grpc-1.3.2/src/core/lib/slice/percent_encoding.c000066400000000000000000000143071310511640000215020ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/slice/percent_encoding.h" #include #include "src/core/lib/slice/slice_internal.h" const uint8_t grpc_url_percent_encoding_unreserved_bytes[256 / 8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xff, 0x03, 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const uint8_t grpc_compatible_percent_encoding_unreserved_bytes[256 / 8] = { 0x00, 0x00, 0x00, 0x00, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; static bool is_unreserved_character(uint8_t c, const uint8_t *unreserved_bytes) { return ((unreserved_bytes[c / 8] >> (c % 8)) & 1) != 0; } grpc_slice grpc_percent_encode_slice(grpc_slice slice, const uint8_t *unreserved_bytes) { static const uint8_t hex[] = "0123456789ABCDEF"; // first pass: count the number of bytes needed to output this string size_t output_length = 0; const uint8_t *slice_start = GRPC_SLICE_START_PTR(slice); const uint8_t *slice_end = GRPC_SLICE_END_PTR(slice); const uint8_t *p; bool any_reserved_bytes = false; for (p = slice_start; p < slice_end; p++) { bool unres = is_unreserved_character(*p, unreserved_bytes); output_length += unres ? 1 : 3; any_reserved_bytes |= !unres; } // no unreserved bytes: return the string unmodified if (!any_reserved_bytes) { return grpc_slice_ref_internal(slice); } // second pass: actually encode grpc_slice out = grpc_slice_malloc(output_length); uint8_t *q = GRPC_SLICE_START_PTR(out); for (p = slice_start; p < slice_end; p++) { if (is_unreserved_character(*p, unreserved_bytes)) { *q++ = *p; } else { *q++ = '%'; *q++ = hex[*p >> 4]; *q++ = hex[*p & 15]; } } GPR_ASSERT(q == GRPC_SLICE_END_PTR(out)); return out; } static bool valid_hex(const uint8_t *p, const uint8_t *end) { if (p >= end) return false; return (*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F'); } static uint8_t dehex(uint8_t c) { if (c >= '0' && c <= '9') return (uint8_t)(c - '0'); if (c >= 'A' && c <= 'F') return (uint8_t)(c - 'A' + 10); if (c >= 'a' && c <= 'f') return (uint8_t)(c - 'a' + 10); GPR_UNREACHABLE_CODE(return 255); } bool grpc_strict_percent_decode_slice(grpc_slice slice_in, const uint8_t *unreserved_bytes, grpc_slice *slice_out) { const uint8_t *p = GRPC_SLICE_START_PTR(slice_in); const uint8_t *in_end = GRPC_SLICE_END_PTR(slice_in); size_t out_length = 0; bool any_percent_encoded_stuff = false; while (p != in_end) { if (*p == '%') { if (!valid_hex(++p, in_end)) return false; if (!valid_hex(++p, in_end)) return false; p++; out_length++; any_percent_encoded_stuff = true; } else if (is_unreserved_character(*p, unreserved_bytes)) { p++; out_length++; } else { return false; } } if (!any_percent_encoded_stuff) { *slice_out = grpc_slice_ref_internal(slice_in); return true; } p = GRPC_SLICE_START_PTR(slice_in); *slice_out = grpc_slice_malloc(out_length); uint8_t *q = GRPC_SLICE_START_PTR(*slice_out); while (p != in_end) { if (*p == '%') { *q++ = (uint8_t)(dehex(p[1]) << 4) | (dehex(p[2])); p += 3; } else { *q++ = *p++; } } GPR_ASSERT(q == GRPC_SLICE_END_PTR(*slice_out)); return true; } grpc_slice grpc_permissive_percent_decode_slice(grpc_slice slice_in) { const uint8_t *p = GRPC_SLICE_START_PTR(slice_in); const uint8_t *in_end = GRPC_SLICE_END_PTR(slice_in); size_t out_length = 0; bool any_percent_encoded_stuff = false; while (p != in_end) { if (*p == '%') { if (!valid_hex(p + 1, in_end) || !valid_hex(p + 2, in_end)) { p++; out_length++; } else { p += 3; out_length++; any_percent_encoded_stuff = true; } } else { p++; out_length++; } } if (!any_percent_encoded_stuff) { return grpc_slice_ref_internal(slice_in); } p = GRPC_SLICE_START_PTR(slice_in); grpc_slice out = grpc_slice_malloc(out_length); uint8_t *q = GRPC_SLICE_START_PTR(out); while (p != in_end) { if (*p == '%') { if (!valid_hex(p + 1, in_end) || !valid_hex(p + 2, in_end)) { *q++ = *p++; } else { *q++ = (uint8_t)(dehex(p[1]) << 4) | (dehex(p[2])); p += 3; } } else { *q++ = *p++; } } GPR_ASSERT(q == GRPC_SLICE_END_PTR(out)); return out; } grpc-1.3.2/src/core/lib/slice/percent_encoding.h000066400000000000000000000074001310511640000215030ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SLICE_PERCENT_ENCODING_H #define GRPC_CORE_LIB_SLICE_PERCENT_ENCODING_H /* Percent encoding and decoding of slices. Transforms arbitrary strings into safe-for-transmission strings by using variants of percent encoding (RFC 3986). Two major variants are supplied: one that strictly matches URL encoding, and another which applies percent encoding only to non-http2 header bytes (the 'compatible' variant) */ #include #include /* URL percent encoding spec bitfield (usabel as 'unreserved_bytes' in grpc_percent_encode_slice, grpc_strict_percent_decode_slice). Flags [A-Za-z0-9-_.~] as unreserved bytes for the percent encoding routines */ extern const uint8_t grpc_url_percent_encoding_unreserved_bytes[256 / 8]; /* URL percent encoding spec bitfield (usabel as 'unreserved_bytes' in grpc_percent_encode_slice, grpc_strict_percent_decode_slice). Flags ascii7 non-control characters excluding '%' as unreserved bytes for the percent encoding routines */ extern const uint8_t grpc_compatible_percent_encoding_unreserved_bytes[256 / 8]; /* Percent-encode a slice, returning the new slice (this cannot fail): unreserved_bytes is a bitfield indicating which bytes are considered unreserved and thus do not need percent encoding */ grpc_slice grpc_percent_encode_slice(grpc_slice slice, const uint8_t *unreserved_bytes); /* Percent-decode a slice, strictly. If the input is legal (contains no unreserved bytes, and legal % encodings), returns true and sets *slice_out to the decoded slice. If the input is not legal, returns false and leaves *slice_out untouched. unreserved_bytes is a bitfield indicating which bytes are considered unreserved and thus do not need percent encoding */ bool grpc_strict_percent_decode_slice(grpc_slice slice_in, const uint8_t *unreserved_bytes, grpc_slice *slice_out); /* Percent-decode a slice, permissively. If a % triplet can not be decoded, pass it through verbatim. This cannot fail. */ grpc_slice grpc_permissive_percent_decode_slice(grpc_slice slice_in); #endif /* GRPC_CORE_LIB_SLICE_PERCENT_ENCODING_H */ grpc-1.3.2/src/core/lib/slice/slice.c000066400000000000000000000364401310511640000172750ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/slice/slice_internal.h" #include #include #include #include #include "src/core/lib/iomgr/exec_ctx.h" char *grpc_slice_to_c_string(grpc_slice slice) { char *out = gpr_malloc(GRPC_SLICE_LENGTH(slice) + 1); memcpy(out, GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice)); out[GRPC_SLICE_LENGTH(slice)] = 0; return out; } grpc_slice grpc_empty_slice(void) { grpc_slice out; out.refcount = NULL; out.data.inlined.length = 0; return out; } grpc_slice grpc_slice_ref_internal(grpc_slice slice) { if (slice.refcount) { slice.refcount->vtable->ref(slice.refcount); } return slice; } void grpc_slice_unref_internal(grpc_exec_ctx *exec_ctx, grpc_slice slice) { if (slice.refcount) { slice.refcount->vtable->unref(exec_ctx, slice.refcount); } } /* Public API */ grpc_slice grpc_slice_ref(grpc_slice slice) { return grpc_slice_ref_internal(slice); } /* Public API */ void grpc_slice_unref(grpc_slice slice) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_slice_unref_internal(&exec_ctx, slice); grpc_exec_ctx_finish(&exec_ctx); } /* grpc_slice_from_static_string support structure - a refcount that does nothing */ static void noop_ref(void *unused) {} static void noop_unref(grpc_exec_ctx *exec_ctx, void *unused) {} static const grpc_slice_refcount_vtable noop_refcount_vtable = { noop_ref, noop_unref, grpc_slice_default_eq_impl, grpc_slice_default_hash_impl}; static grpc_slice_refcount noop_refcount = {&noop_refcount_vtable, &noop_refcount}; grpc_slice grpc_slice_from_static_buffer(const void *s, size_t len) { grpc_slice slice; slice.refcount = &noop_refcount; slice.data.refcounted.bytes = (uint8_t *)s; slice.data.refcounted.length = len; return slice; } grpc_slice grpc_slice_from_static_string(const char *s) { return grpc_slice_from_static_buffer(s, strlen(s)); } /* grpc_slice_new support structures - we create a refcount object extended with the user provided data pointer & destroy function */ typedef struct new_slice_refcount { grpc_slice_refcount rc; gpr_refcount refs; void (*user_destroy)(void *); void *user_data; } new_slice_refcount; static void new_slice_ref(void *p) { new_slice_refcount *r = p; gpr_ref(&r->refs); } static void new_slice_unref(grpc_exec_ctx *exec_ctx, void *p) { new_slice_refcount *r = p; if (gpr_unref(&r->refs)) { r->user_destroy(r->user_data); gpr_free(r); } } static const grpc_slice_refcount_vtable new_slice_vtable = { new_slice_ref, new_slice_unref, grpc_slice_default_eq_impl, grpc_slice_default_hash_impl}; grpc_slice grpc_slice_new_with_user_data(void *p, size_t len, void (*destroy)(void *), void *user_data) { grpc_slice slice; new_slice_refcount *rc = gpr_malloc(sizeof(new_slice_refcount)); gpr_ref_init(&rc->refs, 1); rc->rc.vtable = &new_slice_vtable; rc->rc.sub_refcount = &rc->rc; rc->user_destroy = destroy; rc->user_data = user_data; slice.refcount = &rc->rc; slice.data.refcounted.bytes = p; slice.data.refcounted.length = len; return slice; } grpc_slice grpc_slice_new(void *p, size_t len, void (*destroy)(void *)) { /* Pass "p" to *destroy when the slice is no longer needed. */ return grpc_slice_new_with_user_data(p, len, destroy, p); } /* grpc_slice_new_with_len support structures - we create a refcount object extended with the user provided data pointer & destroy function */ typedef struct new_with_len_slice_refcount { grpc_slice_refcount rc; gpr_refcount refs; void *user_data; size_t user_length; void (*user_destroy)(void *, size_t); } new_with_len_slice_refcount; static void new_with_len_ref(void *p) { new_with_len_slice_refcount *r = p; gpr_ref(&r->refs); } static void new_with_len_unref(grpc_exec_ctx *exec_ctx, void *p) { new_with_len_slice_refcount *r = p; if (gpr_unref(&r->refs)) { r->user_destroy(r->user_data, r->user_length); gpr_free(r); } } static const grpc_slice_refcount_vtable new_with_len_vtable = { new_with_len_ref, new_with_len_unref, grpc_slice_default_eq_impl, grpc_slice_default_hash_impl}; grpc_slice grpc_slice_new_with_len(void *p, size_t len, void (*destroy)(void *, size_t)) { grpc_slice slice; new_with_len_slice_refcount *rc = gpr_malloc(sizeof(new_with_len_slice_refcount)); gpr_ref_init(&rc->refs, 1); rc->rc.vtable = &new_with_len_vtable; rc->rc.sub_refcount = &rc->rc; rc->user_destroy = destroy; rc->user_data = p; rc->user_length = len; slice.refcount = &rc->rc; slice.data.refcounted.bytes = p; slice.data.refcounted.length = len; return slice; } grpc_slice grpc_slice_from_copied_buffer(const char *source, size_t length) { if (length == 0) return grpc_empty_slice(); grpc_slice slice = grpc_slice_malloc(length); memcpy(GRPC_SLICE_START_PTR(slice), source, length); return slice; } grpc_slice grpc_slice_from_copied_string(const char *source) { return grpc_slice_from_copied_buffer(source, strlen(source)); } typedef struct { grpc_slice_refcount base; gpr_refcount refs; } malloc_refcount; static void malloc_ref(void *p) { malloc_refcount *r = p; gpr_ref(&r->refs); } static void malloc_unref(grpc_exec_ctx *exec_ctx, void *p) { malloc_refcount *r = p; if (gpr_unref(&r->refs)) { gpr_free(r); } } static const grpc_slice_refcount_vtable malloc_vtable = { malloc_ref, malloc_unref, grpc_slice_default_eq_impl, grpc_slice_default_hash_impl}; grpc_slice grpc_slice_malloc(size_t length) { grpc_slice slice; if (length > sizeof(slice.data.inlined.bytes)) { /* Memory layout used by the slice created here: +-----------+----------------------------------------------------------+ | refcount | bytes | +-----------+----------------------------------------------------------+ refcount is a malloc_refcount bytes is an array of bytes of the requested length Both parts are placed in the same allocation returned from gpr_malloc */ malloc_refcount *rc = gpr_malloc(sizeof(malloc_refcount) + length); /* Initial refcount on rc is 1 - and it's up to the caller to release this reference. */ gpr_ref_init(&rc->refs, 1); rc->base.vtable = &malloc_vtable; rc->base.sub_refcount = &rc->base; /* Build up the slice to be returned. */ /* The slices refcount points back to the allocated block. */ slice.refcount = &rc->base; /* The data bytes are placed immediately after the refcount struct */ slice.data.refcounted.bytes = (uint8_t *)(rc + 1); /* And the length of the block is set to the requested length */ slice.data.refcounted.length = length; } else { /* small slice: just inline the data */ slice.refcount = NULL; slice.data.inlined.length = (uint8_t)length; } return slice; } grpc_slice grpc_slice_sub_no_ref(grpc_slice source, size_t begin, size_t end) { grpc_slice subset; GPR_ASSERT(end >= begin); if (source.refcount) { /* Enforce preconditions */ GPR_ASSERT(source.data.refcounted.length >= end); /* Build the result */ subset.refcount = source.refcount->sub_refcount; /* Point into the source array */ subset.data.refcounted.bytes = source.data.refcounted.bytes + begin; subset.data.refcounted.length = end - begin; } else { /* Enforce preconditions */ GPR_ASSERT(source.data.inlined.length >= end); subset.refcount = NULL; subset.data.inlined.length = (uint8_t)(end - begin); memcpy(subset.data.inlined.bytes, source.data.inlined.bytes + begin, end - begin); } return subset; } grpc_slice grpc_slice_sub(grpc_slice source, size_t begin, size_t end) { grpc_slice subset; if (end - begin <= sizeof(subset.data.inlined.bytes)) { subset.refcount = NULL; subset.data.inlined.length = (uint8_t)(end - begin); memcpy(subset.data.inlined.bytes, GRPC_SLICE_START_PTR(source) + begin, end - begin); } else { subset = grpc_slice_sub_no_ref(source, begin, end); /* Bump the refcount */ subset.refcount->vtable->ref(subset.refcount); } return subset; } grpc_slice grpc_slice_split_tail(grpc_slice *source, size_t split) { grpc_slice tail; if (source->refcount == NULL) { /* inlined data, copy it out */ GPR_ASSERT(source->data.inlined.length >= split); tail.refcount = NULL; tail.data.inlined.length = (uint8_t)(source->data.inlined.length - split); memcpy(tail.data.inlined.bytes, source->data.inlined.bytes + split, tail.data.inlined.length); source->data.inlined.length = (uint8_t)split; } else { size_t tail_length = source->data.refcounted.length - split; GPR_ASSERT(source->data.refcounted.length >= split); if (tail_length < sizeof(tail.data.inlined.bytes)) { /* Copy out the bytes - it'll be cheaper than refcounting */ tail.refcount = NULL; tail.data.inlined.length = (uint8_t)tail_length; memcpy(tail.data.inlined.bytes, source->data.refcounted.bytes + split, tail_length); } else { /* Build the result */ tail.refcount = source->refcount->sub_refcount; /* Bump the refcount */ tail.refcount->vtable->ref(tail.refcount); /* Point into the source array */ tail.data.refcounted.bytes = source->data.refcounted.bytes + split; tail.data.refcounted.length = tail_length; } source->refcount = source->refcount->sub_refcount; source->data.refcounted.length = split; } return tail; } grpc_slice grpc_slice_split_head(grpc_slice *source, size_t split) { grpc_slice head; if (source->refcount == NULL) { GPR_ASSERT(source->data.inlined.length >= split); head.refcount = NULL; head.data.inlined.length = (uint8_t)split; memcpy(head.data.inlined.bytes, source->data.inlined.bytes, split); source->data.inlined.length = (uint8_t)(source->data.inlined.length - split); memmove(source->data.inlined.bytes, source->data.inlined.bytes + split, source->data.inlined.length); } else if (split < sizeof(head.data.inlined.bytes)) { GPR_ASSERT(source->data.refcounted.length >= split); head.refcount = NULL; head.data.inlined.length = (uint8_t)split; memcpy(head.data.inlined.bytes, source->data.refcounted.bytes, split); source->refcount = source->refcount->sub_refcount; source->data.refcounted.bytes += split; source->data.refcounted.length -= split; } else { GPR_ASSERT(source->data.refcounted.length >= split); /* Build the result */ head.refcount = source->refcount->sub_refcount; /* Bump the refcount */ head.refcount->vtable->ref(head.refcount); /* Point into the source array */ head.data.refcounted.bytes = source->data.refcounted.bytes; head.data.refcounted.length = split; source->refcount = source->refcount->sub_refcount; source->data.refcounted.bytes += split; source->data.refcounted.length -= split; } return head; } int grpc_slice_default_eq_impl(grpc_slice a, grpc_slice b) { if (GRPC_SLICE_LENGTH(a) != GRPC_SLICE_LENGTH(b)) return false; if (GRPC_SLICE_LENGTH(a) == 0) return true; return 0 == memcmp(GRPC_SLICE_START_PTR(a), GRPC_SLICE_START_PTR(b), GRPC_SLICE_LENGTH(a)); } int grpc_slice_eq(grpc_slice a, grpc_slice b) { if (a.refcount && b.refcount && a.refcount->vtable == b.refcount->vtable) { return a.refcount->vtable->eq(a, b); } return grpc_slice_default_eq_impl(a, b); } int grpc_slice_cmp(grpc_slice a, grpc_slice b) { int d = (int)(GRPC_SLICE_LENGTH(a) - GRPC_SLICE_LENGTH(b)); if (d != 0) return d; return memcmp(GRPC_SLICE_START_PTR(a), GRPC_SLICE_START_PTR(b), GRPC_SLICE_LENGTH(a)); } int grpc_slice_str_cmp(grpc_slice a, const char *b) { size_t b_length = strlen(b); int d = (int)(GRPC_SLICE_LENGTH(a) - b_length); if (d != 0) return d; return memcmp(GRPC_SLICE_START_PTR(a), b, b_length); } int grpc_slice_is_equivalent(grpc_slice a, grpc_slice b) { if (a.refcount == NULL || b.refcount == NULL) { return grpc_slice_eq(a, b); } return a.data.refcounted.length == b.data.refcounted.length && a.data.refcounted.bytes == b.data.refcounted.bytes; } int grpc_slice_buf_start_eq(grpc_slice a, const void *b, size_t len) { if (GRPC_SLICE_LENGTH(a) < len) return 0; return 0 == memcmp(GRPC_SLICE_START_PTR(a), b, len); } int grpc_slice_rchr(grpc_slice s, char c) { const char *b = (const char *)GRPC_SLICE_START_PTR(s); int i; for (i = (int)GRPC_SLICE_LENGTH(s) - 1; i != -1 && b[i] != c; i--) ; return i; } int grpc_slice_chr(grpc_slice s, char c) { const char *b = (const char *)GRPC_SLICE_START_PTR(s); const char *p = memchr(b, c, GRPC_SLICE_LENGTH(s)); return p == NULL ? -1 : (int)(p - b); } int grpc_slice_slice(grpc_slice haystack, grpc_slice needle) { size_t haystack_len = GRPC_SLICE_LENGTH(haystack); const uint8_t *haystack_bytes = GRPC_SLICE_START_PTR(haystack); size_t needle_len = GRPC_SLICE_LENGTH(needle); const uint8_t *needle_bytes = GRPC_SLICE_START_PTR(needle); if (haystack_len == 0 || needle_len == 0) return -1; if (haystack_len < needle_len) return -1; if (haystack_len == needle_len) return grpc_slice_eq(haystack, needle) ? 0 : -1; if (needle_len == 1) return grpc_slice_chr(haystack, (char)*needle_bytes); const uint8_t *last = haystack_bytes + haystack_len - needle_len; for (const uint8_t *cur = haystack_bytes; cur != last; ++cur) { if (0 == memcmp(cur, needle_bytes, needle_len)) { return (int)(cur - haystack_bytes); } } return -1; } grpc_slice grpc_slice_dup(grpc_slice a) { grpc_slice copy = grpc_slice_malloc(GRPC_SLICE_LENGTH(a)); memcpy(GRPC_SLICE_START_PTR(copy), GRPC_SLICE_START_PTR(a), GRPC_SLICE_LENGTH(a)); return copy; } grpc-1.3.2/src/core/lib/slice/slice_buffer.c000066400000000000000000000276451310511640000206350ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include "src/core/lib/slice/slice_internal.h" /* grow a buffer; requires GRPC_SLICE_BUFFER_INLINE_ELEMENTS > 1 */ #define GROW(x) (3 * (x) / 2) static void maybe_embiggen(grpc_slice_buffer *sb) { /* How far away from sb->base_slices is sb->slices pointer */ size_t slice_offset = (size_t)(sb->slices - sb->base_slices); size_t slice_count = sb->count + slice_offset; if (slice_count == sb->capacity) { if (sb->base_slices != sb->slices) { /* Make room by moving elements if there's still space unused */ memmove(sb->base_slices, sb->slices, sb->count * sizeof(grpc_slice)); sb->slices = sb->base_slices; } else { /* Allocate more memory if no more space is available */ sb->capacity = GROW(sb->capacity); GPR_ASSERT(sb->capacity > slice_count); if (sb->base_slices == sb->inlined) { sb->base_slices = gpr_malloc(sb->capacity * sizeof(grpc_slice)); memcpy(sb->base_slices, sb->inlined, slice_count * sizeof(grpc_slice)); } else { sb->base_slices = gpr_realloc(sb->base_slices, sb->capacity * sizeof(grpc_slice)); } sb->slices = sb->base_slices + slice_offset; } } } void grpc_slice_buffer_init(grpc_slice_buffer *sb) { sb->count = 0; sb->length = 0; sb->capacity = GRPC_SLICE_BUFFER_INLINE_ELEMENTS; sb->base_slices = sb->slices = sb->inlined; } void grpc_slice_buffer_destroy_internal(grpc_exec_ctx *exec_ctx, grpc_slice_buffer *sb) { grpc_slice_buffer_reset_and_unref_internal(exec_ctx, sb); if (sb->base_slices != sb->inlined) { gpr_free(sb->base_slices); } } void grpc_slice_buffer_destroy(grpc_slice_buffer *sb) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_slice_buffer_destroy_internal(&exec_ctx, sb); grpc_exec_ctx_finish(&exec_ctx); } uint8_t *grpc_slice_buffer_tiny_add(grpc_slice_buffer *sb, size_t n) { grpc_slice *back; uint8_t *out; sb->length += n; if (sb->count == 0) goto add_new; back = &sb->slices[sb->count - 1]; if (back->refcount) goto add_new; if ((back->data.inlined.length + n) > sizeof(back->data.inlined.bytes)) goto add_new; out = back->data.inlined.bytes + back->data.inlined.length; back->data.inlined.length = (uint8_t)(back->data.inlined.length + n); return out; add_new: maybe_embiggen(sb); back = &sb->slices[sb->count]; sb->count++; back->refcount = NULL; back->data.inlined.length = (uint8_t)n; return back->data.inlined.bytes; } size_t grpc_slice_buffer_add_indexed(grpc_slice_buffer *sb, grpc_slice s) { size_t out = sb->count; maybe_embiggen(sb); sb->slices[out] = s; sb->length += GRPC_SLICE_LENGTH(s); sb->count = out + 1; return out; } void grpc_slice_buffer_add(grpc_slice_buffer *sb, grpc_slice s) { size_t n = sb->count; /* if both the last slice in the slice buffer and the slice being added are inlined (that is, that they carry their data inside the slice data structure), and the back slice is not full, then concatenate directly into the back slice, preventing many small slices being passed into writes */ if (!s.refcount && n) { grpc_slice *back = &sb->slices[n - 1]; if (!back->refcount && back->data.inlined.length < GRPC_SLICE_INLINED_SIZE) { if (s.data.inlined.length + back->data.inlined.length <= GRPC_SLICE_INLINED_SIZE) { memcpy(back->data.inlined.bytes + back->data.inlined.length, s.data.inlined.bytes, s.data.inlined.length); back->data.inlined.length = (uint8_t)(back->data.inlined.length + s.data.inlined.length); } else { size_t cp1 = GRPC_SLICE_INLINED_SIZE - back->data.inlined.length; memcpy(back->data.inlined.bytes + back->data.inlined.length, s.data.inlined.bytes, cp1); back->data.inlined.length = GRPC_SLICE_INLINED_SIZE; maybe_embiggen(sb); back = &sb->slices[n]; sb->count = n + 1; back->refcount = NULL; back->data.inlined.length = (uint8_t)(s.data.inlined.length - cp1); memcpy(back->data.inlined.bytes, s.data.inlined.bytes + cp1, s.data.inlined.length - cp1); } sb->length += s.data.inlined.length; return; /* early out */ } } grpc_slice_buffer_add_indexed(sb, s); } void grpc_slice_buffer_addn(grpc_slice_buffer *sb, grpc_slice *s, size_t n) { size_t i; for (i = 0; i < n; i++) { grpc_slice_buffer_add(sb, s[i]); } } void grpc_slice_buffer_pop(grpc_slice_buffer *sb) { if (sb->count != 0) { size_t count = --sb->count; sb->length -= GRPC_SLICE_LENGTH(sb->slices[count]); } } void grpc_slice_buffer_reset_and_unref_internal(grpc_exec_ctx *exec_ctx, grpc_slice_buffer *sb) { size_t i; for (i = 0; i < sb->count; i++) { grpc_slice_unref_internal(exec_ctx, sb->slices[i]); } sb->count = 0; sb->length = 0; } void grpc_slice_buffer_reset_and_unref(grpc_slice_buffer *sb) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_slice_buffer_reset_and_unref_internal(&exec_ctx, sb); grpc_exec_ctx_finish(&exec_ctx); } void grpc_slice_buffer_swap(grpc_slice_buffer *a, grpc_slice_buffer *b) { size_t a_offset = (size_t)(a->slices - a->base_slices); size_t b_offset = (size_t)(b->slices - b->base_slices); size_t a_count = a->count + a_offset; size_t b_count = b->count + b_offset; if (a->base_slices == a->inlined) { if (b->base_slices == b->inlined) { /* swap contents of inlined buffer */ grpc_slice temp[GRPC_SLICE_BUFFER_INLINE_ELEMENTS]; memcpy(temp, a->base_slices, a_count * sizeof(grpc_slice)); memcpy(a->base_slices, b->base_slices, b_count * sizeof(grpc_slice)); memcpy(b->base_slices, temp, a_count * sizeof(grpc_slice)); } else { /* a is inlined, b is not - copy a inlined into b, fix pointers */ a->base_slices = b->base_slices; b->base_slices = b->inlined; memcpy(b->base_slices, a->inlined, a_count * sizeof(grpc_slice)); } } else if (b->base_slices == b->inlined) { /* b is inlined, a is not - copy b inlined int a, fix pointers */ b->base_slices = a->base_slices; a->base_slices = a->inlined; memcpy(a->base_slices, b->inlined, b_count * sizeof(grpc_slice)); } else { /* no inlining: easy swap */ GPR_SWAP(grpc_slice *, a->base_slices, b->base_slices); } /* Update the slices pointers (cannot do a GPR_SWAP on slices fields here). * Also note that since the base_slices pointers are already swapped we need * use 'b_offset' for 'a->base_slices' and vice versa */ a->slices = a->base_slices + b_offset; b->slices = b->base_slices + a_offset; /* base_slices and slices fields are correctly set. Swap all other fields */ GPR_SWAP(size_t, a->count, b->count); GPR_SWAP(size_t, a->capacity, b->capacity); GPR_SWAP(size_t, a->length, b->length); } void grpc_slice_buffer_move_into(grpc_slice_buffer *src, grpc_slice_buffer *dst) { /* anything to move? */ if (src->count == 0) { return; } /* anything in dst? */ if (dst->count == 0) { grpc_slice_buffer_swap(src, dst); return; } /* both buffers have data - copy, and reset src */ grpc_slice_buffer_addn(dst, src->slices, src->count); src->count = 0; src->length = 0; } void grpc_slice_buffer_move_first(grpc_slice_buffer *src, size_t n, grpc_slice_buffer *dst) { size_t output_len = dst->length + n; size_t new_input_len = src->length - n; GPR_ASSERT(src->length >= n); if (src->length == n) { grpc_slice_buffer_move_into(src, dst); return; } while (src->count > 0) { grpc_slice slice = grpc_slice_buffer_take_first(src); size_t slice_len = GRPC_SLICE_LENGTH(slice); if (n > slice_len) { grpc_slice_buffer_add(dst, slice); n -= slice_len; } else if (n == slice_len) { grpc_slice_buffer_add(dst, slice); break; } else { /* n < slice_len */ grpc_slice_buffer_undo_take_first(src, grpc_slice_split_tail(&slice, n)); GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == n); grpc_slice_buffer_add(dst, slice); break; } } GPR_ASSERT(dst->length == output_len); GPR_ASSERT(src->length == new_input_len); GPR_ASSERT(src->count > 0); } void grpc_slice_buffer_move_first_into_buffer(grpc_exec_ctx *exec_ctx, grpc_slice_buffer *src, size_t n, void *dst) { char *dstp = dst; GPR_ASSERT(src->length >= n); while (n > 0) { grpc_slice slice = grpc_slice_buffer_take_first(src); size_t slice_len = GRPC_SLICE_LENGTH(slice); if (slice_len > n) { memcpy(dstp, GRPC_SLICE_START_PTR(slice), n); grpc_slice_buffer_undo_take_first( src, grpc_slice_sub_no_ref(slice, n, slice_len)); n = 0; } else if (slice_len == n) { memcpy(dstp, GRPC_SLICE_START_PTR(slice), n); grpc_slice_unref_internal(exec_ctx, slice); n = 0; } else { memcpy(dstp, GRPC_SLICE_START_PTR(slice), slice_len); dstp += slice_len; n -= slice_len; grpc_slice_unref_internal(exec_ctx, slice); } } } void grpc_slice_buffer_trim_end(grpc_slice_buffer *sb, size_t n, grpc_slice_buffer *garbage) { GPR_ASSERT(n <= sb->length); sb->length -= n; for (;;) { size_t idx = sb->count - 1; grpc_slice slice = sb->slices[idx]; size_t slice_len = GRPC_SLICE_LENGTH(slice); if (slice_len > n) { sb->slices[idx] = grpc_slice_split_head(&slice, slice_len - n); grpc_slice_buffer_add_indexed(garbage, slice); return; } else if (slice_len == n) { grpc_slice_buffer_add_indexed(garbage, slice); sb->count = idx; return; } else { grpc_slice_buffer_add_indexed(garbage, slice); n -= slice_len; sb->count = idx; } } } grpc_slice grpc_slice_buffer_take_first(grpc_slice_buffer *sb) { grpc_slice slice; GPR_ASSERT(sb->count > 0); slice = sb->slices[0]; sb->slices++; sb->count--; sb->length -= GRPC_SLICE_LENGTH(slice); return slice; } void grpc_slice_buffer_undo_take_first(grpc_slice_buffer *sb, grpc_slice slice) { sb->slices--; sb->slices[0] = slice; sb->count++; sb->length += GRPC_SLICE_LENGTH(slice); } grpc-1.3.2/src/core/lib/slice/slice_hash_table.c000066400000000000000000000112461310511640000214440ustar00rootroot00000000000000// // Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #include "src/core/lib/slice/slice_hash_table.h" #include #include #include #include #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/transport/metadata.h" struct grpc_slice_hash_table { gpr_refcount refs; size_t size; grpc_slice_hash_table_entry* entries; }; static bool is_empty(grpc_slice_hash_table_entry* entry) { return entry->vtable == NULL; } // Helper function for insert and get operations that performs quadratic // probing (https://en.wikipedia.org/wiki/Quadratic_probing). static size_t grpc_slice_hash_table_find_index( const grpc_slice_hash_table* table, const grpc_slice key, bool find_empty) { size_t hash = grpc_slice_hash(key); for (size_t i = 0; i < table->size; ++i) { const size_t idx = (hash + i * i) % table->size; if (is_empty(&table->entries[idx])) { return find_empty ? idx : table->size; } if (grpc_slice_eq(table->entries[idx].key, key)) { return idx; } } return table->size; // Not found. } static void grpc_slice_hash_table_add( grpc_slice_hash_table* table, grpc_slice key, void* value, const grpc_slice_hash_table_vtable* vtable) { GPR_ASSERT(value != NULL); const size_t idx = grpc_slice_hash_table_find_index(table, key, true /* find_empty */); GPR_ASSERT(idx != table->size); // Table should never be full. grpc_slice_hash_table_entry* entry = &table->entries[idx]; entry->key = grpc_slice_ref_internal(key); entry->value = vtable->copy_value(value); entry->vtable = vtable; } grpc_slice_hash_table* grpc_slice_hash_table_create( size_t num_entries, grpc_slice_hash_table_entry* entries) { grpc_slice_hash_table* table = gpr_zalloc(sizeof(*table)); gpr_ref_init(&table->refs, 1); // Quadratic probing gets best performance when the table is no more // than half full. table->size = num_entries * 2; const size_t entry_size = sizeof(grpc_slice_hash_table_entry) * table->size; table->entries = gpr_zalloc(entry_size); for (size_t i = 0; i < num_entries; ++i) { grpc_slice_hash_table_entry* entry = &entries[i]; grpc_slice_hash_table_add(table, entry->key, entry->value, entry->vtable); } return table; } grpc_slice_hash_table* grpc_slice_hash_table_ref(grpc_slice_hash_table* table) { if (table != NULL) gpr_ref(&table->refs); return table; } void grpc_slice_hash_table_unref(grpc_exec_ctx* exec_ctx, grpc_slice_hash_table* table) { if (table != NULL && gpr_unref(&table->refs)) { for (size_t i = 0; i < table->size; ++i) { grpc_slice_hash_table_entry* entry = &table->entries[i]; if (!is_empty(entry)) { grpc_slice_unref_internal(exec_ctx, entry->key); entry->vtable->destroy_value(exec_ctx, entry->value); } } gpr_free(table->entries); gpr_free(table); } } void* grpc_slice_hash_table_get(const grpc_slice_hash_table* table, const grpc_slice key) { const size_t idx = grpc_slice_hash_table_find_index(table, key, false /* find_empty */); if (idx == table->size) return NULL; // Not found. return table->entries[idx].value; } grpc-1.3.2/src/core/lib/slice/slice_hash_table.h000066400000000000000000000063261310511640000214540ustar00rootroot00000000000000/* * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GRPC_CORE_LIB_SLICE_SLICE_HASH_TABLE_H #define GRPC_CORE_LIB_SLICE_SLICE_HASH_TABLE_H #include "src/core/lib/transport/metadata.h" /** Hash table implementation. * * This implementation uses open addressing * (https://en.wikipedia.org/wiki/Open_addressing) with quadratic * probing (https://en.wikipedia.org/wiki/Quadratic_probing). * * The keys are \a grpc_slice objects. The values are arbitrary pointers * with a common vtable. * * Hash tables are intentionally immutable, to avoid the need for locking. */ typedef struct grpc_slice_hash_table grpc_slice_hash_table; typedef struct grpc_slice_hash_table_vtable { void (*destroy_value)(grpc_exec_ctx *exec_ctx, void *value); void *(*copy_value)(void *value); } grpc_slice_hash_table_vtable; typedef struct grpc_slice_hash_table_entry { grpc_slice key; void *value; /* Must not be NULL. */ const grpc_slice_hash_table_vtable *vtable; } grpc_slice_hash_table_entry; /** Creates a new hash table of containing \a entries, which is an array of length \a num_entries. Creates its own copy of all keys and values from \a entries. */ grpc_slice_hash_table *grpc_slice_hash_table_create( size_t num_entries, grpc_slice_hash_table_entry *entries); grpc_slice_hash_table *grpc_slice_hash_table_ref(grpc_slice_hash_table *table); void grpc_slice_hash_table_unref(grpc_exec_ctx *exec_ctx, grpc_slice_hash_table *table); /** Returns the value from \a table associated with \a key. Returns NULL if \a key is not found. */ void *grpc_slice_hash_table_get(const grpc_slice_hash_table *table, const grpc_slice key); #endif /* GRPC_CORE_LIB_SLICE_SLICE_HASH_TABLE_H */ grpc-1.3.2/src/core/lib/slice/slice_intern.c000066400000000000000000000265331310511640000206560ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/slice/slice_internal.h" #include #include #include #include "src/core/lib/iomgr/iomgr_internal.h" /* for iomgr_abort_on_leaks() */ #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/murmur_hash.h" #include "src/core/lib/transport/static_metadata.h" #define LOG2_SHARD_COUNT 5 #define SHARD_COUNT (1 << LOG2_SHARD_COUNT) #define INITIAL_SHARD_CAPACITY 8 #define TABLE_IDX(hash, capacity) (((hash) >> LOG2_SHARD_COUNT) % (capacity)) #define SHARD_IDX(hash) ((hash) & ((1 << LOG2_SHARD_COUNT) - 1)) typedef struct interned_slice_refcount { grpc_slice_refcount base; grpc_slice_refcount sub; size_t length; gpr_atm refcnt; uint32_t hash; struct interned_slice_refcount *bucket_next; } interned_slice_refcount; typedef struct slice_shard { gpr_mu mu; interned_slice_refcount **strs; size_t count; size_t capacity; } slice_shard; /* hash seed: decided at initialization time */ static uint32_t g_hash_seed; static int g_forced_hash_seed = 0; static slice_shard g_shards[SHARD_COUNT]; typedef struct { uint32_t hash; uint32_t idx; } static_metadata_hash_ent; static static_metadata_hash_ent static_metadata_hash[4 * GRPC_STATIC_MDSTR_COUNT]; static uint32_t max_static_metadata_hash_probe; static uint32_t static_metadata_hash_values[GRPC_STATIC_MDSTR_COUNT]; static void interned_slice_ref(void *p) { interned_slice_refcount *s = p; GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&s->refcnt, 1) > 0); } static void interned_slice_destroy(interned_slice_refcount *s) { slice_shard *shard = &g_shards[SHARD_IDX(s->hash)]; gpr_mu_lock(&shard->mu); GPR_ASSERT(0 == gpr_atm_no_barrier_load(&s->refcnt)); interned_slice_refcount **prev_next; interned_slice_refcount *cur; for (prev_next = &shard->strs[TABLE_IDX(s->hash, shard->capacity)], cur = *prev_next; cur != s; prev_next = &cur->bucket_next, cur = cur->bucket_next) ; *prev_next = cur->bucket_next; shard->count--; gpr_free(s); gpr_mu_unlock(&shard->mu); } static void interned_slice_unref(grpc_exec_ctx *exec_ctx, void *p) { interned_slice_refcount *s = p; if (1 == gpr_atm_full_fetch_add(&s->refcnt, -1)) { interned_slice_destroy(s); } } static void interned_slice_sub_ref(void *p) { interned_slice_ref(((char *)p) - offsetof(interned_slice_refcount, sub)); } static void interned_slice_sub_unref(grpc_exec_ctx *exec_ctx, void *p) { interned_slice_unref(exec_ctx, ((char *)p) - offsetof(interned_slice_refcount, sub)); } static uint32_t interned_slice_hash(grpc_slice slice) { interned_slice_refcount *s = (interned_slice_refcount *)slice.refcount; return s->hash; } static int interned_slice_eq(grpc_slice a, grpc_slice b) { return a.refcount == b.refcount; } static const grpc_slice_refcount_vtable interned_slice_vtable = { interned_slice_ref, interned_slice_unref, interned_slice_eq, interned_slice_hash}; static const grpc_slice_refcount_vtable interned_slice_sub_vtable = { interned_slice_sub_ref, interned_slice_sub_unref, grpc_slice_default_eq_impl, grpc_slice_default_hash_impl}; static void grow_shard(slice_shard *shard) { size_t capacity = shard->capacity * 2; size_t i; interned_slice_refcount **strtab; interned_slice_refcount *s, *next; GPR_TIMER_BEGIN("grow_strtab", 0); strtab = gpr_zalloc(sizeof(interned_slice_refcount *) * capacity); for (i = 0; i < shard->capacity; i++) { for (s = shard->strs[i]; s; s = next) { size_t idx = TABLE_IDX(s->hash, capacity); next = s->bucket_next; s->bucket_next = strtab[idx]; strtab[idx] = s; } } gpr_free(shard->strs); shard->strs = strtab; shard->capacity = capacity; GPR_TIMER_END("grow_strtab", 0); } static grpc_slice materialize(interned_slice_refcount *s) { grpc_slice slice; slice.refcount = &s->base; slice.data.refcounted.bytes = (uint8_t *)(s + 1); slice.data.refcounted.length = s->length; return slice; } uint32_t grpc_slice_default_hash_impl(grpc_slice s) { return gpr_murmur_hash3(GRPC_SLICE_START_PTR(s), GRPC_SLICE_LENGTH(s), g_hash_seed); } uint32_t grpc_static_slice_hash(grpc_slice s) { return static_metadata_hash_values[GRPC_STATIC_METADATA_INDEX(s)]; } int grpc_static_slice_eq(grpc_slice a, grpc_slice b) { return GRPC_STATIC_METADATA_INDEX(a) == GRPC_STATIC_METADATA_INDEX(b); } uint32_t grpc_slice_hash(grpc_slice s) { return s.refcount == NULL ? grpc_slice_default_hash_impl(s) : s.refcount->vtable->hash(s); } grpc_slice grpc_slice_maybe_static_intern(grpc_slice slice, bool *returned_slice_is_different) { if (GRPC_IS_STATIC_METADATA_STRING(slice)) { return slice; } uint32_t hash = grpc_slice_hash(slice); for (uint32_t i = 0; i <= max_static_metadata_hash_probe; i++) { static_metadata_hash_ent ent = static_metadata_hash[(hash + i) % GPR_ARRAY_SIZE(static_metadata_hash)]; if (ent.hash == hash && ent.idx < GRPC_STATIC_MDSTR_COUNT && grpc_slice_eq(grpc_static_slice_table[ent.idx], slice)) { *returned_slice_is_different = true; return grpc_static_slice_table[ent.idx]; } } return slice; } bool grpc_slice_is_interned(grpc_slice slice) { return (slice.refcount && slice.refcount->vtable == &interned_slice_vtable) || GRPC_IS_STATIC_METADATA_STRING(slice); } grpc_slice grpc_slice_intern(grpc_slice slice) { GPR_TIMER_BEGIN("grpc_slice_intern", 0); if (GRPC_IS_STATIC_METADATA_STRING(slice)) { GPR_TIMER_END("grpc_slice_intern", 0); return slice; } uint32_t hash = grpc_slice_hash(slice); for (uint32_t i = 0; i <= max_static_metadata_hash_probe; i++) { static_metadata_hash_ent ent = static_metadata_hash[(hash + i) % GPR_ARRAY_SIZE(static_metadata_hash)]; if (ent.hash == hash && ent.idx < GRPC_STATIC_MDSTR_COUNT && grpc_slice_eq(grpc_static_slice_table[ent.idx], slice)) { GPR_TIMER_END("grpc_slice_intern", 0); return grpc_static_slice_table[ent.idx]; } } interned_slice_refcount *s; slice_shard *shard = &g_shards[SHARD_IDX(hash)]; gpr_mu_lock(&shard->mu); /* search for an existing string */ size_t idx = TABLE_IDX(hash, shard->capacity); for (s = shard->strs[idx]; s; s = s->bucket_next) { if (s->hash == hash && grpc_slice_eq(slice, materialize(s))) { if (gpr_atm_no_barrier_fetch_add(&s->refcnt, 1) == 0) { /* If we get here, we've added a ref to something that was about to * die - drop it immediately. * The *only* possible path here (given the shard mutex) should be to * drop from one ref back to zero - assert that with a CAS */ GPR_ASSERT(gpr_atm_rel_cas(&s->refcnt, 1, 0)); /* and treat this as if we were never here... sshhh */ } else { gpr_mu_unlock(&shard->mu); GPR_TIMER_END("grpc_slice_intern", 0); return materialize(s); } } } /* not found: create a new string */ /* string data goes after the internal_string header */ s = gpr_malloc(sizeof(*s) + GRPC_SLICE_LENGTH(slice)); gpr_atm_rel_store(&s->refcnt, 1); s->length = GRPC_SLICE_LENGTH(slice); s->hash = hash; s->base.vtable = &interned_slice_vtable; s->base.sub_refcount = &s->sub; s->sub.vtable = &interned_slice_sub_vtable; s->sub.sub_refcount = &s->sub; s->bucket_next = shard->strs[idx]; shard->strs[idx] = s; memcpy(s + 1, GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice)); shard->count++; if (shard->count > shard->capacity * 2) { grow_shard(shard); } gpr_mu_unlock(&shard->mu); GPR_TIMER_END("grpc_slice_intern", 0); return materialize(s); } void grpc_test_only_set_slice_hash_seed(uint32_t seed) { g_hash_seed = seed; g_forced_hash_seed = 1; } void grpc_slice_intern_init(void) { if (!g_forced_hash_seed) { g_hash_seed = (uint32_t)gpr_now(GPR_CLOCK_REALTIME).tv_nsec; } for (size_t i = 0; i < SHARD_COUNT; i++) { slice_shard *shard = &g_shards[i]; gpr_mu_init(&shard->mu); shard->count = 0; shard->capacity = INITIAL_SHARD_CAPACITY; shard->strs = gpr_zalloc(sizeof(*shard->strs) * shard->capacity); } for (size_t i = 0; i < GPR_ARRAY_SIZE(static_metadata_hash); i++) { static_metadata_hash[i].hash = 0; static_metadata_hash[i].idx = GRPC_STATIC_MDSTR_COUNT; } max_static_metadata_hash_probe = 0; for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) { static_metadata_hash_values[i] = grpc_slice_default_hash_impl(grpc_static_slice_table[i]); for (size_t j = 0; j < GPR_ARRAY_SIZE(static_metadata_hash); j++) { size_t slot = (static_metadata_hash_values[i] + j) % GPR_ARRAY_SIZE(static_metadata_hash); if (static_metadata_hash[slot].idx == GRPC_STATIC_MDSTR_COUNT) { static_metadata_hash[slot].hash = static_metadata_hash_values[i]; static_metadata_hash[slot].idx = (uint32_t)i; if (j > max_static_metadata_hash_probe) { max_static_metadata_hash_probe = (uint32_t)j; } break; } } } } void grpc_slice_intern_shutdown(void) { for (size_t i = 0; i < SHARD_COUNT; i++) { slice_shard *shard = &g_shards[i]; gpr_mu_destroy(&shard->mu); /* TODO(ctiller): GPR_ASSERT(shard->count == 0); */ if (shard->count != 0) { gpr_log(GPR_DEBUG, "WARNING: %" PRIuPTR " metadata strings were leaked", shard->count); for (size_t j = 0; j < shard->capacity; j++) { for (interned_slice_refcount *s = shard->strs[j]; s; s = s->bucket_next) { char *text = grpc_dump_slice(materialize(s), GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "LEAKED: %s", text); gpr_free(text); } } if (grpc_iomgr_abort_on_leaks()) { abort(); } } gpr_free(shard->strs); } } grpc-1.3.2/src/core/lib/slice/slice_internal.h000066400000000000000000000054721310511640000211770ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SLICE_SLICE_INTERNAL_H #define GRPC_CORE_LIB_SLICE_SLICE_INTERNAL_H #include #include #include "src/core/lib/iomgr/exec_ctx.h" grpc_slice grpc_slice_ref_internal(grpc_slice slice); void grpc_slice_unref_internal(grpc_exec_ctx *exec_ctx, grpc_slice slice); void grpc_slice_buffer_reset_and_unref_internal(grpc_exec_ctx *exec_ctx, grpc_slice_buffer *sb); void grpc_slice_buffer_destroy_internal(grpc_exec_ctx *exec_ctx, grpc_slice_buffer *sb); /* Check if a slice is interned */ bool grpc_slice_is_interned(grpc_slice slice); void grpc_slice_intern_init(void); void grpc_slice_intern_shutdown(void); void grpc_test_only_set_slice_hash_seed(uint32_t key); // if slice matches a static slice, returns the static slice // otherwise returns the passed in slice (without reffing it) // used for surface boundaries where we might receive an un-interned static // string grpc_slice grpc_slice_maybe_static_intern(grpc_slice slice, bool *returned_slice_is_different); uint32_t grpc_static_slice_hash(grpc_slice s); int grpc_static_slice_eq(grpc_slice a, grpc_slice b); #endif /* GRPC_CORE_LIB_SLICE_SLICE_INTERNAL_H */ grpc-1.3.2/src/core/lib/slice/slice_string_helpers.c000066400000000000000000000071601310511640000224020ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/slice/slice_string_helpers.h" #include #include #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/support/string.h" char *grpc_dump_slice(grpc_slice s, uint32_t flags) { return gpr_dump((const char *)GRPC_SLICE_START_PTR(s), GRPC_SLICE_LENGTH(s), flags); } /** Finds the initial (\a begin) and final (\a end) offsets of the next * substring from \a str + \a read_offset until the next \a sep or the end of \a * str. * * Returns 1 and updates \a begin and \a end. Returns 0 otherwise. */ static int slice_find_separator_offset(const grpc_slice str, const char *sep, const size_t read_offset, size_t *begin, size_t *end) { size_t i; const uint8_t *str_ptr = GRPC_SLICE_START_PTR(str) + read_offset; const size_t str_len = GRPC_SLICE_LENGTH(str) - read_offset; const size_t sep_len = strlen(sep); if (str_len < sep_len) { return 0; } for (i = 0; i <= str_len - sep_len; i++) { if (memcmp(str_ptr + i, sep, sep_len) == 0) { *begin = read_offset; *end = read_offset + i; return 1; } } return 0; } void grpc_slice_split(grpc_slice str, const char *sep, grpc_slice_buffer *dst) { const size_t sep_len = strlen(sep); size_t begin, end; GPR_ASSERT(sep_len > 0); if (slice_find_separator_offset(str, sep, 0, &begin, &end) != 0) { do { grpc_slice_buffer_add_indexed(dst, grpc_slice_sub(str, begin, end)); } while (slice_find_separator_offset(str, sep, end + sep_len, &begin, &end) != 0); grpc_slice_buffer_add_indexed( dst, grpc_slice_sub(str, end + sep_len, GRPC_SLICE_LENGTH(str))); } else { /* no sep found, add whole input */ grpc_slice_buffer_add_indexed(dst, grpc_slice_ref_internal(str)); } } bool grpc_parse_slice_to_uint32(grpc_slice str, uint32_t *result) { return gpr_parse_bytes_to_uint32((const char *)GRPC_SLICE_START_PTR(str), GRPC_SLICE_LENGTH(str), result) != 0; } grpc-1.3.2/src/core/lib/slice/slice_string_helpers.h000066400000000000000000000044511310511640000224070ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SLICE_SLICE_STRING_HELPERS_H #define GRPC_CORE_LIB_SLICE_SLICE_STRING_HELPERS_H #include #include #include #include #include #include "src/core/lib/support/string.h" #ifdef __cplusplus extern "C" { #endif /* Calls gpr_dump on a slice. */ char *grpc_dump_slice(grpc_slice slice, uint32_t flags); /** Split \a str by the separator \a sep. Results are stored in \a dst, which * should be a properly initialized instance. */ void grpc_slice_split(grpc_slice str, const char *sep, grpc_slice_buffer *dst); bool grpc_parse_slice_to_uint32(grpc_slice str, uint32_t *result); #ifdef __cplusplus } #endif #endif /* GRPC_CORE_LIB_SLICE_SLICE_STRING_HELPERS_H */ grpc-1.3.2/src/core/lib/slice/slice_traits.h000066400000000000000000000035541310511640000206700ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SLICE_SLICE_TRAITS_H #define GRPC_CORE_LIB_SLICE_SLICE_TRAITS_H #include #include bool grpc_slice_is_legal_header(grpc_slice s); bool grpc_slice_is_legal_nonbin_header(grpc_slice s); bool grpc_slice_is_bin_suffixed(grpc_slice s); #endif /* GRPC_CORE_LIB_SLICE_SLICE_TRAITS_H */ grpc-1.3.2/src/core/lib/support/000077500000000000000000000000001310511640000164405ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/support/alloc.c000066400000000000000000000072021310511640000176770ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include "src/core/lib/profiling/timers.h" static void *zalloc_with_calloc(size_t sz) { return calloc(sz, 1); } static void *zalloc_with_gpr_malloc(size_t sz) { void *p = gpr_malloc(sz); memset(p, 0, sz); return p; } static gpr_allocation_functions g_alloc_functions = {malloc, zalloc_with_calloc, realloc, free}; gpr_allocation_functions gpr_get_allocation_functions() { return g_alloc_functions; } void gpr_set_allocation_functions(gpr_allocation_functions functions) { GPR_ASSERT(functions.malloc_fn != NULL); GPR_ASSERT(functions.realloc_fn != NULL); GPR_ASSERT(functions.free_fn != NULL); if (functions.zalloc_fn == NULL) { functions.zalloc_fn = zalloc_with_gpr_malloc; } g_alloc_functions = functions; } void *gpr_malloc(size_t size) { void *p; if (size == 0) return NULL; GPR_TIMER_BEGIN("gpr_malloc", 0); p = g_alloc_functions.malloc_fn(size); if (!p) { abort(); } GPR_TIMER_END("gpr_malloc", 0); return p; } void *gpr_zalloc(size_t size) { void *p; if (size == 0) return NULL; GPR_TIMER_BEGIN("gpr_zalloc", 0); p = g_alloc_functions.zalloc_fn(size); if (!p) { abort(); } GPR_TIMER_END("gpr_zalloc", 0); return p; } void gpr_free(void *p) { GPR_TIMER_BEGIN("gpr_free", 0); g_alloc_functions.free_fn(p); GPR_TIMER_END("gpr_free", 0); } void *gpr_realloc(void *p, size_t size) { if ((size == 0) && (p == NULL)) return NULL; GPR_TIMER_BEGIN("gpr_realloc", 0); p = g_alloc_functions.realloc_fn(p, size); if (!p) { abort(); } GPR_TIMER_END("gpr_realloc", 0); return p; } void *gpr_malloc_aligned(size_t size, size_t alignment_log) { size_t alignment = ((size_t)1) << alignment_log; size_t extra = alignment - 1 + sizeof(void *); void *p = gpr_malloc(size + extra); void **ret = (void **)(((uintptr_t)p + extra) & ~(alignment - 1)); ret[-1] = p; return (void *)ret; } void gpr_free_aligned(void *ptr) { gpr_free(((void **)ptr)[-1]); } grpc-1.3.2/src/core/lib/support/arena.c000066400000000000000000000067351310511640000177050ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/support/arena.h" #include #include #include #include #define ROUND_UP_TO_ALIGNMENT_SIZE(x) \ (((x) + GPR_MAX_ALIGNMENT - 1u) & ~(GPR_MAX_ALIGNMENT - 1u)) typedef struct zone { size_t size_begin; size_t size_end; gpr_atm next_atm; } zone; struct gpr_arena { gpr_atm size_so_far; zone initial_zone; }; gpr_arena *gpr_arena_create(size_t initial_size) { initial_size = ROUND_UP_TO_ALIGNMENT_SIZE(initial_size); gpr_arena *a = gpr_zalloc(sizeof(gpr_arena) + initial_size); a->initial_zone.size_end = initial_size; return a; } size_t gpr_arena_destroy(gpr_arena *arena) { gpr_atm size = gpr_atm_no_barrier_load(&arena->size_so_far); zone *z = (zone *)gpr_atm_no_barrier_load(&arena->initial_zone.next_atm); gpr_free(arena); while (z) { zone *next_z = (zone *)gpr_atm_no_barrier_load(&z->next_atm); gpr_free(z); z = next_z; } return (size_t)size; } void *gpr_arena_alloc(gpr_arena *arena, size_t size) { size = ROUND_UP_TO_ALIGNMENT_SIZE(size); size_t start = (size_t)gpr_atm_no_barrier_fetch_add(&arena->size_so_far, size); zone *z = &arena->initial_zone; while (start > z->size_end) { zone *next_z = (zone *)gpr_atm_acq_load(&z->next_atm); if (next_z == NULL) { size_t next_z_size = (size_t)gpr_atm_no_barrier_load(&arena->size_so_far); next_z = gpr_zalloc(sizeof(zone) + next_z_size); next_z->size_begin = z->size_end; next_z->size_end = z->size_end + next_z_size; if (!gpr_atm_rel_cas(&z->next_atm, (gpr_atm)NULL, (gpr_atm)next_z)) { gpr_free(next_z); next_z = (zone *)gpr_atm_acq_load(&z->next_atm); } } z = next_z; } if (start + size > z->size_end) { return gpr_arena_alloc(arena, size); } GPR_ASSERT(start >= z->size_begin); GPR_ASSERT(start + size <= z->size_end); return ((char *)(z + 1)) + start - z->size_begin; } grpc-1.3.2/src/core/lib/support/arena.h000066400000000000000000000044511310511640000177030ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ // \file Arena based allocator // Allows very fast allocation of memory, but that memory cannot be freed until // the arena as a whole is freed // Tracks the total memory allocated against it, so that future arenas can // pre-allocate the right amount of memory #ifndef GRPC_CORE_LIB_SUPPORT_ARENA_H #define GRPC_CORE_LIB_SUPPORT_ARENA_H #include typedef struct gpr_arena gpr_arena; // Create an arena, with \a initial_size bytes in the first allocated buffer gpr_arena *gpr_arena_create(size_t initial_size); // Allocate \a size bytes from the arena void *gpr_arena_alloc(gpr_arena *arena, size_t size); // Destroy an arena, returning the total number of bytes allocated size_t gpr_arena_destroy(gpr_arena *arena); #endif /* GRPC_CORE_LIB_SUPPORT_ARENA_H */ grpc-1.3.2/src/core/lib/support/atm.c000066400000000000000000000037331310511640000173730ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include gpr_atm gpr_atm_no_barrier_clamped_add(gpr_atm *value, gpr_atm delta, gpr_atm min, gpr_atm max) { gpr_atm current; gpr_atm new; do { current = gpr_atm_no_barrier_load(value); new = GPR_CLAMP(current + delta, min, max); if (new == current) break; } while (!gpr_atm_no_barrier_cas(value, current, new)); return new; } grpc-1.3.2/src/core/lib/support/avl.c000066400000000000000000000236531310511640000173770ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include gpr_avl gpr_avl_create(const gpr_avl_vtable *vtable) { gpr_avl out; out.vtable = vtable; out.root = NULL; return out; } static gpr_avl_node *ref_node(gpr_avl_node *node) { if (node) { gpr_ref(&node->refs); } return node; } static void unref_node(const gpr_avl_vtable *vtable, gpr_avl_node *node) { if (node == NULL) { return; } if (gpr_unref(&node->refs)) { vtable->destroy_key(node->key); vtable->destroy_value(node->value); unref_node(vtable, node->left); unref_node(vtable, node->right); gpr_free(node); } } static long node_height(gpr_avl_node *node) { return node == NULL ? 0 : node->height; } #ifndef NDEBUG static long calculate_height(gpr_avl_node *node) { return node == NULL ? 0 : 1 + GPR_MAX(calculate_height(node->left), calculate_height(node->right)); } static gpr_avl_node *assert_invariants(gpr_avl_node *n) { if (n == NULL) return NULL; assert_invariants(n->left); assert_invariants(n->right); assert(calculate_height(n) == n->height); assert(labs(node_height(n->left) - node_height(n->right)) <= 1); return n; } #else static gpr_avl_node *assert_invariants(gpr_avl_node *n) { return n; } #endif gpr_avl_node *new_node(void *key, void *value, gpr_avl_node *left, gpr_avl_node *right) { gpr_avl_node *node = gpr_malloc(sizeof(*node)); gpr_ref_init(&node->refs, 1); node->key = key; node->value = value; node->left = assert_invariants(left); node->right = assert_invariants(right); node->height = 1 + GPR_MAX(node_height(left), node_height(right)); return node; } static gpr_avl_node *get(const gpr_avl_vtable *vtable, gpr_avl_node *node, void *key) { long cmp; if (node == NULL) { return NULL; } cmp = vtable->compare_keys(node->key, key); if (cmp == 0) { return node; } else if (cmp > 0) { return get(vtable, node->left, key); } else { return get(vtable, node->right, key); } } void *gpr_avl_get(gpr_avl avl, void *key) { gpr_avl_node *node = get(avl.vtable, avl.root, key); return node ? node->value : NULL; } int gpr_avl_maybe_get(gpr_avl avl, void *key, void **value) { gpr_avl_node *node = get(avl.vtable, avl.root, key); if (node != NULL) { *value = node->value; return 1; } return 0; } static gpr_avl_node *rotate_left(const gpr_avl_vtable *vtable, void *key, void *value, gpr_avl_node *left, gpr_avl_node *right) { gpr_avl_node *n = new_node(vtable->copy_key(right->key), vtable->copy_value(right->value), new_node(key, value, left, ref_node(right->left)), ref_node(right->right)); unref_node(vtable, right); return n; } static gpr_avl_node *rotate_right(const gpr_avl_vtable *vtable, void *key, void *value, gpr_avl_node *left, gpr_avl_node *right) { gpr_avl_node *n = new_node( vtable->copy_key(left->key), vtable->copy_value(left->value), ref_node(left->left), new_node(key, value, ref_node(left->right), right)); unref_node(vtable, left); return n; } static gpr_avl_node *rotate_left_right(const gpr_avl_vtable *vtable, void *key, void *value, gpr_avl_node *left, gpr_avl_node *right) { /* rotate_right(..., rotate_left(left), right) */ gpr_avl_node *n = new_node( vtable->copy_key(left->right->key), vtable->copy_value(left->right->value), new_node(vtable->copy_key(left->key), vtable->copy_value(left->value), ref_node(left->left), ref_node(left->right->left)), new_node(key, value, ref_node(left->right->right), right)); unref_node(vtable, left); return n; } static gpr_avl_node *rotate_right_left(const gpr_avl_vtable *vtable, void *key, void *value, gpr_avl_node *left, gpr_avl_node *right) { /* rotate_left(..., left, rotate_right(right)) */ gpr_avl_node *n = new_node( vtable->copy_key(right->left->key), vtable->copy_value(right->left->value), new_node(key, value, left, ref_node(right->left->left)), new_node(vtable->copy_key(right->key), vtable->copy_value(right->value), ref_node(right->left->right), ref_node(right->right))); unref_node(vtable, right); return n; } static gpr_avl_node *rebalance(const gpr_avl_vtable *vtable, void *key, void *value, gpr_avl_node *left, gpr_avl_node *right) { switch (node_height(left) - node_height(right)) { case 2: if (node_height(left->left) - node_height(left->right) == -1) { return assert_invariants( rotate_left_right(vtable, key, value, left, right)); } else { return assert_invariants(rotate_right(vtable, key, value, left, right)); } case -2: if (node_height(right->left) - node_height(right->right) == 1) { return assert_invariants( rotate_right_left(vtable, key, value, left, right)); } else { return assert_invariants(rotate_left(vtable, key, value, left, right)); } default: return assert_invariants(new_node(key, value, left, right)); } } static gpr_avl_node *add(const gpr_avl_vtable *vtable, gpr_avl_node *node, void *key, void *value) { long cmp; if (node == NULL) { return new_node(key, value, NULL, NULL); } cmp = vtable->compare_keys(node->key, key); if (cmp == 0) { return new_node(key, value, ref_node(node->left), ref_node(node->right)); } else if (cmp > 0) { return rebalance( vtable, vtable->copy_key(node->key), vtable->copy_value(node->value), add(vtable, node->left, key, value), ref_node(node->right)); } else { return rebalance(vtable, vtable->copy_key(node->key), vtable->copy_value(node->value), ref_node(node->left), add(vtable, node->right, key, value)); } } gpr_avl gpr_avl_add(gpr_avl avl, void *key, void *value) { gpr_avl_node *old_root = avl.root; avl.root = add(avl.vtable, avl.root, key, value); assert_invariants(avl.root); unref_node(avl.vtable, old_root); return avl; } static gpr_avl_node *in_order_head(gpr_avl_node *node) { while (node->left != NULL) { node = node->left; } return node; } static gpr_avl_node *in_order_tail(gpr_avl_node *node) { while (node->right != NULL) { node = node->right; } return node; } static gpr_avl_node *remove(const gpr_avl_vtable *vtable, gpr_avl_node *node, void *key) { long cmp; if (node == NULL) { return NULL; } cmp = vtable->compare_keys(node->key, key); if (cmp == 0) { if (node->left == NULL) { return ref_node(node->right); } else if (node->right == NULL) { return ref_node(node->left); } else if (node->left->height < node->right->height) { gpr_avl_node *h = in_order_head(node->right); return rebalance(vtable, vtable->copy_key(h->key), vtable->copy_value(h->value), ref_node(node->left), remove(vtable, node->right, h->key)); } else { gpr_avl_node *h = in_order_tail(node->left); return rebalance( vtable, vtable->copy_key(h->key), vtable->copy_value(h->value), remove(vtable, node->left, h->key), ref_node(node->right)); } } else if (cmp > 0) { return rebalance(vtable, vtable->copy_key(node->key), vtable->copy_value(node->value), remove(vtable, node->left, key), ref_node(node->right)); } else { return rebalance(vtable, vtable->copy_key(node->key), vtable->copy_value(node->value), ref_node(node->left), remove(vtable, node->right, key)); } } gpr_avl gpr_avl_remove(gpr_avl avl, void *key) { gpr_avl_node *old_root = avl.root; avl.root = remove(avl.vtable, avl.root, key); assert_invariants(avl.root); unref_node(avl.vtable, old_root); return avl; } gpr_avl gpr_avl_ref(gpr_avl avl) { ref_node(avl.root); return avl; } void gpr_avl_unref(gpr_avl avl) { unref_node(avl.vtable, avl.root); } int gpr_avl_is_empty(gpr_avl avl) { return avl.root == NULL; } grpc-1.3.2/src/core/lib/support/backoff.c000066400000000000000000000072701310511640000202050ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/support/backoff.h" #include void gpr_backoff_init(gpr_backoff *backoff, int64_t initial_connect_timeout, double multiplier, double jitter, int64_t min_timeout_millis, int64_t max_timeout_millis) { backoff->initial_connect_timeout = initial_connect_timeout; backoff->multiplier = multiplier; backoff->jitter = jitter; backoff->min_timeout_millis = min_timeout_millis; backoff->max_timeout_millis = max_timeout_millis; backoff->rng_state = (uint32_t)gpr_now(GPR_CLOCK_REALTIME).tv_nsec; } gpr_timespec gpr_backoff_begin(gpr_backoff *backoff, gpr_timespec now) { backoff->current_timeout_millis = backoff->initial_connect_timeout; const int64_t first_timeout = GPR_MAX(backoff->current_timeout_millis, backoff->min_timeout_millis); return gpr_time_add(now, gpr_time_from_millis(first_timeout, GPR_TIMESPAN)); } /* Generate a random number between 0 and 1. */ static double generate_uniform_random_number(uint32_t *rng_state) { *rng_state = (1103515245 * *rng_state + 12345) % ((uint32_t)1 << 31); return *rng_state / (double)((uint32_t)1 << 31); } gpr_timespec gpr_backoff_step(gpr_backoff *backoff, gpr_timespec now) { const double new_timeout_millis = backoff->multiplier * (double)backoff->current_timeout_millis; backoff->current_timeout_millis = GPR_MIN((int64_t)new_timeout_millis, backoff->max_timeout_millis); const double jitter_range_width = backoff->jitter * new_timeout_millis; const double jitter = (2 * generate_uniform_random_number(&backoff->rng_state) - 1) * jitter_range_width; backoff->current_timeout_millis = (int64_t)((double)(backoff->current_timeout_millis) + jitter); const gpr_timespec current_deadline = gpr_time_add( now, gpr_time_from_millis(backoff->current_timeout_millis, GPR_TIMESPAN)); const gpr_timespec min_deadline = gpr_time_add( now, gpr_time_from_millis(backoff->min_timeout_millis, GPR_TIMESPAN)); return gpr_time_max(current_deadline, min_deadline); } void gpr_backoff_reset(gpr_backoff *backoff) { backoff->current_timeout_millis = backoff->initial_connect_timeout; } grpc-1.3.2/src/core/lib/support/backoff.h000066400000000000000000000057001310511640000202060ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SUPPORT_BACKOFF_H #define GRPC_CORE_LIB_SUPPORT_BACKOFF_H #include typedef struct { /// const: how long to wait after the first failure before retrying int64_t initial_connect_timeout; /// const: factor with which to multiply backoff after a failed retry double multiplier; /// const: amount to randomize backoffs double jitter; /// const: minimum time between retries in milliseconds int64_t min_timeout_millis; /// const: maximum time between retries in milliseconds int64_t max_timeout_millis; /// random number generator uint32_t rng_state; /// current retry timeout in milliseconds int64_t current_timeout_millis; } gpr_backoff; /// Initialize backoff machinery - does not need to be destroyed void gpr_backoff_init(gpr_backoff *backoff, int64_t initial_connect_timeout, double multiplier, double jitter, int64_t min_timeout_millis, int64_t max_timeout_millis); /// Begin retry loop: returns a timespec for the NEXT retry gpr_timespec gpr_backoff_begin(gpr_backoff *backoff, gpr_timespec now); /// Step a retry loop: returns a timespec for the NEXT retry gpr_timespec gpr_backoff_step(gpr_backoff *backoff, gpr_timespec now); /// Reset the backoff, so the next gpr_backoff_step will be a gpr_backoff_begin /// instead void gpr_backoff_reset(gpr_backoff *backoff); #endif /* GRPC_CORE_LIB_SUPPORT_BACKOFF_H */ grpc-1.3.2/src/core/lib/support/block_annotate.h000066400000000000000000000041161310511640000215760ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SUPPORT_BLOCK_ANNOTATE_H #define GRPC_CORE_LIB_SUPPORT_BLOCK_ANNOTATE_H /* These annotations identify the beginning and end of regions where the code may block for reasons other than synchronization functions. These include poll, epoll, and getaddrinfo. */ #define GRPC_SCHEDULING_START_BLOCKING_REGION \ do { \ } while (0) #define GRPC_SCHEDULING_END_BLOCKING_REGION \ do { \ } while (0) #endif /* GRPC_CORE_LIB_SUPPORT_BLOCK_ANNOTATE_H */ grpc-1.3.2/src/core/lib/support/cmdline.c000066400000000000000000000217371310511640000202310ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include "src/core/lib/support/string.h" typedef enum { ARGTYPE_INT, ARGTYPE_BOOL, ARGTYPE_STRING } argtype; typedef struct arg { const char *name; const char *help; argtype type; void *value; struct arg *next; } arg; struct gpr_cmdline { const char *description; arg *args; const char *argv0; const char *extra_arg_name; const char *extra_arg_help; void (*extra_arg)(void *user_data, const char *arg); void *extra_arg_user_data; int (*state)(gpr_cmdline *cl, char *arg); arg *cur_arg; int survive_failure; }; static int normal_state(gpr_cmdline *cl, char *arg); gpr_cmdline *gpr_cmdline_create(const char *description) { gpr_cmdline *cl = gpr_zalloc(sizeof(gpr_cmdline)); cl->description = description; cl->state = normal_state; return cl; } void gpr_cmdline_set_survive_failure(gpr_cmdline *cl) { cl->survive_failure = 1; } void gpr_cmdline_destroy(gpr_cmdline *cl) { while (cl->args) { arg *a = cl->args; cl->args = a->next; gpr_free(a); } gpr_free(cl); } static void add_arg(gpr_cmdline *cl, const char *name, const char *help, argtype type, void *value) { arg *a; for (a = cl->args; a; a = a->next) { GPR_ASSERT(0 != strcmp(a->name, name)); } a = gpr_zalloc(sizeof(arg)); a->name = name; a->help = help; a->type = type; a->value = value; a->next = cl->args; cl->args = a; } void gpr_cmdline_add_int(gpr_cmdline *cl, const char *name, const char *help, int *value) { add_arg(cl, name, help, ARGTYPE_INT, value); } void gpr_cmdline_add_flag(gpr_cmdline *cl, const char *name, const char *help, int *value) { add_arg(cl, name, help, ARGTYPE_BOOL, value); } void gpr_cmdline_add_string(gpr_cmdline *cl, const char *name, const char *help, char **value) { add_arg(cl, name, help, ARGTYPE_STRING, value); } void gpr_cmdline_on_extra_arg( gpr_cmdline *cl, const char *name, const char *help, void (*on_extra_arg)(void *user_data, const char *arg), void *user_data) { GPR_ASSERT(!cl->extra_arg); GPR_ASSERT(on_extra_arg); cl->extra_arg = on_extra_arg; cl->extra_arg_user_data = user_data; cl->extra_arg_name = name; cl->extra_arg_help = help; } /* recursively descend argument list, adding the last element to s first - so that arguments are added in the order they were added to the list by api calls */ static void add_args_to_usage(gpr_strvec *s, arg *a) { char *tmp; if (!a) return; add_args_to_usage(s, a->next); switch (a->type) { case ARGTYPE_BOOL: gpr_asprintf(&tmp, " [--%s|--no-%s]", a->name, a->name); gpr_strvec_add(s, tmp); break; case ARGTYPE_STRING: gpr_asprintf(&tmp, " [--%s=string]", a->name); gpr_strvec_add(s, tmp); break; case ARGTYPE_INT: gpr_asprintf(&tmp, " [--%s=int]", a->name); gpr_strvec_add(s, tmp); break; } } char *gpr_cmdline_usage_string(gpr_cmdline *cl, const char *argv0) { /* TODO(ctiller): make this prettier */ gpr_strvec s; char *tmp; const char *name = strrchr(argv0, '/'); if (name) { name++; } else { name = argv0; } gpr_strvec_init(&s); gpr_asprintf(&tmp, "Usage: %s", name); gpr_strvec_add(&s, tmp); add_args_to_usage(&s, cl->args); if (cl->extra_arg) { gpr_asprintf(&tmp, " [%s...]", cl->extra_arg_name); gpr_strvec_add(&s, tmp); } gpr_strvec_add(&s, gpr_strdup("\n")); tmp = gpr_strvec_flatten(&s, NULL); gpr_strvec_destroy(&s); return tmp; } static int print_usage_and_die(gpr_cmdline *cl) { char *usage = gpr_cmdline_usage_string(cl, cl->argv0); fprintf(stderr, "%s", usage); gpr_free(usage); if (!cl->survive_failure) { exit(1); } return 0; } static int extra_state(gpr_cmdline *cl, char *str) { if (!cl->extra_arg) { return print_usage_and_die(cl); } cl->extra_arg(cl->extra_arg_user_data, str); return 1; } static arg *find_arg(gpr_cmdline *cl, char *name) { arg *a; for (a = cl->args; a; a = a->next) { if (0 == strcmp(a->name, name)) { break; } } if (!a) { fprintf(stderr, "Unknown argument: %s\n", name); return NULL; } return a; } static int value_state(gpr_cmdline *cl, char *str) { long intval; char *end; GPR_ASSERT(cl->cur_arg); switch (cl->cur_arg->type) { case ARGTYPE_INT: intval = strtol(str, &end, 0); if (*end || intval < INT_MIN || intval > INT_MAX) { fprintf(stderr, "expected integer, got '%s' for %s\n", str, cl->cur_arg->name); return print_usage_and_die(cl); } *(int *)cl->cur_arg->value = (int)intval; break; case ARGTYPE_BOOL: if (0 == strcmp(str, "1") || 0 == strcmp(str, "true")) { *(int *)cl->cur_arg->value = 1; } else if (0 == strcmp(str, "0") || 0 == strcmp(str, "false")) { *(int *)cl->cur_arg->value = 0; } else { fprintf(stderr, "expected boolean, got '%s' for %s\n", str, cl->cur_arg->name); return print_usage_and_die(cl); } break; case ARGTYPE_STRING: *(char **)cl->cur_arg->value = str; break; } cl->state = normal_state; return 1; } static int normal_state(gpr_cmdline *cl, char *str) { char *eq = NULL; char *tmp = NULL; char *arg_name = NULL; int r = 1; if (0 == strcmp(str, "-help") || 0 == strcmp(str, "--help") || 0 == strcmp(str, "-h")) { return print_usage_and_die(cl); } cl->cur_arg = NULL; if (str[0] == '-') { if (str[1] == '-') { if (str[2] == 0) { /* handle '--' to move to just extra args */ cl->state = extra_state; return 1; } str += 2; } else { str += 1; } /* first byte of str is now past the leading '-' or '--' */ if (str[0] == 'n' && str[1] == 'o' && str[2] == '-') { /* str is of the form '--no-foo' - it's a flag disable */ str += 3; cl->cur_arg = find_arg(cl, str); if (cl->cur_arg == NULL) { return print_usage_and_die(cl); } if (cl->cur_arg->type != ARGTYPE_BOOL) { fprintf(stderr, "%s is not a flag argument\n", str); return print_usage_and_die(cl); } *(int *)cl->cur_arg->value = 0; return 1; /* early out */ } eq = strchr(str, '='); if (eq != NULL) { /* copy the string into a temp buffer and extract the name */ tmp = arg_name = gpr_malloc((size_t)(eq - str + 1)); memcpy(arg_name, str, (size_t)(eq - str)); arg_name[eq - str] = 0; } else { arg_name = str; } cl->cur_arg = find_arg(cl, arg_name); if (cl->cur_arg == NULL) { return print_usage_and_die(cl); } if (eq != NULL) { /* str was of the type --foo=value, parse the value */ r = value_state(cl, eq + 1); } else if (cl->cur_arg->type != ARGTYPE_BOOL) { /* flag types don't have a '--foo value' variant, other types do */ cl->state = value_state; } else { /* flag parameter: just set the value */ *(int *)cl->cur_arg->value = 1; } } else { r = extra_state(cl, str); } gpr_free(tmp); return r; } int gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv) { int i; GPR_ASSERT(argc >= 1); cl->argv0 = argv[0]; for (i = 1; i < argc; i++) { if (!cl->state(cl, argv[i])) { return 0; } } return 1; } grpc-1.3.2/src/core/lib/support/cpu_iphone.c000066400000000000000000000043161310511640000207410ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifdef GPR_CPU_IPHONE /* Probably 2 instead of 1, but see comment on gpr_cpu_current_cpu. */ unsigned gpr_cpu_num_cores(void) { return 1; } /* Most code that's using this is using it to shard across work queues. So unless profiling shows it's a problem or there appears a way to detect the currently running CPU core, let's have it shard the default way. Note that the interface in cpu.h lets gpr_cpu_num_cores return 0, but doing it makes it impossible for gpr_cpu_current_cpu to satisfy its stated range, and some code might be relying on it. */ unsigned gpr_cpu_current_cpu(void) { return 0; } #endif /* GPR_CPU_IPHONE */ grpc-1.3.2/src/core/lib/support/cpu_linux.c000066400000000000000000000051221310511640000206120ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif /* _GNU_SOURCE */ #include #ifdef GPR_CPU_LINUX #include #include #include #include #include #include #include static int ncpus = 0; static void init_num_cpus() { /* This must be signed. sysconf returns -1 when the number cannot be determined */ ncpus = (int)sysconf(_SC_NPROCESSORS_ONLN); if (ncpus < 1) { gpr_log(GPR_ERROR, "Cannot determine number of CPUs: assuming 1"); ncpus = 1; } } unsigned gpr_cpu_num_cores(void) { static gpr_once once = GPR_ONCE_INIT; gpr_once_init(&once, init_num_cpus); return (unsigned)ncpus; } unsigned gpr_cpu_current_cpu(void) { #ifdef GPR_MUSL_LIBC_COMPAT // sched_getcpu() is undefined on musl return 0; #else int cpu = sched_getcpu(); if (cpu < 0) { gpr_log(GPR_ERROR, "Error determining current CPU: %s\n", strerror(errno)); return 0; } return (unsigned)cpu; #endif } #endif /* GPR_CPU_LINUX */ grpc-1.3.2/src/core/lib/support/cpu_posix.c000066400000000000000000000050471310511640000206230ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifdef GPR_CPU_POSIX #include #include #include #include #include #include static __thread char magic_thread_local; static long ncpus = 0; static void init_ncpus() { ncpus = sysconf(_SC_NPROCESSORS_ONLN); if (ncpus < 1 || ncpus > INT32_MAX) { gpr_log(GPR_ERROR, "Cannot determine number of CPUs: assuming 1"); ncpus = 1; } } unsigned gpr_cpu_num_cores(void) { static gpr_once once = GPR_ONCE_INIT; gpr_once_init(&once, init_ncpus); return (unsigned)ncpus; } unsigned gpr_cpu_current_cpu(void) { /* NOTE: there's no way I know to return the actual cpu index portably... most code that's using this is using it to shard across work queues though, so here we use thread identity instead to achieve a similar though not identical effect */ return (unsigned)GPR_HASH_POINTER(&magic_thread_local, gpr_cpu_num_cores()); } #endif /* GPR_CPU_POSIX */ grpc-1.3.2/src/core/lib/support/cpu_windows.c000066400000000000000000000035221310511640000211470ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifdef GPR_WINDOWS #include unsigned gpr_cpu_num_cores(void) { SYSTEM_INFO si; GetSystemInfo(&si); return si.dwNumberOfProcessors; } unsigned gpr_cpu_current_cpu(void) { return GetCurrentProcessorNumber(); } #endif /* GPR_WINDOWS */ grpc-1.3.2/src/core/lib/support/env.h000066400000000000000000000042471310511640000174100ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SUPPORT_ENV_H #define GRPC_CORE_LIB_SUPPORT_ENV_H #include #ifdef __cplusplus extern "C" { #endif /* Env utility functions */ /* Gets the environment variable value with the specified name. Returns a newly allocated string. It is the responsability of the caller to gpr_free the return value if not NULL (which means that the environment variable exists). */ char *gpr_getenv(const char *name); /* Sets the the environment with the specified name to the specified value. */ void gpr_setenv(const char *name, const char *value); #ifdef __cplusplus } #endif #endif /* GRPC_CORE_LIB_SUPPORT_ENV_H */ grpc-1.3.2/src/core/lib/support/env_linux.c000066400000000000000000000062471310511640000206240ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* for secure_getenv. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #ifdef GPR_LINUX_ENV #include "src/core/lib/support/env.h" #include #include #include #include #include #include #include #include "src/core/lib/support/string.h" char *gpr_getenv(const char *name) { #if defined(GPR_BACKWARDS_COMPATIBILITY_MODE) typedef char *(*getenv_type)(const char *); static getenv_type getenv_func = NULL; /* Check to see which getenv variant is supported (go from most * to least secure) */ const char *names[] = {"secure_getenv", "__secure_getenv", "getenv"}; for (size_t i = 0; getenv_func == NULL && i < GPR_ARRAY_SIZE(names); i++) { getenv_func = (getenv_type)dlsym(RTLD_DEFAULT, names[i]); if (getenv_func != NULL && strstr(names[i], "secure") == NULL) { gpr_log(GPR_DEBUG, "Warning: insecure environment read function '%s' used", names[i]); } } char *result = getenv_func(name); return result == NULL ? result : gpr_strdup(result); #elif __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17) char *result = secure_getenv(name); return result == NULL ? result : gpr_strdup(result); #else gpr_log(GPR_DEBUG, "Warning: insecure environment read function '%s' used", "getenv"); char *result = getenv(name); return result == NULL ? result : gpr_strdup(result); #endif } void gpr_setenv(const char *name, const char *value) { int res = setenv(name, value, 1); GPR_ASSERT(res == 0); } #endif /* GPR_LINUX_ENV */ grpc-1.3.2/src/core/lib/support/env_posix.c000066400000000000000000000040331310511640000206160ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifdef GPR_POSIX_ENV #include "src/core/lib/support/env.h" #include #include #include #include "src/core/lib/support/string.h" char *gpr_getenv(const char *name) { char *result = getenv(name); return result == NULL ? result : gpr_strdup(result); } void gpr_setenv(const char *name, const char *value) { int res = setenv(name, value, 1); GPR_ASSERT(res == 0); } #endif /* GPR_POSIX_ENV */ grpc-1.3.2/src/core/lib/support/env_windows.c000066400000000000000000000051741310511640000211550ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifdef GPR_WINDOWS_ENV #include #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" #include "src/core/lib/support/string_windows.h" #include #include #include char *gpr_getenv(const char *name) { char *result = NULL; DWORD size; LPTSTR tresult = NULL; LPTSTR tname = gpr_char_to_tchar(name); DWORD ret; ret = GetEnvironmentVariable(tname, NULL, 0); if (ret == 0) return NULL; size = ret * (DWORD)sizeof(TCHAR); tresult = gpr_malloc(size); ret = GetEnvironmentVariable(tname, tresult, size); gpr_free(tname); if (ret == 0) { gpr_free(tresult); return NULL; } result = gpr_tchar_to_char(tresult); gpr_free(tresult); return result; } void gpr_setenv(const char *name, const char *value) { LPTSTR tname = gpr_char_to_tchar(name); LPTSTR tvalue = gpr_char_to_tchar(value); BOOL res = SetEnvironmentVariable(tname, tvalue); gpr_free(tname); gpr_free(tvalue); GPR_ASSERT(res); } #endif /* GPR_WINDOWS_ENV */ grpc-1.3.2/src/core/lib/support/histogram.c000066400000000000000000000171741310511640000206130ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include /* Histograms are stored with exponentially increasing bucket sizes. The first bucket is [0, m) where m = 1 + resolution Bucket n (n>=1) contains [m**n, m**(n+1)) There are sufficient buckets to reach max_bucket_start */ struct gpr_histogram { /* Sum of all values seen so far */ double sum; /* Sum of squares of all values seen so far */ double sum_of_squares; /* number of values seen so far */ double count; /* m in the description */ double multiplier; double one_on_log_multiplier; /* minimum value seen */ double min_seen; /* maximum value seen */ double max_seen; /* maximum representable value */ double max_possible; /* number of buckets */ size_t num_buckets; /* the buckets themselves */ uint32_t *buckets; }; /* determine a bucket index given a value - does no bounds checking */ static size_t bucket_for_unchecked(gpr_histogram *h, double x) { return (size_t)(log(x) * h->one_on_log_multiplier); } /* bounds checked version of the above */ static size_t bucket_for(gpr_histogram *h, double x) { size_t bucket = bucket_for_unchecked(h, GPR_CLAMP(x, 1.0, h->max_possible)); GPR_ASSERT(bucket < h->num_buckets); return bucket; } /* at what value does a bucket start? */ static double bucket_start(gpr_histogram *h, double x) { return pow(h->multiplier, x); } gpr_histogram *gpr_histogram_create(double resolution, double max_bucket_start) { gpr_histogram *h = gpr_malloc(sizeof(gpr_histogram)); GPR_ASSERT(resolution > 0.0); GPR_ASSERT(max_bucket_start > resolution); h->sum = 0.0; h->sum_of_squares = 0.0; h->multiplier = 1.0 + resolution; h->one_on_log_multiplier = 1.0 / log(1.0 + resolution); h->max_possible = max_bucket_start; h->count = 0.0; h->min_seen = max_bucket_start; h->max_seen = 0.0; h->num_buckets = bucket_for_unchecked(h, max_bucket_start) + 1; GPR_ASSERT(h->num_buckets > 1); GPR_ASSERT(h->num_buckets < 100000000); h->buckets = gpr_zalloc(sizeof(uint32_t) * h->num_buckets); return h; } void gpr_histogram_destroy(gpr_histogram *h) { gpr_free(h->buckets); gpr_free(h); } void gpr_histogram_add(gpr_histogram *h, double x) { h->sum += x; h->sum_of_squares += x * x; h->count++; if (x < h->min_seen) { h->min_seen = x; } if (x > h->max_seen) { h->max_seen = x; } h->buckets[bucket_for(h, x)]++; } int gpr_histogram_merge(gpr_histogram *dst, const gpr_histogram *src) { if ((dst->num_buckets != src->num_buckets) || (dst->multiplier != src->multiplier)) { /* Fail because these histograms don't match */ return 0; } gpr_histogram_merge_contents(dst, src->buckets, src->num_buckets, src->min_seen, src->max_seen, src->sum, src->sum_of_squares, src->count); return 1; } void gpr_histogram_merge_contents(gpr_histogram *dst, const uint32_t *data, size_t data_count, double min_seen, double max_seen, double sum, double sum_of_squares, double count) { size_t i; GPR_ASSERT(dst->num_buckets == data_count); dst->sum += sum; dst->sum_of_squares += sum_of_squares; dst->count += count; if (min_seen < dst->min_seen) { dst->min_seen = min_seen; } if (max_seen > dst->max_seen) { dst->max_seen = max_seen; } for (i = 0; i < dst->num_buckets; i++) { dst->buckets[i] += data[i]; } } static double threshold_for_count_below(gpr_histogram *h, double count_below) { double count_so_far; double lower_bound; double upper_bound; size_t lower_idx; size_t upper_idx; if (h->count == 0) { return 0.0; } if (count_below <= 0) { return h->min_seen; } if (count_below >= h->count) { return h->max_seen; } /* find the lowest bucket that gets us above count_below */ count_so_far = 0.0; for (lower_idx = 0; lower_idx < h->num_buckets; lower_idx++) { count_so_far += h->buckets[lower_idx]; if (count_so_far >= count_below) { break; } } if (count_so_far == count_below) { /* this bucket hits the threshold exactly... we should be midway through any run of zero values following the bucket */ for (upper_idx = lower_idx + 1; upper_idx < h->num_buckets; upper_idx++) { if (h->buckets[upper_idx]) { break; } } return (bucket_start(h, (double)lower_idx) + bucket_start(h, (double)upper_idx)) / 2.0; } else { /* treat values as uniform throughout the bucket, and find where this value should lie */ lower_bound = bucket_start(h, (double)lower_idx); upper_bound = bucket_start(h, (double)(lower_idx + 1)); return GPR_CLAMP(upper_bound - (upper_bound - lower_bound) * (count_so_far - count_below) / h->buckets[lower_idx], h->min_seen, h->max_seen); } } double gpr_histogram_percentile(gpr_histogram *h, double percentile) { return threshold_for_count_below(h, h->count * percentile / 100.0); } double gpr_histogram_mean(gpr_histogram *h) { GPR_ASSERT(h->count != 0); return h->sum / h->count; } double gpr_histogram_stddev(gpr_histogram *h) { return sqrt(gpr_histogram_variance(h)); } double gpr_histogram_variance(gpr_histogram *h) { if (h->count == 0) return 0.0; return (h->sum_of_squares * h->count - h->sum * h->sum) / (h->count * h->count); } double gpr_histogram_maximum(gpr_histogram *h) { return h->max_seen; } double gpr_histogram_minimum(gpr_histogram *h) { return h->min_seen; } double gpr_histogram_count(gpr_histogram *h) { return h->count; } double gpr_histogram_sum(gpr_histogram *h) { return h->sum; } double gpr_histogram_sum_of_squares(gpr_histogram *h) { return h->sum_of_squares; } const uint32_t *gpr_histogram_get_contents(gpr_histogram *h, size_t *size) { *size = h->num_buckets; return h->buckets; } grpc-1.3.2/src/core/lib/support/host_port.c000066400000000000000000000070701310511640000206310ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include "src/core/lib/support/string.h" int gpr_join_host_port(char **out, const char *host, int port) { if (host[0] != '[' && strchr(host, ':') != NULL) { /* IPv6 literals must be enclosed in brackets. */ return gpr_asprintf(out, "[%s]:%d", host, port); } else { /* Ordinary non-bracketed host:port. */ return gpr_asprintf(out, "%s:%d", host, port); } } int gpr_split_host_port(const char *name, char **host, char **port) { const char *host_start; size_t host_len; const char *port_start; *host = NULL; *port = NULL; if (name[0] == '[') { /* Parse a bracketed host, typically an IPv6 literal. */ const char *rbracket = strchr(name, ']'); if (rbracket == NULL) { /* Unmatched [ */ return 0; } if (rbracket[1] == '\0') { /* ] */ port_start = NULL; } else if (rbracket[1] == ':') { /* ]: */ port_start = rbracket + 2; } else { /* ] */ return 0; } host_start = name + 1; host_len = (size_t)(rbracket - host_start); if (memchr(host_start, ':', host_len) == NULL) { /* Require all bracketed hosts to contain a colon, because a hostname or IPv4 address should never use brackets. */ return 0; } } else { const char *colon = strchr(name, ':'); if (colon != NULL && strchr(colon + 1, ':') == NULL) { /* Exactly 1 colon. Split into host:port. */ host_start = name; host_len = (size_t)(colon - name); port_start = colon + 1; } else { /* 0 or 2+ colons. Bare hostname or IPv6 litearal. */ host_start = name; host_len = strlen(name); port_start = NULL; } } /* Allocate return values. */ *host = gpr_malloc(host_len + 1); memcpy(*host, host_start, host_len); (*host)[host_len] = '\0'; if (port_start != NULL) { *port = gpr_strdup(port_start); } return 1; } grpc-1.3.2/src/core/lib/support/log.c000066400000000000000000000071531310511640000173730ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" #include #include extern void gpr_default_log(gpr_log_func_args *args); static gpr_log_func g_log_func = gpr_default_log; static gpr_atm g_min_severity_to_print = GPR_LOG_VERBOSITY_UNSET; const char *gpr_log_severity_string(gpr_log_severity severity) { switch (severity) { case GPR_LOG_SEVERITY_DEBUG: return "D"; case GPR_LOG_SEVERITY_INFO: return "I"; case GPR_LOG_SEVERITY_ERROR: return "E"; } GPR_UNREACHABLE_CODE(return "UNKNOWN"); } void gpr_log_message(const char *file, int line, gpr_log_severity severity, const char *message) { if ((gpr_atm)severity < gpr_atm_no_barrier_load(&g_min_severity_to_print)) { return; } gpr_log_func_args lfargs; memset(&lfargs, 0, sizeof(lfargs)); lfargs.file = file; lfargs.line = line; lfargs.severity = severity; lfargs.message = message; g_log_func(&lfargs); } void gpr_set_log_verbosity(gpr_log_severity min_severity_to_print) { gpr_atm_no_barrier_store(&g_min_severity_to_print, (gpr_atm)min_severity_to_print); } void gpr_log_verbosity_init() { char *verbosity = gpr_getenv("GRPC_VERBOSITY"); gpr_atm min_severity_to_print = GPR_LOG_SEVERITY_ERROR; if (verbosity != NULL) { if (gpr_stricmp(verbosity, "DEBUG") == 0) { min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_DEBUG; } else if (gpr_stricmp(verbosity, "INFO") == 0) { min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_INFO; } else if (gpr_stricmp(verbosity, "ERROR") == 0) { min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_ERROR; } gpr_free(verbosity); } if ((gpr_atm_no_barrier_load(&g_min_severity_to_print)) == GPR_LOG_VERBOSITY_UNSET) { gpr_atm_no_barrier_store(&g_min_severity_to_print, min_severity_to_print); } } void gpr_set_log_function(gpr_log_func f) { g_log_func = f ? f : gpr_default_log; } grpc-1.3.2/src/core/lib/support/log_android.c000066400000000000000000000055621310511640000210750ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifdef GPR_ANDROID #include #include #include #include #include #include static android_LogPriority severity_to_log_priority(gpr_log_severity severity) { switch (severity) { case GPR_LOG_SEVERITY_DEBUG: return ANDROID_LOG_DEBUG; case GPR_LOG_SEVERITY_INFO: return ANDROID_LOG_INFO; case GPR_LOG_SEVERITY_ERROR: return ANDROID_LOG_ERROR; } return ANDROID_LOG_DEFAULT; } void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format, ...) { char *message = NULL; va_list args; va_start(args, format); vasprintf(&message, format, args); va_end(args); gpr_log_message(file, line, severity, message); free(message); } void gpr_default_log(gpr_log_func_args *args) { char *final_slash; const char *display_file; char *output = NULL; final_slash = strrchr(args->file, '/'); if (final_slash == NULL) display_file = args->file; else display_file = final_slash + 1; asprintf(&output, "%s:%d] %s", display_file, args->line, args->message); __android_log_write(severity_to_log_priority(args->severity), "GRPC", output); /* allocated by asprintf => use free, not gpr_free */ free(output); } #endif /* GPR_ANDROID */ grpc-1.3.2/src/core/lib/support/log_linux.c000066400000000000000000000064621310511640000206140ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef _POSIX_SOURCE #define _POSIX_SOURCE #endif #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #ifdef GPR_LINUX_LOG #include #include #include #include #include #include #include #include #include #include static long gettid(void) { return syscall(__NR_gettid); } void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format, ...) { char *message = NULL; va_list args; va_start(args, format); if (vasprintf(&message, format, args) == -1) { va_end(args); return; } va_end(args); gpr_log_message(file, line, severity, message); /* message has been allocated by vasprintf above, and needs free */ free(message); } void gpr_default_log(gpr_log_func_args *args) { char *final_slash; char *prefix; const char *display_file; char time_buffer[64]; time_t timer; gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); struct tm tm; timer = (time_t)now.tv_sec; final_slash = strrchr(args->file, '/'); if (final_slash == NULL) display_file = args->file; else display_file = final_slash + 1; if (!localtime_r(&timer, &tm)) { strcpy(time_buffer, "error:localtime"); } else if (0 == strftime(time_buffer, sizeof(time_buffer), "%m%d %H:%M:%S", &tm)) { strcpy(time_buffer, "error:strftime"); } gpr_asprintf(&prefix, "%s%s.%09" PRId32 " %7ld %s:%d]", gpr_log_severity_string(args->severity), time_buffer, now.tv_nsec, gettid(), display_file, args->line); fprintf(stderr, "%-60s %s\n", prefix, args->message); gpr_free(prefix); } #endif /* GPR_LINUX_LOG */ grpc-1.3.2/src/core/lib/support/log_posix.c000066400000000000000000000067011310511640000206130ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifdef GPR_POSIX_LOG #include #include #include #include #include #include #include #include #include #include static intptr_t gettid(void) { return (intptr_t)pthread_self(); } void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format, ...) { char buf[64]; char *allocated = NULL; char *message = NULL; int ret; va_list args; va_start(args, format); ret = vsnprintf(buf, sizeof(buf), format, args); va_end(args); if (ret < 0) { message = NULL; } else if ((size_t)ret <= sizeof(buf) - 1) { message = buf; } else { message = allocated = gpr_malloc((size_t)ret + 1); va_start(args, format); vsnprintf(message, (size_t)(ret + 1), format, args); va_end(args); } gpr_log_message(file, line, severity, message); gpr_free(allocated); } void gpr_default_log(gpr_log_func_args *args) { char *final_slash; const char *display_file; char time_buffer[64]; time_t timer; gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); struct tm tm; timer = (time_t)now.tv_sec; final_slash = strrchr(args->file, '/'); if (final_slash == NULL) display_file = args->file; else display_file = final_slash + 1; if (!localtime_r(&timer, &tm)) { strcpy(time_buffer, "error:localtime"); } else if (0 == strftime(time_buffer, sizeof(time_buffer), "%m%d %H:%M:%S", &tm)) { strcpy(time_buffer, "error:strftime"); } char *prefix; gpr_asprintf(&prefix, "%s%s.%09d %7tu %s:%d]", gpr_log_severity_string(args->severity), time_buffer, (int)(now.tv_nsec), gettid(), display_file, args->line); fprintf(stderr, "%-70s %s\n", prefix, args->message); gpr_free(prefix); } #endif /* defined(GPR_POSIX_LOG) */ grpc-1.3.2/src/core/lib/support/log_windows.c000066400000000000000000000071211310511640000211400ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifdef GPR_WINDOWS_LOG #include #include #include #include #include #include #include #include "src/core/lib/support/string.h" #include "src/core/lib/support/string_windows.h" void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format, ...) { char *message = NULL; va_list args; int ret; /* Determine the length. */ va_start(args, format); ret = _vscprintf(format, args); va_end(args); if (ret < 0) { message = NULL; } else { /* Allocate a new buffer, with space for the NUL terminator. */ size_t strp_buflen = (size_t)ret + 1; message = gpr_malloc(strp_buflen); /* Print to the buffer. */ va_start(args, format); ret = vsnprintf_s(message, strp_buflen, _TRUNCATE, format, args); va_end(args); if ((size_t)ret != strp_buflen - 1) { /* This should never happen. */ gpr_free(message); message = NULL; } } gpr_log_message(file, line, severity, message); gpr_free(message); } /* Simple starter implementation */ void gpr_default_log(gpr_log_func_args *args) { char *final_slash; const char *display_file; char time_buffer[64]; time_t timer; gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); struct tm tm; timer = (time_t)now.tv_sec; final_slash = strrchr(args->file, '\\'); if (final_slash == NULL) display_file = args->file; else display_file = final_slash + 1; if (localtime_s(&tm, &timer)) { strcpy(time_buffer, "error:localtime"); } else if (0 == strftime(time_buffer, sizeof(time_buffer), "%m%d %H:%M:%S", &tm)) { strcpy(time_buffer, "error:strftime"); } fprintf(stderr, "%s%s.%09u %5lu %s:%d] %s\n", gpr_log_severity_string(args->severity), time_buffer, (int)(now.tv_nsec), GetCurrentThreadId(), display_file, args->line, args->message); fflush(stderr); } #endif /* GPR_WINDOWS_LOG */ grpc-1.3.2/src/core/lib/support/mpscq.c000066400000000000000000000057441310511640000177410ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/support/mpscq.h" #include void gpr_mpscq_init(gpr_mpscq *q) { gpr_atm_no_barrier_store(&q->head, (gpr_atm)&q->stub); q->tail = &q->stub; gpr_atm_no_barrier_store(&q->stub.next, (gpr_atm)NULL); } void gpr_mpscq_destroy(gpr_mpscq *q) { GPR_ASSERT(gpr_atm_no_barrier_load(&q->head) == (gpr_atm)&q->stub); GPR_ASSERT(q->tail == &q->stub); } void gpr_mpscq_push(gpr_mpscq *q, gpr_mpscq_node *n) { gpr_atm_no_barrier_store(&n->next, (gpr_atm)NULL); gpr_mpscq_node *prev = (gpr_mpscq_node *)gpr_atm_full_xchg(&q->head, (gpr_atm)n); gpr_atm_rel_store(&prev->next, (gpr_atm)n); } gpr_mpscq_node *gpr_mpscq_pop(gpr_mpscq *q) { gpr_mpscq_node *tail = q->tail; gpr_mpscq_node *next = (gpr_mpscq_node *)gpr_atm_acq_load(&tail->next); if (tail == &q->stub) { // indicates the list is actually (ephemerally) empty if (next == NULL) return NULL; q->tail = next; tail = next; next = (gpr_mpscq_node *)gpr_atm_acq_load(&tail->next); } if (next != NULL) { q->tail = next; return tail; } gpr_mpscq_node *head = (gpr_mpscq_node *)gpr_atm_acq_load(&q->head); if (tail != head) { // indicates a retry is in order: we're still adding return NULL; } gpr_mpscq_push(q, &q->stub); next = (gpr_mpscq_node *)gpr_atm_acq_load(&tail->next); if (next != NULL) { q->tail = next; return tail; } // indicates a retry is in order: we're still adding return NULL; } grpc-1.3.2/src/core/lib/support/mpscq.h000066400000000000000000000051201310511640000177320ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SUPPORT_MPSCQ_H #define GRPC_CORE_LIB_SUPPORT_MPSCQ_H #include #include // Multiple-producer single-consumer lock free queue, based upon the // implementation from Dmitry Vyukov here: // http://www.1024cores.net/home/lock-free-algorithms/queues/intrusive-mpsc-node-based-queue // List node (include this in a data structure at the top, and add application // fields after it - to simulate inheritance) typedef struct gpr_mpscq_node { gpr_atm next; } gpr_mpscq_node; // Actual queue type typedef struct gpr_mpscq { gpr_atm head; // make sure head & tail don't share a cacheline char padding[GPR_CACHELINE_SIZE]; gpr_mpscq_node *tail; gpr_mpscq_node stub; } gpr_mpscq; void gpr_mpscq_init(gpr_mpscq *q); void gpr_mpscq_destroy(gpr_mpscq *q); // Push a node void gpr_mpscq_push(gpr_mpscq *q, gpr_mpscq_node *n); // Pop a node (returns NULL if no node is ready - which doesn't indicate that // the queue is empty!!) gpr_mpscq_node *gpr_mpscq_pop(gpr_mpscq *q); #endif /* GRPC_CORE_LIB_SUPPORT_MPSCQ_H */ grpc-1.3.2/src/core/lib/support/murmur_hash.c000066400000000000000000000053401310511640000211400ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/support/murmur_hash.h" #include #define ROTL32(x, r) ((x) << (r)) | ((x) >> (32 - (r))) #define FMIX32(h) \ (h) ^= (h) >> 16; \ (h) *= 0x85ebca6b; \ (h) ^= (h) >> 13; \ (h) *= 0xc2b2ae35; \ (h) ^= (h) >> 16; uint32_t gpr_murmur_hash3(const void *key, size_t len, uint32_t seed) { const uint8_t *data = (const uint8_t *)key; const size_t nblocks = len / 4; int i; uint32_t h1 = seed; uint32_t k1; const uint32_t c1 = 0xcc9e2d51; const uint32_t c2 = 0x1b873593; const uint32_t *blocks = ((const uint32_t *)key) + nblocks; const uint8_t *tail = (const uint8_t *)(data + nblocks * 4); /* body */ for (i = -(int)nblocks; i; i++) { memcpy(&k1, blocks + i, sizeof(uint32_t)); k1 *= c1; k1 = ROTL32(k1, 15); k1 *= c2; h1 ^= k1; h1 = ROTL32(h1, 13); h1 = h1 * 5 + 0xe6546b64; } k1 = 0; /* tail */ switch (len & 3) { case 3: k1 ^= ((uint32_t)tail[2]) << 16; case 2: k1 ^= ((uint32_t)tail[1]) << 8; case 1: k1 ^= tail[0]; k1 *= c1; k1 = ROTL32(k1, 15); k1 *= c2; h1 ^= k1; }; /* finalization */ h1 ^= (uint32_t)len; FMIX32(h1); return h1; } grpc-1.3.2/src/core/lib/support/murmur_hash.h000066400000000000000000000035351310511640000211510ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SUPPORT_MURMUR_HASH_H #define GRPC_CORE_LIB_SUPPORT_MURMUR_HASH_H #include #include /* compute the hash of key (length len) */ uint32_t gpr_murmur_hash3(const void *key, size_t len, uint32_t seed); #endif /* GRPC_CORE_LIB_SUPPORT_MURMUR_HASH_H */ grpc-1.3.2/src/core/lib/support/spinlock.h000066400000000000000000000043031310511640000204330ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SUPPORT_SPINLOCK_H #define GRPC_CORE_LIB_SUPPORT_SPINLOCK_H #include /* Simple spinlock. No backoff strategy, gpr_spinlock_lock is almost always a concurrency code smell. */ typedef struct { gpr_atm atm; } gpr_spinlock; #define GPR_SPINLOCK_INITIALIZER ((gpr_spinlock){0}) #define GPR_SPINLOCK_STATIC_INITIALIZER \ { 0 } #define gpr_spinlock_trylock(lock) (gpr_atm_acq_cas(&(lock)->atm, 0, 1)) #define gpr_spinlock_unlock(lock) (gpr_atm_rel_store(&(lock)->atm, 0)) #define gpr_spinlock_lock(lock) \ do { \ } while (!gpr_spinlock_trylock((lock))) #endif /* GRPC_CORE_LIB_SUPPORT_SPINLOCK_H */ grpc-1.3.2/src/core/lib/support/stack_lockfree.c000066400000000000000000000144531310511640000215720ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/support/stack_lockfree.h" #include #include #include #include #include #include /* The lockfree node structure is a single architecture-level word that allows for an atomic CAS to set it up. */ struct lockfree_node_contents { /* next thing to look at. Actual index for head, next index otherwise */ uint16_t index; #ifdef GPR_ARCH_64 uint16_t pad; uint32_t aba_ctr; #else #ifdef GPR_ARCH_32 uint16_t aba_ctr; #else #error Unsupported bit width architecture #endif #endif }; /* Use a union to make sure that these are in the same bits as an atm word */ typedef union lockfree_node { gpr_atm atm; struct lockfree_node_contents contents; } lockfree_node; /* make sure that entries aligned to 8-bytes */ #define ENTRY_ALIGNMENT_BITS 3 /* reserve this entry as invalid */ #define INVALID_ENTRY_INDEX ((1 << 16) - 1) struct gpr_stack_lockfree { lockfree_node *entries; lockfree_node head; /* An atomic entry describing curr head */ #ifndef NDEBUG /* Bitmap of pushed entries to check for double-push or pop */ gpr_atm pushed[(INVALID_ENTRY_INDEX + 1) / (8 * sizeof(gpr_atm))]; #endif }; gpr_stack_lockfree *gpr_stack_lockfree_create(size_t entries) { gpr_stack_lockfree *stack; stack = gpr_malloc(sizeof(*stack)); /* Since we only allocate 16 bits to represent an entry number, * make sure that we are within the desired range */ /* Reserve the highest entry number as a dummy */ GPR_ASSERT(entries < INVALID_ENTRY_INDEX); stack->entries = gpr_malloc_aligned(entries * sizeof(stack->entries[0]), ENTRY_ALIGNMENT_BITS); /* Clear out all entries */ memset(stack->entries, 0, entries * sizeof(stack->entries[0])); memset(&stack->head, 0, sizeof(stack->head)); #ifndef NDEBUG memset(&stack->pushed, 0, sizeof(stack->pushed)); #endif GPR_ASSERT(sizeof(stack->entries->atm) == sizeof(stack->entries->contents)); /* Point the head at reserved dummy entry */ stack->head.contents.index = INVALID_ENTRY_INDEX; /* Fill in the pad and aba_ctr to avoid confusing memcheck tools */ #ifdef GPR_ARCH_64 stack->head.contents.pad = 0; #endif stack->head.contents.aba_ctr = 0; return stack; } void gpr_stack_lockfree_destroy(gpr_stack_lockfree *stack) { gpr_free_aligned(stack->entries); gpr_free(stack); } int gpr_stack_lockfree_push(gpr_stack_lockfree *stack, int entry) { lockfree_node head; lockfree_node newhead; lockfree_node curent; lockfree_node newent; /* First fill in the entry's index and aba ctr for new head */ newhead.contents.index = (uint16_t)entry; #ifdef GPR_ARCH_64 /* Fill in the pad to avoid confusing memcheck tools */ newhead.contents.pad = 0; #endif /* Also post-increment the aba_ctr */ curent.atm = gpr_atm_no_barrier_load(&stack->entries[entry].atm); newhead.contents.aba_ctr = ++curent.contents.aba_ctr; gpr_atm_no_barrier_store(&stack->entries[entry].atm, curent.atm); #ifndef NDEBUG /* Check for double push */ { int pushed_index = entry / (int)(8 * sizeof(gpr_atm)); int pushed_bit = entry % (int)(8 * sizeof(gpr_atm)); gpr_atm old_val; old_val = gpr_atm_no_barrier_fetch_add(&stack->pushed[pushed_index], ((gpr_atm)1 << pushed_bit)); GPR_ASSERT((old_val & (((gpr_atm)1) << pushed_bit)) == 0); } #endif do { /* Atomically get the existing head value for use */ head.atm = gpr_atm_no_barrier_load(&(stack->head.atm)); /* Point to it */ newent.atm = gpr_atm_no_barrier_load(&stack->entries[entry].atm); newent.contents.index = head.contents.index; gpr_atm_no_barrier_store(&stack->entries[entry].atm, newent.atm); } while (!gpr_atm_rel_cas(&(stack->head.atm), head.atm, newhead.atm)); /* Use rel_cas above to make sure that entry index is set properly */ return head.contents.index == INVALID_ENTRY_INDEX; } int gpr_stack_lockfree_pop(gpr_stack_lockfree *stack) { lockfree_node head; lockfree_node newhead; do { head.atm = gpr_atm_acq_load(&(stack->head.atm)); if (head.contents.index == INVALID_ENTRY_INDEX) { return -1; } newhead.atm = gpr_atm_no_barrier_load(&(stack->entries[head.contents.index].atm)); } while (!gpr_atm_no_barrier_cas(&(stack->head.atm), head.atm, newhead.atm)); #ifndef NDEBUG /* Check for valid pop */ { int pushed_index = head.contents.index / (8 * sizeof(gpr_atm)); int pushed_bit = head.contents.index % (8 * sizeof(gpr_atm)); gpr_atm old_val; old_val = gpr_atm_no_barrier_fetch_add(&stack->pushed[pushed_index], -((gpr_atm)1 << pushed_bit)); GPR_ASSERT((old_val & (((gpr_atm)1) << pushed_bit)) != 0); } #endif return head.contents.index; } grpc-1.3.2/src/core/lib/support/stack_lockfree.h000066400000000000000000000044601310511640000215740ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SUPPORT_STACK_LOCKFREE_H #define GRPC_CORE_LIB_SUPPORT_STACK_LOCKFREE_H #include typedef struct gpr_stack_lockfree gpr_stack_lockfree; /* This stack must specify the maximum number of entries to track. The current implementation only allows up to 65534 entries */ gpr_stack_lockfree *gpr_stack_lockfree_create(size_t entries); void gpr_stack_lockfree_destroy(gpr_stack_lockfree *stack); /* Pass in a valid entry number for the next stack entry */ /* Returns 1 if this is the first element on the stack, 0 otherwise */ int gpr_stack_lockfree_push(gpr_stack_lockfree *, int entry); /* Returns -1 on empty or the actual entry number */ int gpr_stack_lockfree_pop(gpr_stack_lockfree *stack); #endif /* GRPC_CORE_LIB_SUPPORT_STACK_LOCKFREE_H */ grpc-1.3.2/src/core/lib/support/string.c000066400000000000000000000201541310511640000201140ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/support/string.h" #include #include #include #include #include #include #include #include #include char *gpr_strdup(const char *src) { char *dst; size_t len; if (!src) { return NULL; } len = strlen(src) + 1; dst = gpr_malloc(len); memcpy(dst, src, len); return dst; } typedef struct { size_t capacity; size_t length; char *data; } dump_out; static dump_out dump_out_create(void) { dump_out r = {0, 0, NULL}; return r; } static void dump_out_append(dump_out *out, char c) { if (out->length == out->capacity) { out->capacity = GPR_MAX(8, 2 * out->capacity); out->data = gpr_realloc(out->data, out->capacity); } out->data[out->length++] = c; } static void hexdump(dump_out *out, const char *buf, size_t len) { static const char hex[16] = "0123456789abcdef"; const uint8_t *const beg = (const uint8_t *)buf; const uint8_t *const end = beg + len; const uint8_t *cur; for (cur = beg; cur != end; ++cur) { if (cur != beg) dump_out_append(out, ' '); dump_out_append(out, hex[*cur >> 4]); dump_out_append(out, hex[*cur & 0xf]); } } static void asciidump(dump_out *out, const char *buf, size_t len) { const uint8_t *const beg = (const uint8_t *)buf; const uint8_t *const end = beg + len; const uint8_t *cur; int out_was_empty = (out->length == 0); if (!out_was_empty) { dump_out_append(out, ' '); dump_out_append(out, '\''); } for (cur = beg; cur != end; ++cur) { dump_out_append(out, (char)(isprint(*cur) ? *(char *)cur : '.')); } if (!out_was_empty) { dump_out_append(out, '\''); } } char *gpr_dump(const char *buf, size_t len, uint32_t flags) { dump_out out = dump_out_create(); if (flags & GPR_DUMP_HEX) { hexdump(&out, buf, len); } if (flags & GPR_DUMP_ASCII) { asciidump(&out, buf, len); } dump_out_append(&out, 0); return out.data; } int gpr_parse_bytes_to_uint32(const char *buf, size_t len, uint32_t *result) { uint32_t out = 0; uint32_t new; size_t i; if (len == 0) return 0; /* must have some bytes */ for (i = 0; i < len; i++) { if (buf[i] < '0' || buf[i] > '9') return 0; /* bad char */ new = 10 * out + (uint32_t)(buf[i] - '0'); if (new < out) return 0; /* overflow */ out = new; } *result = out; return 1; } void gpr_reverse_bytes(char *str, int len) { char *p1, *p2; for (p1 = str, p2 = str + len - 1; p2 > p1; ++p1, --p2) { char temp = *p1; *p1 = *p2; *p2 = temp; } } int gpr_ltoa(long value, char *string) { long sign; int i = 0; if (value == 0) { string[0] = '0'; string[1] = 0; return 1; } sign = value < 0 ? -1 : 1; while (value) { string[i++] = (char)('0' + sign * (value % 10)); value /= 10; } if (sign < 0) string[i++] = '-'; gpr_reverse_bytes(string, i); string[i] = 0; return i; } int int64_ttoa(int64_t value, char *string) { int64_t sign; int i = 0; if (value == 0) { string[0] = '0'; string[1] = 0; return 1; } sign = value < 0 ? -1 : 1; while (value) { string[i++] = (char)('0' + sign * (value % 10)); value /= 10; } if (sign < 0) string[i++] = '-'; gpr_reverse_bytes(string, i); string[i] = 0; return i; } int gpr_parse_nonnegative_int(const char *value) { char *end; long result = strtol(value, &end, 0); if (*end != '\0' || result < 0 || result > INT_MAX) return -1; return (int)result; } char *gpr_leftpad(const char *str, char flag, size_t length) { const size_t str_length = strlen(str); const size_t out_length = str_length > length ? str_length : length; char *out = gpr_malloc(out_length + 1); memset(out, flag, out_length - str_length); memcpy(out + out_length - str_length, str, str_length); out[out_length] = 0; return out; } char *gpr_strjoin(const char **strs, size_t nstrs, size_t *final_length) { return gpr_strjoin_sep(strs, nstrs, "", final_length); } char *gpr_strjoin_sep(const char **strs, size_t nstrs, const char *sep, size_t *final_length) { const size_t sep_len = strlen(sep); size_t out_length = 0; size_t i; char *out; for (i = 0; i < nstrs; i++) { out_length += strlen(strs[i]); } out_length += 1; /* null terminator */ if (nstrs > 0) { out_length += sep_len * (nstrs - 1); /* separators */ } out = gpr_malloc(out_length); out_length = 0; for (i = 0; i < nstrs; i++) { const size_t slen = strlen(strs[i]); if (i != 0) { memcpy(out + out_length, sep, sep_len); out_length += sep_len; } memcpy(out + out_length, strs[i], slen); out_length += slen; } out[out_length] = 0; if (final_length != NULL) { *final_length = out_length; } return out; } void gpr_strvec_init(gpr_strvec *sv) { memset(sv, 0, sizeof(*sv)); } void gpr_strvec_destroy(gpr_strvec *sv) { size_t i; for (i = 0; i < sv->count; i++) { gpr_free(sv->strs[i]); } gpr_free(sv->strs); } void gpr_strvec_add(gpr_strvec *sv, char *str) { if (sv->count == sv->capacity) { sv->capacity = GPR_MAX(sv->capacity + 8, sv->capacity * 2); sv->strs = gpr_realloc(sv->strs, sizeof(char *) * sv->capacity); } sv->strs[sv->count++] = str; } char *gpr_strvec_flatten(gpr_strvec *sv, size_t *final_length) { return gpr_strjoin((const char **)sv->strs, sv->count, final_length); } int gpr_stricmp(const char *a, const char *b) { int ca, cb; do { ca = tolower(*a); cb = tolower(*b); ++a; ++b; } while (ca == cb && ca && cb); return ca - cb; } static void add_string_to_split(const char *beg, const char *end, char ***strs, size_t *nstrs, size_t *capstrs) { char *out = gpr_malloc((size_t)(end - beg) + 1); memcpy(out, beg, (size_t)(end - beg)); out[end - beg] = 0; if (*nstrs == *capstrs) { *capstrs = GPR_MAX(8, 2 * *capstrs); *strs = gpr_realloc(*strs, sizeof(*strs) * *capstrs); } (*strs)[*nstrs] = out; ++*nstrs; } void gpr_string_split(const char *input, const char *sep, char ***strs, size_t *nstrs) { char *next; *strs = NULL; *nstrs = 0; size_t capstrs = 0; while ((next = strstr(input, sep))) { add_string_to_split(input, next, strs, nstrs, &capstrs); input = next + strlen(sep); } add_string_to_split(input, input + strlen(input), strs, nstrs, &capstrs); } void *gpr_memrchr(const void *s, int c, size_t n) { if (s == NULL) return NULL; char *b = (char *)s; size_t i; for (i = 0; i < n; i++) { if (b[n - i - 1] == c) { return &b[n - i - 1]; } } return NULL; } grpc-1.3.2/src/core/lib/support/string.h000066400000000000000000000114451310511640000201240ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SUPPORT_STRING_H #define GRPC_CORE_LIB_SUPPORT_STRING_H #include #include #ifdef __cplusplus extern "C" { #endif /* String utility functions */ /* Flags for gpr_dump function. */ #define GPR_DUMP_HEX 0x00000001 #define GPR_DUMP_ASCII 0x00000002 /* Converts array buf, of length len, into a C string according to the flags. Result should be freed with gpr_free() */ char *gpr_dump(const char *buf, size_t len, uint32_t flags); /* Parses an array of bytes into an integer (base 10). Returns 1 on success, 0 on failure. */ int gpr_parse_bytes_to_uint32(const char *data, size_t length, uint32_t *result); /* Minimum buffer size for calling ltoa */ #define GPR_LTOA_MIN_BUFSIZE (3 * sizeof(long)) /* Convert a long to a string in base 10; returns the length of the output string (or 0 on failure). output must be at least GPR_LTOA_MIN_BUFSIZE bytes long. */ int gpr_ltoa(long value, char *output); /* Minimum buffer size for calling int64toa */ #define GPR_INT64TOA_MIN_BUFSIZE (3 * sizeof(int64_t)) /* Convert an int64 to a string in base 10; returns the length of the output string (or 0 on failure). output must be at least GPR_INT64TOA_MIN_BUFSIZE bytes long. NOTE: This function ensures sufficient bit width even on Win x64, where long is 32bit is size.*/ int int64_ttoa(int64_t value, char *output); // Parses a non-negative number from a value string. Returns -1 on error. int gpr_parse_nonnegative_int(const char *value); /* Reverse a run of bytes */ void gpr_reverse_bytes(char *str, int len); /* Pad a string with flag characters. The given length specifies the minimum field width. The input string is never truncated. */ char *gpr_leftpad(const char *str, char flag, size_t length); /* Join a set of strings, returning the resulting string. Total combined length (excluding null terminator) is returned in total_length if it is non-null. */ char *gpr_strjoin(const char **strs, size_t nstrs, size_t *total_length); /* Join a set of strings using a separator, returning the resulting string. Total combined length (excluding null terminator) is returned in total_length if it is non-null. */ char *gpr_strjoin_sep(const char **strs, size_t nstrs, const char *sep, size_t *total_length); void gpr_string_split(const char *input, const char *sep, char ***strs, size_t *nstrs); /* A vector of strings... for building up a final string one piece at a time */ typedef struct { char **strs; size_t count; size_t capacity; } gpr_strvec; /* Initialize/destroy */ void gpr_strvec_init(gpr_strvec *strs); void gpr_strvec_destroy(gpr_strvec *strs); /* Add a string to a strvec, takes ownership of the string */ void gpr_strvec_add(gpr_strvec *strs, char *add); /* Return a joined string with all added substrings, optionally setting total_length as per gpr_strjoin */ char *gpr_strvec_flatten(gpr_strvec *strs, size_t *total_length); /** Case insensitive string comparison... return <0 if lower(a)0 if lower(a)>lower(b) */ int gpr_stricmp(const char *a, const char *b); void *gpr_memrchr(const void *s, int c, size_t n); #ifdef __cplusplus } #endif #endif /* GRPC_CORE_LIB_SUPPORT_STRING_H */ grpc-1.3.2/src/core/lib/support/string_posix.c000066400000000000000000000053031310511640000213350ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifdef GPR_POSIX_STRING #include #include #include #include int gpr_asprintf(char **strp, const char *format, ...) { va_list args; int ret; char buf[64]; size_t strp_buflen; /* Use a constant-sized buffer to determine the length. */ va_start(args, format); ret = vsnprintf(buf, sizeof(buf), format, args); va_end(args); if (ret < 0) { *strp = NULL; return -1; } /* Allocate a new buffer, with space for the NUL terminator. */ strp_buflen = (size_t)ret + 1; if ((*strp = gpr_malloc(strp_buflen)) == NULL) { /* This shouldn't happen, because gpr_malloc() calls abort(). */ return -1; } /* Return early if we have all the bytes. */ if (strp_buflen <= sizeof(buf)) { memcpy(*strp, buf, strp_buflen); return ret; } /* Try again using the larger buffer. */ va_start(args, format); ret = vsnprintf(*strp, strp_buflen, format, args); va_end(args); if ((size_t)ret == strp_buflen - 1) { return ret; } /* This should never happen. */ gpr_free(*strp); *strp = NULL; return -1; } #endif /* GPR_POSIX_STRING */ grpc-1.3.2/src/core/lib/support/string_util_windows.c000066400000000000000000000063141310511640000227250ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* Posix code for gpr snprintf support. */ #include #ifdef GPR_WINDOWS /* Some platforms (namely msys) need wchar to be included BEFORE anything else, especially strsafe.h. */ #include #include #include #include #include #include #include #include "src/core/lib/support/string.h" #if defined UNICODE || defined _UNICODE LPTSTR gpr_char_to_tchar(LPCSTR input) { LPTSTR ret; int needed = MultiByteToWideChar(CP_UTF8, 0, input, -1, NULL, 0); if (needed <= 0) return NULL; ret = gpr_malloc((unsigned)needed * sizeof(TCHAR)); MultiByteToWideChar(CP_UTF8, 0, input, -1, ret, needed); return ret; } LPSTR gpr_tchar_to_char(LPCTSTR input) { LPSTR ret; int needed = WideCharToMultiByte(CP_UTF8, 0, input, -1, NULL, 0, NULL, NULL); if (needed <= 0) return NULL; ret = gpr_malloc((unsigned)needed); WideCharToMultiByte(CP_UTF8, 0, input, -1, ret, needed, NULL, NULL); return ret; } #else char *gpr_tchar_to_char(LPTSTR input) { return gpr_strdup(input); } char *gpr_char_to_tchar(LPTSTR input) { return gpr_strdup(input); } #endif char *gpr_format_message(int messageid) { LPTSTR tmessage; char *message; DWORD status = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD)messageid, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), (LPTSTR)(&tmessage), 0, NULL); if (status == 0) return gpr_strdup("Unable to retrieve error string"); message = gpr_tchar_to_char(tmessage); LocalFree(tmessage); return message; } #endif /* GPR_WINDOWS */ grpc-1.3.2/src/core/lib/support/string_windows.c000066400000000000000000000051211310511640000216630ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* Windows code for gpr snprintf support. */ #include #ifdef GPR_WINDOWS_STRING #include #include #include #include #include "src/core/lib/support/string.h" int gpr_asprintf(char **strp, const char *format, ...) { va_list args; int ret; size_t strp_buflen; /* Determine the length. */ va_start(args, format); ret = _vscprintf(format, args); va_end(args); if (ret < 0) { *strp = NULL; return -1; } /* Allocate a new buffer, with space for the NUL terminator. */ strp_buflen = (size_t)ret + 1; if ((*strp = gpr_malloc(strp_buflen)) == NULL) { /* This shouldn't happen, because gpr_malloc() calls abort(). */ return -1; } /* Print to the buffer. */ va_start(args, format); ret = vsnprintf_s(*strp, strp_buflen, _TRUNCATE, format, args); va_end(args); if ((size_t)ret == strp_buflen - 1) { return ret; } /* This should never happen. */ gpr_free(*strp); *strp = NULL; return -1; } #endif /* GPR_WINDOWS_STRING */ grpc-1.3.2/src/core/lib/support/string_windows.h000066400000000000000000000036551310511640000217020ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SUPPORT_STRING_WINDOWS_H #define GRPC_CORE_LIB_SUPPORT_STRING_WINDOWS_H #include #ifdef GPR_WINDOWS /* These allocate new strings using gpr_malloc to convert from and to utf-8. */ LPTSTR gpr_char_to_tchar(LPCSTR input); LPSTR gpr_tchar_to_char(LPCTSTR input); #endif /* GPR_WINDOWS */ #endif /* GRPC_CORE_LIB_SUPPORT_STRING_WINDOWS_H */ grpc-1.3.2/src/core/lib/support/subprocess_posix.c000066400000000000000000000063451310511640000222260ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifdef GPR_POSIX_SUBPROCESS #include #include #include #include #include #include #include #include #include #include #include #include #include struct gpr_subprocess { int pid; bool joined; }; const char *gpr_subprocess_binary_extension() { return ""; } gpr_subprocess *gpr_subprocess_create(int argc, const char **argv) { gpr_subprocess *r; int pid; char **exec_args; pid = fork(); if (pid == -1) { return NULL; } else if (pid == 0) { exec_args = gpr_malloc(((size_t)argc + 1) * sizeof(char *)); memcpy(exec_args, argv, (size_t)argc * sizeof(char *)); exec_args[argc] = NULL; execv(exec_args[0], exec_args); /* if we reach here, an error has occurred */ gpr_log(GPR_ERROR, "execv '%s' failed: %s", exec_args[0], strerror(errno)); _exit(1); return NULL; } else { r = gpr_zalloc(sizeof(gpr_subprocess)); r->pid = pid; return r; } } void gpr_subprocess_destroy(gpr_subprocess *p) { if (!p->joined) { kill(p->pid, SIGKILL); gpr_subprocess_join(p); } gpr_free(p); } int gpr_subprocess_join(gpr_subprocess *p) { int status; retry: if (waitpid(p->pid, &status, 0) == -1) { if (errno == EINTR) { goto retry; } gpr_log(GPR_ERROR, "waitpid failed for pid %d: %s", p->pid, strerror(errno)); return -1; } p->joined = true; return status; } void gpr_subprocess_interrupt(gpr_subprocess *p) { if (!p->joined) { kill(p->pid, SIGINT); } } #endif /* GPR_POSIX_SUBPROCESS */ grpc-1.3.2/src/core/lib/support/subprocess_windows.c000066400000000000000000000077071310511640000225610ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifdef GPR_WINDOWS_SUBPROCESS #include #include #include #include #include #include #include "src/core/lib/support/string.h" #include "src/core/lib/support/string_windows.h" struct gpr_subprocess { PROCESS_INFORMATION pi; int joined; int interrupted; }; const char *gpr_subprocess_binary_extension() { return ".exe"; } gpr_subprocess *gpr_subprocess_create(int argc, const char **argv) { gpr_subprocess *r; STARTUPINFO si; PROCESS_INFORMATION pi; char *args = gpr_strjoin_sep(argv, (size_t)argc, " ", NULL); TCHAR *args_tchar; args_tchar = gpr_char_to_tchar(args); gpr_free(args); memset(&si, 0, sizeof(si)); si.cb = sizeof(si); memset(&pi, 0, sizeof(pi)); if (!CreateProcess(NULL, args_tchar, NULL, NULL, FALSE, CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &pi)) { gpr_free(args_tchar); return NULL; } gpr_free(args_tchar); r = gpr_malloc(sizeof(gpr_subprocess)); memset(r, 0, sizeof(*r)); r->pi = pi; return r; } void gpr_subprocess_destroy(gpr_subprocess *p) { if (p) { if (!p->joined) { gpr_subprocess_interrupt(p); gpr_subprocess_join(p); } if (p->pi.hProcess) { CloseHandle(p->pi.hProcess); } if (p->pi.hThread) { CloseHandle(p->pi.hThread); } gpr_free(p); } } int gpr_subprocess_join(gpr_subprocess *p) { DWORD dwExitCode; if (GetExitCodeProcess(p->pi.hProcess, &dwExitCode)) { if (dwExitCode == STILL_ACTIVE) { if (WaitForSingleObject(p->pi.hProcess, INFINITE) == WAIT_OBJECT_0) { p->joined = 1; goto getExitCode; } return -1; // failed to join } else { goto getExitCode; } } else { return -1; // failed to get exit code } getExitCode: if (p->interrupted) { return 0; } if (GetExitCodeProcess(p->pi.hProcess, &dwExitCode)) { return (int)dwExitCode; } else { return -1; // failed to get exit code } } void gpr_subprocess_interrupt(gpr_subprocess *p) { DWORD dwExitCode; if (GetExitCodeProcess(p->pi.hProcess, &dwExitCode)) { if (dwExitCode == STILL_ACTIVE) { gpr_log(GPR_INFO, "sending ctrl-break"); GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, p->pi.dwProcessId); p->joined = 1; p->interrupted = 1; } } return; } #endif /* GPR_WINDOWS_SUBPROCESS */ grpc-1.3.2/src/core/lib/support/sync.c000066400000000000000000000104241310511640000175610ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* Generic implementation of synchronization primitives. */ #include #include #include #include /* Number of mutexes to allocate for events, to avoid lock contention. Should be a prime. */ enum { event_sync_partitions = 31 }; /* Events are partitioned by address to avoid lock contention. */ static struct sync_array_s { gpr_mu mu; gpr_cv cv; } sync_array[event_sync_partitions]; /* This routine is executed once on first use, via event_once */ static gpr_once event_once = GPR_ONCE_INIT; static void event_initialize(void) { int i; for (i = 0; i != event_sync_partitions; i++) { gpr_mu_init(&sync_array[i].mu); gpr_cv_init(&sync_array[i].cv); } } /* Hash ev into an element of sync_array[]. */ static struct sync_array_s *hash(gpr_event *ev) { return &sync_array[((uintptr_t)ev) % event_sync_partitions]; } void gpr_event_init(gpr_event *ev) { gpr_once_init(&event_once, &event_initialize); ev->state = 0; } void gpr_event_set(gpr_event *ev, void *value) { struct sync_array_s *s = hash(ev); gpr_mu_lock(&s->mu); GPR_ASSERT(gpr_atm_acq_load(&ev->state) == 0); gpr_atm_rel_store(&ev->state, (gpr_atm)value); gpr_cv_broadcast(&s->cv); gpr_mu_unlock(&s->mu); GPR_ASSERT(value != NULL); } void *gpr_event_get(gpr_event *ev) { return (void *)gpr_atm_acq_load(&ev->state); } void *gpr_event_wait(gpr_event *ev, gpr_timespec abs_deadline) { void *result = (void *)gpr_atm_acq_load(&ev->state); if (result == NULL) { struct sync_array_s *s = hash(ev); gpr_mu_lock(&s->mu); do { result = (void *)gpr_atm_acq_load(&ev->state); } while (result == NULL && !gpr_cv_wait(&s->cv, &s->mu, abs_deadline)); gpr_mu_unlock(&s->mu); } return result; } void gpr_ref_init(gpr_refcount *r, int n) { gpr_atm_rel_store(&r->count, n); } void gpr_ref(gpr_refcount *r) { gpr_atm_no_barrier_fetch_add(&r->count, 1); } void gpr_ref_non_zero(gpr_refcount *r) { #ifndef NDEBUG gpr_atm prior = gpr_atm_no_barrier_fetch_add(&r->count, 1); assert(prior > 0); #else gpr_ref(r); #endif } void gpr_refn(gpr_refcount *r, int n) { gpr_atm_no_barrier_fetch_add(&r->count, n); } int gpr_unref(gpr_refcount *r) { gpr_atm prior = gpr_atm_full_fetch_add(&r->count, -1); GPR_ASSERT(prior > 0); return prior == 1; } int gpr_ref_is_unique(gpr_refcount *r) { return gpr_atm_acq_load(&r->count) == 1; } void gpr_stats_init(gpr_stats_counter *c, intptr_t n) { gpr_atm_rel_store(&c->value, n); } void gpr_stats_inc(gpr_stats_counter *c, intptr_t inc) { gpr_atm_no_barrier_fetch_add(&c->value, inc); } intptr_t gpr_stats_read(const gpr_stats_counter *c) { /* don't need acquire-load, but we have no no-barrier load yet */ return gpr_atm_acq_load(&c->value); } grpc-1.3.2/src/core/lib/support/sync_posix.c000066400000000000000000000074301310511640000210060ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifdef GPR_POSIX_SYNC #include #include #include #include #include #include "src/core/lib/profiling/timers.h" #ifdef GPR_LOW_LEVEL_COUNTERS gpr_atm gpr_mu_locks = 0; gpr_atm gpr_counter_atm_cas = 0; gpr_atm gpr_counter_atm_add = 0; #endif void gpr_mu_init(gpr_mu* mu) { GPR_ASSERT(pthread_mutex_init(mu, NULL) == 0); } void gpr_mu_destroy(gpr_mu* mu) { GPR_ASSERT(pthread_mutex_destroy(mu) == 0); } void gpr_mu_lock(gpr_mu* mu) { #ifdef GPR_LOW_LEVEL_COUNTERS GPR_ATM_INC_COUNTER(gpr_mu_locks); #endif GPR_TIMER_BEGIN("gpr_mu_lock", 0); GPR_ASSERT(pthread_mutex_lock(mu) == 0); GPR_TIMER_END("gpr_mu_lock", 0); } void gpr_mu_unlock(gpr_mu* mu) { GPR_TIMER_BEGIN("gpr_mu_unlock", 0); GPR_ASSERT(pthread_mutex_unlock(mu) == 0); GPR_TIMER_END("gpr_mu_unlock", 0); } int gpr_mu_trylock(gpr_mu* mu) { int err; GPR_TIMER_BEGIN("gpr_mu_trylock", 0); err = pthread_mutex_trylock(mu); GPR_ASSERT(err == 0 || err == EBUSY); GPR_TIMER_END("gpr_mu_trylock", 0); return err == 0; } /*----------------------------------------*/ void gpr_cv_init(gpr_cv* cv) { GPR_ASSERT(pthread_cond_init(cv, NULL) == 0); } void gpr_cv_destroy(gpr_cv* cv) { GPR_ASSERT(pthread_cond_destroy(cv) == 0); } int gpr_cv_wait(gpr_cv* cv, gpr_mu* mu, gpr_timespec abs_deadline) { int err = 0; if (gpr_time_cmp(abs_deadline, gpr_inf_future(abs_deadline.clock_type)) == 0) { err = pthread_cond_wait(cv, mu); } else { struct timespec abs_deadline_ts; abs_deadline = gpr_convert_clock_type(abs_deadline, GPR_CLOCK_REALTIME); abs_deadline_ts.tv_sec = (time_t)abs_deadline.tv_sec; abs_deadline_ts.tv_nsec = abs_deadline.tv_nsec; err = pthread_cond_timedwait(cv, mu, &abs_deadline_ts); } GPR_ASSERT(err == 0 || err == ETIMEDOUT || err == EAGAIN); return err == ETIMEDOUT; } void gpr_cv_signal(gpr_cv* cv) { GPR_ASSERT(pthread_cond_signal(cv) == 0); } void gpr_cv_broadcast(gpr_cv* cv) { GPR_ASSERT(pthread_cond_broadcast(cv) == 0); } /*----------------------------------------*/ void gpr_once_init(gpr_once* once, void (*init_function)(void)) { GPR_ASSERT(pthread_once(once, init_function) == 0); } #endif /* GRP_POSIX_SYNC */ grpc-1.3.2/src/core/lib/support/sync_windows.c000066400000000000000000000103531310511640000213340ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* Win32 code for gpr synchronization support. */ #include #ifdef GPR_WINDOWS #include #include #include void gpr_mu_init(gpr_mu *mu) { InitializeCriticalSection(&mu->cs); mu->locked = 0; } void gpr_mu_destroy(gpr_mu *mu) { DeleteCriticalSection(&mu->cs); } void gpr_mu_lock(gpr_mu *mu) { EnterCriticalSection(&mu->cs); GPR_ASSERT(!mu->locked); mu->locked = 1; } void gpr_mu_unlock(gpr_mu *mu) { mu->locked = 0; LeaveCriticalSection(&mu->cs); } int gpr_mu_trylock(gpr_mu *mu) { int result = TryEnterCriticalSection(&mu->cs); if (result) { if (mu->locked) { /* This thread already holds the lock. */ LeaveCriticalSection(&mu->cs); /* Decrement lock count. */ result = 0; /* Indicate failure */ } mu->locked = 1; } return result; } /*----------------------------------------*/ void gpr_cv_init(gpr_cv *cv) { InitializeConditionVariable(cv); } void gpr_cv_destroy(gpr_cv *cv) { /* Condition variables don't need destruction in Win32. */ } int gpr_cv_wait(gpr_cv *cv, gpr_mu *mu, gpr_timespec abs_deadline) { int timeout = 0; DWORD timeout_max_ms; mu->locked = 0; if (gpr_time_cmp(abs_deadline, gpr_inf_future(abs_deadline.clock_type)) == 0) { SleepConditionVariableCS(cv, &mu->cs, INFINITE); } else { abs_deadline = gpr_convert_clock_type(abs_deadline, GPR_CLOCK_REALTIME); gpr_timespec now = gpr_now(abs_deadline.clock_type); int64_t now_ms = (int64_t)now.tv_sec * 1000 + now.tv_nsec / 1000000; int64_t deadline_ms = (int64_t)abs_deadline.tv_sec * 1000 + abs_deadline.tv_nsec / 1000000; if (now_ms >= deadline_ms) { timeout = 1; } else { if ((deadline_ms - now_ms) >= INFINITE) { timeout_max_ms = INFINITE - 1; } else { timeout_max_ms = (DWORD)(deadline_ms - now_ms); } timeout = (SleepConditionVariableCS(cv, &mu->cs, timeout_max_ms) == 0 && GetLastError() == ERROR_TIMEOUT); } } mu->locked = 1; return timeout; } void gpr_cv_signal(gpr_cv *cv) { WakeConditionVariable(cv); } void gpr_cv_broadcast(gpr_cv *cv) { WakeAllConditionVariable(cv); } /*----------------------------------------*/ static void *dummy; struct run_once_func_arg { void (*init_function)(void); }; static BOOL CALLBACK run_once_func(gpr_once *once, void *v, void **pv) { struct run_once_func_arg *arg = v; (*arg->init_function)(); return 1; } void gpr_once_init(gpr_once *once, void (*init_function)(void)) { struct run_once_func_arg arg; arg.init_function = init_function; InitOnceExecuteOnce(once, run_once_func, &arg, &dummy); } #endif /* GPR_WINDOWS */ grpc-1.3.2/src/core/lib/support/thd.c000066400000000000000000000044541310511640000173720ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* Posix implementation for gpr threads. */ #include #include enum { GPR_THD_JOINABLE = 1 }; gpr_thd_options gpr_thd_options_default(void) { gpr_thd_options options; memset(&options, 0, sizeof(options)); return options; } void gpr_thd_options_set_detached(gpr_thd_options* options) { options->flags &= ~GPR_THD_JOINABLE; } void gpr_thd_options_set_joinable(gpr_thd_options* options) { options->flags |= GPR_THD_JOINABLE; } int gpr_thd_options_is_detached(const gpr_thd_options* options) { if (!options) return 1; return (options->flags & GPR_THD_JOINABLE) == 0; } int gpr_thd_options_is_joinable(const gpr_thd_options* options) { if (!options) return 0; return (options->flags & GPR_THD_JOINABLE) == GPR_THD_JOINABLE; } grpc-1.3.2/src/core/lib/support/thd_internal.h000066400000000000000000000033731310511640000212720ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SUPPORT_THD_INTERNAL_H #define GRPC_CORE_LIB_SUPPORT_THD_INTERNAL_H /* Internal interfaces between modules within the gpr support library. */ #endif /* GRPC_CORE_LIB_SUPPORT_THD_INTERNAL_H */ grpc-1.3.2/src/core/lib/support/thd_posix.c000066400000000000000000000063631310511640000206150ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* Posix implementation for gpr threads. */ #include #ifdef GPR_POSIX_SYNC #include #include #include #include #include #include #include struct thd_arg { void (*body)(void *arg); /* body of a thread */ void *arg; /* argument to a thread */ }; /* Body of every thread started via gpr_thd_new. */ static void *thread_body(void *v) { struct thd_arg a = *(struct thd_arg *)v; free(v); (*a.body)(a.arg); return NULL; } int gpr_thd_new(gpr_thd_id *t, void (*thd_body)(void *arg), void *arg, const gpr_thd_options *options) { int thread_started; pthread_attr_t attr; pthread_t p; /* don't use gpr_malloc as we may cause an infinite recursion with * the profiling code */ struct thd_arg *a = malloc(sizeof(*a)); GPR_ASSERT(a != NULL); a->body = thd_body; a->arg = arg; GPR_ASSERT(pthread_attr_init(&attr) == 0); if (gpr_thd_options_is_detached(options)) { GPR_ASSERT(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0); } else { GPR_ASSERT(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE) == 0); } thread_started = (pthread_create(&p, &attr, &thread_body, a) == 0); GPR_ASSERT(pthread_attr_destroy(&attr) == 0); if (!thread_started) { /* don't use gpr_free, as this was allocated using malloc (see above) */ free(a); } *t = (gpr_thd_id)p; return thread_started; } gpr_thd_id gpr_thd_currentid(void) { return (gpr_thd_id)pthread_self(); } void gpr_thd_join(gpr_thd_id t) { pthread_join((pthread_t)t, NULL); } #endif /* GPR_POSIX_SYNC */ grpc-1.3.2/src/core/lib/support/thd_windows.c000066400000000000000000000072521310511640000211430ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* Windows implementation for gpr threads. */ #include #ifdef GPR_WINDOWS #include #include #include #include #if defined(_MSC_VER) #define thread_local __declspec(thread) #elif defined(__GNUC__) #define thread_local __thread #else #error "Unknown compiler - please file a bug report" #endif struct thd_info { void (*body)(void *arg); /* body of a thread */ void *arg; /* argument to a thread */ HANDLE join_event; /* if joinable, the join event */ int joinable; /* true if not detached */ }; static thread_local struct thd_info *g_thd_info; /* Destroys a thread info */ static void destroy_thread(struct thd_info *t) { if (t->joinable) CloseHandle(t->join_event); gpr_free(t); } /* Body of every thread started via gpr_thd_new. */ static DWORD WINAPI thread_body(void *v) { g_thd_info = (struct thd_info *)v; g_thd_info->body(g_thd_info->arg); if (g_thd_info->joinable) { BOOL ret = SetEvent(g_thd_info->join_event); GPR_ASSERT(ret); } else { destroy_thread(g_thd_info); } return 0; } int gpr_thd_new(gpr_thd_id *t, void (*thd_body)(void *arg), void *arg, const gpr_thd_options *options) { HANDLE handle; struct thd_info *info = gpr_malloc(sizeof(*info)); info->body = thd_body; info->arg = arg; *t = 0; if (gpr_thd_options_is_joinable(options)) { info->joinable = 1; info->join_event = CreateEvent(NULL, FALSE, FALSE, NULL); if (info->join_event == NULL) { gpr_free(info); return 0; } } else { info->joinable = 0; } handle = CreateThread(NULL, 64 * 1024, thread_body, info, 0, NULL); if (handle == NULL) { destroy_thread(info); } else { *t = (gpr_thd_id)info; CloseHandle(handle); } return handle != NULL; } gpr_thd_id gpr_thd_currentid(void) { return (gpr_thd_id)g_thd_info; } void gpr_thd_join(gpr_thd_id t) { struct thd_info *info = (struct thd_info *)t; DWORD ret = WaitForSingleObject(info->join_event, INFINITE); GPR_ASSERT(ret == WAIT_OBJECT_0); destroy_thread(info); } #endif /* GPR_WINDOWS */ grpc-1.3.2/src/core/lib/support/time.c000066400000000000000000000201261310511640000175430ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* Generic implementation of time calls. */ #include #include #include #include #include int gpr_time_cmp(gpr_timespec a, gpr_timespec b) { int cmp = (a.tv_sec > b.tv_sec) - (a.tv_sec < b.tv_sec); GPR_ASSERT(a.clock_type == b.clock_type); if (cmp == 0 && a.tv_sec != INT64_MAX && a.tv_sec != INT64_MIN) { cmp = (a.tv_nsec > b.tv_nsec) - (a.tv_nsec < b.tv_nsec); } return cmp; } gpr_timespec gpr_time_min(gpr_timespec a, gpr_timespec b) { return gpr_time_cmp(a, b) < 0 ? a : b; } gpr_timespec gpr_time_max(gpr_timespec a, gpr_timespec b) { return gpr_time_cmp(a, b) > 0 ? a : b; } gpr_timespec gpr_time_0(gpr_clock_type type) { gpr_timespec out; out.tv_sec = 0; out.tv_nsec = 0; out.clock_type = type; return out; } gpr_timespec gpr_inf_future(gpr_clock_type type) { gpr_timespec out; out.tv_sec = INT64_MAX; out.tv_nsec = 0; out.clock_type = type; return out; } gpr_timespec gpr_inf_past(gpr_clock_type type) { gpr_timespec out; out.tv_sec = INT64_MIN; out.tv_nsec = 0; out.clock_type = type; return out; } static gpr_timespec to_seconds_from_sub_second_time(int64_t time_in_units, int64_t units_per_sec, gpr_clock_type type) { gpr_timespec out; if (time_in_units == INT64_MAX) { out = gpr_inf_future(type); } else if (time_in_units == INT64_MIN) { out = gpr_inf_past(type); } else { if (time_in_units >= 0) { out.tv_sec = time_in_units / units_per_sec; } else { out.tv_sec = (-((units_per_sec - 1) - (time_in_units + units_per_sec)) / units_per_sec) - 1; } out.tv_nsec = (int32_t)((time_in_units - out.tv_sec * units_per_sec) * GPR_NS_PER_SEC / units_per_sec); out.clock_type = type; } return out; } static gpr_timespec to_seconds_from_above_second_time(int64_t time_in_units, int64_t secs_per_unit, gpr_clock_type type) { gpr_timespec out; if (time_in_units >= INT64_MAX / secs_per_unit) { out = gpr_inf_future(type); } else if (time_in_units <= INT64_MIN / secs_per_unit) { out = gpr_inf_past(type); } else { out.tv_sec = time_in_units * secs_per_unit; out.tv_nsec = 0; out.clock_type = type; } return out; } gpr_timespec gpr_time_from_nanos(int64_t ns, gpr_clock_type type) { return to_seconds_from_sub_second_time(ns, GPR_NS_PER_SEC, type); } gpr_timespec gpr_time_from_micros(int64_t us, gpr_clock_type type) { return to_seconds_from_sub_second_time(us, GPR_US_PER_SEC, type); } gpr_timespec gpr_time_from_millis(int64_t ms, gpr_clock_type type) { return to_seconds_from_sub_second_time(ms, GPR_MS_PER_SEC, type); } gpr_timespec gpr_time_from_seconds(int64_t s, gpr_clock_type type) { return to_seconds_from_sub_second_time(s, 1, type); } gpr_timespec gpr_time_from_minutes(int64_t m, gpr_clock_type type) { return to_seconds_from_above_second_time(m, 60, type); } gpr_timespec gpr_time_from_hours(int64_t h, gpr_clock_type type) { return to_seconds_from_above_second_time(h, 3600, type); } gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b) { gpr_timespec sum; int64_t inc = 0; GPR_ASSERT(b.clock_type == GPR_TIMESPAN); sum.clock_type = a.clock_type; sum.tv_nsec = a.tv_nsec + b.tv_nsec; if (sum.tv_nsec >= GPR_NS_PER_SEC) { sum.tv_nsec -= GPR_NS_PER_SEC; inc++; } if (a.tv_sec == INT64_MAX || a.tv_sec == INT64_MIN) { sum = a; } else if (b.tv_sec == INT64_MAX || (b.tv_sec >= 0 && a.tv_sec >= INT64_MAX - b.tv_sec)) { sum = gpr_inf_future(sum.clock_type); } else if (b.tv_sec == INT64_MIN || (b.tv_sec <= 0 && a.tv_sec <= INT64_MIN - b.tv_sec)) { sum = gpr_inf_past(sum.clock_type); } else { sum.tv_sec = a.tv_sec + b.tv_sec; if (inc != 0 && sum.tv_sec == INT64_MAX - 1) { sum = gpr_inf_future(sum.clock_type); } else { sum.tv_sec += inc; } } return sum; } gpr_timespec gpr_time_sub(gpr_timespec a, gpr_timespec b) { gpr_timespec diff; int64_t dec = 0; if (b.clock_type == GPR_TIMESPAN) { diff.clock_type = a.clock_type; } else { GPR_ASSERT(a.clock_type == b.clock_type); diff.clock_type = GPR_TIMESPAN; } diff.tv_nsec = a.tv_nsec - b.tv_nsec; if (diff.tv_nsec < 0) { diff.tv_nsec += GPR_NS_PER_SEC; dec++; } if (a.tv_sec == INT64_MAX || a.tv_sec == INT64_MIN) { diff = a; } else if (b.tv_sec == INT64_MIN || (b.tv_sec <= 0 && a.tv_sec >= INT64_MAX + b.tv_sec)) { diff = gpr_inf_future(GPR_CLOCK_REALTIME); } else if (b.tv_sec == INT64_MAX || (b.tv_sec >= 0 && a.tv_sec <= INT64_MIN + b.tv_sec)) { diff = gpr_inf_past(GPR_CLOCK_REALTIME); } else { diff.tv_sec = a.tv_sec - b.tv_sec; if (dec != 0 && diff.tv_sec == INT64_MIN + 1) { diff = gpr_inf_past(GPR_CLOCK_REALTIME); } else { diff.tv_sec -= dec; } } return diff; } int gpr_time_similar(gpr_timespec a, gpr_timespec b, gpr_timespec threshold) { int cmp_ab; GPR_ASSERT(a.clock_type == b.clock_type); GPR_ASSERT(threshold.clock_type == GPR_TIMESPAN); cmp_ab = gpr_time_cmp(a, b); if (cmp_ab == 0) return 1; if (cmp_ab < 0) { return gpr_time_cmp(gpr_time_sub(b, a), threshold) <= 0; } else { return gpr_time_cmp(gpr_time_sub(a, b), threshold) <= 0; } } int32_t gpr_time_to_millis(gpr_timespec t) { if (t.tv_sec >= 2147483) { if (t.tv_sec == 2147483 && t.tv_nsec < 648 * GPR_NS_PER_MS) { return 2147483 * GPR_MS_PER_SEC + t.tv_nsec / GPR_NS_PER_MS; } return 2147483647; } else if (t.tv_sec <= -2147483) { /* TODO(ctiller): correct handling here (it's so far in the past do we care?) */ return -2147483647; } else { return (int32_t)(t.tv_sec * GPR_MS_PER_SEC + t.tv_nsec / GPR_NS_PER_MS); } } double gpr_timespec_to_micros(gpr_timespec t) { return (double)t.tv_sec * GPR_US_PER_SEC + t.tv_nsec * 1e-3; } gpr_timespec gpr_convert_clock_type(gpr_timespec t, gpr_clock_type clock_type) { if (t.clock_type == clock_type) { return t; } if (t.tv_sec == INT64_MAX || t.tv_sec == INT64_MIN) { t.clock_type = clock_type; return t; } if (clock_type == GPR_TIMESPAN) { return gpr_time_sub(t, gpr_now(t.clock_type)); } if (t.clock_type == GPR_TIMESPAN) { return gpr_time_add(gpr_now(clock_type), t); } return gpr_time_add(gpr_now(clock_type), gpr_time_sub(t, gpr_now(t.clock_type))); } grpc-1.3.2/src/core/lib/support/time_posix.c000066400000000000000000000125151310511640000207700ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "src/core/lib/support/time_precise.h" #ifdef GPR_POSIX_TIME #include #include #include #ifdef __linux__ #include #endif #include #include #include "src/core/lib/support/block_annotate.h" static struct timespec timespec_from_gpr(gpr_timespec gts) { struct timespec rv; if (sizeof(time_t) < sizeof(int64_t)) { /* fine to assert, as this is only used in gpr_sleep_until */ GPR_ASSERT(gts.tv_sec <= INT32_MAX && gts.tv_sec >= INT32_MIN); } rv.tv_sec = (time_t)gts.tv_sec; rv.tv_nsec = gts.tv_nsec; return rv; } #if _POSIX_TIMERS > 0 static gpr_timespec gpr_from_timespec(struct timespec ts, gpr_clock_type clock_type) { /* * timespec.tv_sec can have smaller size than gpr_timespec.tv_sec, * but we are only using this function to implement gpr_now * so there's no need to handle "infinity" values. */ gpr_timespec rv; rv.tv_sec = ts.tv_sec; rv.tv_nsec = (int32_t)ts.tv_nsec; rv.clock_type = clock_type; return rv; } /** maps gpr_clock_type --> clockid_t for clock_gettime */ static const clockid_t clockid_for_gpr_clock[] = {CLOCK_MONOTONIC, CLOCK_REALTIME}; void gpr_time_init(void) { gpr_precise_clock_init(); } static gpr_timespec now_impl(gpr_clock_type clock_type) { struct timespec now; GPR_ASSERT(clock_type != GPR_TIMESPAN); if (clock_type == GPR_CLOCK_PRECISE) { gpr_timespec ret; gpr_precise_clock_now(&ret); return ret; } else { #if defined(GPR_BACKWARDS_COMPATIBILITY_MODE) && defined(__linux__) /* avoid ABI problems by invoking syscalls directly */ syscall(SYS_clock_gettime, clockid_for_gpr_clock[clock_type], &now); #else clock_gettime(clockid_for_gpr_clock[clock_type], &now); #endif return gpr_from_timespec(now, clock_type); } } #else /* For some reason Apple's OSes haven't implemented clock_gettime. */ #include #include #include static double g_time_scale; static uint64_t g_time_start; void gpr_time_init(void) { mach_timebase_info_data_t tb = {0, 1}; gpr_precise_clock_init(); mach_timebase_info(&tb); g_time_scale = tb.numer; g_time_scale /= tb.denom; g_time_start = mach_absolute_time(); } static gpr_timespec now_impl(gpr_clock_type clock) { gpr_timespec now; struct timeval now_tv; double now_dbl; now.clock_type = clock; switch (clock) { case GPR_CLOCK_REALTIME: gettimeofday(&now_tv, NULL); now.tv_sec = now_tv.tv_sec; now.tv_nsec = now_tv.tv_usec * 1000; break; case GPR_CLOCK_MONOTONIC: now_dbl = ((double)(mach_absolute_time() - g_time_start)) * g_time_scale; now.tv_sec = (int64_t)(now_dbl * 1e-9); now.tv_nsec = (int32_t)(now_dbl - ((double)now.tv_sec) * 1e9); break; case GPR_CLOCK_PRECISE: gpr_precise_clock_now(&now); break; case GPR_TIMESPAN: abort(); } return now; } #endif gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type) = now_impl; gpr_timespec gpr_now(gpr_clock_type clock_type) { return gpr_now_impl(clock_type); } void gpr_sleep_until(gpr_timespec until) { gpr_timespec now; gpr_timespec delta; struct timespec delta_ts; int ns_result; for (;;) { /* We could simplify by using clock_nanosleep instead, but it might be * slightly less portable. */ now = gpr_now(until.clock_type); if (gpr_time_cmp(until, now) <= 0) { return; } delta = gpr_time_sub(until, now); delta_ts = timespec_from_gpr(delta); GRPC_SCHEDULING_START_BLOCKING_REGION; ns_result = nanosleep(&delta_ts, NULL); GRPC_SCHEDULING_END_BLOCKING_REGION; if (ns_result == 0) { break; } } } #endif /* GPR_POSIX_TIME */ grpc-1.3.2/src/core/lib/support/time_precise.c000066400000000000000000000062051310511640000212570ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #ifdef GRPC_TIMERS_RDTSC #if defined(__i386__) static void gpr_get_cycle_counter(long long int *clk) { long long int ret; __asm__ volatile("rdtsc" : "=A"(ret)); *clk = ret; } // ---------------------------------------------------------------- #elif defined(__x86_64__) || defined(__amd64__) static void gpr_get_cycle_counter(long long int *clk) { unsigned long long low, high; __asm__ volatile("rdtsc" : "=a"(low), "=d"(high)); *clk = (long long)(high << 32) | (long long)low; } #endif static double cycles_per_second = 0; static long long int start_cycle; void gpr_precise_clock_init(void) { time_t start; long long end_cycle; gpr_log(GPR_DEBUG, "Calibrating timers"); start = time(NULL); while (time(NULL) == start) ; gpr_get_cycle_counter(&start_cycle); while (time(NULL) <= start + 10) ; gpr_get_cycle_counter(&end_cycle); cycles_per_second = (double)(end_cycle - start_cycle) / 10.0; gpr_log(GPR_DEBUG, "... cycles_per_second = %f\n", cycles_per_second); } void gpr_precise_clock_now(gpr_timespec *clk) { long long int counter; double secs; gpr_get_cycle_counter(&counter); secs = (double)(counter - start_cycle) / cycles_per_second; clk->clock_type = GPR_CLOCK_PRECISE; clk->tv_sec = (int64_t)secs; clk->tv_nsec = (int32_t)(1e9 * (secs - (double)clk->tv_sec)); } #else /* GRPC_TIMERS_RDTSC */ void gpr_precise_clock_init(void) {} void gpr_precise_clock_now(gpr_timespec *clk) { *clk = gpr_now(GPR_CLOCK_REALTIME); clk->clock_type = GPR_CLOCK_PRECISE; } #endif /* GRPC_TIMERS_RDTSC */ grpc-1.3.2/src/core/lib/support/time_precise.h000066400000000000000000000034421310511640000212640ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SUPPORT_TIME_PRECISE_H #define GRPC_CORE_LIB_SUPPORT_TIME_PRECISE_H #include void gpr_precise_clock_init(void); void gpr_precise_clock_now(gpr_timespec *clk); #endif /* GRPC_CORE_LIB_SUPPORT_TIME_PRECISE_H */ grpc-1.3.2/src/core/lib/support/time_windows.c000066400000000000000000000072651310511640000213260ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* Win32 code for gpr time support. */ #include #ifdef GPR_WINDOWS_TIME #include #include #include #include #include #include "src/core/lib/support/block_annotate.h" #include "src/core/lib/support/time_precise.h" static LARGE_INTEGER g_start_time; static double g_time_scale; void gpr_time_init(void) { LARGE_INTEGER frequency; QueryPerformanceFrequency(&frequency); QueryPerformanceCounter(&g_start_time); g_time_scale = 1.0 / (double)frequency.QuadPart; } static gpr_timespec now_impl(gpr_clock_type clock) { gpr_timespec now_tv; LONGLONG diff; struct _timeb now_tb; LARGE_INTEGER timestamp; double now_dbl; now_tv.clock_type = clock; switch (clock) { case GPR_CLOCK_REALTIME: _ftime_s(&now_tb); now_tv.tv_sec = (int64_t)now_tb.time; now_tv.tv_nsec = now_tb.millitm * 1000000; break; case GPR_CLOCK_MONOTONIC: case GPR_CLOCK_PRECISE: QueryPerformanceCounter(×tamp); diff = timestamp.QuadPart - g_start_time.QuadPart; now_dbl = (double)diff * g_time_scale; now_tv.tv_sec = (int64_t)now_dbl; now_tv.tv_nsec = (int32_t)((now_dbl - (double)now_tv.tv_sec) * 1e9); break; case GPR_TIMESPAN: abort(); break; } return now_tv; } gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type) = now_impl; gpr_timespec gpr_now(gpr_clock_type clock_type) { return gpr_now_impl(clock_type); } void gpr_sleep_until(gpr_timespec until) { gpr_timespec now; gpr_timespec delta; int64_t sleep_millis; for (;;) { /* We could simplify by using clock_nanosleep instead, but it might be * slightly less portable. */ now = gpr_now(until.clock_type); if (gpr_time_cmp(until, now) <= 0) { return; } delta = gpr_time_sub(until, now); sleep_millis = delta.tv_sec * GPR_MS_PER_SEC + delta.tv_nsec / GPR_NS_PER_MS; GPR_ASSERT((sleep_millis >= 0) && (sleep_millis <= INT_MAX)); GRPC_SCHEDULING_START_BLOCKING_REGION; Sleep((DWORD)sleep_millis); GRPC_SCHEDULING_END_BLOCKING_REGION; } } #endif /* GPR_WINDOWS_TIME */ grpc-1.3.2/src/core/lib/support/tls_pthread.c000066400000000000000000000035001310511640000211130ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifdef GPR_PTHREAD_TLS #include intptr_t gpr_tls_set(struct gpr_pthread_thread_local *tls, intptr_t value) { GPR_ASSERT(0 == pthread_setspecific(tls->key, (void *)value)); return value; } #endif /* GPR_PTHREAD_TLS */ grpc-1.3.2/src/core/lib/support/tmpfile.h000066400000000000000000000040701310511640000202520ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SUPPORT_TMPFILE_H #define GRPC_CORE_LIB_SUPPORT_TMPFILE_H #include #ifdef __cplusplus extern "C" { #endif /* Creates a temporary file from a prefix. If tmp_filename is not NULL, *tmp_filename is assigned the name of the created file and it is the responsibility of the caller to gpr_free it unless an error occurs in which case it will be set to NULL. */ FILE *gpr_tmpfile(const char *prefix, char **tmp_filename); #ifdef __cplusplus } #endif #endif /* GRPC_CORE_LIB_SUPPORT_TMPFILE_H */ grpc-1.3.2/src/core/lib/support/tmpfile_msys.c000066400000000000000000000050031310511640000213150ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifdef GPR_MSYS_TMPFILE #include #include #include #include #include #include #include #include "src/core/lib/support/string_windows.h" #include "src/core/lib/support/tmpfile.h" FILE *gpr_tmpfile(const char *prefix, char **tmp_filename_out) { FILE *result = NULL; char tmp_filename[MAX_PATH]; UINT success; if (tmp_filename_out != NULL) *tmp_filename_out = NULL; /* Generate a unique filename with our template + temporary path. */ success = GetTempFileNameA(".", prefix, 0, tmp_filename); fprintf(stderr, "success = %d\n", success); if (success) { /* Open a file there. */ result = fopen(tmp_filename, "wb+"); fprintf(stderr, "result = %p\n", result); } if (result != NULL && tmp_filename_out) { *tmp_filename_out = gpr_strdup(tmp_filename); } return result; } #endif /* GPR_MSYS_TMPFILE */ grpc-1.3.2/src/core/lib/support/tmpfile_posix.c000066400000000000000000000052471310511640000214760ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifdef GPR_POSIX_TMPFILE #include "src/core/lib/support/tmpfile.h" #include #include #include #include #include #include #include #include "src/core/lib/support/string.h" FILE *gpr_tmpfile(const char *prefix, char **tmp_filename) { FILE *result = NULL; char *template; int fd; if (tmp_filename != NULL) *tmp_filename = NULL; gpr_asprintf(&template, "/tmp/%s_XXXXXX", prefix); GPR_ASSERT(template != NULL); fd = mkstemp(template); if (fd == -1) { gpr_log(GPR_ERROR, "mkstemp failed for template %s with error %s.", template, strerror(errno)); goto end; } result = fdopen(fd, "w+"); if (result == NULL) { gpr_log(GPR_ERROR, "Could not open file %s from fd %d (error = %s).", template, fd, strerror(errno)); unlink(template); close(fd); goto end; } end: if (result != NULL && tmp_filename != NULL) { *tmp_filename = template; } else { gpr_free(template); } return result; } #endif /* GPR_POSIX_TMPFILE */ grpc-1.3.2/src/core/lib/support/tmpfile_windows.c000066400000000000000000000055301310511640000220210ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #ifdef GPR_WINDOWS_TMPFILE #include #include #include #include #include #include #include #include "src/core/lib/support/string_windows.h" #include "src/core/lib/support/tmpfile.h" FILE *gpr_tmpfile(const char *prefix, char **tmp_filename_out) { FILE *result = NULL; LPTSTR template_string = NULL; TCHAR tmp_path[MAX_PATH]; TCHAR tmp_filename[MAX_PATH]; DWORD status; UINT success; if (tmp_filename_out != NULL) *tmp_filename_out = NULL; /* Convert our prefix to TCHAR. */ template_string = gpr_char_to_tchar(prefix); GPR_ASSERT(template_string); /* Get the path to the best temporary folder available. */ status = GetTempPath(MAX_PATH, tmp_path); if (status == 0 || status > MAX_PATH) goto end; /* Generate a unique filename with our template + temporary path. */ success = GetTempFileName(tmp_path, template_string, 0, tmp_filename); if (!success) goto end; /* Open a file there. */ if (_tfopen_s(&result, tmp_filename, TEXT("wb+")) != 0) goto end; end: if (result && tmp_filename_out) { *tmp_filename_out = gpr_tchar_to_char(tmp_filename); } gpr_free(template_string); return result; } #endif /* GPR_WINDOWS_TMPFILE */ grpc-1.3.2/src/core/lib/support/wrap_memcpy.c000066400000000000000000000042231310511640000211300ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include /* Provide a wrapped memcpy for targets that need to be backwards * compatible with older libc's. * * Enable by setting LDFLAGS=-Wl,-wrap,memcpy when linking. */ #ifdef __linux__ #if defined(__x86_64__) && !defined(GPR_MUSL_LIBC_COMPAT) __asm__(".symver memcpy,memcpy@GLIBC_2.2.5"); void *__wrap_memcpy(void *destination, const void *source, size_t num) { return memcpy(destination, source, num); } #else /* !__x86_64__ */ void *__wrap_memcpy(void *destination, const void *source, size_t num) { return memmove(destination, source, num); } #endif #endif grpc-1.3.2/src/core/lib/surface/000077500000000000000000000000001310511640000163545ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/surface/README.md000066400000000000000000000001701310511640000176310ustar00rootroot00000000000000# Surface Surface provides the bulk of the gRPC Core public API, and translates it into calls against core components. grpc-1.3.2/src/core/lib/surface/alarm.c000066400000000000000000000063671310511640000176300ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/surface/completion_queue.h" struct grpc_alarm { grpc_timer alarm; grpc_closure on_alarm; grpc_cq_completion completion; /** completion queue where events about this alarm will be posted */ grpc_completion_queue *cq; /** user supplied tag */ void *tag; }; static void do_nothing_end_completion(grpc_exec_ctx *exec_ctx, void *arg, grpc_cq_completion *c) {} static void alarm_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_alarm *alarm = arg; grpc_cq_end_op(exec_ctx, alarm->cq, alarm->tag, error, do_nothing_end_completion, NULL, &alarm->completion); } grpc_alarm *grpc_alarm_create(grpc_completion_queue *cq, gpr_timespec deadline, void *tag) { grpc_alarm *alarm = gpr_malloc(sizeof(grpc_alarm)); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_CQ_INTERNAL_REF(cq, "alarm"); alarm->cq = cq; alarm->tag = tag; grpc_cq_begin_op(cq, tag); grpc_closure_init(&alarm->on_alarm, alarm_cb, alarm, grpc_schedule_on_exec_ctx); grpc_timer_init(&exec_ctx, &alarm->alarm, gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC), &alarm->on_alarm, gpr_now(GPR_CLOCK_MONOTONIC)); grpc_exec_ctx_finish(&exec_ctx); return alarm; } void grpc_alarm_cancel(grpc_alarm *alarm) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_timer_cancel(&exec_ctx, &alarm->alarm); grpc_exec_ctx_finish(&exec_ctx); } void grpc_alarm_destroy(grpc_alarm *alarm) { grpc_alarm_cancel(alarm); GRPC_CQ_INTERNAL_UNREF(alarm->cq, "alarm"); gpr_free(alarm); } grpc-1.3.2/src/core/lib/surface/api_trace.c000066400000000000000000000031471310511640000204540ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/surface/api_trace.h" int grpc_api_trace = 0; grpc-1.3.2/src/core/lib/surface/api_trace.h000066400000000000000000000055351310511640000204640ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SURFACE_API_TRACE_H #define GRPC_CORE_LIB_SURFACE_API_TRACE_H #include #include "src/core/lib/debug/trace.h" extern int grpc_api_trace; /* Provide unwrapping macros because we're in C89 and variadic macros weren't introduced until C99... */ #define GRPC_API_TRACE_UNWRAP0() #define GRPC_API_TRACE_UNWRAP1(a) , a #define GRPC_API_TRACE_UNWRAP2(a, b) , a, b #define GRPC_API_TRACE_UNWRAP3(a, b, c) , a, b, c #define GRPC_API_TRACE_UNWRAP4(a, b, c, d) , a, b, c, d #define GRPC_API_TRACE_UNWRAP5(a, b, c, d, e) , a, b, c, d, e #define GRPC_API_TRACE_UNWRAP6(a, b, c, d, e, f) , a, b, c, d, e, f #define GRPC_API_TRACE_UNWRAP7(a, b, c, d, e, f, g) , a, b, c, d, e, f, g #define GRPC_API_TRACE_UNWRAP8(a, b, c, d, e, f, g, h) , a, b, c, d, e, f, g, h #define GRPC_API_TRACE_UNWRAP9(a, b, c, d, e, f, g, h, i) \ , a, b, c, d, e, f, g, h, i #define GRPC_API_TRACE_UNWRAP10(a, b, c, d, e, f, g, h, i, j) \ , a, b, c, d, e, f, g, h, i, j /* Due to the limitations of C89's preprocessor, the arity of the var-arg list 'nargs' must be specified. */ #define GRPC_API_TRACE(fmt, nargs, args) \ if (grpc_api_trace) { \ gpr_log(GPR_INFO, fmt GRPC_API_TRACE_UNWRAP##nargs args); \ } #endif /* GRPC_CORE_LIB_SURFACE_API_TRACE_H */ grpc-1.3.2/src/core/lib/surface/byte_buffer.c000066400000000000000000000072371310511640000210250ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include "src/core/lib/slice/slice_internal.h" grpc_byte_buffer *grpc_raw_byte_buffer_create(grpc_slice *slices, size_t nslices) { return grpc_raw_compressed_byte_buffer_create(slices, nslices, GRPC_COMPRESS_NONE); } grpc_byte_buffer *grpc_raw_compressed_byte_buffer_create( grpc_slice *slices, size_t nslices, grpc_compression_algorithm compression) { size_t i; grpc_byte_buffer *bb = gpr_malloc(sizeof(grpc_byte_buffer)); bb->type = GRPC_BB_RAW; bb->data.raw.compression = compression; grpc_slice_buffer_init(&bb->data.raw.slice_buffer); for (i = 0; i < nslices; i++) { grpc_slice_ref_internal(slices[i]); grpc_slice_buffer_add(&bb->data.raw.slice_buffer, slices[i]); } return bb; } grpc_byte_buffer *grpc_raw_byte_buffer_from_reader( grpc_byte_buffer_reader *reader) { grpc_byte_buffer *bb = gpr_malloc(sizeof(grpc_byte_buffer)); grpc_slice slice; bb->type = GRPC_BB_RAW; bb->data.raw.compression = GRPC_COMPRESS_NONE; grpc_slice_buffer_init(&bb->data.raw.slice_buffer); while (grpc_byte_buffer_reader_next(reader, &slice)) { grpc_slice_buffer_add(&bb->data.raw.slice_buffer, slice); } return bb; } grpc_byte_buffer *grpc_byte_buffer_copy(grpc_byte_buffer *bb) { switch (bb->type) { case GRPC_BB_RAW: return grpc_raw_compressed_byte_buffer_create( bb->data.raw.slice_buffer.slices, bb->data.raw.slice_buffer.count, bb->data.raw.compression); } GPR_UNREACHABLE_CODE(return NULL); } void grpc_byte_buffer_destroy(grpc_byte_buffer *bb) { if (!bb) return; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; switch (bb->type) { case GRPC_BB_RAW: grpc_slice_buffer_destroy_internal(&exec_ctx, &bb->data.raw.slice_buffer); break; } gpr_free(bb); grpc_exec_ctx_finish(&exec_ctx); } size_t grpc_byte_buffer_length(grpc_byte_buffer *bb) { switch (bb->type) { case GRPC_BB_RAW: return bb->data.raw.slice_buffer.length; } GPR_UNREACHABLE_CODE(return 0); } grpc-1.3.2/src/core/lib/surface/byte_buffer_reader.c000066400000000000000000000123251310511640000223410ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include "src/core/lib/compression/message_compress.h" #include "src/core/lib/slice/slice_internal.h" static int is_compressed(grpc_byte_buffer *buffer) { switch (buffer->type) { case GRPC_BB_RAW: if (buffer->data.raw.compression == GRPC_COMPRESS_NONE) { return 0 /* GPR_FALSE */; } break; } return 1 /* GPR_TRUE */; } int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader, grpc_byte_buffer *buffer) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_slice_buffer decompressed_slices_buffer; reader->buffer_in = buffer; switch (reader->buffer_in->type) { case GRPC_BB_RAW: grpc_slice_buffer_init(&decompressed_slices_buffer); if (is_compressed(reader->buffer_in)) { if (grpc_msg_decompress(&exec_ctx, reader->buffer_in->data.raw.compression, &reader->buffer_in->data.raw.slice_buffer, &decompressed_slices_buffer) == 0) { gpr_log(GPR_ERROR, "Unexpected error decompressing data for algorithm with enum " "value '%d'.", reader->buffer_in->data.raw.compression); memset(reader, 0, sizeof(*reader)); return 0; } else { /* all fine */ reader->buffer_out = grpc_raw_byte_buffer_create(decompressed_slices_buffer.slices, decompressed_slices_buffer.count); } grpc_slice_buffer_destroy_internal(&exec_ctx, &decompressed_slices_buffer); } else { /* not compressed, use the input buffer as output */ reader->buffer_out = reader->buffer_in; } reader->current.index = 0; break; } grpc_exec_ctx_finish(&exec_ctx); return 1; } void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader) { switch (reader->buffer_in->type) { case GRPC_BB_RAW: /* keeping the same if-else structure as in the init function */ if (is_compressed(reader->buffer_in)) { grpc_byte_buffer_destroy(reader->buffer_out); } break; } } int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader *reader, grpc_slice *slice) { switch (reader->buffer_in->type) { case GRPC_BB_RAW: { grpc_slice_buffer *slice_buffer; slice_buffer = &reader->buffer_out->data.raw.slice_buffer; if (reader->current.index < slice_buffer->count) { *slice = grpc_slice_ref_internal( slice_buffer->slices[reader->current.index]); reader->current.index += 1; return 1; } break; } } return 0; } grpc_slice grpc_byte_buffer_reader_readall(grpc_byte_buffer_reader *reader) { grpc_slice in_slice; size_t bytes_read = 0; const size_t input_size = grpc_byte_buffer_length(reader->buffer_out); grpc_slice out_slice = grpc_slice_malloc(input_size); uint8_t *const outbuf = GRPC_SLICE_START_PTR(out_slice); /* just an alias */ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; while (grpc_byte_buffer_reader_next(reader, &in_slice) != 0) { const size_t slice_length = GRPC_SLICE_LENGTH(in_slice); memcpy(&(outbuf[bytes_read]), GRPC_SLICE_START_PTR(in_slice), slice_length); bytes_read += slice_length; grpc_slice_unref_internal(&exec_ctx, in_slice); GPR_ASSERT(bytes_read <= input_size); } grpc_exec_ctx_finish(&exec_ctx); return out_slice; } grpc-1.3.2/src/core/lib/surface/call.c000066400000000000000000002100511310511640000174320ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/compression/algorithm_metadata.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/arena.h" #include "src/core/lib/support/string.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/call.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/completion_queue.h" #include "src/core/lib/surface/validate_metadata.h" #include "src/core/lib/transport/error_utils.h" #include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/transport.h" /** The maximum number of concurrent batches possible. Based upon the maximum number of individually queueable ops in the batch api: - initial metadata send - message send - status/close send (depending on client/server) - initial metadata recv - message recv - status/close recv (depending on client/server) */ #define MAX_CONCURRENT_BATCHES 6 #define MAX_SEND_EXTRA_METADATA_COUNT 3 /* Status data for a request can come from several sources; this enumerates them all, and acts as a priority sorting for which status to return to the application - earlier entries override later ones */ typedef enum { /* Status came from the application layer overriding whatever the wire says */ STATUS_FROM_API_OVERRIDE = 0, /* Status came from 'the wire' - or somewhere below the surface layer */ STATUS_FROM_WIRE, /* Status was created by some internal channel stack operation: must come via add_batch_error */ STATUS_FROM_CORE, /* Status was created by some surface error */ STATUS_FROM_SURFACE, /* Status came from the server sending status */ STATUS_FROM_SERVER_STATUS, STATUS_SOURCE_COUNT } status_source; typedef struct { bool is_set; grpc_error *error; } received_status; static gpr_atm pack_received_status(received_status r) { return r.is_set ? (1 | (gpr_atm)r.error) : 0; } static received_status unpack_received_status(gpr_atm atm) { return (atm & 1) == 0 ? (received_status){.is_set = false, .error = GRPC_ERROR_NONE} : (received_status){.is_set = true, .error = (grpc_error *)(atm & ~(gpr_atm)1)}; } #define MAX_ERRORS_PER_BATCH 4 typedef struct batch_control { grpc_call *call; /* Share memory for cq_completion and notify_tag as they are never needed simultaneously. Each byte used in this data structure count as six bytes per call, so any savings we can make are worthwhile, We use notify_tag to determine whether or not to send notification to the completion queue. Once we've made that determination, we can reuse the memory for cq_completion. */ union { grpc_cq_completion cq_completion; struct { /* Any given op indicates completion by either (a) calling a closure or (b) sending a notification on the call's completion queue. If \a is_closure is true, \a tag indicates a closure to be invoked; otherwise, \a tag indicates the tag to be used in the notification to be sent to the completion queue. */ void *tag; bool is_closure; } notify_tag; } completion_data; grpc_closure finish_batch; gpr_refcount steps_to_complete; grpc_error *errors[MAX_ERRORS_PER_BATCH]; gpr_atm num_errors; grpc_transport_stream_op_batch op; } batch_control; typedef struct { gpr_mu child_list_mu; grpc_call *first_child; } parent_call; typedef struct { grpc_call *parent; /** siblings: children of the same parent form a list, and this list is protected under parent->mu */ grpc_call *sibling_next; grpc_call *sibling_prev; } child_call; struct grpc_call { gpr_arena *arena; grpc_completion_queue *cq; grpc_polling_entity pollent; grpc_channel *channel; gpr_timespec start_time; /* parent_call* */ gpr_atm parent_call_atm; child_call *child_call; /* client or server call */ bool is_client; /** has grpc_call_destroy been called */ bool destroy_called; /** flag indicating that cancellation is inherited */ bool cancellation_is_inherited; /** which ops are in-flight */ bool sent_initial_metadata; bool sending_message; bool sent_final_op; bool received_initial_metadata; bool receiving_message; bool requested_final_op; gpr_atm any_ops_sent_atm; gpr_atm received_final_op_atm; /* have we received initial metadata */ bool has_initial_md_been_received; batch_control *active_batches[MAX_CONCURRENT_BATCHES]; grpc_transport_stream_op_batch_payload stream_op_payload; /* first idx: is_receiving, second idx: is_trailing */ grpc_metadata_batch metadata_batch[2][2]; /* Buffered read metadata waiting to be returned to the application. Element 0 is initial metadata, element 1 is trailing metadata. */ grpc_metadata_array *buffered_metadata[2]; /* Packed received call statuses from various sources */ gpr_atm status[STATUS_SOURCE_COUNT]; /* Call data useful used for reporting. Only valid after the call has * completed */ grpc_call_final_info final_info; /* Compression algorithm for *incoming* data */ grpc_compression_algorithm incoming_compression_algorithm; /* Supported encodings (compression algorithms), a bitset */ uint32_t encodings_accepted_by_peer; /* Contexts for various subsystems (security, tracing, ...). */ grpc_call_context_element context[GRPC_CONTEXT_COUNT]; /* for the client, extra metadata is initial metadata; for the server, it's trailing metadata */ grpc_linked_mdelem send_extra_metadata[MAX_SEND_EXTRA_METADATA_COUNT]; int send_extra_metadata_count; gpr_timespec send_deadline; grpc_slice_buffer_stream sending_stream; grpc_byte_stream *receiving_stream; grpc_byte_buffer **receiving_buffer; grpc_slice receiving_slice; grpc_closure receiving_slice_ready; grpc_closure receiving_stream_ready; grpc_closure receiving_initial_metadata_ready; uint32_t test_only_last_message_flags; grpc_closure release_call; union { struct { grpc_status_code *status; grpc_slice *status_details; } client; struct { int *cancelled; } server; } final_op; void *saved_receiving_stream_ready_bctlp; }; int grpc_call_error_trace = 0; #define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1)) #define CALL_FROM_CALL_STACK(call_stack) (((grpc_call *)(call_stack)) - 1) #define CALL_ELEM_FROM_CALL(call, idx) \ grpc_call_stack_element(CALL_STACK_FROM_CALL(call), idx) #define CALL_FROM_TOP_ELEM(top_elem) \ CALL_FROM_CALL_STACK(grpc_call_stack_from_top_element(top_elem)) static void execute_op(grpc_exec_ctx *exec_ctx, grpc_call *call, grpc_transport_stream_op_batch *op); static void cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c, status_source source, grpc_status_code status, const char *description); static void cancel_with_error(grpc_exec_ctx *exec_ctx, grpc_call *c, status_source source, grpc_error *error); static void destroy_call(grpc_exec_ctx *exec_ctx, void *call_stack, grpc_error *error); static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp, grpc_error *error); static void get_final_status(grpc_call *call, void (*set_value)(grpc_status_code code, void *user_data), void *set_value_user_data, grpc_slice *details); static void set_status_value_directly(grpc_status_code status, void *dest); static void set_status_from_error(grpc_exec_ctx *exec_ctx, grpc_call *call, status_source source, grpc_error *error); static void process_data_after_md(grpc_exec_ctx *exec_ctx, batch_control *bctl); static void post_batch_completion(grpc_exec_ctx *exec_ctx, batch_control *bctl); static void add_batch_error(grpc_exec_ctx *exec_ctx, batch_control *bctl, grpc_error *error, bool has_cancelled); static void add_init_error(grpc_error **composite, grpc_error *new) { if (new == GRPC_ERROR_NONE) return; if (*composite == GRPC_ERROR_NONE) *composite = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Call creation failed"); *composite = grpc_error_add_child(*composite, new); } static parent_call *get_or_create_parent_call(grpc_call *call) { parent_call *p = (parent_call *)gpr_atm_acq_load(&call->parent_call_atm); if (p == NULL) { p = gpr_arena_alloc(call->arena, sizeof(*p)); gpr_mu_init(&p->child_list_mu); if (!gpr_atm_rel_cas(&call->parent_call_atm, (gpr_atm)NULL, (gpr_atm)p)) { gpr_mu_destroy(&p->child_list_mu); p = (parent_call *)gpr_atm_acq_load(&call->parent_call_atm); } } return p; } static parent_call *get_parent_call(grpc_call *call) { return (parent_call *)gpr_atm_acq_load(&call->parent_call_atm); } grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx, const grpc_call_create_args *args, grpc_call **out_call) { size_t i, j; grpc_error *error = GRPC_ERROR_NONE; grpc_channel_stack *channel_stack = grpc_channel_get_channel_stack(args->channel); grpc_call *call; GPR_TIMER_BEGIN("grpc_call_create", 0); gpr_arena *arena = gpr_arena_create(grpc_channel_get_call_size_estimate(args->channel)); call = gpr_arena_alloc(arena, sizeof(grpc_call) + channel_stack->call_stack_size); call->arena = arena; *out_call = call; call->channel = args->channel; call->cq = args->cq; call->start_time = gpr_now(GPR_CLOCK_MONOTONIC); /* Always support no compression */ GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE); call->is_client = args->server_transport_data == NULL; call->stream_op_payload.context = call->context; grpc_slice path = grpc_empty_slice(); if (call->is_client) { GPR_ASSERT(args->add_initial_metadata_count < MAX_SEND_EXTRA_METADATA_COUNT); for (i = 0; i < args->add_initial_metadata_count; i++) { call->send_extra_metadata[i].md = args->add_initial_metadata[i]; if (grpc_slice_eq(GRPC_MDKEY(args->add_initial_metadata[i]), GRPC_MDSTR_PATH)) { path = grpc_slice_ref_internal( GRPC_MDVALUE(args->add_initial_metadata[i])); } } call->send_extra_metadata_count = (int)args->add_initial_metadata_count; } else { GPR_ASSERT(args->add_initial_metadata_count == 0); call->send_extra_metadata_count = 0; } for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { call->metadata_batch[i][j].deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC); } } gpr_timespec send_deadline = gpr_convert_clock_type(args->send_deadline, GPR_CLOCK_MONOTONIC); if (args->parent_call != NULL) { child_call *cc = call->child_call = gpr_arena_alloc(arena, sizeof(child_call)); call->child_call->parent = args->parent_call; GRPC_CALL_INTERNAL_REF(args->parent_call, "child"); GPR_ASSERT(call->is_client); GPR_ASSERT(!args->parent_call->is_client); parent_call *pc = get_or_create_parent_call(args->parent_call); gpr_mu_lock(&pc->child_list_mu); if (args->propagation_mask & GRPC_PROPAGATE_DEADLINE) { send_deadline = gpr_time_min( gpr_convert_clock_type(send_deadline, args->parent_call->send_deadline.clock_type), args->parent_call->send_deadline); } /* for now GRPC_PROPAGATE_TRACING_CONTEXT *MUST* be passed with * GRPC_PROPAGATE_STATS_CONTEXT */ /* TODO(ctiller): This should change to use the appropriate census start_op * call. */ if (args->propagation_mask & GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT) { if (0 == (args->propagation_mask & GRPC_PROPAGATE_CENSUS_STATS_CONTEXT)) { add_init_error(&error, GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Census tracing propagation requested " "without Census context propagation")); } grpc_call_context_set( call, GRPC_CONTEXT_TRACING, args->parent_call->context[GRPC_CONTEXT_TRACING].value, NULL); } else if (args->propagation_mask & GRPC_PROPAGATE_CENSUS_STATS_CONTEXT) { add_init_error(&error, GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Census context propagation requested " "without Census tracing propagation")); } if (args->propagation_mask & GRPC_PROPAGATE_CANCELLATION) { call->cancellation_is_inherited = 1; if (gpr_atm_acq_load(&args->parent_call->received_final_op_atm)) { cancel_with_error(exec_ctx, call, STATUS_FROM_API_OVERRIDE, GRPC_ERROR_CANCELLED); } } if (pc->first_child == NULL) { pc->first_child = call; cc->sibling_next = cc->sibling_prev = call; } else { cc->sibling_next = pc->first_child; cc->sibling_prev = pc->first_child->child_call->sibling_prev; cc->sibling_next->child_call->sibling_prev = cc->sibling_prev->child_call->sibling_next = call; } gpr_mu_unlock(&pc->child_list_mu); } call->send_deadline = send_deadline; GRPC_CHANNEL_INTERNAL_REF(args->channel, "call"); /* initial refcount dropped by grpc_call_destroy */ grpc_call_element_args call_args = { .call_stack = CALL_STACK_FROM_CALL(call), .server_transport_data = args->server_transport_data, .context = call->context, .path = path, .start_time = call->start_time, .deadline = send_deadline, .arena = call->arena}; add_init_error(&error, grpc_call_stack_init(exec_ctx, channel_stack, 1, destroy_call, call, &call_args)); if (error != GRPC_ERROR_NONE) { cancel_with_error(exec_ctx, call, STATUS_FROM_SURFACE, GRPC_ERROR_REF(error)); } if (args->cq != NULL) { GPR_ASSERT( args->pollset_set_alternative == NULL && "Only one of 'cq' and 'pollset_set_alternative' should be non-NULL."); GRPC_CQ_INTERNAL_REF(args->cq, "bind"); call->pollent = grpc_polling_entity_create_from_pollset(grpc_cq_pollset(args->cq)); } if (args->pollset_set_alternative != NULL) { call->pollent = grpc_polling_entity_create_from_pollset_set( args->pollset_set_alternative); } if (!grpc_polling_entity_is_empty(&call->pollent)) { grpc_call_stack_set_pollset_or_pollset_set( exec_ctx, CALL_STACK_FROM_CALL(call), &call->pollent); } grpc_slice_unref_internal(exec_ctx, path); GPR_TIMER_END("grpc_call_create", 0); return error; } void grpc_call_set_completion_queue(grpc_exec_ctx *exec_ctx, grpc_call *call, grpc_completion_queue *cq) { GPR_ASSERT(cq); if (grpc_polling_entity_pollset_set(&call->pollent) != NULL) { gpr_log(GPR_ERROR, "A pollset_set is already registered for this call."); abort(); } call->cq = cq; GRPC_CQ_INTERNAL_REF(cq, "bind"); call->pollent = grpc_polling_entity_create_from_pollset(grpc_cq_pollset(cq)); grpc_call_stack_set_pollset_or_pollset_set( exec_ctx, CALL_STACK_FROM_CALL(call), &call->pollent); } #ifdef GRPC_STREAM_REFCOUNT_DEBUG #define REF_REASON reason #define REF_ARG , const char *reason #else #define REF_REASON "" #define REF_ARG #endif void grpc_call_internal_ref(grpc_call *c REF_ARG) { GRPC_CALL_STACK_REF(CALL_STACK_FROM_CALL(c), REF_REASON); } void grpc_call_internal_unref(grpc_exec_ctx *exec_ctx, grpc_call *c REF_ARG) { GRPC_CALL_STACK_UNREF(exec_ctx, CALL_STACK_FROM_CALL(c), REF_REASON); } static void release_call(grpc_exec_ctx *exec_ctx, void *call, grpc_error *error) { grpc_call *c = call; grpc_channel *channel = c->channel; grpc_channel_update_call_size_estimate(channel, gpr_arena_destroy(c->arena)); GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, "call"); } static void set_status_value_directly(grpc_status_code status, void *dest); static void destroy_call(grpc_exec_ctx *exec_ctx, void *call, grpc_error *error) { size_t i; int ii; grpc_call *c = call; GPR_TIMER_BEGIN("destroy_call", 0); for (i = 0; i < 2; i++) { grpc_metadata_batch_destroy( exec_ctx, &c->metadata_batch[1 /* is_receiving */][i /* is_initial */]); } if (c->receiving_stream != NULL) { grpc_byte_stream_destroy(exec_ctx, c->receiving_stream); } parent_call *pc = get_parent_call(c); if (pc != NULL) { gpr_mu_destroy(&pc->child_list_mu); } for (ii = 0; ii < c->send_extra_metadata_count; ii++) { GRPC_MDELEM_UNREF(exec_ctx, c->send_extra_metadata[ii].md); } for (i = 0; i < GRPC_CONTEXT_COUNT; i++) { if (c->context[i].destroy) { c->context[i].destroy(c->context[i].value); } } if (c->cq) { GRPC_CQ_INTERNAL_UNREF(c->cq, "bind"); } get_final_status(call, set_status_value_directly, &c->final_info.final_status, NULL); c->final_info.stats.latency = gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), c->start_time); for (i = 0; i < STATUS_SOURCE_COUNT; i++) { GRPC_ERROR_UNREF( unpack_received_status(gpr_atm_acq_load(&c->status[i])).error); } grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c), &c->final_info, grpc_closure_init(&c->release_call, release_call, c, grpc_schedule_on_exec_ctx)); GPR_TIMER_END("destroy_call", 0); } void grpc_call_destroy(grpc_call *c) { child_call *cc = c->child_call; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GPR_TIMER_BEGIN("grpc_call_destroy", 0); GRPC_API_TRACE("grpc_call_destroy(c=%p)", 1, (c)); if (cc) { parent_call *pc = get_parent_call(cc->parent); gpr_mu_lock(&pc->child_list_mu); if (c == pc->first_child) { pc->first_child = cc->sibling_next; if (c == pc->first_child) { pc->first_child = NULL; } } cc->sibling_prev->child_call->sibling_next = cc->sibling_next; cc->sibling_next->child_call->sibling_prev = cc->sibling_prev; gpr_mu_unlock(&pc->child_list_mu); GRPC_CALL_INTERNAL_UNREF(&exec_ctx, cc->parent, "child"); } GPR_ASSERT(!c->destroy_called); c->destroy_called = 1; bool cancel = gpr_atm_acq_load(&c->any_ops_sent_atm) != 0 && gpr_atm_acq_load(&c->received_final_op_atm) == 0; if (cancel) { cancel_with_error(&exec_ctx, c, STATUS_FROM_API_OVERRIDE, GRPC_ERROR_CANCELLED); } GRPC_CALL_INTERNAL_UNREF(&exec_ctx, c, "destroy"); grpc_exec_ctx_finish(&exec_ctx); GPR_TIMER_END("grpc_call_destroy", 0); } grpc_call_error grpc_call_cancel(grpc_call *call, void *reserved) { GRPC_API_TRACE("grpc_call_cancel(call=%p, reserved=%p)", 2, (call, reserved)); GPR_ASSERT(!reserved); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; cancel_with_error(&exec_ctx, call, STATUS_FROM_API_OVERRIDE, GRPC_ERROR_CANCELLED); grpc_exec_ctx_finish(&exec_ctx); return GRPC_CALL_OK; } static void execute_op(grpc_exec_ctx *exec_ctx, grpc_call *call, grpc_transport_stream_op_batch *op) { grpc_call_element *elem; GPR_TIMER_BEGIN("execute_op", 0); elem = CALL_ELEM_FROM_CALL(call, 0); elem->filter->start_transport_stream_op_batch(exec_ctx, elem, op); GPR_TIMER_END("execute_op", 0); } char *grpc_call_get_peer(grpc_call *call) { grpc_call_element *elem = CALL_ELEM_FROM_CALL(call, 0); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; char *result; GRPC_API_TRACE("grpc_call_get_peer(%p)", 1, (call)); result = elem->filter->get_peer(&exec_ctx, elem); if (result == NULL) { result = grpc_channel_get_target(call->channel); } if (result == NULL) { result = gpr_strdup("unknown"); } grpc_exec_ctx_finish(&exec_ctx); return result; } grpc_call *grpc_call_from_top_element(grpc_call_element *elem) { return CALL_FROM_TOP_ELEM(elem); } /******************************************************************************* * CANCELLATION */ grpc_call_error grpc_call_cancel_with_status(grpc_call *c, grpc_status_code status, const char *description, void *reserved) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE( "grpc_call_cancel_with_status(" "c=%p, status=%d, description=%s, reserved=%p)", 4, (c, (int)status, description, reserved)); GPR_ASSERT(reserved == NULL); cancel_with_status(&exec_ctx, c, STATUS_FROM_API_OVERRIDE, status, description); grpc_exec_ctx_finish(&exec_ctx); return GRPC_CALL_OK; } static void done_termination(grpc_exec_ctx *exec_ctx, void *call, grpc_error *error) { GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "termination"); } static void cancel_with_error(grpc_exec_ctx *exec_ctx, grpc_call *c, status_source source, grpc_error *error) { GRPC_CALL_INTERNAL_REF(c, "termination"); set_status_from_error(exec_ctx, c, source, GRPC_ERROR_REF(error)); grpc_transport_stream_op_batch *op = grpc_make_transport_stream_op( grpc_closure_create(done_termination, c, grpc_schedule_on_exec_ctx)); op->cancel_stream = true; op->payload->cancel_stream.cancel_error = error; execute_op(exec_ctx, c, op); } static grpc_error *error_from_status(grpc_status_code status, const char *description) { return grpc_error_set_int( grpc_error_set_str(GRPC_ERROR_CREATE_FROM_COPIED_STRING(description), GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_copied_string(description)), GRPC_ERROR_INT_GRPC_STATUS, status); } static void cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c, status_source source, grpc_status_code status, const char *description) { cancel_with_error(exec_ctx, c, source, error_from_status(status, description)); } /******************************************************************************* * FINAL STATUS CODE MANIPULATION */ static bool get_final_status_from( grpc_call *call, grpc_error *error, bool allow_ok_status, void (*set_value)(grpc_status_code code, void *user_data), void *set_value_user_data, grpc_slice *details) { grpc_status_code code; grpc_slice slice = grpc_empty_slice(); grpc_error_get_status(error, call->send_deadline, &code, &slice, NULL); if (code == GRPC_STATUS_OK && !allow_ok_status) { return false; } set_value(code, set_value_user_data); if (details != NULL) { *details = grpc_slice_ref_internal(slice); } return true; } static void get_final_status(grpc_call *call, void (*set_value)(grpc_status_code code, void *user_data), void *set_value_user_data, grpc_slice *details) { int i; received_status status[STATUS_SOURCE_COUNT]; for (i = 0; i < STATUS_SOURCE_COUNT; i++) { status[i] = unpack_received_status(gpr_atm_acq_load(&call->status[i])); } if (grpc_call_error_trace) { gpr_log(GPR_DEBUG, "get_final_status %s", call->is_client ? "CLI" : "SVR"); for (i = 0; i < STATUS_SOURCE_COUNT; i++) { if (status[i].is_set) { gpr_log(GPR_DEBUG, " %d: %s", i, grpc_error_string(status[i].error)); } } } /* first search through ignoring "OK" statuses: if something went wrong, * ensure we report it */ for (int allow_ok_status = 0; allow_ok_status < 2; allow_ok_status++) { /* search for the best status we can present: ideally the error we use has a clearly defined grpc-status, and we'll prefer that. */ for (i = 0; i < STATUS_SOURCE_COUNT; i++) { if (status[i].is_set && grpc_error_has_clear_grpc_status(status[i].error)) { if (get_final_status_from(call, status[i].error, allow_ok_status != 0, set_value, set_value_user_data, details)) { return; } } } /* If no clearly defined status exists, search for 'anything' */ for (i = 0; i < STATUS_SOURCE_COUNT; i++) { if (status[i].is_set) { if (get_final_status_from(call, status[i].error, allow_ok_status != 0, set_value, set_value_user_data, details)) { return; } } } } /* If nothing exists, set some default */ if (call->is_client) { set_value(GRPC_STATUS_UNKNOWN, set_value_user_data); } else { set_value(GRPC_STATUS_OK, set_value_user_data); } } static void set_status_from_error(grpc_exec_ctx *exec_ctx, grpc_call *call, status_source source, grpc_error *error) { if (!gpr_atm_rel_cas(&call->status[source], pack_received_status((received_status){ .is_set = false, .error = GRPC_ERROR_NONE}), pack_received_status((received_status){ .is_set = true, .error = error}))) { GRPC_ERROR_UNREF(error); } } /******************************************************************************* * COMPRESSION */ static void set_incoming_compression_algorithm( grpc_call *call, grpc_compression_algorithm algo) { GPR_ASSERT(algo < GRPC_COMPRESS_ALGORITHMS_COUNT); call->incoming_compression_algorithm = algo; } grpc_compression_algorithm grpc_call_test_only_get_compression_algorithm( grpc_call *call) { grpc_compression_algorithm algorithm; algorithm = call->incoming_compression_algorithm; return algorithm; } static grpc_compression_algorithm compression_algorithm_for_level_locked( grpc_call *call, grpc_compression_level level) { return grpc_compression_algorithm_for_level(level, call->encodings_accepted_by_peer); } uint32_t grpc_call_test_only_get_message_flags(grpc_call *call) { uint32_t flags; flags = call->test_only_last_message_flags; return flags; } static void destroy_encodings_accepted_by_peer(void *p) { return; } static void set_encodings_accepted_by_peer(grpc_exec_ctx *exec_ctx, grpc_call *call, grpc_mdelem mdel) { size_t i; grpc_compression_algorithm algorithm; grpc_slice_buffer accept_encoding_parts; grpc_slice accept_encoding_slice; void *accepted_user_data; accepted_user_data = grpc_mdelem_get_user_data(mdel, destroy_encodings_accepted_by_peer); if (accepted_user_data != NULL) { call->encodings_accepted_by_peer = (uint32_t)(((uintptr_t)accepted_user_data) - 1); return; } accept_encoding_slice = GRPC_MDVALUE(mdel); grpc_slice_buffer_init(&accept_encoding_parts); grpc_slice_split(accept_encoding_slice, ",", &accept_encoding_parts); /* No need to zero call->encodings_accepted_by_peer: grpc_call_create already * zeroes the whole grpc_call */ /* Always support no compression */ GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE); for (i = 0; i < accept_encoding_parts.count; i++) { grpc_slice accept_encoding_entry_slice = accept_encoding_parts.slices[i]; if (grpc_compression_algorithm_parse(accept_encoding_entry_slice, &algorithm)) { GPR_BITSET(&call->encodings_accepted_by_peer, algorithm); } else { char *accept_encoding_entry_str = grpc_slice_to_c_string(accept_encoding_entry_slice); gpr_log(GPR_ERROR, "Invalid entry in accept encoding metadata: '%s'. Ignoring.", accept_encoding_entry_str); gpr_free(accept_encoding_entry_str); } } grpc_slice_buffer_destroy_internal(exec_ctx, &accept_encoding_parts); grpc_mdelem_set_user_data( mdel, destroy_encodings_accepted_by_peer, (void *)(((uintptr_t)call->encodings_accepted_by_peer) + 1)); } uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call) { uint32_t encodings_accepted_by_peer; encodings_accepted_by_peer = call->encodings_accepted_by_peer; return encodings_accepted_by_peer; } static grpc_linked_mdelem *linked_from_md(grpc_metadata *md) { return (grpc_linked_mdelem *)&md->internal_data; } static grpc_metadata *get_md_elem(grpc_metadata *metadata, grpc_metadata *additional_metadata, int i, int count) { grpc_metadata *res = i < count ? &metadata[i] : &additional_metadata[i - count]; GPR_ASSERT(res); return res; } static int prepare_application_metadata( grpc_exec_ctx *exec_ctx, grpc_call *call, int count, grpc_metadata *metadata, int is_trailing, int prepend_extra_metadata, grpc_metadata *additional_metadata, int additional_metadata_count) { int total_count = count + additional_metadata_count; int i; grpc_metadata_batch *batch = &call->metadata_batch[0 /* is_receiving */][is_trailing]; for (i = 0; i < total_count; i++) { const grpc_metadata *md = get_md_elem(metadata, additional_metadata, i, count); grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data; GPR_ASSERT(sizeof(grpc_linked_mdelem) == sizeof(md->internal_data)); if (!GRPC_LOG_IF_ERROR("validate_metadata", grpc_validate_header_key_is_legal(md->key))) { break; } else if (!grpc_is_binary_header(md->key) && !GRPC_LOG_IF_ERROR( "validate_metadata", grpc_validate_header_nonbin_value_is_legal(md->value))) { break; } l->md = grpc_mdelem_from_grpc_metadata(exec_ctx, (grpc_metadata *)md); } if (i != total_count) { for (int j = 0; j < i; j++) { const grpc_metadata *md = get_md_elem(metadata, additional_metadata, j, count); grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data; GRPC_MDELEM_UNREF(exec_ctx, l->md); } return 0; } if (prepend_extra_metadata) { if (call->send_extra_metadata_count == 0) { prepend_extra_metadata = 0; } else { for (i = 0; i < call->send_extra_metadata_count; i++) { GRPC_LOG_IF_ERROR("prepare_application_metadata", grpc_metadata_batch_link_tail( exec_ctx, batch, &call->send_extra_metadata[i])); } } } for (i = 0; i < total_count; i++) { grpc_metadata *md = get_md_elem(metadata, additional_metadata, i, count); GRPC_LOG_IF_ERROR( "prepare_application_metadata", grpc_metadata_batch_link_tail(exec_ctx, batch, linked_from_md(md))); } call->send_extra_metadata_count = 0; return 1; } /* we offset status by a small amount when storing it into transport metadata as metadata cannot store a 0 value (which is used as OK for grpc_status_codes */ #define STATUS_OFFSET 1 static void destroy_status(void *ignored) {} static uint32_t decode_status(grpc_mdelem md) { uint32_t status; void *user_data; if (grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) return 0; if (grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_1)) return 1; if (grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_2)) return 2; user_data = grpc_mdelem_get_user_data(md, destroy_status); if (user_data != NULL) { status = ((uint32_t)(intptr_t)user_data) - STATUS_OFFSET; } else { if (!grpc_parse_slice_to_uint32(GRPC_MDVALUE(md), &status)) { status = GRPC_STATUS_UNKNOWN; /* could not parse status code */ } grpc_mdelem_set_user_data(md, destroy_status, (void *)(intptr_t)(status + STATUS_OFFSET)); } return status; } static grpc_compression_algorithm decode_compression(grpc_mdelem md) { grpc_compression_algorithm algorithm = grpc_compression_algorithm_from_slice(GRPC_MDVALUE(md)); if (algorithm == GRPC_COMPRESS_ALGORITHMS_COUNT) { char *md_c_str = grpc_slice_to_c_string(GRPC_MDVALUE(md)); gpr_log(GPR_ERROR, "Invalid incoming compression algorithm: '%s'. Interpreting " "incoming data as uncompressed.", md_c_str); gpr_free(md_c_str); return GRPC_COMPRESS_NONE; } return algorithm; } static void recv_common_filter(grpc_exec_ctx *exec_ctx, grpc_call *call, grpc_metadata_batch *b) { if (b->idx.named.grpc_status != NULL) { uint32_t status_code = decode_status(b->idx.named.grpc_status->md); grpc_error *error = status_code == GRPC_STATUS_OK ? GRPC_ERROR_NONE : grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Error received from peer"), GRPC_ERROR_INT_GRPC_STATUS, (intptr_t)status_code); if (b->idx.named.grpc_message != NULL) { error = grpc_error_set_str( error, GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.grpc_message->md))); grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_message); } else if (error != GRPC_ERROR_NONE) { error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, grpc_empty_slice()); } set_status_from_error(exec_ctx, call, STATUS_FROM_WIRE, error); grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_status); } } static void publish_app_metadata(grpc_call *call, grpc_metadata_batch *b, int is_trailing) { if (b->list.count == 0) return; GPR_TIMER_BEGIN("publish_app_metadata", 0); grpc_metadata_array *dest; grpc_metadata *mdusr; dest = call->buffered_metadata[is_trailing]; if (dest->count + b->list.count > dest->capacity) { dest->capacity = GPR_MAX(dest->capacity + b->list.count, dest->capacity * 3 / 2); dest->metadata = gpr_realloc(dest->metadata, sizeof(grpc_metadata) * dest->capacity); } for (grpc_linked_mdelem *l = b->list.head; l != NULL; l = l->next) { mdusr = &dest->metadata[dest->count++]; /* we pass back borrowed slices that are valid whilst the call is valid */ mdusr->key = GRPC_MDKEY(l->md); mdusr->value = GRPC_MDVALUE(l->md); } GPR_TIMER_END("publish_app_metadata", 0); } static void recv_initial_filter(grpc_exec_ctx *exec_ctx, grpc_call *call, grpc_metadata_batch *b) { recv_common_filter(exec_ctx, call, b); if (b->idx.named.grpc_encoding != NULL) { GPR_TIMER_BEGIN("incoming_compression_algorithm", 0); set_incoming_compression_algorithm( call, decode_compression(b->idx.named.grpc_encoding->md)); GPR_TIMER_END("incoming_compression_algorithm", 0); grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_encoding); } if (b->idx.named.grpc_accept_encoding != NULL) { GPR_TIMER_BEGIN("encodings_accepted_by_peer", 0); set_encodings_accepted_by_peer(exec_ctx, call, b->idx.named.grpc_accept_encoding->md); grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_accept_encoding); GPR_TIMER_END("encodings_accepted_by_peer", 0); } publish_app_metadata(call, b, false); } static void recv_trailing_filter(grpc_exec_ctx *exec_ctx, void *args, grpc_metadata_batch *b) { grpc_call *call = args; recv_common_filter(exec_ctx, call, b); publish_app_metadata(call, b, true); } grpc_call_stack *grpc_call_get_call_stack(grpc_call *call) { return CALL_STACK_FROM_CALL(call); } /******************************************************************************* * BATCH API IMPLEMENTATION */ static void set_status_value_directly(grpc_status_code status, void *dest) { *(grpc_status_code *)dest = status; } static void set_cancelled_value(grpc_status_code status, void *dest) { *(int *)dest = (status != GRPC_STATUS_OK); } static bool are_write_flags_valid(uint32_t flags) { /* check that only bits in GRPC_WRITE_(INTERNAL?)_USED_MASK are set */ const uint32_t allowed_write_positions = (GRPC_WRITE_USED_MASK | GRPC_WRITE_INTERNAL_USED_MASK); const uint32_t invalid_positions = ~allowed_write_positions; return !(flags & invalid_positions); } static bool are_initial_metadata_flags_valid(uint32_t flags, bool is_client) { /* check that only bits in GRPC_WRITE_(INTERNAL?)_USED_MASK are set */ uint32_t invalid_positions = ~GRPC_INITIAL_METADATA_USED_MASK; if (!is_client) { invalid_positions |= GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; } return !(flags & invalid_positions); } static int batch_slot_for_op(grpc_op_type type) { switch (type) { case GRPC_OP_SEND_INITIAL_METADATA: return 0; case GRPC_OP_SEND_MESSAGE: return 1; case GRPC_OP_SEND_CLOSE_FROM_CLIENT: case GRPC_OP_SEND_STATUS_FROM_SERVER: return 2; case GRPC_OP_RECV_INITIAL_METADATA: return 3; case GRPC_OP_RECV_MESSAGE: return 4; case GRPC_OP_RECV_CLOSE_ON_SERVER: case GRPC_OP_RECV_STATUS_ON_CLIENT: return 5; } GPR_UNREACHABLE_CODE(return 123456789); } static batch_control *allocate_batch_control(grpc_call *call, const grpc_op *ops, size_t num_ops) { int slot = batch_slot_for_op(ops[0].op); batch_control **pslot = &call->active_batches[slot]; if (*pslot == NULL) { *pslot = gpr_arena_alloc(call->arena, sizeof(batch_control)); } batch_control *bctl = *pslot; if (bctl->call != NULL) { return NULL; } memset(bctl, 0, sizeof(*bctl)); bctl->call = call; bctl->op.payload = &call->stream_op_payload; return bctl; } static void finish_batch_completion(grpc_exec_ctx *exec_ctx, void *user_data, grpc_cq_completion *storage) { batch_control *bctl = user_data; grpc_call *call = bctl->call; bctl->call = NULL; GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion"); } static grpc_error *consolidate_batch_errors(batch_control *bctl) { size_t n = (size_t)gpr_atm_acq_load(&bctl->num_errors); if (n == 0) { return GRPC_ERROR_NONE; } else if (n == 1) { /* Skip creating a composite error in the case that only one error was logged */ grpc_error *e = bctl->errors[0]; bctl->errors[0] = NULL; return e; } else { grpc_error *error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Call batch failed", bctl->errors, n); for (size_t i = 0; i < n; i++) { GRPC_ERROR_UNREF(bctl->errors[i]); bctl->errors[i] = NULL; } return error; } } static void post_batch_completion(grpc_exec_ctx *exec_ctx, batch_control *bctl) { grpc_call *next_child_call; grpc_call *call = bctl->call; grpc_error *error = consolidate_batch_errors(bctl); if (bctl->op.send_initial_metadata) { grpc_metadata_batch_destroy( exec_ctx, &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]); } if (bctl->op.send_message) { call->sending_message = false; } if (bctl->op.send_trailing_metadata) { grpc_metadata_batch_destroy( exec_ctx, &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]); } if (bctl->op.recv_trailing_metadata) { grpc_metadata_batch *md = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; recv_trailing_filter(exec_ctx, call, md); /* propagate cancellation to any interested children */ gpr_atm_rel_store(&call->received_final_op_atm, 1); parent_call *pc = get_parent_call(call); if (pc != NULL) { grpc_call *child; gpr_mu_lock(&pc->child_list_mu); child = pc->first_child; if (child != NULL) { do { next_child_call = child->child_call->sibling_next; if (child->cancellation_is_inherited) { GRPC_CALL_INTERNAL_REF(child, "propagate_cancel"); cancel_with_error(exec_ctx, child, STATUS_FROM_API_OVERRIDE, GRPC_ERROR_CANCELLED); GRPC_CALL_INTERNAL_UNREF(exec_ctx, child, "propagate_cancel"); } child = next_child_call; } while (child != pc->first_child); } gpr_mu_unlock(&pc->child_list_mu); } if (call->is_client) { get_final_status(call, set_status_value_directly, call->final_op.client.status, call->final_op.client.status_details); } else { get_final_status(call, set_cancelled_value, call->final_op.server.cancelled, NULL); } GRPC_ERROR_UNREF(error); error = GRPC_ERROR_NONE; } if (bctl->completion_data.notify_tag.is_closure) { /* unrefs bctl->error */ bctl->call = NULL; grpc_closure_run(exec_ctx, bctl->completion_data.notify_tag.tag, error); GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion"); } else { /* unrefs bctl->error */ grpc_cq_end_op( exec_ctx, bctl->call->cq, bctl->completion_data.notify_tag.tag, error, finish_batch_completion, bctl, &bctl->completion_data.cq_completion); } } static void finish_batch_step(grpc_exec_ctx *exec_ctx, batch_control *bctl) { if (gpr_unref(&bctl->steps_to_complete)) { post_batch_completion(exec_ctx, bctl); } } static void continue_receiving_slices(grpc_exec_ctx *exec_ctx, batch_control *bctl) { grpc_call *call = bctl->call; for (;;) { size_t remaining = call->receiving_stream->length - (*call->receiving_buffer)->data.raw.slice_buffer.length; if (remaining == 0) { call->receiving_message = 0; grpc_byte_stream_destroy(exec_ctx, call->receiving_stream); call->receiving_stream = NULL; finish_batch_step(exec_ctx, bctl); return; } if (grpc_byte_stream_next(exec_ctx, call->receiving_stream, &call->receiving_slice, remaining, &call->receiving_slice_ready)) { grpc_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer, call->receiving_slice); } else { return; } } } static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp, grpc_error *error) { batch_control *bctl = bctlp; grpc_call *call = bctl->call; if (error == GRPC_ERROR_NONE) { grpc_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer, call->receiving_slice); continue_receiving_slices(exec_ctx, bctl); } else { if (grpc_trace_operation_failures) { GRPC_LOG_IF_ERROR("receiving_slice_ready", GRPC_ERROR_REF(error)); } grpc_byte_stream_destroy(exec_ctx, call->receiving_stream); call->receiving_stream = NULL; grpc_byte_buffer_destroy(*call->receiving_buffer); *call->receiving_buffer = NULL; finish_batch_step(exec_ctx, bctl); } } static void process_data_after_md(grpc_exec_ctx *exec_ctx, batch_control *bctl) { grpc_call *call = bctl->call; if (call->receiving_stream == NULL) { *call->receiving_buffer = NULL; call->receiving_message = 0; finish_batch_step(exec_ctx, bctl); } else { call->test_only_last_message_flags = call->receiving_stream->flags; if ((call->receiving_stream->flags & GRPC_WRITE_INTERNAL_COMPRESS) && (call->incoming_compression_algorithm > GRPC_COMPRESS_NONE)) { *call->receiving_buffer = grpc_raw_compressed_byte_buffer_create( NULL, 0, call->incoming_compression_algorithm); } else { *call->receiving_buffer = grpc_raw_byte_buffer_create(NULL, 0); } grpc_closure_init(&call->receiving_slice_ready, receiving_slice_ready, bctl, grpc_schedule_on_exec_ctx); continue_receiving_slices(exec_ctx, bctl); } } static void receiving_stream_ready(grpc_exec_ctx *exec_ctx, void *bctlp, grpc_error *error) { batch_control *bctl = bctlp; grpc_call *call = bctl->call; if (error != GRPC_ERROR_NONE) { if (call->receiving_stream != NULL) { grpc_byte_stream_destroy(exec_ctx, call->receiving_stream); call->receiving_stream = NULL; } add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), true); cancel_with_error(exec_ctx, call, STATUS_FROM_SURFACE, GRPC_ERROR_REF(error)); } if (call->has_initial_md_been_received || error != GRPC_ERROR_NONE || call->receiving_stream == NULL) { process_data_after_md(exec_ctx, bctlp); } else { call->saved_receiving_stream_ready_bctlp = bctlp; } } static void validate_filtered_metadata(grpc_exec_ctx *exec_ctx, batch_control *bctl) { grpc_call *call = bctl->call; /* validate call->incoming_compression_algorithm */ if (call->incoming_compression_algorithm != GRPC_COMPRESS_NONE) { const grpc_compression_algorithm algo = call->incoming_compression_algorithm; char *error_msg = NULL; const grpc_compression_options compression_options = grpc_channel_compression_options(call->channel); /* check if algorithm is known */ if (algo >= GRPC_COMPRESS_ALGORITHMS_COUNT) { gpr_asprintf(&error_msg, "Invalid compression algorithm value '%d'.", algo); gpr_log(GPR_ERROR, "%s", error_msg); cancel_with_status(exec_ctx, call, STATUS_FROM_SURFACE, GRPC_STATUS_UNIMPLEMENTED, error_msg); } else if (grpc_compression_options_is_algorithm_enabled( &compression_options, algo) == 0) { /* check if algorithm is supported by current channel config */ char *algo_name = NULL; grpc_compression_algorithm_name(algo, &algo_name); gpr_asprintf(&error_msg, "Compression algorithm '%s' is disabled.", algo_name); gpr_log(GPR_ERROR, "%s", error_msg); cancel_with_status(exec_ctx, call, STATUS_FROM_SURFACE, GRPC_STATUS_UNIMPLEMENTED, error_msg); } else { call->incoming_compression_algorithm = algo; } gpr_free(error_msg); } /* make sure the received grpc-encoding is amongst the ones listed in * grpc-accept-encoding */ GPR_ASSERT(call->encodings_accepted_by_peer != 0); if (!GPR_BITGET(call->encodings_accepted_by_peer, call->incoming_compression_algorithm)) { extern int grpc_compression_trace; if (grpc_compression_trace) { char *algo_name = NULL; grpc_compression_algorithm_name(call->incoming_compression_algorithm, &algo_name); gpr_log(GPR_ERROR, "Compression algorithm (grpc-encoding = '%s') not present in " "the bitset of accepted encodings (grpc-accept-encodings: " "'0x%x')", algo_name, call->encodings_accepted_by_peer); } } } static void add_batch_error(grpc_exec_ctx *exec_ctx, batch_control *bctl, grpc_error *error, bool has_cancelled) { if (error == GRPC_ERROR_NONE) return; int idx = (int)gpr_atm_full_fetch_add(&bctl->num_errors, 1); if (idx == 0 && !has_cancelled) { cancel_with_error(exec_ctx, bctl->call, STATUS_FROM_CORE, GRPC_ERROR_REF(error)); } bctl->errors[idx] = error; } static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx, void *bctlp, grpc_error *error) { batch_control *bctl = bctlp; grpc_call *call = bctl->call; add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), false); if (error == GRPC_ERROR_NONE) { grpc_metadata_batch *md = &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */]; recv_initial_filter(exec_ctx, call, md); /* TODO(ctiller): this could be moved into recv_initial_filter now */ GPR_TIMER_BEGIN("validate_filtered_metadata", 0); validate_filtered_metadata(exec_ctx, bctl); GPR_TIMER_END("validate_filtered_metadata", 0); if (gpr_time_cmp(md->deadline, gpr_inf_future(md->deadline.clock_type)) != 0 && !call->is_client) { call->send_deadline = gpr_convert_clock_type(md->deadline, GPR_CLOCK_MONOTONIC); } } call->has_initial_md_been_received = true; if (call->saved_receiving_stream_ready_bctlp != NULL) { grpc_closure *saved_rsr_closure = grpc_closure_create( receiving_stream_ready, call->saved_receiving_stream_ready_bctlp, grpc_schedule_on_exec_ctx); call->saved_receiving_stream_ready_bctlp = NULL; grpc_closure_run(exec_ctx, saved_rsr_closure, GRPC_ERROR_REF(error)); } finish_batch_step(exec_ctx, bctl); } static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp, grpc_error *error) { batch_control *bctl = bctlp; add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), false); finish_batch_step(exec_ctx, bctl); } static void free_no_op_completion(grpc_exec_ctx *exec_ctx, void *p, grpc_cq_completion *completion) { gpr_free(completion); } static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, grpc_call *call, const grpc_op *ops, size_t nops, void *notify_tag, int is_notify_tag_closure) { size_t i; const grpc_op *op; batch_control *bctl; int num_completion_callbacks_needed = 1; grpc_call_error error = GRPC_CALL_OK; // sent_initial_metadata guards against variable reuse. grpc_metadata compression_md; GPR_TIMER_BEGIN("grpc_call_start_batch", 0); GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, notify_tag); if (nops == 0) { if (!is_notify_tag_closure) { grpc_cq_begin_op(call->cq, notify_tag); grpc_cq_end_op(exec_ctx, call->cq, notify_tag, GRPC_ERROR_NONE, free_no_op_completion, NULL, gpr_malloc(sizeof(grpc_cq_completion))); } else { grpc_closure_sched(exec_ctx, notify_tag, GRPC_ERROR_NONE); } error = GRPC_CALL_OK; goto done; } bctl = allocate_batch_control(call, ops, nops); if (bctl == NULL) { return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; } bctl->completion_data.notify_tag.tag = notify_tag; bctl->completion_data.notify_tag.is_closure = (uint8_t)(is_notify_tag_closure != 0); grpc_transport_stream_op_batch *stream_op = &bctl->op; grpc_transport_stream_op_batch_payload *stream_op_payload = &call->stream_op_payload; stream_op->covered_by_poller = true; /* rewrite batch ops into a transport op */ for (i = 0; i < nops; i++) { op = &ops[i]; if (op->reserved != NULL) { error = GRPC_CALL_ERROR; goto done_with_error; } switch (op->op) { case GRPC_OP_SEND_INITIAL_METADATA: /* Flag validation: currently allow no flags */ if (!are_initial_metadata_flags_valid(op->flags, call->is_client)) { error = GRPC_CALL_ERROR_INVALID_FLAGS; goto done_with_error; } if (call->sent_initial_metadata) { error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; goto done_with_error; } /* process compression level */ memset(&compression_md, 0, sizeof(compression_md)); size_t additional_metadata_count = 0; grpc_compression_level effective_compression_level; bool level_set = false; if (op->data.send_initial_metadata.maybe_compression_level.is_set) { effective_compression_level = op->data.send_initial_metadata.maybe_compression_level.level; level_set = true; } else { const grpc_compression_options copts = grpc_channel_compression_options(call->channel); level_set = copts.default_level.is_set; if (level_set) { effective_compression_level = copts.default_level.level; } } if (level_set && !call->is_client) { const grpc_compression_algorithm calgo = compression_algorithm_for_level_locked( call, effective_compression_level); // the following will be picked up by the compress filter and used as // the call's compression algorithm. compression_md.key = GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST; compression_md.value = grpc_compression_algorithm_slice(calgo); additional_metadata_count++; } if (op->data.send_initial_metadata.count + additional_metadata_count > INT_MAX) { error = GRPC_CALL_ERROR_INVALID_METADATA; goto done_with_error; } stream_op->send_initial_metadata = true; call->sent_initial_metadata = true; if (!prepare_application_metadata( exec_ctx, call, (int)op->data.send_initial_metadata.count, op->data.send_initial_metadata.metadata, 0, call->is_client, &compression_md, (int)additional_metadata_count)) { error = GRPC_CALL_ERROR_INVALID_METADATA; goto done_with_error; } /* TODO(ctiller): just make these the same variable? */ call->metadata_batch[0][0].deadline = call->send_deadline; stream_op_payload->send_initial_metadata.send_initial_metadata = &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]; stream_op_payload->send_initial_metadata.send_initial_metadata_flags = op->flags; break; case GRPC_OP_SEND_MESSAGE: if (!are_write_flags_valid(op->flags)) { error = GRPC_CALL_ERROR_INVALID_FLAGS; goto done_with_error; } if (op->data.send_message.send_message == NULL) { error = GRPC_CALL_ERROR_INVALID_MESSAGE; goto done_with_error; } if (call->sending_message) { error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; goto done_with_error; } stream_op->send_message = true; call->sending_message = true; grpc_slice_buffer_stream_init( &call->sending_stream, &op->data.send_message.send_message->data.raw.slice_buffer, op->flags); /* If the outgoing buffer is already compressed, mark it as so in the flags. These will be picked up by the compression filter and further (wasteful) attempts at compression skipped. */ if (op->data.send_message.send_message->data.raw.compression > GRPC_COMPRESS_NONE) { call->sending_stream.base.flags |= GRPC_WRITE_INTERNAL_COMPRESS; } stream_op_payload->send_message.send_message = &call->sending_stream.base; break; case GRPC_OP_SEND_CLOSE_FROM_CLIENT: /* Flag validation: currently allow no flags */ if (op->flags != 0) { error = GRPC_CALL_ERROR_INVALID_FLAGS; goto done_with_error; } if (!call->is_client) { error = GRPC_CALL_ERROR_NOT_ON_SERVER; goto done_with_error; } if (call->sent_final_op) { error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; goto done_with_error; } stream_op->send_trailing_metadata = true; call->sent_final_op = true; stream_op_payload->send_trailing_metadata.send_trailing_metadata = &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]; break; case GRPC_OP_SEND_STATUS_FROM_SERVER: /* Flag validation: currently allow no flags */ if (op->flags != 0) { error = GRPC_CALL_ERROR_INVALID_FLAGS; goto done_with_error; } if (call->is_client) { error = GRPC_CALL_ERROR_NOT_ON_CLIENT; goto done_with_error; } if (call->sent_final_op) { error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; goto done_with_error; } if (op->data.send_status_from_server.trailing_metadata_count > INT_MAX) { error = GRPC_CALL_ERROR_INVALID_METADATA; goto done_with_error; } stream_op->send_trailing_metadata = true; call->sent_final_op = true; GPR_ASSERT(call->send_extra_metadata_count == 0); call->send_extra_metadata_count = 1; call->send_extra_metadata[0].md = grpc_channel_get_reffed_status_elem( exec_ctx, call->channel, op->data.send_status_from_server.status); { grpc_error *override_error = GRPC_ERROR_NONE; if (op->data.send_status_from_server.status != GRPC_STATUS_OK) { override_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Error from server send status"); } if (op->data.send_status_from_server.status_details != NULL) { call->send_extra_metadata[1].md = grpc_mdelem_from_slices( exec_ctx, GRPC_MDSTR_GRPC_MESSAGE, grpc_slice_ref_internal( *op->data.send_status_from_server.status_details)); call->send_extra_metadata_count++; char *msg = grpc_slice_to_c_string( GRPC_MDVALUE(call->send_extra_metadata[1].md)); override_error = grpc_error_set_str(override_error, GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_copied_string(msg)); gpr_free(msg); } set_status_from_error(exec_ctx, call, STATUS_FROM_API_OVERRIDE, override_error); } if (!prepare_application_metadata( exec_ctx, call, (int)op->data.send_status_from_server.trailing_metadata_count, op->data.send_status_from_server.trailing_metadata, 1, 1, NULL, 0)) { for (int n = 0; n < call->send_extra_metadata_count; n++) { GRPC_MDELEM_UNREF(exec_ctx, call->send_extra_metadata[n].md); } call->send_extra_metadata_count = 0; error = GRPC_CALL_ERROR_INVALID_METADATA; goto done_with_error; } stream_op_payload->send_trailing_metadata.send_trailing_metadata = &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]; break; case GRPC_OP_RECV_INITIAL_METADATA: /* Flag validation: currently allow no flags */ if (op->flags != 0) { error = GRPC_CALL_ERROR_INVALID_FLAGS; goto done_with_error; } if (call->received_initial_metadata) { error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; goto done_with_error; } /* IF this is a server, then GRPC_OP_RECV_INITIAL_METADATA *must* come from server.c. In that case, it's coming from accept_stream, and in that case we're not necessarily covered by a poller. */ stream_op->covered_by_poller = call->is_client; call->received_initial_metadata = true; call->buffered_metadata[0] = op->data.recv_initial_metadata.recv_initial_metadata; grpc_closure_init(&call->receiving_initial_metadata_ready, receiving_initial_metadata_ready, bctl, grpc_schedule_on_exec_ctx); stream_op->recv_initial_metadata = true; stream_op_payload->recv_initial_metadata.recv_initial_metadata = &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */]; stream_op_payload->recv_initial_metadata.recv_initial_metadata_ready = &call->receiving_initial_metadata_ready; num_completion_callbacks_needed++; break; case GRPC_OP_RECV_MESSAGE: /* Flag validation: currently allow no flags */ if (op->flags != 0) { error = GRPC_CALL_ERROR_INVALID_FLAGS; goto done_with_error; } if (call->receiving_message) { error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; goto done_with_error; } call->receiving_message = true; stream_op->recv_message = true; call->receiving_buffer = op->data.recv_message.recv_message; stream_op_payload->recv_message.recv_message = &call->receiving_stream; grpc_closure_init(&call->receiving_stream_ready, receiving_stream_ready, bctl, grpc_schedule_on_exec_ctx); stream_op_payload->recv_message.recv_message_ready = &call->receiving_stream_ready; num_completion_callbacks_needed++; break; case GRPC_OP_RECV_STATUS_ON_CLIENT: /* Flag validation: currently allow no flags */ if (op->flags != 0) { error = GRPC_CALL_ERROR_INVALID_FLAGS; goto done_with_error; } if (!call->is_client) { error = GRPC_CALL_ERROR_NOT_ON_SERVER; goto done_with_error; } if (call->requested_final_op) { error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; goto done_with_error; } call->requested_final_op = true; call->buffered_metadata[1] = op->data.recv_status_on_client.trailing_metadata; call->final_op.client.status = op->data.recv_status_on_client.status; call->final_op.client.status_details = op->data.recv_status_on_client.status_details; stream_op->recv_trailing_metadata = true; stream_op->collect_stats = true; stream_op_payload->recv_trailing_metadata.recv_trailing_metadata = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; stream_op_payload->collect_stats.collect_stats = &call->final_info.stats.transport_stream_stats; break; case GRPC_OP_RECV_CLOSE_ON_SERVER: /* Flag validation: currently allow no flags */ if (op->flags != 0) { error = GRPC_CALL_ERROR_INVALID_FLAGS; goto done_with_error; } if (call->is_client) { error = GRPC_CALL_ERROR_NOT_ON_CLIENT; goto done_with_error; } if (call->requested_final_op) { error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; goto done_with_error; } call->requested_final_op = true; call->final_op.server.cancelled = op->data.recv_close_on_server.cancelled; stream_op->recv_trailing_metadata = true; stream_op->collect_stats = true; stream_op_payload->recv_trailing_metadata.recv_trailing_metadata = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; stream_op_payload->collect_stats.collect_stats = &call->final_info.stats.transport_stream_stats; break; } } GRPC_CALL_INTERNAL_REF(call, "completion"); if (!is_notify_tag_closure) { grpc_cq_begin_op(call->cq, notify_tag); } gpr_ref_init(&bctl->steps_to_complete, num_completion_callbacks_needed); grpc_closure_init(&bctl->finish_batch, finish_batch, bctl, grpc_schedule_on_exec_ctx); stream_op->on_complete = &bctl->finish_batch; gpr_atm_rel_store(&call->any_ops_sent_atm, 1); execute_op(exec_ctx, call, stream_op); done: GPR_TIMER_END("grpc_call_start_batch", 0); return error; done_with_error: /* reverse any mutations that occured */ if (stream_op->send_initial_metadata) { call->sent_initial_metadata = false; grpc_metadata_batch_clear(exec_ctx, &call->metadata_batch[0][0]); } if (stream_op->send_message) { call->sending_message = false; grpc_byte_stream_destroy(exec_ctx, &call->sending_stream.base); } if (stream_op->send_trailing_metadata) { call->sent_final_op = false; grpc_metadata_batch_clear(exec_ctx, &call->metadata_batch[0][1]); } if (stream_op->recv_initial_metadata) { call->received_initial_metadata = false; } if (stream_op->recv_message) { call->receiving_message = false; } if (stream_op->recv_trailing_metadata) { call->requested_final_op = false; } goto done; } grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops, size_t nops, void *tag, void *reserved) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_call_error err; GRPC_API_TRACE( "grpc_call_start_batch(call=%p, ops=%p, nops=%lu, tag=%p, " "reserved=%p)", 5, (call, ops, (unsigned long)nops, tag, reserved)); if (reserved != NULL) { err = GRPC_CALL_ERROR; } else { err = call_start_batch(&exec_ctx, call, ops, nops, tag, 0); } grpc_exec_ctx_finish(&exec_ctx); return err; } grpc_call_error grpc_call_start_batch_and_execute(grpc_exec_ctx *exec_ctx, grpc_call *call, const grpc_op *ops, size_t nops, grpc_closure *closure) { return call_start_batch(exec_ctx, call, ops, nops, closure, 1); } void grpc_call_context_set(grpc_call *call, grpc_context_index elem, void *value, void (*destroy)(void *value)) { if (call->context[elem].destroy) { call->context[elem].destroy(call->context[elem].value); } call->context[elem].value = value; call->context[elem].destroy = destroy; } void *grpc_call_context_get(grpc_call *call, grpc_context_index elem) { return call->context[elem].value; } uint8_t grpc_call_is_client(grpc_call *call) { return call->is_client; } grpc_compression_algorithm grpc_call_compression_for_level( grpc_call *call, grpc_compression_level level) { grpc_compression_algorithm algo = compression_algorithm_for_level_locked(call, level); return algo; } const char *grpc_call_error_to_string(grpc_call_error error) { switch (error) { case GRPC_CALL_ERROR: return "GRPC_CALL_ERROR"; case GRPC_CALL_ERROR_ALREADY_ACCEPTED: return "GRPC_CALL_ERROR_ALREADY_ACCEPTED"; case GRPC_CALL_ERROR_ALREADY_FINISHED: return "GRPC_CALL_ERROR_ALREADY_FINISHED"; case GRPC_CALL_ERROR_ALREADY_INVOKED: return "GRPC_CALL_ERROR_ALREADY_INVOKED"; case GRPC_CALL_ERROR_BATCH_TOO_BIG: return "GRPC_CALL_ERROR_BATCH_TOO_BIG"; case GRPC_CALL_ERROR_INVALID_FLAGS: return "GRPC_CALL_ERROR_INVALID_FLAGS"; case GRPC_CALL_ERROR_INVALID_MESSAGE: return "GRPC_CALL_ERROR_INVALID_MESSAGE"; case GRPC_CALL_ERROR_INVALID_METADATA: return "GRPC_CALL_ERROR_INVALID_METADATA"; case GRPC_CALL_ERROR_NOT_INVOKED: return "GRPC_CALL_ERROR_NOT_INVOKED"; case GRPC_CALL_ERROR_NOT_ON_CLIENT: return "GRPC_CALL_ERROR_NOT_ON_CLIENT"; case GRPC_CALL_ERROR_NOT_ON_SERVER: return "GRPC_CALL_ERROR_NOT_ON_SERVER"; case GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE: return "GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE"; case GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH: return "GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH"; case GRPC_CALL_ERROR_TOO_MANY_OPERATIONS: return "GRPC_CALL_ERROR_TOO_MANY_OPERATIONS"; case GRPC_CALL_OK: return "GRPC_CALL_OK"; } GPR_UNREACHABLE_CODE(return "GRPC_CALL_ERROR_UNKNOW"); } grpc-1.3.2/src/core/lib/surface/call.h000066400000000000000000000122431310511640000174420ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SURFACE_CALL_H #define GRPC_CORE_LIB_SURFACE_CALL_H #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/context.h" #include "src/core/lib/surface/api_trace.h" #include #include #ifdef __cplusplus extern "C" { #endif typedef void (*grpc_ioreq_completion_func)(grpc_exec_ctx *exec_ctx, grpc_call *call, int success, void *user_data); typedef struct grpc_call_create_args { grpc_channel *channel; grpc_call *parent_call; uint32_t propagation_mask; grpc_completion_queue *cq; /* if not NULL, it'll be used in lieu of cq */ grpc_pollset_set *pollset_set_alternative; const void *server_transport_data; grpc_mdelem *add_initial_metadata; size_t add_initial_metadata_count; gpr_timespec send_deadline; } grpc_call_create_args; /* Create a new call based on \a args. Regardless of success or failure, always returns a valid new call into *call */ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx, const grpc_call_create_args *args, grpc_call **call); void grpc_call_set_completion_queue(grpc_exec_ctx *exec_ctx, grpc_call *call, grpc_completion_queue *cq); #ifdef GRPC_STREAM_REFCOUNT_DEBUG void grpc_call_internal_ref(grpc_call *call, const char *reason); void grpc_call_internal_unref(grpc_exec_ctx *exec_ctx, grpc_call *call, const char *reason); #define GRPC_CALL_INTERNAL_REF(call, reason) \ grpc_call_internal_ref(call, reason) #define GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, reason) \ grpc_call_internal_unref(exec_ctx, call, reason) #else void grpc_call_internal_ref(grpc_call *call); void grpc_call_internal_unref(grpc_exec_ctx *exec_ctx, grpc_call *call); #define GRPC_CALL_INTERNAL_REF(call, reason) grpc_call_internal_ref(call) #define GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, reason) \ grpc_call_internal_unref(exec_ctx, call) #endif grpc_call_stack *grpc_call_get_call_stack(grpc_call *call); grpc_call_error grpc_call_start_batch_and_execute(grpc_exec_ctx *exec_ctx, grpc_call *call, const grpc_op *ops, size_t nops, grpc_closure *closure); /* Given the top call_element, get the call object. */ grpc_call *grpc_call_from_top_element(grpc_call_element *surface_element); void grpc_call_log_batch(char *file, int line, gpr_log_severity severity, grpc_call *call, const grpc_op *ops, size_t nops, void *tag); /* Set a context pointer. No thread safety guarantees are made wrt this value. */ /* TODO(#9731): add exec_ctx to destroy */ void grpc_call_context_set(grpc_call *call, grpc_context_index elem, void *value, void (*destroy)(void *value)); /* Get a context pointer. */ void *grpc_call_context_get(grpc_call *call, grpc_context_index elem); #define GRPC_CALL_LOG_BATCH(sev, call, ops, nops, tag) \ if (grpc_api_trace) grpc_call_log_batch(sev, call, ops, nops, tag) uint8_t grpc_call_is_client(grpc_call *call); /* Return an appropriate compression algorithm for the requested compression \a * level in the context of \a call. */ grpc_compression_algorithm grpc_call_compression_for_level( grpc_call *call, grpc_compression_level level); extern int grpc_call_error_trace; #ifdef __cplusplus } #endif #endif /* GRPC_CORE_LIB_SURFACE_CALL_H */ grpc-1.3.2/src/core/lib/surface/call_details.c000066400000000000000000000043731310511640000211470ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/surface/api_trace.h" void grpc_call_details_init(grpc_call_details* cd) { GRPC_API_TRACE("grpc_call_details_init(cd=%p)", 1, (cd)); memset(cd, 0, sizeof(*cd)); cd->method = grpc_empty_slice(); cd->host = grpc_empty_slice(); } void grpc_call_details_destroy(grpc_call_details* cd) { GRPC_API_TRACE("grpc_call_details_destroy(cd=%p)", 1, (cd)); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_slice_unref_internal(&exec_ctx, cd->method); grpc_slice_unref_internal(&exec_ctx, cd->host); grpc_exec_ctx_finish(&exec_ctx); } grpc-1.3.2/src/core/lib/surface/call_log_batch.c000066400000000000000000000116271310511640000214440ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/surface/call.h" #include #include #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/string.h" static void add_metadata(gpr_strvec *b, const grpc_metadata *md, size_t count) { size_t i; if (md == NULL) { gpr_strvec_add(b, gpr_strdup("(nil)")); return; } for (i = 0; i < count; i++) { gpr_strvec_add(b, gpr_strdup("\nkey=")); gpr_strvec_add(b, grpc_slice_to_c_string(md[i].key)); gpr_strvec_add(b, gpr_strdup(" value=")); gpr_strvec_add(b, grpc_dump_slice(md[i].value, GPR_DUMP_HEX | GPR_DUMP_ASCII)); } } char *grpc_op_string(const grpc_op *op) { char *tmp; char *out; gpr_strvec b; gpr_strvec_init(&b); switch (op->op) { case GRPC_OP_SEND_INITIAL_METADATA: gpr_strvec_add(&b, gpr_strdup("SEND_INITIAL_METADATA")); add_metadata(&b, op->data.send_initial_metadata.metadata, op->data.send_initial_metadata.count); break; case GRPC_OP_SEND_MESSAGE: gpr_asprintf(&tmp, "SEND_MESSAGE ptr=%p", op->data.send_message.send_message); gpr_strvec_add(&b, tmp); break; case GRPC_OP_SEND_CLOSE_FROM_CLIENT: gpr_strvec_add(&b, gpr_strdup("SEND_CLOSE_FROM_CLIENT")); break; case GRPC_OP_SEND_STATUS_FROM_SERVER: gpr_asprintf(&tmp, "SEND_STATUS_FROM_SERVER status=%d details=", op->data.send_status_from_server.status); gpr_strvec_add(&b, tmp); if (op->data.send_status_from_server.status_details != NULL) { gpr_strvec_add(&b, grpc_dump_slice( *op->data.send_status_from_server.status_details, GPR_DUMP_ASCII)); } else { gpr_strvec_add(&b, gpr_strdup("(null)")); } add_metadata(&b, op->data.send_status_from_server.trailing_metadata, op->data.send_status_from_server.trailing_metadata_count); break; case GRPC_OP_RECV_INITIAL_METADATA: gpr_asprintf(&tmp, "RECV_INITIAL_METADATA ptr=%p", op->data.recv_initial_metadata.recv_initial_metadata); gpr_strvec_add(&b, tmp); break; case GRPC_OP_RECV_MESSAGE: gpr_asprintf(&tmp, "RECV_MESSAGE ptr=%p", op->data.recv_message.recv_message); gpr_strvec_add(&b, tmp); break; case GRPC_OP_RECV_STATUS_ON_CLIENT: gpr_asprintf(&tmp, "RECV_STATUS_ON_CLIENT metadata=%p status=%p details=%p", op->data.recv_status_on_client.trailing_metadata, op->data.recv_status_on_client.status, op->data.recv_status_on_client.status_details); gpr_strvec_add(&b, tmp); break; case GRPC_OP_RECV_CLOSE_ON_SERVER: gpr_asprintf(&tmp, "RECV_CLOSE_ON_SERVER cancelled=%p", op->data.recv_close_on_server.cancelled); gpr_strvec_add(&b, tmp); } out = gpr_strvec_flatten(&b, NULL); gpr_strvec_destroy(&b); return out; } void grpc_call_log_batch(char *file, int line, gpr_log_severity severity, grpc_call *call, const grpc_op *ops, size_t nops, void *tag) { char *tmp; size_t i; for (i = 0; i < nops; i++) { tmp = grpc_op_string(&ops[i]); gpr_log(file, line, severity, "ops[%" PRIuPTR "]: %s", i, tmp); gpr_free(tmp); } } grpc-1.3.2/src/core/lib/surface/call_test_only.h000066400000000000000000000046161310511640000215470ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SURFACE_CALL_TEST_ONLY_H #define GRPC_CORE_LIB_SURFACE_CALL_TEST_ONLY_H #include #ifdef __cplusplus extern "C" { #endif /** Return the compression algorithm from \a call. * * \warning This function should \b only be used in test code. */ grpc_compression_algorithm grpc_call_test_only_get_compression_algorithm( grpc_call *call); /** Return the message flags from \a call. * * \warning This function should \b only be used in test code. */ uint32_t grpc_call_test_only_get_message_flags(grpc_call *call); /** Returns a bitset for the encodings (compression algorithms) supported by \a * call's peer. * * To be indexed by grpc_compression_algorithm enum values. */ uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call); #ifdef __cplusplus } #endif #endif /* GRPC_CORE_LIB_SURFACE_CALL_TEST_ONLY_H */ grpc-1.3.2/src/core/lib/surface/channel.c000066400000000000000000000426731310511640000201440ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/surface/channel.h" #include #include #include #include #include #include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/support/string.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/call.h" #include "src/core/lib/surface/channel_init.h" #include "src/core/lib/transport/static_metadata.h" /** Cache grpc-status: X mdelems for X = 0..NUM_CACHED_STATUS_ELEMS. * Avoids needing to take a metadata context lock for sending status * if the status code is <= NUM_CACHED_STATUS_ELEMS. * Sized to allow the most commonly used codes to fit in * (OK, Cancelled, Unknown). */ #define NUM_CACHED_STATUS_ELEMS 3 typedef struct registered_call { grpc_mdelem path; grpc_mdelem authority; struct registered_call *next; } registered_call; struct grpc_channel { int is_client; grpc_compression_options compression_options; grpc_mdelem default_authority; gpr_atm call_size_estimate; gpr_mu registered_call_mu; registered_call *registered_calls; char *target; }; #define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack *)((c) + 1)) #define CHANNEL_FROM_CHANNEL_STACK(channel_stack) \ (((grpc_channel *)(channel_stack)) - 1) #define CHANNEL_FROM_TOP_ELEM(top_elem) \ CHANNEL_FROM_CHANNEL_STACK(grpc_channel_stack_from_top_element(top_elem)) static void destroy_channel(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); grpc_channel *grpc_channel_create_with_builder( grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, grpc_channel_stack_type channel_stack_type) { char *target = gpr_strdup(grpc_channel_stack_builder_get_target(builder)); grpc_channel_args *args = grpc_channel_args_copy( grpc_channel_stack_builder_get_channel_arguments(builder)); grpc_channel *channel; grpc_error *error = grpc_channel_stack_builder_finish( exec_ctx, builder, sizeof(grpc_channel), 1, destroy_channel, NULL, (void **)&channel); if (error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "channel stack builder failed: %s", grpc_error_string(error)); GRPC_ERROR_UNREF(error); gpr_free(target); goto done; } memset(channel, 0, sizeof(*channel)); channel->target = target; channel->is_client = grpc_channel_stack_type_is_client(channel_stack_type); gpr_mu_init(&channel->registered_call_mu); channel->registered_calls = NULL; gpr_atm_no_barrier_store( &channel->call_size_estimate, (gpr_atm)CHANNEL_STACK_FROM_CHANNEL(channel)->call_stack_size); grpc_compression_options_init(&channel->compression_options); for (size_t i = 0; i < args->num_args; i++) { if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) { if (args->args[i].type != GRPC_ARG_STRING) { gpr_log(GPR_ERROR, "%s ignored: it must be a string", GRPC_ARG_DEFAULT_AUTHORITY); } else { if (!GRPC_MDISNULL(channel->default_authority)) { /* setting this takes precedence over anything else */ GRPC_MDELEM_UNREF(exec_ctx, channel->default_authority); } channel->default_authority = grpc_mdelem_from_slices( exec_ctx, GRPC_MDSTR_AUTHORITY, grpc_slice_intern( grpc_slice_from_static_string(args->args[i].value.string))); } } else if (0 == strcmp(args->args[i].key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) { if (args->args[i].type != GRPC_ARG_STRING) { gpr_log(GPR_ERROR, "%s ignored: it must be a string", GRPC_SSL_TARGET_NAME_OVERRIDE_ARG); } else { if (!GRPC_MDISNULL(channel->default_authority)) { /* other ways of setting this (notably ssl) take precedence */ gpr_log(GPR_ERROR, "%s ignored: default host already set some other way", GRPC_SSL_TARGET_NAME_OVERRIDE_ARG); } else { channel->default_authority = grpc_mdelem_from_slices( exec_ctx, GRPC_MDSTR_AUTHORITY, grpc_slice_intern( grpc_slice_from_static_string(args->args[i].value.string))); } } } else if (0 == strcmp(args->args[i].key, GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL)) { channel->compression_options.default_level.is_set = true; channel->compression_options.default_level.level = (grpc_compression_level)grpc_channel_arg_get_integer( &args->args[i], (grpc_integer_options){GRPC_COMPRESS_LEVEL_NONE, GRPC_COMPRESS_LEVEL_NONE, GRPC_COMPRESS_LEVEL_COUNT - 1}); } else if (0 == strcmp(args->args[i].key, GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM)) { channel->compression_options.default_algorithm.is_set = true; channel->compression_options.default_algorithm.algorithm = (grpc_compression_algorithm)grpc_channel_arg_get_integer( &args->args[i], (grpc_integer_options){GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_ALGORITHMS_COUNT - 1}); } else if (0 == strcmp(args->args[i].key, GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET)) { channel->compression_options.enabled_algorithms_bitset = (uint32_t)args->args[i].value.integer | 0x1; /* always support no compression */ } } done: grpc_channel_args_destroy(exec_ctx, args); return channel; } grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target, const grpc_channel_args *input_args, grpc_channel_stack_type channel_stack_type, grpc_transport *optional_transport) { grpc_channel_stack_builder *builder = grpc_channel_stack_builder_create(); grpc_channel_stack_builder_set_channel_arguments(exec_ctx, builder, input_args); grpc_channel_stack_builder_set_target(builder, target); grpc_channel_stack_builder_set_transport(builder, optional_transport); if (!grpc_channel_init_create_stack(exec_ctx, builder, channel_stack_type)) { grpc_channel_stack_builder_destroy(exec_ctx, builder); return NULL; } return grpc_channel_create_with_builder(exec_ctx, builder, channel_stack_type); } size_t grpc_channel_get_call_size_estimate(grpc_channel *channel) { #define ROUND_UP_SIZE 256 /* We round up our current estimate to the NEXT value of ROUND_UP_SIZE. This ensures: 1. a consistent size allocation when our estimate is drifting slowly (which is common) - which tends to help most allocators reuse memory 2. a small amount of allowed growth over the estimate without hitting the arena size doubling case, reducing overall memory usage */ return ((size_t)gpr_atm_no_barrier_load(&channel->call_size_estimate) + 2 * ROUND_UP_SIZE) & ~(size_t)(ROUND_UP_SIZE - 1); } void grpc_channel_update_call_size_estimate(grpc_channel *channel, size_t size) { size_t cur = (size_t)gpr_atm_no_barrier_load(&channel->call_size_estimate); if (cur < size) { /* size grew: update estimate */ gpr_atm_no_barrier_cas(&channel->call_size_estimate, (gpr_atm)cur, (gpr_atm)size); /* if we lose: never mind, something else will likely update soon enough */ } else if (cur == size) { /* no change: holding pattern */ } else if (cur > 0) { /* size shrank: decrease estimate */ gpr_atm_no_barrier_cas( &channel->call_size_estimate, (gpr_atm)cur, (gpr_atm)(GPR_MIN(cur - 1, (255 * cur + size) / 256))); /* if we lose: never mind, something else will likely update soon enough */ } } char *grpc_channel_get_target(grpc_channel *channel) { GRPC_API_TRACE("grpc_channel_get_target(channel=%p)", 1, (channel)); return gpr_strdup(channel->target); } void grpc_channel_get_info(grpc_channel *channel, const grpc_channel_info *channel_info) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_channel_element *elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0); elem->filter->get_channel_info(&exec_ctx, elem, channel_info); grpc_exec_ctx_finish(&exec_ctx); } static grpc_call *grpc_channel_create_call_internal( grpc_exec_ctx *exec_ctx, grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_completion_queue *cq, grpc_pollset_set *pollset_set_alternative, grpc_mdelem path_mdelem, grpc_mdelem authority_mdelem, gpr_timespec deadline) { grpc_mdelem send_metadata[2]; size_t num_metadata = 0; GPR_ASSERT(channel->is_client); GPR_ASSERT(!(cq != NULL && pollset_set_alternative != NULL)); send_metadata[num_metadata++] = path_mdelem; if (!GRPC_MDISNULL(authority_mdelem)) { send_metadata[num_metadata++] = authority_mdelem; } else if (!GRPC_MDISNULL(channel->default_authority)) { send_metadata[num_metadata++] = GRPC_MDELEM_REF(channel->default_authority); } grpc_call_create_args args; memset(&args, 0, sizeof(args)); args.channel = channel; args.parent_call = parent_call; args.propagation_mask = propagation_mask; args.cq = cq; args.pollset_set_alternative = pollset_set_alternative; args.server_transport_data = NULL; args.add_initial_metadata = send_metadata; args.add_initial_metadata_count = num_metadata; args.send_deadline = deadline; grpc_call *call; GRPC_LOG_IF_ERROR("call_create", grpc_call_create(exec_ctx, &args, &call)); return call; } grpc_call *grpc_channel_create_call(grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_completion_queue *cq, grpc_slice method, const grpc_slice *host, gpr_timespec deadline, void *reserved) { GPR_ASSERT(!reserved); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_call *call = grpc_channel_create_call_internal( &exec_ctx, channel, parent_call, propagation_mask, cq, NULL, grpc_mdelem_from_slices(&exec_ctx, GRPC_MDSTR_PATH, grpc_slice_ref_internal(method)), host != NULL ? grpc_mdelem_from_slices(&exec_ctx, GRPC_MDSTR_AUTHORITY, grpc_slice_ref_internal(*host)) : GRPC_MDNULL, deadline); grpc_exec_ctx_finish(&exec_ctx); return call; } grpc_call *grpc_channel_create_pollset_set_call( grpc_exec_ctx *exec_ctx, grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_pollset_set *pollset_set, grpc_slice method, const grpc_slice *host, gpr_timespec deadline, void *reserved) { GPR_ASSERT(!reserved); return grpc_channel_create_call_internal( exec_ctx, channel, parent_call, propagation_mask, NULL, pollset_set, grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_PATH, grpc_slice_ref_internal(method)), host != NULL ? grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_AUTHORITY, grpc_slice_ref_internal(*host)) : GRPC_MDNULL, deadline); } void *grpc_channel_register_call(grpc_channel *channel, const char *method, const char *host, void *reserved) { registered_call *rc = gpr_malloc(sizeof(registered_call)); GRPC_API_TRACE( "grpc_channel_register_call(channel=%p, method=%s, host=%s, reserved=%p)", 4, (channel, method, host, reserved)); GPR_ASSERT(!reserved); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; rc->path = grpc_mdelem_from_slices( &exec_ctx, GRPC_MDSTR_PATH, grpc_slice_intern(grpc_slice_from_static_string(method))); rc->authority = host ? grpc_mdelem_from_slices( &exec_ctx, GRPC_MDSTR_AUTHORITY, grpc_slice_intern(grpc_slice_from_static_string(host))) : GRPC_MDNULL; gpr_mu_lock(&channel->registered_call_mu); rc->next = channel->registered_calls; channel->registered_calls = rc; gpr_mu_unlock(&channel->registered_call_mu); grpc_exec_ctx_finish(&exec_ctx); return rc; } grpc_call *grpc_channel_create_registered_call( grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_completion_queue *completion_queue, void *registered_call_handle, gpr_timespec deadline, void *reserved) { registered_call *rc = registered_call_handle; GRPC_API_TRACE( "grpc_channel_create_registered_call(" "channel=%p, parent_call=%p, propagation_mask=%x, completion_queue=%p, " "registered_call_handle=%p, " "deadline=gpr_timespec { tv_sec: %" PRId64 ", tv_nsec: %d, clock_type: %d }, " "reserved=%p)", 9, (channel, parent_call, (unsigned)propagation_mask, completion_queue, registered_call_handle, deadline.tv_sec, deadline.tv_nsec, (int)deadline.clock_type, reserved)); GPR_ASSERT(!reserved); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_call *call = grpc_channel_create_call_internal( &exec_ctx, channel, parent_call, propagation_mask, completion_queue, NULL, GRPC_MDELEM_REF(rc->path), GRPC_MDELEM_REF(rc->authority), deadline); grpc_exec_ctx_finish(&exec_ctx); return call; } #ifdef GRPC_STREAM_REFCOUNT_DEBUG #define REF_REASON reason #define REF_ARG , const char *reason #else #define REF_REASON "" #define REF_ARG #endif void grpc_channel_internal_ref(grpc_channel *c REF_ARG) { GRPC_CHANNEL_STACK_REF(CHANNEL_STACK_FROM_CHANNEL(c), REF_REASON); } void grpc_channel_internal_unref(grpc_exec_ctx *exec_ctx, grpc_channel *c REF_ARG) { GRPC_CHANNEL_STACK_UNREF(exec_ctx, CHANNEL_STACK_FROM_CHANNEL(c), REF_REASON); } static void destroy_channel(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_channel *channel = arg; grpc_channel_stack_destroy(exec_ctx, CHANNEL_STACK_FROM_CHANNEL(channel)); while (channel->registered_calls) { registered_call *rc = channel->registered_calls; channel->registered_calls = rc->next; GRPC_MDELEM_UNREF(exec_ctx, rc->path); GRPC_MDELEM_UNREF(exec_ctx, rc->authority); gpr_free(rc); } GRPC_MDELEM_UNREF(exec_ctx, channel->default_authority); gpr_mu_destroy(&channel->registered_call_mu); gpr_free(channel->target); gpr_free(channel); } void grpc_channel_destroy(grpc_channel *channel) { grpc_transport_op *op = grpc_make_transport_op(NULL); grpc_channel_element *elem; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE("grpc_channel_destroy(channel=%p)", 1, (channel)); op->disconnect_with_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel Destroyed"); elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0); elem->filter->start_transport_op(&exec_ctx, elem, op); GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, channel, "channel"); grpc_exec_ctx_finish(&exec_ctx); } grpc_channel_stack *grpc_channel_get_channel_stack(grpc_channel *channel) { return CHANNEL_STACK_FROM_CHANNEL(channel); } grpc_compression_options grpc_channel_compression_options( const grpc_channel *channel) { return channel->compression_options; } grpc_mdelem grpc_channel_get_reffed_status_elem(grpc_exec_ctx *exec_ctx, grpc_channel *channel, int i) { char tmp[GPR_LTOA_MIN_BUFSIZE]; switch (i) { case 0: return GRPC_MDELEM_GRPC_STATUS_0; case 1: return GRPC_MDELEM_GRPC_STATUS_1; case 2: return GRPC_MDELEM_GRPC_STATUS_2; } gpr_ltoa(i, tmp); return grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_STATUS, grpc_slice_from_copied_string(tmp)); } grpc-1.3.2/src/core/lib/surface/channel.h000066400000000000000000000113401310511640000201340ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SURFACE_CHANNEL_H #define GRPC_CORE_LIB_SURFACE_CHANNEL_H #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/surface/channel_stack_type.h" grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target, const grpc_channel_args *args, grpc_channel_stack_type channel_stack_type, grpc_transport *optional_transport); grpc_channel *grpc_channel_create_with_builder( grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, grpc_channel_stack_type channel_stack_type); /** Create a call given a grpc_channel, in order to call \a method. Progress is tied to activity on \a pollset_set. The returned call object is meant to be used with \a grpc_call_start_batch_and_execute, which relies on callbacks to signal completions. \a method and \a host need only live through the invocation of this function. If \a parent_call is non-NULL, it must be a server-side call. It will be used to propagate properties from the server call to this new client call, depending on the value of \a propagation_mask (see propagation_bits.h for possible values) */ grpc_call *grpc_channel_create_pollset_set_call( grpc_exec_ctx *exec_ctx, grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_pollset_set *pollset_set, grpc_slice method, const grpc_slice *host, gpr_timespec deadline, void *reserved); /** Get a (borrowed) pointer to this channels underlying channel stack */ grpc_channel_stack *grpc_channel_get_channel_stack(grpc_channel *channel); /** Get a grpc_mdelem of grpc-status: X where X is the numeric value of status_code. The returned elem is owned by the caller. */ grpc_mdelem grpc_channel_get_reffed_status_elem(grpc_exec_ctx *exec_ctx, grpc_channel *channel, int status_code); size_t grpc_channel_get_call_size_estimate(grpc_channel *channel); void grpc_channel_update_call_size_estimate(grpc_channel *channel, size_t size); #ifdef GRPC_STREAM_REFCOUNT_DEBUG void grpc_channel_internal_ref(grpc_channel *channel, const char *reason); void grpc_channel_internal_unref(grpc_exec_ctx *exec_ctx, grpc_channel *channel, const char *reason); #define GRPC_CHANNEL_INTERNAL_REF(channel, reason) \ grpc_channel_internal_ref(channel, reason) #define GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, reason) \ grpc_channel_internal_unref(exec_ctx, channel, reason) #else void grpc_channel_internal_ref(grpc_channel *channel); void grpc_channel_internal_unref(grpc_exec_ctx *exec_ctx, grpc_channel *channel); #define GRPC_CHANNEL_INTERNAL_REF(channel, reason) \ grpc_channel_internal_ref(channel) #define GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, reason) \ grpc_channel_internal_unref(exec_ctx, channel) #endif /** Return the channel's compression options. */ grpc_compression_options grpc_channel_compression_options( const grpc_channel *channel); #endif /* GRPC_CORE_LIB_SURFACE_CHANNEL_H */ grpc-1.3.2/src/core/lib/surface/channel_init.c000066400000000000000000000111161310511640000211530ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/surface/channel_init.h" #include #include typedef struct stage_slot { grpc_channel_init_stage fn; void *arg; int priority; size_t insertion_order; } stage_slot; typedef struct stage_slots { stage_slot *slots; size_t num_slots; size_t cap_slots; } stage_slots; static stage_slots g_slots[GRPC_NUM_CHANNEL_STACK_TYPES]; static bool g_finalized; void grpc_channel_init_init(void) { for (int i = 0; i < GRPC_NUM_CHANNEL_STACK_TYPES; i++) { g_slots[i].slots = NULL; g_slots[i].num_slots = 0; g_slots[i].cap_slots = 0; } g_finalized = false; } void grpc_channel_init_register_stage(grpc_channel_stack_type type, int priority, grpc_channel_init_stage stage, void *stage_arg) { GPR_ASSERT(!g_finalized); if (g_slots[type].cap_slots == g_slots[type].num_slots) { g_slots[type].cap_slots = GPR_MAX(8, 3 * g_slots[type].cap_slots / 2); g_slots[type].slots = gpr_realloc(g_slots[type].slots, g_slots[type].cap_slots * sizeof(*g_slots[type].slots)); } stage_slot *s = &g_slots[type].slots[g_slots[type].num_slots++]; s->insertion_order = g_slots[type].num_slots; s->priority = priority; s->fn = stage; s->arg = stage_arg; } static int compare_slots(const void *a, const void *b) { const stage_slot *sa = a; const stage_slot *sb = b; int c = GPR_ICMP(sa->priority, sb->priority); if (c != 0) return c; return GPR_ICMP(sa->insertion_order, sb->insertion_order); } void grpc_channel_init_finalize(void) { GPR_ASSERT(!g_finalized); for (int i = 0; i < GRPC_NUM_CHANNEL_STACK_TYPES; i++) { qsort(g_slots[i].slots, g_slots[i].num_slots, sizeof(*g_slots[i].slots), compare_slots); } g_finalized = true; } void grpc_channel_init_shutdown(void) { for (int i = 0; i < GRPC_NUM_CHANNEL_STACK_TYPES; i++) { gpr_free(g_slots[i].slots); g_slots[i].slots = (void *)(uintptr_t)0xdeadbeef; } } static const char *name_for_type(grpc_channel_stack_type type) { switch (type) { case GRPC_CLIENT_CHANNEL: return "CLIENT_CHANNEL"; case GRPC_CLIENT_SUBCHANNEL: return "CLIENT_SUBCHANNEL"; case GRPC_SERVER_CHANNEL: return "SERVER_CHANNEL"; case GRPC_CLIENT_LAME_CHANNEL: return "CLIENT_LAME_CHANNEL"; case GRPC_CLIENT_DIRECT_CHANNEL: return "CLIENT_DIRECT_CHANNEL"; case GRPC_NUM_CHANNEL_STACK_TYPES: break; } GPR_UNREACHABLE_CODE(return "UNKNOWN"); } bool grpc_channel_init_create_stack(grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, grpc_channel_stack_type type) { GPR_ASSERT(g_finalized); grpc_channel_stack_builder_set_name(builder, name_for_type(type)); for (size_t i = 0; i < g_slots[type].num_slots; i++) { const stage_slot *slot = &g_slots[type].slots[i]; if (!slot->fn(exec_ctx, builder, slot->arg)) { return false; } } return true; } grpc-1.3.2/src/core/lib/surface/channel_init.h000066400000000000000000000102131310511640000211550ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SURFACE_CHANNEL_INIT_H #define GRPC_CORE_LIB_SURFACE_CHANNEL_INIT_H #include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/surface/channel_stack_type.h" #include "src/core/lib/transport/transport.h" #define GRPC_CHANNEL_INIT_BUILTIN_PRIORITY 10000 #ifdef __cplusplus extern "C" { #endif /// This module provides a way for plugins (and the grpc core library itself) /// to register mutators for channel stacks. /// It also provides a universal entry path to run those mutators to build /// a channel stack for various subsystems. /// One stage of mutation: call functions against \a builder to influence the /// finally constructed channel stack typedef bool (*grpc_channel_init_stage)(grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, void *arg); /// Global initialization of the system void grpc_channel_init_init(void); /// Register one stage of mutators. /// Stages are run in priority order (lowest to highest), and then in /// registration order (in the case of a tie). /// Stages are registered against one of the pre-determined channel stack /// types. void grpc_channel_init_register_stage(grpc_channel_stack_type type, int priority, grpc_channel_init_stage stage_fn, void *stage_arg); /// Finalize registration. No more calls to grpc_channel_init_register_stage are /// allowed. void grpc_channel_init_finalize(void); /// Shutdown the channel init system void grpc_channel_init_shutdown(void); /// Construct a channel stack of some sort: see channel_stack.h for details /// \a type is the type of channel stack to create /// \a prefix_bytes is the number of bytes before the channel stack to allocate /// \a args are configuration arguments for the channel stack /// \a initial_refs is the initial refcount to give the channel stack /// \a destroy and \a destroy_arg specify how to destroy the channel stack /// if destroy_arg is NULL, the returned value from this function will be /// substituted /// \a optional_transport is either NULL or a constructed transport object /// Returns a pointer to the base of the memory allocated (the actual channel /// stack object will be prefix_bytes past that pointer) bool grpc_channel_init_create_stack(grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, grpc_channel_stack_type type); #ifdef __cplusplus } #endif #endif /* GRPC_CORE_LIB_SURFACE_CHANNEL_INIT_H */ grpc-1.3.2/src/core/lib/surface/channel_ping.c000066400000000000000000000061361310511640000211530ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/surface/channel.h" #include #include #include #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/completion_queue.h" typedef struct { grpc_closure closure; void *tag; grpc_completion_queue *cq; grpc_cq_completion completion_storage; } ping_result; static void ping_destroy(grpc_exec_ctx *exec_ctx, void *arg, grpc_cq_completion *storage) { gpr_free(arg); } static void ping_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { ping_result *pr = arg; grpc_cq_end_op(exec_ctx, pr->cq, pr->tag, GRPC_ERROR_REF(error), ping_destroy, pr, &pr->completion_storage); } void grpc_channel_ping(grpc_channel *channel, grpc_completion_queue *cq, void *tag, void *reserved) { GRPC_API_TRACE("grpc_channel_ping(channel=%p, cq=%p, tag=%p, reserved=%p)", 4, (channel, cq, tag, reserved)); grpc_transport_op *op = grpc_make_transport_op(NULL); ping_result *pr = gpr_malloc(sizeof(*pr)); grpc_channel_element *top_elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GPR_ASSERT(reserved == NULL); pr->tag = tag; pr->cq = cq; grpc_closure_init(&pr->closure, ping_done, pr, grpc_schedule_on_exec_ctx); op->send_ping = &pr->closure; op->bind_pollset = grpc_cq_pollset(cq); grpc_cq_begin_op(cq, tag); top_elem->filter->start_transport_op(&exec_ctx, top_elem, op); grpc_exec_ctx_finish(&exec_ctx); } grpc-1.3.2/src/core/lib/surface/channel_stack_type.c000066400000000000000000000041341310511640000223600ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/surface/channel_stack_type.h" #include #include bool grpc_channel_stack_type_is_client(grpc_channel_stack_type type) { switch (type) { case GRPC_CLIENT_CHANNEL: return true; case GRPC_CLIENT_SUBCHANNEL: return true; case GRPC_CLIENT_LAME_CHANNEL: return true; case GRPC_CLIENT_DIRECT_CHANNEL: return true; case GRPC_SERVER_CHANNEL: return false; case GRPC_NUM_CHANNEL_STACK_TYPES: break; } GPR_UNREACHABLE_CODE(return true;); } grpc-1.3.2/src/core/lib/surface/channel_stack_type.h000066400000000000000000000045521310511640000223710ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SURFACE_CHANNEL_STACK_TYPE_H #define GRPC_CORE_LIB_SURFACE_CHANNEL_STACK_TYPE_H #include typedef enum { // normal top-half client channel with load-balancing, connection management GRPC_CLIENT_CHANNEL, // bottom-half of a client channel: everything that happens post-load // balancing (bound to a specific transport) GRPC_CLIENT_SUBCHANNEL, // a permanently broken client channel GRPC_CLIENT_LAME_CHANNEL, // a directly connected client channel (without load-balancing, directly talks // to a transport) GRPC_CLIENT_DIRECT_CHANNEL, // server side channel GRPC_SERVER_CHANNEL, // must be last GRPC_NUM_CHANNEL_STACK_TYPES } grpc_channel_stack_type; bool grpc_channel_stack_type_is_client(grpc_channel_stack_type type); #endif /* GRPC_CORE_LIB_SURFACE_CHANNEL_STACK_TYPE_H */ grpc-1.3.2/src/core/lib/surface/completion_queue.c000066400000000000000000000555701310511640000221110ustar00rootroot00000000000000/* * * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/surface/completion_queue.h" #include #include #include #include #include #include #include #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/support/string.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/call.h" #include "src/core/lib/surface/event_string.h" int grpc_trace_operation_failures; #ifndef NDEBUG int grpc_trace_pending_tags; #endif typedef struct { grpc_pollset_worker **worker; void *tag; } plucker; /* Completion queue structure */ struct grpc_completion_queue { /** owned by pollset */ gpr_mu *mu; /** completed events */ grpc_cq_completion completed_head; grpc_cq_completion *completed_tail; /** Number of pending events (+1 if we're not shutdown) */ gpr_refcount pending_events; /** Once owning_refs drops to zero, we will destroy the cq */ gpr_refcount owning_refs; /** counter of how many things have ever been queued on this completion queue useful for avoiding locks to check the queue */ gpr_atm things_queued_ever; /** 0 initially, 1 once we've begun shutting down */ int shutdown; int shutdown_called; int is_server_cq; /** Can the server cq accept incoming channels */ int is_non_listening_server_cq; int num_pluckers; plucker pluckers[GRPC_MAX_COMPLETION_QUEUE_PLUCKERS]; grpc_closure pollset_shutdown_done; #ifndef NDEBUG void **outstanding_tags; size_t outstanding_tag_count; size_t outstanding_tag_capacity; #endif grpc_completion_queue *next_free; }; #define POLLSET_FROM_CQ(cq) ((grpc_pollset *)(cq + 1)) #define CQ_FROM_POLLSET(ps) (((grpc_completion_queue *)ps) - 1) int grpc_cq_pluck_trace; int grpc_cq_event_timeout_trace; #define GRPC_SURFACE_TRACE_RETURNED_EVENT(cq, event) \ if (grpc_api_trace && \ (grpc_cq_pluck_trace || (event)->type != GRPC_QUEUE_TIMEOUT)) { \ char *_ev = grpc_event_string(event); \ gpr_log(GPR_INFO, "RETURN_EVENT[%p]: %s", cq, _ev); \ gpr_free(_ev); \ } static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *cc, grpc_error *error); grpc_completion_queue *grpc_completion_queue_create(void *reserved) { grpc_completion_queue *cc; GPR_ASSERT(!reserved); GPR_TIMER_BEGIN("grpc_completion_queue_create", 0); GRPC_API_TRACE("grpc_completion_queue_create(reserved=%p)", 1, (reserved)); cc = gpr_zalloc(sizeof(grpc_completion_queue) + grpc_pollset_size()); grpc_pollset_init(POLLSET_FROM_CQ(cc), &cc->mu); #ifndef NDEBUG cc->outstanding_tags = NULL; cc->outstanding_tag_capacity = 0; #endif /* Initial ref is dropped by grpc_completion_queue_shutdown */ gpr_ref_init(&cc->pending_events, 1); /* One for destroy(), one for pollset_shutdown */ gpr_ref_init(&cc->owning_refs, 2); cc->completed_tail = &cc->completed_head; cc->completed_head.next = (uintptr_t)cc->completed_tail; cc->shutdown = 0; cc->shutdown_called = 0; cc->is_server_cq = 0; cc->is_non_listening_server_cq = 0; cc->num_pluckers = 0; gpr_atm_no_barrier_store(&cc->things_queued_ever, 0); #ifndef NDEBUG cc->outstanding_tag_count = 0; #endif grpc_closure_init(&cc->pollset_shutdown_done, on_pollset_shutdown_done, cc, grpc_schedule_on_exec_ctx); GPR_TIMER_END("grpc_completion_queue_create", 0); return cc; } #ifdef GRPC_CQ_REF_COUNT_DEBUG void grpc_cq_internal_ref(grpc_completion_queue *cc, const char *reason, const char *file, int line) { gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p ref %d -> %d %s", cc, (int)cc->owning_refs.count, (int)cc->owning_refs.count + 1, reason); #else void grpc_cq_internal_ref(grpc_completion_queue *cc) { #endif gpr_ref(&cc->owning_refs); } static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_completion_queue *cc = arg; GRPC_CQ_INTERNAL_UNREF(cc, "pollset_destroy"); } #ifdef GRPC_CQ_REF_COUNT_DEBUG void grpc_cq_internal_unref(grpc_completion_queue *cc, const char *reason, const char *file, int line) { gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p unref %d -> %d %s", cc, (int)cc->owning_refs.count, (int)cc->owning_refs.count - 1, reason); #else void grpc_cq_internal_unref(grpc_completion_queue *cc) { #endif if (gpr_unref(&cc->owning_refs)) { GPR_ASSERT(cc->completed_head.next == (uintptr_t)&cc->completed_head); grpc_pollset_destroy(POLLSET_FROM_CQ(cc)); #ifndef NDEBUG gpr_free(cc->outstanding_tags); #endif gpr_free(cc); } } void grpc_cq_begin_op(grpc_completion_queue *cc, void *tag) { #ifndef NDEBUG gpr_mu_lock(cc->mu); GPR_ASSERT(!cc->shutdown_called); if (cc->outstanding_tag_count == cc->outstanding_tag_capacity) { cc->outstanding_tag_capacity = GPR_MAX(4, 2 * cc->outstanding_tag_capacity); cc->outstanding_tags = gpr_realloc(cc->outstanding_tags, sizeof(*cc->outstanding_tags) * cc->outstanding_tag_capacity); } cc->outstanding_tags[cc->outstanding_tag_count++] = tag; gpr_mu_unlock(cc->mu); #endif gpr_ref(&cc->pending_events); } /* Signal the end of an operation - if this is the last waiting-to-be-queued event, then enter shutdown mode */ /* Queue a GRPC_OP_COMPLETED operation */ void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc, void *tag, grpc_error *error, void (*done)(grpc_exec_ctx *exec_ctx, void *done_arg, grpc_cq_completion *storage), void *done_arg, grpc_cq_completion *storage) { int shutdown; int i; grpc_pollset_worker *pluck_worker; #ifndef NDEBUG int found = 0; #endif GPR_TIMER_BEGIN("grpc_cq_end_op", 0); if (grpc_api_trace || (grpc_trace_operation_failures && error != GRPC_ERROR_NONE)) { const char *errmsg = grpc_error_string(error); GRPC_API_TRACE( "grpc_cq_end_op(exec_ctx=%p, cc=%p, tag=%p, error=%s, done=%p, " "done_arg=%p, storage=%p)", 7, (exec_ctx, cc, tag, errmsg, done, done_arg, storage)); if (grpc_trace_operation_failures && error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Operation failed: tag=%p, error=%s", tag, errmsg); } } storage->tag = tag; storage->done = done; storage->done_arg = done_arg; storage->next = ((uintptr_t)&cc->completed_head) | ((uintptr_t)(error == GRPC_ERROR_NONE)); gpr_mu_lock(cc->mu); #ifndef NDEBUG for (i = 0; i < (int)cc->outstanding_tag_count; i++) { if (cc->outstanding_tags[i] == tag) { cc->outstanding_tag_count--; GPR_SWAP(void *, cc->outstanding_tags[i], cc->outstanding_tags[cc->outstanding_tag_count]); found = 1; break; } } GPR_ASSERT(found); #endif shutdown = gpr_unref(&cc->pending_events); gpr_atm_no_barrier_fetch_add(&cc->things_queued_ever, 1); if (!shutdown) { cc->completed_tail->next = ((uintptr_t)storage) | (1u & (uintptr_t)cc->completed_tail->next); cc->completed_tail = storage; pluck_worker = NULL; for (i = 0; i < cc->num_pluckers; i++) { if (cc->pluckers[i].tag == tag) { pluck_worker = *cc->pluckers[i].worker; break; } } grpc_error *kick_error = grpc_pollset_kick(POLLSET_FROM_CQ(cc), pluck_worker); gpr_mu_unlock(cc->mu); if (kick_error != GRPC_ERROR_NONE) { const char *msg = grpc_error_string(kick_error); gpr_log(GPR_ERROR, "Kick failed: %s", msg); GRPC_ERROR_UNREF(kick_error); } } else { cc->completed_tail->next = ((uintptr_t)storage) | (1u & (uintptr_t)cc->completed_tail->next); cc->completed_tail = storage; GPR_ASSERT(!cc->shutdown); GPR_ASSERT(cc->shutdown_called); cc->shutdown = 1; grpc_pollset_shutdown(exec_ctx, POLLSET_FROM_CQ(cc), &cc->pollset_shutdown_done); gpr_mu_unlock(cc->mu); } GPR_TIMER_END("grpc_cq_end_op", 0); GRPC_ERROR_UNREF(error); } typedef struct { gpr_atm last_seen_things_queued_ever; grpc_completion_queue *cq; gpr_timespec deadline; grpc_cq_completion *stolen_completion; void *tag; /* for pluck */ bool first_loop; } cq_is_finished_arg; static bool cq_is_next_finished(grpc_exec_ctx *exec_ctx, void *arg) { cq_is_finished_arg *a = arg; grpc_completion_queue *cq = a->cq; GPR_ASSERT(a->stolen_completion == NULL); gpr_atm current_last_seen_things_queued_ever = gpr_atm_no_barrier_load(&cq->things_queued_ever); if (current_last_seen_things_queued_ever != a->last_seen_things_queued_ever) { gpr_mu_lock(cq->mu); a->last_seen_things_queued_ever = gpr_atm_no_barrier_load(&cq->things_queued_ever); if (cq->completed_tail != &cq->completed_head) { a->stolen_completion = (grpc_cq_completion *)cq->completed_head.next; cq->completed_head.next = a->stolen_completion->next & ~(uintptr_t)1; if (a->stolen_completion == cq->completed_tail) { cq->completed_tail = &cq->completed_head; } gpr_mu_unlock(cq->mu); return true; } gpr_mu_unlock(cq->mu); } return !a->first_loop && gpr_time_cmp(a->deadline, gpr_now(a->deadline.clock_type)) < 0; } #ifndef NDEBUG static void dump_pending_tags(grpc_completion_queue *cc) { if (!grpc_trace_pending_tags) return; gpr_strvec v; gpr_strvec_init(&v); gpr_strvec_add(&v, gpr_strdup("PENDING TAGS:")); gpr_mu_lock(cc->mu); for (size_t i = 0; i < cc->outstanding_tag_count; i++) { char *s; gpr_asprintf(&s, " %p", cc->outstanding_tags[i]); gpr_strvec_add(&v, s); } gpr_mu_unlock(cc->mu); char *out = gpr_strvec_flatten(&v, NULL); gpr_strvec_destroy(&v); gpr_log(GPR_DEBUG, "%s", out); gpr_free(out); } #else static void dump_pending_tags(grpc_completion_queue *cc) {} #endif grpc_event grpc_completion_queue_next(grpc_completion_queue *cc, gpr_timespec deadline, void *reserved) { grpc_event ret; gpr_timespec now; GPR_TIMER_BEGIN("grpc_completion_queue_next", 0); GRPC_API_TRACE( "grpc_completion_queue_next(" "cc=%p, " "deadline=gpr_timespec { tv_sec: %" PRId64 ", tv_nsec: %d, clock_type: %d }, " "reserved=%p)", 5, (cc, deadline.tv_sec, deadline.tv_nsec, (int)deadline.clock_type, reserved)); GPR_ASSERT(!reserved); dump_pending_tags(cc); deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC); GRPC_CQ_INTERNAL_REF(cc, "next"); gpr_mu_lock(cc->mu); cq_is_finished_arg is_finished_arg = { .last_seen_things_queued_ever = gpr_atm_no_barrier_load(&cc->things_queued_ever), .cq = cc, .deadline = deadline, .stolen_completion = NULL, .tag = NULL, .first_loop = true}; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INITIALIZER(0, cq_is_next_finished, &is_finished_arg); for (;;) { if (is_finished_arg.stolen_completion != NULL) { gpr_mu_unlock(cc->mu); grpc_cq_completion *c = is_finished_arg.stolen_completion; is_finished_arg.stolen_completion = NULL; ret.type = GRPC_OP_COMPLETE; ret.success = c->next & 1u; ret.tag = c->tag; c->done(&exec_ctx, c->done_arg, c); break; } if (cc->completed_tail != &cc->completed_head) { grpc_cq_completion *c = (grpc_cq_completion *)cc->completed_head.next; cc->completed_head.next = c->next & ~(uintptr_t)1; if (c == cc->completed_tail) { cc->completed_tail = &cc->completed_head; } gpr_mu_unlock(cc->mu); ret.type = GRPC_OP_COMPLETE; ret.success = c->next & 1u; ret.tag = c->tag; c->done(&exec_ctx, c->done_arg, c); break; } if (cc->shutdown) { gpr_mu_unlock(cc->mu); memset(&ret, 0, sizeof(ret)); ret.type = GRPC_QUEUE_SHUTDOWN; break; } now = gpr_now(GPR_CLOCK_MONOTONIC); if (!is_finished_arg.first_loop && gpr_time_cmp(now, deadline) >= 0) { gpr_mu_unlock(cc->mu); memset(&ret, 0, sizeof(ret)); ret.type = GRPC_QUEUE_TIMEOUT; dump_pending_tags(cc); break; } /* Check alarms - these are a global resource so we just ping each time through on every pollset. May update deadline to ensure timely wakeups. TODO(ctiller): can this work be localized? */ gpr_timespec iteration_deadline = deadline; if (grpc_timer_check(&exec_ctx, now, &iteration_deadline)) { GPR_TIMER_MARK("alarm_triggered", 0); gpr_mu_unlock(cc->mu); grpc_exec_ctx_flush(&exec_ctx); gpr_mu_lock(cc->mu); continue; } else { grpc_error *err = grpc_pollset_work(&exec_ctx, POLLSET_FROM_CQ(cc), NULL, now, iteration_deadline); if (err != GRPC_ERROR_NONE) { gpr_mu_unlock(cc->mu); const char *msg = grpc_error_string(err); gpr_log(GPR_ERROR, "Completion queue next failed: %s", msg); GRPC_ERROR_UNREF(err); memset(&ret, 0, sizeof(ret)); ret.type = GRPC_QUEUE_TIMEOUT; dump_pending_tags(cc); break; } } is_finished_arg.first_loop = false; } GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret); GRPC_CQ_INTERNAL_UNREF(cc, "next"); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(is_finished_arg.stolen_completion == NULL); GPR_TIMER_END("grpc_completion_queue_next", 0); return ret; } static int add_plucker(grpc_completion_queue *cc, void *tag, grpc_pollset_worker **worker) { if (cc->num_pluckers == GRPC_MAX_COMPLETION_QUEUE_PLUCKERS) { return 0; } cc->pluckers[cc->num_pluckers].tag = tag; cc->pluckers[cc->num_pluckers].worker = worker; cc->num_pluckers++; return 1; } static void del_plucker(grpc_completion_queue *cc, void *tag, grpc_pollset_worker **worker) { int i; for (i = 0; i < cc->num_pluckers; i++) { if (cc->pluckers[i].tag == tag && cc->pluckers[i].worker == worker) { cc->num_pluckers--; GPR_SWAP(plucker, cc->pluckers[i], cc->pluckers[cc->num_pluckers]); return; } } GPR_UNREACHABLE_CODE(return ); } static bool cq_is_pluck_finished(grpc_exec_ctx *exec_ctx, void *arg) { cq_is_finished_arg *a = arg; grpc_completion_queue *cq = a->cq; GPR_ASSERT(a->stolen_completion == NULL); gpr_atm current_last_seen_things_queued_ever = gpr_atm_no_barrier_load(&cq->things_queued_ever); if (current_last_seen_things_queued_ever != a->last_seen_things_queued_ever) { gpr_mu_lock(cq->mu); a->last_seen_things_queued_ever = gpr_atm_no_barrier_load(&cq->things_queued_ever); grpc_cq_completion *c; grpc_cq_completion *prev = &cq->completed_head; while ((c = (grpc_cq_completion *)(prev->next & ~(uintptr_t)1)) != &cq->completed_head) { if (c->tag == a->tag) { prev->next = (prev->next & (uintptr_t)1) | (c->next & ~(uintptr_t)1); if (c == cq->completed_tail) { cq->completed_tail = prev; } gpr_mu_unlock(cq->mu); a->stolen_completion = c; return true; } prev = c; } gpr_mu_unlock(cq->mu); } return !a->first_loop && gpr_time_cmp(a->deadline, gpr_now(a->deadline.clock_type)) < 0; } grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag, gpr_timespec deadline, void *reserved) { grpc_event ret; grpc_cq_completion *c; grpc_cq_completion *prev; grpc_pollset_worker *worker = NULL; gpr_timespec now; GPR_TIMER_BEGIN("grpc_completion_queue_pluck", 0); if (grpc_cq_pluck_trace) { GRPC_API_TRACE( "grpc_completion_queue_pluck(" "cc=%p, tag=%p, " "deadline=gpr_timespec { tv_sec: %" PRId64 ", tv_nsec: %d, clock_type: %d }, " "reserved=%p)", 6, (cc, tag, deadline.tv_sec, deadline.tv_nsec, (int)deadline.clock_type, reserved)); } GPR_ASSERT(!reserved); dump_pending_tags(cc); deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC); GRPC_CQ_INTERNAL_REF(cc, "pluck"); gpr_mu_lock(cc->mu); cq_is_finished_arg is_finished_arg = { .last_seen_things_queued_ever = gpr_atm_no_barrier_load(&cc->things_queued_ever), .cq = cc, .deadline = deadline, .stolen_completion = NULL, .tag = tag, .first_loop = true}; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INITIALIZER(0, cq_is_pluck_finished, &is_finished_arg); for (;;) { if (is_finished_arg.stolen_completion != NULL) { gpr_mu_unlock(cc->mu); c = is_finished_arg.stolen_completion; is_finished_arg.stolen_completion = NULL; ret.type = GRPC_OP_COMPLETE; ret.success = c->next & 1u; ret.tag = c->tag; c->done(&exec_ctx, c->done_arg, c); break; } prev = &cc->completed_head; while ((c = (grpc_cq_completion *)(prev->next & ~(uintptr_t)1)) != &cc->completed_head) { if (c->tag == tag) { prev->next = (prev->next & (uintptr_t)1) | (c->next & ~(uintptr_t)1); if (c == cc->completed_tail) { cc->completed_tail = prev; } gpr_mu_unlock(cc->mu); ret.type = GRPC_OP_COMPLETE; ret.success = c->next & 1u; ret.tag = c->tag; c->done(&exec_ctx, c->done_arg, c); goto done; } prev = c; } if (cc->shutdown) { gpr_mu_unlock(cc->mu); memset(&ret, 0, sizeof(ret)); ret.type = GRPC_QUEUE_SHUTDOWN; break; } if (!add_plucker(cc, tag, &worker)) { gpr_log(GPR_DEBUG, "Too many outstanding grpc_completion_queue_pluck calls: maximum " "is %d", GRPC_MAX_COMPLETION_QUEUE_PLUCKERS); gpr_mu_unlock(cc->mu); memset(&ret, 0, sizeof(ret)); /* TODO(ctiller): should we use a different result here */ ret.type = GRPC_QUEUE_TIMEOUT; dump_pending_tags(cc); break; } now = gpr_now(GPR_CLOCK_MONOTONIC); if (!is_finished_arg.first_loop && gpr_time_cmp(now, deadline) >= 0) { del_plucker(cc, tag, &worker); gpr_mu_unlock(cc->mu); memset(&ret, 0, sizeof(ret)); ret.type = GRPC_QUEUE_TIMEOUT; dump_pending_tags(cc); break; } /* Check alarms - these are a global resource so we just ping each time through on every pollset. May update deadline to ensure timely wakeups. TODO(ctiller): can this work be localized? */ gpr_timespec iteration_deadline = deadline; if (grpc_timer_check(&exec_ctx, now, &iteration_deadline)) { GPR_TIMER_MARK("alarm_triggered", 0); gpr_mu_unlock(cc->mu); grpc_exec_ctx_flush(&exec_ctx); gpr_mu_lock(cc->mu); } else { grpc_error *err = grpc_pollset_work(&exec_ctx, POLLSET_FROM_CQ(cc), &worker, now, iteration_deadline); if (err != GRPC_ERROR_NONE) { del_plucker(cc, tag, &worker); gpr_mu_unlock(cc->mu); const char *msg = grpc_error_string(err); gpr_log(GPR_ERROR, "Completion queue next failed: %s", msg); GRPC_ERROR_UNREF(err); memset(&ret, 0, sizeof(ret)); ret.type = GRPC_QUEUE_TIMEOUT; dump_pending_tags(cc); break; } } is_finished_arg.first_loop = false; del_plucker(cc, tag, &worker); } done: GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret); GRPC_CQ_INTERNAL_UNREF(cc, "pluck"); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(is_finished_arg.stolen_completion == NULL); GPR_TIMER_END("grpc_completion_queue_pluck", 0); return ret; } /* Shutdown simply drops a ref that we reserved at creation time; if we drop to zero here, then enter shutdown mode and wake up any waiters */ void grpc_completion_queue_shutdown(grpc_completion_queue *cc) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GPR_TIMER_BEGIN("grpc_completion_queue_shutdown", 0); GRPC_API_TRACE("grpc_completion_queue_shutdown(cc=%p)", 1, (cc)); gpr_mu_lock(cc->mu); if (cc->shutdown_called) { gpr_mu_unlock(cc->mu); GPR_TIMER_END("grpc_completion_queue_shutdown", 0); return; } cc->shutdown_called = 1; if (gpr_unref(&cc->pending_events)) { GPR_ASSERT(!cc->shutdown); cc->shutdown = 1; grpc_pollset_shutdown(&exec_ctx, POLLSET_FROM_CQ(cc), &cc->pollset_shutdown_done); } gpr_mu_unlock(cc->mu); grpc_exec_ctx_finish(&exec_ctx); GPR_TIMER_END("grpc_completion_queue_shutdown", 0); } void grpc_completion_queue_destroy(grpc_completion_queue *cc) { GRPC_API_TRACE("grpc_completion_queue_destroy(cc=%p)", 1, (cc)); GPR_TIMER_BEGIN("grpc_completion_queue_destroy", 0); grpc_completion_queue_shutdown(cc); GRPC_CQ_INTERNAL_UNREF(cc, "destroy"); GPR_TIMER_END("grpc_completion_queue_destroy", 0); } grpc_pollset *grpc_cq_pollset(grpc_completion_queue *cc) { return POLLSET_FROM_CQ(cc); } grpc_completion_queue *grpc_cq_from_pollset(grpc_pollset *ps) { return CQ_FROM_POLLSET(ps); } void grpc_cq_mark_non_listening_server_cq(grpc_completion_queue *cc) { cc->is_non_listening_server_cq = 1; } bool grpc_cq_is_non_listening_server_cq(grpc_completion_queue *cc) { return (cc->is_non_listening_server_cq == 1); } void grpc_cq_mark_server_cq(grpc_completion_queue *cc) { cc->is_server_cq = 1; } int grpc_cq_is_server_cq(grpc_completion_queue *cc) { return cc->is_server_cq; } grpc-1.3.2/src/core/lib/surface/completion_queue.h000066400000000000000000000104251310511640000221040ustar00rootroot00000000000000/* * * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SURFACE_COMPLETION_QUEUE_H #define GRPC_CORE_LIB_SURFACE_COMPLETION_QUEUE_H /* Internal API for completion queues */ #include #include "src/core/lib/iomgr/pollset.h" /* These trace flags default to 1. The corresponding lines are only traced if grpc_api_trace is also truthy */ extern int grpc_cq_pluck_trace; extern int grpc_cq_event_timeout_trace; extern int grpc_trace_operation_failures; #ifndef NDEBUG extern int grpc_trace_pending_tags; #endif typedef struct grpc_cq_completion { /** user supplied tag */ void *tag; /** done callback - called when this queue element is no longer needed by the completion queue */ void (*done)(grpc_exec_ctx *exec_ctx, void *done_arg, struct grpc_cq_completion *c); void *done_arg; /** next pointer; low bit is used to indicate success or not */ uintptr_t next; } grpc_cq_completion; //#define GRPC_CQ_REF_COUNT_DEBUG #ifdef GRPC_CQ_REF_COUNT_DEBUG void grpc_cq_internal_ref(grpc_completion_queue *cc, const char *reason, const char *file, int line); void grpc_cq_internal_unref(grpc_completion_queue *cc, const char *reason, const char *file, int line); #define GRPC_CQ_INTERNAL_REF(cc, reason) \ grpc_cq_internal_ref(cc, reason, __FILE__, __LINE__) #define GRPC_CQ_INTERNAL_UNREF(cc, reason) \ grpc_cq_internal_unref(cc, reason, __FILE__, __LINE__) #else void grpc_cq_internal_ref(grpc_completion_queue *cc); void grpc_cq_internal_unref(grpc_completion_queue *cc); #define GRPC_CQ_INTERNAL_REF(cc, reason) grpc_cq_internal_ref(cc) #define GRPC_CQ_INTERNAL_UNREF(cc, reason) grpc_cq_internal_unref(cc) #endif /* Flag that an operation is beginning: the completion channel will not finish shutdown until a corrensponding grpc_cq_end_* call is made. \a tag is currently used only in debug builds. */ void grpc_cq_begin_op(grpc_completion_queue *cc, void *tag); /* Queue a GRPC_OP_COMPLETED operation; tag must correspond to the tag passed to grpc_cq_begin_op */ void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc, void *tag, grpc_error *error, void (*done)(grpc_exec_ctx *exec_ctx, void *done_arg, grpc_cq_completion *storage), void *done_arg, grpc_cq_completion *storage); grpc_pollset *grpc_cq_pollset(grpc_completion_queue *cc); grpc_completion_queue *grpc_cq_from_pollset(grpc_pollset *ps); void grpc_cq_mark_non_listening_server_cq(grpc_completion_queue *cc); bool grpc_cq_is_non_listening_server_cq(grpc_completion_queue *cc); void grpc_cq_mark_server_cq(grpc_completion_queue *cc); int grpc_cq_is_server_cq(grpc_completion_queue *cc); #endif /* GRPC_CORE_LIB_SURFACE_COMPLETION_QUEUE_H */ grpc-1.3.2/src/core/lib/surface/completion_queue_factory.c000066400000000000000000000065361310511640000236360ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/surface/completion_queue_factory.h" #include "src/core/lib/surface/completion_queue.h" #include /* TODO (sreek) - Currently this does not use the attributes arg. This will be added in a future PR */ static grpc_completion_queue* default_create( const grpc_completion_queue_factory* factory, const grpc_completion_queue_attributes* attributes) { return grpc_completion_queue_create(NULL); } static grpc_completion_queue_factory_vtable default_vtable = {default_create}; static const grpc_completion_queue_factory g_default_cq_factory = { "Default Factory", NULL, &default_vtable}; const grpc_completion_queue_factory* grpc_completion_queue_factory_lookup( const grpc_completion_queue_attributes* attributes) { /* As we add more fields to grpc_completion_queue_attributes, we may have to change this assert to: GPR_ASSERT (attributes->version >= 1 && attributes->version <= GRPC_CQ_CURRENT_VERSION) */ GPR_ASSERT(attributes->version == 1); /* The default factory can handle version 1 of the attributes structure. We may have to change this as more fields are added to the structure */ return &g_default_cq_factory; } grpc_completion_queue* grpc_completion_queue_create_for_next(void* reserved) { GPR_ASSERT(!reserved); grpc_completion_queue_attributes attr = {1, GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING}; return g_default_cq_factory.vtable->create(&g_default_cq_factory, &attr); } grpc_completion_queue* grpc_completion_queue_create_for_pluck(void* reserved) { GPR_ASSERT(!reserved); grpc_completion_queue_attributes attr = {1, GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING}; return g_default_cq_factory.vtable->create(&g_default_cq_factory, &attr); } grpc-1.3.2/src/core/lib/surface/completion_queue_factory.h000066400000000000000000000042541310511640000236360ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SURFACE_COMPLETION_QUEUE_FACTORY_H #define GRPC_CORE_LIB_SURFACE_COMPLETION_QUEUE_FACTORY_H #include #include "src/core/lib/surface/completion_queue.h" typedef struct grpc_completion_queue_factory_vtable { grpc_completion_queue* (*create)(const grpc_completion_queue_factory*, const grpc_completion_queue_attributes*); } grpc_completion_queue_factory_vtable; struct grpc_completion_queue_factory { const char* name; void* data; /* Factory specific data */ grpc_completion_queue_factory_vtable* vtable; }; #endif /* GRPC_CORE_LIB_SURFACE_COMPLETION_QUEUE_FACTORY_H */ grpc-1.3.2/src/core/lib/surface/event_string.c000066400000000000000000000052341310511640000212330ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/surface/event_string.h" #include #include #include #include "src/core/lib/support/string.h" static void addhdr(gpr_strvec *buf, grpc_event *ev) { char *tmp; gpr_asprintf(&tmp, "tag:%p", ev->tag); gpr_strvec_add(buf, tmp); } static const char *errstr(int success) { return success ? "OK" : "ERROR"; } static void adderr(gpr_strvec *buf, int success) { char *tmp; gpr_asprintf(&tmp, " %s", errstr(success)); gpr_strvec_add(buf, tmp); } char *grpc_event_string(grpc_event *ev) { char *out; gpr_strvec buf; if (ev == NULL) return gpr_strdup("null"); gpr_strvec_init(&buf); switch (ev->type) { case GRPC_QUEUE_TIMEOUT: gpr_strvec_add(&buf, gpr_strdup("QUEUE_TIMEOUT")); break; case GRPC_QUEUE_SHUTDOWN: gpr_strvec_add(&buf, gpr_strdup("QUEUE_SHUTDOWN")); break; case GRPC_OP_COMPLETE: gpr_strvec_add(&buf, gpr_strdup("OP_COMPLETE: ")); addhdr(&buf, ev); adderr(&buf, ev->success); break; } out = gpr_strvec_flatten(&buf, NULL); gpr_strvec_destroy(&buf); return out; } grpc-1.3.2/src/core/lib/surface/event_string.h000066400000000000000000000035011310511640000212330ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SURFACE_EVENT_STRING_H #define GRPC_CORE_LIB_SURFACE_EVENT_STRING_H #include /* Returns a string describing an event. Must be later freed with gpr_free() */ char *grpc_event_string(grpc_event *ev); #endif /* GRPC_CORE_LIB_SURFACE_EVENT_STRING_H */ grpc-1.3.2/src/core/lib/surface/init.c000066400000000000000000000246741310511640000175000ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/compress_filter.h" #include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/channel/deadline_filter.h" #include "src/core/lib/channel/handshaker_registry.h" #include "src/core/lib/channel/http_client_filter.h" #include "src/core/lib/channel/http_server_filter.h" #include "src/core/lib/channel/message_size_filter.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/resource_quota.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/call.h" #include "src/core/lib/surface/channel_init.h" #include "src/core/lib/surface/completion_queue.h" #include "src/core/lib/surface/init.h" #include "src/core/lib/surface/lame_client.h" #include "src/core/lib/surface/server.h" #include "src/core/lib/transport/bdp_estimator.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/transport_impl.h" /* (generated) built in registry of plugins */ extern void grpc_register_built_in_plugins(void); #define MAX_PLUGINS 128 static gpr_once g_basic_init = GPR_ONCE_INIT; static gpr_mu g_init_mu; static int g_initializations; static void do_basic_init(void) { gpr_log_verbosity_init(); gpr_mu_init(&g_init_mu); grpc_register_built_in_plugins(); g_initializations = 0; } static bool append_filter(grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, void *arg) { return grpc_channel_stack_builder_append_filter( builder, (const grpc_channel_filter *)arg, NULL, NULL); } static bool prepend_filter(grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, void *arg) { return grpc_channel_stack_builder_prepend_filter( builder, (const grpc_channel_filter *)arg, NULL, NULL); } static bool maybe_add_http_filter(grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, void *arg) { grpc_transport *t = grpc_channel_stack_builder_get_transport(builder); if (t && strstr(t->vtable->name, "http")) { return grpc_channel_stack_builder_prepend_filter( builder, (const grpc_channel_filter *)arg, NULL, NULL); } return true; } static void register_builtin_channel_init() { grpc_channel_init_register_stage( GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter, (void *)&grpc_client_deadline_filter); grpc_channel_init_register_stage( GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter, (void *)&grpc_server_deadline_filter); grpc_channel_init_register_stage( GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter, (void *)&grpc_message_size_filter); grpc_channel_init_register_stage( GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter, (void *)&grpc_message_size_filter); grpc_channel_init_register_stage( GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter, (void *)&grpc_message_size_filter); grpc_channel_init_register_stage( GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter, (void *)&grpc_compress_filter); grpc_channel_init_register_stage( GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter, (void *)&grpc_compress_filter); grpc_channel_init_register_stage( GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter, (void *)&grpc_compress_filter); grpc_channel_init_register_stage( GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, maybe_add_http_filter, (void *)&grpc_http_client_filter); grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, grpc_add_connected_filter, NULL); grpc_channel_init_register_stage( GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, maybe_add_http_filter, (void *)&grpc_http_client_filter); grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, grpc_add_connected_filter, NULL); grpc_channel_init_register_stage( GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, maybe_add_http_filter, (void *)&grpc_http_server_filter); grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, grpc_add_connected_filter, NULL); grpc_channel_init_register_stage(GRPC_CLIENT_LAME_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, append_filter, (void *)&grpc_lame_filter); grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, prepend_filter, (void *)&grpc_server_top_filter); } typedef struct grpc_plugin { void (*init)(); void (*destroy)(); } grpc_plugin; static grpc_plugin g_all_of_the_plugins[MAX_PLUGINS]; static int g_number_of_plugins = 0; void grpc_register_plugin(void (*init)(void), void (*destroy)(void)) { GRPC_API_TRACE("grpc_register_plugin(init=%p, destroy=%p)", 2, ((void *)(intptr_t)init, (void *)(intptr_t)destroy)); GPR_ASSERT(g_number_of_plugins != MAX_PLUGINS); g_all_of_the_plugins[g_number_of_plugins].init = init; g_all_of_the_plugins[g_number_of_plugins].destroy = destroy; g_number_of_plugins++; } void grpc_init(void) { int i; gpr_once_init(&g_basic_init, do_basic_init); gpr_mu_lock(&g_init_mu); if (++g_initializations == 1) { gpr_time_init(); grpc_slice_intern_init(); grpc_mdctx_global_init(); grpc_channel_init_init(); grpc_register_tracer("api", &grpc_api_trace); grpc_register_tracer("channel", &grpc_trace_channel); grpc_register_tracer("connectivity_state", &grpc_connectivity_state_trace); grpc_register_tracer("channel_stack_builder", &grpc_trace_channel_stack_builder); grpc_register_tracer("http1", &grpc_http1_trace); grpc_register_tracer("compression", &grpc_compression_trace); grpc_register_tracer("queue_pluck", &grpc_cq_pluck_trace); grpc_register_tracer("combiner", &grpc_combiner_trace); grpc_register_tracer("server_channel", &grpc_server_channel_trace); grpc_register_tracer("bdp_estimator", &grpc_bdp_estimator_trace); // Default pluck trace to 1 grpc_cq_pluck_trace = 1; grpc_register_tracer("queue_timeout", &grpc_cq_event_timeout_trace); // Default timeout trace to 1 grpc_cq_event_timeout_trace = 1; grpc_register_tracer("op_failure", &grpc_trace_operation_failures); grpc_register_tracer("resource_quota", &grpc_resource_quota_trace); grpc_register_tracer("call_error", &grpc_call_error_trace); #ifndef NDEBUG grpc_register_tracer("pending_tags", &grpc_trace_pending_tags); #endif grpc_security_pre_init(); grpc_iomgr_init(); grpc_executor_init(); gpr_timers_global_init(); grpc_handshaker_factory_registry_init(); grpc_security_init(); for (i = 0; i < g_number_of_plugins; i++) { if (g_all_of_the_plugins[i].init != NULL) { g_all_of_the_plugins[i].init(); } } /* register channel finalization AFTER all plugins, to ensure that it's run * at the appropriate time */ grpc_register_security_filters(); register_builtin_channel_init(); grpc_tracer_init("GRPC_TRACE"); /* no more changes to channel init pipelines */ grpc_channel_init_finalize(); } gpr_mu_unlock(&g_init_mu); GRPC_API_TRACE("grpc_init(void)", 0, ()); } void grpc_shutdown(void) { int i; GRPC_API_TRACE("grpc_shutdown(void)", 0, ()); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; gpr_mu_lock(&g_init_mu); if (--g_initializations == 0) { grpc_executor_shutdown(&exec_ctx); grpc_iomgr_shutdown(&exec_ctx); gpr_timers_global_destroy(); grpc_tracer_shutdown(); for (i = g_number_of_plugins; i >= 0; i--) { if (g_all_of_the_plugins[i].destroy != NULL) { g_all_of_the_plugins[i].destroy(); } } grpc_mdctx_global_shutdown(&exec_ctx); grpc_handshaker_factory_registry_shutdown(&exec_ctx); grpc_slice_intern_shutdown(); } gpr_mu_unlock(&g_init_mu); grpc_exec_ctx_finish(&exec_ctx); } int grpc_is_initialized(void) { int r; gpr_once_init(&g_basic_init, do_basic_init); gpr_mu_lock(&g_init_mu); r = g_initializations > 0; gpr_mu_unlock(&g_init_mu); return r; } grpc-1.3.2/src/core/lib/surface/init.h000066400000000000000000000034441310511640000174750ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SURFACE_INIT_H #define GRPC_CORE_LIB_SURFACE_INIT_H void grpc_register_security_filters(void); void grpc_security_pre_init(void); void grpc_security_init(void); int grpc_is_initialized(void); #endif /* GRPC_CORE_LIB_SURFACE_INIT_H */ grpc-1.3.2/src/core/lib/surface/init_secure.c000066400000000000000000000075021310511640000210350ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "src/core/lib/surface/init.h" #include #include #include "src/core/lib/debug/trace.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/transport/auth_filters.h" #include "src/core/lib/security/transport/secure_endpoint.h" #include "src/core/lib/security/transport/security_connector.h" #include "src/core/lib/security/transport/security_handshaker.h" #include "src/core/lib/surface/channel_init.h" #include "src/core/tsi/transport_security_interface.h" void grpc_security_pre_init(void) { grpc_register_tracer("secure_endpoint", &grpc_trace_secure_endpoint); grpc_register_tracer("transport_security", &tsi_tracing_enabled); } static bool maybe_prepend_client_auth_filter( grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, void *arg) { const grpc_channel_args *args = grpc_channel_stack_builder_get_channel_arguments(builder); if (args) { for (size_t i = 0; i < args->num_args; i++) { if (0 == strcmp(GRPC_ARG_SECURITY_CONNECTOR, args->args[i].key)) { return grpc_channel_stack_builder_prepend_filter( builder, &grpc_client_auth_filter, NULL, NULL); } } } return true; } static bool maybe_prepend_server_auth_filter( grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, void *arg) { const grpc_channel_args *args = grpc_channel_stack_builder_get_channel_arguments(builder); if (args) { for (size_t i = 0; i < args->num_args; i++) { if (0 == strcmp(GRPC_SERVER_CREDENTIALS_ARG, args->args[i].key)) { return grpc_channel_stack_builder_prepend_filter( builder, &grpc_server_auth_filter, NULL, NULL); } } } return true; } void grpc_register_security_filters(void) { grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX, maybe_prepend_client_auth_filter, NULL); grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX, maybe_prepend_client_auth_filter, NULL); grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, maybe_prepend_server_auth_filter, NULL); } void grpc_security_init() { grpc_security_register_handshaker_factories(); } grpc-1.3.2/src/core/lib/surface/init_unsecure.c000066400000000000000000000032771310511640000214050ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/surface/init.h" void grpc_security_pre_init(void) {} void grpc_register_security_filters(void) {} void grpc_security_init(void) {} grpc-1.3.2/src/core/lib/surface/lame_client.c000066400000000000000000000161011310511640000207730ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/surface/lame_client.h" #include #include #include #include #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/support/string.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/call.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/transport/static_metadata.h" typedef struct { grpc_linked_mdelem status; grpc_linked_mdelem details; gpr_atm filled_metadata; } call_data; typedef struct { grpc_status_code error_code; const char *error_message; } channel_data; static void fill_metadata(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_metadata_batch *mdb) { call_data *calld = elem->call_data; if (!gpr_atm_no_barrier_cas(&calld->filled_metadata, 0, 1)) { return; } channel_data *chand = elem->channel_data; char tmp[GPR_LTOA_MIN_BUFSIZE]; gpr_ltoa(chand->error_code, tmp); calld->status.md = grpc_mdelem_from_slices( exec_ctx, GRPC_MDSTR_GRPC_STATUS, grpc_slice_from_copied_string(tmp)); calld->details.md = grpc_mdelem_from_slices( exec_ctx, GRPC_MDSTR_GRPC_MESSAGE, grpc_slice_from_copied_string(chand->error_message)); calld->status.prev = calld->details.next = NULL; calld->status.next = &calld->details; calld->details.prev = &calld->status; mdb->list.head = &calld->status; mdb->list.tail = &calld->details; mdb->list.count = 2; mdb->deadline = gpr_inf_future(GPR_CLOCK_REALTIME); } static void lame_start_transport_stream_op_batch( grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op_batch *op) { GRPC_CALL_LOG_OP(GPR_INFO, elem, op); if (op->recv_initial_metadata) { fill_metadata(exec_ctx, elem, op->payload->recv_initial_metadata.recv_initial_metadata); } else if (op->recv_trailing_metadata) { fill_metadata(exec_ctx, elem, op->payload->recv_trailing_metadata.recv_trailing_metadata); } grpc_transport_stream_op_batch_finish_with_failure( exec_ctx, op, GRPC_ERROR_CREATE_FROM_STATIC_STRING("lame client channel")); } static char *lame_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { return NULL; } static void lame_get_channel_info(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, const grpc_channel_info *channel_info) {} static void lame_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_transport_op *op) { if (op->on_connectivity_state_change) { GPR_ASSERT(*op->connectivity_state != GRPC_CHANNEL_SHUTDOWN); *op->connectivity_state = GRPC_CHANNEL_SHUTDOWN; grpc_closure_sched(exec_ctx, op->on_connectivity_state_change, GRPC_ERROR_NONE); } if (op->send_ping != NULL) { grpc_closure_sched( exec_ctx, op->send_ping, GRPC_ERROR_CREATE_FROM_STATIC_STRING("lame client channel")); } GRPC_ERROR_UNREF(op->disconnect_with_error); if (op->on_consumed != NULL) { grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE); } } static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_element_args *args) { call_data *calld = elem->call_data; gpr_atm_no_barrier_store(&calld->filled_metadata, 0); return GRPC_ERROR_NONE; } static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, grpc_closure *then_schedule_closure) { grpc_closure_sched(exec_ctx, then_schedule_closure, GRPC_ERROR_NONE); } static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_channel_element_args *args) { GPR_ASSERT(args->is_first); GPR_ASSERT(args->is_last); return GRPC_ERROR_NONE; } static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) {} const grpc_channel_filter grpc_lame_filter = { lame_start_transport_stream_op_batch, lame_start_transport_op, sizeof(call_data), init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, destroy_call_elem, sizeof(channel_data), init_channel_elem, destroy_channel_elem, lame_get_peer, lame_get_channel_info, "lame-client", }; #define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack *)((c) + 1)) grpc_channel *grpc_lame_client_channel_create(const char *target, grpc_status_code error_code, const char *error_message) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_channel_element *elem; channel_data *chand; grpc_channel *channel = grpc_channel_create(&exec_ctx, target, NULL, GRPC_CLIENT_LAME_CHANNEL, NULL); elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); GRPC_API_TRACE( "grpc_lame_client_channel_create(target=%s, error_code=%d, " "error_message=%s)", 3, (target, (int)error_code, error_message)); GPR_ASSERT(elem->filter == &grpc_lame_filter); chand = (channel_data *)elem->channel_data; chand->error_code = error_code; chand->error_message = error_message; grpc_exec_ctx_finish(&exec_ctx); return channel; } grpc-1.3.2/src/core/lib/surface/lame_client.h000066400000000000000000000034211310511640000210010ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SURFACE_LAME_CLIENT_H #define GRPC_CORE_LIB_SURFACE_LAME_CLIENT_H #include "src/core/lib/channel/channel_stack.h" extern const grpc_channel_filter grpc_lame_filter; #endif /* GRPC_CORE_LIB_SURFACE_LAME_CLIENT_H */ grpc-1.3.2/src/core/lib/surface/metadata_array.c000066400000000000000000000037501310511640000215030ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include "src/core/lib/surface/api_trace.h" void grpc_metadata_array_init(grpc_metadata_array* array) { GRPC_API_TRACE("grpc_metadata_array_init(array=%p)", 1, (array)); memset(array, 0, sizeof(*array)); } void grpc_metadata_array_destroy(grpc_metadata_array* array) { GRPC_API_TRACE("grpc_metadata_array_destroy(array=%p)", 1, (array)); gpr_free(array->metadata); } grpc-1.3.2/src/core/lib/surface/server.c000066400000000000000000001501021310511640000200250ustar00rootroot00000000000000/* * * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/surface/server.h" #include #include #include #include #include #include #include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/support/stack_lockfree.h" #include "src/core/lib/support/string.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/call.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/completion_queue.h" #include "src/core/lib/surface/init.h" #include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/static_metadata.h" typedef struct listener { void *arg; void (*start)(grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg, grpc_pollset **pollsets, size_t pollset_count); void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg, grpc_closure *closure); struct listener *next; grpc_closure destroy_done; } listener; typedef struct call_data call_data; typedef struct channel_data channel_data; typedef struct registered_method registered_method; typedef enum { BATCH_CALL, REGISTERED_CALL } requested_call_type; int grpc_server_channel_trace = 0; typedef struct requested_call { requested_call_type type; size_t cq_idx; void *tag; grpc_server *server; grpc_completion_queue *cq_bound_to_call; grpc_call **call; grpc_cq_completion completion; grpc_metadata_array *initial_metadata; union { struct { grpc_call_details *details; } batch; struct { registered_method *registered_method; gpr_timespec *deadline; grpc_byte_buffer **optional_payload; } registered; } data; } requested_call; typedef struct channel_registered_method { registered_method *server_registered_method; uint32_t flags; bool has_host; grpc_slice method; grpc_slice host; } channel_registered_method; struct channel_data { grpc_server *server; grpc_connectivity_state connectivity_state; grpc_channel *channel; size_t cq_idx; /* linked list of all channels on a server */ channel_data *next; channel_data *prev; channel_registered_method *registered_methods; uint32_t registered_method_slots; uint32_t registered_method_max_probes; grpc_closure finish_destroy_channel_closure; grpc_closure channel_connectivity_changed; }; typedef struct shutdown_tag { void *tag; grpc_completion_queue *cq; grpc_cq_completion completion; } shutdown_tag; typedef enum { /* waiting for metadata */ NOT_STARTED, /* inital metadata read, not flow controlled in yet */ PENDING, /* flow controlled in, on completion queue */ ACTIVATED, /* cancelled before being queued */ ZOMBIED } call_state; typedef struct request_matcher request_matcher; struct call_data { grpc_call *call; /** protects state */ gpr_mu mu_state; /** the current state of a call - see call_state */ call_state state; bool path_set; bool host_set; grpc_slice path; grpc_slice host; gpr_timespec deadline; grpc_completion_queue *cq_new; grpc_metadata_batch *recv_initial_metadata; uint32_t recv_initial_metadata_flags; grpc_metadata_array initial_metadata; request_matcher *request_matcher; grpc_byte_buffer *payload; grpc_closure got_initial_metadata; grpc_closure server_on_recv_initial_metadata; grpc_closure kill_zombie_closure; grpc_closure *on_done_recv_initial_metadata; grpc_closure publish; call_data *pending_next; }; struct request_matcher { grpc_server *server; call_data *pending_head; call_data *pending_tail; gpr_stack_lockfree **requests_per_cq; }; struct registered_method { char *method; char *host; grpc_server_register_method_payload_handling payload_handling; uint32_t flags; /* one request matcher per method */ request_matcher request_matcher; registered_method *next; }; typedef struct { grpc_channel **channels; size_t num_channels; } channel_broadcaster; struct grpc_server { grpc_channel_args *channel_args; grpc_completion_queue **cqs; grpc_pollset **pollsets; size_t cq_count; size_t pollset_count; bool started; /* The two following mutexes control access to server-state mu_global controls access to non-call-related state (e.g., channel state) mu_call controls access to call-related state (e.g., the call lists) If they are ever required to be nested, you must lock mu_global before mu_call. This is currently used in shutdown processing (grpc_server_shutdown_and_notify and maybe_finish_shutdown) */ gpr_mu mu_global; /* mutex for server and channel state */ gpr_mu mu_call; /* mutex for call-specific state */ registered_method *registered_methods; /** one request matcher for unregistered methods */ request_matcher unregistered_request_matcher; /** free list of available requested_calls_per_cq indices */ gpr_stack_lockfree **request_freelist_per_cq; /** requested call backing data */ requested_call **requested_calls_per_cq; int max_requested_calls_per_cq; gpr_atm shutdown_flag; uint8_t shutdown_published; size_t num_shutdown_tags; shutdown_tag *shutdown_tags; channel_data root_channel_data; listener *listeners; int listeners_destroyed; gpr_refcount internal_refcount; /** when did we print the last shutdown progress message */ gpr_timespec last_shutdown_message_time; }; #define SERVER_FROM_CALL_ELEM(elem) \ (((channel_data *)(elem)->channel_data)->server) static void publish_new_rpc(grpc_exec_ctx *exec_ctx, void *calld, grpc_error *error); static void fail_call(grpc_exec_ctx *exec_ctx, grpc_server *server, size_t cq_idx, requested_call *rc, grpc_error *error); /* Before calling maybe_finish_shutdown, we must hold mu_global and not hold mu_call */ static void maybe_finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_server *server); /* * channel broadcaster */ /* assumes server locked */ static void channel_broadcaster_init(grpc_server *s, channel_broadcaster *cb) { channel_data *c; size_t count = 0; for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) { count++; } cb->num_channels = count; cb->channels = gpr_malloc(sizeof(*cb->channels) * cb->num_channels); count = 0; for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) { cb->channels[count++] = c->channel; GRPC_CHANNEL_INTERNAL_REF(c->channel, "broadcast"); } } struct shutdown_cleanup_args { grpc_closure closure; grpc_slice slice; }; static void shutdown_cleanup(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { struct shutdown_cleanup_args *a = arg; grpc_slice_unref_internal(exec_ctx, a->slice); gpr_free(a); } static void send_shutdown(grpc_exec_ctx *exec_ctx, grpc_channel *channel, bool send_goaway, grpc_error *send_disconnect) { struct shutdown_cleanup_args *sc = gpr_malloc(sizeof(*sc)); grpc_closure_init(&sc->closure, shutdown_cleanup, sc, grpc_schedule_on_exec_ctx); grpc_transport_op *op = grpc_make_transport_op(&sc->closure); grpc_channel_element *elem; op->goaway_error = send_goaway ? grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Server shutdown"), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_OK) : GRPC_ERROR_NONE; op->set_accept_stream = true; sc->slice = grpc_slice_from_copied_string("Server shutdown"); op->disconnect_with_error = send_disconnect; elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); elem->filter->start_transport_op(exec_ctx, elem, op); } static void channel_broadcaster_shutdown(grpc_exec_ctx *exec_ctx, channel_broadcaster *cb, bool send_goaway, grpc_error *force_disconnect) { size_t i; for (i = 0; i < cb->num_channels; i++) { send_shutdown(exec_ctx, cb->channels[i], send_goaway, GRPC_ERROR_REF(force_disconnect)); GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, cb->channels[i], "broadcast"); } gpr_free(cb->channels); GRPC_ERROR_UNREF(force_disconnect); } /* * request_matcher */ static void request_matcher_init(request_matcher *rm, size_t entries, grpc_server *server) { memset(rm, 0, sizeof(*rm)); rm->server = server; rm->requests_per_cq = gpr_malloc(sizeof(*rm->requests_per_cq) * server->cq_count); for (size_t i = 0; i < server->cq_count; i++) { rm->requests_per_cq[i] = gpr_stack_lockfree_create(entries); } } static void request_matcher_destroy(request_matcher *rm) { for (size_t i = 0; i < rm->server->cq_count; i++) { GPR_ASSERT(gpr_stack_lockfree_pop(rm->requests_per_cq[i]) == -1); gpr_stack_lockfree_destroy(rm->requests_per_cq[i]); } gpr_free(rm->requests_per_cq); } static void kill_zombie(grpc_exec_ctx *exec_ctx, void *elem, grpc_error *error) { grpc_call_destroy(grpc_call_from_top_element(elem)); } static void request_matcher_zombify_all_pending_calls(grpc_exec_ctx *exec_ctx, request_matcher *rm) { while (rm->pending_head) { call_data *calld = rm->pending_head; rm->pending_head = calld->pending_next; gpr_mu_lock(&calld->mu_state); calld->state = ZOMBIED; gpr_mu_unlock(&calld->mu_state); grpc_closure_init( &calld->kill_zombie_closure, kill_zombie, grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0), grpc_schedule_on_exec_ctx); grpc_closure_sched(exec_ctx, &calld->kill_zombie_closure, GRPC_ERROR_NONE); } } static void request_matcher_kill_requests(grpc_exec_ctx *exec_ctx, grpc_server *server, request_matcher *rm, grpc_error *error) { int request_id; for (size_t i = 0; i < server->cq_count; i++) { while ((request_id = gpr_stack_lockfree_pop(rm->requests_per_cq[i])) != -1) { fail_call(exec_ctx, server, i, &server->requested_calls_per_cq[i][request_id], GRPC_ERROR_REF(error)); } } GRPC_ERROR_UNREF(error); } /* * server proper */ static void server_ref(grpc_server *server) { gpr_ref(&server->internal_refcount); } static void server_delete(grpc_exec_ctx *exec_ctx, grpc_server *server) { registered_method *rm; size_t i; grpc_channel_args_destroy(exec_ctx, server->channel_args); gpr_mu_destroy(&server->mu_global); gpr_mu_destroy(&server->mu_call); while ((rm = server->registered_methods) != NULL) { server->registered_methods = rm->next; if (server->started) { request_matcher_destroy(&rm->request_matcher); } gpr_free(rm->method); gpr_free(rm->host); gpr_free(rm); } if (server->started) { request_matcher_destroy(&server->unregistered_request_matcher); } for (i = 0; i < server->cq_count; i++) { GRPC_CQ_INTERNAL_UNREF(server->cqs[i], "server"); if (server->started) { gpr_stack_lockfree_destroy(server->request_freelist_per_cq[i]); gpr_free(server->requested_calls_per_cq[i]); } } gpr_free(server->request_freelist_per_cq); gpr_free(server->requested_calls_per_cq); gpr_free(server->cqs); gpr_free(server->pollsets); gpr_free(server->shutdown_tags); gpr_free(server); } static void server_unref(grpc_exec_ctx *exec_ctx, grpc_server *server) { if (gpr_unref(&server->internal_refcount)) { server_delete(exec_ctx, server); } } static int is_channel_orphaned(channel_data *chand) { return chand->next == chand; } static void orphan_channel(channel_data *chand) { chand->next->prev = chand->prev; chand->prev->next = chand->next; chand->next = chand->prev = chand; } static void finish_destroy_channel(grpc_exec_ctx *exec_ctx, void *cd, grpc_error *error) { channel_data *chand = cd; grpc_server *server = chand->server; GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, chand->channel, "server"); server_unref(exec_ctx, server); } static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand, grpc_error *error) { if (is_channel_orphaned(chand)) return; GPR_ASSERT(chand->server != NULL); orphan_channel(chand); server_ref(chand->server); maybe_finish_shutdown(exec_ctx, chand->server); grpc_closure_init(&chand->finish_destroy_channel_closure, finish_destroy_channel, chand, grpc_schedule_on_exec_ctx); if (grpc_server_channel_trace && error != GRPC_ERROR_NONE) { const char *msg = grpc_error_string(error); gpr_log(GPR_INFO, "Disconnected client: %s", msg); } GRPC_ERROR_UNREF(error); grpc_transport_op *op = grpc_make_transport_op(&chand->finish_destroy_channel_closure); op->set_accept_stream = true; grpc_channel_next_op(exec_ctx, grpc_channel_stack_element( grpc_channel_get_channel_stack(chand->channel), 0), op); } static void done_request_event(grpc_exec_ctx *exec_ctx, void *req, grpc_cq_completion *c) { requested_call *rc = req; grpc_server *server = rc->server; if (rc >= server->requested_calls_per_cq[rc->cq_idx] && rc < server->requested_calls_per_cq[rc->cq_idx] + server->max_requested_calls_per_cq) { GPR_ASSERT(rc - server->requested_calls_per_cq[rc->cq_idx] <= INT_MAX); gpr_stack_lockfree_push( server->request_freelist_per_cq[rc->cq_idx], (int)(rc - server->requested_calls_per_cq[rc->cq_idx])); } else { gpr_free(req); } server_unref(exec_ctx, server); } static void publish_call(grpc_exec_ctx *exec_ctx, grpc_server *server, call_data *calld, size_t cq_idx, requested_call *rc) { grpc_call_set_completion_queue(exec_ctx, calld->call, rc->cq_bound_to_call); grpc_call *call = calld->call; *rc->call = call; calld->cq_new = server->cqs[cq_idx]; GPR_SWAP(grpc_metadata_array, *rc->initial_metadata, calld->initial_metadata); switch (rc->type) { case BATCH_CALL: GPR_ASSERT(calld->host_set); GPR_ASSERT(calld->path_set); rc->data.batch.details->host = grpc_slice_ref_internal(calld->host); rc->data.batch.details->method = grpc_slice_ref_internal(calld->path); rc->data.batch.details->deadline = calld->deadline; rc->data.batch.details->flags = calld->recv_initial_metadata_flags; break; case REGISTERED_CALL: *rc->data.registered.deadline = calld->deadline; if (rc->data.registered.optional_payload) { *rc->data.registered.optional_payload = calld->payload; } break; default: GPR_UNREACHABLE_CODE(return ); } grpc_call_element *elem = grpc_call_stack_element(grpc_call_get_call_stack(call), 0); channel_data *chand = elem->channel_data; server_ref(chand->server); grpc_cq_end_op(exec_ctx, calld->cq_new, rc->tag, GRPC_ERROR_NONE, done_request_event, rc, &rc->completion); } static void publish_new_rpc(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_call_element *call_elem = arg; call_data *calld = call_elem->call_data; channel_data *chand = call_elem->channel_data; request_matcher *rm = calld->request_matcher; grpc_server *server = rm->server; if (error != GRPC_ERROR_NONE || gpr_atm_acq_load(&server->shutdown_flag)) { gpr_mu_lock(&calld->mu_state); calld->state = ZOMBIED; gpr_mu_unlock(&calld->mu_state); grpc_closure_init( &calld->kill_zombie_closure, kill_zombie, grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0), grpc_schedule_on_exec_ctx); grpc_closure_sched(exec_ctx, &calld->kill_zombie_closure, GRPC_ERROR_REF(error)); return; } for (size_t i = 0; i < server->cq_count; i++) { size_t cq_idx = (chand->cq_idx + i) % server->cq_count; int request_id = gpr_stack_lockfree_pop(rm->requests_per_cq[cq_idx]); if (request_id == -1) { continue; } else { gpr_mu_lock(&calld->mu_state); calld->state = ACTIVATED; gpr_mu_unlock(&calld->mu_state); publish_call(exec_ctx, server, calld, cq_idx, &server->requested_calls_per_cq[cq_idx][request_id]); return; /* early out */ } } /* no cq to take the request found: queue it on the slow list */ gpr_mu_lock(&server->mu_call); gpr_mu_lock(&calld->mu_state); calld->state = PENDING; gpr_mu_unlock(&calld->mu_state); if (rm->pending_head == NULL) { rm->pending_tail = rm->pending_head = calld; } else { rm->pending_tail->pending_next = calld; rm->pending_tail = calld; } calld->pending_next = NULL; gpr_mu_unlock(&server->mu_call); } static void finish_start_new_rpc( grpc_exec_ctx *exec_ctx, grpc_server *server, grpc_call_element *elem, request_matcher *rm, grpc_server_register_method_payload_handling payload_handling) { call_data *calld = elem->call_data; if (gpr_atm_acq_load(&server->shutdown_flag)) { gpr_mu_lock(&calld->mu_state); calld->state = ZOMBIED; gpr_mu_unlock(&calld->mu_state); grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem, grpc_schedule_on_exec_ctx); grpc_closure_sched(exec_ctx, &calld->kill_zombie_closure, GRPC_ERROR_NONE); return; } calld->request_matcher = rm; switch (payload_handling) { case GRPC_SRM_PAYLOAD_NONE: publish_new_rpc(exec_ctx, elem, GRPC_ERROR_NONE); break; case GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER: { grpc_op op; memset(&op, 0, sizeof(op)); op.op = GRPC_OP_RECV_MESSAGE; op.data.recv_message.recv_message = &calld->payload; grpc_closure_init(&calld->publish, publish_new_rpc, elem, grpc_schedule_on_exec_ctx); grpc_call_start_batch_and_execute(exec_ctx, calld->call, &op, 1, &calld->publish); break; } } } static void start_new_rpc(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { channel_data *chand = elem->channel_data; call_data *calld = elem->call_data; grpc_server *server = chand->server; uint32_t i; uint32_t hash; channel_registered_method *rm; if (chand->registered_methods && calld->path_set && calld->host_set) { /* TODO(ctiller): unify these two searches */ /* check for an exact match with host */ hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash(calld->host), grpc_slice_hash(calld->path)); for (i = 0; i <= chand->registered_method_max_probes; i++) { rm = &chand->registered_methods[(hash + i) % chand->registered_method_slots]; if (!rm) break; if (!rm->has_host) continue; if (!grpc_slice_eq(rm->host, calld->host)) continue; if (!grpc_slice_eq(rm->method, calld->path)) continue; if ((rm->flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) && 0 == (calld->recv_initial_metadata_flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST)) { continue; } finish_start_new_rpc(exec_ctx, server, elem, &rm->server_registered_method->request_matcher, rm->server_registered_method->payload_handling); return; } /* check for a wildcard method definition (no host set) */ hash = GRPC_MDSTR_KV_HASH(0, grpc_slice_hash(calld->path)); for (i = 0; i <= chand->registered_method_max_probes; i++) { rm = &chand->registered_methods[(hash + i) % chand->registered_method_slots]; if (!rm) break; if (rm->has_host) continue; if (!grpc_slice_eq(rm->method, calld->path)) continue; if ((rm->flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) && 0 == (calld->recv_initial_metadata_flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST)) { continue; } finish_start_new_rpc(exec_ctx, server, elem, &rm->server_registered_method->request_matcher, rm->server_registered_method->payload_handling); return; } } finish_start_new_rpc(exec_ctx, server, elem, &server->unregistered_request_matcher, GRPC_SRM_PAYLOAD_NONE); } static int num_listeners(grpc_server *server) { listener *l; int n = 0; for (l = server->listeners; l; l = l->next) { n++; } return n; } static void done_shutdown_event(grpc_exec_ctx *exec_ctx, void *server, grpc_cq_completion *completion) { server_unref(exec_ctx, server); } static int num_channels(grpc_server *server) { channel_data *chand; int n = 0; for (chand = server->root_channel_data.next; chand != &server->root_channel_data; chand = chand->next) { n++; } return n; } static void kill_pending_work_locked(grpc_exec_ctx *exec_ctx, grpc_server *server, grpc_error *error) { if (server->started) { request_matcher_kill_requests(exec_ctx, server, &server->unregistered_request_matcher, GRPC_ERROR_REF(error)); request_matcher_zombify_all_pending_calls( exec_ctx, &server->unregistered_request_matcher); for (registered_method *rm = server->registered_methods; rm; rm = rm->next) { request_matcher_kill_requests(exec_ctx, server, &rm->request_matcher, GRPC_ERROR_REF(error)); request_matcher_zombify_all_pending_calls(exec_ctx, &rm->request_matcher); } } GRPC_ERROR_UNREF(error); } static void maybe_finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_server *server) { size_t i; if (!gpr_atm_acq_load(&server->shutdown_flag) || server->shutdown_published) { return; } kill_pending_work_locked( exec_ctx, server, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Server Shutdown")); if (server->root_channel_data.next != &server->root_channel_data || server->listeners_destroyed < num_listeners(server)) { if (gpr_time_cmp(gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), server->last_shutdown_message_time), gpr_time_from_seconds(1, GPR_TIMESPAN)) >= 0) { server->last_shutdown_message_time = gpr_now(GPR_CLOCK_REALTIME); gpr_log(GPR_DEBUG, "Waiting for %d channels and %d/%d listeners to be destroyed" " before shutting down server", num_channels(server), num_listeners(server) - server->listeners_destroyed, num_listeners(server)); } return; } server->shutdown_published = 1; for (i = 0; i < server->num_shutdown_tags; i++) { server_ref(server); grpc_cq_end_op(exec_ctx, server->shutdown_tags[i].cq, server->shutdown_tags[i].tag, GRPC_ERROR_NONE, done_shutdown_event, server, &server->shutdown_tags[i].completion); } } static void server_on_recv_initial_metadata(grpc_exec_ctx *exec_ctx, void *ptr, grpc_error *error) { grpc_call_element *elem = ptr; call_data *calld = elem->call_data; gpr_timespec op_deadline; if (error == GRPC_ERROR_NONE) { GPR_ASSERT(calld->recv_initial_metadata->idx.named.path != NULL); GPR_ASSERT(calld->recv_initial_metadata->idx.named.authority != NULL); calld->path = grpc_slice_ref_internal( GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.path->md)); calld->host = grpc_slice_ref_internal( GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.authority->md)); calld->path_set = true; calld->host_set = true; grpc_metadata_batch_remove(exec_ctx, calld->recv_initial_metadata, calld->recv_initial_metadata->idx.named.path); grpc_metadata_batch_remove( exec_ctx, calld->recv_initial_metadata, calld->recv_initial_metadata->idx.named.authority); } else { GRPC_ERROR_REF(error); } op_deadline = calld->recv_initial_metadata->deadline; if (0 != gpr_time_cmp(op_deadline, gpr_inf_future(op_deadline.clock_type))) { calld->deadline = op_deadline; } if (calld->host_set && calld->path_set) { /* do nothing */ } else { grpc_error *src_error = error; error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Missing :authority or :path", &error, 1); GRPC_ERROR_UNREF(src_error); } grpc_closure_run(exec_ctx, calld->on_done_recv_initial_metadata, error); } static void server_mutate_op(grpc_call_element *elem, grpc_transport_stream_op_batch *op) { call_data *calld = elem->call_data; if (op->recv_initial_metadata) { GPR_ASSERT(op->payload->recv_initial_metadata.recv_flags == NULL); calld->recv_initial_metadata = op->payload->recv_initial_metadata.recv_initial_metadata; calld->on_done_recv_initial_metadata = op->payload->recv_initial_metadata.recv_initial_metadata_ready; op->payload->recv_initial_metadata.recv_initial_metadata_ready = &calld->server_on_recv_initial_metadata; op->payload->recv_initial_metadata.recv_flags = &calld->recv_initial_metadata_flags; } } static void server_start_transport_stream_op_batch( grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op_batch *op) { GRPC_CALL_LOG_OP(GPR_INFO, elem, op); server_mutate_op(elem, op); grpc_call_next_op(exec_ctx, elem, op); } static void got_initial_metadata(grpc_exec_ctx *exec_ctx, void *ptr, grpc_error *error) { grpc_call_element *elem = ptr; call_data *calld = elem->call_data; if (error == GRPC_ERROR_NONE) { start_new_rpc(exec_ctx, elem); } else { gpr_mu_lock(&calld->mu_state); if (calld->state == NOT_STARTED) { calld->state = ZOMBIED; gpr_mu_unlock(&calld->mu_state); grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem, grpc_schedule_on_exec_ctx); grpc_closure_sched(exec_ctx, &calld->kill_zombie_closure, GRPC_ERROR_NONE); } else if (calld->state == PENDING) { calld->state = ZOMBIED; gpr_mu_unlock(&calld->mu_state); /* zombied call will be destroyed when it's removed from the pending queue... later */ } else { gpr_mu_unlock(&calld->mu_state); } } } static void accept_stream(grpc_exec_ctx *exec_ctx, void *cd, grpc_transport *transport, const void *transport_server_data) { channel_data *chand = cd; /* create a call */ grpc_call_create_args args; memset(&args, 0, sizeof(args)); args.channel = chand->channel; args.server_transport_data = transport_server_data; args.send_deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC); grpc_call *call; grpc_error *error = grpc_call_create(exec_ctx, &args, &call); grpc_call_element *elem = grpc_call_stack_element(grpc_call_get_call_stack(call), 0); if (error != GRPC_ERROR_NONE) { got_initial_metadata(exec_ctx, elem, error); GRPC_ERROR_UNREF(error); return; } call_data *calld = elem->call_data; grpc_op op; memset(&op, 0, sizeof(op)); op.op = GRPC_OP_RECV_INITIAL_METADATA; op.data.recv_initial_metadata.recv_initial_metadata = &calld->initial_metadata; grpc_closure_init(&calld->got_initial_metadata, got_initial_metadata, elem, grpc_schedule_on_exec_ctx); grpc_call_start_batch_and_execute(exec_ctx, call, &op, 1, &calld->got_initial_metadata); } static void channel_connectivity_changed(grpc_exec_ctx *exec_ctx, void *cd, grpc_error *error) { channel_data *chand = cd; grpc_server *server = chand->server; if (chand->connectivity_state != GRPC_CHANNEL_SHUTDOWN) { grpc_transport_op *op = grpc_make_transport_op(NULL); op->on_connectivity_state_change = &chand->channel_connectivity_changed, op->connectivity_state = &chand->connectivity_state; grpc_channel_next_op(exec_ctx, grpc_channel_stack_element( grpc_channel_get_channel_stack(chand->channel), 0), op); } else { gpr_mu_lock(&server->mu_global); destroy_channel(exec_ctx, chand, GRPC_ERROR_REF(error)); gpr_mu_unlock(&server->mu_global); GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, chand->channel, "connectivity"); } } static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_element_args *args) { call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; memset(calld, 0, sizeof(call_data)); calld->deadline = gpr_inf_future(GPR_CLOCK_REALTIME); calld->call = grpc_call_from_top_element(elem); gpr_mu_init(&calld->mu_state); grpc_closure_init(&calld->server_on_recv_initial_metadata, server_on_recv_initial_metadata, elem, grpc_schedule_on_exec_ctx); server_ref(chand->server); return GRPC_ERROR_NONE; } static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, grpc_closure *ignored) { channel_data *chand = elem->channel_data; call_data *calld = elem->call_data; GPR_ASSERT(calld->state != PENDING); if (calld->host_set) { grpc_slice_unref_internal(exec_ctx, calld->host); } if (calld->path_set) { grpc_slice_unref_internal(exec_ctx, calld->path); } grpc_metadata_array_destroy(&calld->initial_metadata); gpr_mu_destroy(&calld->mu_state); server_unref(exec_ctx, chand->server); } static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_channel_element_args *args) { channel_data *chand = elem->channel_data; GPR_ASSERT(args->is_first); GPR_ASSERT(!args->is_last); chand->server = NULL; chand->channel = NULL; chand->next = chand->prev = chand; chand->registered_methods = NULL; chand->connectivity_state = GRPC_CHANNEL_IDLE; grpc_closure_init(&chand->channel_connectivity_changed, channel_connectivity_changed, chand, grpc_schedule_on_exec_ctx); return GRPC_ERROR_NONE; } static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) { size_t i; channel_data *chand = elem->channel_data; if (chand->registered_methods) { for (i = 0; i < chand->registered_method_slots; i++) { grpc_slice_unref_internal(exec_ctx, chand->registered_methods[i].method); if (chand->registered_methods[i].has_host) { grpc_slice_unref_internal(exec_ctx, chand->registered_methods[i].host); } } gpr_free(chand->registered_methods); } if (chand->server) { gpr_mu_lock(&chand->server->mu_global); chand->next->prev = chand->prev; chand->prev->next = chand->next; chand->next = chand->prev = chand; maybe_finish_shutdown(exec_ctx, chand->server); gpr_mu_unlock(&chand->server->mu_global); server_unref(exec_ctx, chand->server); } } const grpc_channel_filter grpc_server_top_filter = { server_start_transport_stream_op_batch, grpc_channel_next_op, sizeof(call_data), init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, destroy_call_elem, sizeof(channel_data), init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer, grpc_channel_next_get_info, "server", }; static void register_completion_queue(grpc_server *server, grpc_completion_queue *cq, bool is_non_listening, void *reserved) { size_t i, n; GPR_ASSERT(!reserved); for (i = 0; i < server->cq_count; i++) { if (server->cqs[i] == cq) return; } grpc_cq_mark_server_cq(cq); if (is_non_listening) { grpc_cq_mark_non_listening_server_cq(cq); } GRPC_CQ_INTERNAL_REF(cq, "server"); n = server->cq_count++; server->cqs = gpr_realloc(server->cqs, server->cq_count * sizeof(grpc_completion_queue *)); server->cqs[n] = cq; } void grpc_server_register_completion_queue(grpc_server *server, grpc_completion_queue *cq, void *reserved) { GRPC_API_TRACE( "grpc_server_register_completion_queue(server=%p, cq=%p, reserved=%p)", 3, (server, cq, reserved)); register_completion_queue(server, cq, false, reserved); } void grpc_server_register_non_listening_completion_queue( grpc_server *server, grpc_completion_queue *cq, void *reserved) { GRPC_API_TRACE( "grpc_server_register_non_listening_completion_queue(server=%p, cq=%p, " "reserved=%p)", 3, (server, cq, reserved)); register_completion_queue(server, cq, true, reserved); } grpc_server *grpc_server_create(const grpc_channel_args *args, void *reserved) { GRPC_API_TRACE("grpc_server_create(%p, %p)", 2, (args, reserved)); grpc_server *server = gpr_zalloc(sizeof(grpc_server)); GPR_ASSERT(grpc_is_initialized() && "call grpc_init()"); gpr_mu_init(&server->mu_global); gpr_mu_init(&server->mu_call); /* decremented by grpc_server_destroy */ gpr_ref_init(&server->internal_refcount, 1); server->root_channel_data.next = server->root_channel_data.prev = &server->root_channel_data; /* TODO(ctiller): expose a channel_arg for this */ server->max_requested_calls_per_cq = 32768; server->channel_args = grpc_channel_args_copy(args); return server; } static int streq(const char *a, const char *b) { if (a == NULL && b == NULL) return 1; if (a == NULL) return 0; if (b == NULL) return 0; return 0 == strcmp(a, b); } void *grpc_server_register_method( grpc_server *server, const char *method, const char *host, grpc_server_register_method_payload_handling payload_handling, uint32_t flags) { registered_method *m; GRPC_API_TRACE( "grpc_server_register_method(server=%p, method=%s, host=%s, " "flags=0x%08x)", 4, (server, method, host, flags)); if (!method) { gpr_log(GPR_ERROR, "grpc_server_register_method method string cannot be NULL"); return NULL; } for (m = server->registered_methods; m; m = m->next) { if (streq(m->method, method) && streq(m->host, host)) { gpr_log(GPR_ERROR, "duplicate registration for %s@%s", method, host ? host : "*"); return NULL; } } if ((flags & ~GRPC_INITIAL_METADATA_USED_MASK) != 0) { gpr_log(GPR_ERROR, "grpc_server_register_method invalid flags 0x%08x", flags); return NULL; } m = gpr_zalloc(sizeof(registered_method)); m->method = gpr_strdup(method); m->host = gpr_strdup(host); m->next = server->registered_methods; m->payload_handling = payload_handling; m->flags = flags; server->registered_methods = m; return m; } void grpc_server_start(grpc_server *server) { listener *l; size_t i; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE("grpc_server_start(server=%p)", 1, (server)); server->started = true; server->pollset_count = 0; server->pollsets = gpr_malloc(sizeof(grpc_pollset *) * server->cq_count); server->request_freelist_per_cq = gpr_malloc(sizeof(*server->request_freelist_per_cq) * server->cq_count); server->requested_calls_per_cq = gpr_malloc(sizeof(*server->requested_calls_per_cq) * server->cq_count); for (i = 0; i < server->cq_count; i++) { if (!grpc_cq_is_non_listening_server_cq(server->cqs[i])) { server->pollsets[server->pollset_count++] = grpc_cq_pollset(server->cqs[i]); } server->request_freelist_per_cq[i] = gpr_stack_lockfree_create((size_t)server->max_requested_calls_per_cq); for (int j = 0; j < server->max_requested_calls_per_cq; j++) { gpr_stack_lockfree_push(server->request_freelist_per_cq[i], j); } server->requested_calls_per_cq[i] = gpr_malloc((size_t)server->max_requested_calls_per_cq * sizeof(*server->requested_calls_per_cq[i])); } request_matcher_init(&server->unregistered_request_matcher, (size_t)server->max_requested_calls_per_cq, server); for (registered_method *rm = server->registered_methods; rm; rm = rm->next) { request_matcher_init(&rm->request_matcher, (size_t)server->max_requested_calls_per_cq, server); } for (l = server->listeners; l; l = l->next) { l->start(&exec_ctx, server, l->arg, server->pollsets, server->pollset_count); } grpc_exec_ctx_finish(&exec_ctx); } void grpc_server_get_pollsets(grpc_server *server, grpc_pollset ***pollsets, size_t *pollset_count) { *pollset_count = server->pollset_count; *pollsets = server->pollsets; } void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s, grpc_transport *transport, grpc_pollset *accepting_pollset, const grpc_channel_args *args) { size_t num_registered_methods; size_t alloc; registered_method *rm; channel_registered_method *crm; grpc_channel *channel; channel_data *chand; uint32_t hash; size_t slots; uint32_t probes; uint32_t max_probes = 0; grpc_transport_op *op = NULL; channel = grpc_channel_create(exec_ctx, NULL, args, GRPC_SERVER_CHANNEL, transport); chand = (channel_data *)grpc_channel_stack_element( grpc_channel_get_channel_stack(channel), 0) ->channel_data; chand->server = s; server_ref(s); chand->channel = channel; size_t cq_idx; grpc_completion_queue *accepting_cq = grpc_cq_from_pollset(accepting_pollset); for (cq_idx = 0; cq_idx < s->cq_count; cq_idx++) { if (s->cqs[cq_idx] == accepting_cq) break; } if (cq_idx == s->cq_count) { /* completion queue not found: pick a random one to publish new calls to */ cq_idx = (size_t)rand() % s->cq_count; } chand->cq_idx = cq_idx; num_registered_methods = 0; for (rm = s->registered_methods; rm; rm = rm->next) { num_registered_methods++; } /* build a lookup table phrased in terms of mdstr's in this channels context to quickly find registered methods */ if (num_registered_methods > 0) { slots = 2 * num_registered_methods; alloc = sizeof(channel_registered_method) * slots; chand->registered_methods = gpr_zalloc(alloc); for (rm = s->registered_methods; rm; rm = rm->next) { grpc_slice host; bool has_host; grpc_slice method; if (rm->host != NULL) { host = grpc_slice_intern(grpc_slice_from_static_string(rm->host)); has_host = true; } else { has_host = false; } method = grpc_slice_intern(grpc_slice_from_static_string(rm->method)); hash = GRPC_MDSTR_KV_HASH(has_host ? grpc_slice_hash(host) : 0, grpc_slice_hash(method)); for (probes = 0; chand->registered_methods[(hash + probes) % slots] .server_registered_method != NULL; probes++) ; if (probes > max_probes) max_probes = probes; crm = &chand->registered_methods[(hash + probes) % slots]; crm->server_registered_method = rm; crm->flags = rm->flags; crm->has_host = has_host; if (has_host) { crm->host = host; } crm->method = method; } GPR_ASSERT(slots <= UINT32_MAX); chand->registered_method_slots = (uint32_t)slots; chand->registered_method_max_probes = max_probes; } gpr_mu_lock(&s->mu_global); chand->next = &s->root_channel_data; chand->prev = chand->next->prev; chand->next->prev = chand->prev->next = chand; gpr_mu_unlock(&s->mu_global); GRPC_CHANNEL_INTERNAL_REF(channel, "connectivity"); op = grpc_make_transport_op(NULL); op->set_accept_stream = true; op->set_accept_stream_fn = accept_stream; op->set_accept_stream_user_data = chand; op->on_connectivity_state_change = &chand->channel_connectivity_changed; op->connectivity_state = &chand->connectivity_state; if (gpr_atm_acq_load(&s->shutdown_flag) != 0) { op->disconnect_with_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Server shutdown"); } grpc_transport_perform_op(exec_ctx, transport, op); } void done_published_shutdown(grpc_exec_ctx *exec_ctx, void *done_arg, grpc_cq_completion *storage) { (void)done_arg; gpr_free(storage); } static void listener_destroy_done(grpc_exec_ctx *exec_ctx, void *s, grpc_error *error) { grpc_server *server = s; gpr_mu_lock(&server->mu_global); server->listeners_destroyed++; maybe_finish_shutdown(exec_ctx, server); gpr_mu_unlock(&server->mu_global); } void grpc_server_shutdown_and_notify(grpc_server *server, grpc_completion_queue *cq, void *tag) { listener *l; shutdown_tag *sdt; channel_broadcaster broadcaster; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE("grpc_server_shutdown_and_notify(server=%p, cq=%p, tag=%p)", 3, (server, cq, tag)); /* lock, and gather up some stuff to do */ gpr_mu_lock(&server->mu_global); grpc_cq_begin_op(cq, tag); if (server->shutdown_published) { grpc_cq_end_op(&exec_ctx, cq, tag, GRPC_ERROR_NONE, done_published_shutdown, NULL, gpr_malloc(sizeof(grpc_cq_completion))); gpr_mu_unlock(&server->mu_global); goto done; } server->shutdown_tags = gpr_realloc(server->shutdown_tags, sizeof(shutdown_tag) * (server->num_shutdown_tags + 1)); sdt = &server->shutdown_tags[server->num_shutdown_tags++]; sdt->tag = tag; sdt->cq = cq; if (gpr_atm_acq_load(&server->shutdown_flag)) { gpr_mu_unlock(&server->mu_global); goto done; } server->last_shutdown_message_time = gpr_now(GPR_CLOCK_REALTIME); channel_broadcaster_init(server, &broadcaster); gpr_atm_rel_store(&server->shutdown_flag, 1); /* collect all unregistered then registered calls */ gpr_mu_lock(&server->mu_call); kill_pending_work_locked( &exec_ctx, server, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Server Shutdown")); gpr_mu_unlock(&server->mu_call); maybe_finish_shutdown(&exec_ctx, server); gpr_mu_unlock(&server->mu_global); /* Shutdown listeners */ for (l = server->listeners; l; l = l->next) { grpc_closure_init(&l->destroy_done, listener_destroy_done, server, grpc_schedule_on_exec_ctx); l->destroy(&exec_ctx, server, l->arg, &l->destroy_done); } channel_broadcaster_shutdown(&exec_ctx, &broadcaster, true /* send_goaway */, GRPC_ERROR_NONE); done: grpc_exec_ctx_finish(&exec_ctx); } void grpc_server_cancel_all_calls(grpc_server *server) { channel_broadcaster broadcaster; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE("grpc_server_cancel_all_calls(server=%p)", 1, (server)); gpr_mu_lock(&server->mu_global); channel_broadcaster_init(server, &broadcaster); gpr_mu_unlock(&server->mu_global); channel_broadcaster_shutdown( &exec_ctx, &broadcaster, false /* send_goaway */, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Cancelling all calls")); grpc_exec_ctx_finish(&exec_ctx); } void grpc_server_destroy(grpc_server *server) { listener *l; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE("grpc_server_destroy(server=%p)", 1, (server)); gpr_mu_lock(&server->mu_global); GPR_ASSERT(gpr_atm_acq_load(&server->shutdown_flag) || !server->listeners); GPR_ASSERT(server->listeners_destroyed == num_listeners(server)); while (server->listeners) { l = server->listeners; server->listeners = l->next; gpr_free(l); } gpr_mu_unlock(&server->mu_global); server_unref(&exec_ctx, server); grpc_exec_ctx_finish(&exec_ctx); } void grpc_server_add_listener( grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg, void (*start)(grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg, grpc_pollset **pollsets, size_t pollset_count), void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg, grpc_closure *on_done)) { listener *l = gpr_malloc(sizeof(listener)); l->arg = arg; l->start = start; l->destroy = destroy; l->next = server->listeners; server->listeners = l; } static grpc_call_error queue_call_request(grpc_exec_ctx *exec_ctx, grpc_server *server, size_t cq_idx, requested_call *rc) { call_data *calld = NULL; request_matcher *rm = NULL; int request_id; if (gpr_atm_acq_load(&server->shutdown_flag)) { fail_call(exec_ctx, server, cq_idx, rc, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Server Shutdown")); return GRPC_CALL_OK; } request_id = gpr_stack_lockfree_pop(server->request_freelist_per_cq[cq_idx]); if (request_id == -1) { /* out of request ids: just fail this one */ fail_call(exec_ctx, server, cq_idx, rc, grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Out of request ids"), GRPC_ERROR_INT_LIMIT, server->max_requested_calls_per_cq)); return GRPC_CALL_OK; } switch (rc->type) { case BATCH_CALL: rm = &server->unregistered_request_matcher; break; case REGISTERED_CALL: rm = &rc->data.registered.registered_method->request_matcher; break; } server->requested_calls_per_cq[cq_idx][request_id] = *rc; gpr_free(rc); if (gpr_stack_lockfree_push(rm->requests_per_cq[cq_idx], request_id)) { /* this was the first queued request: we need to lock and start matching calls */ gpr_mu_lock(&server->mu_call); while ((calld = rm->pending_head) != NULL) { request_id = gpr_stack_lockfree_pop(rm->requests_per_cq[cq_idx]); if (request_id == -1) break; rm->pending_head = calld->pending_next; gpr_mu_unlock(&server->mu_call); gpr_mu_lock(&calld->mu_state); if (calld->state == ZOMBIED) { gpr_mu_unlock(&calld->mu_state); grpc_closure_init( &calld->kill_zombie_closure, kill_zombie, grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0), grpc_schedule_on_exec_ctx); grpc_closure_sched(exec_ctx, &calld->kill_zombie_closure, GRPC_ERROR_NONE); } else { GPR_ASSERT(calld->state == PENDING); calld->state = ACTIVATED; gpr_mu_unlock(&calld->mu_state); publish_call(exec_ctx, server, calld, cq_idx, &server->requested_calls_per_cq[cq_idx][request_id]); } gpr_mu_lock(&server->mu_call); } gpr_mu_unlock(&server->mu_call); } return GRPC_CALL_OK; } grpc_call_error grpc_server_request_call( grpc_server *server, grpc_call **call, grpc_call_details *details, grpc_metadata_array *initial_metadata, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag) { grpc_call_error error; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; requested_call *rc = gpr_malloc(sizeof(*rc)); GRPC_API_TRACE( "grpc_server_request_call(" "server=%p, call=%p, details=%p, initial_metadata=%p, " "cq_bound_to_call=%p, cq_for_notification=%p, tag=%p)", 7, (server, call, details, initial_metadata, cq_bound_to_call, cq_for_notification, tag)); size_t cq_idx; for (cq_idx = 0; cq_idx < server->cq_count; cq_idx++) { if (server->cqs[cq_idx] == cq_for_notification) { break; } } if (cq_idx == server->cq_count) { gpr_free(rc); error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE; goto done; } grpc_cq_begin_op(cq_for_notification, tag); details->reserved = NULL; rc->cq_idx = cq_idx; rc->type = BATCH_CALL; rc->server = server; rc->tag = tag; rc->cq_bound_to_call = cq_bound_to_call; rc->call = call; rc->data.batch.details = details; rc->initial_metadata = initial_metadata; error = queue_call_request(&exec_ctx, server, cq_idx, rc); done: grpc_exec_ctx_finish(&exec_ctx); return error; } grpc_call_error grpc_server_request_registered_call( grpc_server *server, void *rmp, grpc_call **call, gpr_timespec *deadline, grpc_metadata_array *initial_metadata, grpc_byte_buffer **optional_payload, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag) { grpc_call_error error; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; requested_call *rc = gpr_malloc(sizeof(*rc)); registered_method *rm = rmp; GRPC_API_TRACE( "grpc_server_request_registered_call(" "server=%p, rmp=%p, call=%p, deadline=%p, initial_metadata=%p, " "optional_payload=%p, cq_bound_to_call=%p, cq_for_notification=%p, " "tag=%p)", 9, (server, rmp, call, deadline, initial_metadata, optional_payload, cq_bound_to_call, cq_for_notification, tag)); size_t cq_idx; for (cq_idx = 0; cq_idx < server->cq_count; cq_idx++) { if (server->cqs[cq_idx] == cq_for_notification) { break; } } if (cq_idx == server->cq_count) { gpr_free(rc); error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE; goto done; } if ((optional_payload == NULL) != (rm->payload_handling == GRPC_SRM_PAYLOAD_NONE)) { gpr_free(rc); error = GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH; goto done; } grpc_cq_begin_op(cq_for_notification, tag); rc->cq_idx = cq_idx; rc->type = REGISTERED_CALL; rc->server = server; rc->tag = tag; rc->cq_bound_to_call = cq_bound_to_call; rc->call = call; rc->data.registered.registered_method = rm; rc->data.registered.deadline = deadline; rc->initial_metadata = initial_metadata; rc->data.registered.optional_payload = optional_payload; error = queue_call_request(&exec_ctx, server, cq_idx, rc); done: grpc_exec_ctx_finish(&exec_ctx); return error; } static void fail_call(grpc_exec_ctx *exec_ctx, grpc_server *server, size_t cq_idx, requested_call *rc, grpc_error *error) { *rc->call = NULL; rc->initial_metadata->count = 0; GPR_ASSERT(error != GRPC_ERROR_NONE); server_ref(server); grpc_cq_end_op(exec_ctx, server->cqs[cq_idx], rc->tag, error, done_request_event, rc, &rc->completion); } const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) { return server->channel_args; } int grpc_server_has_open_connections(grpc_server *server) { int r; gpr_mu_lock(&server->mu_global); r = server->root_channel_data.next != &server->root_channel_data; gpr_mu_unlock(&server->mu_global); return r; } grpc-1.3.2/src/core/lib/surface/server.h000066400000000000000000000062101310511640000200320ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SURFACE_SERVER_H #define GRPC_CORE_LIB_SURFACE_SERVER_H #include #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/transport/transport.h" extern const grpc_channel_filter grpc_server_top_filter; /** Lightweight tracing of server channel state */ extern int grpc_server_channel_trace; /* Add a listener to the server: when the server starts, it will call start, and when it shuts down, it will call destroy */ void grpc_server_add_listener( grpc_exec_ctx *exec_ctx, grpc_server *server, void *listener, void (*start)(grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg, grpc_pollset **pollsets, size_t npollsets), void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_server *server, void *arg, grpc_closure *on_done)); /* Setup a transport - creates a channel stack, binds the transport to the server */ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *server, grpc_transport *transport, grpc_pollset *accepting_pollset, const grpc_channel_args *args); const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server); int grpc_server_has_open_connections(grpc_server *server); /* Do not call this before grpc_server_start. Returns the pollsets and the * number of pollsets via 'pollsets' and 'pollset_count'. */ void grpc_server_get_pollsets(grpc_server *server, grpc_pollset ***pollsets, size_t *pollset_count); #endif /* GRPC_CORE_LIB_SURFACE_SERVER_H */ grpc-1.3.2/src/core/lib/surface/validate_metadata.c000066400000000000000000000103261310511640000221530ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include "src/core/lib/iomgr/error.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" static grpc_error *conforms_to(grpc_slice slice, const uint8_t *legal_bits, const char *err_desc) { const uint8_t *p = GRPC_SLICE_START_PTR(slice); const uint8_t *e = GRPC_SLICE_END_PTR(slice); for (; p != e; p++) { int idx = *p; int byte = idx / 8; int bit = idx % 8; if ((legal_bits[byte] & (1 << bit)) == 0) { char *dump = grpc_dump_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII); grpc_error *error = grpc_error_set_str( grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(err_desc), GRPC_ERROR_INT_OFFSET, p - GRPC_SLICE_START_PTR(slice)), GRPC_ERROR_STR_RAW_BYTES, grpc_slice_from_copied_string(dump)); gpr_free(dump); return error; } } return GRPC_ERROR_NONE; } static int error2int(grpc_error *error) { int r = (error == GRPC_ERROR_NONE); GRPC_ERROR_UNREF(error); return r; } grpc_error *grpc_validate_header_key_is_legal(grpc_slice slice) { static const uint8_t legal_header_bits[256 / 8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xff, 0x03, 0x00, 0x00, 0x00, 0x80, 0xfe, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; if (GRPC_SLICE_LENGTH(slice) == 0) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Metadata keys cannot be zero length"); } if (GRPC_SLICE_START_PTR(slice)[0] == ':') { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Metadata keys cannot start with :"); } return conforms_to(slice, legal_header_bits, "Illegal header key"); } int grpc_header_key_is_legal(grpc_slice slice) { return error2int(grpc_validate_header_key_is_legal(slice)); } grpc_error *grpc_validate_header_nonbin_value_is_legal(grpc_slice slice) { static const uint8_t legal_header_bits[256 / 8] = { 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; return conforms_to(slice, legal_header_bits, "Illegal header value"); } int grpc_header_nonbin_value_is_legal(grpc_slice slice) { return error2int(grpc_validate_header_nonbin_value_is_legal(slice)); } int grpc_is_binary_header(grpc_slice slice) { if (GRPC_SLICE_LENGTH(slice) < 5) return 0; return 0 == memcmp(GRPC_SLICE_END_PTR(slice) - 4, "-bin", 4); } grpc-1.3.2/src/core/lib/surface/validate_metadata.h000066400000000000000000000036111310511640000221570ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_SURFACE_VALIDATE_METADATA_H #define GRPC_CORE_LIB_SURFACE_VALIDATE_METADATA_H #include #include "src/core/lib/iomgr/error.h" grpc_error *grpc_validate_header_key_is_legal(grpc_slice slice); grpc_error *grpc_validate_header_nonbin_value_is_legal(grpc_slice slice); #endif /* GRPC_CORE_LIB_SURFACE_VALIDATE_METADATA_H */ grpc-1.3.2/src/core/lib/surface/version.c000066400000000000000000000034071310511640000202110ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* This file is autogenerated from: templates/src/core/surface/version.c.template */ #include const char *grpc_version_string(void) { return "3.0.0"; } const char *grpc_g_stands_for(void) { return "gentle"; } grpc-1.3.2/src/core/lib/transport/000077500000000000000000000000001310511640000167605ustar00rootroot00000000000000grpc-1.3.2/src/core/lib/transport/README.md000066400000000000000000000004541310511640000202420ustar00rootroot00000000000000# Transport Common implementation details for gRPC Transports. Transports multiplex messages across some single connection. In ext/ there are implementations atop [a custom http2 implementation](/src/core/ext/transport/chttp2/README.md) and atop [cronet](/src/core/ext/transport/cronet/README.md). grpc-1.3.2/src/core/lib/transport/bdp_estimator.c000066400000000000000000000076301310511640000217660ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/transport/bdp_estimator.h" #include #include #include int grpc_bdp_estimator_trace = 0; void grpc_bdp_estimator_init(grpc_bdp_estimator *estimator, const char *name) { estimator->estimate = 65536; estimator->ping_state = GRPC_BDP_PING_UNSCHEDULED; estimator->name = name; } bool grpc_bdp_estimator_get_estimate(grpc_bdp_estimator *estimator, int64_t *estimate) { *estimate = estimator->estimate; return true; } bool grpc_bdp_estimator_add_incoming_bytes(grpc_bdp_estimator *estimator, int64_t num_bytes) { estimator->accumulator += num_bytes; switch (estimator->ping_state) { case GRPC_BDP_PING_UNSCHEDULED: return true; case GRPC_BDP_PING_SCHEDULED: return false; case GRPC_BDP_PING_STARTED: return false; } GPR_UNREACHABLE_CODE(return false); } void grpc_bdp_estimator_schedule_ping(grpc_bdp_estimator *estimator) { if (grpc_bdp_estimator_trace) { gpr_log(GPR_DEBUG, "bdp[%s]:sched acc=%" PRId64 " est=%" PRId64, estimator->name, estimator->accumulator, estimator->estimate); } GPR_ASSERT(estimator->ping_state == GRPC_BDP_PING_UNSCHEDULED); estimator->ping_state = GRPC_BDP_PING_SCHEDULED; estimator->accumulator = 0; } void grpc_bdp_estimator_start_ping(grpc_bdp_estimator *estimator) { if (grpc_bdp_estimator_trace) { gpr_log(GPR_DEBUG, "bdp[%s]:start acc=%" PRId64 " est=%" PRId64, estimator->name, estimator->accumulator, estimator->estimate); } GPR_ASSERT(estimator->ping_state == GRPC_BDP_PING_SCHEDULED); estimator->ping_state = GRPC_BDP_PING_STARTED; estimator->accumulator = 0; } void grpc_bdp_estimator_complete_ping(grpc_bdp_estimator *estimator) { if (grpc_bdp_estimator_trace) { gpr_log(GPR_DEBUG, "bdp[%s]:complete acc=%" PRId64 " est=%" PRId64, estimator->name, estimator->accumulator, estimator->estimate); } GPR_ASSERT(estimator->ping_state == GRPC_BDP_PING_STARTED); if (estimator->accumulator > 2 * estimator->estimate / 3) { estimator->estimate *= 2; if (grpc_bdp_estimator_trace) { gpr_log(GPR_DEBUG, "bdp[%s]: estimate increased to %" PRId64, estimator->name, estimator->estimate); } } estimator->ping_state = GRPC_BDP_PING_UNSCHEDULED; estimator->accumulator = 0; } grpc-1.3.2/src/core/lib/transport/bdp_estimator.h000066400000000000000000000061221310511640000217660ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_TRANSPORT_BDP_ESTIMATOR_H #define GRPC_CORE_LIB_TRANSPORT_BDP_ESTIMATOR_H #include #include #define GRPC_BDP_SAMPLES 16 #define GRPC_BDP_MIN_SAMPLES_FOR_ESTIMATE 3 extern int grpc_bdp_estimator_trace; typedef enum { GRPC_BDP_PING_UNSCHEDULED, GRPC_BDP_PING_SCHEDULED, GRPC_BDP_PING_STARTED } grpc_bdp_estimator_ping_state; typedef struct grpc_bdp_estimator { grpc_bdp_estimator_ping_state ping_state; int64_t accumulator; int64_t estimate; const char *name; } grpc_bdp_estimator; void grpc_bdp_estimator_init(grpc_bdp_estimator *estimator, const char *name); // Returns true if a reasonable estimate could be obtained bool grpc_bdp_estimator_get_estimate(grpc_bdp_estimator *estimator, int64_t *estimate); // Returns true if the user should schedule a ping bool grpc_bdp_estimator_add_incoming_bytes(grpc_bdp_estimator *estimator, int64_t num_bytes); // Schedule a ping: call in response to receiving a true from // grpc_bdp_estimator_add_incoming_bytes once a ping has been scheduled by a // transport (but not necessarily started) void grpc_bdp_estimator_schedule_ping(grpc_bdp_estimator *estimator); // Start a ping: call after calling grpc_bdp_estimator_schedule_ping and once // the ping is on the wire void grpc_bdp_estimator_start_ping(grpc_bdp_estimator *estimator); // Completes a previously started ping void grpc_bdp_estimator_complete_ping(grpc_bdp_estimator *estimator); #endif /* GRPC_CORE_LIB_TRANSPORT_BDP_ESTIMATOR_H */ grpc-1.3.2/src/core/lib/transport/byte_stream.c000066400000000000000000000065121310511640000214460ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/transport/byte_stream.h" #include #include #include "src/core/lib/slice/slice_internal.h" int grpc_byte_stream_next(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream, grpc_slice *slice, size_t max_size_hint, grpc_closure *on_complete) { return byte_stream->next(exec_ctx, byte_stream, slice, max_size_hint, on_complete); } void grpc_byte_stream_destroy(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream) { byte_stream->destroy(exec_ctx, byte_stream); } /* slice_buffer_stream */ static int slice_buffer_stream_next(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream, grpc_slice *slice, size_t max_size_hint, grpc_closure *on_complete) { grpc_slice_buffer_stream *stream = (grpc_slice_buffer_stream *)byte_stream; GPR_ASSERT(stream->cursor < stream->backing_buffer->count); *slice = grpc_slice_ref_internal(stream->backing_buffer->slices[stream->cursor]); stream->cursor++; return 1; } static void slice_buffer_stream_destroy(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream) {} void grpc_slice_buffer_stream_init(grpc_slice_buffer_stream *stream, grpc_slice_buffer *slice_buffer, uint32_t flags) { GPR_ASSERT(slice_buffer->length <= UINT32_MAX); stream->base.length = (uint32_t)slice_buffer->length; stream->base.flags = flags; stream->base.next = slice_buffer_stream_next; stream->base.destroy = slice_buffer_stream_destroy; stream->backing_buffer = slice_buffer; stream->cursor = 0; } grpc-1.3.2/src/core/lib/transport/byte_stream.h000066400000000000000000000066521310511640000214600ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_TRANSPORT_BYTE_STREAM_H #define GRPC_CORE_LIB_TRANSPORT_BYTE_STREAM_H #include #include "src/core/lib/iomgr/exec_ctx.h" /** Internal bit flag for grpc_begin_message's \a flags signaling the use of * compression for the message */ #define GRPC_WRITE_INTERNAL_COMPRESS (0x80000000u) /** Mask of all valid internal flags. */ #define GRPC_WRITE_INTERNAL_USED_MASK (GRPC_WRITE_INTERNAL_COMPRESS) struct grpc_byte_stream; typedef struct grpc_byte_stream grpc_byte_stream; struct grpc_byte_stream { uint32_t length; uint32_t flags; int (*next)(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream, grpc_slice *slice, size_t max_size_hint, grpc_closure *on_complete); void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream); }; /* returns 1 if the bytes are available immediately (in which case * on_complete will not be called), 0 if the bytes will be available * asynchronously. * * max_size_hint can be set as a hint as to the maximum number * of bytes that would be acceptable to read. * * once a slice is returned into *slice, it is owned by the caller. */ int grpc_byte_stream_next(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream, grpc_slice *slice, size_t max_size_hint, grpc_closure *on_complete); void grpc_byte_stream_destroy(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream); /* grpc_byte_stream that wraps a slice buffer */ typedef struct grpc_slice_buffer_stream { grpc_byte_stream base; grpc_slice_buffer *backing_buffer; size_t cursor; } grpc_slice_buffer_stream; void grpc_slice_buffer_stream_init(grpc_slice_buffer_stream *stream, grpc_slice_buffer *slice_buffer, uint32_t flags); #endif /* GRPC_CORE_LIB_TRANSPORT_BYTE_STREAM_H */ grpc-1.3.2/src/core/lib/transport/connectivity_state.c000066400000000000000000000172401310511640000230460ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/transport/connectivity_state.h" #include #include #include #include int grpc_connectivity_state_trace = 0; const char *grpc_connectivity_state_name(grpc_connectivity_state state) { switch (state) { case GRPC_CHANNEL_INIT: return "INIT"; case GRPC_CHANNEL_IDLE: return "IDLE"; case GRPC_CHANNEL_CONNECTING: return "CONNECTING"; case GRPC_CHANNEL_READY: return "READY"; case GRPC_CHANNEL_TRANSIENT_FAILURE: return "TRANSIENT_FAILURE"; case GRPC_CHANNEL_SHUTDOWN: return "SHUTDOWN"; } GPR_UNREACHABLE_CODE(return "UNKNOWN"); } void grpc_connectivity_state_init(grpc_connectivity_state_tracker *tracker, grpc_connectivity_state init_state, const char *name) { gpr_atm_no_barrier_store(&tracker->current_state_atm, init_state); tracker->current_error = GRPC_ERROR_NONE; tracker->watchers = NULL; tracker->name = gpr_strdup(name); } void grpc_connectivity_state_destroy(grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker) { grpc_error *error; grpc_connectivity_state_watcher *w; while ((w = tracker->watchers)) { tracker->watchers = w->next; if (GRPC_CHANNEL_SHUTDOWN != *w->current) { *w->current = GRPC_CHANNEL_SHUTDOWN; error = GRPC_ERROR_NONE; } else { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Shutdown connectivity owner"); } grpc_closure_sched(exec_ctx, w->notify, error); gpr_free(w); } GRPC_ERROR_UNREF(tracker->current_error); gpr_free(tracker->name); } grpc_connectivity_state grpc_connectivity_state_check( grpc_connectivity_state_tracker *tracker) { grpc_connectivity_state cur = (grpc_connectivity_state)gpr_atm_no_barrier_load( &tracker->current_state_atm); if (grpc_connectivity_state_trace) { gpr_log(GPR_DEBUG, "CONWATCH: %p %s: get %s", tracker, tracker->name, grpc_connectivity_state_name(cur)); } return cur; } grpc_connectivity_state grpc_connectivity_state_get( grpc_connectivity_state_tracker *tracker, grpc_error **error) { grpc_connectivity_state cur = (grpc_connectivity_state)gpr_atm_no_barrier_load( &tracker->current_state_atm); if (grpc_connectivity_state_trace) { gpr_log(GPR_DEBUG, "CONWATCH: %p %s: get %s", tracker, tracker->name, grpc_connectivity_state_name(cur)); } if (error != NULL) { *error = GRPC_ERROR_REF(tracker->current_error); } return cur; } bool grpc_connectivity_state_has_watchers( grpc_connectivity_state_tracker *connectivity_state) { return connectivity_state->watchers != NULL; } bool grpc_connectivity_state_notify_on_state_change( grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker, grpc_connectivity_state *current, grpc_closure *notify) { grpc_connectivity_state cur = (grpc_connectivity_state)gpr_atm_no_barrier_load( &tracker->current_state_atm); if (grpc_connectivity_state_trace) { if (current == NULL) { gpr_log(GPR_DEBUG, "CONWATCH: %p %s: unsubscribe notify=%p", tracker, tracker->name, notify); } else { gpr_log(GPR_DEBUG, "CONWATCH: %p %s: from %s [cur=%s] notify=%p", tracker, tracker->name, grpc_connectivity_state_name(*current), grpc_connectivity_state_name(cur), notify); } } if (current == NULL) { grpc_connectivity_state_watcher *w = tracker->watchers; if (w != NULL && w->notify == notify) { grpc_closure_sched(exec_ctx, notify, GRPC_ERROR_CANCELLED); tracker->watchers = w->next; gpr_free(w); return false; } while (w != NULL) { grpc_connectivity_state_watcher *rm_candidate = w->next; if (rm_candidate != NULL && rm_candidate->notify == notify) { grpc_closure_sched(exec_ctx, notify, GRPC_ERROR_CANCELLED); w->next = w->next->next; gpr_free(rm_candidate); return false; } w = w->next; } return false; } else { if (cur != *current) { *current = cur; grpc_closure_sched(exec_ctx, notify, GRPC_ERROR_REF(tracker->current_error)); } else { grpc_connectivity_state_watcher *w = gpr_malloc(sizeof(*w)); w->current = current; w->notify = notify; w->next = tracker->watchers; tracker->watchers = w; } return cur == GRPC_CHANNEL_IDLE; } } void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker, grpc_connectivity_state state, grpc_error *error, const char *reason) { grpc_connectivity_state cur = (grpc_connectivity_state)gpr_atm_no_barrier_load( &tracker->current_state_atm); grpc_connectivity_state_watcher *w; if (grpc_connectivity_state_trace) { const char *error_string = grpc_error_string(error); gpr_log(GPR_DEBUG, "SET: %p %s: %s --> %s [%s] error=%p %s", tracker, tracker->name, grpc_connectivity_state_name(cur), grpc_connectivity_state_name(state), reason, error, error_string); } switch (state) { case GRPC_CHANNEL_INIT: case GRPC_CHANNEL_CONNECTING: case GRPC_CHANNEL_IDLE: case GRPC_CHANNEL_READY: GPR_ASSERT(error == GRPC_ERROR_NONE); break; case GRPC_CHANNEL_SHUTDOWN: case GRPC_CHANNEL_TRANSIENT_FAILURE: GPR_ASSERT(error != GRPC_ERROR_NONE); break; } GRPC_ERROR_UNREF(tracker->current_error); tracker->current_error = error; if (cur == state) { return; } GPR_ASSERT(cur != GRPC_CHANNEL_SHUTDOWN); gpr_atm_no_barrier_store(&tracker->current_state_atm, state); while ((w = tracker->watchers) != NULL) { *w->current = state; tracker->watchers = w->next; if (grpc_connectivity_state_trace) { gpr_log(GPR_DEBUG, "NOTIFY: %p %s: %p", tracker, tracker->name, w->notify); } grpc_closure_sched(exec_ctx, w->notify, GRPC_ERROR_REF(tracker->current_error)); gpr_free(w); } } grpc-1.3.2/src/core/lib/transport/connectivity_state.h000066400000000000000000000104271310511640000230530ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_TRANSPORT_CONNECTIVITY_STATE_H #define GRPC_CORE_LIB_TRANSPORT_CONNECTIVITY_STATE_H #include #include "src/core/lib/iomgr/exec_ctx.h" typedef struct grpc_connectivity_state_watcher { /** we keep watchers in a linked list */ struct grpc_connectivity_state_watcher *next; /** closure to notify on change */ grpc_closure *notify; /** the current state as believed by the watcher */ grpc_connectivity_state *current; } grpc_connectivity_state_watcher; typedef struct { /** current grpc_connectivity_state */ gpr_atm current_state_atm; /** error associated with state */ grpc_error *current_error; /** all our watchers */ grpc_connectivity_state_watcher *watchers; /** a name to help debugging */ char *name; } grpc_connectivity_state_tracker; extern int grpc_connectivity_state_trace; /** enum --> string conversion */ const char *grpc_connectivity_state_name(grpc_connectivity_state state); void grpc_connectivity_state_init(grpc_connectivity_state_tracker *tracker, grpc_connectivity_state init_state, const char *name); void grpc_connectivity_state_destroy(grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker); /** Set connectivity state; not thread safe; access must be serialized with an * external lock */ void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker, grpc_connectivity_state state, grpc_error *associated_error, const char *reason); /** Return true if this connectivity state has watchers. Access must be serialized with an external lock. */ bool grpc_connectivity_state_has_watchers( grpc_connectivity_state_tracker *tracker); /** Return the last seen connectivity state. No need to synchronize access. */ grpc_connectivity_state grpc_connectivity_state_check( grpc_connectivity_state_tracker *tracker); /** Return the last seen connectivity state, and the associated error. Access must be serialized with an external lock. */ grpc_connectivity_state grpc_connectivity_state_get( grpc_connectivity_state_tracker *tracker, grpc_error **error); /** Return 1 if the channel should start connecting, 0 otherwise. If current==NULL cancel notify if it is already queued (success==0 in that case). Access must be serialized with an external lock. */ bool grpc_connectivity_state_notify_on_state_change( grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker, grpc_connectivity_state *current, grpc_closure *notify); #endif /* GRPC_CORE_LIB_TRANSPORT_CONNECTIVITY_STATE_H */ grpc-1.3.2/src/core/lib/transport/error_utils.c000066400000000000000000000116771310511640000215110ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/transport/error_utils.h" #include "src/core/lib/iomgr/error_internal.h" #include "src/core/lib/transport/status_conversion.h" static grpc_error *recursively_find_error_with_field(grpc_error *error, grpc_error_ints which) { // If the error itself has a status code, return it. if (grpc_error_get_int(error, which, NULL)) { return error; } if (grpc_error_is_special(error)) return NULL; // Otherwise, search through its children. uint8_t slot = error->first_err; while (slot != UINT8_MAX) { grpc_linked_error *lerr = (grpc_linked_error *)(error->arena + slot); grpc_error *result = recursively_find_error_with_field(lerr->err, which); if (result) return result; slot = lerr->next; } return NULL; } void grpc_error_get_status(grpc_error *error, gpr_timespec deadline, grpc_status_code *code, grpc_slice *slice, grpc_http2_error_code *http_error) { // Start with the parent error and recurse through the tree of children // until we find the first one that has a status code. grpc_error *found_error = recursively_find_error_with_field(error, GRPC_ERROR_INT_GRPC_STATUS); if (found_error == NULL) { /// If no grpc-status exists, retry through the tree to find a http2 error /// code found_error = recursively_find_error_with_field(error, GRPC_ERROR_INT_HTTP2_ERROR); } // If we found an error with a status code above, use that; otherwise, // fall back to using the parent error. if (found_error == NULL) found_error = error; grpc_status_code status = GRPC_STATUS_UNKNOWN; intptr_t integer; if (grpc_error_get_int(found_error, GRPC_ERROR_INT_GRPC_STATUS, &integer)) { status = (grpc_status_code)integer; } else if (grpc_error_get_int(found_error, GRPC_ERROR_INT_HTTP2_ERROR, &integer)) { status = grpc_http2_error_to_grpc_status((grpc_http2_error_code)integer, deadline); } if (code != NULL) *code = status; if (http_error != NULL) { if (grpc_error_get_int(found_error, GRPC_ERROR_INT_HTTP2_ERROR, &integer)) { *http_error = (grpc_http2_error_code)integer; } else if (grpc_error_get_int(found_error, GRPC_ERROR_INT_GRPC_STATUS, &integer)) { *http_error = grpc_status_to_http2_error((grpc_status_code)integer); } else { *http_error = found_error == GRPC_ERROR_NONE ? GRPC_HTTP2_NO_ERROR : GRPC_HTTP2_INTERNAL_ERROR; } } // If the error has a status message, use it. Otherwise, fall back to // the error description. if (slice != NULL) { if (!grpc_error_get_str(found_error, GRPC_ERROR_STR_GRPC_MESSAGE, slice)) { if (!grpc_error_get_str(found_error, GRPC_ERROR_STR_DESCRIPTION, slice)) { *slice = grpc_slice_from_static_string("unknown error"); } } } if (found_error == NULL) found_error = error; } bool grpc_error_has_clear_grpc_status(grpc_error *error) { if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, NULL)) { return true; } uint8_t slot = error->first_err; while (slot != UINT8_MAX) { grpc_linked_error *lerr = (grpc_linked_error *)(error->arena + slot); if (grpc_error_has_clear_grpc_status(lerr->err)) { return true; } slot = lerr->next; } return false; } grpc-1.3.2/src/core/lib/transport/error_utils.h000066400000000000000000000052071310511640000215060ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_TRANSPORT_ERROR_UTILS_H #define GRPC_CORE_LIB_TRANSPORT_ERROR_UTILS_H #include "src/core/lib/iomgr/error.h" #include "src/core/lib/transport/http2_errors.h" /// A utility function to get the status code and message to be returned /// to the application. If not set in the top-level message, looks /// through child errors until it finds the first one with these attributes. /// All attributes are pulled from the same child error. If any of the /// attributes (code, msg, http_status) are unneeded, they can be passed as /// NULL. void grpc_error_get_status(grpc_error *error, gpr_timespec deadline, grpc_status_code *code, grpc_slice *slice, grpc_http2_error_code *http_status); /// A utility function to check whether there is a clear status code that /// doesn't need to be guessed in \a error. This means that \a error or some /// child has GRPC_ERROR_INT_GRPC_STATUS set, or that it is GRPC_ERROR_NONE or /// GRPC_ERROR_CANCELLED bool grpc_error_has_clear_grpc_status(grpc_error *error); #endif /* GRPC_CORE_LIB_TRANSPORT_ERROR_UTILS_H */ grpc-1.3.2/src/core/lib/transport/http2_errors.h000066400000000000000000000044611310511640000215730ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_TRANSPORT_HTTP2_ERRORS_H #define GRPC_CORE_LIB_TRANSPORT_HTTP2_ERRORS_H /* error codes for RST_STREAM from http2 draft 14 section 7 */ typedef enum { GRPC_HTTP2_NO_ERROR = 0x0, GRPC_HTTP2_PROTOCOL_ERROR = 0x1, GRPC_HTTP2_INTERNAL_ERROR = 0x2, GRPC_HTTP2_FLOW_CONTROL_ERROR = 0x3, GRPC_HTTP2_SETTINGS_TIMEOUT = 0x4, GRPC_HTTP2_STREAM_CLOSED = 0x5, GRPC_HTTP2_FRAME_SIZE_ERROR = 0x6, GRPC_HTTP2_REFUSED_STREAM = 0x7, GRPC_HTTP2_CANCEL = 0x8, GRPC_HTTP2_COMPRESSION_ERROR = 0x9, GRPC_HTTP2_CONNECT_ERROR = 0xa, GRPC_HTTP2_ENHANCE_YOUR_CALM = 0xb, GRPC_HTTP2_INADEQUATE_SECURITY = 0xc, /* force use of a default clause */ GRPC_HTTP2__ERROR_DO_NOT_USE = -1 } grpc_http2_error_code; #endif /* GRPC_CORE_LIB_TRANSPORT_HTTP2_ERRORS_H */ grpc-1.3.2/src/core/lib/transport/metadata.c000066400000000000000000000455521310511640000207170ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/transport/metadata.h" #include #include #include #include #include #include #include #include #include #include #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/murmur_hash.h" #include "src/core/lib/support/string.h" #include "src/core/lib/transport/static_metadata.h" /* There are two kinds of mdelem and mdstr instances. * Static instances are declared in static_metadata.{h,c} and * are initialized by grpc_mdctx_global_init(). * Dynamic instances are stored in hash tables on grpc_mdctx, and are backed * by internal_string and internal_element structures. * Internal helper functions here-in (is_mdstr_static, is_mdelem_static) are * used to determine which kind of element a pointer refers to. */ #ifdef GRPC_METADATA_REFCOUNT_DEBUG #define DEBUG_ARGS , const char *file, int line #define FWD_DEBUG_ARGS , file, line #define REF_MD_LOCKED(shard, s) ref_md_locked((shard), (s), __FILE__, __LINE__) #else #define DEBUG_ARGS #define FWD_DEBUG_ARGS #define REF_MD_LOCKED(shard, s) ref_md_locked((shard), (s)) #endif #define INITIAL_SHARD_CAPACITY 8 #define LOG2_SHARD_COUNT 4 #define SHARD_COUNT ((size_t)(1 << LOG2_SHARD_COUNT)) #define TABLE_IDX(hash, capacity) (((hash) >> (LOG2_SHARD_COUNT)) % (capacity)) #define SHARD_IDX(hash) ((hash) & ((1 << (LOG2_SHARD_COUNT)) - 1)) typedef void (*destroy_user_data_func)(void *user_data); /* Shadow structure for grpc_mdelem_data for interned elements */ typedef struct interned_metadata { /* must be byte compatible with grpc_mdelem_data */ grpc_slice key; grpc_slice value; /* private only data */ gpr_atm refcnt; gpr_mu mu_user_data; gpr_atm destroy_user_data; gpr_atm user_data; struct interned_metadata *bucket_next; } interned_metadata; /* Shadow structure for grpc_mdelem_data for allocated elements */ typedef struct allocated_metadata { /* must be byte compatible with grpc_mdelem_data */ grpc_slice key; grpc_slice value; /* private only data */ gpr_atm refcnt; } allocated_metadata; typedef struct mdtab_shard { gpr_mu mu; interned_metadata **elems; size_t count; size_t capacity; /** Estimate of the number of unreferenced mdelems in the hash table. This will eventually converge to the exact number, but it's instantaneous accuracy is not guaranteed */ gpr_atm free_estimate; } mdtab_shard; static mdtab_shard g_shards[SHARD_COUNT]; static void gc_mdtab(grpc_exec_ctx *exec_ctx, mdtab_shard *shard); void grpc_mdctx_global_init(void) { /* initialize shards */ for (size_t i = 0; i < SHARD_COUNT; i++) { mdtab_shard *shard = &g_shards[i]; gpr_mu_init(&shard->mu); shard->count = 0; gpr_atm_no_barrier_store(&shard->free_estimate, 0); shard->capacity = INITIAL_SHARD_CAPACITY; shard->elems = gpr_zalloc(sizeof(*shard->elems) * shard->capacity); } } void grpc_mdctx_global_shutdown(grpc_exec_ctx *exec_ctx) { for (size_t i = 0; i < SHARD_COUNT; i++) { mdtab_shard *shard = &g_shards[i]; gpr_mu_destroy(&shard->mu); gc_mdtab(exec_ctx, shard); /* TODO(ctiller): GPR_ASSERT(shard->count == 0); */ if (shard->count != 0) { gpr_log(GPR_DEBUG, "WARNING: %" PRIuPTR " metadata elements were leaked", shard->count); if (grpc_iomgr_abort_on_leaks()) { abort(); } } gpr_free(shard->elems); } } static int is_mdelem_static(grpc_mdelem e) { return GRPC_MDELEM_DATA(e) >= &grpc_static_mdelem_table[0] && GRPC_MDELEM_DATA(e) < &grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT]; } static void ref_md_locked(mdtab_shard *shard, interned_metadata *md DEBUG_ARGS) { #ifdef GRPC_METADATA_REFCOUNT_DEBUG char *key_str = grpc_slice_to_c_string(md->key); char *value_str = grpc_slice_to_c_string(md->value); gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "ELM REF:%p:%zu->%zu: '%s' = '%s'", (void *)md, gpr_atm_no_barrier_load(&md->refcnt), gpr_atm_no_barrier_load(&md->refcnt) + 1, key_str, value_str); gpr_free(key_str); gpr_free(value_str); #endif if (0 == gpr_atm_no_barrier_fetch_add(&md->refcnt, 1)) { gpr_atm_no_barrier_fetch_add(&shard->free_estimate, -1); } } static void gc_mdtab(grpc_exec_ctx *exec_ctx, mdtab_shard *shard) { size_t i; interned_metadata **prev_next; interned_metadata *md, *next; gpr_atm num_freed = 0; GPR_TIMER_BEGIN("gc_mdtab", 0); for (i = 0; i < shard->capacity; i++) { prev_next = &shard->elems[i]; for (md = shard->elems[i]; md; md = next) { void *user_data = (void *)gpr_atm_no_barrier_load(&md->user_data); next = md->bucket_next; if (gpr_atm_acq_load(&md->refcnt) == 0) { grpc_slice_unref_internal(exec_ctx, md->key); grpc_slice_unref_internal(exec_ctx, md->value); if (md->user_data) { ((destroy_user_data_func)gpr_atm_no_barrier_load( &md->destroy_user_data))(user_data); } gpr_free(md); *prev_next = next; num_freed++; shard->count--; } else { prev_next = &md->bucket_next; } } } gpr_atm_no_barrier_fetch_add(&shard->free_estimate, -num_freed); GPR_TIMER_END("gc_mdtab", 0); } static void grow_mdtab(mdtab_shard *shard) { size_t capacity = shard->capacity * 2; size_t i; interned_metadata **mdtab; interned_metadata *md, *next; uint32_t hash; GPR_TIMER_BEGIN("grow_mdtab", 0); mdtab = gpr_zalloc(sizeof(interned_metadata *) * capacity); for (i = 0; i < shard->capacity; i++) { for (md = shard->elems[i]; md; md = next) { size_t idx; hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash(md->key), grpc_slice_hash(md->value)); next = md->bucket_next; idx = TABLE_IDX(hash, capacity); md->bucket_next = mdtab[idx]; mdtab[idx] = md; } } gpr_free(shard->elems); shard->elems = mdtab; shard->capacity = capacity; GPR_TIMER_END("grow_mdtab", 0); } static void rehash_mdtab(grpc_exec_ctx *exec_ctx, mdtab_shard *shard) { if (gpr_atm_no_barrier_load(&shard->free_estimate) > (gpr_atm)(shard->capacity / 4)) { gc_mdtab(exec_ctx, shard); } else { grow_mdtab(shard); } } grpc_mdelem grpc_mdelem_create( grpc_exec_ctx *exec_ctx, grpc_slice key, grpc_slice value, grpc_mdelem_data *compatible_external_backing_store) { if (!grpc_slice_is_interned(key) || !grpc_slice_is_interned(value)) { if (compatible_external_backing_store != NULL) { return GRPC_MAKE_MDELEM(compatible_external_backing_store, GRPC_MDELEM_STORAGE_EXTERNAL); } allocated_metadata *allocated = gpr_malloc(sizeof(*allocated)); allocated->key = grpc_slice_ref_internal(key); allocated->value = grpc_slice_ref_internal(value); gpr_atm_rel_store(&allocated->refcnt, 1); #ifdef GRPC_METADATA_REFCOUNT_DEBUG char *key_str = grpc_slice_to_c_string(allocated->key); char *value_str = grpc_slice_to_c_string(allocated->value); gpr_log(GPR_DEBUG, "ELM ALLOC:%p:%zu: '%s' = '%s'", (void *)allocated, gpr_atm_no_barrier_load(&allocated->refcnt), key_str, value_str); gpr_free(key_str); gpr_free(value_str); #endif return GRPC_MAKE_MDELEM(allocated, GRPC_MDELEM_STORAGE_ALLOCATED); } if (GRPC_IS_STATIC_METADATA_STRING(key) && GRPC_IS_STATIC_METADATA_STRING(value)) { grpc_mdelem static_elem = grpc_static_mdelem_for_static_strings( GRPC_STATIC_METADATA_INDEX(key), GRPC_STATIC_METADATA_INDEX(value)); if (!GRPC_MDISNULL(static_elem)) { return static_elem; } } uint32_t hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash(key), grpc_slice_hash(value)); interned_metadata *md; mdtab_shard *shard = &g_shards[SHARD_IDX(hash)]; size_t idx; GPR_TIMER_BEGIN("grpc_mdelem_from_metadata_strings", 0); gpr_mu_lock(&shard->mu); idx = TABLE_IDX(hash, shard->capacity); /* search for an existing pair */ for (md = shard->elems[idx]; md; md = md->bucket_next) { if (grpc_slice_eq(key, md->key) && grpc_slice_eq(value, md->value)) { REF_MD_LOCKED(shard, md); gpr_mu_unlock(&shard->mu); GPR_TIMER_END("grpc_mdelem_from_metadata_strings", 0); return GRPC_MAKE_MDELEM(md, GRPC_MDELEM_STORAGE_INTERNED); } } /* not found: create a new pair */ md = gpr_malloc(sizeof(interned_metadata)); gpr_atm_rel_store(&md->refcnt, 1); md->key = grpc_slice_ref_internal(key); md->value = grpc_slice_ref_internal(value); md->user_data = 0; md->destroy_user_data = 0; md->bucket_next = shard->elems[idx]; shard->elems[idx] = md; gpr_mu_init(&md->mu_user_data); #ifdef GRPC_METADATA_REFCOUNT_DEBUG char *key_str = grpc_slice_to_c_string(md->key); char *value_str = grpc_slice_to_c_string(md->value); gpr_log(GPR_DEBUG, "ELM NEW:%p:%zu: '%s' = '%s'", (void *)md, gpr_atm_no_barrier_load(&md->refcnt), key_str, value_str); gpr_free(key_str); gpr_free(value_str); #endif shard->count++; if (shard->count > shard->capacity * 2) { rehash_mdtab(exec_ctx, shard); } gpr_mu_unlock(&shard->mu); GPR_TIMER_END("grpc_mdelem_from_metadata_strings", 0); return GRPC_MAKE_MDELEM(md, GRPC_MDELEM_STORAGE_INTERNED); } grpc_mdelem grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key, grpc_slice value) { grpc_mdelem out = grpc_mdelem_create(exec_ctx, key, value, NULL); grpc_slice_unref_internal(exec_ctx, key); grpc_slice_unref_internal(exec_ctx, value); return out; } grpc_mdelem grpc_mdelem_from_grpc_metadata(grpc_exec_ctx *exec_ctx, grpc_metadata *metadata) { bool changed = false; grpc_slice key_slice = grpc_slice_maybe_static_intern(metadata->key, &changed); grpc_slice value_slice = grpc_slice_maybe_static_intern(metadata->value, &changed); return grpc_mdelem_create(exec_ctx, key_slice, value_slice, changed ? NULL : (grpc_mdelem_data *)metadata); } static size_t get_base64_encoded_size(size_t raw_length) { static const uint8_t tail_xtra[3] = {0, 2, 3}; return raw_length / 3 * 4 + tail_xtra[raw_length % 3]; } size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem elem) { size_t overhead_and_key = 32 + GRPC_SLICE_LENGTH(GRPC_MDKEY(elem)); size_t value_len = GRPC_SLICE_LENGTH(GRPC_MDVALUE(elem)); if (grpc_is_binary_header(GRPC_MDKEY(elem))) { return overhead_and_key + get_base64_encoded_size(value_len); } else { return overhead_and_key + value_len; } } grpc_mdelem grpc_mdelem_ref(grpc_mdelem gmd DEBUG_ARGS) { switch (GRPC_MDELEM_STORAGE(gmd)) { case GRPC_MDELEM_STORAGE_EXTERNAL: case GRPC_MDELEM_STORAGE_STATIC: break; case GRPC_MDELEM_STORAGE_INTERNED: { interned_metadata *md = (interned_metadata *)GRPC_MDELEM_DATA(gmd); #ifdef GRPC_METADATA_REFCOUNT_DEBUG char *key_str = grpc_slice_to_c_string(md->key); char *value_str = grpc_slice_to_c_string(md->value); gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "ELM REF:%p:%zu->%zu: '%s' = '%s'", (void *)md, gpr_atm_no_barrier_load(&md->refcnt), gpr_atm_no_barrier_load(&md->refcnt) + 1, key_str, value_str); gpr_free(key_str); gpr_free(value_str); #endif /* we can assume the ref count is >= 1 as the application is calling this function - meaning that no adjustment to mdtab_free is necessary, simplifying the logic here to be just an atomic increment */ /* use C assert to have this removed in opt builds */ GPR_ASSERT(gpr_atm_no_barrier_load(&md->refcnt) >= 1); gpr_atm_no_barrier_fetch_add(&md->refcnt, 1); break; } case GRPC_MDELEM_STORAGE_ALLOCATED: { allocated_metadata *md = (allocated_metadata *)GRPC_MDELEM_DATA(gmd); #ifdef GRPC_METADATA_REFCOUNT_DEBUG char *key_str = grpc_slice_to_c_string(md->key); char *value_str = grpc_slice_to_c_string(md->value); gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "ELM REF:%p:%zu->%zu: '%s' = '%s'", (void *)md, gpr_atm_no_barrier_load(&md->refcnt), gpr_atm_no_barrier_load(&md->refcnt) + 1, key_str, value_str); gpr_free(key_str); gpr_free(value_str); #endif /* we can assume the ref count is >= 1 as the application is calling this function - meaning that no adjustment to mdtab_free is necessary, simplifying the logic here to be just an atomic increment */ /* use C assert to have this removed in opt builds */ gpr_atm_no_barrier_fetch_add(&md->refcnt, 1); break; } } return gmd; } void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem gmd DEBUG_ARGS) { switch (GRPC_MDELEM_STORAGE(gmd)) { case GRPC_MDELEM_STORAGE_EXTERNAL: case GRPC_MDELEM_STORAGE_STATIC: break; case GRPC_MDELEM_STORAGE_INTERNED: { interned_metadata *md = (interned_metadata *)GRPC_MDELEM_DATA(gmd); #ifdef GRPC_METADATA_REFCOUNT_DEBUG char *key_str = grpc_slice_to_c_string(md->key); char *value_str = grpc_slice_to_c_string(md->value); gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "ELM UNREF:%p:%zu->%zu: '%s' = '%s'", (void *)md, gpr_atm_no_barrier_load(&md->refcnt), gpr_atm_no_barrier_load(&md->refcnt) - 1, key_str, value_str); gpr_free(key_str); gpr_free(value_str); #endif uint32_t hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash(md->key), grpc_slice_hash(md->value)); const gpr_atm prev_refcount = gpr_atm_full_fetch_add(&md->refcnt, -1); GPR_ASSERT(prev_refcount >= 1); if (1 == prev_refcount) { /* once the refcount hits zero, some other thread can come along and free md at any time: it's unsafe from this point on to access it */ mdtab_shard *shard = &g_shards[SHARD_IDX(hash)]; gpr_atm_no_barrier_fetch_add(&shard->free_estimate, 1); } break; } case GRPC_MDELEM_STORAGE_ALLOCATED: { allocated_metadata *md = (allocated_metadata *)GRPC_MDELEM_DATA(gmd); #ifdef GRPC_METADATA_REFCOUNT_DEBUG char *key_str = grpc_slice_to_c_string(md->key); char *value_str = grpc_slice_to_c_string(md->value); gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "ELM UNREF:%p:%zu->%zu: '%s' = '%s'", (void *)md, gpr_atm_no_barrier_load(&md->refcnt), gpr_atm_no_barrier_load(&md->refcnt) - 1, key_str, value_str); gpr_free(key_str); gpr_free(value_str); #endif const gpr_atm prev_refcount = gpr_atm_full_fetch_add(&md->refcnt, -1); GPR_ASSERT(prev_refcount >= 1); if (1 == prev_refcount) { grpc_slice_unref_internal(exec_ctx, md->key); grpc_slice_unref_internal(exec_ctx, md->value); gpr_free(md); } break; } } } void *grpc_mdelem_get_user_data(grpc_mdelem md, void (*destroy_func)(void *)) { switch (GRPC_MDELEM_STORAGE(md)) { case GRPC_MDELEM_STORAGE_EXTERNAL: case GRPC_MDELEM_STORAGE_ALLOCATED: return NULL; case GRPC_MDELEM_STORAGE_STATIC: return (void *)grpc_static_mdelem_user_data[GRPC_MDELEM_DATA(md) - grpc_static_mdelem_table]; case GRPC_MDELEM_STORAGE_INTERNED: { interned_metadata *im = (interned_metadata *)GRPC_MDELEM_DATA(md); void *result; if (gpr_atm_acq_load(&im->destroy_user_data) == (gpr_atm)destroy_func) { return (void *)gpr_atm_no_barrier_load(&im->user_data); } else { return NULL; } return result; } } GPR_UNREACHABLE_CODE(return NULL); } void *grpc_mdelem_set_user_data(grpc_mdelem md, void (*destroy_func)(void *), void *user_data) { switch (GRPC_MDELEM_STORAGE(md)) { case GRPC_MDELEM_STORAGE_EXTERNAL: case GRPC_MDELEM_STORAGE_ALLOCATED: destroy_func(user_data); return NULL; case GRPC_MDELEM_STORAGE_STATIC: destroy_func(user_data); return (void *)grpc_static_mdelem_user_data[GRPC_MDELEM_DATA(md) - grpc_static_mdelem_table]; case GRPC_MDELEM_STORAGE_INTERNED: { interned_metadata *im = (interned_metadata *)GRPC_MDELEM_DATA(md); GPR_ASSERT(!is_mdelem_static(md)); GPR_ASSERT((user_data == NULL) == (destroy_func == NULL)); gpr_mu_lock(&im->mu_user_data); if (gpr_atm_no_barrier_load(&im->destroy_user_data)) { /* user data can only be set once */ gpr_mu_unlock(&im->mu_user_data); if (destroy_func != NULL) { destroy_func(user_data); } return (void *)gpr_atm_no_barrier_load(&im->user_data); } gpr_atm_no_barrier_store(&im->user_data, (gpr_atm)user_data); gpr_atm_rel_store(&im->destroy_user_data, (gpr_atm)destroy_func); gpr_mu_unlock(&im->mu_user_data); return user_data; } } GPR_UNREACHABLE_CODE(return NULL); } bool grpc_mdelem_eq(grpc_mdelem a, grpc_mdelem b) { if (a.payload == b.payload) return true; if (GRPC_MDELEM_IS_INTERNED(a) && GRPC_MDELEM_IS_INTERNED(b)) return false; if (GRPC_MDISNULL(a) || GRPC_MDISNULL(b)) return false; return grpc_slice_eq(GRPC_MDKEY(a), GRPC_MDKEY(b)) && grpc_slice_eq(GRPC_MDVALUE(a), GRPC_MDVALUE(b)); } grpc-1.3.2/src/core/lib/transport/metadata.h000066400000000000000000000174001310511640000207130ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_TRANSPORT_METADATA_H #define GRPC_CORE_LIB_TRANSPORT_METADATA_H #include #include #include #include "src/core/lib/iomgr/exec_ctx.h" #ifdef __cplusplus extern "C" { #endif /* This file provides a mechanism for tracking metadata through the grpc stack. It's not intended for consumption outside of the library. Metadata is tracked in the context of a grpc_mdctx. For the time being there is one of these per-channel, avoiding cross channel interference with memory use and lock contention. The context tracks unique strings (grpc_mdstr) and pairs of strings (grpc_mdelem). Any of these objects can be checked for equality by comparing their pointers. These objects are reference counted. grpc_mdelem can additionally store a (non-NULL) user data pointer. This pointer is intended to be used to cache semantic meaning of a metadata element. For example, an OAuth token may cache the credentials it represents and the time at which it expires in the mdelem user data. Combining this metadata cache and the hpack compression table allows us to simply lookup complete preparsed objects quickly, incurring a few atomic ops per metadata element on the fast path. grpc_mdelem instances MAY live longer than their refcount implies, and are garbage collected periodically, meaning cached data can easily outlive a single request. STATIC METADATA: in static_metadata.h we declare a set of static metadata. These mdelems and mdstrs are available via pre-declared code generated macros and are available to code anywhere between grpc_init() and grpc_shutdown(). They are not refcounted, but can be passed to _ref and _unref functions declared here - in which case those functions are effectively no-ops. */ /* Forward declarations */ typedef struct grpc_mdelem grpc_mdelem; /* if changing this, make identical changes in: - interned_metadata, allocated_metadata in metadata.c - grpc_metadata in grpc_types.h */ typedef struct grpc_mdelem_data { const grpc_slice key; const grpc_slice value; /* there is a private part to this in metadata.c */ } grpc_mdelem_data; /* GRPC_MDELEM_STORAGE_* enum values that can be treated as interned always have this bit set in their integer value */ #define GRPC_MDELEM_STORAGE_INTERNED_BIT 1 typedef enum { /* memory pointed to by grpc_mdelem::payload is owned by an external system */ GRPC_MDELEM_STORAGE_EXTERNAL = 0, /* memory pointed to by grpc_mdelem::payload is interned by the metadata system */ GRPC_MDELEM_STORAGE_INTERNED = GRPC_MDELEM_STORAGE_INTERNED_BIT, /* memory pointed to by grpc_mdelem::payload is allocated by the metadata system */ GRPC_MDELEM_STORAGE_ALLOCATED = 2, /* memory is in the static metadata table */ GRPC_MDELEM_STORAGE_STATIC = 2 | GRPC_MDELEM_STORAGE_INTERNED_BIT, } grpc_mdelem_data_storage; struct grpc_mdelem { /* a grpc_mdelem_data* generally, with the two lower bits signalling memory ownership as per grpc_mdelem_data_storage */ uintptr_t payload; }; #define GRPC_MDELEM_DATA(md) \ ((grpc_mdelem_data *)((md).payload & ~(uintptr_t)3)) #define GRPC_MDELEM_STORAGE(md) \ ((grpc_mdelem_data_storage)((md).payload & (uintptr_t)3)) #define GRPC_MAKE_MDELEM(data, storage) \ ((grpc_mdelem){((uintptr_t)(data)) | ((uintptr_t)storage)}) #define GRPC_MDELEM_IS_INTERNED(md) \ ((grpc_mdelem_data_storage)((md).payload & \ (uintptr_t)GRPC_MDELEM_STORAGE_INTERNED_BIT)) /* Unrefs the slices. */ grpc_mdelem grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key, grpc_slice value); /* Cheaply convert a grpc_metadata to a grpc_mdelem; may use the grpc_metadata object as backing storage (so lifetimes should align) */ grpc_mdelem grpc_mdelem_from_grpc_metadata(grpc_exec_ctx *exec_ctx, grpc_metadata *metadata); /* Does not unref the slices; if a new non-interned mdelem is needed, allocates one if compatible_external_backing_store is NULL, or uses compatible_external_backing_store if it is non-NULL (in which case it's the users responsibility to ensure that it outlives usage) */ grpc_mdelem grpc_mdelem_create( grpc_exec_ctx *exec_ctx, grpc_slice key, grpc_slice value, grpc_mdelem_data *compatible_external_backing_store); bool grpc_mdelem_eq(grpc_mdelem a, grpc_mdelem b); size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem elem); /* Mutator and accessor for grpc_mdelem user data. The destructor function is used as a type tag and is checked during user_data fetch. */ void *grpc_mdelem_get_user_data(grpc_mdelem md, void (*if_destroy_func)(void *)); void *grpc_mdelem_set_user_data(grpc_mdelem md, void (*destroy_func)(void *), void *user_data); /* Reference counting */ //#define GRPC_METADATA_REFCOUNT_DEBUG #ifdef GRPC_METADATA_REFCOUNT_DEBUG #define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s), __FILE__, __LINE__) #define GRPC_MDELEM_UNREF(exec_ctx, s) \ grpc_mdelem_unref((exec_ctx), (s), __FILE__, __LINE__) grpc_mdelem grpc_mdelem_ref(grpc_mdelem md, const char *file, int line); void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem md, const char *file, int line); #else #define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s)) #define GRPC_MDELEM_UNREF(exec_ctx, s) grpc_mdelem_unref((exec_ctx), (s)) grpc_mdelem grpc_mdelem_ref(grpc_mdelem md); void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem md); #endif #define GRPC_MDKEY(md) (GRPC_MDELEM_DATA(md)->key) #define GRPC_MDVALUE(md) (GRPC_MDELEM_DATA(md)->value) #define GRPC_MDNULL GRPC_MAKE_MDELEM(NULL, GRPC_MDELEM_STORAGE_EXTERNAL) #define GRPC_MDISNULL(md) (GRPC_MDELEM_DATA(md) == NULL) /* We add 32 bytes of padding as per RFC-7540 section 6.5.2. */ #define GRPC_MDELEM_LENGTH(e) \ (GRPC_SLICE_LENGTH(GRPC_MDKEY((e))) + GRPC_SLICE_LENGTH(GRPC_MDVALUE((e))) + \ 32) #define GRPC_MDSTR_KV_HASH(k_hash, v_hash) (GPR_ROTL((k_hash), 2) ^ (v_hash)) void grpc_mdctx_global_init(void); void grpc_mdctx_global_shutdown(grpc_exec_ctx *exec_ctx); #ifdef __cplusplus } #endif #endif /* GRPC_CORE_LIB_TRANSPORT_METADATA_H */ grpc-1.3.2/src/core/lib/transport/metadata_batch.c000066400000000000000000000265051310511640000220550ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/transport/metadata_batch.h" #include #include #include #include #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" static void assert_valid_list(grpc_mdelem_list *list) { #ifndef NDEBUG grpc_linked_mdelem *l; GPR_ASSERT((list->head == NULL) == (list->tail == NULL)); if (!list->head) return; GPR_ASSERT(list->head->prev == NULL); GPR_ASSERT(list->tail->next == NULL); GPR_ASSERT((list->head == list->tail) == (list->head->next == NULL)); size_t verified_count = 0; for (l = list->head; l; l = l->next) { GPR_ASSERT(!GRPC_MDISNULL(l->md)); GPR_ASSERT((l->prev == NULL) == (l == list->head)); GPR_ASSERT((l->next == NULL) == (l == list->tail)); if (l->next) GPR_ASSERT(l->next->prev == l); if (l->prev) GPR_ASSERT(l->prev->next == l); verified_count++; } GPR_ASSERT(list->count == verified_count); #endif /* NDEBUG */ } static void assert_valid_callouts(grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch) { #ifndef NDEBUG for (grpc_linked_mdelem *l = batch->list.head; l != NULL; l = l->next) { grpc_slice key_interned = grpc_slice_intern(GRPC_MDKEY(l->md)); grpc_metadata_batch_callouts_index callout_idx = GRPC_BATCH_INDEX_OF(key_interned); if (callout_idx != GRPC_BATCH_CALLOUTS_COUNT) { GPR_ASSERT(batch->idx.array[callout_idx] == l); } grpc_slice_unref_internal(exec_ctx, key_interned); } #endif } #ifndef NDEBUG void grpc_metadata_batch_assert_ok(grpc_metadata_batch *batch) { assert_valid_list(&batch->list); } #endif /* NDEBUG */ void grpc_metadata_batch_init(grpc_metadata_batch *batch) { memset(batch, 0, sizeof(*batch)); batch->deadline = gpr_inf_future(GPR_CLOCK_REALTIME); } void grpc_metadata_batch_destroy(grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch) { grpc_linked_mdelem *l; for (l = batch->list.head; l; l = l->next) { GRPC_MDELEM_UNREF(exec_ctx, l->md); } } grpc_error *grpc_attach_md_to_error(grpc_error *src, grpc_mdelem md) { grpc_error *out = grpc_error_set_str( grpc_error_set_str(src, GRPC_ERROR_STR_KEY, grpc_slice_ref_internal(GRPC_MDKEY(md))), GRPC_ERROR_STR_VALUE, grpc_slice_ref_internal(GRPC_MDVALUE(md))); return out; } static grpc_error *maybe_link_callout(grpc_metadata_batch *batch, grpc_linked_mdelem *storage) GRPC_MUST_USE_RESULT; static grpc_error *maybe_link_callout(grpc_metadata_batch *batch, grpc_linked_mdelem *storage) { grpc_metadata_batch_callouts_index idx = GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)); if (idx == GRPC_BATCH_CALLOUTS_COUNT) { return GRPC_ERROR_NONE; } if (batch->idx.array[idx] == NULL) { batch->idx.array[idx] = storage; return GRPC_ERROR_NONE; } return grpc_attach_md_to_error( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Unallowed duplicate metadata"), storage->md); } static void maybe_unlink_callout(grpc_metadata_batch *batch, grpc_linked_mdelem *storage) { grpc_metadata_batch_callouts_index idx = GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)); if (idx == GRPC_BATCH_CALLOUTS_COUNT) { return; } GPR_ASSERT(batch->idx.array[idx] != NULL); batch->idx.array[idx] = NULL; } grpc_error *grpc_metadata_batch_add_head(grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, grpc_linked_mdelem *storage, grpc_mdelem elem_to_add) { GPR_ASSERT(!GRPC_MDISNULL(elem_to_add)); storage->md = elem_to_add; return grpc_metadata_batch_link_head(exec_ctx, batch, storage); } static void link_head(grpc_mdelem_list *list, grpc_linked_mdelem *storage) { assert_valid_list(list); GPR_ASSERT(!GRPC_MDISNULL(storage->md)); storage->prev = NULL; storage->next = list->head; if (list->head != NULL) { list->head->prev = storage; } else { list->tail = storage; } list->head = storage; list->count++; assert_valid_list(list); } grpc_error *grpc_metadata_batch_link_head(grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, grpc_linked_mdelem *storage) { assert_valid_callouts(exec_ctx, batch); grpc_error *err = maybe_link_callout(batch, storage); if (err != GRPC_ERROR_NONE) { assert_valid_callouts(exec_ctx, batch); return err; } link_head(&batch->list, storage); assert_valid_callouts(exec_ctx, batch); return GRPC_ERROR_NONE; } grpc_error *grpc_metadata_batch_add_tail(grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, grpc_linked_mdelem *storage, grpc_mdelem elem_to_add) { GPR_ASSERT(!GRPC_MDISNULL(elem_to_add)); storage->md = elem_to_add; return grpc_metadata_batch_link_tail(exec_ctx, batch, storage); } static void link_tail(grpc_mdelem_list *list, grpc_linked_mdelem *storage) { assert_valid_list(list); GPR_ASSERT(!GRPC_MDISNULL(storage->md)); storage->prev = list->tail; storage->next = NULL; storage->reserved = NULL; if (list->tail != NULL) { list->tail->next = storage; } else { list->head = storage; } list->tail = storage; list->count++; assert_valid_list(list); } grpc_error *grpc_metadata_batch_link_tail(grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, grpc_linked_mdelem *storage) { assert_valid_callouts(exec_ctx, batch); grpc_error *err = maybe_link_callout(batch, storage); if (err != GRPC_ERROR_NONE) { assert_valid_callouts(exec_ctx, batch); return err; } link_tail(&batch->list, storage); assert_valid_callouts(exec_ctx, batch); return GRPC_ERROR_NONE; } static void unlink_storage(grpc_mdelem_list *list, grpc_linked_mdelem *storage) { assert_valid_list(list); if (storage->prev != NULL) { storage->prev->next = storage->next; } else { list->head = storage->next; } if (storage->next != NULL) { storage->next->prev = storage->prev; } else { list->tail = storage->prev; } list->count--; assert_valid_list(list); } void grpc_metadata_batch_remove(grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, grpc_linked_mdelem *storage) { assert_valid_callouts(exec_ctx, batch); maybe_unlink_callout(batch, storage); unlink_storage(&batch->list, storage); GRPC_MDELEM_UNREF(exec_ctx, storage->md); assert_valid_callouts(exec_ctx, batch); } void grpc_metadata_batch_set_value(grpc_exec_ctx *exec_ctx, grpc_linked_mdelem *storage, grpc_slice value) { grpc_mdelem old = storage->md; grpc_mdelem new = grpc_mdelem_from_slices( exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(old)), value); storage->md = new; GRPC_MDELEM_UNREF(exec_ctx, old); } grpc_error *grpc_metadata_batch_substitute(grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, grpc_linked_mdelem *storage, grpc_mdelem new) { assert_valid_callouts(exec_ctx, batch); grpc_error *error = GRPC_ERROR_NONE; grpc_mdelem old = storage->md; if (!grpc_slice_eq(GRPC_MDKEY(new), GRPC_MDKEY(old))) { maybe_unlink_callout(batch, storage); storage->md = new; error = maybe_link_callout(batch, storage); if (error != GRPC_ERROR_NONE) { unlink_storage(&batch->list, storage); GRPC_MDELEM_UNREF(exec_ctx, storage->md); } } else { storage->md = new; } GRPC_MDELEM_UNREF(exec_ctx, old); assert_valid_callouts(exec_ctx, batch); return error; } void grpc_metadata_batch_clear(grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch) { grpc_metadata_batch_destroy(exec_ctx, batch); grpc_metadata_batch_init(batch); } bool grpc_metadata_batch_is_empty(grpc_metadata_batch *batch) { return batch->list.head == NULL && gpr_time_cmp(gpr_inf_future(batch->deadline.clock_type), batch->deadline) == 0; } size_t grpc_metadata_batch_size(grpc_metadata_batch *batch) { size_t size = 0; for (grpc_linked_mdelem *elem = batch->list.head; elem != NULL; elem = elem->next) { size += GRPC_MDELEM_LENGTH(elem->md); } return size; } static void add_error(grpc_error **composite, grpc_error *error, const char *composite_error_string) { if (error == GRPC_ERROR_NONE) return; if (*composite == GRPC_ERROR_NONE) { *composite = GRPC_ERROR_CREATE_FROM_COPIED_STRING(composite_error_string); } *composite = grpc_error_add_child(*composite, error); } grpc_error *grpc_metadata_batch_filter(grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, grpc_metadata_batch_filter_func func, void *user_data, const char *composite_error_string) { grpc_linked_mdelem *l = batch->list.head; grpc_error *error = GRPC_ERROR_NONE; while (l) { grpc_linked_mdelem *next = l->next; grpc_filtered_mdelem new = func(exec_ctx, user_data, l->md); add_error(&error, new.error, composite_error_string); if (GRPC_MDISNULL(new.md)) { grpc_metadata_batch_remove(exec_ctx, batch, l); } else if (new.md.payload != l->md.payload) { grpc_metadata_batch_substitute(exec_ctx, batch, l, new.md); } l = next; } return error; } grpc-1.3.2/src/core/lib/transport/metadata_batch.h000066400000000000000000000150001310511640000220460ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_TRANSPORT_METADATA_BATCH_H #define GRPC_CORE_LIB_TRANSPORT_METADATA_BATCH_H #include #include #include #include #include #include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/static_metadata.h" #ifdef __cplusplus extern "C" { #endif typedef struct grpc_linked_mdelem { grpc_mdelem md; struct grpc_linked_mdelem *next; struct grpc_linked_mdelem *prev; void *reserved; } grpc_linked_mdelem; typedef struct grpc_mdelem_list { size_t count; grpc_linked_mdelem *head; grpc_linked_mdelem *tail; } grpc_mdelem_list; typedef struct grpc_metadata_batch { /** Metadata elements in this batch */ grpc_mdelem_list list; grpc_metadata_batch_callouts idx; /** Used to calculate grpc-timeout at the point of sending, or gpr_inf_future if this batch does not need to send a grpc-timeout */ gpr_timespec deadline; } grpc_metadata_batch; void grpc_metadata_batch_init(grpc_metadata_batch *batch); void grpc_metadata_batch_destroy(grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch); void grpc_metadata_batch_clear(grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch); bool grpc_metadata_batch_is_empty(grpc_metadata_batch *batch); /* Returns the transport size of the batch. */ size_t grpc_metadata_batch_size(grpc_metadata_batch *batch); /** Remove \a storage from the batch, unreffing the mdelem contained */ void grpc_metadata_batch_remove(grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, grpc_linked_mdelem *storage); /** Substitute a new mdelem for an old value */ grpc_error *grpc_metadata_batch_substitute(grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, grpc_linked_mdelem *storage, grpc_mdelem new_value); void grpc_metadata_batch_set_value(grpc_exec_ctx *exec_ctx, grpc_linked_mdelem *storage, grpc_slice value); /** Add \a storage to the beginning of \a batch. storage->md is assumed to be valid. \a storage is owned by the caller and must survive for the lifetime of batch. This usually means it should be around for the lifetime of the call. */ grpc_error *grpc_metadata_batch_link_head( grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, grpc_linked_mdelem *storage) GRPC_MUST_USE_RESULT; /** Add \a storage to the end of \a batch. storage->md is assumed to be valid. \a storage is owned by the caller and must survive for the lifetime of batch. This usually means it should be around for the lifetime of the call. */ grpc_error *grpc_metadata_batch_link_tail( grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, grpc_linked_mdelem *storage) GRPC_MUST_USE_RESULT; /** Add \a elem_to_add as the first element in \a batch, using \a storage as backing storage for the linked list element. \a storage is owned by the caller and must survive for the lifetime of batch. This usually means it should be around for the lifetime of the call. Takes ownership of \a elem_to_add */ grpc_error *grpc_metadata_batch_add_head( grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, grpc_linked_mdelem *storage, grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT; /** Add \a elem_to_add as the last element in \a batch, using \a storage as backing storage for the linked list element. \a storage is owned by the caller and must survive for the lifetime of batch. This usually means it should be around for the lifetime of the call. Takes ownership of \a elem_to_add */ grpc_error *grpc_metadata_batch_add_tail( grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, grpc_linked_mdelem *storage, grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT; grpc_error *grpc_attach_md_to_error(grpc_error *src, grpc_mdelem md); typedef struct { grpc_error *error; grpc_mdelem md; } grpc_filtered_mdelem; #define GRPC_FILTERED_ERROR(error) \ ((grpc_filtered_mdelem){(error), GRPC_MDNULL}) #define GRPC_FILTERED_MDELEM(md) ((grpc_filtered_mdelem){GRPC_ERROR_NONE, (md)}) #define GRPC_FILTERED_REMOVE() \ ((grpc_filtered_mdelem){GRPC_ERROR_NONE, GRPC_MDNULL}) typedef grpc_filtered_mdelem (*grpc_metadata_batch_filter_func)( grpc_exec_ctx *exec_ctx, void *user_data, grpc_mdelem elem); grpc_error *grpc_metadata_batch_filter( grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, grpc_metadata_batch_filter_func func, void *user_data, const char *composite_error_string) GRPC_MUST_USE_RESULT; #ifndef NDEBUG void grpc_metadata_batch_assert_ok(grpc_metadata_batch *comd); #else #define grpc_metadata_batch_assert_ok(comd) \ do { \ } while (0) #endif #ifdef __cplusplus } #endif #endif /* GRPC_CORE_LIB_TRANSPORT_METADATA_BATCH_H */ grpc-1.3.2/src/core/lib/transport/pid_controller.c000066400000000000000000000067361310511640000221570ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/transport/pid_controller.h" #include void grpc_pid_controller_init(grpc_pid_controller *pid_controller, grpc_pid_controller_args args) { pid_controller->args = args; pid_controller->last_control_value = args.initial_control_value; grpc_pid_controller_reset(pid_controller); } void grpc_pid_controller_reset(grpc_pid_controller *pid_controller) { pid_controller->last_error = 0.0; pid_controller->last_dc_dt = 0.0; pid_controller->error_integral = 0.0; } double grpc_pid_controller_update(grpc_pid_controller *pid_controller, double error, double dt) { if (dt == 0) return pid_controller->last_control_value; /* integrate error using the trapezoid rule */ pid_controller->error_integral += dt * (pid_controller->last_error + error) * 0.5; pid_controller->error_integral = GPR_CLAMP( pid_controller->error_integral, -pid_controller->args.integral_range, pid_controller->args.integral_range); double diff_error = (error - pid_controller->last_error) / dt; /* calculate derivative of control value vs time */ double dc_dt = pid_controller->args.gain_p * error + pid_controller->args.gain_i * pid_controller->error_integral + pid_controller->args.gain_d * diff_error; /* and perform trapezoidal integration */ double new_control_value = pid_controller->last_control_value + dt * (pid_controller->last_dc_dt + dc_dt) * 0.5; new_control_value = GPR_CLAMP(new_control_value, pid_controller->args.min_control_value, pid_controller->args.max_control_value); pid_controller->last_error = error; pid_controller->last_dc_dt = dc_dt; pid_controller->last_control_value = new_control_value; return new_control_value; } double grpc_pid_controller_last(grpc_pid_controller *pid_controller) { return pid_controller->last_control_value; } grpc-1.3.2/src/core/lib/transport/pid_controller.h000066400000000000000000000060731310511640000221560ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_TRANSPORT_PID_CONTROLLER_H #define GRPC_CORE_LIB_TRANSPORT_PID_CONTROLLER_H /* \file Simple PID controller. Implements a proportional-integral-derivative controller. Used when we want to iteratively control a variable to converge some other observed value to a 'set-point'. Gains can be set to adjust sensitivity to current error (p), the integral of error (i), and the derivative of error (d). */ typedef struct { double gain_p; double gain_i; double gain_d; double initial_control_value; double min_control_value; double max_control_value; double integral_range; } grpc_pid_controller_args; typedef struct { double last_error; double error_integral; double last_control_value; double last_dc_dt; grpc_pid_controller_args args; } grpc_pid_controller; /** Initialize the controller */ void grpc_pid_controller_init(grpc_pid_controller *pid_controller, grpc_pid_controller_args args); /** Reset the controller: useful when things have changed significantly */ void grpc_pid_controller_reset(grpc_pid_controller *pid_controller); /** Update the controller: given a current error estimate, and the time since the last update, returns a new control value */ double grpc_pid_controller_update(grpc_pid_controller *pid_controller, double error, double dt); /** Returns the last control value calculated */ double grpc_pid_controller_last(grpc_pid_controller *pid_controller); #endif /* GRPC_CORE_LIB_TRANSPORT_PID_CONTROLLER_H */ grpc-1.3.2/src/core/lib/transport/service_config.c000066400000000000000000000242761310511640000221240ustar00rootroot00000000000000// // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #include "src/core/lib/transport/service_config.h" #include #include #include #include #include #include "src/core/lib/json/json.h" #include "src/core/lib/slice/slice_hash_table.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/string.h" // The main purpose of the code here is to parse the service config in // JSON form, which will look like this: // // { // "loadBalancingPolicy": "string", // optional // "methodConfig": [ // array of one or more method_config objects // { // "name": [ // array of one or more name objects // { // "service": "string", // required // "method": "string", // optional // } // ], // // remaining fields are optional. // // see https://developers.google.com/protocol-buffers/docs/proto3#json // // for format details. // "waitForReady": bool, // "timeout": "duration_string", // "maxRequestMessageBytes": "int64_string", // "maxResponseMessageBytes": "int64_string", // } // ] // } struct grpc_service_config { char* json_string; // Underlying storage for json_tree. grpc_json* json_tree; }; grpc_service_config* grpc_service_config_create(const char* json_string) { grpc_service_config* service_config = gpr_malloc(sizeof(*service_config)); service_config->json_string = gpr_strdup(json_string); service_config->json_tree = grpc_json_parse_string(service_config->json_string); if (service_config->json_tree == NULL) { gpr_log(GPR_INFO, "failed to parse JSON for service config"); gpr_free(service_config->json_string); gpr_free(service_config); return NULL; } return service_config; } void grpc_service_config_destroy(grpc_service_config* service_config) { grpc_json_destroy(service_config->json_tree); gpr_free(service_config->json_string); gpr_free(service_config); } void grpc_service_config_parse_global_params( const grpc_service_config* service_config, void (*process_json)(const grpc_json* json, void* arg), void* arg) { const grpc_json* json = service_config->json_tree; if (json->type != GRPC_JSON_OBJECT || json->key != NULL) return; for (grpc_json* field = json->child; field != NULL; field = field->next) { if (field->key == NULL) return; if (strcmp(field->key, "methodConfig") == 0) continue; process_json(field, arg); } } const char* grpc_service_config_get_lb_policy_name( const grpc_service_config* service_config) { const grpc_json* json = service_config->json_tree; if (json->type != GRPC_JSON_OBJECT || json->key != NULL) return NULL; const char* lb_policy_name = NULL; for (grpc_json* field = json->child; field != NULL; field = field->next) { if (field->key == NULL) return NULL; if (strcmp(field->key, "loadBalancingPolicy") == 0) { if (lb_policy_name != NULL) return NULL; // Duplicate. if (field->type != GRPC_JSON_STRING) return NULL; lb_policy_name = field->value; } } return lb_policy_name; } // Returns the number of names specified in the method config \a json. static size_t count_names_in_method_config_json(grpc_json* json) { size_t num_names = 0; for (grpc_json* field = json->child; field != NULL; field = field->next) { if (field->key != NULL && strcmp(field->key, "name") == 0) ++num_names; } return num_names; } // Returns a path string for the JSON name object specified by \a json. // Returns NULL on error. Caller takes ownership of result. static char* parse_json_method_name(grpc_json* json) { if (json->type != GRPC_JSON_OBJECT) return NULL; const char* service_name = NULL; const char* method_name = NULL; for (grpc_json* child = json->child; child != NULL; child = child->next) { if (child->key == NULL) return NULL; if (child->type != GRPC_JSON_STRING) return NULL; if (strcmp(child->key, "service") == 0) { if (service_name != NULL) return NULL; // Duplicate. if (child->value == NULL) return NULL; service_name = child->value; } else if (strcmp(child->key, "method") == 0) { if (method_name != NULL) return NULL; // Duplicate. if (child->value == NULL) return NULL; method_name = child->value; } } if (service_name == NULL) return NULL; // Required field. char* path; gpr_asprintf(&path, "/%s/%s", service_name, method_name == NULL ? "*" : method_name); return path; } // Parses the method config from \a json. Adds an entry to \a entries for // each name found, incrementing \a idx for each entry added. // Returns false on error. static bool parse_json_method_config( grpc_exec_ctx* exec_ctx, grpc_json* json, void* (*create_value)(const grpc_json* method_config_json), const grpc_slice_hash_table_vtable* vtable, grpc_slice_hash_table_entry* entries, size_t* idx) { // Construct value. void* method_config = create_value(json); if (method_config == NULL) return false; // Construct list of paths. bool success = false; gpr_strvec paths; gpr_strvec_init(&paths); for (grpc_json* child = json->child; child != NULL; child = child->next) { if (child->key == NULL) continue; if (strcmp(child->key, "name") == 0) { if (child->type != GRPC_JSON_ARRAY) goto done; for (grpc_json* name = child->child; name != NULL; name = name->next) { char* path = parse_json_method_name(name); gpr_strvec_add(&paths, path); } } } if (paths.count == 0) goto done; // No names specified. // Add entry for each path. for (size_t i = 0; i < paths.count; ++i) { entries[*idx].key = grpc_slice_from_copied_string(paths.strs[i]); entries[*idx].value = vtable->copy_value(method_config); entries[*idx].vtable = vtable; ++*idx; } success = true; done: vtable->destroy_value(exec_ctx, method_config); gpr_strvec_destroy(&paths); return success; } grpc_slice_hash_table* grpc_service_config_create_method_config_table( grpc_exec_ctx* exec_ctx, const grpc_service_config* service_config, void* (*create_value)(const grpc_json* method_config_json), const grpc_slice_hash_table_vtable* vtable) { const grpc_json* json = service_config->json_tree; // Traverse parsed JSON tree. if (json->type != GRPC_JSON_OBJECT || json->key != NULL) return NULL; size_t num_entries = 0; grpc_slice_hash_table_entry* entries = NULL; for (grpc_json* field = json->child; field != NULL; field = field->next) { if (field->key == NULL) return NULL; if (strcmp(field->key, "methodConfig") == 0) { if (entries != NULL) return NULL; // Duplicate. if (field->type != GRPC_JSON_ARRAY) return NULL; // Find number of entries. for (grpc_json* method = field->child; method != NULL; method = method->next) { num_entries += count_names_in_method_config_json(method); } // Populate method config table entries. entries = gpr_malloc(num_entries * sizeof(grpc_slice_hash_table_entry)); size_t idx = 0; for (grpc_json* method = field->child; method != NULL; method = method->next) { if (!parse_json_method_config(exec_ctx, method, create_value, vtable, entries, &idx)) { return NULL; } } GPR_ASSERT(idx == num_entries); } } // Instantiate method config table. grpc_slice_hash_table* method_config_table = NULL; if (entries != NULL) { method_config_table = grpc_slice_hash_table_create(num_entries, entries); // Clean up. for (size_t i = 0; i < num_entries; ++i) { grpc_slice_unref_internal(exec_ctx, entries[i].key); vtable->destroy_value(exec_ctx, entries[i].value); } gpr_free(entries); } return method_config_table; } void* grpc_method_config_table_get(grpc_exec_ctx* exec_ctx, const grpc_slice_hash_table* table, grpc_slice path) { void* value = grpc_slice_hash_table_get(table, path); // If we didn't find a match for the path, try looking for a wildcard // entry (i.e., change "/service/method" to "/service/*"). if (value == NULL) { char* path_str = grpc_slice_to_c_string(path); const char* sep = strrchr(path_str, '/') + 1; const size_t len = (size_t)(sep - path_str); char* buf = gpr_malloc(len + 2); // '*' and NUL memcpy(buf, path_str, len); buf[len] = '*'; buf[len + 1] = '\0'; grpc_slice wildcard_path = grpc_slice_from_copied_string(buf); gpr_free(buf); value = grpc_slice_hash_table_get(table, wildcard_path); grpc_slice_unref_internal(exec_ctx, wildcard_path); gpr_free(path_str); } return value; } grpc-1.3.2/src/core/lib/transport/service_config.h000066400000000000000000000071201310511640000221160ustar00rootroot00000000000000// // Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #ifndef GRPC_CORE_LIB_TRANSPORT_SERVICE_CONFIG_H #define GRPC_CORE_LIB_TRANSPORT_SERVICE_CONFIG_H #include #include "src/core/lib/json/json.h" #include "src/core/lib/slice/slice_hash_table.h" typedef struct grpc_service_config grpc_service_config; grpc_service_config* grpc_service_config_create(const char* json_string); void grpc_service_config_destroy(grpc_service_config* service_config); /// Invokes \a process_json() for each global parameter in the service /// config. \a arg is passed as the second argument to \a process_json(). void grpc_service_config_parse_global_params( const grpc_service_config* service_config, void (*process_json)(const grpc_json* json, void* arg), void* arg); /// Gets the LB policy name from \a service_config. /// Returns NULL if no LB policy name was specified. /// Caller does NOT take ownership. const char* grpc_service_config_get_lb_policy_name( const grpc_service_config* service_config); /// Creates a method config table based on the data in \a json. /// The table's keys are request paths. The table's value type is /// returned by \a create_value(), based on data parsed from the JSON tree. /// \a vtable provides methods used to manage the values. /// Returns NULL on error. grpc_slice_hash_table* grpc_service_config_create_method_config_table( grpc_exec_ctx* exec_ctx, const grpc_service_config* service_config, void* (*create_value)(const grpc_json* method_config_json), const grpc_slice_hash_table_vtable* vtable); /// A helper function for looking up values in the table returned by /// \a grpc_service_config_create_method_config_table(). /// Gets the method config for the specified \a path, which should be of /// the form "/service/method". /// Returns NULL if the method has no config. /// Caller does NOT own a reference to the result. void* grpc_method_config_table_get(grpc_exec_ctx* exec_ctx, const grpc_slice_hash_table* table, grpc_slice path); #endif /* GRPC_CORE_LIB_TRANSPORT_SERVICE_CONFIG_H */ grpc-1.3.2/src/core/lib/transport/static_metadata.c000066400000000000000000001226561310511640000222670ustar00rootroot00000000000000/* * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * WARNING: Auto-generated code. * * To make changes to this file, change * tools/codegen/core/gen_static_metadata.py, and then re-run it. * * See metadata.h for an explanation of the interface here, and metadata.c for * an explanation of what's going on. */ #include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/slice/slice_internal.h" static uint8_t g_bytes[] = { 58, 112, 97, 116, 104, 58, 109, 101, 116, 104, 111, 100, 58, 115, 116, 97, 116, 117, 115, 58, 97, 117, 116, 104, 111, 114, 105, 116, 121, 58, 115, 99, 104, 101, 109, 101, 116, 101, 103, 114, 112, 99, 45, 109, 101, 115, 115, 97, 103, 101, 103, 114, 112, 99, 45, 115, 116, 97, 116, 117, 115, 103, 114, 112, 99, 45, 112, 97, 121, 108, 111, 97, 100, 45, 98, 105, 110, 103, 114, 112, 99, 45, 101, 110, 99, 111, 100, 105, 110, 103, 103, 114, 112, 99, 45, 97, 99, 99, 101, 112, 116, 45, 101, 110, 99, 111, 100, 105, 110, 103, 99, 111, 110, 116, 101, 110, 116, 45, 116, 121, 112, 101, 103, 114, 112, 99, 45, 105, 110, 116, 101, 114, 110, 97, 108, 45, 101, 110, 99, 111, 100, 105, 110, 103, 45, 114, 101, 113, 117, 101, 115, 116, 117, 115, 101, 114, 45, 97, 103, 101, 110, 116, 104, 111, 115, 116, 108, 98, 45, 116, 111, 107, 101, 110, 103, 114, 112, 99, 45, 116, 105, 109, 101, 111, 117, 116, 103, 114, 112, 99, 45, 116, 114, 97, 99, 105, 110, 103, 45, 98, 105, 110, 103, 114, 112, 99, 45, 115, 116, 97, 116, 115, 45, 98, 105, 110, 103, 114, 112, 99, 46, 119, 97, 105, 116, 95, 102, 111, 114, 95, 114, 101, 97, 100, 121, 103, 114, 112, 99, 46, 116, 105, 109, 101, 111, 117, 116, 103, 114, 112, 99, 46, 109, 97, 120, 95, 114, 101, 113, 117, 101, 115, 116, 95, 109, 101, 115, 115, 97, 103, 101, 95, 98, 121, 116, 101, 115, 103, 114, 112, 99, 46, 109, 97, 120, 95, 114, 101, 115, 112, 111, 110, 115, 101, 95, 109, 101, 115, 115, 97, 103, 101, 95, 98, 121, 116, 101, 115, 47, 103, 114, 112, 99, 46, 108, 98, 46, 118, 49, 46, 76, 111, 97, 100, 66, 97, 108, 97, 110, 99, 101, 114, 47, 66, 97, 108, 97, 110, 99, 101, 76, 111, 97, 100, 48, 49, 50, 105, 100, 101, 110, 116, 105, 116, 121, 103, 122, 105, 112, 100, 101, 102, 108, 97, 116, 101, 116, 114, 97, 105, 108, 101, 114, 115, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47, 103, 114, 112, 99, 80, 79, 83, 84, 50, 48, 48, 52, 48, 52, 104, 116, 116, 112, 104, 116, 116, 112, 115, 103, 114, 112, 99, 71, 69, 84, 80, 85, 84, 47, 47, 105, 110, 100, 101, 120, 46, 104, 116, 109, 108, 50, 48, 52, 50, 48, 54, 51, 48, 52, 52, 48, 48, 53, 48, 48, 97, 99, 99, 101, 112, 116, 45, 99, 104, 97, 114, 115, 101, 116, 97, 99, 99, 101, 112, 116, 45, 101, 110, 99, 111, 100, 105, 110, 103, 103, 122, 105, 112, 44, 32, 100, 101, 102, 108, 97, 116, 101, 97, 99, 99, 101, 112, 116, 45, 108, 97, 110, 103, 117, 97, 103, 101, 97, 99, 99, 101, 112, 116, 45, 114, 97, 110, 103, 101, 115, 97, 99, 99, 101, 112, 116, 97, 99, 99, 101, 115, 115, 45, 99, 111, 110, 116, 114, 111, 108, 45, 97, 108, 108, 111, 119, 45, 111, 114, 105, 103, 105, 110, 97, 103, 101, 97, 108, 108, 111, 119, 97, 117, 116, 104, 111, 114, 105, 122, 97, 116, 105, 111, 110, 99, 97, 99, 104, 101, 45, 99, 111, 110, 116, 114, 111, 108, 99, 111, 110, 116, 101, 110, 116, 45, 100, 105, 115, 112, 111, 115, 105, 116, 105, 111, 110, 99, 111, 110, 116, 101, 110, 116, 45, 101, 110, 99, 111, 100, 105, 110, 103, 99, 111, 110, 116, 101, 110, 116, 45, 108, 97, 110, 103, 117, 97, 103, 101, 99, 111, 110, 116, 101, 110, 116, 45, 108, 101, 110, 103, 116, 104, 99, 111, 110, 116, 101, 110, 116, 45, 108, 111, 99, 97, 116, 105, 111, 110, 99, 111, 110, 116, 101, 110, 116, 45, 114, 97, 110, 103, 101, 99, 111, 111, 107, 105, 101, 100, 97, 116, 101, 101, 116, 97, 103, 101, 120, 112, 101, 99, 116, 101, 120, 112, 105, 114, 101, 115, 102, 114, 111, 109, 105, 102, 45, 109, 97, 116, 99, 104, 105, 102, 45, 109, 111, 100, 105, 102, 105, 101, 100, 45, 115, 105, 110, 99, 101, 105, 102, 45, 110, 111, 110, 101, 45, 109, 97, 116, 99, 104, 105, 102, 45, 114, 97, 110, 103, 101, 105, 102, 45, 117, 110, 109, 111, 100, 105, 102, 105, 101, 100, 45, 115, 105, 110, 99, 101, 108, 97, 115, 116, 45, 109, 111, 100, 105, 102, 105, 101, 100, 108, 105, 110, 107, 108, 111, 99, 97, 116, 105, 111, 110, 109, 97, 120, 45, 102, 111, 114, 119, 97, 114, 100, 115, 112, 114, 111, 120, 121, 45, 97, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 101, 112, 114, 111, 120, 121, 45, 97, 117, 116, 104, 111, 114, 105, 122, 97, 116, 105, 111, 110, 114, 97, 110, 103, 101, 114, 101, 102, 101, 114, 101, 114, 114, 101, 102, 114, 101, 115, 104, 114, 101, 116, 114, 121, 45, 97, 102, 116, 101, 114, 115, 101, 114, 118, 101, 114, 115, 101, 116, 45, 99, 111, 111, 107, 105, 101, 115, 116, 114, 105, 99, 116, 45, 116, 114, 97, 110, 115, 112, 111, 114, 116, 45, 115, 101, 99, 117, 114, 105, 116, 121, 116, 114, 97, 110, 115, 102, 101, 114, 45, 101, 110, 99, 111, 100, 105, 110, 103, 118, 97, 114, 121, 118, 105, 97, 119, 119, 119, 45, 97, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 101, 105, 100, 101, 110, 116, 105, 116, 121, 44, 100, 101, 102, 108, 97, 116, 101, 105, 100, 101, 110, 116, 105, 116, 121, 44, 103, 122, 105, 112, 100, 101, 102, 108, 97, 116, 101, 44, 103, 122, 105, 112, 105, 100, 101, 110, 116, 105, 116, 121, 44, 100, 101, 102, 108, 97, 116, 101, 44, 103, 122, 105, 112}; static void static_ref(void *unused) {} static void static_unref(grpc_exec_ctx *exec_ctx, void *unused) {} static const grpc_slice_refcount_vtable static_sub_vtable = { static_ref, static_unref, grpc_slice_default_eq_impl, grpc_slice_default_hash_impl}; const grpc_slice_refcount_vtable grpc_static_metadata_vtable = { static_ref, static_unref, grpc_static_slice_eq, grpc_static_slice_hash}; static grpc_slice_refcount static_sub_refcnt = {&static_sub_vtable, &static_sub_refcnt}; grpc_slice_refcount grpc_static_metadata_refcounts[GRPC_STATIC_MDSTR_COUNT] = { {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, {&grpc_static_metadata_vtable, &static_sub_refcnt}, }; const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT] = { {.refcount = &grpc_static_metadata_refcounts[0], .data.refcounted = {g_bytes + 0, 5}}, {.refcount = &grpc_static_metadata_refcounts[1], .data.refcounted = {g_bytes + 5, 7}}, {.refcount = &grpc_static_metadata_refcounts[2], .data.refcounted = {g_bytes + 12, 7}}, {.refcount = &grpc_static_metadata_refcounts[3], .data.refcounted = {g_bytes + 19, 10}}, {.refcount = &grpc_static_metadata_refcounts[4], .data.refcounted = {g_bytes + 29, 7}}, {.refcount = &grpc_static_metadata_refcounts[5], .data.refcounted = {g_bytes + 36, 2}}, {.refcount = &grpc_static_metadata_refcounts[6], .data.refcounted = {g_bytes + 38, 12}}, {.refcount = &grpc_static_metadata_refcounts[7], .data.refcounted = {g_bytes + 50, 11}}, {.refcount = &grpc_static_metadata_refcounts[8], .data.refcounted = {g_bytes + 61, 16}}, {.refcount = &grpc_static_metadata_refcounts[9], .data.refcounted = {g_bytes + 77, 13}}, {.refcount = &grpc_static_metadata_refcounts[10], .data.refcounted = {g_bytes + 90, 20}}, {.refcount = &grpc_static_metadata_refcounts[11], .data.refcounted = {g_bytes + 110, 12}}, {.refcount = &grpc_static_metadata_refcounts[12], .data.refcounted = {g_bytes + 122, 30}}, {.refcount = &grpc_static_metadata_refcounts[13], .data.refcounted = {g_bytes + 152, 10}}, {.refcount = &grpc_static_metadata_refcounts[14], .data.refcounted = {g_bytes + 162, 4}}, {.refcount = &grpc_static_metadata_refcounts[15], .data.refcounted = {g_bytes + 166, 8}}, {.refcount = &grpc_static_metadata_refcounts[16], .data.refcounted = {g_bytes + 174, 12}}, {.refcount = &grpc_static_metadata_refcounts[17], .data.refcounted = {g_bytes + 186, 16}}, {.refcount = &grpc_static_metadata_refcounts[18], .data.refcounted = {g_bytes + 202, 14}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}, {.refcount = &grpc_static_metadata_refcounts[20], .data.refcounted = {g_bytes + 216, 19}}, {.refcount = &grpc_static_metadata_refcounts[21], .data.refcounted = {g_bytes + 235, 12}}, {.refcount = &grpc_static_metadata_refcounts[22], .data.refcounted = {g_bytes + 247, 30}}, {.refcount = &grpc_static_metadata_refcounts[23], .data.refcounted = {g_bytes + 277, 31}}, {.refcount = &grpc_static_metadata_refcounts[24], .data.refcounted = {g_bytes + 308, 36}}, {.refcount = &grpc_static_metadata_refcounts[25], .data.refcounted = {g_bytes + 344, 1}}, {.refcount = &grpc_static_metadata_refcounts[26], .data.refcounted = {g_bytes + 345, 1}}, {.refcount = &grpc_static_metadata_refcounts[27], .data.refcounted = {g_bytes + 346, 1}}, {.refcount = &grpc_static_metadata_refcounts[28], .data.refcounted = {g_bytes + 347, 8}}, {.refcount = &grpc_static_metadata_refcounts[29], .data.refcounted = {g_bytes + 355, 4}}, {.refcount = &grpc_static_metadata_refcounts[30], .data.refcounted = {g_bytes + 359, 7}}, {.refcount = &grpc_static_metadata_refcounts[31], .data.refcounted = {g_bytes + 366, 8}}, {.refcount = &grpc_static_metadata_refcounts[32], .data.refcounted = {g_bytes + 374, 16}}, {.refcount = &grpc_static_metadata_refcounts[33], .data.refcounted = {g_bytes + 390, 4}}, {.refcount = &grpc_static_metadata_refcounts[34], .data.refcounted = {g_bytes + 394, 3}}, {.refcount = &grpc_static_metadata_refcounts[35], .data.refcounted = {g_bytes + 397, 3}}, {.refcount = &grpc_static_metadata_refcounts[36], .data.refcounted = {g_bytes + 400, 4}}, {.refcount = &grpc_static_metadata_refcounts[37], .data.refcounted = {g_bytes + 404, 5}}, {.refcount = &grpc_static_metadata_refcounts[38], .data.refcounted = {g_bytes + 409, 4}}, {.refcount = &grpc_static_metadata_refcounts[39], .data.refcounted = {g_bytes + 413, 3}}, {.refcount = &grpc_static_metadata_refcounts[40], .data.refcounted = {g_bytes + 416, 3}}, {.refcount = &grpc_static_metadata_refcounts[41], .data.refcounted = {g_bytes + 419, 1}}, {.refcount = &grpc_static_metadata_refcounts[42], .data.refcounted = {g_bytes + 420, 11}}, {.refcount = &grpc_static_metadata_refcounts[43], .data.refcounted = {g_bytes + 431, 3}}, {.refcount = &grpc_static_metadata_refcounts[44], .data.refcounted = {g_bytes + 434, 3}}, {.refcount = &grpc_static_metadata_refcounts[45], .data.refcounted = {g_bytes + 437, 3}}, {.refcount = &grpc_static_metadata_refcounts[46], .data.refcounted = {g_bytes + 440, 3}}, {.refcount = &grpc_static_metadata_refcounts[47], .data.refcounted = {g_bytes + 443, 3}}, {.refcount = &grpc_static_metadata_refcounts[48], .data.refcounted = {g_bytes + 446, 14}}, {.refcount = &grpc_static_metadata_refcounts[49], .data.refcounted = {g_bytes + 460, 15}}, {.refcount = &grpc_static_metadata_refcounts[50], .data.refcounted = {g_bytes + 475, 13}}, {.refcount = &grpc_static_metadata_refcounts[51], .data.refcounted = {g_bytes + 488, 15}}, {.refcount = &grpc_static_metadata_refcounts[52], .data.refcounted = {g_bytes + 503, 13}}, {.refcount = &grpc_static_metadata_refcounts[53], .data.refcounted = {g_bytes + 516, 6}}, {.refcount = &grpc_static_metadata_refcounts[54], .data.refcounted = {g_bytes + 522, 27}}, {.refcount = &grpc_static_metadata_refcounts[55], .data.refcounted = {g_bytes + 549, 3}}, {.refcount = &grpc_static_metadata_refcounts[56], .data.refcounted = {g_bytes + 552, 5}}, {.refcount = &grpc_static_metadata_refcounts[57], .data.refcounted = {g_bytes + 557, 13}}, {.refcount = &grpc_static_metadata_refcounts[58], .data.refcounted = {g_bytes + 570, 13}}, {.refcount = &grpc_static_metadata_refcounts[59], .data.refcounted = {g_bytes + 583, 19}}, {.refcount = &grpc_static_metadata_refcounts[60], .data.refcounted = {g_bytes + 602, 16}}, {.refcount = &grpc_static_metadata_refcounts[61], .data.refcounted = {g_bytes + 618, 16}}, {.refcount = &grpc_static_metadata_refcounts[62], .data.refcounted = {g_bytes + 634, 14}}, {.refcount = &grpc_static_metadata_refcounts[63], .data.refcounted = {g_bytes + 648, 16}}, {.refcount = &grpc_static_metadata_refcounts[64], .data.refcounted = {g_bytes + 664, 13}}, {.refcount = &grpc_static_metadata_refcounts[65], .data.refcounted = {g_bytes + 677, 6}}, {.refcount = &grpc_static_metadata_refcounts[66], .data.refcounted = {g_bytes + 683, 4}}, {.refcount = &grpc_static_metadata_refcounts[67], .data.refcounted = {g_bytes + 687, 4}}, {.refcount = &grpc_static_metadata_refcounts[68], .data.refcounted = {g_bytes + 691, 6}}, {.refcount = &grpc_static_metadata_refcounts[69], .data.refcounted = {g_bytes + 697, 7}}, {.refcount = &grpc_static_metadata_refcounts[70], .data.refcounted = {g_bytes + 704, 4}}, {.refcount = &grpc_static_metadata_refcounts[71], .data.refcounted = {g_bytes + 708, 8}}, {.refcount = &grpc_static_metadata_refcounts[72], .data.refcounted = {g_bytes + 716, 17}}, {.refcount = &grpc_static_metadata_refcounts[73], .data.refcounted = {g_bytes + 733, 13}}, {.refcount = &grpc_static_metadata_refcounts[74], .data.refcounted = {g_bytes + 746, 8}}, {.refcount = &grpc_static_metadata_refcounts[75], .data.refcounted = {g_bytes + 754, 19}}, {.refcount = &grpc_static_metadata_refcounts[76], .data.refcounted = {g_bytes + 773, 13}}, {.refcount = &grpc_static_metadata_refcounts[77], .data.refcounted = {g_bytes + 786, 4}}, {.refcount = &grpc_static_metadata_refcounts[78], .data.refcounted = {g_bytes + 790, 8}}, {.refcount = &grpc_static_metadata_refcounts[79], .data.refcounted = {g_bytes + 798, 12}}, {.refcount = &grpc_static_metadata_refcounts[80], .data.refcounted = {g_bytes + 810, 18}}, {.refcount = &grpc_static_metadata_refcounts[81], .data.refcounted = {g_bytes + 828, 19}}, {.refcount = &grpc_static_metadata_refcounts[82], .data.refcounted = {g_bytes + 847, 5}}, {.refcount = &grpc_static_metadata_refcounts[83], .data.refcounted = {g_bytes + 852, 7}}, {.refcount = &grpc_static_metadata_refcounts[84], .data.refcounted = {g_bytes + 859, 7}}, {.refcount = &grpc_static_metadata_refcounts[85], .data.refcounted = {g_bytes + 866, 11}}, {.refcount = &grpc_static_metadata_refcounts[86], .data.refcounted = {g_bytes + 877, 6}}, {.refcount = &grpc_static_metadata_refcounts[87], .data.refcounted = {g_bytes + 883, 10}}, {.refcount = &grpc_static_metadata_refcounts[88], .data.refcounted = {g_bytes + 893, 25}}, {.refcount = &grpc_static_metadata_refcounts[89], .data.refcounted = {g_bytes + 918, 17}}, {.refcount = &grpc_static_metadata_refcounts[90], .data.refcounted = {g_bytes + 935, 4}}, {.refcount = &grpc_static_metadata_refcounts[91], .data.refcounted = {g_bytes + 939, 3}}, {.refcount = &grpc_static_metadata_refcounts[92], .data.refcounted = {g_bytes + 942, 16}}, {.refcount = &grpc_static_metadata_refcounts[93], .data.refcounted = {g_bytes + 958, 16}}, {.refcount = &grpc_static_metadata_refcounts[94], .data.refcounted = {g_bytes + 974, 13}}, {.refcount = &grpc_static_metadata_refcounts[95], .data.refcounted = {g_bytes + 987, 12}}, {.refcount = &grpc_static_metadata_refcounts[96], .data.refcounted = {g_bytes + 999, 21}}, }; uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 6, 6, 8, 8}; static const int8_t elems_r[] = { 10, 8, -3, 0, 9, 21, -75, 22, 0, 10, -7, 20, 0, 19, 18, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -48, -49, 16, -51, -52, -53, -54, -54, -55, -56, -57, 0, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 14, 13, 12, 11, 10, 9, 8, 0}; static uint32_t elems_phash(uint32_t i) { i -= 41; uint32_t x = i % 95; uint32_t y = i / 95; uint32_t h = x; if (y < GPR_ARRAY_SIZE(elems_r)) { uint32_t delta = (uint32_t)elems_r[y]; h += delta; } return h; } static const uint16_t elem_keys[] = { 998, 999, 1000, 237, 238, 239, 240, 241, 136, 137, 41, 42, 424, 425, 426, 901, 902, 903, 704, 705, 1086, 516, 706, 1280, 1377, 1474, 4675, 4772, 4803, 4966, 5063, 5160, 5257, 1099, 5354, 5451, 5548, 5645, 5742, 5839, 5936, 6033, 6130, 6227, 6324, 6421, 6518, 6615, 6712, 6809, 6906, 7003, 7100, 7197, 7294, 7391, 7488, 7585, 7682, 7779, 7876, 7973, 8070, 8167, 8264, 1063, 1064, 1065, 1066, 8361, 8458, 8555, 8652, 8749, 8846, 8943, 310, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 228, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static const uint8_t elem_idxs[] = { 73, 76, 74, 19, 20, 21, 22, 23, 15, 16, 17, 18, 11, 12, 13, 3, 4, 5, 0, 1, 41, 6, 2, 69, 48, 55, 24, 25, 26, 27, 28, 29, 30, 7, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 42, 43, 44, 45, 46, 47, 49, 50, 51, 52, 53, 54, 56, 57, 58, 59, 60, 61, 62, 63, 64, 75, 77, 78, 79, 65, 66, 67, 68, 70, 71, 72, 14, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 8, 9, 10}; grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b) { if (a == -1 || b == -1) return GRPC_MDNULL; uint32_t k = (uint32_t)(a * 97 + b); uint32_t h = elems_phash(k); return h < GPR_ARRAY_SIZE(elem_keys) && elem_keys[h] == k ? GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[elem_idxs[h]], GRPC_MDELEM_STORAGE_STATIC) : GRPC_MDNULL; } grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT] = { {{.refcount = &grpc_static_metadata_refcounts[7], .data.refcounted = {g_bytes + 50, 11}}, {.refcount = &grpc_static_metadata_refcounts[25], .data.refcounted = {g_bytes + 344, 1}}}, {{.refcount = &grpc_static_metadata_refcounts[7], .data.refcounted = {g_bytes + 50, 11}}, {.refcount = &grpc_static_metadata_refcounts[26], .data.refcounted = {g_bytes + 345, 1}}}, {{.refcount = &grpc_static_metadata_refcounts[7], .data.refcounted = {g_bytes + 50, 11}}, {.refcount = &grpc_static_metadata_refcounts[27], .data.refcounted = {g_bytes + 346, 1}}}, {{.refcount = &grpc_static_metadata_refcounts[9], .data.refcounted = {g_bytes + 77, 13}}, {.refcount = &grpc_static_metadata_refcounts[28], .data.refcounted = {g_bytes + 347, 8}}}, {{.refcount = &grpc_static_metadata_refcounts[9], .data.refcounted = {g_bytes + 77, 13}}, {.refcount = &grpc_static_metadata_refcounts[29], .data.refcounted = {g_bytes + 355, 4}}}, {{.refcount = &grpc_static_metadata_refcounts[9], .data.refcounted = {g_bytes + 77, 13}}, {.refcount = &grpc_static_metadata_refcounts[30], .data.refcounted = {g_bytes + 359, 7}}}, {{.refcount = &grpc_static_metadata_refcounts[5], .data.refcounted = {g_bytes + 36, 2}}, {.refcount = &grpc_static_metadata_refcounts[31], .data.refcounted = {g_bytes + 366, 8}}}, {{.refcount = &grpc_static_metadata_refcounts[11], .data.refcounted = {g_bytes + 110, 12}}, {.refcount = &grpc_static_metadata_refcounts[32], .data.refcounted = {g_bytes + 374, 16}}}, {{.refcount = &grpc_static_metadata_refcounts[1], .data.refcounted = {g_bytes + 5, 7}}, {.refcount = &grpc_static_metadata_refcounts[33], .data.refcounted = {g_bytes + 390, 4}}}, {{.refcount = &grpc_static_metadata_refcounts[2], .data.refcounted = {g_bytes + 12, 7}}, {.refcount = &grpc_static_metadata_refcounts[34], .data.refcounted = {g_bytes + 394, 3}}}, {{.refcount = &grpc_static_metadata_refcounts[2], .data.refcounted = {g_bytes + 12, 7}}, {.refcount = &grpc_static_metadata_refcounts[35], .data.refcounted = {g_bytes + 397, 3}}}, {{.refcount = &grpc_static_metadata_refcounts[4], .data.refcounted = {g_bytes + 29, 7}}, {.refcount = &grpc_static_metadata_refcounts[36], .data.refcounted = {g_bytes + 400, 4}}}, {{.refcount = &grpc_static_metadata_refcounts[4], .data.refcounted = {g_bytes + 29, 7}}, {.refcount = &grpc_static_metadata_refcounts[37], .data.refcounted = {g_bytes + 404, 5}}}, {{.refcount = &grpc_static_metadata_refcounts[4], .data.refcounted = {g_bytes + 29, 7}}, {.refcount = &grpc_static_metadata_refcounts[38], .data.refcounted = {g_bytes + 409, 4}}}, {{.refcount = &grpc_static_metadata_refcounts[3], .data.refcounted = {g_bytes + 19, 10}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[1], .data.refcounted = {g_bytes + 5, 7}}, {.refcount = &grpc_static_metadata_refcounts[39], .data.refcounted = {g_bytes + 413, 3}}}, {{.refcount = &grpc_static_metadata_refcounts[1], .data.refcounted = {g_bytes + 5, 7}}, {.refcount = &grpc_static_metadata_refcounts[40], .data.refcounted = {g_bytes + 416, 3}}}, {{.refcount = &grpc_static_metadata_refcounts[0], .data.refcounted = {g_bytes + 0, 5}}, {.refcount = &grpc_static_metadata_refcounts[41], .data.refcounted = {g_bytes + 419, 1}}}, {{.refcount = &grpc_static_metadata_refcounts[0], .data.refcounted = {g_bytes + 0, 5}}, {.refcount = &grpc_static_metadata_refcounts[42], .data.refcounted = {g_bytes + 420, 11}}}, {{.refcount = &grpc_static_metadata_refcounts[2], .data.refcounted = {g_bytes + 12, 7}}, {.refcount = &grpc_static_metadata_refcounts[43], .data.refcounted = {g_bytes + 431, 3}}}, {{.refcount = &grpc_static_metadata_refcounts[2], .data.refcounted = {g_bytes + 12, 7}}, {.refcount = &grpc_static_metadata_refcounts[44], .data.refcounted = {g_bytes + 434, 3}}}, {{.refcount = &grpc_static_metadata_refcounts[2], .data.refcounted = {g_bytes + 12, 7}}, {.refcount = &grpc_static_metadata_refcounts[45], .data.refcounted = {g_bytes + 437, 3}}}, {{.refcount = &grpc_static_metadata_refcounts[2], .data.refcounted = {g_bytes + 12, 7}}, {.refcount = &grpc_static_metadata_refcounts[46], .data.refcounted = {g_bytes + 440, 3}}}, {{.refcount = &grpc_static_metadata_refcounts[2], .data.refcounted = {g_bytes + 12, 7}}, {.refcount = &grpc_static_metadata_refcounts[47], .data.refcounted = {g_bytes + 443, 3}}}, {{.refcount = &grpc_static_metadata_refcounts[48], .data.refcounted = {g_bytes + 446, 14}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[49], .data.refcounted = {g_bytes + 460, 15}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[49], .data.refcounted = {g_bytes + 460, 15}}, {.refcount = &grpc_static_metadata_refcounts[50], .data.refcounted = {g_bytes + 475, 13}}}, {{.refcount = &grpc_static_metadata_refcounts[51], .data.refcounted = {g_bytes + 488, 15}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[52], .data.refcounted = {g_bytes + 503, 13}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[53], .data.refcounted = {g_bytes + 516, 6}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[54], .data.refcounted = {g_bytes + 522, 27}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[55], .data.refcounted = {g_bytes + 549, 3}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[56], .data.refcounted = {g_bytes + 552, 5}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[57], .data.refcounted = {g_bytes + 557, 13}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[58], .data.refcounted = {g_bytes + 570, 13}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[59], .data.refcounted = {g_bytes + 583, 19}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[60], .data.refcounted = {g_bytes + 602, 16}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[61], .data.refcounted = {g_bytes + 618, 16}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[62], .data.refcounted = {g_bytes + 634, 14}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[63], .data.refcounted = {g_bytes + 648, 16}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[64], .data.refcounted = {g_bytes + 664, 13}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[11], .data.refcounted = {g_bytes + 110, 12}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[65], .data.refcounted = {g_bytes + 677, 6}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[66], .data.refcounted = {g_bytes + 683, 4}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[67], .data.refcounted = {g_bytes + 687, 4}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[68], .data.refcounted = {g_bytes + 691, 6}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[69], .data.refcounted = {g_bytes + 697, 7}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[70], .data.refcounted = {g_bytes + 704, 4}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[14], .data.refcounted = {g_bytes + 162, 4}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[71], .data.refcounted = {g_bytes + 708, 8}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[72], .data.refcounted = {g_bytes + 716, 17}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[73], .data.refcounted = {g_bytes + 733, 13}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[74], .data.refcounted = {g_bytes + 746, 8}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[75], .data.refcounted = {g_bytes + 754, 19}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[76], .data.refcounted = {g_bytes + 773, 13}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[15], .data.refcounted = {g_bytes + 166, 8}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[77], .data.refcounted = {g_bytes + 786, 4}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[78], .data.refcounted = {g_bytes + 790, 8}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[79], .data.refcounted = {g_bytes + 798, 12}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[80], .data.refcounted = {g_bytes + 810, 18}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[81], .data.refcounted = {g_bytes + 828, 19}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[82], .data.refcounted = {g_bytes + 847, 5}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[83], .data.refcounted = {g_bytes + 852, 7}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[84], .data.refcounted = {g_bytes + 859, 7}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[85], .data.refcounted = {g_bytes + 866, 11}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[86], .data.refcounted = {g_bytes + 877, 6}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[87], .data.refcounted = {g_bytes + 883, 10}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[88], .data.refcounted = {g_bytes + 893, 25}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[89], .data.refcounted = {g_bytes + 918, 17}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[13], .data.refcounted = {g_bytes + 152, 10}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[90], .data.refcounted = {g_bytes + 935, 4}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[91], .data.refcounted = {g_bytes + 939, 3}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[92], .data.refcounted = {g_bytes + 942, 16}}, {.refcount = &grpc_static_metadata_refcounts[19], .data.refcounted = {g_bytes + 216, 0}}}, {{.refcount = &grpc_static_metadata_refcounts[10], .data.refcounted = {g_bytes + 90, 20}}, {.refcount = &grpc_static_metadata_refcounts[28], .data.refcounted = {g_bytes + 347, 8}}}, {{.refcount = &grpc_static_metadata_refcounts[10], .data.refcounted = {g_bytes + 90, 20}}, {.refcount = &grpc_static_metadata_refcounts[30], .data.refcounted = {g_bytes + 359, 7}}}, {{.refcount = &grpc_static_metadata_refcounts[10], .data.refcounted = {g_bytes + 90, 20}}, {.refcount = &grpc_static_metadata_refcounts[93], .data.refcounted = {g_bytes + 958, 16}}}, {{.refcount = &grpc_static_metadata_refcounts[10], .data.refcounted = {g_bytes + 90, 20}}, {.refcount = &grpc_static_metadata_refcounts[29], .data.refcounted = {g_bytes + 355, 4}}}, {{.refcount = &grpc_static_metadata_refcounts[10], .data.refcounted = {g_bytes + 90, 20}}, {.refcount = &grpc_static_metadata_refcounts[94], .data.refcounted = {g_bytes + 974, 13}}}, {{.refcount = &grpc_static_metadata_refcounts[10], .data.refcounted = {g_bytes + 90, 20}}, {.refcount = &grpc_static_metadata_refcounts[95], .data.refcounted = {g_bytes + 987, 12}}}, {{.refcount = &grpc_static_metadata_refcounts[10], .data.refcounted = {g_bytes + 90, 20}}, {.refcount = &grpc_static_metadata_refcounts[96], .data.refcounted = {g_bytes + 999, 21}}}, }; const uint8_t grpc_static_accept_encoding_metadata[8] = {0, 73, 74, 75, 76, 77, 78, 79}; grpc-1.3.2/src/core/lib/transport/static_metadata.h000066400000000000000000000576361310511640000223010ustar00rootroot00000000000000/* * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * WARNING: Auto-generated code. * * To make changes to this file, change * tools/codegen/core/gen_static_metadata.py, and then re-run it. * * See metadata.h for an explanation of the interface here, and metadata.c for * an explanation of what's going on. */ #ifndef GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H #define GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H #include "src/core/lib/transport/metadata.h" #define GRPC_STATIC_MDSTR_COUNT 97 extern const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT]; /* ":path" */ #define GRPC_MDSTR_PATH (grpc_static_slice_table[0]) /* ":method" */ #define GRPC_MDSTR_METHOD (grpc_static_slice_table[1]) /* ":status" */ #define GRPC_MDSTR_STATUS (grpc_static_slice_table[2]) /* ":authority" */ #define GRPC_MDSTR_AUTHORITY (grpc_static_slice_table[3]) /* ":scheme" */ #define GRPC_MDSTR_SCHEME (grpc_static_slice_table[4]) /* "te" */ #define GRPC_MDSTR_TE (grpc_static_slice_table[5]) /* "grpc-message" */ #define GRPC_MDSTR_GRPC_MESSAGE (grpc_static_slice_table[6]) /* "grpc-status" */ #define GRPC_MDSTR_GRPC_STATUS (grpc_static_slice_table[7]) /* "grpc-payload-bin" */ #define GRPC_MDSTR_GRPC_PAYLOAD_BIN (grpc_static_slice_table[8]) /* "grpc-encoding" */ #define GRPC_MDSTR_GRPC_ENCODING (grpc_static_slice_table[9]) /* "grpc-accept-encoding" */ #define GRPC_MDSTR_GRPC_ACCEPT_ENCODING (grpc_static_slice_table[10]) /* "content-type" */ #define GRPC_MDSTR_CONTENT_TYPE (grpc_static_slice_table[11]) /* "grpc-internal-encoding-request" */ #define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (grpc_static_slice_table[12]) /* "user-agent" */ #define GRPC_MDSTR_USER_AGENT (grpc_static_slice_table[13]) /* "host" */ #define GRPC_MDSTR_HOST (grpc_static_slice_table[14]) /* "lb-token" */ #define GRPC_MDSTR_LB_TOKEN (grpc_static_slice_table[15]) /* "grpc-timeout" */ #define GRPC_MDSTR_GRPC_TIMEOUT (grpc_static_slice_table[16]) /* "grpc-tracing-bin" */ #define GRPC_MDSTR_GRPC_TRACING_BIN (grpc_static_slice_table[17]) /* "grpc-stats-bin" */ #define GRPC_MDSTR_GRPC_STATS_BIN (grpc_static_slice_table[18]) /* "" */ #define GRPC_MDSTR_EMPTY (grpc_static_slice_table[19]) /* "grpc.wait_for_ready" */ #define GRPC_MDSTR_GRPC_DOT_WAIT_FOR_READY (grpc_static_slice_table[20]) /* "grpc.timeout" */ #define GRPC_MDSTR_GRPC_DOT_TIMEOUT (grpc_static_slice_table[21]) /* "grpc.max_request_message_bytes" */ #define GRPC_MDSTR_GRPC_DOT_MAX_REQUEST_MESSAGE_BYTES \ (grpc_static_slice_table[22]) /* "grpc.max_response_message_bytes" */ #define GRPC_MDSTR_GRPC_DOT_MAX_RESPONSE_MESSAGE_BYTES \ (grpc_static_slice_table[23]) /* "/grpc.lb.v1.LoadBalancer/BalanceLoad" */ #define GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD \ (grpc_static_slice_table[24]) /* "0" */ #define GRPC_MDSTR_0 (grpc_static_slice_table[25]) /* "1" */ #define GRPC_MDSTR_1 (grpc_static_slice_table[26]) /* "2" */ #define GRPC_MDSTR_2 (grpc_static_slice_table[27]) /* "identity" */ #define GRPC_MDSTR_IDENTITY (grpc_static_slice_table[28]) /* "gzip" */ #define GRPC_MDSTR_GZIP (grpc_static_slice_table[29]) /* "deflate" */ #define GRPC_MDSTR_DEFLATE (grpc_static_slice_table[30]) /* "trailers" */ #define GRPC_MDSTR_TRAILERS (grpc_static_slice_table[31]) /* "application/grpc" */ #define GRPC_MDSTR_APPLICATION_SLASH_GRPC (grpc_static_slice_table[32]) /* "POST" */ #define GRPC_MDSTR_POST (grpc_static_slice_table[33]) /* "200" */ #define GRPC_MDSTR_200 (grpc_static_slice_table[34]) /* "404" */ #define GRPC_MDSTR_404 (grpc_static_slice_table[35]) /* "http" */ #define GRPC_MDSTR_HTTP (grpc_static_slice_table[36]) /* "https" */ #define GRPC_MDSTR_HTTPS (grpc_static_slice_table[37]) /* "grpc" */ #define GRPC_MDSTR_GRPC (grpc_static_slice_table[38]) /* "GET" */ #define GRPC_MDSTR_GET (grpc_static_slice_table[39]) /* "PUT" */ #define GRPC_MDSTR_PUT (grpc_static_slice_table[40]) /* "/" */ #define GRPC_MDSTR_SLASH (grpc_static_slice_table[41]) /* "/index.html" */ #define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (grpc_static_slice_table[42]) /* "204" */ #define GRPC_MDSTR_204 (grpc_static_slice_table[43]) /* "206" */ #define GRPC_MDSTR_206 (grpc_static_slice_table[44]) /* "304" */ #define GRPC_MDSTR_304 (grpc_static_slice_table[45]) /* "400" */ #define GRPC_MDSTR_400 (grpc_static_slice_table[46]) /* "500" */ #define GRPC_MDSTR_500 (grpc_static_slice_table[47]) /* "accept-charset" */ #define GRPC_MDSTR_ACCEPT_CHARSET (grpc_static_slice_table[48]) /* "accept-encoding" */ #define GRPC_MDSTR_ACCEPT_ENCODING (grpc_static_slice_table[49]) /* "gzip, deflate" */ #define GRPC_MDSTR_GZIP_COMMA_DEFLATE (grpc_static_slice_table[50]) /* "accept-language" */ #define GRPC_MDSTR_ACCEPT_LANGUAGE (grpc_static_slice_table[51]) /* "accept-ranges" */ #define GRPC_MDSTR_ACCEPT_RANGES (grpc_static_slice_table[52]) /* "accept" */ #define GRPC_MDSTR_ACCEPT (grpc_static_slice_table[53]) /* "access-control-allow-origin" */ #define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN (grpc_static_slice_table[54]) /* "age" */ #define GRPC_MDSTR_AGE (grpc_static_slice_table[55]) /* "allow" */ #define GRPC_MDSTR_ALLOW (grpc_static_slice_table[56]) /* "authorization" */ #define GRPC_MDSTR_AUTHORIZATION (grpc_static_slice_table[57]) /* "cache-control" */ #define GRPC_MDSTR_CACHE_CONTROL (grpc_static_slice_table[58]) /* "content-disposition" */ #define GRPC_MDSTR_CONTENT_DISPOSITION (grpc_static_slice_table[59]) /* "content-encoding" */ #define GRPC_MDSTR_CONTENT_ENCODING (grpc_static_slice_table[60]) /* "content-language" */ #define GRPC_MDSTR_CONTENT_LANGUAGE (grpc_static_slice_table[61]) /* "content-length" */ #define GRPC_MDSTR_CONTENT_LENGTH (grpc_static_slice_table[62]) /* "content-location" */ #define GRPC_MDSTR_CONTENT_LOCATION (grpc_static_slice_table[63]) /* "content-range" */ #define GRPC_MDSTR_CONTENT_RANGE (grpc_static_slice_table[64]) /* "cookie" */ #define GRPC_MDSTR_COOKIE (grpc_static_slice_table[65]) /* "date" */ #define GRPC_MDSTR_DATE (grpc_static_slice_table[66]) /* "etag" */ #define GRPC_MDSTR_ETAG (grpc_static_slice_table[67]) /* "expect" */ #define GRPC_MDSTR_EXPECT (grpc_static_slice_table[68]) /* "expires" */ #define GRPC_MDSTR_EXPIRES (grpc_static_slice_table[69]) /* "from" */ #define GRPC_MDSTR_FROM (grpc_static_slice_table[70]) /* "if-match" */ #define GRPC_MDSTR_IF_MATCH (grpc_static_slice_table[71]) /* "if-modified-since" */ #define GRPC_MDSTR_IF_MODIFIED_SINCE (grpc_static_slice_table[72]) /* "if-none-match" */ #define GRPC_MDSTR_IF_NONE_MATCH (grpc_static_slice_table[73]) /* "if-range" */ #define GRPC_MDSTR_IF_RANGE (grpc_static_slice_table[74]) /* "if-unmodified-since" */ #define GRPC_MDSTR_IF_UNMODIFIED_SINCE (grpc_static_slice_table[75]) /* "last-modified" */ #define GRPC_MDSTR_LAST_MODIFIED (grpc_static_slice_table[76]) /* "link" */ #define GRPC_MDSTR_LINK (grpc_static_slice_table[77]) /* "location" */ #define GRPC_MDSTR_LOCATION (grpc_static_slice_table[78]) /* "max-forwards" */ #define GRPC_MDSTR_MAX_FORWARDS (grpc_static_slice_table[79]) /* "proxy-authenticate" */ #define GRPC_MDSTR_PROXY_AUTHENTICATE (grpc_static_slice_table[80]) /* "proxy-authorization" */ #define GRPC_MDSTR_PROXY_AUTHORIZATION (grpc_static_slice_table[81]) /* "range" */ #define GRPC_MDSTR_RANGE (grpc_static_slice_table[82]) /* "referer" */ #define GRPC_MDSTR_REFERER (grpc_static_slice_table[83]) /* "refresh" */ #define GRPC_MDSTR_REFRESH (grpc_static_slice_table[84]) /* "retry-after" */ #define GRPC_MDSTR_RETRY_AFTER (grpc_static_slice_table[85]) /* "server" */ #define GRPC_MDSTR_SERVER (grpc_static_slice_table[86]) /* "set-cookie" */ #define GRPC_MDSTR_SET_COOKIE (grpc_static_slice_table[87]) /* "strict-transport-security" */ #define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (grpc_static_slice_table[88]) /* "transfer-encoding" */ #define GRPC_MDSTR_TRANSFER_ENCODING (grpc_static_slice_table[89]) /* "vary" */ #define GRPC_MDSTR_VARY (grpc_static_slice_table[90]) /* "via" */ #define GRPC_MDSTR_VIA (grpc_static_slice_table[91]) /* "www-authenticate" */ #define GRPC_MDSTR_WWW_AUTHENTICATE (grpc_static_slice_table[92]) /* "identity,deflate" */ #define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE (grpc_static_slice_table[93]) /* "identity,gzip" */ #define GRPC_MDSTR_IDENTITY_COMMA_GZIP (grpc_static_slice_table[94]) /* "deflate,gzip" */ #define GRPC_MDSTR_DEFLATE_COMMA_GZIP (grpc_static_slice_table[95]) /* "identity,deflate,gzip" */ #define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \ (grpc_static_slice_table[96]) extern const grpc_slice_refcount_vtable grpc_static_metadata_vtable; extern grpc_slice_refcount grpc_static_metadata_refcounts[GRPC_STATIC_MDSTR_COUNT]; #define GRPC_IS_STATIC_METADATA_STRING(slice) \ ((slice).refcount != NULL && \ (slice).refcount->vtable == &grpc_static_metadata_vtable) #define GRPC_STATIC_METADATA_INDEX(static_slice) \ ((int)((static_slice).refcount - grpc_static_metadata_refcounts)) #define GRPC_STATIC_MDELEM_COUNT 80 extern grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT]; extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT]; /* "grpc-status": "0" */ #define GRPC_MDELEM_GRPC_STATUS_0 \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[0], GRPC_MDELEM_STORAGE_STATIC)) /* "grpc-status": "1" */ #define GRPC_MDELEM_GRPC_STATUS_1 \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[1], GRPC_MDELEM_STORAGE_STATIC)) /* "grpc-status": "2" */ #define GRPC_MDELEM_GRPC_STATUS_2 \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[2], GRPC_MDELEM_STORAGE_STATIC)) /* "grpc-encoding": "identity" */ #define GRPC_MDELEM_GRPC_ENCODING_IDENTITY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[3], GRPC_MDELEM_STORAGE_STATIC)) /* "grpc-encoding": "gzip" */ #define GRPC_MDELEM_GRPC_ENCODING_GZIP \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[4], GRPC_MDELEM_STORAGE_STATIC)) /* "grpc-encoding": "deflate" */ #define GRPC_MDELEM_GRPC_ENCODING_DEFLATE \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[5], GRPC_MDELEM_STORAGE_STATIC)) /* "te": "trailers" */ #define GRPC_MDELEM_TE_TRAILERS \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[6], GRPC_MDELEM_STORAGE_STATIC)) /* "content-type": "application/grpc" */ #define GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[7], GRPC_MDELEM_STORAGE_STATIC)) /* ":method": "POST" */ #define GRPC_MDELEM_METHOD_POST \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[8], GRPC_MDELEM_STORAGE_STATIC)) /* ":status": "200" */ #define GRPC_MDELEM_STATUS_200 \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[9], GRPC_MDELEM_STORAGE_STATIC)) /* ":status": "404" */ #define GRPC_MDELEM_STATUS_404 \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[10], GRPC_MDELEM_STORAGE_STATIC)) /* ":scheme": "http" */ #define GRPC_MDELEM_SCHEME_HTTP \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[11], GRPC_MDELEM_STORAGE_STATIC)) /* ":scheme": "https" */ #define GRPC_MDELEM_SCHEME_HTTPS \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[12], GRPC_MDELEM_STORAGE_STATIC)) /* ":scheme": "grpc" */ #define GRPC_MDELEM_SCHEME_GRPC \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[13], GRPC_MDELEM_STORAGE_STATIC)) /* ":authority": "" */ #define GRPC_MDELEM_AUTHORITY_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[14], GRPC_MDELEM_STORAGE_STATIC)) /* ":method": "GET" */ #define GRPC_MDELEM_METHOD_GET \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[15], GRPC_MDELEM_STORAGE_STATIC)) /* ":method": "PUT" */ #define GRPC_MDELEM_METHOD_PUT \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[16], GRPC_MDELEM_STORAGE_STATIC)) /* ":path": "/" */ #define GRPC_MDELEM_PATH_SLASH \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[17], GRPC_MDELEM_STORAGE_STATIC)) /* ":path": "/index.html" */ #define GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[18], GRPC_MDELEM_STORAGE_STATIC)) /* ":status": "204" */ #define GRPC_MDELEM_STATUS_204 \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[19], GRPC_MDELEM_STORAGE_STATIC)) /* ":status": "206" */ #define GRPC_MDELEM_STATUS_206 \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[20], GRPC_MDELEM_STORAGE_STATIC)) /* ":status": "304" */ #define GRPC_MDELEM_STATUS_304 \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[21], GRPC_MDELEM_STORAGE_STATIC)) /* ":status": "400" */ #define GRPC_MDELEM_STATUS_400 \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[22], GRPC_MDELEM_STORAGE_STATIC)) /* ":status": "500" */ #define GRPC_MDELEM_STATUS_500 \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[23], GRPC_MDELEM_STORAGE_STATIC)) /* "accept-charset": "" */ #define GRPC_MDELEM_ACCEPT_CHARSET_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[24], GRPC_MDELEM_STORAGE_STATIC)) /* "accept-encoding": "" */ #define GRPC_MDELEM_ACCEPT_ENCODING_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[25], GRPC_MDELEM_STORAGE_STATIC)) /* "accept-encoding": "gzip, deflate" */ #define GRPC_MDELEM_ACCEPT_ENCODING_GZIP_COMMA_DEFLATE \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[26], GRPC_MDELEM_STORAGE_STATIC)) /* "accept-language": "" */ #define GRPC_MDELEM_ACCEPT_LANGUAGE_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[27], GRPC_MDELEM_STORAGE_STATIC)) /* "accept-ranges": "" */ #define GRPC_MDELEM_ACCEPT_RANGES_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[28], GRPC_MDELEM_STORAGE_STATIC)) /* "accept": "" */ #define GRPC_MDELEM_ACCEPT_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[29], GRPC_MDELEM_STORAGE_STATIC)) /* "access-control-allow-origin": "" */ #define GRPC_MDELEM_ACCESS_CONTROL_ALLOW_ORIGIN_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[30], GRPC_MDELEM_STORAGE_STATIC)) /* "age": "" */ #define GRPC_MDELEM_AGE_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[31], GRPC_MDELEM_STORAGE_STATIC)) /* "allow": "" */ #define GRPC_MDELEM_ALLOW_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[32], GRPC_MDELEM_STORAGE_STATIC)) /* "authorization": "" */ #define GRPC_MDELEM_AUTHORIZATION_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[33], GRPC_MDELEM_STORAGE_STATIC)) /* "cache-control": "" */ #define GRPC_MDELEM_CACHE_CONTROL_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[34], GRPC_MDELEM_STORAGE_STATIC)) /* "content-disposition": "" */ #define GRPC_MDELEM_CONTENT_DISPOSITION_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[35], GRPC_MDELEM_STORAGE_STATIC)) /* "content-encoding": "" */ #define GRPC_MDELEM_CONTENT_ENCODING_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[36], GRPC_MDELEM_STORAGE_STATIC)) /* "content-language": "" */ #define GRPC_MDELEM_CONTENT_LANGUAGE_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[37], GRPC_MDELEM_STORAGE_STATIC)) /* "content-length": "" */ #define GRPC_MDELEM_CONTENT_LENGTH_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[38], GRPC_MDELEM_STORAGE_STATIC)) /* "content-location": "" */ #define GRPC_MDELEM_CONTENT_LOCATION_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[39], GRPC_MDELEM_STORAGE_STATIC)) /* "content-range": "" */ #define GRPC_MDELEM_CONTENT_RANGE_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[40], GRPC_MDELEM_STORAGE_STATIC)) /* "content-type": "" */ #define GRPC_MDELEM_CONTENT_TYPE_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[41], GRPC_MDELEM_STORAGE_STATIC)) /* "cookie": "" */ #define GRPC_MDELEM_COOKIE_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[42], GRPC_MDELEM_STORAGE_STATIC)) /* "date": "" */ #define GRPC_MDELEM_DATE_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[43], GRPC_MDELEM_STORAGE_STATIC)) /* "etag": "" */ #define GRPC_MDELEM_ETAG_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[44], GRPC_MDELEM_STORAGE_STATIC)) /* "expect": "" */ #define GRPC_MDELEM_EXPECT_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[45], GRPC_MDELEM_STORAGE_STATIC)) /* "expires": "" */ #define GRPC_MDELEM_EXPIRES_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[46], GRPC_MDELEM_STORAGE_STATIC)) /* "from": "" */ #define GRPC_MDELEM_FROM_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[47], GRPC_MDELEM_STORAGE_STATIC)) /* "host": "" */ #define GRPC_MDELEM_HOST_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[48], GRPC_MDELEM_STORAGE_STATIC)) /* "if-match": "" */ #define GRPC_MDELEM_IF_MATCH_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[49], GRPC_MDELEM_STORAGE_STATIC)) /* "if-modified-since": "" */ #define GRPC_MDELEM_IF_MODIFIED_SINCE_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[50], GRPC_MDELEM_STORAGE_STATIC)) /* "if-none-match": "" */ #define GRPC_MDELEM_IF_NONE_MATCH_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[51], GRPC_MDELEM_STORAGE_STATIC)) /* "if-range": "" */ #define GRPC_MDELEM_IF_RANGE_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[52], GRPC_MDELEM_STORAGE_STATIC)) /* "if-unmodified-since": "" */ #define GRPC_MDELEM_IF_UNMODIFIED_SINCE_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[53], GRPC_MDELEM_STORAGE_STATIC)) /* "last-modified": "" */ #define GRPC_MDELEM_LAST_MODIFIED_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[54], GRPC_MDELEM_STORAGE_STATIC)) /* "lb-token": "" */ #define GRPC_MDELEM_LB_TOKEN_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[55], GRPC_MDELEM_STORAGE_STATIC)) /* "link": "" */ #define GRPC_MDELEM_LINK_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[56], GRPC_MDELEM_STORAGE_STATIC)) /* "location": "" */ #define GRPC_MDELEM_LOCATION_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[57], GRPC_MDELEM_STORAGE_STATIC)) /* "max-forwards": "" */ #define GRPC_MDELEM_MAX_FORWARDS_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[58], GRPC_MDELEM_STORAGE_STATIC)) /* "proxy-authenticate": "" */ #define GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[59], GRPC_MDELEM_STORAGE_STATIC)) /* "proxy-authorization": "" */ #define GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[60], GRPC_MDELEM_STORAGE_STATIC)) /* "range": "" */ #define GRPC_MDELEM_RANGE_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[61], GRPC_MDELEM_STORAGE_STATIC)) /* "referer": "" */ #define GRPC_MDELEM_REFERER_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[62], GRPC_MDELEM_STORAGE_STATIC)) /* "refresh": "" */ #define GRPC_MDELEM_REFRESH_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[63], GRPC_MDELEM_STORAGE_STATIC)) /* "retry-after": "" */ #define GRPC_MDELEM_RETRY_AFTER_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[64], GRPC_MDELEM_STORAGE_STATIC)) /* "server": "" */ #define GRPC_MDELEM_SERVER_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[65], GRPC_MDELEM_STORAGE_STATIC)) /* "set-cookie": "" */ #define GRPC_MDELEM_SET_COOKIE_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[66], GRPC_MDELEM_STORAGE_STATIC)) /* "strict-transport-security": "" */ #define GRPC_MDELEM_STRICT_TRANSPORT_SECURITY_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[67], GRPC_MDELEM_STORAGE_STATIC)) /* "transfer-encoding": "" */ #define GRPC_MDELEM_TRANSFER_ENCODING_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[68], GRPC_MDELEM_STORAGE_STATIC)) /* "user-agent": "" */ #define GRPC_MDELEM_USER_AGENT_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[69], GRPC_MDELEM_STORAGE_STATIC)) /* "vary": "" */ #define GRPC_MDELEM_VARY_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[70], GRPC_MDELEM_STORAGE_STATIC)) /* "via": "" */ #define GRPC_MDELEM_VIA_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[71], GRPC_MDELEM_STORAGE_STATIC)) /* "www-authenticate": "" */ #define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[72], GRPC_MDELEM_STORAGE_STATIC)) /* "grpc-accept-encoding": "identity" */ #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[73], GRPC_MDELEM_STORAGE_STATIC)) /* "grpc-accept-encoding": "deflate" */ #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[74], GRPC_MDELEM_STORAGE_STATIC)) /* "grpc-accept-encoding": "identity,deflate" */ #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[75], GRPC_MDELEM_STORAGE_STATIC)) /* "grpc-accept-encoding": "gzip" */ #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_GZIP \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[76], GRPC_MDELEM_STORAGE_STATIC)) /* "grpc-accept-encoding": "identity,gzip" */ #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[77], GRPC_MDELEM_STORAGE_STATIC)) /* "grpc-accept-encoding": "deflate,gzip" */ #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE_COMMA_GZIP \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[78], GRPC_MDELEM_STORAGE_STATIC)) /* "grpc-accept-encoding": "identity,deflate,gzip" */ #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[79], GRPC_MDELEM_STORAGE_STATIC)) grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b); typedef enum { GRPC_BATCH_PATH, GRPC_BATCH_METHOD, GRPC_BATCH_STATUS, GRPC_BATCH_AUTHORITY, GRPC_BATCH_SCHEME, GRPC_BATCH_TE, GRPC_BATCH_GRPC_MESSAGE, GRPC_BATCH_GRPC_STATUS, GRPC_BATCH_GRPC_PAYLOAD_BIN, GRPC_BATCH_GRPC_ENCODING, GRPC_BATCH_GRPC_ACCEPT_ENCODING, GRPC_BATCH_CONTENT_TYPE, GRPC_BATCH_GRPC_INTERNAL_ENCODING_REQUEST, GRPC_BATCH_USER_AGENT, GRPC_BATCH_HOST, GRPC_BATCH_LB_TOKEN, GRPC_BATCH_CALLOUTS_COUNT } grpc_metadata_batch_callouts_index; typedef union { struct grpc_linked_mdelem *array[GRPC_BATCH_CALLOUTS_COUNT]; struct { struct grpc_linked_mdelem *path; struct grpc_linked_mdelem *method; struct grpc_linked_mdelem *status; struct grpc_linked_mdelem *authority; struct grpc_linked_mdelem *scheme; struct grpc_linked_mdelem *te; struct grpc_linked_mdelem *grpc_message; struct grpc_linked_mdelem *grpc_status; struct grpc_linked_mdelem *grpc_payload_bin; struct grpc_linked_mdelem *grpc_encoding; struct grpc_linked_mdelem *grpc_accept_encoding; struct grpc_linked_mdelem *content_type; struct grpc_linked_mdelem *grpc_internal_encoding_request; struct grpc_linked_mdelem *user_agent; struct grpc_linked_mdelem *host; struct grpc_linked_mdelem *lb_token; } named; } grpc_metadata_batch_callouts; #define GRPC_BATCH_INDEX_OF(slice) \ (GRPC_IS_STATIC_METADATA_STRING((slice)) \ ? (grpc_metadata_batch_callouts_index)GPR_CLAMP( \ GRPC_STATIC_METADATA_INDEX((slice)), 0, \ GRPC_BATCH_CALLOUTS_COUNT) \ : GRPC_BATCH_CALLOUTS_COUNT) extern const uint8_t grpc_static_accept_encoding_metadata[8]; #define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) \ (GRPC_MAKE_MDELEM( \ &grpc_static_mdelem_table[grpc_static_accept_encoding_metadata[(algs)]], \ GRPC_MDELEM_STORAGE_STATIC)) #endif /* GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H */ grpc-1.3.2/src/core/lib/transport/status_conversion.c000066400000000000000000000077571310511640000227340ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/transport/status_conversion.h" int grpc_status_to_http2_error(grpc_status_code status) { switch (status) { case GRPC_STATUS_OK: return GRPC_HTTP2_NO_ERROR; case GRPC_STATUS_CANCELLED: return GRPC_HTTP2_CANCEL; case GRPC_STATUS_DEADLINE_EXCEEDED: return GRPC_HTTP2_CANCEL; case GRPC_STATUS_RESOURCE_EXHAUSTED: return GRPC_HTTP2_ENHANCE_YOUR_CALM; case GRPC_STATUS_PERMISSION_DENIED: return GRPC_HTTP2_INADEQUATE_SECURITY; case GRPC_STATUS_UNAVAILABLE: return GRPC_HTTP2_REFUSED_STREAM; default: return GRPC_HTTP2_INTERNAL_ERROR; } } grpc_status_code grpc_http2_error_to_grpc_status(grpc_http2_error_code error, gpr_timespec deadline) { switch (error) { case GRPC_HTTP2_NO_ERROR: /* should never be received */ return GRPC_STATUS_INTERNAL; case GRPC_HTTP2_CANCEL: /* http2 cancel translates to STATUS_CANCELLED iff deadline hasn't been * exceeded */ return gpr_time_cmp(gpr_now(deadline.clock_type), deadline) >= 0 ? GRPC_STATUS_DEADLINE_EXCEEDED : GRPC_STATUS_CANCELLED; case GRPC_HTTP2_ENHANCE_YOUR_CALM: return GRPC_STATUS_RESOURCE_EXHAUSTED; case GRPC_HTTP2_INADEQUATE_SECURITY: return GRPC_STATUS_PERMISSION_DENIED; case GRPC_HTTP2_REFUSED_STREAM: return GRPC_STATUS_UNAVAILABLE; default: return GRPC_STATUS_INTERNAL; } } grpc_status_code grpc_http2_status_to_grpc_status(int status) { switch (status) { /* these HTTP2 status codes are called out explicitly in status.proto */ case 200: return GRPC_STATUS_OK; case 400: return GRPC_STATUS_INVALID_ARGUMENT; case 401: return GRPC_STATUS_UNAUTHENTICATED; case 403: return GRPC_STATUS_PERMISSION_DENIED; case 404: return GRPC_STATUS_NOT_FOUND; case 409: return GRPC_STATUS_ABORTED; case 412: return GRPC_STATUS_FAILED_PRECONDITION; case 429: return GRPC_STATUS_RESOURCE_EXHAUSTED; case 499: return GRPC_STATUS_CANCELLED; case 500: return GRPC_STATUS_UNKNOWN; case 501: return GRPC_STATUS_UNIMPLEMENTED; case 503: return GRPC_STATUS_UNAVAILABLE; case 504: return GRPC_STATUS_DEADLINE_EXCEEDED; /* everything else is unknown */ default: return GRPC_STATUS_UNKNOWN; } } int grpc_status_to_http2_status(grpc_status_code status) { return 200; } grpc-1.3.2/src/core/lib/transport/status_conversion.h000066400000000000000000000043731310511640000227300ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_TRANSPORT_STATUS_CONVERSION_H #define GRPC_CORE_LIB_TRANSPORT_STATUS_CONVERSION_H #include #include "src/core/lib/transport/http2_errors.h" /* Conversion of grpc status codes to http2 error codes (for RST_STREAM) */ grpc_http2_error_code grpc_status_to_http2_error(grpc_status_code status); grpc_status_code grpc_http2_error_to_grpc_status(grpc_http2_error_code error, gpr_timespec deadline); /* Conversion of HTTP status codes (:status) to grpc status codes */ grpc_status_code grpc_http2_status_to_grpc_status(int status); int grpc_status_to_http2_status(grpc_status_code status); #endif /* GRPC_CORE_LIB_TRANSPORT_STATUS_CONVERSION_H */ grpc-1.3.2/src/core/lib/transport/timeout_encoding.c000066400000000000000000000135641310511640000224710ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/transport/timeout_encoding.h" #include #include #include #include "src/core/lib/support/string.h" static int64_t round_up(int64_t x, int64_t divisor) { return (x / divisor + (x % divisor != 0)) * divisor; } /* round an integer up to the next value with three significant figures */ static int64_t round_up_to_three_sig_figs(int64_t x) { if (x < 1000) return x; if (x < 10000) return round_up(x, 10); if (x < 100000) return round_up(x, 100); if (x < 1000000) return round_up(x, 1000); if (x < 10000000) return round_up(x, 10000); if (x < 100000000) return round_up(x, 100000); if (x < 1000000000) return round_up(x, 1000000); return round_up(x, 10000000); } /* encode our minimum viable timeout value */ static void enc_tiny(char *buffer) { memcpy(buffer, "1n", 3); } static void enc_ext(char *buffer, int64_t value, char ext) { int n = int64_ttoa(value, buffer); buffer[n] = ext; buffer[n + 1] = 0; } static void enc_seconds(char *buffer, int64_t sec) { if (sec % 3600 == 0) { enc_ext(buffer, sec / 3600, 'H'); } else if (sec % 60 == 0) { enc_ext(buffer, sec / 60, 'M'); } else { enc_ext(buffer, sec, 'S'); } } static void enc_nanos(char *buffer, int64_t x) { x = round_up_to_three_sig_figs(x); if (x < 100000) { if (x % 1000 == 0) { enc_ext(buffer, x / 1000, 'u'); } else { enc_ext(buffer, x, 'n'); } } else if (x < 100000000) { if (x % 1000000 == 0) { enc_ext(buffer, x / 1000000, 'm'); } else { enc_ext(buffer, x / 1000, 'u'); } } else if (x < 1000000000) { enc_ext(buffer, x / 1000000, 'm'); } else { /* note that this is only ever called with times of less than one second, so if we reach here the time must have been rounded up to a whole second (and no more) */ memcpy(buffer, "1S", 3); } } static void enc_micros(char *buffer, int64_t x) { x = round_up_to_three_sig_figs(x); if (x < 100000) { if (x % 1000 == 0) { enc_ext(buffer, x / 1000, 'm'); } else { enc_ext(buffer, x, 'u'); } } else if (x < 100000000) { if (x % 1000000 == 0) { enc_ext(buffer, x / 1000000, 'S'); } else { enc_ext(buffer, x / 1000, 'm'); } } else { enc_ext(buffer, x / 1000000, 'S'); } } void grpc_http2_encode_timeout(gpr_timespec timeout, char *buffer) { if (timeout.tv_sec < 0) { enc_tiny(buffer); } else if (timeout.tv_sec == 0) { enc_nanos(buffer, timeout.tv_nsec); } else if (timeout.tv_sec < 1000 && timeout.tv_nsec != 0) { enc_micros(buffer, (int64_t)(timeout.tv_sec * 1000000) + (timeout.tv_nsec / 1000 + (timeout.tv_nsec % 1000 != 0))); } else { enc_seconds(buffer, timeout.tv_sec + (timeout.tv_nsec != 0)); } } static int is_all_whitespace(const char *p, const char *end) { while (p != end && *p == ' ') p++; return p == end; } int grpc_http2_decode_timeout(grpc_slice text, gpr_timespec *timeout) { int32_t x = 0; const uint8_t *p = GRPC_SLICE_START_PTR(text); const uint8_t *end = GRPC_SLICE_END_PTR(text); int have_digit = 0; /* skip whitespace */ for (; p != end && *p == ' '; p++) ; /* decode numeric part */ for (; p != end && *p >= '0' && *p <= '9'; p++) { int32_t digit = (int32_t)(*p - (uint8_t)'0'); have_digit = 1; /* spec allows max. 8 digits, but we allow values up to 1,000,000,000 */ if (x >= (100 * 1000 * 1000)) { if (x != (100 * 1000 * 1000) || digit != 0) { *timeout = gpr_inf_future(GPR_TIMESPAN); return 1; } } x = x * 10 + digit; } if (!have_digit) return 0; /* skip whitespace */ for (; p != end && *p == ' '; p++) ; if (p == end) return 0; /* decode unit specifier */ switch (*p) { case 'n': *timeout = gpr_time_from_nanos(x, GPR_TIMESPAN); break; case 'u': *timeout = gpr_time_from_micros(x, GPR_TIMESPAN); break; case 'm': *timeout = gpr_time_from_millis(x, GPR_TIMESPAN); break; case 'S': *timeout = gpr_time_from_seconds(x, GPR_TIMESPAN); break; case 'M': *timeout = gpr_time_from_minutes(x, GPR_TIMESPAN); break; case 'H': *timeout = gpr_time_from_hours(x, GPR_TIMESPAN); break; default: return 0; } p++; return is_all_whitespace((const char *)p, (const char *)end); } grpc-1.3.2/src/core/lib/transport/timeout_encoding.h000066400000000000000000000041331310511640000224660ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_TRANSPORT_TIMEOUT_ENCODING_H #define GRPC_CORE_LIB_TRANSPORT_TIMEOUT_ENCODING_H #include #include #include "src/core/lib/support/string.h" #define GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE (GPR_LTOA_MIN_BUFSIZE + 1) /* Encode/decode timeouts to the GRPC over HTTP/2 format; encoding may round up arbitrarily */ void grpc_http2_encode_timeout(gpr_timespec timeout, char *buffer); int grpc_http2_decode_timeout(grpc_slice text, gpr_timespec *timeout); #endif /* GRPC_CORE_LIB_TRANSPORT_TIMEOUT_ENCODING_H */ grpc-1.3.2/src/core/lib/transport/transport.c000066400000000000000000000255251310511640000211710ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/transport/transport.h" #include #include #include #include #include #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/string.h" #include "src/core/lib/transport/transport_impl.h" #ifdef GRPC_STREAM_REFCOUNT_DEBUG void grpc_stream_ref(grpc_stream_refcount *refcount, const char *reason) { gpr_atm val = gpr_atm_no_barrier_load(&refcount->refs.count); gpr_log(GPR_DEBUG, "%s %p:%p REF %" PRIdPTR "->%" PRIdPTR " %s", refcount->object_type, refcount, refcount->destroy.cb_arg, val, val + 1, reason); #else void grpc_stream_ref(grpc_stream_refcount *refcount) { #endif gpr_ref_non_zero(&refcount->refs); } #ifdef GRPC_STREAM_REFCOUNT_DEBUG void grpc_stream_unref(grpc_exec_ctx *exec_ctx, grpc_stream_refcount *refcount, const char *reason) { gpr_atm val = gpr_atm_no_barrier_load(&refcount->refs.count); gpr_log(GPR_DEBUG, "%s %p:%p UNREF %" PRIdPTR "->%" PRIdPTR " %s", refcount->object_type, refcount, refcount->destroy.cb_arg, val, val - 1, reason); #else void grpc_stream_unref(grpc_exec_ctx *exec_ctx, grpc_stream_refcount *refcount) { #endif if (gpr_unref(&refcount->refs)) { if (exec_ctx->flags & GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP) { /* Ick. The thread we're running on MAY be owned (indirectly) by a call-stack. If that's the case, destroying the call-stack MAY try to destroy the thread, which is a tangled mess that we just don't want to ever have to cope with. Throw this over to the executor (on a core-owned thread) and process it there. */ refcount->destroy.scheduler = grpc_executor_scheduler; } grpc_closure_sched(exec_ctx, &refcount->destroy, GRPC_ERROR_NONE); } } #define STREAM_REF_FROM_SLICE_REF(p) \ ((grpc_stream_refcount *)(((uint8_t *)p) - \ offsetof(grpc_stream_refcount, slice_refcount))) static void slice_stream_ref(void *p) { #ifdef GRPC_STREAM_REFCOUNT_DEBUG grpc_stream_ref(STREAM_REF_FROM_SLICE_REF(p), "slice"); #else grpc_stream_ref(STREAM_REF_FROM_SLICE_REF(p)); #endif } static void slice_stream_unref(grpc_exec_ctx *exec_ctx, void *p) { #ifdef GRPC_STREAM_REFCOUNT_DEBUG grpc_stream_unref(exec_ctx, STREAM_REF_FROM_SLICE_REF(p), "slice"); #else grpc_stream_unref(exec_ctx, STREAM_REF_FROM_SLICE_REF(p)); #endif } grpc_slice grpc_slice_from_stream_owned_buffer(grpc_stream_refcount *refcount, void *buffer, size_t length) { slice_stream_ref(&refcount->slice_refcount); return (grpc_slice){.refcount = &refcount->slice_refcount, .data.refcounted = {.bytes = buffer, .length = length}}; } static const grpc_slice_refcount_vtable stream_ref_slice_vtable = { .ref = slice_stream_ref, .unref = slice_stream_unref, .eq = grpc_slice_default_eq_impl, .hash = grpc_slice_default_hash_impl}; #ifdef GRPC_STREAM_REFCOUNT_DEBUG void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs, grpc_iomgr_cb_func cb, void *cb_arg, const char *object_type) { refcount->object_type = object_type; #else void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs, grpc_iomgr_cb_func cb, void *cb_arg) { #endif gpr_ref_init(&refcount->refs, initial_refs); grpc_closure_init(&refcount->destroy, cb, cb_arg, grpc_schedule_on_exec_ctx); refcount->slice_refcount.vtable = &stream_ref_slice_vtable; refcount->slice_refcount.sub_refcount = &refcount->slice_refcount; } static void move64(uint64_t *from, uint64_t *to) { *to += *from; *from = 0; } void grpc_transport_move_one_way_stats(grpc_transport_one_way_stats *from, grpc_transport_one_way_stats *to) { move64(&from->framing_bytes, &to->framing_bytes); move64(&from->data_bytes, &to->data_bytes); move64(&from->header_bytes, &to->header_bytes); } void grpc_transport_move_stats(grpc_transport_stream_stats *from, grpc_transport_stream_stats *to) { grpc_transport_move_one_way_stats(&from->incoming, &to->incoming); grpc_transport_move_one_way_stats(&from->outgoing, &to->outgoing); } size_t grpc_transport_stream_size(grpc_transport *transport) { return transport->vtable->sizeof_stream; } void grpc_transport_destroy(grpc_exec_ctx *exec_ctx, grpc_transport *transport) { transport->vtable->destroy(exec_ctx, transport); } int grpc_transport_init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *transport, grpc_stream *stream, grpc_stream_refcount *refcount, const void *server_data, gpr_arena *arena) { return transport->vtable->init_stream(exec_ctx, transport, stream, refcount, server_data, arena); } void grpc_transport_perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *transport, grpc_stream *stream, grpc_transport_stream_op_batch *op) { transport->vtable->perform_stream_op(exec_ctx, transport, stream, op); } void grpc_transport_perform_op(grpc_exec_ctx *exec_ctx, grpc_transport *transport, grpc_transport_op *op) { transport->vtable->perform_op(exec_ctx, transport, op); } void grpc_transport_set_pops(grpc_exec_ctx *exec_ctx, grpc_transport *transport, grpc_stream *stream, grpc_polling_entity *pollent) { grpc_pollset *pollset; grpc_pollset_set *pollset_set; if ((pollset = grpc_polling_entity_pollset(pollent)) != NULL) { transport->vtable->set_pollset(exec_ctx, transport, stream, pollset); } else if ((pollset_set = grpc_polling_entity_pollset_set(pollent)) != NULL) { transport->vtable->set_pollset_set(exec_ctx, transport, stream, pollset_set); } else { abort(); } } void grpc_transport_destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *transport, grpc_stream *stream, grpc_closure *then_schedule_closure) { transport->vtable->destroy_stream(exec_ctx, transport, stream, then_schedule_closure); } char *grpc_transport_get_peer(grpc_exec_ctx *exec_ctx, grpc_transport *transport) { return transport->vtable->get_peer(exec_ctx, transport); } grpc_endpoint *grpc_transport_get_endpoint(grpc_exec_ctx *exec_ctx, grpc_transport *transport) { return transport->vtable->get_endpoint(exec_ctx, transport); } void grpc_transport_stream_op_batch_finish_with_failure( grpc_exec_ctx *exec_ctx, grpc_transport_stream_op_batch *op, grpc_error *error) { if (op->recv_message) { grpc_closure_sched(exec_ctx, op->payload->recv_message.recv_message_ready, GRPC_ERROR_REF(error)); } if (op->recv_initial_metadata) { grpc_closure_sched( exec_ctx, op->payload->recv_initial_metadata.recv_initial_metadata_ready, GRPC_ERROR_REF(error)); } grpc_closure_sched(exec_ctx, op->on_complete, error); if (op->cancel_stream) { GRPC_ERROR_UNREF(op->payload->cancel_stream.cancel_error); } } typedef struct { grpc_closure outer_on_complete; grpc_closure *inner_on_complete; grpc_transport_op op; } made_transport_op; static void destroy_made_transport_op(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { made_transport_op *op = arg; grpc_closure_sched(exec_ctx, op->inner_on_complete, GRPC_ERROR_REF(error)); gpr_free(op); } grpc_transport_op *grpc_make_transport_op(grpc_closure *on_complete) { made_transport_op *op = gpr_malloc(sizeof(*op)); grpc_closure_init(&op->outer_on_complete, destroy_made_transport_op, op, grpc_schedule_on_exec_ctx); op->inner_on_complete = on_complete; memset(&op->op, 0, sizeof(op->op)); op->op.on_consumed = &op->outer_on_complete; return &op->op; } typedef struct { grpc_closure outer_on_complete; grpc_closure *inner_on_complete; grpc_transport_stream_op_batch op; grpc_transport_stream_op_batch_payload payload; } made_transport_stream_op; static void destroy_made_transport_stream_op(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { made_transport_stream_op *op = arg; grpc_closure *c = op->inner_on_complete; gpr_free(op); grpc_closure_run(exec_ctx, c, GRPC_ERROR_REF(error)); } grpc_transport_stream_op_batch *grpc_make_transport_stream_op( grpc_closure *on_complete) { made_transport_stream_op *op = gpr_zalloc(sizeof(*op)); op->op.payload = &op->payload; grpc_closure_init(&op->outer_on_complete, destroy_made_transport_stream_op, op, grpc_schedule_on_exec_ctx); op->inner_on_complete = on_complete; op->op.on_complete = &op->outer_on_complete; return &op->op; } grpc-1.3.2/src/core/lib/transport/transport.h000066400000000000000000000331411310511640000211670ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_TRANSPORT_TRANSPORT_H #define GRPC_CORE_LIB_TRANSPORT_TRANSPORT_H #include #include "src/core/lib/channel/context.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/pollset_set.h" #include "src/core/lib/support/arena.h" #include "src/core/lib/transport/byte_stream.h" #include "src/core/lib/transport/metadata_batch.h" #ifdef __cplusplus extern "C" { #endif /* forward declarations */ typedef struct grpc_transport grpc_transport; /* grpc_stream doesn't actually exist. It's used as a typesafe opaque pointer for whatever data the transport wants to track for a stream. */ typedef struct grpc_stream grpc_stream; //#define GRPC_STREAM_REFCOUNT_DEBUG typedef struct grpc_stream_refcount { gpr_refcount refs; grpc_closure destroy; #ifdef GRPC_STREAM_REFCOUNT_DEBUG const char *object_type; #endif grpc_slice_refcount slice_refcount; } grpc_stream_refcount; #ifdef GRPC_STREAM_REFCOUNT_DEBUG void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs, grpc_iomgr_cb_func cb, void *cb_arg, const char *object_type); void grpc_stream_ref(grpc_stream_refcount *refcount, const char *reason); void grpc_stream_unref(grpc_exec_ctx *exec_ctx, grpc_stream_refcount *refcount, const char *reason); #define GRPC_STREAM_REF_INIT(rc, ir, cb, cb_arg, objtype) \ grpc_stream_ref_init(rc, ir, cb, cb_arg, objtype) #else void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs, grpc_iomgr_cb_func cb, void *cb_arg); void grpc_stream_ref(grpc_stream_refcount *refcount); void grpc_stream_unref(grpc_exec_ctx *exec_ctx, grpc_stream_refcount *refcount); #define GRPC_STREAM_REF_INIT(rc, ir, cb, cb_arg, objtype) \ grpc_stream_ref_init(rc, ir, cb, cb_arg) #endif /* Wrap a buffer that is owned by some stream object into a slice that shares the same refcount */ grpc_slice grpc_slice_from_stream_owned_buffer(grpc_stream_refcount *refcount, void *buffer, size_t length); typedef struct { uint64_t framing_bytes; uint64_t data_bytes; uint64_t header_bytes; } grpc_transport_one_way_stats; typedef struct grpc_transport_stream_stats { grpc_transport_one_way_stats incoming; grpc_transport_one_way_stats outgoing; } grpc_transport_stream_stats; void grpc_transport_move_one_way_stats(grpc_transport_one_way_stats *from, grpc_transport_one_way_stats *to); void grpc_transport_move_stats(grpc_transport_stream_stats *from, grpc_transport_stream_stats *to); typedef struct { void *extra_arg; grpc_closure closure; } grpc_handler_private_op_data; typedef struct grpc_transport_stream_op_batch_payload grpc_transport_stream_op_batch_payload; /* Transport stream op: a set of operations to perform on a transport against a single stream */ typedef struct grpc_transport_stream_op_batch { /** Should be enqueued when all requested operations (excluding recv_message and recv_initial_metadata which have their own closures) in a given batch have been completed. */ grpc_closure *on_complete; /** Values for the stream op (fields set are determined by flags above) */ grpc_transport_stream_op_batch_payload *payload; /** Is the completion of this op covered by a poller (if false: the op should complete independently of some pollset being polled) */ bool covered_by_poller : 1; /** Send initial metadata to the peer, from the provided metadata batch. */ bool send_initial_metadata : 1; /** Send trailing metadata to the peer, from the provided metadata batch. */ bool send_trailing_metadata : 1; /** Send message data to the peer, from the provided byte stream. */ bool send_message : 1; /** Receive initial metadata from the stream, into provided metadata batch. */ bool recv_initial_metadata : 1; /** Receive message data from the stream, into provided byte stream. */ bool recv_message : 1; /** Receive trailing metadata from the stream, into provided metadata batch. */ bool recv_trailing_metadata : 1; /** Collect any stats into provided buffer, zero internal stat counters */ bool collect_stats : 1; /** Cancel this stream with the provided error */ bool cancel_stream : 1; /*************************************************************************** * remaining fields are initialized and used at the discretion of the * current handler of the op */ grpc_handler_private_op_data handler_private; } grpc_transport_stream_op_batch; struct grpc_transport_stream_op_batch_payload { struct { grpc_metadata_batch *send_initial_metadata; /** Iff send_initial_metadata != NULL, flags associated with send_initial_metadata: a bitfield of GRPC_INITIAL_METADATA_xxx */ uint32_t send_initial_metadata_flags; } send_initial_metadata; struct { grpc_metadata_batch *send_trailing_metadata; } send_trailing_metadata; struct { grpc_byte_stream *send_message; } send_message; struct { grpc_metadata_batch *recv_initial_metadata; uint32_t *recv_flags; /** Should be enqueued when initial metadata is ready to be processed. */ grpc_closure *recv_initial_metadata_ready; } recv_initial_metadata; struct { grpc_byte_stream **recv_message; /** Should be enqueued when one message is ready to be processed. */ grpc_closure *recv_message_ready; } recv_message; struct { grpc_metadata_batch *recv_trailing_metadata; } recv_trailing_metadata; struct { grpc_transport_stream_stats *collect_stats; } collect_stats; /** Forcefully close this stream. The HTTP2 semantics should be: - server side: if cancel_error has GRPC_ERROR_INT_GRPC_STATUS, and trailing metadata has not been sent, send trailing metadata with status and message from cancel_error (use grpc_error_get_status) followed by a RST_STREAM with error=GRPC_CHTTP2_NO_ERROR to force a full close - at all other times: use grpc_error_get_status to get a status code, and convert to a HTTP2 error code using grpc_chttp2_grpc_status_to_http2_error. Send a RST_STREAM with this error. */ struct { grpc_error *cancel_error; } cancel_stream; /* Indexes correspond to grpc_context_index enum values */ grpc_call_context_element *context; }; /** Transport op: a set of operations to perform on a transport as a whole */ typedef struct grpc_transport_op { /** Called when processing of this op is done. */ grpc_closure *on_consumed; /** connectivity monitoring - set connectivity_state to NULL to unsubscribe */ grpc_closure *on_connectivity_state_change; grpc_connectivity_state *connectivity_state; /** should the transport be disconnected */ grpc_error *disconnect_with_error; /** what should the goaway contain? */ grpc_error *goaway_error; /** set the callback for accepting new streams; this is a permanent callback, unlike the other one-shot closures. If true, the callback is set to set_accept_stream_fn, with its user_data argument set to set_accept_stream_user_data */ bool set_accept_stream; void (*set_accept_stream_fn)(grpc_exec_ctx *exec_ctx, void *user_data, grpc_transport *transport, const void *server_data); void *set_accept_stream_user_data; /** add this transport to a pollset */ grpc_pollset *bind_pollset; /** add this transport to a pollset_set */ grpc_pollset_set *bind_pollset_set; /** send a ping, call this back if not NULL */ grpc_closure *send_ping; /*************************************************************************** * remaining fields are initialized and used at the discretion of the * transport implementation */ grpc_handler_private_op_data handler_private; } grpc_transport_op; /* Returns the amount of memory required to store a grpc_stream for this transport */ size_t grpc_transport_stream_size(grpc_transport *transport); /* Initialize transport data for a stream. Returns 0 on success, any other (transport-defined) value for failure. May assume that stream contains all-zeros. Arguments: transport - the transport on which to create this stream stream - a pointer to uninitialized memory to initialize server_data - either NULL for a client initiated stream, or a pointer supplied from the accept_stream callback function */ int grpc_transport_init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *transport, grpc_stream *stream, grpc_stream_refcount *refcount, const void *server_data, gpr_arena *arena); void grpc_transport_set_pops(grpc_exec_ctx *exec_ctx, grpc_transport *transport, grpc_stream *stream, grpc_polling_entity *pollent); /* Destroy transport data for a stream. Requires: a recv_batch with final_state == GRPC_STREAM_CLOSED has been received by the up-layer. Must not be called in the same call stack as recv_frame. Arguments: transport - the transport on which to create this stream stream - the grpc_stream to destroy (memory is still owned by the caller, but any child memory must be cleaned up) */ void grpc_transport_destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *transport, grpc_stream *stream, grpc_closure *then_schedule_closure); void grpc_transport_stream_op_batch_finish_with_failure( grpc_exec_ctx *exec_ctx, grpc_transport_stream_op_batch *op, grpc_error *error); char *grpc_transport_stream_op_batch_string(grpc_transport_stream_op_batch *op); char *grpc_transport_op_string(grpc_transport_op *op); /* Send a batch of operations on a transport Takes ownership of any objects contained in ops. Arguments: transport - the transport on which to initiate the stream stream - the stream on which to send the operations. This must be non-NULL and previously initialized by the same transport. op - a grpc_transport_stream_op_batch specifying the op to perform */ void grpc_transport_perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *transport, grpc_stream *stream, grpc_transport_stream_op_batch *op); void grpc_transport_perform_op(grpc_exec_ctx *exec_ctx, grpc_transport *transport, grpc_transport_op *op); /* Send a ping on a transport Calls cb with user data when a response is received. */ void grpc_transport_ping(grpc_transport *transport, grpc_closure *cb); /* Advise peer of pending connection termination. */ void grpc_transport_goaway(grpc_transport *transport, grpc_status_code status, grpc_slice debug_data); /* Close a transport. Aborts all open streams. */ void grpc_transport_close(grpc_transport *transport); /* Destroy the transport */ void grpc_transport_destroy(grpc_exec_ctx *exec_ctx, grpc_transport *transport); /* Get the transports peer */ char *grpc_transport_get_peer(grpc_exec_ctx *exec_ctx, grpc_transport *transport); /* Get the endpoint used by \a transport */ grpc_endpoint *grpc_transport_get_endpoint(grpc_exec_ctx *exec_ctx, grpc_transport *transport); /* Allocate a grpc_transport_op, and preconfigure the on_consumed closure to \a on_consumed and then delete the returned transport op */ grpc_transport_op *grpc_make_transport_op(grpc_closure *on_consumed); /* Allocate a grpc_transport_stream_op_batch, and preconfigure the on_consumed closure to \a on_consumed and then delete the returned transport op */ grpc_transport_stream_op_batch *grpc_make_transport_stream_op( grpc_closure *on_consumed); #ifdef __cplusplus } #endif #endif /* GRPC_CORE_LIB_TRANSPORT_TRANSPORT_H */ grpc-1.3.2/src/core/lib/transport/transport_impl.h000066400000000000000000000075411310511640000222150ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_LIB_TRANSPORT_TRANSPORT_IMPL_H #define GRPC_CORE_LIB_TRANSPORT_TRANSPORT_IMPL_H #include "src/core/lib/transport/transport.h" typedef struct grpc_transport_vtable { /* Memory required for a single stream element - this is allocated by upper layers and initialized by the transport */ size_t sizeof_stream; /* = sizeof(transport stream) */ /* name of this transport implementation */ const char *name; /* implementation of grpc_transport_init_stream */ int (*init_stream)(grpc_exec_ctx *exec_ctx, grpc_transport *self, grpc_stream *stream, grpc_stream_refcount *refcount, const void *server_data, gpr_arena *arena); /* implementation of grpc_transport_set_pollset */ void (*set_pollset)(grpc_exec_ctx *exec_ctx, grpc_transport *self, grpc_stream *stream, grpc_pollset *pollset); /* implementation of grpc_transport_set_pollset */ void (*set_pollset_set)(grpc_exec_ctx *exec_ctx, grpc_transport *self, grpc_stream *stream, grpc_pollset_set *pollset_set); /* implementation of grpc_transport_perform_stream_op */ void (*perform_stream_op)(grpc_exec_ctx *exec_ctx, grpc_transport *self, grpc_stream *stream, grpc_transport_stream_op_batch *op); /* implementation of grpc_transport_perform_op */ void (*perform_op)(grpc_exec_ctx *exec_ctx, grpc_transport *self, grpc_transport_op *op); /* implementation of grpc_transport_destroy_stream */ void (*destroy_stream)(grpc_exec_ctx *exec_ctx, grpc_transport *self, grpc_stream *stream, grpc_closure *then_schedule_closure); /* implementation of grpc_transport_destroy */ void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_transport *self); /* implementation of grpc_transport_get_peer */ char *(*get_peer)(grpc_exec_ctx *exec_ctx, grpc_transport *self); /* implementation of grpc_transport_get_endpoint */ grpc_endpoint *(*get_endpoint)(grpc_exec_ctx *exec_ctx, grpc_transport *self); } grpc_transport_vtable; /* an instance of a grpc transport */ struct grpc_transport { /* pointer to a vtable defining operations on this transport */ const grpc_transport_vtable *vtable; }; #endif /* GRPC_CORE_LIB_TRANSPORT_TRANSPORT_IMPL_H */ grpc-1.3.2/src/core/lib/transport/transport_op_string.c000066400000000000000000000157211310511640000232520ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/channel/channel_stack.h" #include #include #include #include #include #include #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/string.h" #include "src/core/lib/transport/connectivity_state.h" /* These routines are here to facilitate debugging - they produce string representations of various transport data structures */ static void put_metadata(gpr_strvec *b, grpc_mdelem md) { gpr_strvec_add(b, gpr_strdup("key=")); gpr_strvec_add( b, grpc_dump_slice(GRPC_MDKEY(md), GPR_DUMP_HEX | GPR_DUMP_ASCII)); gpr_strvec_add(b, gpr_strdup(" value=")); gpr_strvec_add( b, grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII)); } static void put_metadata_list(gpr_strvec *b, grpc_metadata_batch md) { grpc_linked_mdelem *m; for (m = md.list.head; m != NULL; m = m->next) { if (m != md.list.head) gpr_strvec_add(b, gpr_strdup(", ")); put_metadata(b, m->md); } if (gpr_time_cmp(md.deadline, gpr_inf_future(md.deadline.clock_type)) != 0) { char *tmp; gpr_asprintf(&tmp, " deadline=%" PRId64 ".%09d", md.deadline.tv_sec, md.deadline.tv_nsec); gpr_strvec_add(b, tmp); } } char *grpc_transport_stream_op_batch_string( grpc_transport_stream_op_batch *op) { char *tmp; char *out; gpr_strvec b; gpr_strvec_init(&b); gpr_strvec_add( &b, gpr_strdup(op->covered_by_poller ? "[COVERED]" : "[UNCOVERED]")); if (op->send_initial_metadata) { gpr_strvec_add(&b, gpr_strdup(" ")); gpr_strvec_add(&b, gpr_strdup("SEND_INITIAL_METADATA{")); put_metadata_list( &b, *op->payload->send_initial_metadata.send_initial_metadata); gpr_strvec_add(&b, gpr_strdup("}")); } if (op->send_message) { gpr_strvec_add(&b, gpr_strdup(" ")); gpr_asprintf(&tmp, "SEND_MESSAGE:flags=0x%08x:len=%d", op->payload->send_message.send_message->flags, op->payload->send_message.send_message->length); gpr_strvec_add(&b, tmp); } if (op->send_trailing_metadata) { gpr_strvec_add(&b, gpr_strdup(" ")); gpr_strvec_add(&b, gpr_strdup("SEND_TRAILING_METADATA{")); put_metadata_list( &b, *op->payload->send_trailing_metadata.send_trailing_metadata); gpr_strvec_add(&b, gpr_strdup("}")); } if (op->recv_initial_metadata) { gpr_strvec_add(&b, gpr_strdup(" ")); gpr_strvec_add(&b, gpr_strdup("RECV_INITIAL_METADATA")); } if (op->recv_message) { gpr_strvec_add(&b, gpr_strdup(" ")); gpr_strvec_add(&b, gpr_strdup("RECV_MESSAGE")); } if (op->recv_trailing_metadata) { gpr_strvec_add(&b, gpr_strdup(" ")); gpr_strvec_add(&b, gpr_strdup("RECV_TRAILING_METADATA")); } if (op->cancel_stream) { gpr_strvec_add(&b, gpr_strdup(" ")); const char *msg = grpc_error_string(op->payload->cancel_stream.cancel_error); gpr_asprintf(&tmp, "CANCEL:%s", msg); gpr_strvec_add(&b, tmp); } out = gpr_strvec_flatten(&b, NULL); gpr_strvec_destroy(&b); return out; } char *grpc_transport_op_string(grpc_transport_op *op) { char *tmp; char *out; bool first = true; gpr_strvec b; gpr_strvec_init(&b); if (op->on_connectivity_state_change != NULL) { if (!first) gpr_strvec_add(&b, gpr_strdup(" ")); first = false; if (op->connectivity_state != NULL) { gpr_asprintf(&tmp, "ON_CONNECTIVITY_STATE_CHANGE:p=%p:from=%s", op->on_connectivity_state_change, grpc_connectivity_state_name(*op->connectivity_state)); gpr_strvec_add(&b, tmp); } else { gpr_asprintf(&tmp, "ON_CONNECTIVITY_STATE_CHANGE:p=%p:unsubscribe", op->on_connectivity_state_change); gpr_strvec_add(&b, tmp); } } if (op->disconnect_with_error != GRPC_ERROR_NONE) { if (!first) gpr_strvec_add(&b, gpr_strdup(" ")); first = false; const char *err = grpc_error_string(op->disconnect_with_error); gpr_asprintf(&tmp, "DISCONNECT:%s", err); gpr_strvec_add(&b, tmp); } if (op->goaway_error) { if (!first) gpr_strvec_add(&b, gpr_strdup(" ")); first = false; const char *msg = grpc_error_string(op->goaway_error); gpr_asprintf(&tmp, "SEND_GOAWAY:%s", msg); gpr_strvec_add(&b, tmp); } if (op->set_accept_stream) { if (!first) gpr_strvec_add(&b, gpr_strdup(" ")); first = false; gpr_asprintf(&tmp, "SET_ACCEPT_STREAM:%p(%p,...)", op->set_accept_stream_fn, op->set_accept_stream_user_data); gpr_strvec_add(&b, tmp); } if (op->bind_pollset != NULL) { if (!first) gpr_strvec_add(&b, gpr_strdup(" ")); first = false; gpr_strvec_add(&b, gpr_strdup("BIND_POLLSET")); } if (op->bind_pollset_set != NULL) { if (!first) gpr_strvec_add(&b, gpr_strdup(" ")); first = false; gpr_strvec_add(&b, gpr_strdup("BIND_POLLSET_SET")); } if (op->send_ping != NULL) { if (!first) gpr_strvec_add(&b, gpr_strdup(" ")); first = false; gpr_strvec_add(&b, gpr_strdup("SEND_PING")); } out = gpr_strvec_flatten(&b, NULL); gpr_strvec_destroy(&b); return out; } void grpc_call_log_op(char *file, int line, gpr_log_severity severity, grpc_call_element *elem, grpc_transport_stream_op_batch *op) { char *str = grpc_transport_stream_op_batch_string(op); gpr_log(file, line, severity, "OP[%s:%p]: %s", elem->filter->name, elem, str); gpr_free(str); } grpc-1.3.2/src/core/plugin_registry/000077500000000000000000000000001310511640000174045ustar00rootroot00000000000000grpc-1.3.2/src/core/plugin_registry/grpc_cronet_plugin_registry.c000066400000000000000000000043121310511640000253630ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include extern void grpc_chttp2_plugin_init(void); extern void grpc_chttp2_plugin_shutdown(void); extern void grpc_client_channel_init(void); extern void grpc_client_channel_shutdown(void); extern void grpc_load_reporting_plugin_init(void); extern void grpc_load_reporting_plugin_shutdown(void); void grpc_register_built_in_plugins(void) { grpc_register_plugin(grpc_chttp2_plugin_init, grpc_chttp2_plugin_shutdown); grpc_register_plugin(grpc_client_channel_init, grpc_client_channel_shutdown); grpc_register_plugin(grpc_load_reporting_plugin_init, grpc_load_reporting_plugin_shutdown); } grpc-1.3.2/src/core/plugin_registry/grpc_plugin_registry.c000066400000000000000000000075061310511640000240210ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include extern void grpc_chttp2_plugin_init(void); extern void grpc_chttp2_plugin_shutdown(void); extern void grpc_client_channel_init(void); extern void grpc_client_channel_shutdown(void); extern void grpc_lb_policy_grpclb_init(void); extern void grpc_lb_policy_grpclb_shutdown(void); extern void grpc_lb_policy_pick_first_init(void); extern void grpc_lb_policy_pick_first_shutdown(void); extern void grpc_lb_policy_round_robin_init(void); extern void grpc_lb_policy_round_robin_shutdown(void); extern void grpc_resolver_dns_ares_init(void); extern void grpc_resolver_dns_ares_shutdown(void); extern void grpc_resolver_dns_native_init(void); extern void grpc_resolver_dns_native_shutdown(void); extern void grpc_resolver_sockaddr_init(void); extern void grpc_resolver_sockaddr_shutdown(void); extern void grpc_load_reporting_plugin_init(void); extern void grpc_load_reporting_plugin_shutdown(void); extern void census_grpc_plugin_init(void); extern void census_grpc_plugin_shutdown(void); extern void grpc_max_age_filter_init(void); extern void grpc_max_age_filter_shutdown(void); void grpc_register_built_in_plugins(void) { grpc_register_plugin(grpc_chttp2_plugin_init, grpc_chttp2_plugin_shutdown); grpc_register_plugin(grpc_client_channel_init, grpc_client_channel_shutdown); grpc_register_plugin(grpc_lb_policy_grpclb_init, grpc_lb_policy_grpclb_shutdown); grpc_register_plugin(grpc_lb_policy_pick_first_init, grpc_lb_policy_pick_first_shutdown); grpc_register_plugin(grpc_lb_policy_round_robin_init, grpc_lb_policy_round_robin_shutdown); grpc_register_plugin(grpc_resolver_dns_ares_init, grpc_resolver_dns_ares_shutdown); grpc_register_plugin(grpc_resolver_dns_native_init, grpc_resolver_dns_native_shutdown); grpc_register_plugin(grpc_resolver_sockaddr_init, grpc_resolver_sockaddr_shutdown); grpc_register_plugin(grpc_load_reporting_plugin_init, grpc_load_reporting_plugin_shutdown); grpc_register_plugin(census_grpc_plugin_init, census_grpc_plugin_shutdown); grpc_register_plugin(grpc_max_age_filter_init, grpc_max_age_filter_shutdown); } grpc-1.3.2/src/core/plugin_registry/grpc_unsecure_plugin_registry.c000066400000000000000000000075061310511640000257320ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include extern void grpc_chttp2_plugin_init(void); extern void grpc_chttp2_plugin_shutdown(void); extern void grpc_client_channel_init(void); extern void grpc_client_channel_shutdown(void); extern void grpc_resolver_dns_ares_init(void); extern void grpc_resolver_dns_ares_shutdown(void); extern void grpc_resolver_dns_native_init(void); extern void grpc_resolver_dns_native_shutdown(void); extern void grpc_resolver_sockaddr_init(void); extern void grpc_resolver_sockaddr_shutdown(void); extern void grpc_load_reporting_plugin_init(void); extern void grpc_load_reporting_plugin_shutdown(void); extern void grpc_lb_policy_grpclb_init(void); extern void grpc_lb_policy_grpclb_shutdown(void); extern void grpc_lb_policy_pick_first_init(void); extern void grpc_lb_policy_pick_first_shutdown(void); extern void grpc_lb_policy_round_robin_init(void); extern void grpc_lb_policy_round_robin_shutdown(void); extern void census_grpc_plugin_init(void); extern void census_grpc_plugin_shutdown(void); extern void grpc_max_age_filter_init(void); extern void grpc_max_age_filter_shutdown(void); void grpc_register_built_in_plugins(void) { grpc_register_plugin(grpc_chttp2_plugin_init, grpc_chttp2_plugin_shutdown); grpc_register_plugin(grpc_client_channel_init, grpc_client_channel_shutdown); grpc_register_plugin(grpc_resolver_dns_ares_init, grpc_resolver_dns_ares_shutdown); grpc_register_plugin(grpc_resolver_dns_native_init, grpc_resolver_dns_native_shutdown); grpc_register_plugin(grpc_resolver_sockaddr_init, grpc_resolver_sockaddr_shutdown); grpc_register_plugin(grpc_load_reporting_plugin_init, grpc_load_reporting_plugin_shutdown); grpc_register_plugin(grpc_lb_policy_grpclb_init, grpc_lb_policy_grpclb_shutdown); grpc_register_plugin(grpc_lb_policy_pick_first_init, grpc_lb_policy_pick_first_shutdown); grpc_register_plugin(grpc_lb_policy_round_robin_init, grpc_lb_policy_round_robin_shutdown); grpc_register_plugin(census_grpc_plugin_init, census_grpc_plugin_shutdown); grpc_register_plugin(grpc_max_age_filter_init, grpc_max_age_filter_shutdown); } grpc-1.3.2/src/core/tsi/000077500000000000000000000000001310511640000147555ustar00rootroot00000000000000grpc-1.3.2/src/core/tsi/README.md000066400000000000000000000001471310511640000162360ustar00rootroot00000000000000# Transport Security Interface An abstraction library over crypto and auth modules (typically OpenSSL) grpc-1.3.2/src/core/tsi/fake_transport_security.c000066400000000000000000000462351310511640000221040ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/tsi/fake_transport_security.h" #include #include #include #include #include #include #include "src/core/tsi/transport_security.h" /* --- Constants. ---*/ #define TSI_FAKE_FRAME_HEADER_SIZE 4 #define TSI_FAKE_FRAME_INITIAL_ALLOCATED_SIZE 64 #define TSI_FAKE_DEFAULT_FRAME_SIZE 16384 /* --- Structure definitions. ---*/ /* a frame is encoded like this: | size | data | where the size field value is the size of the size field plus the size of the data encoded in little endian on 4 bytes. */ typedef struct { unsigned char *data; size_t size; size_t allocated_size; size_t offset; int needs_draining; } tsi_fake_frame; typedef enum { TSI_FAKE_CLIENT_INIT = 0, TSI_FAKE_SERVER_INIT = 1, TSI_FAKE_CLIENT_FINISHED = 2, TSI_FAKE_SERVER_FINISHED = 3, TSI_FAKE_HANDSHAKE_MESSAGE_MAX = 4 } tsi_fake_handshake_message; typedef struct { tsi_handshaker base; int is_client; tsi_fake_handshake_message next_message_to_send; int needs_incoming_message; tsi_fake_frame incoming; tsi_fake_frame outgoing; tsi_result result; } tsi_fake_handshaker; typedef struct { tsi_frame_protector base; tsi_fake_frame protect_frame; tsi_fake_frame unprotect_frame; size_t max_frame_size; } tsi_fake_frame_protector; /* --- Utils. ---*/ static const char *tsi_fake_handshake_message_strings[] = { "CLIENT_INIT", "SERVER_INIT", "CLIENT_FINISHED", "SERVER_FINISHED"}; static const char *tsi_fake_handshake_message_to_string(int msg) { if (msg < 0 || msg >= TSI_FAKE_HANDSHAKE_MESSAGE_MAX) { gpr_log(GPR_ERROR, "Invalid message %d", msg); return "UNKNOWN"; } return tsi_fake_handshake_message_strings[msg]; } static tsi_result tsi_fake_handshake_message_from_string( const char *msg_string, tsi_fake_handshake_message *msg) { tsi_fake_handshake_message i; for (i = 0; i < TSI_FAKE_HANDSHAKE_MESSAGE_MAX; i++) { if (strncmp(msg_string, tsi_fake_handshake_message_strings[i], strlen(tsi_fake_handshake_message_strings[i])) == 0) { *msg = i; return TSI_OK; } } gpr_log(GPR_ERROR, "Invalid handshake message."); return TSI_DATA_CORRUPTED; } static uint32_t load32_little_endian(const unsigned char *buf) { return ((uint32_t)(buf[0]) | (uint32_t)(buf[1] << 8) | (uint32_t)(buf[2] << 16) | (uint32_t)(buf[3] << 24)); } static void store32_little_endian(uint32_t value, unsigned char *buf) { buf[3] = (unsigned char)((value >> 24) & 0xFF); buf[2] = (unsigned char)((value >> 16) & 0xFF); buf[1] = (unsigned char)((value >> 8) & 0xFF); buf[0] = (unsigned char)((value)&0xFF); } static void tsi_fake_frame_reset(tsi_fake_frame *frame, int needs_draining) { frame->offset = 0; frame->needs_draining = needs_draining; if (!needs_draining) frame->size = 0; } /* Returns 1 if successful, 0 otherwise. */ static int tsi_fake_frame_ensure_size(tsi_fake_frame *frame) { if (frame->data == NULL) { frame->allocated_size = frame->size; frame->data = gpr_malloc(frame->allocated_size); if (frame->data == NULL) return 0; } else if (frame->size > frame->allocated_size) { unsigned char *new_data = gpr_realloc(frame->data, frame->size); if (new_data == NULL) { gpr_free(frame->data); frame->data = NULL; return 0; } frame->data = new_data; frame->allocated_size = frame->size; } return 1; } /* This method should not be called if frame->needs_framing is not 0. */ static tsi_result fill_frame_from_bytes(const unsigned char *incoming_bytes, size_t *incoming_bytes_size, tsi_fake_frame *frame) { size_t available_size = *incoming_bytes_size; size_t to_read_size = 0; const unsigned char *bytes_cursor = incoming_bytes; if (frame->needs_draining) return TSI_INTERNAL_ERROR; if (frame->data == NULL) { frame->allocated_size = TSI_FAKE_FRAME_INITIAL_ALLOCATED_SIZE; frame->data = gpr_malloc(frame->allocated_size); if (frame->data == NULL) return TSI_OUT_OF_RESOURCES; } if (frame->offset < TSI_FAKE_FRAME_HEADER_SIZE) { to_read_size = TSI_FAKE_FRAME_HEADER_SIZE - frame->offset; if (to_read_size > available_size) { /* Just fill what we can and exit. */ memcpy(frame->data + frame->offset, bytes_cursor, available_size); bytes_cursor += available_size; frame->offset += available_size; *incoming_bytes_size = (size_t)(bytes_cursor - incoming_bytes); return TSI_INCOMPLETE_DATA; } memcpy(frame->data + frame->offset, bytes_cursor, to_read_size); bytes_cursor += to_read_size; frame->offset += to_read_size; available_size -= to_read_size; frame->size = load32_little_endian(frame->data); if (!tsi_fake_frame_ensure_size(frame)) return TSI_OUT_OF_RESOURCES; } to_read_size = frame->size - frame->offset; if (to_read_size > available_size) { memcpy(frame->data + frame->offset, bytes_cursor, available_size); frame->offset += available_size; bytes_cursor += available_size; *incoming_bytes_size = (size_t)(bytes_cursor - incoming_bytes); return TSI_INCOMPLETE_DATA; } memcpy(frame->data + frame->offset, bytes_cursor, to_read_size); bytes_cursor += to_read_size; *incoming_bytes_size = (size_t)(bytes_cursor - incoming_bytes); tsi_fake_frame_reset(frame, 1 /* needs_draining */); return TSI_OK; } /* This method should not be called if frame->needs_framing is 0. */ static tsi_result drain_frame_to_bytes(unsigned char *outgoing_bytes, size_t *outgoing_bytes_size, tsi_fake_frame *frame) { size_t to_write_size = frame->size - frame->offset; if (!frame->needs_draining) return TSI_INTERNAL_ERROR; if (*outgoing_bytes_size < to_write_size) { memcpy(outgoing_bytes, frame->data + frame->offset, *outgoing_bytes_size); frame->offset += *outgoing_bytes_size; return TSI_INCOMPLETE_DATA; } memcpy(outgoing_bytes, frame->data + frame->offset, to_write_size); *outgoing_bytes_size = to_write_size; tsi_fake_frame_reset(frame, 0 /* needs_draining */); return TSI_OK; } static tsi_result bytes_to_frame(unsigned char *bytes, size_t bytes_size, tsi_fake_frame *frame) { frame->offset = 0; frame->size = bytes_size + TSI_FAKE_FRAME_HEADER_SIZE; if (!tsi_fake_frame_ensure_size(frame)) return TSI_OUT_OF_RESOURCES; store32_little_endian((uint32_t)frame->size, frame->data); memcpy(frame->data + TSI_FAKE_FRAME_HEADER_SIZE, bytes, bytes_size); tsi_fake_frame_reset(frame, 1 /* needs draining */); return TSI_OK; } static void tsi_fake_frame_destruct(tsi_fake_frame *frame) { if (frame->data != NULL) gpr_free(frame->data); } /* --- tsi_frame_protector methods implementation. ---*/ static tsi_result fake_protector_protect(tsi_frame_protector *self, const unsigned char *unprotected_bytes, size_t *unprotected_bytes_size, unsigned char *protected_output_frames, size_t *protected_output_frames_size) { tsi_result result = TSI_OK; tsi_fake_frame_protector *impl = (tsi_fake_frame_protector *)self; unsigned char frame_header[TSI_FAKE_FRAME_HEADER_SIZE]; tsi_fake_frame *frame = &impl->protect_frame; size_t saved_output_size = *protected_output_frames_size; size_t drained_size = 0; size_t *num_bytes_written = protected_output_frames_size; *num_bytes_written = 0; /* Try to drain first. */ if (frame->needs_draining) { drained_size = saved_output_size - *num_bytes_written; result = drain_frame_to_bytes(protected_output_frames, &drained_size, frame); *num_bytes_written += drained_size; protected_output_frames += drained_size; if (result != TSI_OK) { if (result == TSI_INCOMPLETE_DATA) { *unprotected_bytes_size = 0; result = TSI_OK; } return result; } } /* Now process the unprotected_bytes. */ if (frame->needs_draining) return TSI_INTERNAL_ERROR; if (frame->size == 0) { /* New frame, create a header. */ size_t written_in_frame_size = 0; store32_little_endian((uint32_t)impl->max_frame_size, frame_header); written_in_frame_size = TSI_FAKE_FRAME_HEADER_SIZE; result = fill_frame_from_bytes(frame_header, &written_in_frame_size, frame); if (result != TSI_INCOMPLETE_DATA) { gpr_log(GPR_ERROR, "fill_frame_from_bytes returned %s", tsi_result_to_string(result)); return result; } } result = fill_frame_from_bytes(unprotected_bytes, unprotected_bytes_size, frame); if (result != TSI_OK) { if (result == TSI_INCOMPLETE_DATA) result = TSI_OK; return result; } /* Try to drain again. */ if (!frame->needs_draining) return TSI_INTERNAL_ERROR; if (frame->offset != 0) return TSI_INTERNAL_ERROR; drained_size = saved_output_size - *num_bytes_written; result = drain_frame_to_bytes(protected_output_frames, &drained_size, frame); *num_bytes_written += drained_size; if (result == TSI_INCOMPLETE_DATA) result = TSI_OK; return result; } static tsi_result fake_protector_protect_flush( tsi_frame_protector *self, unsigned char *protected_output_frames, size_t *protected_output_frames_size, size_t *still_pending_size) { tsi_result result = TSI_OK; tsi_fake_frame_protector *impl = (tsi_fake_frame_protector *)self; tsi_fake_frame *frame = &impl->protect_frame; if (!frame->needs_draining) { /* Create a short frame. */ frame->size = frame->offset; frame->offset = 0; frame->needs_draining = 1; store32_little_endian((uint32_t)frame->size, frame->data); /* Overwrite header. */ } result = drain_frame_to_bytes(protected_output_frames, protected_output_frames_size, frame); if (result == TSI_INCOMPLETE_DATA) result = TSI_OK; *still_pending_size = frame->size - frame->offset; return result; } static tsi_result fake_protector_unprotect( tsi_frame_protector *self, const unsigned char *protected_frames_bytes, size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes, size_t *unprotected_bytes_size) { tsi_result result = TSI_OK; tsi_fake_frame_protector *impl = (tsi_fake_frame_protector *)self; tsi_fake_frame *frame = &impl->unprotect_frame; size_t saved_output_size = *unprotected_bytes_size; size_t drained_size = 0; size_t *num_bytes_written = unprotected_bytes_size; *num_bytes_written = 0; /* Try to drain first. */ if (frame->needs_draining) { /* Go past the header if needed. */ if (frame->offset == 0) frame->offset = TSI_FAKE_FRAME_HEADER_SIZE; drained_size = saved_output_size - *num_bytes_written; result = drain_frame_to_bytes(unprotected_bytes, &drained_size, frame); unprotected_bytes += drained_size; *num_bytes_written += drained_size; if (result != TSI_OK) { if (result == TSI_INCOMPLETE_DATA) { *protected_frames_bytes_size = 0; result = TSI_OK; } return result; } } /* Now process the protected_bytes. */ if (frame->needs_draining) return TSI_INTERNAL_ERROR; result = fill_frame_from_bytes(protected_frames_bytes, protected_frames_bytes_size, frame); if (result != TSI_OK) { if (result == TSI_INCOMPLETE_DATA) result = TSI_OK; return result; } /* Try to drain again. */ if (!frame->needs_draining) return TSI_INTERNAL_ERROR; if (frame->offset != 0) return TSI_INTERNAL_ERROR; frame->offset = TSI_FAKE_FRAME_HEADER_SIZE; /* Go past the header. */ drained_size = saved_output_size - *num_bytes_written; result = drain_frame_to_bytes(unprotected_bytes, &drained_size, frame); *num_bytes_written += drained_size; if (result == TSI_INCOMPLETE_DATA) result = TSI_OK; return result; } static void fake_protector_destroy(tsi_frame_protector *self) { tsi_fake_frame_protector *impl = (tsi_fake_frame_protector *)self; tsi_fake_frame_destruct(&impl->protect_frame); tsi_fake_frame_destruct(&impl->unprotect_frame); gpr_free(self); } static const tsi_frame_protector_vtable frame_protector_vtable = { fake_protector_protect, fake_protector_protect_flush, fake_protector_unprotect, fake_protector_destroy, }; /* --- tsi_handshaker methods implementation. ---*/ static tsi_result fake_handshaker_get_bytes_to_send_to_peer( tsi_handshaker *self, unsigned char *bytes, size_t *bytes_size) { tsi_fake_handshaker *impl = (tsi_fake_handshaker *)self; tsi_result result = TSI_OK; if (impl->needs_incoming_message || impl->result == TSI_OK) { *bytes_size = 0; return TSI_OK; } if (!impl->outgoing.needs_draining) { tsi_fake_handshake_message next_message_to_send = impl->next_message_to_send + 2; const char *msg_string = tsi_fake_handshake_message_to_string(impl->next_message_to_send); result = bytes_to_frame((unsigned char *)msg_string, strlen(msg_string), &impl->outgoing); if (result != TSI_OK) return result; if (next_message_to_send > TSI_FAKE_HANDSHAKE_MESSAGE_MAX) { next_message_to_send = TSI_FAKE_HANDSHAKE_MESSAGE_MAX; } if (tsi_tracing_enabled) { gpr_log(GPR_INFO, "%s prepared %s.", impl->is_client ? "Client" : "Server", tsi_fake_handshake_message_to_string(impl->next_message_to_send)); } impl->next_message_to_send = next_message_to_send; } result = drain_frame_to_bytes(bytes, bytes_size, &impl->outgoing); if (result != TSI_OK) return result; if (!impl->is_client && impl->next_message_to_send == TSI_FAKE_HANDSHAKE_MESSAGE_MAX) { /* We're done. */ if (tsi_tracing_enabled) { gpr_log(GPR_INFO, "Server is done."); } impl->result = TSI_OK; } else { impl->needs_incoming_message = 1; } return TSI_OK; } static tsi_result fake_handshaker_process_bytes_from_peer( tsi_handshaker *self, const unsigned char *bytes, size_t *bytes_size) { tsi_result result = TSI_OK; tsi_fake_handshaker *impl = (tsi_fake_handshaker *)self; tsi_fake_handshake_message expected_msg = impl->next_message_to_send - 1; tsi_fake_handshake_message received_msg; if (!impl->needs_incoming_message || impl->result == TSI_OK) { *bytes_size = 0; return TSI_OK; } result = fill_frame_from_bytes(bytes, bytes_size, &impl->incoming); if (result != TSI_OK) return result; /* We now have a complete frame. */ result = tsi_fake_handshake_message_from_string( (const char *)impl->incoming.data + TSI_FAKE_FRAME_HEADER_SIZE, &received_msg); if (result != TSI_OK) { impl->result = result; return result; } if (received_msg != expected_msg) { gpr_log(GPR_ERROR, "Invalid received message (%s instead of %s)", tsi_fake_handshake_message_to_string(received_msg), tsi_fake_handshake_message_to_string(expected_msg)); } if (tsi_tracing_enabled) { gpr_log(GPR_INFO, "%s received %s.", impl->is_client ? "Client" : "Server", tsi_fake_handshake_message_to_string(received_msg)); } tsi_fake_frame_reset(&impl->incoming, 0 /* needs_draining */); impl->needs_incoming_message = 0; if (impl->next_message_to_send == TSI_FAKE_HANDSHAKE_MESSAGE_MAX) { /* We're done. */ if (tsi_tracing_enabled) { gpr_log(GPR_INFO, "%s is done.", impl->is_client ? "Client" : "Server"); } impl->result = TSI_OK; } return TSI_OK; } static tsi_result fake_handshaker_get_result(tsi_handshaker *self) { tsi_fake_handshaker *impl = (tsi_fake_handshaker *)self; return impl->result; } static tsi_result fake_handshaker_extract_peer(tsi_handshaker *self, tsi_peer *peer) { tsi_result result = tsi_construct_peer(1, peer); if (result != TSI_OK) return result; result = tsi_construct_string_peer_property_from_cstring( TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_FAKE_CERTIFICATE_TYPE, &peer->properties[0]); if (result != TSI_OK) tsi_peer_destruct(peer); return result; } static tsi_result fake_handshaker_create_frame_protector( tsi_handshaker *self, size_t *max_protected_frame_size, tsi_frame_protector **protector) { *protector = tsi_create_fake_protector(max_protected_frame_size); if (*protector == NULL) return TSI_OUT_OF_RESOURCES; return TSI_OK; } static void fake_handshaker_destroy(tsi_handshaker *self) { tsi_fake_handshaker *impl = (tsi_fake_handshaker *)self; tsi_fake_frame_destruct(&impl->incoming); tsi_fake_frame_destruct(&impl->outgoing); gpr_free(self); } static const tsi_handshaker_vtable handshaker_vtable = { fake_handshaker_get_bytes_to_send_to_peer, fake_handshaker_process_bytes_from_peer, fake_handshaker_get_result, fake_handshaker_extract_peer, fake_handshaker_create_frame_protector, fake_handshaker_destroy, }; tsi_handshaker *tsi_create_fake_handshaker(int is_client) { tsi_fake_handshaker *impl = gpr_zalloc(sizeof(*impl)); impl->base.vtable = &handshaker_vtable; impl->is_client = is_client; impl->result = TSI_HANDSHAKE_IN_PROGRESS; if (is_client) { impl->needs_incoming_message = 0; impl->next_message_to_send = TSI_FAKE_CLIENT_INIT; } else { impl->needs_incoming_message = 1; impl->next_message_to_send = TSI_FAKE_SERVER_INIT; } return &impl->base; } tsi_frame_protector *tsi_create_fake_protector( size_t *max_protected_frame_size) { tsi_fake_frame_protector *impl = gpr_zalloc(sizeof(*impl)); impl->max_frame_size = (max_protected_frame_size == NULL) ? TSI_FAKE_DEFAULT_FRAME_SIZE : *max_protected_frame_size; impl->base.vtable = &frame_protector_vtable; return &impl->base; } grpc-1.3.2/src/core/tsi/fake_transport_security.h000066400000000000000000000046331310511640000221050ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_TSI_FAKE_TRANSPORT_SECURITY_H #define GRPC_CORE_TSI_FAKE_TRANSPORT_SECURITY_H #include "src/core/tsi/transport_security_interface.h" #ifdef __cplusplus extern "C" { #endif /* Value for the TSI_CERTIFICATE_TYPE_PEER_PROPERTY property for FAKE certs. */ #define TSI_FAKE_CERTIFICATE_TYPE "FAKE" /* Creates a fake handshaker that will create a fake frame protector. No cryptography is performed in these objects. They just simulate handshake messages going back and forth for the handshaker and do some framing on cleartext data for the protector. */ tsi_handshaker *tsi_create_fake_handshaker(int is_client); /* Creates a protector directly without going through the handshake phase. */ tsi_frame_protector *tsi_create_fake_protector( size_t *max_protected_frame_size); #ifdef __cplusplus } #endif #endif /* GRPC_CORE_TSI_FAKE_TRANSPORT_SECURITY_H */ grpc-1.3.2/src/core/tsi/ssl_transport_security.c000066400000000000000000001541751310511640000220020ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/tsi/ssl_transport_security.h" #include #include #include /* TODO(jboeuf): refactor inet_ntop into a portability header. */ /* Note: for whomever reads this and tries to refactor this, this can't be in grpc, it has to be in gpr. */ #ifdef GPR_WINDOWS #include #else #include #endif #include #include #include #include #include #include #include /* For OPENSSL_free */ #include #include #include #include #include "src/core/tsi/ssl_types.h" #include "src/core/tsi/transport_security.h" /* --- Constants. ---*/ #define TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND 16384 #define TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND 1024 /* Putting a macro like this and littering the source file with #if is really bad practice. TODO(jboeuf): refactor all the #if / #endif in a separate module. */ #ifndef TSI_OPENSSL_ALPN_SUPPORT #define TSI_OPENSSL_ALPN_SUPPORT 1 #endif /* TODO(jboeuf): I have not found a way to get this number dynamically from the SSL structure. This is what we would ultimately want though... */ #define TSI_SSL_MAX_PROTECTION_OVERHEAD 100 /* --- Structure definitions. ---*/ struct tsi_ssl_client_handshaker_factory { SSL_CTX *ssl_context; unsigned char *alpn_protocol_list; size_t alpn_protocol_list_length; }; struct tsi_ssl_server_handshaker_factory { /* Several contexts to support SNI. The tsi_peer array contains the subject names of the server certificates associated with the contexts at the same index. */ SSL_CTX **ssl_contexts; tsi_peer *ssl_context_x509_subject_names; size_t ssl_context_count; unsigned char *alpn_protocol_list; size_t alpn_protocol_list_length; }; typedef struct { tsi_handshaker base; SSL *ssl; BIO *into_ssl; BIO *from_ssl; tsi_result result; } tsi_ssl_handshaker; typedef struct { tsi_frame_protector base; SSL *ssl; BIO *into_ssl; BIO *from_ssl; unsigned char *buffer; size_t buffer_size; size_t buffer_offset; } tsi_ssl_frame_protector; /* --- Library Initialization. ---*/ static gpr_once init_openssl_once = GPR_ONCE_INIT; static gpr_mu *openssl_mutexes = NULL; static void openssl_locking_cb(int mode, int type, const char *file, int line) { if (mode & CRYPTO_LOCK) { gpr_mu_lock(&openssl_mutexes[type]); } else { gpr_mu_unlock(&openssl_mutexes[type]); } } static unsigned long openssl_thread_id_cb(void) { return (unsigned long)gpr_thd_currentid(); } static void init_openssl(void) { int i; int num_locks; SSL_library_init(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); num_locks = CRYPTO_num_locks(); GPR_ASSERT(num_locks > 0); openssl_mutexes = gpr_malloc((size_t)num_locks * sizeof(gpr_mu)); for (i = 0; i < CRYPTO_num_locks(); i++) { gpr_mu_init(&openssl_mutexes[i]); } CRYPTO_set_locking_callback(openssl_locking_cb); CRYPTO_set_id_callback(openssl_thread_id_cb); } /* --- Ssl utils. ---*/ static const char *ssl_error_string(int error) { switch (error) { case SSL_ERROR_NONE: return "SSL_ERROR_NONE"; case SSL_ERROR_ZERO_RETURN: return "SSL_ERROR_ZERO_RETURN"; case SSL_ERROR_WANT_READ: return "SSL_ERROR_WANT_READ"; case SSL_ERROR_WANT_WRITE: return "SSL_ERROR_WANT_WRITE"; case SSL_ERROR_WANT_CONNECT: return "SSL_ERROR_WANT_CONNECT"; case SSL_ERROR_WANT_ACCEPT: return "SSL_ERROR_WANT_ACCEPT"; case SSL_ERROR_WANT_X509_LOOKUP: return "SSL_ERROR_WANT_X509_LOOKUP"; case SSL_ERROR_SYSCALL: return "SSL_ERROR_SYSCALL"; case SSL_ERROR_SSL: return "SSL_ERROR_SSL"; default: return "Unknown error"; } } /* TODO(jboeuf): Remove when we are past the debugging phase with this code. */ static void ssl_log_where_info(const SSL *ssl, int where, int flag, const char *msg) { if ((where & flag) && tsi_tracing_enabled) { gpr_log(GPR_INFO, "%20.20s - %30.30s - %5.10s", msg, SSL_state_string_long(ssl), SSL_state_string(ssl)); } } /* Used for debugging. TODO(jboeuf): Remove when code is mature enough. */ static void ssl_info_callback(const SSL *ssl, int where, int ret) { if (ret == 0) { gpr_log(GPR_ERROR, "ssl_info_callback: error occured.\n"); return; } ssl_log_where_info(ssl, where, SSL_CB_LOOP, "LOOP"); ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_START, "HANDSHAKE START"); ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_DONE, "HANDSHAKE DONE"); } /* Returns 1 if name looks like an IP address, 0 otherwise. This is a very rough heuristic, and only handles IPv6 in hexadecimal form. */ static int looks_like_ip_address(const char *name) { size_t i; size_t dot_count = 0; size_t num_size = 0; for (i = 0; i < strlen(name); i++) { if (name[i] == ':') { /* IPv6 Address in hexadecimal form, : is not allowed in DNS names. */ return 1; } if (name[i] >= '0' && name[i] <= '9') { if (num_size > 3) return 0; num_size++; } else if (name[i] == '.') { if (dot_count > 3 || num_size == 0) return 0; dot_count++; num_size = 0; } else { return 0; } } if (dot_count < 3 || num_size == 0) return 0; return 1; } /* Gets the subject CN from an X509 cert. */ static tsi_result ssl_get_x509_common_name(X509 *cert, unsigned char **utf8, size_t *utf8_size) { int common_name_index = -1; X509_NAME_ENTRY *common_name_entry = NULL; ASN1_STRING *common_name_asn1 = NULL; X509_NAME *subject_name = X509_get_subject_name(cert); int utf8_returned_size = 0; if (subject_name == NULL) { gpr_log(GPR_ERROR, "Could not get subject name from certificate."); return TSI_NOT_FOUND; } common_name_index = X509_NAME_get_index_by_NID(subject_name, NID_commonName, -1); if (common_name_index == -1) { gpr_log(GPR_ERROR, "Could not get common name of subject from certificate."); return TSI_NOT_FOUND; } common_name_entry = X509_NAME_get_entry(subject_name, common_name_index); if (common_name_entry == NULL) { gpr_log(GPR_ERROR, "Could not get common name entry from certificate."); return TSI_INTERNAL_ERROR; } common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry); if (common_name_asn1 == NULL) { gpr_log(GPR_ERROR, "Could not get common name entry asn1 from certificate."); return TSI_INTERNAL_ERROR; } utf8_returned_size = ASN1_STRING_to_UTF8(utf8, common_name_asn1); if (utf8_returned_size < 0) { gpr_log(GPR_ERROR, "Could not extract utf8 from asn1 string."); return TSI_OUT_OF_RESOURCES; } *utf8_size = (size_t)utf8_returned_size; return TSI_OK; } /* Gets the subject CN of an X509 cert as a tsi_peer_property. */ static tsi_result peer_property_from_x509_common_name( X509 *cert, tsi_peer_property *property) { unsigned char *common_name; size_t common_name_size; tsi_result result = ssl_get_x509_common_name(cert, &common_name, &common_name_size); if (result != TSI_OK) { if (result == TSI_NOT_FOUND) { common_name = NULL; common_name_size = 0; } else { return result; } } result = tsi_construct_string_peer_property( TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, common_name == NULL ? "" : (const char *)common_name, common_name_size, property); OPENSSL_free(common_name); return result; } /* Gets the X509 cert in PEM format as a tsi_peer_property. */ static tsi_result add_pem_certificate(X509 *cert, tsi_peer_property *property) { BIO *bio = BIO_new(BIO_s_mem()); if (!PEM_write_bio_X509(bio, cert)) { BIO_free(bio); return TSI_INTERNAL_ERROR; } char *contents; long len = BIO_get_mem_data(bio, &contents); if (len <= 0) { BIO_free(bio); return TSI_INTERNAL_ERROR; } tsi_result result = tsi_construct_string_peer_property( TSI_X509_PEM_CERT_PROPERTY, (const char *)contents, (size_t)len, property); BIO_free(bio); return result; } /* Gets the subject SANs from an X509 cert as a tsi_peer_property. */ static tsi_result add_subject_alt_names_properties_to_peer( tsi_peer *peer, GENERAL_NAMES *subject_alt_names, size_t subject_alt_name_count) { size_t i; tsi_result result = TSI_OK; /* Reset for DNS entries filtering. */ peer->property_count -= subject_alt_name_count; for (i = 0; i < subject_alt_name_count; i++) { GENERAL_NAME *subject_alt_name = sk_GENERAL_NAME_value(subject_alt_names, TSI_SIZE_AS_SIZE(i)); /* Filter out the non-dns entries names. */ if (subject_alt_name->type == GEN_DNS) { unsigned char *name = NULL; int name_size; name_size = ASN1_STRING_to_UTF8(&name, subject_alt_name->d.dNSName); if (name_size < 0) { gpr_log(GPR_ERROR, "Could not get utf8 from asn1 string."); result = TSI_INTERNAL_ERROR; break; } result = tsi_construct_string_peer_property( TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, (const char *)name, (size_t)name_size, &peer->properties[peer->property_count++]); OPENSSL_free(name); } else if (subject_alt_name->type == GEN_IPADD) { char ntop_buf[INET6_ADDRSTRLEN]; int af; if (subject_alt_name->d.iPAddress->length == 4) { af = AF_INET; } else if (subject_alt_name->d.iPAddress->length == 16) { af = AF_INET6; } else { gpr_log(GPR_ERROR, "SAN IP Address contained invalid IP"); result = TSI_INTERNAL_ERROR; break; } const char *name = inet_ntop(af, subject_alt_name->d.iPAddress->data, ntop_buf, INET6_ADDRSTRLEN); if (name == NULL) { gpr_log(GPR_ERROR, "Could not get IP string from asn1 octet."); result = TSI_INTERNAL_ERROR; break; } result = tsi_construct_string_peer_property_from_cstring( TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, name, &peer->properties[peer->property_count++]); } if (result != TSI_OK) break; } return result; } /* Gets information about the peer's X509 cert as a tsi_peer object. */ static tsi_result peer_from_x509(X509 *cert, int include_certificate_type, tsi_peer *peer) { /* TODO(jboeuf): Maybe add more properties. */ GENERAL_NAMES *subject_alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0); int subject_alt_name_count = (subject_alt_names != NULL) ? (int)sk_GENERAL_NAME_num(subject_alt_names) : 0; size_t property_count; tsi_result result; GPR_ASSERT(subject_alt_name_count >= 0); property_count = (include_certificate_type ? (size_t)1 : 0) + 2 /* common name, certificate */ + (size_t)subject_alt_name_count; result = tsi_construct_peer(property_count, peer); if (result != TSI_OK) return result; do { if (include_certificate_type) { result = tsi_construct_string_peer_property_from_cstring( TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE, &peer->properties[0]); if (result != TSI_OK) break; } result = peer_property_from_x509_common_name( cert, &peer->properties[include_certificate_type ? 1 : 0]); if (result != TSI_OK) break; result = add_pem_certificate( cert, &peer->properties[include_certificate_type ? 2 : 1]); if (result != TSI_OK) break; if (subject_alt_name_count != 0) { result = add_subject_alt_names_properties_to_peer( peer, subject_alt_names, (size_t)subject_alt_name_count); if (result != TSI_OK) break; } } while (0); if (subject_alt_names != NULL) { sk_GENERAL_NAME_pop_free(subject_alt_names, GENERAL_NAME_free); } if (result != TSI_OK) tsi_peer_destruct(peer); return result; } /* Logs the SSL error stack. */ static void log_ssl_error_stack(void) { unsigned long err; while ((err = ERR_get_error()) != 0) { char details[256]; ERR_error_string_n((uint32_t)err, details, sizeof(details)); gpr_log(GPR_ERROR, "%s", details); } } /* Performs an SSL_read and handle errors. */ static tsi_result do_ssl_read(SSL *ssl, unsigned char *unprotected_bytes, size_t *unprotected_bytes_size) { int read_from_ssl; GPR_ASSERT(*unprotected_bytes_size <= INT_MAX); read_from_ssl = SSL_read(ssl, unprotected_bytes, (int)*unprotected_bytes_size); if (read_from_ssl == 0) { gpr_log(GPR_ERROR, "SSL_read returned 0 unexpectedly."); return TSI_INTERNAL_ERROR; } if (read_from_ssl < 0) { read_from_ssl = SSL_get_error(ssl, read_from_ssl); switch (read_from_ssl) { case SSL_ERROR_WANT_READ: /* We need more data to finish the frame. */ *unprotected_bytes_size = 0; return TSI_OK; case SSL_ERROR_WANT_WRITE: gpr_log( GPR_ERROR, "Peer tried to renegotiate SSL connection. This is unsupported."); return TSI_UNIMPLEMENTED; case SSL_ERROR_SSL: gpr_log(GPR_ERROR, "Corruption detected."); log_ssl_error_stack(); return TSI_DATA_CORRUPTED; default: gpr_log(GPR_ERROR, "SSL_read failed with error %s.", ssl_error_string(read_from_ssl)); return TSI_PROTOCOL_FAILURE; } } *unprotected_bytes_size = (size_t)read_from_ssl; return TSI_OK; } /* Performs an SSL_write and handle errors. */ static tsi_result do_ssl_write(SSL *ssl, unsigned char *unprotected_bytes, size_t unprotected_bytes_size) { int ssl_write_result; GPR_ASSERT(unprotected_bytes_size <= INT_MAX); ssl_write_result = SSL_write(ssl, unprotected_bytes, (int)unprotected_bytes_size); if (ssl_write_result < 0) { ssl_write_result = SSL_get_error(ssl, ssl_write_result); if (ssl_write_result == SSL_ERROR_WANT_READ) { gpr_log(GPR_ERROR, "Peer tried to renegotiate SSL connection. This is unsupported."); return TSI_UNIMPLEMENTED; } else { gpr_log(GPR_ERROR, "SSL_write failed with error %s.", ssl_error_string(ssl_write_result)); return TSI_INTERNAL_ERROR; } } return TSI_OK; } /* Loads an in-memory PEM certificate chain into the SSL context. */ static tsi_result ssl_ctx_use_certificate_chain( SSL_CTX *context, const unsigned char *pem_cert_chain, size_t pem_cert_chain_size) { tsi_result result = TSI_OK; X509 *certificate = NULL; BIO *pem; GPR_ASSERT(pem_cert_chain_size <= INT_MAX); pem = BIO_new_mem_buf((void *)pem_cert_chain, (int)pem_cert_chain_size); if (pem == NULL) return TSI_OUT_OF_RESOURCES; do { certificate = PEM_read_bio_X509_AUX(pem, NULL, NULL, ""); if (certificate == NULL) { result = TSI_INVALID_ARGUMENT; break; } if (!SSL_CTX_use_certificate(context, certificate)) { result = TSI_INVALID_ARGUMENT; break; } while (1) { X509 *certificate_authority = PEM_read_bio_X509(pem, NULL, NULL, ""); if (certificate_authority == NULL) { ERR_clear_error(); break; /* Done reading. */ } if (!SSL_CTX_add_extra_chain_cert(context, certificate_authority)) { X509_free(certificate_authority); result = TSI_INVALID_ARGUMENT; break; } /* We don't need to free certificate_authority as its ownership has been transfered to the context. That is not the case for certificate though. */ } } while (0); if (certificate != NULL) X509_free(certificate); BIO_free(pem); return result; } /* Loads an in-memory PEM private key into the SSL context. */ static tsi_result ssl_ctx_use_private_key(SSL_CTX *context, const unsigned char *pem_key, size_t pem_key_size) { tsi_result result = TSI_OK; EVP_PKEY *private_key = NULL; BIO *pem; GPR_ASSERT(pem_key_size <= INT_MAX); pem = BIO_new_mem_buf((void *)pem_key, (int)pem_key_size); if (pem == NULL) return TSI_OUT_OF_RESOURCES; do { private_key = PEM_read_bio_PrivateKey(pem, NULL, NULL, ""); if (private_key == NULL) { result = TSI_INVALID_ARGUMENT; break; } if (!SSL_CTX_use_PrivateKey(context, private_key)) { result = TSI_INVALID_ARGUMENT; break; } } while (0); if (private_key != NULL) EVP_PKEY_free(private_key); BIO_free(pem); return result; } /* Loads in-memory PEM verification certs into the SSL context and optionally returns the verification cert names (root_names can be NULL). */ static tsi_result ssl_ctx_load_verification_certs( SSL_CTX *context, const unsigned char *pem_roots, size_t pem_roots_size, STACK_OF(X509_NAME) * *root_names) { tsi_result result = TSI_OK; size_t num_roots = 0; X509 *root = NULL; X509_NAME *root_name = NULL; BIO *pem; X509_STORE *root_store; GPR_ASSERT(pem_roots_size <= INT_MAX); pem = BIO_new_mem_buf((void *)pem_roots, (int)pem_roots_size); root_store = SSL_CTX_get_cert_store(context); if (root_store == NULL) return TSI_INVALID_ARGUMENT; if (pem == NULL) return TSI_OUT_OF_RESOURCES; if (root_names != NULL) { *root_names = sk_X509_NAME_new_null(); if (*root_names == NULL) return TSI_OUT_OF_RESOURCES; } while (1) { root = PEM_read_bio_X509_AUX(pem, NULL, NULL, ""); if (root == NULL) { ERR_clear_error(); break; /* We're at the end of stream. */ } if (root_names != NULL) { root_name = X509_get_subject_name(root); if (root_name == NULL) { gpr_log(GPR_ERROR, "Could not get name from root certificate."); result = TSI_INVALID_ARGUMENT; break; } root_name = X509_NAME_dup(root_name); if (root_name == NULL) { result = TSI_OUT_OF_RESOURCES; break; } sk_X509_NAME_push(*root_names, root_name); root_name = NULL; } if (!X509_STORE_add_cert(root_store, root)) { gpr_log(GPR_ERROR, "Could not add root certificate to ssl context."); result = TSI_INTERNAL_ERROR; break; } X509_free(root); num_roots++; } if (num_roots == 0) { gpr_log(GPR_ERROR, "Could not load any root certificate."); result = TSI_INVALID_ARGUMENT; } if (result != TSI_OK) { if (root != NULL) X509_free(root); if (root_names != NULL) { sk_X509_NAME_pop_free(*root_names, X509_NAME_free); *root_names = NULL; if (root_name != NULL) X509_NAME_free(root_name); } } BIO_free(pem); return result; } /* Populates the SSL context with a private key and a cert chain, and sets the cipher list and the ephemeral ECDH key. */ static tsi_result populate_ssl_context( SSL_CTX *context, const unsigned char *pem_private_key, size_t pem_private_key_size, const unsigned char *pem_certificate_chain, size_t pem_certificate_chain_size, const char *cipher_list) { tsi_result result = TSI_OK; if (pem_certificate_chain != NULL) { result = ssl_ctx_use_certificate_chain(context, pem_certificate_chain, pem_certificate_chain_size); if (result != TSI_OK) { gpr_log(GPR_ERROR, "Invalid cert chain file."); return result; } } if (pem_private_key != NULL) { result = ssl_ctx_use_private_key(context, pem_private_key, pem_private_key_size); if (result != TSI_OK || !SSL_CTX_check_private_key(context)) { gpr_log(GPR_ERROR, "Invalid private key."); return result != TSI_OK ? result : TSI_INVALID_ARGUMENT; } } if ((cipher_list != NULL) && !SSL_CTX_set_cipher_list(context, cipher_list)) { gpr_log(GPR_ERROR, "Invalid cipher list: %s.", cipher_list); return TSI_INVALID_ARGUMENT; } { EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); if (!SSL_CTX_set_tmp_ecdh(context, ecdh)) { gpr_log(GPR_ERROR, "Could not set ephemeral ECDH key."); EC_KEY_free(ecdh); return TSI_INTERNAL_ERROR; } SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE); EC_KEY_free(ecdh); } return TSI_OK; } /* Extracts the CN and the SANs from an X509 cert as a peer object. */ static tsi_result extract_x509_subject_names_from_pem_cert( const unsigned char *pem_cert, size_t pem_cert_size, tsi_peer *peer) { tsi_result result = TSI_OK; X509 *cert = NULL; BIO *pem; GPR_ASSERT(pem_cert_size <= INT_MAX); pem = BIO_new_mem_buf((void *)pem_cert, (int)pem_cert_size); if (pem == NULL) return TSI_OUT_OF_RESOURCES; cert = PEM_read_bio_X509(pem, NULL, NULL, ""); if (cert == NULL) { gpr_log(GPR_ERROR, "Invalid certificate"); result = TSI_INVALID_ARGUMENT; } else { result = peer_from_x509(cert, 0, peer); } if (cert != NULL) X509_free(cert); BIO_free(pem); return result; } /* Builds the alpn protocol name list according to rfc 7301. */ static tsi_result build_alpn_protocol_name_list( const unsigned char **alpn_protocols, const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols, unsigned char **protocol_name_list, size_t *protocol_name_list_length) { uint16_t i; unsigned char *current; *protocol_name_list = NULL; *protocol_name_list_length = 0; if (num_alpn_protocols == 0) return TSI_INVALID_ARGUMENT; for (i = 0; i < num_alpn_protocols; i++) { if (alpn_protocols_lengths[i] == 0) { gpr_log(GPR_ERROR, "Invalid 0-length protocol name."); return TSI_INVALID_ARGUMENT; } *protocol_name_list_length += (size_t)alpn_protocols_lengths[i] + 1; } *protocol_name_list = gpr_malloc(*protocol_name_list_length); if (*protocol_name_list == NULL) return TSI_OUT_OF_RESOURCES; current = *protocol_name_list; for (i = 0; i < num_alpn_protocols; i++) { *(current++) = alpn_protocols_lengths[i]; memcpy(current, alpn_protocols[i], alpn_protocols_lengths[i]); current += alpn_protocols_lengths[i]; } /* Safety check. */ if ((current < *protocol_name_list) || ((uintptr_t)(current - *protocol_name_list) != *protocol_name_list_length)) { return TSI_INTERNAL_ERROR; } return TSI_OK; } // The verification callback is used for clients that don't really care about // the server's certificate, but we need to pull it anyway, in case a higher // layer wants to look at it. In this case the verification may fail, but // we don't really care. static int NullVerifyCallback(int preverify_ok, X509_STORE_CTX *ctx) { return 1; } /* --- tsi_frame_protector methods implementation. ---*/ static tsi_result ssl_protector_protect(tsi_frame_protector *self, const unsigned char *unprotected_bytes, size_t *unprotected_bytes_size, unsigned char *protected_output_frames, size_t *protected_output_frames_size) { tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self; int read_from_ssl; size_t available; tsi_result result = TSI_OK; /* First see if we have some pending data in the SSL BIO. */ int pending_in_ssl = (int)BIO_pending(impl->from_ssl); if (pending_in_ssl > 0) { *unprotected_bytes_size = 0; GPR_ASSERT(*protected_output_frames_size <= INT_MAX); read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames, (int)*protected_output_frames_size); if (read_from_ssl < 0) { gpr_log(GPR_ERROR, "Could not read from BIO even though some data is pending"); return TSI_INTERNAL_ERROR; } *protected_output_frames_size = (size_t)read_from_ssl; return TSI_OK; } /* Now see if we can send a complete frame. */ available = impl->buffer_size - impl->buffer_offset; if (available > *unprotected_bytes_size) { /* If we cannot, just copy the data in our internal buffer. */ memcpy(impl->buffer + impl->buffer_offset, unprotected_bytes, *unprotected_bytes_size); impl->buffer_offset += *unprotected_bytes_size; *protected_output_frames_size = 0; return TSI_OK; } /* If we can, prepare the buffer, send it to SSL_write and read. */ memcpy(impl->buffer + impl->buffer_offset, unprotected_bytes, available); result = do_ssl_write(impl->ssl, impl->buffer, impl->buffer_size); if (result != TSI_OK) return result; GPR_ASSERT(*protected_output_frames_size <= INT_MAX); read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames, (int)*protected_output_frames_size); if (read_from_ssl < 0) { gpr_log(GPR_ERROR, "Could not read from BIO after SSL_write."); return TSI_INTERNAL_ERROR; } *protected_output_frames_size = (size_t)read_from_ssl; *unprotected_bytes_size = available; impl->buffer_offset = 0; return TSI_OK; } static tsi_result ssl_protector_protect_flush( tsi_frame_protector *self, unsigned char *protected_output_frames, size_t *protected_output_frames_size, size_t *still_pending_size) { tsi_result result = TSI_OK; tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self; int read_from_ssl = 0; int pending; if (impl->buffer_offset != 0) { result = do_ssl_write(impl->ssl, impl->buffer, impl->buffer_offset); if (result != TSI_OK) return result; impl->buffer_offset = 0; } pending = (int)BIO_pending(impl->from_ssl); GPR_ASSERT(pending >= 0); *still_pending_size = (size_t)pending; if (*still_pending_size == 0) return TSI_OK; GPR_ASSERT(*protected_output_frames_size <= INT_MAX); read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames, (int)*protected_output_frames_size); if (read_from_ssl <= 0) { gpr_log(GPR_ERROR, "Could not read from BIO after SSL_write."); return TSI_INTERNAL_ERROR; } *protected_output_frames_size = (size_t)read_from_ssl; pending = (int)BIO_pending(impl->from_ssl); GPR_ASSERT(pending >= 0); *still_pending_size = (size_t)pending; return TSI_OK; } static tsi_result ssl_protector_unprotect( tsi_frame_protector *self, const unsigned char *protected_frames_bytes, size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes, size_t *unprotected_bytes_size) { tsi_result result = TSI_OK; int written_into_ssl = 0; size_t output_bytes_size = *unprotected_bytes_size; size_t output_bytes_offset = 0; tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self; /* First, try to read remaining data from ssl. */ result = do_ssl_read(impl->ssl, unprotected_bytes, unprotected_bytes_size); if (result != TSI_OK) return result; if (*unprotected_bytes_size == output_bytes_size) { /* We have read everything we could and cannot process any more input. */ *protected_frames_bytes_size = 0; return TSI_OK; } output_bytes_offset = *unprotected_bytes_size; unprotected_bytes += output_bytes_offset; *unprotected_bytes_size = output_bytes_size - output_bytes_offset; /* Then, try to write some data to ssl. */ GPR_ASSERT(*protected_frames_bytes_size <= INT_MAX); written_into_ssl = BIO_write(impl->into_ssl, protected_frames_bytes, (int)*protected_frames_bytes_size); if (written_into_ssl < 0) { gpr_log(GPR_ERROR, "Sending protected frame to ssl failed with %d", written_into_ssl); return TSI_INTERNAL_ERROR; } *protected_frames_bytes_size = (size_t)written_into_ssl; /* Now try to read some data again. */ result = do_ssl_read(impl->ssl, unprotected_bytes, unprotected_bytes_size); if (result == TSI_OK) { /* Don't forget to output the total number of bytes read. */ *unprotected_bytes_size += output_bytes_offset; } return result; } static void ssl_protector_destroy(tsi_frame_protector *self) { tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self; if (impl->buffer != NULL) gpr_free(impl->buffer); if (impl->ssl != NULL) SSL_free(impl->ssl); gpr_free(self); } static const tsi_frame_protector_vtable frame_protector_vtable = { ssl_protector_protect, ssl_protector_protect_flush, ssl_protector_unprotect, ssl_protector_destroy, }; /* --- tsi_handshaker methods implementation. ---*/ static tsi_result ssl_handshaker_get_bytes_to_send_to_peer(tsi_handshaker *self, unsigned char *bytes, size_t *bytes_size) { tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self; int bytes_read_from_ssl = 0; if (bytes == NULL || bytes_size == NULL || *bytes_size == 0 || *bytes_size > INT_MAX) { return TSI_INVALID_ARGUMENT; } GPR_ASSERT(*bytes_size <= INT_MAX); bytes_read_from_ssl = BIO_read(impl->from_ssl, bytes, (int)*bytes_size); if (bytes_read_from_ssl < 0) { *bytes_size = 0; if (!BIO_should_retry(impl->from_ssl)) { impl->result = TSI_INTERNAL_ERROR; return impl->result; } else { return TSI_OK; } } *bytes_size = (size_t)bytes_read_from_ssl; return BIO_pending(impl->from_ssl) == 0 ? TSI_OK : TSI_INCOMPLETE_DATA; } static tsi_result ssl_handshaker_get_result(tsi_handshaker *self) { tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self; if ((impl->result == TSI_HANDSHAKE_IN_PROGRESS) && SSL_is_init_finished(impl->ssl)) { impl->result = TSI_OK; } return impl->result; } static tsi_result ssl_handshaker_process_bytes_from_peer( tsi_handshaker *self, const unsigned char *bytes, size_t *bytes_size) { tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self; int bytes_written_into_ssl_size = 0; if (bytes == NULL || bytes_size == 0 || *bytes_size > INT_MAX) { return TSI_INVALID_ARGUMENT; } GPR_ASSERT(*bytes_size <= INT_MAX); bytes_written_into_ssl_size = BIO_write(impl->into_ssl, bytes, (int)*bytes_size); if (bytes_written_into_ssl_size < 0) { gpr_log(GPR_ERROR, "Could not write to memory BIO."); impl->result = TSI_INTERNAL_ERROR; return impl->result; } *bytes_size = (size_t)bytes_written_into_ssl_size; if (!tsi_handshaker_is_in_progress(self)) { impl->result = TSI_OK; return impl->result; } else { /* Get ready to get some bytes from SSL. */ int ssl_result = SSL_do_handshake(impl->ssl); ssl_result = SSL_get_error(impl->ssl, ssl_result); switch (ssl_result) { case SSL_ERROR_WANT_READ: if (BIO_pending(impl->from_ssl) == 0) { /* We need more data. */ return TSI_INCOMPLETE_DATA; } else { return TSI_OK; } case SSL_ERROR_NONE: return TSI_OK; default: { char err_str[256]; ERR_error_string_n(ERR_get_error(), err_str, sizeof(err_str)); gpr_log(GPR_ERROR, "Handshake failed with fatal error %s: %s.", ssl_error_string(ssl_result), err_str); impl->result = TSI_PROTOCOL_FAILURE; return impl->result; } } } } static tsi_result ssl_handshaker_extract_peer(tsi_handshaker *self, tsi_peer *peer) { tsi_result result = TSI_OK; const unsigned char *alpn_selected = NULL; unsigned int alpn_selected_len; tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self; X509 *peer_cert = SSL_get_peer_certificate(impl->ssl); if (peer_cert != NULL) { result = peer_from_x509(peer_cert, 1, peer); X509_free(peer_cert); if (result != TSI_OK) return result; } #if TSI_OPENSSL_ALPN_SUPPORT SSL_get0_alpn_selected(impl->ssl, &alpn_selected, &alpn_selected_len); #endif /* TSI_OPENSSL_ALPN_SUPPORT */ if (alpn_selected == NULL) { /* Try npn. */ SSL_get0_next_proto_negotiated(impl->ssl, &alpn_selected, &alpn_selected_len); } if (alpn_selected != NULL) { size_t i; tsi_peer_property *new_properties = gpr_zalloc(sizeof(*new_properties) * (peer->property_count + 1)); for (i = 0; i < peer->property_count; i++) { new_properties[i] = peer->properties[i]; } result = tsi_construct_string_peer_property( TSI_SSL_ALPN_SELECTED_PROTOCOL, (const char *)alpn_selected, alpn_selected_len, &new_properties[peer->property_count]); if (result != TSI_OK) { gpr_free(new_properties); return result; } if (peer->properties != NULL) gpr_free(peer->properties); peer->property_count++; peer->properties = new_properties; } return result; } static tsi_result ssl_handshaker_create_frame_protector( tsi_handshaker *self, size_t *max_output_protected_frame_size, tsi_frame_protector **protector) { size_t actual_max_output_protected_frame_size = TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND; tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self; tsi_ssl_frame_protector *protector_impl = gpr_zalloc(sizeof(*protector_impl)); if (max_output_protected_frame_size != NULL) { if (*max_output_protected_frame_size > TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND) { *max_output_protected_frame_size = TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND; } else if (*max_output_protected_frame_size < TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND) { *max_output_protected_frame_size = TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND; } actual_max_output_protected_frame_size = *max_output_protected_frame_size; } protector_impl->buffer_size = actual_max_output_protected_frame_size - TSI_SSL_MAX_PROTECTION_OVERHEAD; protector_impl->buffer = gpr_malloc(protector_impl->buffer_size); if (protector_impl->buffer == NULL) { gpr_log(GPR_ERROR, "Could not allocated buffer for tsi_ssl_frame_protector."); gpr_free(protector_impl); return TSI_INTERNAL_ERROR; } /* Transfer ownership of ssl to the frame protector. It is OK as the caller * cannot call anything else but destroy on the handshaker after this call. */ protector_impl->ssl = impl->ssl; impl->ssl = NULL; protector_impl->into_ssl = impl->into_ssl; protector_impl->from_ssl = impl->from_ssl; protector_impl->base.vtable = &frame_protector_vtable; *protector = &protector_impl->base; return TSI_OK; } static void ssl_handshaker_destroy(tsi_handshaker *self) { tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self; SSL_free(impl->ssl); /* The BIO objects are owned by ssl */ gpr_free(impl); } static const tsi_handshaker_vtable handshaker_vtable = { ssl_handshaker_get_bytes_to_send_to_peer, ssl_handshaker_process_bytes_from_peer, ssl_handshaker_get_result, ssl_handshaker_extract_peer, ssl_handshaker_create_frame_protector, ssl_handshaker_destroy, }; /* --- tsi_ssl_handshaker_factory common methods. --- */ static tsi_result create_tsi_ssl_handshaker(SSL_CTX *ctx, int is_client, const char *server_name_indication, tsi_handshaker **handshaker) { SSL *ssl = SSL_new(ctx); BIO *into_ssl = NULL; BIO *from_ssl = NULL; tsi_ssl_handshaker *impl = NULL; *handshaker = NULL; if (ctx == NULL) { gpr_log(GPR_ERROR, "SSL Context is null. Should never happen."); return TSI_INTERNAL_ERROR; } if (ssl == NULL) { return TSI_OUT_OF_RESOURCES; } SSL_set_info_callback(ssl, ssl_info_callback); into_ssl = BIO_new(BIO_s_mem()); from_ssl = BIO_new(BIO_s_mem()); if (into_ssl == NULL || from_ssl == NULL) { gpr_log(GPR_ERROR, "BIO_new failed."); SSL_free(ssl); if (into_ssl != NULL) BIO_free(into_ssl); if (from_ssl != NULL) BIO_free(into_ssl); return TSI_OUT_OF_RESOURCES; } SSL_set_bio(ssl, into_ssl, from_ssl); if (is_client) { int ssl_result; SSL_set_connect_state(ssl); if (server_name_indication != NULL) { if (!SSL_set_tlsext_host_name(ssl, server_name_indication)) { gpr_log(GPR_ERROR, "Invalid server name indication %s.", server_name_indication); SSL_free(ssl); return TSI_INTERNAL_ERROR; } } ssl_result = SSL_do_handshake(ssl); ssl_result = SSL_get_error(ssl, ssl_result); if (ssl_result != SSL_ERROR_WANT_READ) { gpr_log(GPR_ERROR, "Unexpected error received from first SSL_do_handshake call: %s", ssl_error_string(ssl_result)); SSL_free(ssl); return TSI_INTERNAL_ERROR; } } else { SSL_set_accept_state(ssl); } impl = gpr_zalloc(sizeof(*impl)); impl->ssl = ssl; impl->into_ssl = into_ssl; impl->from_ssl = from_ssl; impl->result = TSI_HANDSHAKE_IN_PROGRESS; impl->base.vtable = &handshaker_vtable; *handshaker = &impl->base; return TSI_OK; } static int select_protocol_list(const unsigned char **out, unsigned char *outlen, const unsigned char *client_list, size_t client_list_len, const unsigned char *server_list, size_t server_list_len) { const unsigned char *client_current = client_list; while ((unsigned int)(client_current - client_list) < client_list_len) { unsigned char client_current_len = *(client_current++); const unsigned char *server_current = server_list; while ((server_current >= server_list) && (uintptr_t)(server_current - server_list) < server_list_len) { unsigned char server_current_len = *(server_current++); if ((client_current_len == server_current_len) && !memcmp(client_current, server_current, server_current_len)) { *out = server_current; *outlen = server_current_len; return SSL_TLSEXT_ERR_OK; } server_current += server_current_len; } client_current += client_current_len; } return SSL_TLSEXT_ERR_NOACK; } /* --- tsi_ssl_client_handshaker_factory methods implementation. --- */ tsi_result tsi_ssl_client_handshaker_factory_create_handshaker( tsi_ssl_client_handshaker_factory *self, const char *server_name_indication, tsi_handshaker **handshaker) { return create_tsi_ssl_handshaker(self->ssl_context, 1, server_name_indication, handshaker); } void tsi_ssl_client_handshaker_factory_destroy( tsi_ssl_client_handshaker_factory *self) { if (self->ssl_context != NULL) SSL_CTX_free(self->ssl_context); if (self->alpn_protocol_list != NULL) gpr_free(self->alpn_protocol_list); gpr_free(self); } static int client_handshaker_factory_npn_callback(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { tsi_ssl_client_handshaker_factory *factory = (tsi_ssl_client_handshaker_factory *)arg; return select_protocol_list((const unsigned char **)out, outlen, factory->alpn_protocol_list, factory->alpn_protocol_list_length, in, inlen); } /* --- tsi_ssl_server_handshaker_factory methods implementation. --- */ tsi_result tsi_ssl_server_handshaker_factory_create_handshaker( tsi_ssl_server_handshaker_factory *self, tsi_handshaker **handshaker) { if (self->ssl_context_count == 0) return TSI_INVALID_ARGUMENT; /* Create the handshaker with the first context. We will switch if needed because of SNI in ssl_server_handshaker_factory_servername_callback. */ return create_tsi_ssl_handshaker(self->ssl_contexts[0], 0, NULL, handshaker); } void tsi_ssl_server_handshaker_factory_destroy( tsi_ssl_server_handshaker_factory *self) { size_t i; for (i = 0; i < self->ssl_context_count; i++) { if (self->ssl_contexts[i] != NULL) { SSL_CTX_free(self->ssl_contexts[i]); tsi_peer_destruct(&self->ssl_context_x509_subject_names[i]); } } if (self->ssl_contexts != NULL) gpr_free(self->ssl_contexts); if (self->ssl_context_x509_subject_names != NULL) { gpr_free(self->ssl_context_x509_subject_names); } if (self->alpn_protocol_list != NULL) gpr_free(self->alpn_protocol_list); gpr_free(self); } static int does_entry_match_name(const char *entry, size_t entry_length, const char *name) { const char *dot; const char *name_subdomain = NULL; size_t name_length = strlen(name); size_t name_subdomain_length; if (entry_length == 0) return 0; /* Take care of '.' terminations. */ if (name[name_length - 1] == '.') { name_length--; } if (entry[entry_length - 1] == '.') { entry_length--; if (entry_length == 0) return 0; } if ((name_length == entry_length) && strncmp(name, entry, entry_length) == 0) { return 1; /* Perfect match. */ } if (entry[0] != '*') return 0; /* Wildchar subdomain matching. */ if (entry_length < 3 || entry[1] != '.') { /* At least *.x */ gpr_log(GPR_ERROR, "Invalid wildchar entry."); return 0; } name_subdomain = strchr(name, '.'); if (name_subdomain == NULL) return 0; name_subdomain_length = strlen(name_subdomain); if (name_subdomain_length < 2) return 0; name_subdomain++; /* Starts after the dot. */ name_subdomain_length--; entry += 2; /* Remove *. */ entry_length -= 2; dot = strchr(name_subdomain, '.'); if ((dot == NULL) || (dot == &name_subdomain[name_subdomain_length - 1])) { gpr_log(GPR_ERROR, "Invalid toplevel subdomain: %s", name_subdomain); return 0; } if (name_subdomain[name_subdomain_length - 1] == '.') { name_subdomain_length--; } return ((entry_length > 0) && (name_subdomain_length == entry_length) && strncmp(entry, name_subdomain, entry_length) == 0); } static int ssl_server_handshaker_factory_servername_callback(SSL *ssl, int *ap, void *arg) { tsi_ssl_server_handshaker_factory *impl = (tsi_ssl_server_handshaker_factory *)arg; size_t i = 0; const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); if (servername == NULL || strlen(servername) == 0) { return SSL_TLSEXT_ERR_NOACK; } for (i = 0; i < impl->ssl_context_count; i++) { if (tsi_ssl_peer_matches_name(&impl->ssl_context_x509_subject_names[i], servername)) { SSL_set_SSL_CTX(ssl, impl->ssl_contexts[i]); return SSL_TLSEXT_ERR_OK; } } gpr_log(GPR_ERROR, "No match found for server name: %s.", servername); return SSL_TLSEXT_ERR_ALERT_WARNING; } #if TSI_OPENSSL_ALPN_SUPPORT static int server_handshaker_factory_alpn_callback( SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { tsi_ssl_server_handshaker_factory *factory = (tsi_ssl_server_handshaker_factory *)arg; return select_protocol_list(out, outlen, in, inlen, factory->alpn_protocol_list, factory->alpn_protocol_list_length); } #endif /* TSI_OPENSSL_ALPN_SUPPORT */ static int server_handshaker_factory_npn_advertised_callback( SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg) { tsi_ssl_server_handshaker_factory *factory = (tsi_ssl_server_handshaker_factory *)arg; *out = factory->alpn_protocol_list; GPR_ASSERT(factory->alpn_protocol_list_length <= UINT_MAX); *outlen = (unsigned int)factory->alpn_protocol_list_length; return SSL_TLSEXT_ERR_OK; } /* --- tsi_ssl_handshaker_factory constructors. --- */ tsi_result tsi_create_ssl_client_handshaker_factory( const unsigned char *pem_private_key, size_t pem_private_key_size, const unsigned char *pem_cert_chain, size_t pem_cert_chain_size, const unsigned char *pem_root_certs, size_t pem_root_certs_size, const char *cipher_list, const unsigned char **alpn_protocols, const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols, tsi_ssl_client_handshaker_factory **factory) { SSL_CTX *ssl_context = NULL; tsi_ssl_client_handshaker_factory *impl = NULL; tsi_result result = TSI_OK; gpr_once_init(&init_openssl_once, init_openssl); if (factory == NULL) return TSI_INVALID_ARGUMENT; *factory = NULL; if (pem_root_certs == NULL) return TSI_INVALID_ARGUMENT; ssl_context = SSL_CTX_new(TLSv1_2_method()); if (ssl_context == NULL) { gpr_log(GPR_ERROR, "Could not create ssl context."); return TSI_INVALID_ARGUMENT; } impl = gpr_zalloc(sizeof(*impl)); impl->ssl_context = ssl_context; do { result = populate_ssl_context(ssl_context, pem_private_key, pem_private_key_size, pem_cert_chain, pem_cert_chain_size, cipher_list); if (result != TSI_OK) break; result = ssl_ctx_load_verification_certs(ssl_context, pem_root_certs, pem_root_certs_size, NULL); if (result != TSI_OK) { gpr_log(GPR_ERROR, "Cannot load server root certificates."); break; } if (num_alpn_protocols != 0) { result = build_alpn_protocol_name_list( alpn_protocols, alpn_protocols_lengths, num_alpn_protocols, &impl->alpn_protocol_list, &impl->alpn_protocol_list_length); if (result != TSI_OK) { gpr_log(GPR_ERROR, "Building alpn list failed with error %s.", tsi_result_to_string(result)); break; } #if TSI_OPENSSL_ALPN_SUPPORT GPR_ASSERT(impl->alpn_protocol_list_length < UINT_MAX); if (SSL_CTX_set_alpn_protos( ssl_context, impl->alpn_protocol_list, (unsigned int)impl->alpn_protocol_list_length)) { gpr_log(GPR_ERROR, "Could not set alpn protocol list to context."); result = TSI_INVALID_ARGUMENT; break; } #endif /* TSI_OPENSSL_ALPN_SUPPORT */ SSL_CTX_set_next_proto_select_cb( ssl_context, client_handshaker_factory_npn_callback, impl); } } while (0); if (result != TSI_OK) { tsi_ssl_client_handshaker_factory_destroy(impl); return result; } SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, NULL); /* TODO(jboeuf): Add revocation verification. */ *factory = impl; return TSI_OK; } tsi_result tsi_create_ssl_server_handshaker_factory( const unsigned char **pem_private_keys, const size_t *pem_private_keys_sizes, const unsigned char **pem_cert_chains, const size_t *pem_cert_chains_sizes, size_t key_cert_pair_count, const unsigned char *pem_client_root_certs, size_t pem_client_root_certs_size, int force_client_auth, const char *cipher_list, const unsigned char **alpn_protocols, const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols, tsi_ssl_server_handshaker_factory **factory) { return tsi_create_ssl_server_handshaker_factory_ex( pem_private_keys, pem_private_keys_sizes, pem_cert_chains, pem_cert_chains_sizes, key_cert_pair_count, pem_client_root_certs, pem_client_root_certs_size, force_client_auth ? TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY : TSI_DONT_REQUEST_CLIENT_CERTIFICATE, cipher_list, alpn_protocols, alpn_protocols_lengths, num_alpn_protocols, factory); } tsi_result tsi_create_ssl_server_handshaker_factory_ex( const unsigned char **pem_private_keys, const size_t *pem_private_keys_sizes, const unsigned char **pem_cert_chains, const size_t *pem_cert_chains_sizes, size_t key_cert_pair_count, const unsigned char *pem_client_root_certs, size_t pem_client_root_certs_size, tsi_client_certificate_request_type client_certificate_request, const char *cipher_list, const unsigned char **alpn_protocols, const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols, tsi_ssl_server_handshaker_factory **factory) { tsi_ssl_server_handshaker_factory *impl = NULL; tsi_result result = TSI_OK; size_t i = 0; gpr_once_init(&init_openssl_once, init_openssl); if (factory == NULL) return TSI_INVALID_ARGUMENT; *factory = NULL; if (key_cert_pair_count == 0 || pem_private_keys == NULL || pem_cert_chains == NULL) { return TSI_INVALID_ARGUMENT; } impl = gpr_zalloc(sizeof(*impl)); impl->ssl_contexts = gpr_zalloc(key_cert_pair_count * sizeof(SSL_CTX *)); impl->ssl_context_x509_subject_names = gpr_zalloc(key_cert_pair_count * sizeof(tsi_peer)); if (impl->ssl_contexts == NULL || impl->ssl_context_x509_subject_names == NULL) { tsi_ssl_server_handshaker_factory_destroy(impl); return TSI_OUT_OF_RESOURCES; } impl->ssl_context_count = key_cert_pair_count; if (num_alpn_protocols > 0) { result = build_alpn_protocol_name_list( alpn_protocols, alpn_protocols_lengths, num_alpn_protocols, &impl->alpn_protocol_list, &impl->alpn_protocol_list_length); if (result != TSI_OK) { tsi_ssl_server_handshaker_factory_destroy(impl); return result; } } for (i = 0; i < key_cert_pair_count; i++) { do { impl->ssl_contexts[i] = SSL_CTX_new(TLSv1_2_method()); if (impl->ssl_contexts[i] == NULL) { gpr_log(GPR_ERROR, "Could not create ssl context."); result = TSI_OUT_OF_RESOURCES; break; } result = populate_ssl_context( impl->ssl_contexts[i], pem_private_keys[i], pem_private_keys_sizes[i], pem_cert_chains[i], pem_cert_chains_sizes[i], cipher_list); if (result != TSI_OK) break; if (pem_client_root_certs != NULL) { STACK_OF(X509_NAME) *root_names = NULL; result = ssl_ctx_load_verification_certs( impl->ssl_contexts[i], pem_client_root_certs, pem_client_root_certs_size, &root_names); if (result != TSI_OK) { gpr_log(GPR_ERROR, "Invalid verification certs."); break; } SSL_CTX_set_client_CA_list(impl->ssl_contexts[i], root_names); switch (client_certificate_request) { case TSI_DONT_REQUEST_CLIENT_CERTIFICATE: SSL_CTX_set_verify(impl->ssl_contexts[i], SSL_VERIFY_NONE, NULL); break; case TSI_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: SSL_CTX_set_verify(impl->ssl_contexts[i], SSL_VERIFY_PEER, NullVerifyCallback); break; case TSI_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY: SSL_CTX_set_verify(impl->ssl_contexts[i], SSL_VERIFY_PEER, NULL); break; case TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: SSL_CTX_set_verify( impl->ssl_contexts[i], SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NullVerifyCallback); break; case TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY: SSL_CTX_set_verify( impl->ssl_contexts[i], SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); break; } /* TODO(jboeuf): Add revocation verification. */ } result = extract_x509_subject_names_from_pem_cert( pem_cert_chains[i], pem_cert_chains_sizes[i], &impl->ssl_context_x509_subject_names[i]); if (result != TSI_OK) break; SSL_CTX_set_tlsext_servername_callback( impl->ssl_contexts[i], ssl_server_handshaker_factory_servername_callback); SSL_CTX_set_tlsext_servername_arg(impl->ssl_contexts[i], impl); #if TSI_OPENSSL_ALPN_SUPPORT SSL_CTX_set_alpn_select_cb(impl->ssl_contexts[i], server_handshaker_factory_alpn_callback, impl); #endif /* TSI_OPENSSL_ALPN_SUPPORT */ SSL_CTX_set_next_protos_advertised_cb( impl->ssl_contexts[i], server_handshaker_factory_npn_advertised_callback, impl); } while (0); if (result != TSI_OK) { tsi_ssl_server_handshaker_factory_destroy(impl); return result; } } *factory = impl; return TSI_OK; } /* --- tsi_ssl utils. --- */ int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name) { size_t i = 0; size_t san_count = 0; const tsi_peer_property *cn_property = NULL; int like_ip = looks_like_ip_address(name); /* Check the SAN first. */ for (i = 0; i < peer->property_count; i++) { const tsi_peer_property *property = &peer->properties[i]; if (property->name == NULL) continue; if (strcmp(property->name, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) { san_count++; if (!like_ip && does_entry_match_name(property->value.data, property->value.length, name)) { return 1; } else if (like_ip && strncmp(name, property->value.data, property->value.length) == 0 && strlen(name) == property->value.length) { /* IP Addresses are exact matches only. */ return 1; } } else if (strcmp(property->name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) { cn_property = property; } } /* If there's no SAN, try the CN, but only if its not like an IP Address */ if (san_count == 0 && cn_property != NULL && !like_ip) { if (does_entry_match_name(cn_property->value.data, cn_property->value.length, name)) { return 1; } } return 0; /* Not found. */ } grpc-1.3.2/src/core/tsi/ssl_transport_security.h000066400000000000000000000250201310511640000217710ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_TSI_SSL_TRANSPORT_SECURITY_H #define GRPC_CORE_TSI_SSL_TRANSPORT_SECURITY_H #include "src/core/tsi/transport_security_interface.h" #ifdef __cplusplus extern "C" { #endif /* Value for the TSI_CERTIFICATE_TYPE_PEER_PROPERTY property for X509 certs. */ #define TSI_X509_CERTIFICATE_TYPE "X509" /* This property is of type TSI_PEER_PROPERTY_STRING. */ #define TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY "x509_subject_common_name" #define TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY \ "x509_subject_alternative_name" #define TSI_X509_PEM_CERT_PROPERTY "x509_pem_cert" #define TSI_SSL_ALPN_SELECTED_PROTOCOL "ssl_alpn_selected_protocol" /* --- tsi_ssl_client_handshaker_factory object --- This object creates a client tsi_handshaker objects implemented in terms of the TLS 1.2 specificiation. */ typedef struct tsi_ssl_client_handshaker_factory tsi_ssl_client_handshaker_factory; /* Creates a client handshaker factory. - pem_private_key is the buffer containing the PEM encoding of the client's private key. This parameter can be NULL if the client does not have a private key. - pem_private_key_size is the size of the associated buffer. - pem_cert_chain is the buffer containing the PEM encoding of the client's certificate chain. This parameter can be NULL if the client does not have a certificate chain. - pem_cert_chain_size is the size of the associated buffer. - pem_roots_cert is the buffer containing the PEM encoding of the server root certificates. This parameter cannot be NULL. - pem_roots_cert_size is the size of the associated buffer. - cipher_suites contains an optional list of the ciphers that the client supports. The format of this string is described in: https://www.openssl.org/docs/apps/ciphers.html. This parameter can be set to NULL to use the default set of ciphers. TODO(jboeuf): Revisit the format of this parameter. - alpn_protocols is an array containing the protocol names that the handshakers created with this factory support. This parameter can be NULL. - alpn_protocols_lengths is an array containing the lengths of the alpn protocols specified in alpn_protocols. This parameter can be NULL. - num_alpn_protocols is the number of alpn protocols and associated lengths specified. If this parameter is 0, the other alpn parameters must be NULL. - factory is the address of the factory pointer to be created. - This method returns TSI_OK on success or TSI_INVALID_PARAMETER in the case where a parameter is invalid. */ tsi_result tsi_create_ssl_client_handshaker_factory( const unsigned char *pem_private_key, size_t pem_private_key_size, const unsigned char *pem_cert_chain, size_t pem_cert_chain_size, const unsigned char *pem_root_certs, size_t pem_root_certs_size, const char *cipher_suites, const unsigned char **alpn_protocols, const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols, tsi_ssl_client_handshaker_factory **factory); /* Creates a client handshaker. - self is the factory from which the handshaker will be created. - server_name_indication indicates the name of the server the client is trying to connect to which will be relayed to the server using the SNI extension. - handshaker is the address of the handshaker pointer to be created. - This method returns TSI_OK on success or TSI_INVALID_PARAMETER in the case where a parameter is invalid. */ tsi_result tsi_ssl_client_handshaker_factory_create_handshaker( tsi_ssl_client_handshaker_factory *self, const char *server_name_indication, tsi_handshaker **handshaker); /* Destroys the handshaker factory. WARNING: it is unsafe to destroy a factory while handshakers created with this factory are still in use. */ void tsi_ssl_client_handshaker_factory_destroy( tsi_ssl_client_handshaker_factory *self); /* --- tsi_ssl_server_handshaker_factory object --- This object creates a client tsi_handshaker objects implemented in terms of the TLS 1.2 specificiation. */ typedef struct tsi_ssl_server_handshaker_factory tsi_ssl_server_handshaker_factory; /* Creates a server handshaker factory. - version indicates which version of the specification to use. - pem_private_keys is an array containing the PEM encoding of the server's private keys. This parameter cannot be NULL. The size of the array is given by the key_cert_pair_count parameter. - pem_private_keys_sizes is the array containing the sizes of the associated buffers. - pem_cert_chains is an array containing the PEM encoding of the server's cert chains. This parameter cannot be NULL. The size of the array is given by the key_cert_pair_count parameter. - pem_cert_chains_sizes is the array containing the sizes of the associated buffers. - key_cert_pair_count indicates the number of items in the private_key_files and cert_chain_files parameters. - pem_client_roots is the buffer containing the PEM encoding of the client root certificates. This parameter may be NULL in which case the server will not authenticate the client. If not NULL, the force_client_auth parameter specifies if the server will accept only authenticated clients or both authenticated and non-authenticated clients. - pem_client_root_certs_size is the size of the associated buffer. - force_client_auth, if set to non-zero will force the client to authenticate with an SSL cert. Note that this option is ignored if pem_client_root_certs is NULL or pem_client_roots_certs_size is 0 - cipher_suites contains an optional list of the ciphers that the server supports. The format of this string is described in: https://www.openssl.org/docs/apps/ciphers.html. This parameter can be set to NULL to use the default set of ciphers. TODO(jboeuf): Revisit the format of this parameter. - alpn_protocols is an array containing the protocol names that the handshakers created with this factory support. This parameter can be NULL. - alpn_protocols_lengths is an array containing the lengths of the alpn protocols specified in alpn_protocols. This parameter can be NULL. - num_alpn_protocols is the number of alpn protocols and associated lengths specified. If this parameter is 0, the other alpn parameters must be NULL. - factory is the address of the factory pointer to be created. - This method returns TSI_OK on success or TSI_INVALID_PARAMETER in the case where a parameter is invalid. */ tsi_result tsi_create_ssl_server_handshaker_factory( const unsigned char **pem_private_keys, const size_t *pem_private_keys_sizes, const unsigned char **pem_cert_chains, const size_t *pem_cert_chains_sizes, size_t key_cert_pair_count, const unsigned char *pem_client_root_certs, size_t pem_client_root_certs_size, int force_client_auth, const char *cipher_suites, const unsigned char **alpn_protocols, const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols, tsi_ssl_server_handshaker_factory **factory); /* Same as tsi_create_ssl_server_handshaker_factory method except uses tsi_client_certificate_request_type to support more ways to handle client certificate authentication. - client_certificate_request, if set to non-zero will force the client to authenticate with an SSL cert. Note that this option is ignored if pem_client_root_certs is NULL or pem_client_roots_certs_size is 0 */ tsi_result tsi_create_ssl_server_handshaker_factory_ex( const unsigned char **pem_private_keys, const size_t *pem_private_keys_sizes, const unsigned char **pem_cert_chains, const size_t *pem_cert_chains_sizes, size_t key_cert_pair_count, const unsigned char *pem_client_root_certs, size_t pem_client_root_certs_size, tsi_client_certificate_request_type client_certificate_request, const char *cipher_suites, const unsigned char **alpn_protocols, const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols, tsi_ssl_server_handshaker_factory **factory); /* Creates a server handshaker. - self is the factory from which the handshaker will be created. - handshaker is the address of the handshaker pointer to be created. - This method returns TSI_OK on success or TSI_INVALID_PARAMETER in the case where a parameter is invalid. */ tsi_result tsi_ssl_server_handshaker_factory_create_handshaker( tsi_ssl_server_handshaker_factory *self, tsi_handshaker **handshaker); /* Destroys the handshaker factory. WARNING: it is unsafe to destroy a factory while handshakers created with this factory are still in use. */ void tsi_ssl_server_handshaker_factory_destroy( tsi_ssl_server_handshaker_factory *self); /* Util that checks that an ssl peer matches a specific name. Still TODO(jboeuf): - handle mixed case. - handle %encoded chars. - handle public suffix wildchar more strictly (e.g. *.co.uk) */ int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name); #ifdef __cplusplus } #endif #endif /* GRPC_CORE_TSI_SSL_TRANSPORT_SECURITY_H */ grpc-1.3.2/src/core/tsi/ssl_types.h000066400000000000000000000043011310511640000171510ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_TSI_SSL_TYPES_H #define GRPC_CORE_TSI_SSL_TYPES_H /* A collection of macros to cast between various integer types that are * used differently between BoringSSL and OpenSSL: * TSI_INT_AS_SIZE(x): convert 'int x' to a length parameter for an OpenSSL * function * TSI_SIZE_AS_SIZE(x): convert 'size_t x' to a length parameter for an OpenSSL * function */ #include #ifdef OPENSSL_IS_BORINGSSL #define TSI_INT_AS_SIZE(x) ((size_t)(x)) #define TSI_SIZE_AS_SIZE(x) (x) #else #define TSI_INT_AS_SIZE(x) (x) #define TSI_SIZE_AS_SIZE(x) ((int)(x)) #endif #endif /* GRPC_CORE_TSI_SSL_TYPES_H */ grpc-1.3.2/src/core/tsi/test_creds/000077500000000000000000000000001310511640000171145ustar00rootroot00000000000000grpc-1.3.2/src/core/tsi/test_creds/BUILD000066400000000000000000000031461310511640000177020ustar00rootroot00000000000000# Copyright 2017, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. licenses(["notice"]) # 3-clause BSD exports_files([ "ca.pem", "server1.key", "server1.pem", ]) grpc-1.3.2/src/core/tsi/test_creds/README000066400000000000000000000040311310511640000177720ustar00rootroot00000000000000The test credentials (CONFIRMEDTESTKEY) have been generated with the following commands: Bad credentials (badclient.* / badserver.*): ============================================ These are self-signed certificates: $ openssl req -x509 -newkey rsa:1024 -keyout badserver.key -out badserver.pem \ -days 3650 -nodes When prompted for certificate information, everything is default except the common name which is set to badserver.test.google.com. Valid test credentials: ======================= The ca is self-signed: ---------------------- $ openssl req -x509 -new -newkey rsa:1024 -nodes -out ca.pem -config ca-openssl.cnf -days 3650 -extensions v3_req When prompted for certificate information, everything is default. client is issued by CA: ----------------------- $ openssl genrsa -out client.key.rsa 1024 $ openssl pkcs8 -topk8 -in client.key.rsa -out client.key -nocrypt $ rm client.key.rsa $ openssl req -new -key client.key -out client.csr When prompted for certificate information, everything is default except the common name which is set to testclient. $ openssl ca -in client.csr -out client.pem server0 is issued by CA: ------------------------ $ openssl genrsa -out server0.key.rsa 1024 $ openssl pkcs8 -topk8 -in server0.key.rsa -out server0.key -nocrypt $ rm server0.key.rsa $ openssl req -new -key server0.key -out server0.csr When prompted for certificate information, everything is default except the common name which is set to *.test.google.com.au. $ openssl ca -in server0.csr -out server0.pem server1 is issued by CA with a special config for subject alternative names: ---------------------------------------------------------------------------- $ openssl genrsa -out server1.key.rsa 1024 $ openssl pkcs8 -topk8 -in server1.key.rsa -out server1.key -nocrypt $ rm server1.key.rsa $ openssl req -new -key server1.key -out server1.csr -config server1-openssl.cnf When prompted for certificate information, everything is default except the common name which is set to *.test.google.com. $ openssl ca -in server1.csr -out server1.pem grpc-1.3.2/src/core/tsi/test_creds/badclient.key000066400000000000000000000016241310511640000215560ustar00rootroot00000000000000-----BEGIN PRIVATE KEY----- MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALJfYnFn4nkj52WF E5W2qUxCfjsEFyuXYYKS/07UPWsv3gpZhtjXgdeGL+dpwEBC0IRDBfGnkMp6YY5S O7rnEz0X3r/fvgYy+dEl2jnaA6zgc7RzMGl9U11d56gP9FiDC2190mvP/hpq2xLZ CTbIximpmaoQyxuuH1bbYunesIG/AgMBAAECgYAdqJCEzMIyZE7oaW0tOpcB0BiP FYoIvH4BKRH8eHvR476mt+YdDhBP1scGUmYeCT4Ej+RgHv2LPTgVYwT9eciP2+E/ CBCNRel0Sw9JepwW0r+jWJtDY1pp6YXAgNRGX2UflvUsT+o9lZvagf9moLTMyGvU uLFnsyfLim1B4vXvWQJBANouZllXGZoSrZLtR3VgV4tzRQvJxu84kLeIk64Ov47X pHVBMTRBfzPEhbBodjr1m5OLaVLqkFcXftzRCrbWoKsCQQDRSoLLXOiLrtJ3DLJC rX7Y8wrHZrqk5bMdZLGa/UX8RanhVw3+Xp+urd1711umeNJfzu/MCk4a1KkG/CU0 rqs9AkA4cSx1DD1JSG+yxMNpsAS1xJomFIrsM9vsPt7FdndDwrF+y+CovhDkGYDk RAHh+svGfZg/pQK2JRPimAmHhzqFAkEAu6Ya70s2FUeB3Mu9aJs2CD6hg3dQEVkB 53DI7TX48d9kGW58VX1xnqS02LyWqAPcW5qm1kLHFLdndaPNmBaj4QJBAJugl367 9d9t/QLTSuULLaoYv2vJT3s1y9HN89EoaDDEkPVfQu6GVEXgIBtim1sI/VPSzI8H aXvaTUwblFWSM70= -----END PRIVATE KEY----- grpc-1.3.2/src/core/tsi/test_creds/badclient.pem000066400000000000000000000017151310511640000215500ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIICoDCCAgmgAwIBAgIJANIz2/zoRiapMA0GCSqGSIb3DQEBBQUAMGkxCzAJBgNV BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxIjAgBgNVBAMMGWJhZGNsaWVudC50ZXN0Lmdvb2dsZS5j b20wHhcNMTQwNzI4MjAwODI1WhcNMjQwNzI1MjAwODI1WjBpMQswCQYDVQQGEwJB VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 cyBQdHkgTHRkMSIwIAYDVQQDDBliYWRjbGllbnQudGVzdC5nb29nbGUuY29tMIGf MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyX2JxZ+J5I+dlhROVtqlMQn47BBcr l2GCkv9O1D1rL94KWYbY14HXhi/nacBAQtCEQwXxp5DKemGOUju65xM9F96/374G MvnRJdo52gOs4HO0czBpfVNdXeeoD/RYgwttfdJrz/4aatsS2Qk2yMYpqZmqEMsb rh9W22Lp3rCBvwIDAQABo1AwTjAdBgNVHQ4EFgQU523AJMR8Ds9V8fhf7gu1i0MM UqAwHwYDVR0jBBgwFoAU523AJMR8Ds9V8fhf7gu1i0MMUqAwDAYDVR0TBAUwAwEB /zANBgkqhkiG9w0BAQUFAAOBgQCI/tvSBYH1iyfLaCTBKwpdj36+MkR9EeJJmImx X+bjhKWXwsBX4PDMWvdusr++QGUYtyoya+hfYMXRhXua39mD54xgloQNuu9REDwX Ffto+aOw3BcYducz6ofxicFK/Y2VeXDurSMpRv5TfGf2Qr6eOOdaRhj6ed7BibHk X1VGZA== -----END CERTIFICATE----- grpc-1.3.2/src/core/tsi/test_creds/badserver.key000066400000000000000000000016241310511640000216060ustar00rootroot00000000000000-----BEGIN PRIVATE KEY----- MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKeZ1e1y29cmBKaW oIUwJ5neOJUjx+eD/3nRPe+dvLXEd9+db0fG5RYRR0S3mF1Ywuj4PIxlTW2YprUS oGSw+tcqWNIzxv94HjwYFkkvER3AblXcDBh0P2zAkzg+nf9AcAsMh0QpDTyrXtMl gqryjq1/vkhFofKMMbY+aXJdG6OBAgMBAAECgYAAgaB51S0A22aMMkxN2rVj6530 JWWHN4jgD1fGj41wZyWNkWYyq1Ep3ed/N6bIMWp1VbqpGe0/9YQba/D8HOTFHGRt 72YXnP1e/ds8cxU4x4j1vvqSPtXpMmkiXfXijOvCl9mrMH2xjghFAt6/1Nb9xo1m VdcOB8OdSuOIw6CI+QJBAN5FZUbS+bRXDWII/FaAih1DBpwCxhYEN+TXPJBxSen6 kOzGt5g+mB6YqRMZ/qshshwPq7bsgFGfJ2lIdS2t3GsCQQDBCKifV5AAkOdOUrkK HvoX3qnVmyIA8CyvWLcIWpfZ76QAYh0q0StedKdOMXaB1jTeSJ2KU1nlss7UD1Yw VbrDAkAwjMHpbW3jiVw//Kx5jIwehiRscWKpLnSzBJyTBFvbwsJjJai2lX2OuVO8 +2GYKb0Iyhd81j3VFkl6grwtpRtPAkB7+n+yt555fpfRKjhGU9b09cHGu7h/OcK5 bBVCfE0DYHLI/DsXgPiF1g6Onh4rDdUu3xyv9xDKAqnscV099hHZAkEAvcFBfXZs tk18N+bUcvXTdZjzZbfLCHlJmwPIspZ8G/6Pn63deg4GVYoCvTwGruah+8y734Ph 7PskfPgUQlB7Ag== -----END PRIVATE KEY----- grpc-1.3.2/src/core/tsi/test_creds/badserver.pem000066400000000000000000000017151310511640000216000ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIICoDCCAgmgAwIBAgIJAPdqwqsKNy81MA0GCSqGSIb3DQEBBQUAMGkxCzAJBgNV BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxIjAgBgNVBAMMGWJhZHNlcnZlci50ZXN0Lmdvb2dsZS5j b20wHhcNMTQwNzI4MjAwODU0WhcNMjQwNzI1MjAwODU0WjBpMQswCQYDVQQGEwJB VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 cyBQdHkgTHRkMSIwIAYDVQQDDBliYWRzZXJ2ZXIudGVzdC5nb29nbGUuY29tMIGf MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnmdXtctvXJgSmlqCFMCeZ3jiVI8fn g/950T3vnby1xHffnW9HxuUWEUdEt5hdWMLo+DyMZU1tmKa1EqBksPrXKljSM8b/ eB48GBZJLxEdwG5V3AwYdD9swJM4Pp3/QHALDIdEKQ08q17TJYKq8o6tf75IRaHy jDG2PmlyXRujgQIDAQABo1AwTjAdBgNVHQ4EFgQU3u/qvHr9knMBeZyAD7mAA/ec 8cUwHwYDVR0jBBgwFoAU3u/qvHr9knMBeZyAD7mAA/ec8cUwDAYDVR0TBAUwAwEB /zANBgkqhkiG9w0BAQUFAAOBgQA/FmR1SGLguxCCfhp4CYCbrAePSyPWDi48gTwj vVZf/OMxdVu/H8sBYFf27BjbrEugAw16DElFtgTZ83pLb2BvkUgb6vBUK5sEkgmh z88zBsgDp8aCf4STDOLFZMBh/E9ZKkm1zogbEmlTjFp/ceSpa2gNv7OuN4WiorOh Wvw40g== -----END CERTIFICATE----- grpc-1.3.2/src/core/tsi/test_creds/ca-openssl.cnf000066400000000000000000000010351310511640000216470ustar00rootroot00000000000000[req] distinguished_name = req_distinguished_name req_extensions = v3_req [req_distinguished_name] countryName = Country Name (2 letter code) countryName_default = AU stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = Some-State organizationName = Organization Name (eg, company) organizationName_default = Internet Widgits Pty Ltd commonName = Common Name (eg, YOUR name) commonName_default = testca [v3_req] basicConstraints = CA:true keyUsage = critical, keyCertSign grpc-1.3.2/src/core/tsi/test_creds/ca.key000066400000000000000000000016201310511640000202100ustar00rootroot00000000000000-----BEGIN PRIVATE KEY----- MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMBA3wVeTGHZR1Ry e/i+J8a2cu5gXwFV6TnObzGM7bLFCO5i9v4mLo4iFzPsHmWDUxKS3Y8iXbu0eYBl LoNY0lSvxDx33O+DuwMmVN+DzSD+Eod9zfvwOWHsazYCZT2PhNxnVWIuJXViY4JA HUGodjx+QAi6yCAurUZGvYXGgZSBAgMBAAECgYAxRi8i9BlFlufGSBVoGmydbJOm bwLKl9dP3o33ODSP9hok5y6A0w5plWk3AJSF1hPLleK9VcSKYGYnt0clmPVHF35g bx2rVK8dOT0mn7rz9Zr70jcSz1ETA2QonHZ+Y+niLmcic9At6hRtWiewblUmyFQm GwggIzi7LOyEUHrEcQJBAOXxyQvnLvtKzXiqcsW/K6rExqVJVk+KF0fzzVyMzTJx HRBxUVgvGdEJT7j+7P2kcTyafve0BBzDSPIaDyiJ+Y0CQQDWCb7jASFSbu5M3Zcd Gkr4ZKN1XO3VLQX10b22bQYdF45hrTN2tnzRvVUR4q86VVnXmiGiTqmLkXcA2WWf pHfFAkAhv9olUBo6MeF0i3frBEMRfm41hk0PwZHnMqZ6pgPcGnQMnMU2rzsXzkkQ OwJnvAIOxhJKovZTjmofdqmw5odlAkBYVUdRWjsNUTjJwj3GRf6gyq/nFMYWz3EB RWFdM1ttkDYzu45ctO2IhfHg4sPceDMO1s6AtKQmNI9/azkUjITdAkApNa9yFRzc TBaDNPd5KVd58LVIzoPQ6i7uMHteLXJUWqSroji6S3s4gKMFJ/dO+ZXIlgQgfJJJ ZDL4cdrdkeoM -----END PRIVATE KEY----- grpc-1.3.2/src/core/tsi/test_creds/ca.pem000066400000000000000000000015271310511640000202070ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIICSjCCAbOgAwIBAgIJAJHGGR4dGioHMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnRlc3RjYTAeFw0xNDExMTEyMjMxMjla Fw0yNDExMDgyMjMxMjlaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0 YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDzANBgNVBAMT BnRlc3RjYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwEDfBV5MYdlHVHJ7 +L4nxrZy7mBfAVXpOc5vMYztssUI7mL2/iYujiIXM+weZYNTEpLdjyJdu7R5gGUu g1jSVK/EPHfc74O7AyZU34PNIP4Sh33N+/A5YexrNgJlPY+E3GdVYi4ldWJjgkAd Qah2PH5ACLrIIC6tRka9hcaBlIECAwEAAaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNV HQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADgYEAHzC7jdYlzAVmddi/gdAeKPau sPBG/C2HCWqHzpCUHcKuvMzDVkY/MP2o6JIW2DBbY64bO/FceExhjcykgaYtCH/m oIU63+CFOTtR7otyQAWHqXa7q4SbCDlG7DyRFxqG0txPtGvy12lgldA2+RgcigQG Dfcog5wrJytaQ6UA0wE= -----END CERTIFICATE----- grpc-1.3.2/src/core/tsi/test_creds/client.key000066400000000000000000000016301310511640000211040ustar00rootroot00000000000000-----BEGIN PRIVATE KEY----- MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAOxUR9uhvhbeVUIM s5WbH0px0mehl2+6sZpNjzvE2KimZpHzMJHukVH0Ffkvhs0b8+S5Ut9VNUAqd3IM JCCAEGtRNoQhM1t9Yr2zAckSvbRacp+FL/Cj9eDmyo00KsVGaeefA4Dh4OW+ZhkT NKcldXqkSuj1sEf244JZYuqZp6/tAgMBAAECgYEAi2NSVqpZMafE5YYUTcMGe6QS k2jtpsqYgggI2RnLJ/2tNZwYI5pwP8QVSbnMaiF4gokD5hGdrNDfTnb2v+yIwYEH 0w8+oG7Z81KodsiZSIDJfTGsAZhVNwOz9y0VD8BBZZ1/274Zh52AUKLjZS/ZwIbS W2ywya855dPnH/wj+0ECQQD9X8D920kByTNHhBG18biAEZ4pxs9f0OAG8333eVcI w2lJDLsYDZrCB2ocgA3lUdozlzPC7YDYw8reg0tkiRY5AkEA7sdNzOeQsQRn7++5 0bP9DtT/iON1gbfxRzCfCfXdoOtfQWIzTePWtURt9X/5D9NofI0Rg5W2oGy/MLe5 /sXHVQJBAIup5XrJDkQywNZyAUU2ecn2bCWBFjwtqd+LBmuMciI9fOKsZtEKZrz/ U0lkeMRoSwvXE8wmGLjjrAbdfohrXFkCQQDZEx/LtIl6JINJQiswVe0tWr6k+ASP 1WXoTm+HYpoF/XUvv9LccNF1IazFj34hwRQwhx7w/V52Ieb+p0jUMYGxAkEAjDhd 9pBO1fKXWiXzi9ZKfoyTNcUq3eBSVKwPG2nItg5ycXengjT5sgcWDnciIzW7BIVI JiqOszq9GWESErAatg== -----END PRIVATE KEY----- grpc-1.3.2/src/core/tsi/test_creds/client.pem000066400000000000000000000014361310511640000211010ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIICHzCCAYgCAQEwDQYJKoZIhvcNAQEFBQAwVjELMAkGA1UEBhMCQVUxEzARBgNV BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0 ZDEPMA0GA1UEAwwGdGVzdGNhMB4XDTE0MDcxNzIzNTYwMloXDTI0MDcxNDIzNTYw MlowWjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDETMBEGA1UEAwwKdGVzdGNsaWVudDCB nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA7FRH26G+Ft5VQgyzlZsfSnHSZ6GX b7qxmk2PO8TYqKZmkfMwke6RUfQV+S+GzRvz5LlS31U1QCp3cgwkIIAQa1E2hCEz W31ivbMByRK9tFpyn4Uv8KP14ObKjTQqxUZp558DgOHg5b5mGRM0pyV1eqRK6PWw R/bjglli6pmnr+0CAwEAATANBgkqhkiG9w0BAQUFAAOBgQAStSm5PM7ubROiKK6/ T2FkKlhiTOx+Ryenm3Eio59emq+jXl+1nhPySX5G2PQzSR5vd1dIhwgZSR4Gyttk tRZ57k/NI1brUW8joiEOMJA/Mr7H7asx7wIRYDE91Fs8GkKWd5LhoPAQj+qdG35C OO+svdkmqH0KZo320ZUqdl2ooQ== -----END CERTIFICATE----- grpc-1.3.2/src/core/tsi/test_creds/server0.key000066400000000000000000000016241310511640000212170ustar00rootroot00000000000000-----BEGIN PRIVATE KEY----- MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANOmffupIGC8YDau rOF4eKnHwPszgpkkhWzKsVxhNDBxCVYx4TEjG0XWIO0iyRXupZbUC+7N/8HnEVNa 8F1jYhng14Iiq99cNQbbnuHHhIztmpocrJTxmnhGzoAnRa1Tb+GnAuRoIHRA/V2c VUE9tbikQugFx/SPgXAw6tfWB+YvAgMBAAECgYEAoEq9qzUBgoHoVEGiSPiWWe8g 5p6yUA1qx2QTQyWTAwT4z0DjjfVKmG99bFsl8+hTnJFnoCp/gnjflEOROwkjp5kG m0drqOPx1jeipJjpXYTBu49h+WpZ1PF+KhVtxsIm3OOCvh67iWaKyyOVb5Og8aiR jl6dn/TdG/dlGD8AfUECQQDuNMle6p0oU8amC6O9wIMBroxx2nFstzE6O35PLEzG /tj0kxxn9Jp2TS9mGaLCzSuXmpjlF4+NOWiBPkrLC2TfAkEA43Xg7uEUkaJAz2/W m1lIBTLt+4rIQY/2emh33bDcA+rv8rwwrMMIv17/xPx7bs49YqGG5xufD+Rwl6TL qFXYsQJAPrOwagax1aKvwJeBw3oAQhoTKAkLIEXcdGqipe6QSzVcIIz0xjxxyEAr AOIwoLxnBCISqwMXq2H4K0UdZPMb2wJAdhdYLY1L6YRMk6XjzImg25oidisKZweA FvMv8DgHMj2CUAqmVrt3SivfLH1M9C09L3zfFhOAFHcsgX58gav4MQJBANSBnrHj tIq4l8z79CPUIuu3QyeEh+XwY8s5qE5CNTck0U59lzp9NvENHbkx3KO896TTerko +8bXHMLkJkHPXms= -----END PRIVATE KEY----- grpc-1.3.2/src/core/tsi/test_creds/server0.pem000066400000000000000000000014321310511640000212050ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIICHDCCAYUCAQQwDQYJKoZIhvcNAQEFBQAwVjELMAkGA1UEBhMCQVUxEzARBgNV BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0 ZDEPMA0GA1UEAwwGdGVzdGNhMB4XDTE0MDcyMjE3NTk0OVoXDTI0MDcxOTE3NTk0 OVowVzELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxFDASBgNVBAoM C0dvb2dsZSBJbmMuMR0wGwYDVQQDDBQqLnRlc3QuZ29vZ2xlLmNvbS5hdTCBnzAN BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA06Z9+6kgYLxgNq6s4Xh4qcfA+zOCmSSF bMqxXGE0MHEJVjHhMSMbRdYg7SLJFe6lltQL7s3/wecRU1rwXWNiGeDXgiKr31w1 Btue4ceEjO2amhyslPGaeEbOgCdFrVNv4acC5GggdED9XZxVQT21uKRC6AXH9I+B cDDq19YH5i8CAwEAATANBgkqhkiG9w0BAQUFAAOBgQBtfR5qXG9TTI8YcYh7sA4V GeNoplp0x6p7OG0NLvbJqAkUnkvjIkk1m1R2AUHhbkxzx6G75JIOoNJcWrCzywBA BIsaTdmnNysf/s1hQJuD3IHiVb+7Ji0jhttnJlYcMid4o0tJO/a2E9YUxR+9cg0i obb+Ql3qsvKdWBC1dDLDLw== -----END CERTIFICATE----- grpc-1.3.2/src/core/tsi/test_creds/server1-openssl.cnf000066400000000000000000000014261310511640000226570ustar00rootroot00000000000000[req] distinguished_name = req_distinguished_name req_extensions = v3_req [req_distinguished_name] countryName = Country Name (2 letter code) countryName_default = US stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = Illinois localityName = Locality Name (eg, city) localityName_default = Chicago organizationName = Organization Name (eg, company) organizationName_default = Example, Co. commonName = Common Name (eg, YOUR name) commonName_max = 64 [v3_req] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName = @alt_names [alt_names] DNS.1 = *.test.google.fr DNS.2 = waterzooi.test.google.be DNS.3 = *.test.youtube.com IP.1 = "192.168.1.3" grpc-1.3.2/src/core/tsi/test_creds/server1.key000066400000000000000000000016201310511640000212140ustar00rootroot00000000000000-----BEGIN PRIVATE KEY----- MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOHDFScoLCVJpYDD M4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1BgzkWF+slf 3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd9N8YwbBY AckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAECgYAn7qGnM2vbjJNBm0VZCkOkTIWm V10okw7EPJrdL2mkre9NasghNXbE1y5zDshx5Nt3KsazKOxTT8d0Jwh/3KbaN+YY tTCbKGW0pXDRBhwUHRcuRzScjli8Rih5UOCiZkhefUTcRb6xIhZJuQy71tjaSy0p dHZRmYyBYO2YEQ8xoQJBAPrJPhMBkzmEYFtyIEqAxQ/o/A6E+E4w8i+KM7nQCK7q K4JXzyXVAjLfyBZWHGM2uro/fjqPggGD6QH1qXCkI4MCQQDmdKeb2TrKRh5BY1LR 81aJGKcJ2XbcDu6wMZK4oqWbTX2KiYn9GB0woM6nSr/Y6iy1u145YzYxEV/iMwff DJULAkB8B2MnyzOg0pNFJqBJuH29bKCcHa8gHJzqXhNO5lAlEbMK95p/P2Wi+4Hd aiEIAF1BF326QJcvYKmwSmrORp85AkAlSNxRJ50OWrfMZnBgzVjDx3xG6KsFQVk2 ol6VhqL6dFgKUORFUWBvnKSyhjJxurlPEahV6oo6+A+mPhFY8eUvAkAZQyTdupP3 XEFQKctGz+9+gKkemDp7LBBMEMBXrGTLPhpEfcjv/7KPdnFHYmhYeBTBnuVmTVWe F98XJ7tIFfJq -----END PRIVATE KEY----- grpc-1.3.2/src/core/tsi/test_creds/server1.pem000066400000000000000000000017041310511640000212100ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50 ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd 9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6 hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8 -----END CERTIFICATE----- grpc-1.3.2/src/core/tsi/transport_security.c000066400000000000000000000231541310511640000211110ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/tsi/transport_security.h" #include #include #include #include /* --- Tracing. --- */ int tsi_tracing_enabled = 0; /* --- tsi_result common implementation. --- */ const char *tsi_result_to_string(tsi_result result) { switch (result) { case TSI_OK: return "TSI_OK"; case TSI_UNKNOWN_ERROR: return "TSI_UNKNOWN_ERROR"; case TSI_INVALID_ARGUMENT: return "TSI_INVALID_ARGUMENT"; case TSI_PERMISSION_DENIED: return "TSI_PERMISSION_DENIED"; case TSI_INCOMPLETE_DATA: return "TSI_INCOMPLETE_DATA"; case TSI_FAILED_PRECONDITION: return "TSI_FAILED_PRECONDITION"; case TSI_UNIMPLEMENTED: return "TSI_UNIMPLEMENTED"; case TSI_INTERNAL_ERROR: return "TSI_INTERNAL_ERROR"; case TSI_DATA_CORRUPTED: return "TSI_DATA_CORRUPTED"; case TSI_NOT_FOUND: return "TSI_NOT_FOUND"; case TSI_PROTOCOL_FAILURE: return "TSI_PROTOCOL_FAILURE"; case TSI_HANDSHAKE_IN_PROGRESS: return "TSI_HANDSHAKE_IN_PROGRESS"; case TSI_OUT_OF_RESOURCES: return "TSI_OUT_OF_RESOURCES"; default: return "UNKNOWN"; } } /* --- tsi_frame_protector common implementation. --- Calls specific implementation after state/input validation. */ tsi_result tsi_frame_protector_protect(tsi_frame_protector *self, const unsigned char *unprotected_bytes, size_t *unprotected_bytes_size, unsigned char *protected_output_frames, size_t *protected_output_frames_size) { if (self == NULL || unprotected_bytes == NULL || unprotected_bytes_size == NULL || protected_output_frames == NULL || protected_output_frames_size == NULL) { return TSI_INVALID_ARGUMENT; } return self->vtable->protect(self, unprotected_bytes, unprotected_bytes_size, protected_output_frames, protected_output_frames_size); } tsi_result tsi_frame_protector_protect_flush( tsi_frame_protector *self, unsigned char *protected_output_frames, size_t *protected_output_frames_size, size_t *still_pending_size) { if (self == NULL || protected_output_frames == NULL || protected_output_frames_size == NULL || still_pending_size == NULL) { return TSI_INVALID_ARGUMENT; } return self->vtable->protect_flush(self, protected_output_frames, protected_output_frames_size, still_pending_size); } tsi_result tsi_frame_protector_unprotect( tsi_frame_protector *self, const unsigned char *protected_frames_bytes, size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes, size_t *unprotected_bytes_size) { if (self == NULL || protected_frames_bytes == NULL || protected_frames_bytes_size == NULL || unprotected_bytes == NULL || unprotected_bytes_size == NULL) { return TSI_INVALID_ARGUMENT; } return self->vtable->unprotect(self, protected_frames_bytes, protected_frames_bytes_size, unprotected_bytes, unprotected_bytes_size); } void tsi_frame_protector_destroy(tsi_frame_protector *self) { if (self == NULL) return; self->vtable->destroy(self); } /* --- tsi_handshaker common implementation. --- Calls specific implementation after state/input validation. */ tsi_result tsi_handshaker_get_bytes_to_send_to_peer(tsi_handshaker *self, unsigned char *bytes, size_t *bytes_size) { if (self == NULL || bytes == NULL || bytes_size == NULL) { return TSI_INVALID_ARGUMENT; } if (self->frame_protector_created) return TSI_FAILED_PRECONDITION; return self->vtable->get_bytes_to_send_to_peer(self, bytes, bytes_size); } tsi_result tsi_handshaker_process_bytes_from_peer(tsi_handshaker *self, const unsigned char *bytes, size_t *bytes_size) { if (self == NULL || bytes == NULL || bytes_size == NULL) { return TSI_INVALID_ARGUMENT; } if (self->frame_protector_created) return TSI_FAILED_PRECONDITION; return self->vtable->process_bytes_from_peer(self, bytes, bytes_size); } tsi_result tsi_handshaker_get_result(tsi_handshaker *self) { if (self == NULL) return TSI_INVALID_ARGUMENT; if (self->frame_protector_created) return TSI_FAILED_PRECONDITION; return self->vtable->get_result(self); } tsi_result tsi_handshaker_extract_peer(tsi_handshaker *self, tsi_peer *peer) { if (self == NULL || peer == NULL) return TSI_INVALID_ARGUMENT; memset(peer, 0, sizeof(tsi_peer)); if (self->frame_protector_created) return TSI_FAILED_PRECONDITION; if (tsi_handshaker_get_result(self) != TSI_OK) { return TSI_FAILED_PRECONDITION; } return self->vtable->extract_peer(self, peer); } tsi_result tsi_handshaker_create_frame_protector( tsi_handshaker *self, size_t *max_protected_frame_size, tsi_frame_protector **protector) { tsi_result result; if (self == NULL || protector == NULL) return TSI_INVALID_ARGUMENT; if (self->frame_protector_created) return TSI_FAILED_PRECONDITION; if (tsi_handshaker_get_result(self) != TSI_OK) { return TSI_FAILED_PRECONDITION; } result = self->vtable->create_frame_protector(self, max_protected_frame_size, protector); if (result == TSI_OK) { self->frame_protector_created = 1; } return result; } void tsi_handshaker_destroy(tsi_handshaker *self) { if (self == NULL) return; self->vtable->destroy(self); } /* --- tsi_peer implementation. --- */ tsi_peer_property tsi_init_peer_property(void) { tsi_peer_property property; memset(&property, 0, sizeof(tsi_peer_property)); return property; } static void tsi_peer_destroy_list_property(tsi_peer_property *children, size_t child_count) { size_t i; for (i = 0; i < child_count; i++) { tsi_peer_property_destruct(&children[i]); } gpr_free(children); } void tsi_peer_property_destruct(tsi_peer_property *property) { if (property->name != NULL) { gpr_free(property->name); } if (property->value.data != NULL) { gpr_free(property->value.data); } *property = tsi_init_peer_property(); /* Reset everything to 0. */ } void tsi_peer_destruct(tsi_peer *self) { if (self == NULL) return; if (self->properties != NULL) { tsi_peer_destroy_list_property(self->properties, self->property_count); self->properties = NULL; } self->property_count = 0; } tsi_result tsi_construct_allocated_string_peer_property( const char *name, size_t value_length, tsi_peer_property *property) { *property = tsi_init_peer_property(); if (name != NULL) property->name = gpr_strdup(name); if (value_length > 0) { property->value.data = gpr_zalloc(value_length); property->value.length = value_length; } return TSI_OK; } tsi_result tsi_construct_string_peer_property_from_cstring( const char *name, const char *value, tsi_peer_property *property) { return tsi_construct_string_peer_property(name, value, strlen(value), property); } tsi_result tsi_construct_string_peer_property(const char *name, const char *value, size_t value_length, tsi_peer_property *property) { tsi_result result = tsi_construct_allocated_string_peer_property( name, value_length, property); if (result != TSI_OK) return result; if (value_length > 0) { memcpy(property->value.data, value, value_length); } return TSI_OK; } tsi_result tsi_construct_peer(size_t property_count, tsi_peer *peer) { memset(peer, 0, sizeof(tsi_peer)); if (property_count > 0) { peer->properties = gpr_zalloc(property_count * sizeof(tsi_peer_property)); peer->property_count = property_count; } return TSI_OK; } grpc-1.3.2/src/core/tsi/transport_security.h000066400000000000000000000113601310511640000211120ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_TSI_TRANSPORT_SECURITY_H #define GRPC_CORE_TSI_TRANSPORT_SECURITY_H #include "src/core/tsi/transport_security_interface.h" #ifdef __cplusplus extern "C" { #endif extern int tsi_tracing_enabled; /* Base for tsi_frame_protector implementations. See transport_security_interface.h for documentation. */ typedef struct { tsi_result (*protect)(tsi_frame_protector *self, const unsigned char *unprotected_bytes, size_t *unprotected_bytes_size, unsigned char *protected_output_frames, size_t *protected_output_frames_size); tsi_result (*protect_flush)(tsi_frame_protector *self, unsigned char *protected_output_frames, size_t *protected_output_frames_size, size_t *still_pending_size); tsi_result (*unprotect)(tsi_frame_protector *self, const unsigned char *protected_frames_bytes, size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes, size_t *unprotected_bytes_size); void (*destroy)(tsi_frame_protector *self); } tsi_frame_protector_vtable; struct tsi_frame_protector { const tsi_frame_protector_vtable *vtable; }; /* Base for tsi_handshaker implementations. See transport_security_interface.h for documentation. */ typedef struct { tsi_result (*get_bytes_to_send_to_peer)(tsi_handshaker *self, unsigned char *bytes, size_t *bytes_size); tsi_result (*process_bytes_from_peer)(tsi_handshaker *self, const unsigned char *bytes, size_t *bytes_size); tsi_result (*get_result)(tsi_handshaker *self); tsi_result (*extract_peer)(tsi_handshaker *self, tsi_peer *peer); tsi_result (*create_frame_protector)(tsi_handshaker *self, size_t *max_protected_frame_size, tsi_frame_protector **protector); void (*destroy)(tsi_handshaker *self); } tsi_handshaker_vtable; struct tsi_handshaker { const tsi_handshaker_vtable *vtable; int frame_protector_created; }; /* Peer and property construction/destruction functions. */ tsi_result tsi_construct_peer(size_t property_count, tsi_peer *peer); tsi_peer_property tsi_init_peer_property(void); void tsi_peer_property_destruct(tsi_peer_property *property); tsi_result tsi_construct_string_peer_property(const char *name, const char *value, size_t value_length, tsi_peer_property *property); tsi_result tsi_construct_allocated_string_peer_property( const char *name, size_t value_length, tsi_peer_property *property); tsi_result tsi_construct_string_peer_property_from_cstring( const char *name, const char *value, tsi_peer_property *property); /* Utils. */ char *tsi_strdup(const char *src); /* Sadly, no strdup in C89. */ #ifdef __cplusplus } #endif #endif /* GRPC_CORE_TSI_TRANSPORT_SECURITY_H */ grpc-1.3.2/src/core/tsi/transport_security_interface.h000066400000000000000000000361031310511640000231340ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_CORE_TSI_TRANSPORT_SECURITY_INTERFACE_H #define GRPC_CORE_TSI_TRANSPORT_SECURITY_INTERFACE_H #include #include #ifdef __cplusplus extern "C" { #endif /* --- tsi result --- */ typedef enum { TSI_OK = 0, TSI_UNKNOWN_ERROR = 1, TSI_INVALID_ARGUMENT = 2, TSI_PERMISSION_DENIED = 3, TSI_INCOMPLETE_DATA = 4, TSI_FAILED_PRECONDITION = 5, TSI_UNIMPLEMENTED = 6, TSI_INTERNAL_ERROR = 7, TSI_DATA_CORRUPTED = 8, TSI_NOT_FOUND = 9, TSI_PROTOCOL_FAILURE = 10, TSI_HANDSHAKE_IN_PROGRESS = 11, TSI_OUT_OF_RESOURCES = 12 } tsi_result; typedef enum { // Default option TSI_DONT_REQUEST_CLIENT_CERTIFICATE, TSI_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY, TSI_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY, TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY, TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY, } tsi_client_certificate_request_type; const char *tsi_result_to_string(tsi_result result); /* --- tsi tracing --- */ /* Set this early to avoid races */ extern int tsi_tracing_enabled; /* --- tsi_frame_protector object --- This object protects and unprotects buffers once the handshake is done. Implementations of this object must be thread compatible. */ typedef struct tsi_frame_protector tsi_frame_protector; /* Outputs protected frames. - unprotected_bytes is an input only parameter and points to the data to be protected. - unprotected_bytes_size is an input/output parameter used by the caller to specify how many bytes are available in unprotected_bytes. The output value is the number of bytes consumed during the call. - protected_output_frames points to a buffer allocated by the caller that will be written. - protected_output_frames_size is an input/output parameter used by the caller to specify how many bytes are available in protected_output_frames. As an output, this value indicates the number of bytes written. - This method returns TSI_OK in case of success or a specific error code in case of failure. Note that even if all the input unprotected bytes are consumed, they may not have been processed into the returned protected output frames. The caller should call the protect_flush method to make sure that there are no more protected bytes buffered in the protector. A typical way to call this method would be: ------------------------------------------------------------------------ unsigned char protected_buffer[4096]; size_t protected_buffer_size = sizeof(protected_buffer); tsi_result result = TSI_OK; while (message_size > 0) { size_t protected_buffer_size_to_send = protected_buffer_size; size_t processed_message_size = message_size; result = tsi_frame_protector_protect(protector, message_bytes, &processed_message_size, protected_buffer, &protected_buffer_size_to_send); if (result != TSI_OK) break; send_bytes_to_peer(protected_buffer, protected_buffer_size_to_send); message_bytes += processed_message_size; message_size -= processed_message_size; // Don't forget to flush. if (message_size == 0) { size_t still_pending_size; do { protected_buffer_size_to_send = protected_buffer_size; result = tsi_frame_protector_protect_flush( protector, protected_buffer, &protected_buffer_size_to_send, &still_pending_size); if (result != TSI_OK) break; send_bytes_to_peer(protected_buffer, protected_buffer_size_to_send); } while (still_pending_size > 0); } } if (result != TSI_OK) HandleError(result); ------------------------------------------------------------------------ */ tsi_result tsi_frame_protector_protect(tsi_frame_protector *self, const unsigned char *unprotected_bytes, size_t *unprotected_bytes_size, unsigned char *protected_output_frames, size_t *protected_output_frames_size); /* Indicates that we need to flush the bytes buffered in the protector and get the resulting frame. - protected_output_frames points to a buffer allocated by the caller that will be written. - protected_output_frames_size is an input/output parameter used by the caller to specify how many bytes are available in protected_output_frames. - still_pending_bytes is an output parameter indicating the number of bytes that still need to be flushed from the protector.*/ tsi_result tsi_frame_protector_protect_flush( tsi_frame_protector *self, unsigned char *protected_output_frames, size_t *protected_output_frames_size, size_t *still_pending_size); /* Outputs unprotected bytes. - protected_frames_bytes is an input only parameter and points to the protected frames to be unprotected. - protected_frames_bytes_size is an input/output only parameter used by the caller to specify how many bytes are available in protected_bytes. The output value is the number of bytes consumed during the call. Implementations will buffer up to a frame of protected data. - unprotected_bytes points to a buffer allocated by the caller that will be written. - unprotected_bytes_size is an input/output parameter used by the caller to specify how many bytes are available in unprotected_bytes. This value is expected to be at most max_protected_frame_size minus overhead which means that max_protected_frame_size is a safe bet. The output value is the number of bytes actually written. If *unprotected_bytes_size is unchanged, there may be more data remaining to unprotect, and the caller should call this function again. - This method returns TSI_OK in case of success. Success includes cases where there is not enough data to output a frame in which case unprotected_bytes_size will be set to 0 and cases where the internal buffer needs to be read before new protected data can be processed in which case protected_frames_size will be set to 0. */ tsi_result tsi_frame_protector_unprotect( tsi_frame_protector *self, const unsigned char *protected_frames_bytes, size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes, size_t *unprotected_bytes_size); /* Destroys the tsi_frame_protector object. */ void tsi_frame_protector_destroy(tsi_frame_protector *self); /* --- tsi_peer objects --- tsi_peer objects are a set of properties. The peer owns the properties. */ /* This property is of type TSI_PEER_PROPERTY_STRING. */ #define TSI_CERTIFICATE_TYPE_PEER_PROPERTY "certificate_type" /* Property values may contain NULL characters just like C++ strings. The length field gives the length of the string. */ typedef struct tsi_peer_property { char *name; struct { char *data; size_t length; } value; } tsi_peer_property; typedef struct { tsi_peer_property *properties; size_t property_count; } tsi_peer; /* Destructs the tsi_peer object. */ void tsi_peer_destruct(tsi_peer *self); /* --- tsi_handshaker objects ---- Implementations of this object must be thread compatible. A typical usage of this object would be: ------------------------------------------------------------------------ tsi_result result = TSI_OK; unsigned char buf[4096]; size_t buf_offset; size_t buf_size; while (1) { // See if we need to send some bytes to the peer. do { size_t buf_size_to_send = sizeof(buf); result = tsi_handshaker_get_bytes_to_send_to_peer(handshaker, buf, &buf_size_to_send); if (buf_size_to_send > 0) send_bytes_to_peer(buf, buf_size_to_send); } while (result == TSI_INCOMPLETE_DATA); if (result != TSI_OK) return result; if (!tsi_handshaker_is_in_progress(handshaker)) break; do { // Read bytes from the peer. buf_size = sizeof(buf); buf_offset = 0; read_bytes_from_peer(buf, &buf_size); if (buf_size == 0) break; // Process the bytes from the peer. We have to be careful as these bytes // may contain non-handshake data (protected data). If this is the case, // we will exit from the loop with buf_size > 0. size_t consumed_by_handshaker = buf_size; result = tsi_handshaker_process_bytes_from_peer( handshaker, buf, &consumed_by_handshaker); buf_size -= consumed_by_handshaker; buf_offset += consumed_by_handshaker; } while (result == TSI_INCOMPLETE_DATA); if (result != TSI_OK) return result; if (!tsi_handshaker_is_in_progress(handshaker)) break; } // Check the Peer. tsi_peer peer; do { result = tsi_handshaker_extract_peer(handshaker, &peer); if (result != TSI_OK) break; result = check_peer(&peer); } while (0); tsi_peer_destruct(&peer); if (result != TSI_OK) return result; // Create the protector. tsi_frame_protector* protector = NULL; result = tsi_handshaker_create_frame_protector(handshaker, NULL, &protector); if (result != TSI_OK) return result; // Do not forget to unprotect outstanding data if any. if (buf_size > 0) { result = tsi_frame_protector_unprotect(protector, buf + buf_offset, buf_size, ..., ...); .... } ... ------------------------------------------------------------------------ */ typedef struct tsi_handshaker tsi_handshaker; /* Gets bytes that need to be sent to the peer. - bytes is the buffer that will be written with the data to be sent to the peer. - bytes_size is an input/output parameter specifying the capacity of the bytes parameter as input and the number of bytes written as output. Returns TSI_OK if all the data to send to the peer has been written or if nothing has to be sent to the peer (in which base bytes_size outputs to 0), otherwise returns TSI_INCOMPLETE_DATA which indicates that this method needs to be called again to get all the bytes to send to the peer (there was more data to write than the specified bytes_size). In case of a fatal error in the handshake, another specific error code is returned. */ tsi_result tsi_handshaker_get_bytes_to_send_to_peer(tsi_handshaker *self, unsigned char *bytes, size_t *bytes_size); /* Processes bytes received from the peer. - bytes is the buffer containing the data. - bytes_size is an input/output parameter specifying the size of the data as input and the number of bytes consumed as output. Return TSI_OK if the handshake has all the data it needs to process, otherwise return TSI_INCOMPLETE_DATA which indicates that this method needs to be called again to complete the data needed for processing. In case of a fatal error in the handshake, another specific error code is returned. */ tsi_result tsi_handshaker_process_bytes_from_peer(tsi_handshaker *self, const unsigned char *bytes, size_t *bytes_size); /* Gets the result of the handshaker. Returns TSI_OK if the hanshake completed successfully and there has been no errors. Returns TSI_HANDSHAKE_IN_PROGRESS if the handshaker is not done yet but no error has been encountered so far. Otherwise the handshaker failed with the returned error. */ tsi_result tsi_handshaker_get_result(tsi_handshaker *self); /* Returns 1 if the handshake is in progress, 0 otherwise. */ #define tsi_handshaker_is_in_progress(h) \ (tsi_handshaker_get_result((h)) == TSI_HANDSHAKE_IN_PROGRESS) /* This method may return TSI_FAILED_PRECONDITION if tsi_handshaker_is_in_progress returns 1, it returns TSI_OK otherwise assuming the handshaker is not in a fatal error state. The caller is responsible for destructing the peer. */ tsi_result tsi_handshaker_extract_peer(tsi_handshaker *self, tsi_peer *peer); /* This method creates a tsi_frame_protector object after the handshake phase is done. After this method has been called successfully, the only method that can be called on this object is Destroy. - max_output_protected_frame_size is an input/output parameter specifying the desired max output protected frame size as input and outputing the actual max output frame size as the output. Passing NULL is OK and will result in the implementation choosing the default maximum protected frame size. Note that this size only applies to outgoing frames (generated with tsi_frame_protector_protect) and not incoming frames (input of tsi_frame_protector_unprotect). - protector is an output parameter pointing to the newly created tsi_frame_protector object. This method may return TSI_FAILED_PRECONDITION if tsi_handshaker_is_in_progress returns 1, it returns TSI_OK otherwise assuming the handshaker is not in a fatal error state. The caller is responsible for destroying the protector. */ tsi_result tsi_handshaker_create_frame_protector( tsi_handshaker *self, size_t *max_output_protected_frame_size, tsi_frame_protector **protector); /* This method releases the tsi_handshaker object. After this method is called, no other method can be called on the object. */ void tsi_handshaker_destroy(tsi_handshaker *self); #ifdef __cplusplus } #endif #endif /* GRPC_CORE_TSI_TRANSPORT_SECURITY_INTERFACE_H */ grpc-1.3.2/src/cpp/000077500000000000000000000000001310511640000140105ustar00rootroot00000000000000grpc-1.3.2/src/cpp/README.md000066400000000000000000000041261310511640000152720ustar00rootroot00000000000000 # Overview This directory contains source code for C++ implementation of gRPC. # Pre-requisites ## Linux ```sh $ [sudo] apt-get install build-essential autoconf libtool ``` ## Mac OSX For a Mac system, git is not available by default. You will first need to install Xcode from the Mac AppStore and then run the following command from a terminal: ```sh $ [sudo] xcode-select --install ``` ## Protoc By default gRPC uses [protocol buffers](https://github.com/google/protobuf), you will need the `protoc` compiler to generate stub server and client code. If you compile gRPC from source, as described below, this also installs the `protoc` compiler. If it hasn't been installed, you can run the following commands to install it. ```sh $ cd grpc/third_party/protobuf $ sudo make install # 'make' should have been run by core grpc ``` Alternatively, you can download `protoc` binaries from [the protocol buffers Github repository](https://github.com/google/protobuf/releases). # Installation Currently to install gRPC for C++, you need to build from source as described below. # Build from Source ```sh $ git clone -b $(curl -L http://grpc.io/release) https://github.com/grpc/grpc $ cd grpc $ git submodule update --init $ make $ [sudo] make install ``` # Documentation You can find out how to build and run our simplest gRPC C++ example in our [C++ quick start](../../examples/cpp). For more detailed documentation on using gRPC in C++ , see our main documentation site at [grpc.io](http://grpc.io), specifically: * [Overview](http://www.grpc.io/docs/): An introduction to gRPC with a simple Hello World example in all our supported languages, including C++. * [gRPC Basics - C++](http://www.grpc.io/docs/tutorials/basic/c.html): A tutorial that steps you through creating a simple gRPC C++ example application. * [Asynchronous Basics - C++](http://www.grpc.io/docs/tutorials/async/helloasync-cpp.html): A tutorial that shows you how to use gRPC C++'s asynchronous/non-blocking APIs. # Examples Code examples for gRPC C++ live in this repository's [examples/cpp](../../examples/cpp) directory. grpc-1.3.2/src/cpp/client/000077500000000000000000000000001310511640000152665ustar00rootroot00000000000000grpc-1.3.2/src/cpp/client/channel_cc.cc000066400000000000000000000143721310511640000176610ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "src/core/lib/profiling/timers.h" namespace grpc { static internal::GrpcLibraryInitializer g_gli_initializer; Channel::Channel(const grpc::string& host, grpc_channel* channel) : host_(host), c_channel_(channel) { g_gli_initializer.summon(); } Channel::~Channel() { grpc_channel_destroy(c_channel_); } namespace { grpc::string GetChannelInfoField(grpc_channel* channel, grpc_channel_info* channel_info, char*** channel_info_field) { char* value = NULL; memset(channel_info, 0, sizeof(*channel_info)); *channel_info_field = &value; grpc_channel_get_info(channel, channel_info); if (value == NULL) return ""; grpc::string result = value; gpr_free(value); return result; } } // namespace grpc::string Channel::GetLoadBalancingPolicyName() const { grpc_channel_info channel_info; return GetChannelInfoField(c_channel_, &channel_info, &channel_info.lb_policy_name); } grpc::string Channel::GetServiceConfigJSON() const { grpc_channel_info channel_info; return GetChannelInfoField(c_channel_, &channel_info, &channel_info.service_config_json); } Call Channel::CreateCall(const RpcMethod& method, ClientContext* context, CompletionQueue* cq) { const bool kRegistered = method.channel_tag() && context->authority().empty(); grpc_call* c_call = NULL; if (kRegistered) { c_call = grpc_channel_create_registered_call( c_channel_, context->propagate_from_call_, context->propagation_options_.c_bitmask(), cq->cq(), method.channel_tag(), context->raw_deadline(), nullptr); } else { const char* host_str = NULL; if (!context->authority().empty()) { host_str = context->authority_.c_str(); } else if (!host_.empty()) { host_str = host_.c_str(); } grpc_slice method_slice = SliceFromCopiedString(method.name()); grpc_slice host_slice; if (host_str != nullptr) { host_slice = SliceFromCopiedString(host_str); } c_call = grpc_channel_create_call( c_channel_, context->propagate_from_call_, context->propagation_options_.c_bitmask(), cq->cq(), method_slice, host_str == nullptr ? nullptr : &host_slice, context->raw_deadline(), nullptr); grpc_slice_unref(method_slice); if (host_str != nullptr) { grpc_slice_unref(host_slice); } } grpc_census_call_set_context(c_call, context->census_context()); context->set_call(c_call, shared_from_this()); return Call(c_call, this, cq); } void Channel::PerformOpsOnCall(CallOpSetInterface* ops, Call* call) { static const size_t MAX_OPS = 8; size_t nops = 0; grpc_op cops[MAX_OPS]; ops->FillOps(cops, &nops); GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(call->call(), cops, nops, ops, nullptr)); } void* Channel::RegisterMethod(const char* method) { return grpc_channel_register_call( c_channel_, method, host_.empty() ? NULL : host_.c_str(), nullptr); } grpc_connectivity_state Channel::GetState(bool try_to_connect) { return grpc_channel_check_connectivity_state(c_channel_, try_to_connect); } namespace { class TagSaver final : public CompletionQueueTag { public: explicit TagSaver(void* tag) : tag_(tag) {} ~TagSaver() override {} bool FinalizeResult(void** tag, bool* status) override { *tag = tag_; delete this; return true; } private: void* tag_; }; } // namespace void Channel::NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline, CompletionQueue* cq, void* tag) { TagSaver* tag_saver = new TagSaver(tag); grpc_channel_watch_connectivity_state(c_channel_, last_observed, deadline, cq->cq(), tag_saver); } bool Channel::WaitForStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline) { CompletionQueue cq; bool ok = false; void* tag = NULL; NotifyOnStateChangeImpl(last_observed, deadline, &cq, NULL); cq.Next(&tag, &ok); GPR_ASSERT(tag == NULL); return ok; } } // namespace grpc grpc-1.3.2/src/cpp/client/client_context.cc000066400000000000000000000115551310511640000206260ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include namespace grpc { class DefaultGlobalClientCallbacks final : public ClientContext::GlobalCallbacks { public: ~DefaultGlobalClientCallbacks() override {} void DefaultConstructor(ClientContext* context) override {} void Destructor(ClientContext* context) override {} }; static DefaultGlobalClientCallbacks g_default_client_callbacks; static ClientContext::GlobalCallbacks* g_client_callbacks = &g_default_client_callbacks; ClientContext::ClientContext() : initial_metadata_received_(false), wait_for_ready_(false), wait_for_ready_explicitly_set_(false), idempotent_(false), cacheable_(false), call_(nullptr), call_canceled_(false), deadline_(gpr_inf_future(GPR_CLOCK_REALTIME)), census_context_(nullptr), propagate_from_call_(nullptr), initial_metadata_corked_(false) { g_client_callbacks->DefaultConstructor(this); } ClientContext::~ClientContext() { if (call_) { grpc_call_destroy(call_); } g_client_callbacks->Destructor(this); } std::unique_ptr ClientContext::FromServerContext( const ServerContext& context, PropagationOptions options) { std::unique_ptr ctx(new ClientContext); ctx->propagate_from_call_ = context.call_; ctx->propagation_options_ = options; return ctx; } void ClientContext::AddMetadata(const grpc::string& meta_key, const grpc::string& meta_value) { send_initial_metadata_.insert(std::make_pair(meta_key, meta_value)); } void ClientContext::set_call(grpc_call* call, const std::shared_ptr& channel) { std::unique_lock lock(mu_); GPR_ASSERT(call_ == nullptr); call_ = call; channel_ = channel; if (creds_ && !creds_->ApplyToCall(call_)) { grpc_call_cancel_with_status(call, GRPC_STATUS_CANCELLED, "Failed to set credentials to rpc.", nullptr); } if (call_canceled_) { grpc_call_cancel(call_, nullptr); } } void ClientContext::set_compression_algorithm( grpc_compression_algorithm algorithm) { char* algorithm_name = nullptr; if (!grpc_compression_algorithm_name(algorithm, &algorithm_name)) { gpr_log(GPR_ERROR, "Name for compression algorithm '%d' unknown.", algorithm); abort(); } GPR_ASSERT(algorithm_name != nullptr); AddMetadata(GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY, algorithm_name); } void ClientContext::TryCancel() { std::unique_lock lock(mu_); if (call_) { grpc_call_cancel(call_, nullptr); } else { call_canceled_ = true; } } grpc::string ClientContext::peer() const { grpc::string peer; if (call_) { char* c_peer = grpc_call_get_peer(call_); peer = c_peer; gpr_free(c_peer); } return peer; } void ClientContext::SetGlobalCallbacks(GlobalCallbacks* client_callbacks) { GPR_ASSERT(g_client_callbacks == &g_default_client_callbacks); GPR_ASSERT(client_callbacks != NULL); GPR_ASSERT(client_callbacks != &g_default_client_callbacks); g_client_callbacks = client_callbacks; } } // namespace grpc grpc-1.3.2/src/cpp/client/create_channel.cc000066400000000000000000000050501310511640000205300ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include "src/cpp/client/create_channel_internal.h" namespace grpc { class ChannelArguments; std::shared_ptr CreateChannel( const grpc::string& target, const std::shared_ptr& creds) { return CreateCustomChannel(target, creds, ChannelArguments()); } std::shared_ptr CreateCustomChannel( const grpc::string& target, const std::shared_ptr& creds, const ChannelArguments& args) { internal::GrpcLibrary init_lib; // We need to call init in case of a bad creds. return creds ? creds->CreateChannel(target, args) : CreateChannelInternal("", grpc_lame_client_channel_create( NULL, GRPC_STATUS_INVALID_ARGUMENT, "Invalid credentials.")); } } // namespace grpc grpc-1.3.2/src/cpp/client/create_channel_internal.cc000066400000000000000000000035451310511640000224330ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include struct grpc_channel; namespace grpc { std::shared_ptr CreateChannelInternal(const grpc::string& host, grpc_channel* c_channel) { return std::shared_ptr(new Channel(host, c_channel)); } } // namespace grpc grpc-1.3.2/src/cpp/client/create_channel_internal.h000066400000000000000000000037561310511640000223010ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_CPP_CLIENT_CREATE_CHANNEL_INTERNAL_H #define GRPC_INTERNAL_CPP_CLIENT_CREATE_CHANNEL_INTERNAL_H #include #include struct grpc_channel; namespace grpc { class Channel; std::shared_ptr CreateChannelInternal(const grpc::string& host, grpc_channel* c_channel); } // namespace grpc #endif // GRPC_INTERNAL_CPP_CLIENT_CREATE_CHANNEL_INTERNAL_H grpc-1.3.2/src/cpp/client/create_channel_posix.cc000066400000000000000000000050651310511640000217600ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include "src/cpp/client/create_channel_internal.h" namespace grpc { #ifdef GPR_SUPPORT_CHANNELS_FROM_FD std::shared_ptr CreateInsecureChannelFromFd(const grpc::string& target, int fd) { internal::GrpcLibrary init_lib; init_lib.init(); return CreateChannelInternal( "", grpc_insecure_channel_create_from_fd(target.c_str(), fd, nullptr)); } std::shared_ptr CreateCustomInsecureChannelFromFd( const grpc::string& target, int fd, const ChannelArguments& args) { internal::GrpcLibrary init_lib; init_lib.init(); grpc_channel_args channel_args; args.SetChannelArgs(&channel_args); return CreateChannelInternal("", grpc_insecure_channel_create_from_fd( target.c_str(), fd, &channel_args)); } #endif // GPR_SUPPORT_CHANNELS_FROM_FD } // namespace grpc grpc-1.3.2/src/cpp/client/credentials_cc.cc000066400000000000000000000036701310511640000205450ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include namespace grpc { static internal::GrpcLibraryInitializer g_gli_initializer; ChannelCredentials::ChannelCredentials() { g_gli_initializer.summon(); } ChannelCredentials::~ChannelCredentials() {} CallCredentials::CallCredentials() { g_gli_initializer.summon(); } CallCredentials::~CallCredentials() {} } // namespace grpc grpc-1.3.2/src/cpp/client/cronet_credentials.cc000066400000000000000000000050761310511640000214540ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include "src/cpp/client/create_channel_internal.h" namespace grpc { class CronetChannelCredentialsImpl final : public ChannelCredentials { public: CronetChannelCredentialsImpl(void* engine) : engine_(engine) {} std::shared_ptr CreateChannel( const string& target, const grpc::ChannelArguments& args) override { grpc_channel_args channel_args; args.SetChannelArgs(&channel_args); return CreateChannelInternal( "", grpc_cronet_secure_channel_create(engine_, target.c_str(), &channel_args, nullptr)); } SecureChannelCredentials* AsSecureCredentials() override { return nullptr; } private: void* engine_; }; std::shared_ptr CronetChannelCredentials(void* engine) { return std::shared_ptr( new CronetChannelCredentialsImpl(engine)); } } // namespace grpc grpc-1.3.2/src/cpp/client/generic_stub.cc000066400000000000000000000040601310511640000202460ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include namespace grpc { // begin a call to a named method std::unique_ptr GenericStub::Call( ClientContext* context, const grpc::string& method, CompletionQueue* cq, void* tag) { return std::unique_ptr( new GenericClientAsyncReaderWriter( channel_.get(), cq, RpcMethod(method.c_str(), RpcMethod::BIDI_STREAMING), context, tag)); } } // namespace grpc grpc-1.3.2/src/cpp/client/insecure_credentials.cc000066400000000000000000000047651310511640000220030ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include "src/cpp/client/create_channel_internal.h" namespace grpc { namespace { class InsecureChannelCredentialsImpl final : public ChannelCredentials { public: std::shared_ptr CreateChannel( const string& target, const grpc::ChannelArguments& args) override { grpc_channel_args channel_args; args.SetChannelArgs(&channel_args); return CreateChannelInternal( "", grpc_insecure_channel_create(target.c_str(), &channel_args, nullptr)); } SecureChannelCredentials* AsSecureCredentials() override { return nullptr; } }; } // namespace std::shared_ptr InsecureChannelCredentials() { return std::shared_ptr( new InsecureChannelCredentialsImpl()); } } // namespace grpc grpc-1.3.2/src/cpp/client/secure_credentials.cc000066400000000000000000000230111310511640000214350ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/cpp/client/secure_credentials.h" #include #include #include #include #include "src/cpp/client/create_channel_internal.h" #include "src/cpp/common/secure_auth_context.h" namespace grpc { static internal::GrpcLibraryInitializer g_gli_initializer; SecureChannelCredentials::SecureChannelCredentials( grpc_channel_credentials* c_creds) : c_creds_(c_creds) { g_gli_initializer.summon(); } std::shared_ptr SecureChannelCredentials::CreateChannel( const string& target, const grpc::ChannelArguments& args) { grpc_channel_args channel_args; args.SetChannelArgs(&channel_args); return CreateChannelInternal( args.GetSslTargetNameOverride(), grpc_secure_channel_create(c_creds_, target.c_str(), &channel_args, nullptr)); } SecureCallCredentials::SecureCallCredentials(grpc_call_credentials* c_creds) : c_creds_(c_creds) { g_gli_initializer.summon(); } bool SecureCallCredentials::ApplyToCall(grpc_call* call) { return grpc_call_set_credentials(call, c_creds_) == GRPC_CALL_OK; } namespace { std::shared_ptr WrapChannelCredentials( grpc_channel_credentials* creds) { return creds == nullptr ? nullptr : std::shared_ptr( new SecureChannelCredentials(creds)); } std::shared_ptr WrapCallCredentials( grpc_call_credentials* creds) { return creds == nullptr ? nullptr : std::shared_ptr( new SecureCallCredentials(creds)); } } // namespace std::shared_ptr GoogleDefaultCredentials() { GrpcLibraryCodegen init; // To call grpc_init(). return WrapChannelCredentials(grpc_google_default_credentials_create()); } // Builds SSL Credentials given SSL specific options std::shared_ptr SslCredentials( const SslCredentialsOptions& options) { GrpcLibraryCodegen init; // To call grpc_init(). grpc_ssl_pem_key_cert_pair pem_key_cert_pair = { options.pem_private_key.c_str(), options.pem_cert_chain.c_str()}; grpc_channel_credentials* c_creds = grpc_ssl_credentials_create( options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(), options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair, nullptr); return WrapChannelCredentials(c_creds); } // Builds credentials for use when running in GCE std::shared_ptr GoogleComputeEngineCredentials() { GrpcLibraryCodegen init; // To call grpc_init(). return WrapCallCredentials( grpc_google_compute_engine_credentials_create(nullptr)); } // Builds JWT credentials. std::shared_ptr ServiceAccountJWTAccessCredentials( const grpc::string& json_key, long token_lifetime_seconds) { GrpcLibraryCodegen init; // To call grpc_init(). if (token_lifetime_seconds <= 0) { gpr_log(GPR_ERROR, "Trying to create JWTCredentials with non-positive lifetime"); return WrapCallCredentials(nullptr); } gpr_timespec lifetime = gpr_time_from_seconds(token_lifetime_seconds, GPR_TIMESPAN); return WrapCallCredentials(grpc_service_account_jwt_access_credentials_create( json_key.c_str(), lifetime, nullptr)); } // Builds refresh token credentials. std::shared_ptr GoogleRefreshTokenCredentials( const grpc::string& json_refresh_token) { GrpcLibraryCodegen init; // To call grpc_init(). return WrapCallCredentials(grpc_google_refresh_token_credentials_create( json_refresh_token.c_str(), nullptr)); } // Builds access token credentials. std::shared_ptr AccessTokenCredentials( const grpc::string& access_token) { GrpcLibraryCodegen init; // To call grpc_init(). return WrapCallCredentials( grpc_access_token_credentials_create(access_token.c_str(), nullptr)); } // Builds IAM credentials. std::shared_ptr GoogleIAMCredentials( const grpc::string& authorization_token, const grpc::string& authority_selector) { GrpcLibraryCodegen init; // To call grpc_init(). return WrapCallCredentials(grpc_google_iam_credentials_create( authorization_token.c_str(), authority_selector.c_str(), nullptr)); } // Combines one channel credentials and one call credentials into a channel // composite credentials. std::shared_ptr CompositeChannelCredentials( const std::shared_ptr& channel_creds, const std::shared_ptr& call_creds) { // Note that we are not saving shared_ptrs to the two credentials passed in // here. This is OK because the underlying C objects (i.e., channel_creds and // call_creds) into grpc_composite_credentials_create will see their refcounts // incremented. SecureChannelCredentials* s_channel_creds = channel_creds->AsSecureCredentials(); SecureCallCredentials* s_call_creds = call_creds->AsSecureCredentials(); if (s_channel_creds && s_call_creds) { return WrapChannelCredentials(grpc_composite_channel_credentials_create( s_channel_creds->GetRawCreds(), s_call_creds->GetRawCreds(), nullptr)); } return nullptr; } void MetadataCredentialsPluginWrapper::Destroy(void* wrapper) { if (wrapper == nullptr) return; MetadataCredentialsPluginWrapper* w = reinterpret_cast(wrapper); delete w; } void MetadataCredentialsPluginWrapper::GetMetadata( void* wrapper, grpc_auth_metadata_context context, grpc_credentials_plugin_metadata_cb cb, void* user_data) { GPR_ASSERT(wrapper); MetadataCredentialsPluginWrapper* w = reinterpret_cast(wrapper); if (!w->plugin_) { cb(user_data, NULL, 0, GRPC_STATUS_OK, NULL); return; } if (w->plugin_->IsBlocking()) { w->thread_pool_->Add( std::bind(&MetadataCredentialsPluginWrapper::InvokePlugin, w, context, cb, user_data)); } else { w->InvokePlugin(context, cb, user_data); } } void MetadataCredentialsPluginWrapper::InvokePlugin( grpc_auth_metadata_context context, grpc_credentials_plugin_metadata_cb cb, void* user_data) { std::multimap metadata; // const_cast is safe since the SecureAuthContext does not take owndership and // the object is passed as a const ref to plugin_->GetMetadata. SecureAuthContext cpp_channel_auth_context( const_cast(context.channel_auth_context), false); Status status = plugin_->GetMetadata(context.service_url, context.method_name, cpp_channel_auth_context, &metadata); std::vector md; for (auto it = metadata.begin(); it != metadata.end(); ++it) { grpc_metadata md_entry; md_entry.key = SliceFromCopiedString(it->first); md_entry.value = SliceFromCopiedString(it->second); md_entry.flags = 0; md.push_back(md_entry); } cb(user_data, md.empty() ? nullptr : &md[0], md.size(), static_cast(status.error_code()), status.error_message().c_str()); for (auto it = md.begin(); it != md.end(); ++it) { grpc_slice_unref(it->key); grpc_slice_unref(it->value); } } MetadataCredentialsPluginWrapper::MetadataCredentialsPluginWrapper( std::unique_ptr plugin) : thread_pool_(CreateDefaultThreadPool()), plugin_(std::move(plugin)) {} std::shared_ptr MetadataCredentialsFromPlugin( std::unique_ptr plugin) { GrpcLibraryCodegen init; // To call grpc_init(). const char* type = plugin->GetType(); MetadataCredentialsPluginWrapper* wrapper = new MetadataCredentialsPluginWrapper(std::move(plugin)); grpc_metadata_credentials_plugin c_plugin = { MetadataCredentialsPluginWrapper::GetMetadata, MetadataCredentialsPluginWrapper::Destroy, wrapper, type}; return WrapCallCredentials( grpc_metadata_credentials_create_from_plugin(c_plugin, nullptr)); } } // namespace grpc grpc-1.3.2/src/cpp/client/secure_credentials.h000066400000000000000000000070161310511640000213060ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_CPP_CLIENT_SECURE_CREDENTIALS_H #define GRPC_INTERNAL_CPP_CLIENT_SECURE_CREDENTIALS_H #include #include #include #include "src/cpp/server/thread_pool_interface.h" namespace grpc { class SecureChannelCredentials final : public ChannelCredentials { public: explicit SecureChannelCredentials(grpc_channel_credentials* c_creds); ~SecureChannelCredentials() { grpc_channel_credentials_release(c_creds_); } grpc_channel_credentials* GetRawCreds() { return c_creds_; } std::shared_ptr CreateChannel( const string& target, const grpc::ChannelArguments& args) override; SecureChannelCredentials* AsSecureCredentials() override { return this; } private: grpc_channel_credentials* const c_creds_; }; class SecureCallCredentials final : public CallCredentials { public: explicit SecureCallCredentials(grpc_call_credentials* c_creds); ~SecureCallCredentials() { grpc_call_credentials_release(c_creds_); } grpc_call_credentials* GetRawCreds() { return c_creds_; } bool ApplyToCall(grpc_call* call) override; SecureCallCredentials* AsSecureCredentials() override { return this; } private: grpc_call_credentials* const c_creds_; }; class MetadataCredentialsPluginWrapper final : private GrpcLibraryCodegen { public: static void Destroy(void* wrapper); static void GetMetadata(void* wrapper, grpc_auth_metadata_context context, grpc_credentials_plugin_metadata_cb cb, void* user_data); explicit MetadataCredentialsPluginWrapper( std::unique_ptr plugin); private: void InvokePlugin(grpc_auth_metadata_context context, grpc_credentials_plugin_metadata_cb cb, void* user_data); std::unique_ptr thread_pool_; std::unique_ptr plugin_; }; } // namespace grpc #endif // GRPC_INTERNAL_CPP_CLIENT_SECURE_CREDENTIALS_H grpc-1.3.2/src/cpp/codegen/000077500000000000000000000000001310511640000154145ustar00rootroot00000000000000grpc-1.3.2/src/cpp/codegen/codegen_init.cc000066400000000000000000000042761310511640000203630ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include /// Null-initializes the global gRPC variables for the codegen library. These /// stay null in the absence of of grpc++ library. In this case, no gRPC /// features such as the ability to perform calls will be available. Trying to /// perform them would result in a segmentation fault when trying to deference /// the following nulled globals. These should be associated with actual /// as part of the instantiation of a \a grpc::GrpcLibraryInitializer variable. grpc::CoreCodegenInterface* grpc::g_core_codegen_interface; grpc::GrpcLibraryInterface* grpc::g_glip; grpc-1.3.2/src/cpp/common/000077500000000000000000000000001310511640000153005ustar00rootroot00000000000000grpc-1.3.2/src/cpp/common/auth_property_iterator.cc000066400000000000000000000056771310511640000224440ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include namespace grpc { AuthPropertyIterator::AuthPropertyIterator() : property_(nullptr), ctx_(nullptr), index_(0), name_(nullptr) {} AuthPropertyIterator::AuthPropertyIterator( const grpc_auth_property* property, const grpc_auth_property_iterator* iter) : property_(property), ctx_(iter->ctx), index_(iter->index), name_(iter->name) {} AuthPropertyIterator::~AuthPropertyIterator() {} AuthPropertyIterator& AuthPropertyIterator::operator++() { grpc_auth_property_iterator iter = {ctx_, index_, name_}; property_ = grpc_auth_property_iterator_next(&iter); ctx_ = iter.ctx; index_ = iter.index; name_ = iter.name; return *this; } AuthPropertyIterator AuthPropertyIterator::operator++(int) { AuthPropertyIterator tmp(*this); operator++(); return tmp; } bool AuthPropertyIterator::operator==(const AuthPropertyIterator& rhs) const { if (property_ == nullptr || rhs.property_ == nullptr) { return property_ == rhs.property_; } else { return index_ == rhs.index_; } } bool AuthPropertyIterator::operator!=(const AuthPropertyIterator& rhs) const { return !operator==(rhs); } const AuthProperty AuthPropertyIterator::operator*() { return std::pair( property_->name, grpc::string_ref(property_->value, property_->value_length)); } } // namespace grpc grpc-1.3.2/src/cpp/common/channel_arguments.cc000066400000000000000000000171241310511640000213110ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include extern "C" { #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/socket_mutator.h" } namespace grpc { ChannelArguments::ChannelArguments() { // This will be ignored if used on the server side. SetString(GRPC_ARG_PRIMARY_USER_AGENT_STRING, "grpc-c++/" + Version()); } ChannelArguments::ChannelArguments(const ChannelArguments& other) : strings_(other.strings_) { args_.reserve(other.args_.size()); auto list_it_dst = strings_.begin(); auto list_it_src = other.strings_.begin(); for (auto a = other.args_.begin(); a != other.args_.end(); ++a) { grpc_arg ap; ap.type = a->type; GPR_ASSERT(list_it_src->c_str() == a->key); ap.key = const_cast(list_it_dst->c_str()); ++list_it_src; ++list_it_dst; switch (a->type) { case GRPC_ARG_INTEGER: ap.value.integer = a->value.integer; break; case GRPC_ARG_STRING: GPR_ASSERT(list_it_src->c_str() == a->value.string); ap.value.string = const_cast(list_it_dst->c_str()); ++list_it_src; ++list_it_dst; break; case GRPC_ARG_POINTER: ap.value.pointer = a->value.pointer; ap.value.pointer.p = a->value.pointer.vtable->copy(ap.value.pointer.p); break; } args_.push_back(ap); } } ChannelArguments::~ChannelArguments() { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; for (auto it = args_.begin(); it != args_.end(); ++it) { if (it->type == GRPC_ARG_POINTER) { it->value.pointer.vtable->destroy(&exec_ctx, it->value.pointer.p); } } grpc_exec_ctx_finish(&exec_ctx); } void ChannelArguments::Swap(ChannelArguments& other) { args_.swap(other.args_); strings_.swap(other.strings_); } void ChannelArguments::SetCompressionAlgorithm( grpc_compression_algorithm algorithm) { SetInt(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, algorithm); } void ChannelArguments::SetSocketMutator(grpc_socket_mutator* mutator) { if (!mutator) { return; } grpc_arg mutator_arg = grpc_socket_mutator_to_arg(mutator); bool replaced = false; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; for (auto it = args_.begin(); it != args_.end(); ++it) { if (it->type == mutator_arg.type && grpc::string(it->key) == grpc::string(mutator_arg.key)) { GPR_ASSERT(!replaced); it->value.pointer.vtable->destroy(&exec_ctx, it->value.pointer.p); it->value.pointer = mutator_arg.value.pointer; replaced = true; } } grpc_exec_ctx_finish(&exec_ctx); if (!replaced) { args_.push_back(mutator_arg); } } // Note: a second call to this will add in front the result of the first call. // An example is calling this on a copy of ChannelArguments which already has a // prefix. The user can build up a prefix string by calling this multiple times, // each with more significant identifier. void ChannelArguments::SetUserAgentPrefix( const grpc::string& user_agent_prefix) { if (user_agent_prefix.empty()) { return; } bool replaced = false; auto strings_it = strings_.begin(); for (auto it = args_.begin(); it != args_.end(); ++it) { const grpc_arg& arg = *it; ++strings_it; if (arg.type == GRPC_ARG_STRING) { if (grpc::string(arg.key) == GRPC_ARG_PRIMARY_USER_AGENT_STRING) { GPR_ASSERT(arg.value.string == strings_it->c_str()); *(strings_it) = user_agent_prefix + " " + arg.value.string; it->value.string = const_cast(strings_it->c_str()); replaced = true; break; } ++strings_it; } } if (!replaced) { SetString(GRPC_ARG_PRIMARY_USER_AGENT_STRING, user_agent_prefix); } } void ChannelArguments::SetResourceQuota( const grpc::ResourceQuota& resource_quota) { SetPointerWithVtable(GRPC_ARG_RESOURCE_QUOTA, resource_quota.c_resource_quota(), grpc_resource_quota_arg_vtable()); } void ChannelArguments::SetMaxReceiveMessageSize(int size) { SetInt(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, size); } void ChannelArguments::SetMaxSendMessageSize(int size) { SetInt(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, size); } void ChannelArguments::SetLoadBalancingPolicyName( const grpc::string& lb_policy_name) { SetString(GRPC_ARG_LB_POLICY_NAME, lb_policy_name); } void ChannelArguments::SetServiceConfigJSON( const grpc::string& service_config_json) { SetString(GRPC_ARG_SERVICE_CONFIG, service_config_json); } void ChannelArguments::SetInt(const grpc::string& key, int value) { grpc_arg arg; arg.type = GRPC_ARG_INTEGER; strings_.push_back(key); arg.key = const_cast(strings_.back().c_str()); arg.value.integer = value; args_.push_back(arg); } void ChannelArguments::SetPointer(const grpc::string& key, void* value) { static const grpc_arg_pointer_vtable vtable = { &PointerVtableMembers::Copy, &PointerVtableMembers::Destroy, &PointerVtableMembers::Compare}; SetPointerWithVtable(key, value, &vtable); } void ChannelArguments::SetPointerWithVtable( const grpc::string& key, void* value, const grpc_arg_pointer_vtable* vtable) { grpc_arg arg; arg.type = GRPC_ARG_POINTER; strings_.push_back(key); arg.key = const_cast(strings_.back().c_str()); arg.value.pointer.p = vtable->copy(value); arg.value.pointer.vtable = vtable; args_.push_back(arg); } void ChannelArguments::SetString(const grpc::string& key, const grpc::string& value) { grpc_arg arg; arg.type = GRPC_ARG_STRING; strings_.push_back(key); arg.key = const_cast(strings_.back().c_str()); strings_.push_back(value); arg.value.string = const_cast(strings_.back().c_str()); args_.push_back(arg); } void ChannelArguments::SetChannelArgs(grpc_channel_args* channel_args) const { channel_args->num_args = args_.size(); if (channel_args->num_args > 0) { channel_args->args = const_cast(&args_[0]); } } } // namespace grpc grpc-1.3.2/src/cpp/common/channel_filter.cc000066400000000000000000000107731310511640000205740ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "src/core/lib/channel/channel_stack.h" #include "src/cpp/common/channel_filter.h" #include namespace grpc { // MetadataBatch grpc_linked_mdelem *MetadataBatch::AddMetadata(grpc_exec_ctx *exec_ctx, const string &key, const string &value) { grpc_linked_mdelem *storage = new grpc_linked_mdelem; memset(storage, 0, sizeof(grpc_linked_mdelem)); storage->md = grpc_mdelem_from_slices(exec_ctx, SliceFromCopiedString(key), SliceFromCopiedString(value)); GRPC_LOG_IF_ERROR("MetadataBatch::AddMetadata", grpc_metadata_batch_link_head(exec_ctx, batch_, storage)); return storage; } // ChannelData void ChannelData::StartTransportOp(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, TransportOp *op) { grpc_channel_next_op(exec_ctx, elem, op->op()); } void ChannelData::GetInfo(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, const grpc_channel_info *channel_info) { grpc_channel_next_get_info(exec_ctx, elem, channel_info); } // CallData void CallData::StartTransportStreamOpBatch(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, TransportStreamOpBatch *op) { grpc_call_next_op(exec_ctx, elem, op->op()); } void CallData::SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_polling_entity *pollent) { grpc_call_stack_ignore_set_pollset_or_pollset_set(exec_ctx, elem, pollent); } char *CallData::GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { return grpc_call_next_get_peer(exec_ctx, elem); } // internal code used by RegisterChannelFilter() namespace internal { // Note: Implicitly initialized to nullptr due to static lifetime. std::vector *channel_filters; namespace { bool MaybeAddFilter(grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, void *arg) { const FilterRecord &filter = *(FilterRecord *)arg; if (filter.include_filter) { const grpc_channel_args *args = grpc_channel_stack_builder_get_channel_arguments(builder); if (!filter.include_filter(*args)) return true; } return grpc_channel_stack_builder_prepend_filter(builder, &filter.filter, nullptr, nullptr); } } // namespace void ChannelFilterPluginInit() { for (size_t i = 0; i < channel_filters->size(); ++i) { FilterRecord &filter = (*channel_filters)[i]; grpc_channel_init_register_stage(filter.stack_type, filter.priority, MaybeAddFilter, (void *)&filter); } } void ChannelFilterPluginShutdown() {} } // namespace internal } // namespace grpc grpc-1.3.2/src/cpp/common/channel_filter.h000066400000000000000000000351611310511640000204340ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPCXX_CHANNEL_FILTER_H #define GRPCXX_CHANNEL_FILTER_H #include #include #include #include #include #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/surface/channel_init.h" #include "src/core/lib/transport/metadata_batch.h" /// An interface to define filters. /// /// To define a filter, implement a subclass of each of \c CallData and /// \c ChannelData. Then register the filter using something like this: /// \code{.cpp} /// RegisterChannelFilter( /// "name-of-filter", GRPC_SERVER_CHANNEL, INT_MAX, nullptr); /// \endcode namespace grpc { /// A C++ wrapper for the \c grpc_metadata_batch struct. class MetadataBatch { public: /// Borrows a pointer to \a batch, but does NOT take ownership. /// The caller must ensure that \a batch continues to exist for as /// long as the MetadataBatch object does. explicit MetadataBatch(grpc_metadata_batch *batch) : batch_(batch) {} grpc_metadata_batch *batch() const { return batch_; } /// Adds metadata and returns the newly allocated storage. /// The caller takes ownership of the result, which must exist for the /// lifetime of the gRPC call. grpc_linked_mdelem *AddMetadata(grpc_exec_ctx *exec_ctx, const string &key, const string &value); class const_iterator : public std::iterator { public: const grpc_mdelem &operator*() const { return elem_->md; } const grpc_mdelem operator->() const { return elem_->md; } const_iterator &operator++() { elem_ = elem_->next; return *this; } const_iterator operator++(int) { const_iterator tmp(*this); operator++(); return tmp; } const_iterator &operator--() { elem_ = elem_->prev; return *this; } const_iterator operator--(int) { const_iterator tmp(*this); operator--(); return tmp; } bool operator==(const const_iterator &other) const { return elem_ == other.elem_; } bool operator!=(const const_iterator &other) const { return elem_ != other.elem_; } private: friend class MetadataBatch; explicit const_iterator(grpc_linked_mdelem *elem) : elem_(elem) {} grpc_linked_mdelem *elem_; }; const_iterator begin() const { return const_iterator(batch_->list.head); } const_iterator end() const { return const_iterator(nullptr); } private: grpc_metadata_batch *batch_; // Not owned. }; /// A C++ wrapper for the \c grpc_transport_op struct. class TransportOp { public: /// Borrows a pointer to \a op, but does NOT take ownership. /// The caller must ensure that \a op continues to exist for as /// long as the TransportOp object does. explicit TransportOp(grpc_transport_op *op) : op_(op) {} grpc_transport_op *op() const { return op_; } // TODO(roth): Add a C++ wrapper for grpc_error? grpc_error *disconnect_with_error() const { return op_->disconnect_with_error; } bool send_goaway() const { return op_->goaway_error != GRPC_ERROR_NONE; } // TODO(roth): Add methods for additional fields as needed. private: grpc_transport_op *op_; // Not owned. }; /// A C++ wrapper for the \c grpc_transport_stream_op_batch struct. class TransportStreamOpBatch { public: /// Borrows a pointer to \a op, but does NOT take ownership. /// The caller must ensure that \a op continues to exist for as /// long as the TransportStreamOpBatch object does. explicit TransportStreamOpBatch(grpc_transport_stream_op_batch *op) : op_(op), send_initial_metadata_( op->send_initial_metadata ? op->payload->send_initial_metadata.send_initial_metadata : nullptr), send_trailing_metadata_( op->send_trailing_metadata ? op->payload->send_trailing_metadata.send_trailing_metadata : nullptr), recv_initial_metadata_( op->recv_initial_metadata ? op->payload->recv_initial_metadata.recv_initial_metadata : nullptr), recv_trailing_metadata_( op->recv_trailing_metadata ? op->payload->recv_trailing_metadata.recv_trailing_metadata : nullptr) {} grpc_transport_stream_op_batch *op() const { return op_; } grpc_closure *on_complete() const { return op_->on_complete; } void set_on_complete(grpc_closure *closure) { op_->on_complete = closure; } MetadataBatch *send_initial_metadata() { return op_->send_initial_metadata ? &send_initial_metadata_ : nullptr; } MetadataBatch *send_trailing_metadata() { return op_->send_trailing_metadata ? &send_trailing_metadata_ : nullptr; } MetadataBatch *recv_initial_metadata() { return op_->recv_initial_metadata ? &recv_initial_metadata_ : nullptr; } MetadataBatch *recv_trailing_metadata() { return op_->recv_trailing_metadata ? &recv_trailing_metadata_ : nullptr; } uint32_t *send_initial_metadata_flags() const { return op_->send_initial_metadata ? &op_->payload->send_initial_metadata .send_initial_metadata_flags : nullptr; } grpc_closure *recv_initial_metadata_ready() const { return op_->recv_initial_metadata ? op_->payload->recv_initial_metadata.recv_initial_metadata_ready : nullptr; } void set_recv_initial_metadata_ready(grpc_closure *closure) { op_->payload->recv_initial_metadata.recv_initial_metadata_ready = closure; } grpc_byte_stream *send_message() const { return op_->send_message ? op_->payload->send_message.send_message : nullptr; } void set_send_message(grpc_byte_stream *send_message) { op_->send_message = true; op_->payload->send_message.send_message = send_message; } census_context *get_census_context() const { return (census_context *)op_->payload->context[GRPC_CONTEXT_TRACING].value; } private: grpc_transport_stream_op_batch *op_; // Not owned. MetadataBatch send_initial_metadata_; MetadataBatch send_trailing_metadata_; MetadataBatch recv_initial_metadata_; MetadataBatch recv_trailing_metadata_; }; /// Represents channel data. class ChannelData { public: virtual ~ChannelData() {} /// Initializes the call data. virtual grpc_error *Init(grpc_exec_ctx *exec_ctx, grpc_channel_element_args *args) { return GRPC_ERROR_NONE; } // TODO(roth): Find a way to avoid passing elem into these methods. virtual void StartTransportOp(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, TransportOp *op); virtual void GetInfo(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, const grpc_channel_info *channel_info); protected: ChannelData() {} }; /// Represents call data. class CallData { public: virtual ~CallData() {} /// Initializes the call data. virtual grpc_error *Init(grpc_exec_ctx *exec_ctx, ChannelData *channel_data, const grpc_call_element_args *args) { return GRPC_ERROR_NONE; } // TODO(roth): Find a way to avoid passing elem into these methods. /// Starts a new stream operation. virtual void StartTransportStreamOpBatch(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, TransportStreamOpBatch *op); /// Sets a pollset or pollset set. virtual void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_polling_entity *pollent); /// Gets the peer name. virtual char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem); protected: CallData() {} }; namespace internal { // Defines static members for passing to C core. // Members of this class correspond to the members of the C // grpc_channel_filter struct. template class ChannelFilter final { public: static const size_t channel_data_size = sizeof(ChannelDataType); static grpc_error *InitChannelElement(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_channel_element_args *args) { ChannelDataType *channel_data = new (elem->channel_data) ChannelDataType(); return channel_data->Init(exec_ctx, args); } static void DestroyChannelElement(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) { reinterpret_cast(elem->channel_data)->~ChannelDataType(); } static void StartTransportOp(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_transport_op *op) { ChannelDataType *channel_data = (ChannelDataType *)elem->channel_data; TransportOp op_wrapper(op); channel_data->StartTransportOp(exec_ctx, elem, &op_wrapper); } static void GetChannelInfo(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, const grpc_channel_info *channel_info) { ChannelDataType *channel_data = (ChannelDataType *)elem->channel_data; channel_data->GetInfo(exec_ctx, elem, channel_info); } static const size_t call_data_size = sizeof(CallDataType); static grpc_error *InitCallElement(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_element_args *args) { ChannelDataType *channel_data = (ChannelDataType *)elem->channel_data; // Construct the object in the already-allocated memory. CallDataType *call_data = new (elem->call_data) CallDataType(); return call_data->Init(exec_ctx, channel_data, args); } static void DestroyCallElement(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, grpc_closure *then_call_closure) { GPR_ASSERT(then_call_closure == NULL); reinterpret_cast(elem->call_data)->~CallDataType(); } static void StartTransportStreamOpBatch(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op_batch *op) { CallDataType *call_data = (CallDataType *)elem->call_data; TransportStreamOpBatch op_wrapper(op); call_data->StartTransportStreamOpBatch(exec_ctx, elem, &op_wrapper); } static void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_polling_entity *pollent) { CallDataType *call_data = (CallDataType *)elem->call_data; call_data->SetPollsetOrPollsetSet(exec_ctx, elem, pollent); } static char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { CallDataType *call_data = (CallDataType *)elem->call_data; return call_data->GetPeer(exec_ctx, elem); } }; struct FilterRecord { grpc_channel_stack_type stack_type; int priority; std::function include_filter; grpc_channel_filter filter; }; extern std::vector *channel_filters; void ChannelFilterPluginInit(); void ChannelFilterPluginShutdown(); } // namespace internal /// Registers a new filter. /// Must be called by only one thread at a time. /// The \a include_filter argument specifies a function that will be called /// to determine at run-time whether or not to add the filter. If the /// value is nullptr, the filter will be added unconditionally. template void RegisterChannelFilter( const char *name, grpc_channel_stack_type stack_type, int priority, std::function include_filter) { // If we haven't been called before, initialize channel_filters and // call grpc_register_plugin(). if (internal::channel_filters == nullptr) { grpc_register_plugin(internal::ChannelFilterPluginInit, internal::ChannelFilterPluginShutdown); internal::channel_filters = new std::vector(); } // Add an entry to channel_filters. The filter will be added when the // C-core initialization code calls ChannelFilterPluginInit(). typedef internal::ChannelFilter FilterType; internal::FilterRecord filter_record = { stack_type, priority, include_filter, {FilterType::StartTransportStreamOpBatch, FilterType::StartTransportOp, FilterType::call_data_size, FilterType::InitCallElement, FilterType::SetPollsetOrPollsetSet, FilterType::DestroyCallElement, FilterType::channel_data_size, FilterType::InitChannelElement, FilterType::DestroyChannelElement, FilterType::GetPeer, FilterType::GetChannelInfo, name}}; internal::channel_filters->push_back(filter_record); } } // namespace grpc #endif // GRPCXX_CHANNEL_FILTER_H grpc-1.3.2/src/cpp/common/completion_queue_cc.cc000066400000000000000000000062511310511640000216350ustar00rootroot00000000000000/* * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include namespace grpc { static internal::GrpcLibraryInitializer g_gli_initializer; // 'CompletionQueue' constructor can safely call GrpcLibraryCodegen(false) here // i.e not have GrpcLibraryCodegen call grpc_init(). This is because, to create // a 'grpc_completion_queue' instance (which is being passed as the input to // this constructor), one must have already called grpc_init(). CompletionQueue::CompletionQueue(grpc_completion_queue* take) : GrpcLibraryCodegen(false), cq_(take) { InitialAvalanching(); } void CompletionQueue::Shutdown() { g_gli_initializer.summon(); CompleteAvalanching(); } void CompletionQueue::CompleteAvalanching() { // Check if this was the last avalanching operation if (gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_, static_cast(-1)) == 1) { grpc_completion_queue_shutdown(cq_); } } CompletionQueue::NextStatus CompletionQueue::AsyncNextInternal( void** tag, bool* ok, gpr_timespec deadline) { for (;;) { auto ev = grpc_completion_queue_next(cq_, deadline, nullptr); switch (ev.type) { case GRPC_QUEUE_TIMEOUT: return TIMEOUT; case GRPC_QUEUE_SHUTDOWN: return SHUTDOWN; case GRPC_OP_COMPLETE: auto cq_tag = static_cast(ev.tag); *ok = ev.success != 0; *tag = cq_tag; if (cq_tag->FinalizeResult(tag, ok)) { return GOT_EVENT; } break; } } } } // namespace grpc grpc-1.3.2/src/cpp/common/core_codegen.cc000066400000000000000000000143101310511640000202220ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include "src/core/lib/profiling/timers.h" extern "C" { struct grpc_byte_buffer; } namespace grpc { grpc_completion_queue* CoreCodegen::grpc_completion_queue_create( void* reserved) { return ::grpc_completion_queue_create(reserved); } void CoreCodegen::grpc_completion_queue_destroy(grpc_completion_queue* cq) { ::grpc_completion_queue_destroy(cq); } grpc_event CoreCodegen::grpc_completion_queue_pluck(grpc_completion_queue* cq, void* tag, gpr_timespec deadline, void* reserved) { return ::grpc_completion_queue_pluck(cq, tag, deadline, reserved); } void* CoreCodegen::gpr_malloc(size_t size) { return ::gpr_malloc(size); } void CoreCodegen::gpr_free(void* p) { return ::gpr_free(p); } void CoreCodegen::gpr_mu_init(gpr_mu* mu) { ::gpr_mu_init(mu); }; void CoreCodegen::gpr_mu_destroy(gpr_mu* mu) { ::gpr_mu_destroy(mu); } void CoreCodegen::gpr_mu_lock(gpr_mu* mu) { ::gpr_mu_lock(mu); } void CoreCodegen::gpr_mu_unlock(gpr_mu* mu) { ::gpr_mu_unlock(mu); } void CoreCodegen::gpr_cv_init(gpr_cv* cv) { ::gpr_cv_init(cv); } void CoreCodegen::gpr_cv_destroy(gpr_cv* cv) { ::gpr_cv_destroy(cv); } int CoreCodegen::gpr_cv_wait(gpr_cv* cv, gpr_mu* mu, gpr_timespec abs_deadline) { return ::gpr_cv_wait(cv, mu, abs_deadline); } void CoreCodegen::gpr_cv_signal(gpr_cv* cv) { ::gpr_cv_signal(cv); } void CoreCodegen::gpr_cv_broadcast(gpr_cv* cv) { ::gpr_cv_broadcast(cv); } void CoreCodegen::grpc_byte_buffer_destroy(grpc_byte_buffer* bb) { ::grpc_byte_buffer_destroy(bb); } int CoreCodegen::grpc_byte_buffer_reader_init(grpc_byte_buffer_reader* reader, grpc_byte_buffer* buffer) { return ::grpc_byte_buffer_reader_init(reader, buffer); } void CoreCodegen::grpc_byte_buffer_reader_destroy( grpc_byte_buffer_reader* reader) { ::grpc_byte_buffer_reader_destroy(reader); } int CoreCodegen::grpc_byte_buffer_reader_next(grpc_byte_buffer_reader* reader, grpc_slice* slice) { return ::grpc_byte_buffer_reader_next(reader, slice); } grpc_byte_buffer* CoreCodegen::grpc_raw_byte_buffer_create(grpc_slice* slice, size_t nslices) { return ::grpc_raw_byte_buffer_create(slice, nslices); } grpc_slice CoreCodegen::grpc_empty_slice() { return ::grpc_empty_slice(); } grpc_slice CoreCodegen::grpc_slice_malloc(size_t length) { return ::grpc_slice_malloc(length); } void CoreCodegen::grpc_slice_unref(grpc_slice slice) { ::grpc_slice_unref(slice); } grpc_slice CoreCodegen::grpc_slice_split_tail(grpc_slice* s, size_t split) { return ::grpc_slice_split_tail(s, split); } grpc_slice CoreCodegen::grpc_slice_from_static_buffer(const void* buffer, size_t length) { return ::grpc_slice_from_static_buffer(buffer, length); } grpc_slice CoreCodegen::grpc_slice_from_copied_buffer(const void* buffer, size_t length) { return ::grpc_slice_from_copied_buffer(static_cast(buffer), length); } void CoreCodegen::grpc_slice_buffer_add(grpc_slice_buffer* sb, grpc_slice slice) { ::grpc_slice_buffer_add(sb, slice); } void CoreCodegen::grpc_slice_buffer_pop(grpc_slice_buffer* sb) { ::grpc_slice_buffer_pop(sb); } void CoreCodegen::grpc_metadata_array_init(grpc_metadata_array* array) { ::grpc_metadata_array_init(array); } void CoreCodegen::grpc_metadata_array_destroy(grpc_metadata_array* array) { ::grpc_metadata_array_destroy(array); } const Status& CoreCodegen::ok() { return grpc::Status::OK; } const Status& CoreCodegen::cancelled() { return grpc::Status::CANCELLED; } gpr_timespec CoreCodegen::gpr_inf_future(gpr_clock_type type) { return ::gpr_inf_future(type); } gpr_timespec CoreCodegen::gpr_time_0(gpr_clock_type type) { return ::gpr_time_0(type); } void CoreCodegen::assert_fail(const char* failed_assertion, const char* file, int line) { gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "assertion failed: %s", failed_assertion); abort(); } } // namespace grpc grpc-1.3.2/src/cpp/common/insecure_create_auth_context.cc000066400000000000000000000034451310511640000235420ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include namespace grpc { std::shared_ptr CreateAuthContext(grpc_call* call) { (void)call; return std::shared_ptr(); } } // namespace grpc grpc-1.3.2/src/cpp/common/resource_quota_cc.cc000066400000000000000000000040061310511640000213140ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include namespace grpc { ResourceQuota::ResourceQuota() : impl_(grpc_resource_quota_create(nullptr)) {} ResourceQuota::ResourceQuota(const grpc::string& name) : impl_(grpc_resource_quota_create(name.c_str())) {} ResourceQuota::~ResourceQuota() { grpc_resource_quota_unref(impl_); } ResourceQuota& ResourceQuota::Resize(size_t new_size) { grpc_resource_quota_resize(impl_, new_size); return *this; } } // namespace grpc grpc-1.3.2/src/cpp/common/rpc_method.cc000066400000000000000000000031541310511640000177360ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include namespace grpc {} // namespace grpc grpc-1.3.2/src/cpp/common/secure_auth_context.cc000066400000000000000000000102501310511640000216600ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/cpp/common/secure_auth_context.h" #include namespace grpc { SecureAuthContext::SecureAuthContext(grpc_auth_context* ctx, bool take_ownership) : ctx_(ctx), take_ownership_(take_ownership) {} SecureAuthContext::~SecureAuthContext() { if (take_ownership_) grpc_auth_context_release(ctx_); } std::vector SecureAuthContext::GetPeerIdentity() const { if (!ctx_) { return std::vector(); } grpc_auth_property_iterator iter = grpc_auth_context_peer_identity(ctx_); std::vector identity; const grpc_auth_property* property = nullptr; while ((property = grpc_auth_property_iterator_next(&iter))) { identity.push_back( grpc::string_ref(property->value, property->value_length)); } return identity; } grpc::string SecureAuthContext::GetPeerIdentityPropertyName() const { if (!ctx_) { return ""; } const char* name = grpc_auth_context_peer_identity_property_name(ctx_); return name == nullptr ? "" : name; } std::vector SecureAuthContext::FindPropertyValues( const grpc::string& name) const { if (!ctx_) { return std::vector(); } grpc_auth_property_iterator iter = grpc_auth_context_find_properties_by_name(ctx_, name.c_str()); const grpc_auth_property* property = nullptr; std::vector values; while ((property = grpc_auth_property_iterator_next(&iter))) { values.push_back(grpc::string_ref(property->value, property->value_length)); } return values; } AuthPropertyIterator SecureAuthContext::begin() const { if (ctx_) { grpc_auth_property_iterator iter = grpc_auth_context_property_iterator(ctx_); const grpc_auth_property* property = grpc_auth_property_iterator_next(&iter); return AuthPropertyIterator(property, &iter); } else { return end(); } } AuthPropertyIterator SecureAuthContext::end() const { return AuthPropertyIterator(); } void SecureAuthContext::AddProperty(const grpc::string& key, const grpc::string_ref& value) { if (!ctx_) return; grpc_auth_context_add_property(ctx_, key.c_str(), value.data(), value.size()); } bool SecureAuthContext::SetPeerIdentityPropertyName(const grpc::string& name) { if (!ctx_) return false; return grpc_auth_context_set_peer_identity_property_name(ctx_, name.c_str()) != 0; } bool SecureAuthContext::IsPeerAuthenticated() const { if (!ctx_) return false; return grpc_auth_context_peer_is_authenticated(ctx_) != 0; } } // namespace grpc grpc-1.3.2/src/cpp/common/secure_auth_context.h000066400000000000000000000051101310511640000215210ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_CPP_COMMON_SECURE_AUTH_CONTEXT_H #define GRPC_INTERNAL_CPP_COMMON_SECURE_AUTH_CONTEXT_H #include struct grpc_auth_context; namespace grpc { class SecureAuthContext final : public AuthContext { public: SecureAuthContext(grpc_auth_context* ctx, bool take_ownership); ~SecureAuthContext() override; bool IsPeerAuthenticated() const override; std::vector GetPeerIdentity() const override; grpc::string GetPeerIdentityPropertyName() const override; std::vector FindPropertyValues( const grpc::string& name) const override; AuthPropertyIterator begin() const override; AuthPropertyIterator end() const override; void AddProperty(const grpc::string& key, const grpc::string_ref& value) override; virtual bool SetPeerIdentityPropertyName(const grpc::string& name) override; private: grpc_auth_context* ctx_; bool take_ownership_; }; } // namespace grpc #endif // GRPC_INTERNAL_CPP_COMMON_SECURE_AUTH_CONTEXT_H grpc-1.3.2/src/cpp/common/secure_channel_arguments.cc000066400000000000000000000041141310511640000226520ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include "src/core/lib/channel/channel_args.h" namespace grpc { void ChannelArguments::SetSslTargetNameOverride(const grpc::string& name) { SetString(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, name); } grpc::string ChannelArguments::GetSslTargetNameOverride() const { for (unsigned int i = 0; i < args_.size(); i++) { if (grpc::string(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) == args_[i].key) { return args_[i].value.string; } } return ""; } } // namespace grpc grpc-1.3.2/src/cpp/common/secure_create_auth_context.cc000066400000000000000000000037651310511640000232200ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include "src/cpp/common/secure_auth_context.h" namespace grpc { std::shared_ptr CreateAuthContext(grpc_call* call) { if (call == nullptr) { return std::shared_ptr(); } return std::shared_ptr( new SecureAuthContext(grpc_call_auth_context(call), true)); } } // namespace grpc grpc-1.3.2/src/cpp/common/version_cc.cc000066400000000000000000000033251310511640000177440ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* This file is autogenerated from: templates/src/core/surface/version.c.template */ #include namespace grpc { grpc::string Version() { return "1.3.2"; } } grpc-1.3.2/src/cpp/ext/000077500000000000000000000000001310511640000146105ustar00rootroot00000000000000grpc-1.3.2/src/cpp/ext/proto_server_reflection.cc000066400000000000000000000201421310511640000220610ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include "src/cpp/ext/proto_server_reflection.h" using grpc::Status; using grpc::StatusCode; using grpc::reflection::v1alpha::ServerReflectionRequest; using grpc::reflection::v1alpha::ExtensionRequest; using grpc::reflection::v1alpha::ServerReflectionResponse; using grpc::reflection::v1alpha::ListServiceResponse; using grpc::reflection::v1alpha::ServiceResponse; using grpc::reflection::v1alpha::ExtensionNumberResponse; using grpc::reflection::v1alpha::ErrorResponse; using grpc::reflection::v1alpha::FileDescriptorResponse; namespace grpc { ProtoServerReflection::ProtoServerReflection() : descriptor_pool_(protobuf::DescriptorPool::generated_pool()) {} void ProtoServerReflection::SetServiceList( const std::vector* services) { services_ = services; } Status ProtoServerReflection::ServerReflectionInfo( ServerContext* context, ServerReaderWriter* stream) { ServerReflectionRequest request; ServerReflectionResponse response; Status status; while (stream->Read(&request)) { switch (request.message_request_case()) { case ServerReflectionRequest::MessageRequestCase::kFileByFilename: status = GetFileByName(context, request.file_by_filename(), &response); break; case ServerReflectionRequest::MessageRequestCase::kFileContainingSymbol: status = GetFileContainingSymbol( context, request.file_containing_symbol(), &response); break; case ServerReflectionRequest::MessageRequestCase:: kFileContainingExtension: status = GetFileContainingExtension( context, &request.file_containing_extension(), &response); break; case ServerReflectionRequest::MessageRequestCase:: kAllExtensionNumbersOfType: status = GetAllExtensionNumbers( context, request.all_extension_numbers_of_type(), response.mutable_all_extension_numbers_response()); break; case ServerReflectionRequest::MessageRequestCase::kListServices: status = ListService(context, response.mutable_list_services_response()); break; default: status = Status(StatusCode::UNIMPLEMENTED, ""); } if (!status.ok()) { FillErrorResponse(status, response.mutable_error_response()); } response.set_valid_host(request.host()); response.set_allocated_original_request( new ServerReflectionRequest(request)); stream->Write(response); } return Status::OK; } void ProtoServerReflection::FillErrorResponse(const Status& status, ErrorResponse* error_response) { error_response->set_error_code(status.error_code()); error_response->set_error_message(status.error_message()); } Status ProtoServerReflection::ListService(ServerContext* context, ListServiceResponse* response) { if (services_ == nullptr) { return Status(StatusCode::NOT_FOUND, "Services not found."); } for (auto it = services_->begin(); it != services_->end(); ++it) { ServiceResponse* service_response = response->add_service(); service_response->set_name(*it); } return Status::OK; } Status ProtoServerReflection::GetFileByName( ServerContext* context, const grpc::string& filename, ServerReflectionResponse* response) { if (descriptor_pool_ == nullptr) { return Status::CANCELLED; } const protobuf::FileDescriptor* file_desc = descriptor_pool_->FindFileByName(filename); if (file_desc == nullptr) { return Status(StatusCode::NOT_FOUND, "File not found."); } std::unordered_set seen_files; FillFileDescriptorResponse(file_desc, response, &seen_files); return Status::OK; } Status ProtoServerReflection::GetFileContainingSymbol( ServerContext* context, const grpc::string& symbol, ServerReflectionResponse* response) { if (descriptor_pool_ == nullptr) { return Status::CANCELLED; } const protobuf::FileDescriptor* file_desc = descriptor_pool_->FindFileContainingSymbol(symbol); if (file_desc == nullptr) { return Status(StatusCode::NOT_FOUND, "Symbol not found."); } std::unordered_set seen_files; FillFileDescriptorResponse(file_desc, response, &seen_files); return Status::OK; } Status ProtoServerReflection::GetFileContainingExtension( ServerContext* context, const ExtensionRequest* request, ServerReflectionResponse* response) { if (descriptor_pool_ == nullptr) { return Status::CANCELLED; } const protobuf::Descriptor* desc = descriptor_pool_->FindMessageTypeByName(request->containing_type()); if (desc == nullptr) { return Status(StatusCode::NOT_FOUND, "Type not found."); } const protobuf::FieldDescriptor* field_desc = descriptor_pool_->FindExtensionByNumber(desc, request->extension_number()); if (field_desc == nullptr) { return Status(StatusCode::NOT_FOUND, "Extension not found."); } std::unordered_set seen_files; FillFileDescriptorResponse(field_desc->file(), response, &seen_files); return Status::OK; } Status ProtoServerReflection::GetAllExtensionNumbers( ServerContext* context, const grpc::string& type, ExtensionNumberResponse* response) { if (descriptor_pool_ == nullptr) { return Status::CANCELLED; } const protobuf::Descriptor* desc = descriptor_pool_->FindMessageTypeByName(type); if (desc == nullptr) { return Status(StatusCode::NOT_FOUND, "Type not found."); } std::vector extensions; descriptor_pool_->FindAllExtensions(desc, &extensions); for (auto it = extensions.begin(); it != extensions.end(); it++) { response->add_extension_number((*it)->number()); } response->set_base_type_name(type); return Status::OK; } void ProtoServerReflection::FillFileDescriptorResponse( const protobuf::FileDescriptor* file_desc, ServerReflectionResponse* response, std::unordered_set* seen_files) { if (seen_files->find(file_desc->name()) != seen_files->end()) { return; } seen_files->insert(file_desc->name()); protobuf::FileDescriptorProto file_desc_proto; grpc::string data; file_desc->CopyTo(&file_desc_proto); file_desc_proto.SerializeToString(&data); response->mutable_file_descriptor_response()->add_file_descriptor_proto(data); for (int i = 0; i < file_desc->dependency_count(); ++i) { FillFileDescriptorResponse(file_desc->dependency(i), response, seen_files); } } } // namespace grpc grpc-1.3.2/src/cpp/ext/proto_server_reflection.h000066400000000000000000000072151310511640000217310ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_CPP_EXT_PROTO_SERVER_REFLECTION_H #define GRPC_INTERNAL_CPP_EXT_PROTO_SERVER_REFLECTION_H #include #include #include #include "src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h" namespace grpc { class ProtoServerReflection final : public reflection::v1alpha::ServerReflection::Service { public: ProtoServerReflection(); // Add the full names of registered services void SetServiceList(const std::vector* services); // implementation of ServerReflectionInfo(stream ServerReflectionRequest) rpc // in ServerReflection service Status ServerReflectionInfo( ServerContext* context, ServerReaderWriter* stream) override; private: Status ListService(ServerContext* context, reflection::v1alpha::ListServiceResponse* response); Status GetFileByName(ServerContext* context, const grpc::string& file_name, reflection::v1alpha::ServerReflectionResponse* response); Status GetFileContainingSymbol( ServerContext* context, const grpc::string& symbol, reflection::v1alpha::ServerReflectionResponse* response); Status GetFileContainingExtension( ServerContext* context, const reflection::v1alpha::ExtensionRequest* request, reflection::v1alpha::ServerReflectionResponse* response); Status GetAllExtensionNumbers( ServerContext* context, const grpc::string& type, reflection::v1alpha::ExtensionNumberResponse* response); void FillFileDescriptorResponse( const protobuf::FileDescriptor* file_desc, reflection::v1alpha::ServerReflectionResponse* response, std::unordered_set* seen_files); void FillErrorResponse(const Status& status, reflection::v1alpha::ErrorResponse* error_response); const protobuf::DescriptorPool* descriptor_pool_; const std::vector* services_; }; } // namespace grpc #endif // GRPC_INTERNAL_CPP_EXT_PROTO_SERVER_REFLECTION_H grpc-1.3.2/src/cpp/ext/proto_server_reflection_plugin.cc000066400000000000000000000066761310511640000234570ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include "src/cpp/ext/proto_server_reflection.h" namespace grpc { namespace reflection { ProtoServerReflectionPlugin::ProtoServerReflectionPlugin() : reflection_service_(new grpc::ProtoServerReflection()) {} grpc::string ProtoServerReflectionPlugin::name() { return "proto_server_reflection"; } void ProtoServerReflectionPlugin::InitServer(grpc::ServerInitializer* si) { si->RegisterService(reflection_service_); } void ProtoServerReflectionPlugin::Finish(grpc::ServerInitializer* si) { reflection_service_->SetServiceList(si->GetServiceList()); } void ProtoServerReflectionPlugin::ChangeArguments(const grpc::string& name, void* value) {} bool ProtoServerReflectionPlugin::has_sync_methods() const { if (reflection_service_) { return reflection_service_->has_synchronous_methods(); } return false; } bool ProtoServerReflectionPlugin::has_async_methods() const { if (reflection_service_) { return reflection_service_->has_async_methods(); } return false; } static std::unique_ptr< ::grpc::ServerBuilderPlugin> CreateProtoReflection() { return std::unique_ptr< ::grpc::ServerBuilderPlugin>( new ProtoServerReflectionPlugin()); } void InitProtoReflectionServerBuilderPlugin() { static bool already_here = false; if (already_here) return; already_here = true; ::grpc::ServerBuilder::InternalAddPluginFactory(&CreateProtoReflection); } // Force InitProtoReflectionServerBuilderPlugin() to be called at static // initialization time. struct StaticProtoReflectionPluginInitializer { StaticProtoReflectionPluginInitializer() { InitProtoReflectionServerBuilderPlugin(); } } static_proto_reflection_plugin_initializer; } // namespace reflection } // namespace grpc grpc-1.3.2/src/cpp/server/000077500000000000000000000000001310511640000153165ustar00rootroot00000000000000grpc-1.3.2/src/cpp/server/async_generic_service.cc000066400000000000000000000037411310511640000221630ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include namespace grpc { void AsyncGenericService::RequestCall( GenericServerContext* ctx, GenericServerAsyncReaderWriter* reader_writer, CompletionQueue* call_cq, ServerCompletionQueue* notification_cq, void* tag) { server_->RequestAsyncGenericCall(ctx, reader_writer, call_cq, notification_cq, tag); } } // namespace grpc grpc-1.3.2/src/cpp/server/channel_argument_option.cc000066400000000000000000000056441310511640000225400ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include namespace grpc { std::unique_ptr MakeChannelArgumentOption( const grpc::string &name, const grpc::string &value) { class StringOption final : public ServerBuilderOption { public: StringOption(const grpc::string &name, const grpc::string &value) : name_(name), value_(value) {} virtual void UpdateArguments(ChannelArguments *args) override { args->SetString(name_, value_); } virtual void UpdatePlugins( std::vector> *plugins) override {} private: const grpc::string name_; const grpc::string value_; }; return std::unique_ptr(new StringOption(name, value)); } std::unique_ptr MakeChannelArgumentOption( const grpc::string &name, int value) { class IntOption final : public ServerBuilderOption { public: IntOption(const grpc::string &name, int value) : name_(name), value_(value) {} virtual void UpdateArguments(ChannelArguments *args) override { args->SetInt(name_, value_); } virtual void UpdatePlugins( std::vector> *plugins) override {} private: const grpc::string name_; const int value_; }; return std::unique_ptr(new IntOption(name, value)); } } // namespace grpc grpc-1.3.2/src/cpp/server/create_default_thread_pool.cc000066400000000000000000000036061310511640000231610ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "src/cpp/server/dynamic_thread_pool.h" #ifndef GRPC_CUSTOM_DEFAULT_THREAD_POOL namespace grpc { ThreadPoolInterface* CreateDefaultThreadPool() { int cores = gpr_cpu_num_cores(); if (!cores) cores = 4; return new DynamicThreadPool(cores); } } // namespace grpc #endif // !GRPC_CUSTOM_DEFAULT_THREAD_POOL grpc-1.3.2/src/cpp/server/dynamic_thread_pool.cc000066400000000000000000000103041310511640000216270ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/cpp/server/dynamic_thread_pool.h" #include #include #include namespace grpc { DynamicThreadPool::DynamicThread::DynamicThread(DynamicThreadPool* pool) : pool_(pool), thd_(new std::thread(&DynamicThreadPool::DynamicThread::ThreadFunc, this)) {} DynamicThreadPool::DynamicThread::~DynamicThread() { thd_->join(); thd_.reset(); } void DynamicThreadPool::DynamicThread::ThreadFunc() { pool_->ThreadFunc(); // Now that we have killed ourselves, we should reduce the thread count std::unique_lock lock(pool_->mu_); pool_->nthreads_--; // Move ourselves to dead list pool_->dead_threads_.push_back(this); if ((pool_->shutdown_) && (pool_->nthreads_ == 0)) { pool_->shutdown_cv_.notify_one(); } } void DynamicThreadPool::ThreadFunc() { for (;;) { // Wait until work is available or we are shutting down. std::unique_lock lock(mu_); if (!shutdown_ && callbacks_.empty()) { // If there are too many threads waiting, then quit this thread if (threads_waiting_ >= reserve_threads_) { break; } threads_waiting_++; cv_.wait(lock); threads_waiting_--; } // Drain callbacks before considering shutdown to ensure all work // gets completed. if (!callbacks_.empty()) { auto cb = callbacks_.front(); callbacks_.pop(); lock.unlock(); cb(); } else if (shutdown_) { break; } } } DynamicThreadPool::DynamicThreadPool(int reserve_threads) : shutdown_(false), reserve_threads_(reserve_threads), nthreads_(0), threads_waiting_(0) { for (int i = 0; i < reserve_threads_; i++) { std::lock_guard lock(mu_); nthreads_++; new DynamicThread(this); } } void DynamicThreadPool::ReapThreads(std::list* tlist) { for (auto t = tlist->begin(); t != tlist->end(); t = tlist->erase(t)) { delete *t; } } DynamicThreadPool::~DynamicThreadPool() { std::unique_lock lock(mu_); shutdown_ = true; cv_.notify_all(); while (nthreads_ != 0) { shutdown_cv_.wait(lock); } ReapThreads(&dead_threads_); } void DynamicThreadPool::Add(const std::function& callback) { std::lock_guard lock(mu_); // Add works to the callbacks list callbacks_.push(callback); // Increase pool size or notify as needed if (threads_waiting_ == 0) { // Kick off a new thread nthreads_++; new DynamicThread(this); } else { cv_.notify_one(); } // Also use this chance to harvest dead threads if (!dead_threads_.empty()) { ReapThreads(&dead_threads_); } } } // namespace grpc grpc-1.3.2/src/cpp/server/dynamic_thread_pool.h000066400000000000000000000052641310511640000215020ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_CPP_DYNAMIC_THREAD_POOL_H #define GRPC_INTERNAL_CPP_DYNAMIC_THREAD_POOL_H #include #include #include #include #include #include #include #include "src/cpp/server/thread_pool_interface.h" namespace grpc { class DynamicThreadPool final : public ThreadPoolInterface { public: explicit DynamicThreadPool(int reserve_threads); ~DynamicThreadPool(); void Add(const std::function& callback) override; private: class DynamicThread { public: DynamicThread(DynamicThreadPool* pool); ~DynamicThread(); private: DynamicThreadPool* pool_; std::unique_ptr thd_; void ThreadFunc(); }; std::mutex mu_; std::condition_variable cv_; std::condition_variable shutdown_cv_; bool shutdown_; std::queue> callbacks_; int reserve_threads_; int nthreads_; int threads_waiting_; std::list dead_threads_; void ThreadFunc(); static void ReapThreads(std::list* tlist); }; } // namespace grpc #endif // GRPC_INTERNAL_CPP_DYNAMIC_THREAD_POOL_H grpc-1.3.2/src/cpp/server/health/000077500000000000000000000000001310511640000165635ustar00rootroot00000000000000grpc-1.3.2/src/cpp/server/health/default_health_check_service.cc000066400000000000000000000143361310511640000247270ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include "src/cpp/server/health/default_health_check_service.h" #include "src/cpp/server/health/health.pb.h" #include "third_party/nanopb/pb_decode.h" #include "third_party/nanopb/pb_encode.h" namespace grpc { namespace { const char kHealthCheckMethodName[] = "/grpc.health.v1.Health/Check"; } // namespace DefaultHealthCheckService::HealthCheckServiceImpl::HealthCheckServiceImpl( DefaultHealthCheckService* service) : service_(service), method_(nullptr) { MethodHandler* handler = new RpcMethodHandler( std::mem_fn(&HealthCheckServiceImpl::Check), this); method_ = new RpcServiceMethod(kHealthCheckMethodName, RpcMethod::NORMAL_RPC, handler); AddMethod(method_); } Status DefaultHealthCheckService::HealthCheckServiceImpl::Check( ServerContext* context, const ByteBuffer* request, ByteBuffer* response) { // Decode request. std::vector slices; if (!request->Dump(&slices).ok()) { return Status(StatusCode::INVALID_ARGUMENT, ""); } uint8_t* request_bytes = nullptr; bool request_bytes_owned = false; size_t request_size = 0; grpc_health_v1_HealthCheckRequest request_struct; if (slices.empty()) { request_struct.has_service = false; } else if (slices.size() == 1) { request_bytes = const_cast(slices[0].begin()); request_size = slices[0].size(); } else { request_bytes_owned = true; request_bytes = static_cast(gpr_malloc(request->Length())); uint8_t* copy_to = request_bytes; for (size_t i = 0; i < slices.size(); i++) { memcpy(copy_to, slices[i].begin(), slices[i].size()); copy_to += slices[i].size(); } } if (request_bytes != nullptr) { pb_istream_t istream = pb_istream_from_buffer(request_bytes, request_size); bool decode_status = pb_decode( &istream, grpc_health_v1_HealthCheckRequest_fields, &request_struct); if (request_bytes_owned) { gpr_free(request_bytes); } if (!decode_status) { return Status(StatusCode::INVALID_ARGUMENT, ""); } } // Check status from the associated default health checking service. DefaultHealthCheckService::ServingStatus serving_status = service_->GetServingStatus( request_struct.has_service ? request_struct.service : ""); if (serving_status == DefaultHealthCheckService::NOT_FOUND) { return Status(StatusCode::NOT_FOUND, ""); } // Encode response grpc_health_v1_HealthCheckResponse response_struct; response_struct.has_status = true; response_struct.status = serving_status == DefaultHealthCheckService::SERVING ? grpc_health_v1_HealthCheckResponse_ServingStatus_SERVING : grpc_health_v1_HealthCheckResponse_ServingStatus_NOT_SERVING; pb_ostream_t ostream; memset(&ostream, 0, sizeof(ostream)); pb_encode(&ostream, grpc_health_v1_HealthCheckResponse_fields, &response_struct); grpc_slice response_slice = grpc_slice_malloc(ostream.bytes_written); ostream = pb_ostream_from_buffer(GRPC_SLICE_START_PTR(response_slice), GRPC_SLICE_LENGTH(response_slice)); bool encode_status = pb_encode( &ostream, grpc_health_v1_HealthCheckResponse_fields, &response_struct); if (!encode_status) { return Status(StatusCode::INTERNAL, "Failed to encode response."); } Slice encoded_response(response_slice, Slice::STEAL_REF); ByteBuffer response_buffer(&encoded_response, 1); response->Swap(&response_buffer); return Status::OK; } DefaultHealthCheckService::DefaultHealthCheckService() { services_map_.emplace("", true); } void DefaultHealthCheckService::SetServingStatus( const grpc::string& service_name, bool serving) { std::lock_guard lock(mu_); services_map_[service_name] = serving; } void DefaultHealthCheckService::SetServingStatus(bool serving) { std::lock_guard lock(mu_); for (auto iter = services_map_.begin(); iter != services_map_.end(); ++iter) { iter->second = serving; } } DefaultHealthCheckService::ServingStatus DefaultHealthCheckService::GetServingStatus( const grpc::string& service_name) const { std::lock_guard lock(mu_); const auto& iter = services_map_.find(service_name); if (iter == services_map_.end()) { return NOT_FOUND; } return iter->second ? SERVING : NOT_SERVING; } DefaultHealthCheckService::HealthCheckServiceImpl* DefaultHealthCheckService::GetHealthCheckService() { GPR_ASSERT(impl_ == nullptr); impl_.reset(new HealthCheckServiceImpl(this)); return impl_.get(); } } // namespace grpc grpc-1.3.2/src/cpp/server/health/default_health_check_service.h000066400000000000000000000057411310511640000245710ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_CPP_SERVER_DEFAULT_HEALTH_CHECK_SERVICE_H #define GRPC_INTERNAL_CPP_SERVER_DEFAULT_HEALTH_CHECK_SERVICE_H #include #include #include #include namespace grpc { // Default implementation of HealthCheckServiceInterface. Server will create and // own it. class DefaultHealthCheckService final : public HealthCheckServiceInterface { public: // The service impl to register with the server. class HealthCheckServiceImpl : public Service { public: explicit HealthCheckServiceImpl(DefaultHealthCheckService* service); Status Check(ServerContext* context, const ByteBuffer* request, ByteBuffer* response); private: const DefaultHealthCheckService* const service_; RpcServiceMethod* method_; }; DefaultHealthCheckService(); void SetServingStatus(const grpc::string& service_name, bool serving) override; void SetServingStatus(bool serving) override; enum ServingStatus { NOT_FOUND, SERVING, NOT_SERVING }; ServingStatus GetServingStatus(const grpc::string& service_name) const; HealthCheckServiceImpl* GetHealthCheckService(); private: mutable std::mutex mu_; std::map services_map_; std::unique_ptr impl_; }; } // namespace grpc #endif // GRPC_INTERNAL_CPP_SERVER_DEFAULT_HEALTH_CHECK_SERVICE_H grpc-1.3.2/src/cpp/server/health/health.pb.c000066400000000000000000000013371310511640000206000ustar00rootroot00000000000000/* Automatically generated nanopb constant definitions */ /* Generated by nanopb-0.3.7-dev */ #include "src/cpp/server/health/health.pb.h" /* @@protoc_insertion_point(includes) */ #if PB_PROTO_HEADER_VERSION != 30 #error Regenerate this file with the current version of nanopb generator. #endif const pb_field_t grpc_health_v1_HealthCheckRequest_fields[2] = { PB_FIELD( 1, STRING , OPTIONAL, STATIC , FIRST, grpc_health_v1_HealthCheckRequest, service, service, 0), PB_LAST_FIELD }; const pb_field_t grpc_health_v1_HealthCheckResponse_fields[2] = { PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, grpc_health_v1_HealthCheckResponse, status, status, 0), PB_LAST_FIELD }; /* @@protoc_insertion_point(eof) */ grpc-1.3.2/src/cpp/server/health/health.pb.h000066400000000000000000000054001310511640000206000ustar00rootroot00000000000000/* Automatically generated nanopb header */ /* Generated by nanopb-0.3.7-dev */ #ifndef PB_GRPC_HEALTH_V1_HEALTH_PB_H_INCLUDED #define PB_GRPC_HEALTH_V1_HEALTH_PB_H_INCLUDED #include "third_party/nanopb/pb.h" /* @@protoc_insertion_point(includes) */ #if PB_PROTO_HEADER_VERSION != 30 #error Regenerate this file with the current version of nanopb generator. #endif #ifdef __cplusplus extern "C" { #endif /* Enum definitions */ typedef enum _grpc_health_v1_HealthCheckResponse_ServingStatus { grpc_health_v1_HealthCheckResponse_ServingStatus_UNKNOWN = 0, grpc_health_v1_HealthCheckResponse_ServingStatus_SERVING = 1, grpc_health_v1_HealthCheckResponse_ServingStatus_NOT_SERVING = 2 } grpc_health_v1_HealthCheckResponse_ServingStatus; #define _grpc_health_v1_HealthCheckResponse_ServingStatus_MIN grpc_health_v1_HealthCheckResponse_ServingStatus_UNKNOWN #define _grpc_health_v1_HealthCheckResponse_ServingStatus_MAX grpc_health_v1_HealthCheckResponse_ServingStatus_NOT_SERVING #define _grpc_health_v1_HealthCheckResponse_ServingStatus_ARRAYSIZE ((grpc_health_v1_HealthCheckResponse_ServingStatus)(grpc_health_v1_HealthCheckResponse_ServingStatus_NOT_SERVING+1)) /* Struct definitions */ typedef struct _grpc_health_v1_HealthCheckRequest { bool has_service; char service[200]; /* @@protoc_insertion_point(struct:grpc_health_v1_HealthCheckRequest) */ } grpc_health_v1_HealthCheckRequest; typedef struct _grpc_health_v1_HealthCheckResponse { bool has_status; grpc_health_v1_HealthCheckResponse_ServingStatus status; /* @@protoc_insertion_point(struct:grpc_health_v1_HealthCheckResponse) */ } grpc_health_v1_HealthCheckResponse; /* Default values for struct fields */ /* Initializer values for message structs */ #define grpc_health_v1_HealthCheckRequest_init_default {false, ""} #define grpc_health_v1_HealthCheckResponse_init_default {false, (grpc_health_v1_HealthCheckResponse_ServingStatus)0} #define grpc_health_v1_HealthCheckRequest_init_zero {false, ""} #define grpc_health_v1_HealthCheckResponse_init_zero {false, (grpc_health_v1_HealthCheckResponse_ServingStatus)0} /* Field tags (for use in manual encoding/decoding) */ #define grpc_health_v1_HealthCheckRequest_service_tag 1 #define grpc_health_v1_HealthCheckResponse_status_tag 1 /* Struct field encoding specification for nanopb */ extern const pb_field_t grpc_health_v1_HealthCheckRequest_fields[2]; extern const pb_field_t grpc_health_v1_HealthCheckResponse_fields[2]; /* Maximum encoded size of messages (where known) */ #define grpc_health_v1_HealthCheckRequest_size 203 #define grpc_health_v1_HealthCheckResponse_size 2 /* Message IDs (where set with "msgid" option) */ #ifdef PB_MSGID #define HEALTH_MESSAGES \ #endif #ifdef __cplusplus } /* extern "C" */ #endif /* @@protoc_insertion_point(eof) */ #endif grpc-1.3.2/src/cpp/server/health/health_check_service.cc000066400000000000000000000036451310511640000232240ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include namespace grpc { namespace { bool g_grpc_default_health_check_service_enabled = false; } // namesapce bool DefaultHealthCheckServiceEnabled() { return g_grpc_default_health_check_service_enabled; } void EnableDefaultHealthCheckService(bool enable) { g_grpc_default_health_check_service_enabled = enable; } } // namespace grpc grpc-1.3.2/src/cpp/server/health/health_check_service_server_builder_option.cc000066400000000000000000000041551310511640000277050ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include namespace grpc { HealthCheckServiceServerBuilderOption::HealthCheckServiceServerBuilderOption( std::unique_ptr hc) : hc_(std::move(hc)) {} // Hand over hc_ to the server. void HealthCheckServiceServerBuilderOption::UpdateArguments( ChannelArguments* args) { args->SetPointer(kHealthCheckServiceInterfaceArg, hc_.release()); } void HealthCheckServiceServerBuilderOption::UpdatePlugins( std::vector>* plugins) {} } // namespace grpc grpc-1.3.2/src/cpp/server/insecure_server_credentials.cc000066400000000000000000000044441310511640000234130ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include namespace grpc { namespace { class InsecureServerCredentialsImpl final : public ServerCredentials { public: int AddPortToServer(const grpc::string& addr, grpc_server* server) override { return grpc_server_add_insecure_http2_port(server, addr.c_str()); } void SetAuthMetadataProcessor( const std::shared_ptr& processor) override { (void)processor; GPR_ASSERT(0); // Should not be called on InsecureServerCredentials. } }; } // namespace std::shared_ptr InsecureServerCredentials() { return std::shared_ptr( new InsecureServerCredentialsImpl()); } } // namespace grpc grpc-1.3.2/src/cpp/server/secure_server_credentials.cc000066400000000000000000000136221310511640000230620ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include "src/cpp/common/secure_auth_context.h" #include "src/cpp/server/secure_server_credentials.h" namespace grpc { void AuthMetadataProcessorAyncWrapper::Destroy(void* wrapper) { auto* w = reinterpret_cast(wrapper); delete w; } void AuthMetadataProcessorAyncWrapper::Process( void* wrapper, grpc_auth_context* context, const grpc_metadata* md, size_t num_md, grpc_process_auth_metadata_done_cb cb, void* user_data) { auto* w = reinterpret_cast(wrapper); if (!w->processor_) { // Early exit. cb(user_data, nullptr, 0, nullptr, 0, GRPC_STATUS_OK, nullptr); return; } if (w->processor_->IsBlocking()) { w->thread_pool_->Add( std::bind(&AuthMetadataProcessorAyncWrapper::InvokeProcessor, w, context, md, num_md, cb, user_data)); } else { // invoke directly. w->InvokeProcessor(context, md, num_md, cb, user_data); } } void AuthMetadataProcessorAyncWrapper::InvokeProcessor( grpc_auth_context* ctx, const grpc_metadata* md, size_t num_md, grpc_process_auth_metadata_done_cb cb, void* user_data) { AuthMetadataProcessor::InputMetadata metadata; for (size_t i = 0; i < num_md; i++) { metadata.insert(std::make_pair(StringRefFromSlice(&md[i].key), StringRefFromSlice(&md[i].value))); } SecureAuthContext context(ctx, false); AuthMetadataProcessor::OutputMetadata consumed_metadata; AuthMetadataProcessor::OutputMetadata response_metadata; Status status = processor_->Process(metadata, &context, &consumed_metadata, &response_metadata); std::vector consumed_md; for (auto it = consumed_metadata.begin(); it != consumed_metadata.end(); ++it) { grpc_metadata md_entry; md_entry.key = SliceReferencingString(it->first); md_entry.value = SliceReferencingString(it->second); md_entry.flags = 0; consumed_md.push_back(md_entry); } std::vector response_md; for (auto it = response_metadata.begin(); it != response_metadata.end(); ++it) { grpc_metadata md_entry; md_entry.key = SliceReferencingString(it->first); md_entry.value = SliceReferencingString(it->second); md_entry.flags = 0; response_md.push_back(md_entry); } auto consumed_md_data = consumed_md.empty() ? nullptr : &consumed_md[0]; auto response_md_data = response_md.empty() ? nullptr : &response_md[0]; cb(user_data, consumed_md_data, consumed_md.size(), response_md_data, response_md.size(), static_cast(status.error_code()), status.error_message().c_str()); } int SecureServerCredentials::AddPortToServer(const grpc::string& addr, grpc_server* server) { return grpc_server_add_secure_http2_port(server, addr.c_str(), creds_); } void SecureServerCredentials::SetAuthMetadataProcessor( const std::shared_ptr& processor) { auto* wrapper = new AuthMetadataProcessorAyncWrapper(processor); grpc_server_credentials_set_auth_metadata_processor( creds_, {AuthMetadataProcessorAyncWrapper::Process, AuthMetadataProcessorAyncWrapper::Destroy, wrapper}); } std::shared_ptr SslServerCredentials( const SslServerCredentialsOptions& options) { std::vector pem_key_cert_pairs; for (auto key_cert_pair = options.pem_key_cert_pairs.begin(); key_cert_pair != options.pem_key_cert_pairs.end(); key_cert_pair++) { grpc_ssl_pem_key_cert_pair p = {key_cert_pair->private_key.c_str(), key_cert_pair->cert_chain.c_str()}; pem_key_cert_pairs.push_back(p); } grpc_server_credentials* c_creds = grpc_ssl_server_credentials_create_ex( options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(), pem_key_cert_pairs.empty() ? nullptr : &pem_key_cert_pairs[0], pem_key_cert_pairs.size(), options.force_client_auth ? GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY : options.client_certificate_request, nullptr); return std::shared_ptr( new SecureServerCredentials(c_creds)); } } // namespace grpc grpc-1.3.2/src/cpp/server/secure_server_credentials.h000066400000000000000000000063371310511640000227310ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_CPP_SERVER_SECURE_SERVER_CREDENTIALS_H #define GRPC_INTERNAL_CPP_SERVER_SECURE_SERVER_CREDENTIALS_H #include #include #include #include "src/cpp/server/thread_pool_interface.h" namespace grpc { class AuthMetadataProcessorAyncWrapper final { public: static void Destroy(void* wrapper); static void Process(void* wrapper, grpc_auth_context* context, const grpc_metadata* md, size_t num_md, grpc_process_auth_metadata_done_cb cb, void* user_data); AuthMetadataProcessorAyncWrapper( const std::shared_ptr& processor) : thread_pool_(CreateDefaultThreadPool()), processor_(processor) {} private: void InvokeProcessor(grpc_auth_context* context, const grpc_metadata* md, size_t num_md, grpc_process_auth_metadata_done_cb cb, void* user_data); std::unique_ptr thread_pool_; std::shared_ptr processor_; }; class SecureServerCredentials final : public ServerCredentials { public: explicit SecureServerCredentials(grpc_server_credentials* creds) : creds_(creds) {} ~SecureServerCredentials() override { grpc_server_credentials_release(creds_); } int AddPortToServer(const grpc::string& addr, grpc_server* server) override; void SetAuthMetadataProcessor( const std::shared_ptr& processor) override; private: grpc_server_credentials* creds_; std::unique_ptr processor_; }; } // namespace grpc #endif // GRPC_INTERNAL_CPP_SERVER_SECURE_SERVER_CREDENTIALS_H grpc-1.3.2/src/cpp/server/server_builder.cc000066400000000000000000000300421310511640000206400ustar00rootroot00000000000000/* * * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include "src/cpp/server/thread_pool_interface.h" namespace grpc { static std::vector (*)()>* g_plugin_factory_list; static gpr_once once_init_plugin_list = GPR_ONCE_INIT; static void do_plugin_list_init(void) { g_plugin_factory_list = new std::vector (*)()>(); } ServerBuilder::ServerBuilder() : max_receive_message_size_(-1), max_send_message_size_(-1), sync_server_settings_(SyncServerSettings()), resource_quota_(nullptr), generic_service_(nullptr) { gpr_once_init(&once_init_plugin_list, do_plugin_list_init); for (auto it = g_plugin_factory_list->begin(); it != g_plugin_factory_list->end(); it++) { auto& factory = *it; plugins_.emplace_back(factory()); } // all compression algorithms enabled by default. enabled_compression_algorithms_bitset_ = (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1; memset(&maybe_default_compression_level_, 0, sizeof(maybe_default_compression_level_)); memset(&maybe_default_compression_algorithm_, 0, sizeof(maybe_default_compression_algorithm_)); } ServerBuilder::~ServerBuilder() { if (resource_quota_ != nullptr) { grpc_resource_quota_unref(resource_quota_); } } std::unique_ptr ServerBuilder::AddCompletionQueue( bool is_frequently_polled) { ServerCompletionQueue* cq = new ServerCompletionQueue(is_frequently_polled); cqs_.push_back(cq); return std::unique_ptr(cq); } ServerBuilder& ServerBuilder::RegisterService(Service* service) { services_.emplace_back(new NamedService(service)); return *this; } ServerBuilder& ServerBuilder::RegisterService(const grpc::string& addr, Service* service) { services_.emplace_back(new NamedService(addr, service)); return *this; } ServerBuilder& ServerBuilder::RegisterAsyncGenericService( AsyncGenericService* service) { if (generic_service_) { gpr_log(GPR_ERROR, "Adding multiple AsyncGenericService is unsupported for now. " "Dropping the service %p", (void*)service); } else { generic_service_ = service; } return *this; } ServerBuilder& ServerBuilder::SetOption( std::unique_ptr option) { options_.push_back(std::move(option)); return *this; } ServerBuilder& ServerBuilder::SetSyncServerOption( ServerBuilder::SyncServerOption option, int val) { switch (option) { case NUM_CQS: sync_server_settings_.num_cqs = val; break; case MIN_POLLERS: sync_server_settings_.min_pollers = val; break; case MAX_POLLERS: sync_server_settings_.max_pollers = val; break; case CQ_TIMEOUT_MSEC: sync_server_settings_.cq_timeout_msec = val; break; } return *this; } ServerBuilder& ServerBuilder::SetCompressionAlgorithmSupportStatus( grpc_compression_algorithm algorithm, bool enabled) { if (enabled) { GPR_BITSET(&enabled_compression_algorithms_bitset_, algorithm); } else { GPR_BITCLEAR(&enabled_compression_algorithms_bitset_, algorithm); } return *this; } ServerBuilder& ServerBuilder::SetDefaultCompressionLevel( grpc_compression_level level) { maybe_default_compression_level_.level = level; return *this; } ServerBuilder& ServerBuilder::SetDefaultCompressionAlgorithm( grpc_compression_algorithm algorithm) { maybe_default_compression_algorithm_.is_set = true; maybe_default_compression_algorithm_.algorithm = algorithm; return *this; } ServerBuilder& ServerBuilder::SetResourceQuota( const grpc::ResourceQuota& resource_quota) { if (resource_quota_ != nullptr) { grpc_resource_quota_unref(resource_quota_); } resource_quota_ = resource_quota.c_resource_quota(); grpc_resource_quota_ref(resource_quota_); return *this; } ServerBuilder& ServerBuilder::AddListeningPort( const grpc::string& addr, std::shared_ptr creds, int* selected_port) { Port port = {addr, creds, selected_port}; ports_.push_back(port); return *this; } std::unique_ptr ServerBuilder::BuildAndStart() { ChannelArguments args; for (auto option = options_.begin(); option != options_.end(); ++option) { (*option)->UpdateArguments(&args); (*option)->UpdatePlugins(&plugins_); } for (auto plugin = plugins_.begin(); plugin != plugins_.end(); plugin++) { (*plugin)->UpdateChannelArguments(&args); } if (max_receive_message_size_ >= 0) { args.SetInt(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, max_receive_message_size_); } if (max_send_message_size_ >= 0) { args.SetInt(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, max_send_message_size_); } args.SetInt(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET, enabled_compression_algorithms_bitset_); if (maybe_default_compression_level_.is_set) { args.SetInt(GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL, maybe_default_compression_level_.level); } if (maybe_default_compression_algorithm_.is_set) { args.SetInt(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, maybe_default_compression_algorithm_.algorithm); } if (resource_quota_ != nullptr) { args.SetPointerWithVtable(GRPC_ARG_RESOURCE_QUOTA, resource_quota_, grpc_resource_quota_arg_vtable()); } // == Determine if the server has any syncrhonous methods == bool has_sync_methods = false; for (auto it = services_.begin(); it != services_.end(); ++it) { if ((*it)->service->has_synchronous_methods()) { has_sync_methods = true; break; } } if (!has_sync_methods) { for (auto plugin = plugins_.begin(); plugin != plugins_.end(); plugin++) { if ((*plugin)->has_sync_methods()) { has_sync_methods = true; break; } } } // If this is a Sync server, i.e a server expositing sync API, then the server // needs to create some completion queues to listen for incoming requests. // 'sync_server_cqs' are those internal completion queues. // // This is different from the completion queues added to the server via // ServerBuilder's AddCompletionQueue() method (those completion queues // are in 'cqs_' member variable of ServerBuilder object) std::shared_ptr>> sync_server_cqs(std::make_shared< std::vector>>()); if (has_sync_methods) { // This is a Sync server gpr_log(GPR_INFO, "Synchronous server. Num CQs: %d, Min pollers: %d, Max Pollers: " "%d, CQ timeout (msec): %d", sync_server_settings_.num_cqs, sync_server_settings_.min_pollers, sync_server_settings_.max_pollers, sync_server_settings_.cq_timeout_msec); // Create completion queues to listen to incoming rpc requests for (int i = 0; i < sync_server_settings_.num_cqs; i++) { sync_server_cqs->emplace_back(new ServerCompletionQueue()); } } std::unique_ptr server(new Server( max_receive_message_size_, &args, sync_server_cqs, sync_server_settings_.min_pollers, sync_server_settings_.max_pollers, sync_server_settings_.cq_timeout_msec)); ServerInitializer* initializer = server->initializer(); // Register all the completion queues with the server. i.e // 1. sync_server_cqs: internal completion queues created IF this is a sync // server // 2. cqs_: Completion queues added via AddCompletionQueue() call // All sync cqs (if any) are frequently polled by ThreadManager int num_frequently_polled_cqs = sync_server_cqs->size(); for (auto it = sync_server_cqs->begin(); it != sync_server_cqs->end(); ++it) { grpc_server_register_completion_queue(server->server_, (*it)->cq(), nullptr); } // cqs_ contains the completion queue added by calling the ServerBuilder's // AddCompletionQueue() API. Some of them may not be frequently polled (i.e by // calling Next() or AsyncNext()) and hence are not safe to be used for // listening to incoming channels. Such completion queues must be registered // as non-listening queues for (auto it = cqs_.begin(); it != cqs_.end(); ++it) { if ((*it)->IsFrequentlyPolled()) { grpc_server_register_completion_queue(server->server_, (*it)->cq(), nullptr); num_frequently_polled_cqs++; } else { grpc_server_register_non_listening_completion_queue(server->server_, (*it)->cq(), nullptr); } } if (num_frequently_polled_cqs == 0) { gpr_log(GPR_ERROR, "At least one of the completion queues must be frequently polled"); return nullptr; } for (auto service = services_.begin(); service != services_.end(); service++) { if (!server->RegisterService((*service)->host.get(), (*service)->service)) { return nullptr; } } for (auto plugin = plugins_.begin(); plugin != plugins_.end(); plugin++) { (*plugin)->InitServer(initializer); } if (generic_service_) { server->RegisterAsyncGenericService(generic_service_); } else { for (auto it = services_.begin(); it != services_.end(); ++it) { if ((*it)->service->has_generic_methods()) { gpr_log(GPR_ERROR, "Some methods were marked generic but there is no " "generic service registered."); return nullptr; } } } bool added_port = false; for (auto port = ports_.begin(); port != ports_.end(); port++) { int r = server->AddListeningPort(port->addr, port->creds.get()); if (!r) { if (added_port) server->Shutdown(); return nullptr; } added_port = true; if (port->selected_port != nullptr) { *port->selected_port = r; } } auto cqs_data = cqs_.empty() ? nullptr : &cqs_[0]; if (!server->Start(cqs_data, cqs_.size())) { if (added_port) server->Shutdown(); return nullptr; } for (auto plugin = plugins_.begin(); plugin != plugins_.end(); plugin++) { (*plugin)->Finish(initializer); } return server; } void ServerBuilder::InternalAddPluginFactory( std::unique_ptr (*CreatePlugin)()) { gpr_once_init(&once_init_plugin_list, do_plugin_list_init); (*g_plugin_factory_list).push_back(CreatePlugin); } } // namespace grpc grpc-1.3.2/src/cpp/server/server_cc.cc000066400000000000000000000553561310511640000176160ustar00rootroot00000000000000/* * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "src/core/lib/profiling/timers.h" #include "src/cpp/server/health/default_health_check_service.h" #include "src/cpp/thread_manager/thread_manager.h" namespace grpc { class DefaultGlobalCallbacks final : public Server::GlobalCallbacks { public: ~DefaultGlobalCallbacks() override {} void PreSynchronousRequest(ServerContext* context) override {} void PostSynchronousRequest(ServerContext* context) override {} }; static std::shared_ptr g_callbacks = nullptr; static gpr_once g_once_init_callbacks = GPR_ONCE_INIT; static void InitGlobalCallbacks() { if (!g_callbacks) { g_callbacks.reset(new DefaultGlobalCallbacks()); } } class Server::UnimplementedAsyncRequestContext { protected: UnimplementedAsyncRequestContext() : generic_stream_(&server_context_) {} GenericServerContext server_context_; GenericServerAsyncReaderWriter generic_stream_; }; class Server::UnimplementedAsyncRequest final : public UnimplementedAsyncRequestContext, public GenericAsyncRequest { public: UnimplementedAsyncRequest(Server* server, ServerCompletionQueue* cq) : GenericAsyncRequest(server, &server_context_, &generic_stream_, cq, cq, NULL, false), server_(server), cq_(cq) {} bool FinalizeResult(void** tag, bool* status) override; ServerContext* context() { return &server_context_; } GenericServerAsyncReaderWriter* stream() { return &generic_stream_; } private: Server* const server_; ServerCompletionQueue* const cq_; }; typedef SneakyCallOpSet UnimplementedAsyncResponseOp; class Server::UnimplementedAsyncResponse final : public UnimplementedAsyncResponseOp { public: UnimplementedAsyncResponse(UnimplementedAsyncRequest* request); ~UnimplementedAsyncResponse() { delete request_; } bool FinalizeResult(void** tag, bool* status) override { bool r = UnimplementedAsyncResponseOp::FinalizeResult(tag, status); delete this; return r; } private: UnimplementedAsyncRequest* const request_; }; class ShutdownTag : public CompletionQueueTag { public: bool FinalizeResult(void** tag, bool* status) { return false; } }; class Server::SyncRequest final : public CompletionQueueTag { public: SyncRequest(RpcServiceMethod* method, void* tag) : method_(method), tag_(tag), in_flight_(false), has_request_payload_(method->method_type() == RpcMethod::NORMAL_RPC || method->method_type() == RpcMethod::SERVER_STREAMING), call_details_(nullptr), cq_(nullptr) { grpc_metadata_array_init(&request_metadata_); } ~SyncRequest() { if (call_details_) { delete call_details_; } grpc_metadata_array_destroy(&request_metadata_); } void SetupRequest() { cq_ = grpc_completion_queue_create(nullptr); } void TeardownRequest() { grpc_completion_queue_destroy(cq_); cq_ = nullptr; } void Request(grpc_server* server, grpc_completion_queue* notify_cq) { GPR_ASSERT(cq_ && !in_flight_); in_flight_ = true; if (tag_) { GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_registered_call( server, tag_, &call_, &deadline_, &request_metadata_, has_request_payload_ ? &request_payload_ : nullptr, cq_, notify_cq, this)); } else { if (!call_details_) { call_details_ = new grpc_call_details; grpc_call_details_init(call_details_); } GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( server, &call_, call_details_, &request_metadata_, cq_, notify_cq, this)); } } bool FinalizeResult(void** tag, bool* status) override { if (!*status) { grpc_completion_queue_destroy(cq_); } if (call_details_) { deadline_ = call_details_->deadline; grpc_call_details_destroy(call_details_); grpc_call_details_init(call_details_); } return true; } class CallData final { public: explicit CallData(Server* server, SyncRequest* mrd) : cq_(mrd->cq_), call_(mrd->call_, server, &cq_, server->max_receive_message_size()), ctx_(mrd->deadline_, &mrd->request_metadata_), has_request_payload_(mrd->has_request_payload_), request_payload_(mrd->request_payload_), method_(mrd->method_) { ctx_.set_call(mrd->call_); ctx_.cq_ = &cq_; GPR_ASSERT(mrd->in_flight_); mrd->in_flight_ = false; mrd->request_metadata_.count = 0; } ~CallData() { if (has_request_payload_ && request_payload_) { grpc_byte_buffer_destroy(request_payload_); } } void Run(std::shared_ptr global_callbacks) { ctx_.BeginCompletionOp(&call_); global_callbacks->PreSynchronousRequest(&ctx_); method_->handler()->RunHandler( MethodHandler::HandlerParameter(&call_, &ctx_, request_payload_)); global_callbacks->PostSynchronousRequest(&ctx_); request_payload_ = nullptr; void* ignored_tag; bool ignored_ok; cq_.Shutdown(); GPR_ASSERT(cq_.Next(&ignored_tag, &ignored_ok) == false); } private: CompletionQueue cq_; Call call_; ServerContext ctx_; const bool has_request_payload_; grpc_byte_buffer* request_payload_; RpcServiceMethod* const method_; }; private: RpcServiceMethod* const method_; void* const tag_; bool in_flight_; const bool has_request_payload_; grpc_call* call_; grpc_call_details* call_details_; gpr_timespec deadline_; grpc_metadata_array request_metadata_; grpc_byte_buffer* request_payload_; grpc_completion_queue* cq_; }; // Implementation of ThreadManager. Each instance of SyncRequestThreadManager // manages a pool of threads that poll for incoming Sync RPCs and call the // appropriate RPC handlers class Server::SyncRequestThreadManager : public ThreadManager { public: SyncRequestThreadManager(Server* server, CompletionQueue* server_cq, std::shared_ptr global_callbacks, int min_pollers, int max_pollers, int cq_timeout_msec) : ThreadManager(min_pollers, max_pollers), server_(server), server_cq_(server_cq), cq_timeout_msec_(cq_timeout_msec), global_callbacks_(global_callbacks) {} WorkStatus PollForWork(void** tag, bool* ok) override { *tag = nullptr; gpr_timespec deadline = gpr_time_from_millis(cq_timeout_msec_, GPR_TIMESPAN); switch (server_cq_->AsyncNext(tag, ok, deadline)) { case CompletionQueue::TIMEOUT: return TIMEOUT; case CompletionQueue::SHUTDOWN: return SHUTDOWN; case CompletionQueue::GOT_EVENT: return WORK_FOUND; } GPR_UNREACHABLE_CODE(return TIMEOUT); } void DoWork(void* tag, bool ok) override { SyncRequest* sync_req = static_cast(tag); if (!sync_req) { // No tag. Nothing to work on. This is an unlikley scenario and possibly a // bug in RPC Manager implementation. gpr_log(GPR_ERROR, "Sync server. DoWork() was called with NULL tag"); return; } if (ok) { // Calldata takes ownership of the completion queue inside sync_req SyncRequest::CallData cd(server_, sync_req); { // Prepare for the next request if (!IsShutdown()) { sync_req->SetupRequest(); // Create new completion queue for sync_req sync_req->Request(server_->c_server(), server_cq_->cq()); } } GPR_TIMER_SCOPE("cd.Run()", 0); cd.Run(global_callbacks_); } // TODO (sreek) If ok is false here (which it isn't in case of // grpc_request_registered_call), we should still re-queue the request // object } void AddSyncMethod(RpcServiceMethod* method, void* tag) { sync_requests_.emplace_back(new SyncRequest(method, tag)); } void AddUnknownSyncMethod() { if (!sync_requests_.empty()) { unknown_method_.reset(new RpcServiceMethod( "unknown", RpcMethod::BIDI_STREAMING, new UnknownMethodHandler)); sync_requests_.emplace_back( new SyncRequest(unknown_method_.get(), nullptr)); } } void ShutdownAndDrainCompletionQueue() { server_cq_->Shutdown(); // Drain any pending items from the queue void* tag; bool ok; while (server_cq_->Next(&tag, &ok)) { // Nothing to be done here } } void Start() { if (!sync_requests_.empty()) { for (auto m = sync_requests_.begin(); m != sync_requests_.end(); m++) { (*m)->SetupRequest(); (*m)->Request(server_->c_server(), server_cq_->cq()); } Initialize(); // ThreadManager's Initialize() } } private: Server* server_; CompletionQueue* server_cq_; int cq_timeout_msec_; std::vector> sync_requests_; std::unique_ptr unknown_method_; std::unique_ptr health_check_; std::shared_ptr global_callbacks_; }; static internal::GrpcLibraryInitializer g_gli_initializer; Server::Server( int max_receive_message_size, ChannelArguments* args, std::shared_ptr>> sync_server_cqs, int min_pollers, int max_pollers, int sync_cq_timeout_msec) : max_receive_message_size_(max_receive_message_size), sync_server_cqs_(sync_server_cqs), started_(false), shutdown_(false), shutdown_notified_(false), has_generic_service_(false), server_(nullptr), server_initializer_(new ServerInitializer(this)), health_check_service_disabled_(false) { g_gli_initializer.summon(); gpr_once_init(&g_once_init_callbacks, InitGlobalCallbacks); global_callbacks_ = g_callbacks; global_callbacks_->UpdateArguments(args); for (auto it = sync_server_cqs_->begin(); it != sync_server_cqs_->end(); it++) { sync_req_mgrs_.emplace_back(new SyncRequestThreadManager( this, (*it).get(), global_callbacks_, min_pollers, max_pollers, sync_cq_timeout_msec)); } grpc_channel_args channel_args; args->SetChannelArgs(&channel_args); for (size_t i = 0; i < channel_args.num_args; i++) { if (0 == strcmp(channel_args.args[i].key, kHealthCheckServiceInterfaceArg)) { if (channel_args.args[i].value.pointer.p == nullptr) { health_check_service_disabled_ = true; } else { health_check_service_.reset(static_cast( channel_args.args[i].value.pointer.p)); } break; } } server_ = grpc_server_create(&channel_args, nullptr); } Server::~Server() { { std::unique_lock lock(mu_); if (started_ && !shutdown_) { lock.unlock(); Shutdown(); } else if (!started_) { // Shutdown the completion queues for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { (*it)->ShutdownAndDrainCompletionQueue(); } } } grpc_server_destroy(server_); } void Server::SetGlobalCallbacks(GlobalCallbacks* callbacks) { GPR_ASSERT(!g_callbacks); GPR_ASSERT(callbacks); g_callbacks.reset(callbacks); } grpc_server* Server::c_server() { return server_; } static grpc_server_register_method_payload_handling PayloadHandlingForMethod( RpcServiceMethod* method) { switch (method->method_type()) { case RpcMethod::NORMAL_RPC: case RpcMethod::SERVER_STREAMING: return GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER; case RpcMethod::CLIENT_STREAMING: case RpcMethod::BIDI_STREAMING: return GRPC_SRM_PAYLOAD_NONE; } GPR_UNREACHABLE_CODE(return GRPC_SRM_PAYLOAD_NONE;); } bool Server::RegisterService(const grpc::string* host, Service* service) { bool has_async_methods = service->has_async_methods(); if (has_async_methods) { GPR_ASSERT(service->server_ == nullptr && "Can only register an asynchronous service against one server."); service->server_ = this; } const char* method_name = nullptr; for (auto it = service->methods_.begin(); it != service->methods_.end(); ++it) { if (it->get() == nullptr) { // Handled by generic service if any. continue; } RpcServiceMethod* method = it->get(); void* tag = grpc_server_register_method( server_, method->name(), host ? host->c_str() : nullptr, PayloadHandlingForMethod(method), 0); if (tag == nullptr) { gpr_log(GPR_DEBUG, "Attempt to register %s multiple times", method->name()); return false; } if (method->handler() == nullptr) { // Async method method->set_server_tag(tag); } else { for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { (*it)->AddSyncMethod(method, tag); } } method_name = method->name(); } // Parse service name. if (method_name != nullptr) { std::stringstream ss(method_name); grpc::string service_name; if (std::getline(ss, service_name, '/') && std::getline(ss, service_name, '/')) { services_.push_back(service_name); } } return true; } void Server::RegisterAsyncGenericService(AsyncGenericService* service) { GPR_ASSERT(service->server_ == nullptr && "Can only register an async generic service against one server."); service->server_ = this; has_generic_service_ = true; } int Server::AddListeningPort(const grpc::string& addr, ServerCredentials* creds) { GPR_ASSERT(!started_); int port = creds->AddPortToServer(addr, server_); global_callbacks_->AddPort(this, port); return port; } bool Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) { GPR_ASSERT(!started_); global_callbacks_->PreServerStart(this); started_ = true; // Only create default health check service when user did not provide an // explicit one. if (health_check_service_ == nullptr && !health_check_service_disabled_ && DefaultHealthCheckServiceEnabled()) { if (sync_server_cqs_->empty()) { gpr_log(GPR_ERROR, "Default health check service disabled at async-only server."); } else { auto* default_hc_service = new DefaultHealthCheckService; health_check_service_.reset(default_hc_service); RegisterService(nullptr, default_hc_service->GetHealthCheckService()); } } grpc_server_start(server_); if (!has_generic_service_) { for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { (*it)->AddUnknownSyncMethod(); } for (size_t i = 0; i < num_cqs; i++) { if (cqs[i]->IsFrequentlyPolled()) { new UnimplementedAsyncRequest(this, cqs[i]); } } } for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { (*it)->Start(); } return true; } void Server::ShutdownInternal(gpr_timespec deadline) { std::unique_lock lock(mu_); if (!shutdown_) { shutdown_ = true; /// The completion queue to use for server shutdown completion notification CompletionQueue shutdown_cq; ShutdownTag shutdown_tag; // Dummy shutdown tag grpc_server_shutdown_and_notify(server_, shutdown_cq.cq(), &shutdown_tag); shutdown_cq.Shutdown(); void* tag; bool ok; CompletionQueue::NextStatus status = shutdown_cq.AsyncNext(&tag, &ok, deadline); // If this timed out, it means we are done with the grace period for a clean // shutdown. We should force a shutdown now by cancelling all inflight calls if (status == CompletionQueue::NextStatus::TIMEOUT) { grpc_server_cancel_all_calls(server_); } // Else in case of SHUTDOWN or GOT_EVENT, it means that the server has // successfully shutdown // Shutdown all ThreadManagers. This will try to gracefully stop all the // threads in the ThreadManagers (once they process any inflight requests) for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { (*it)->Shutdown(); // ThreadManager's Shutdown() } // Wait for threads in all ThreadManagers to terminate for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { (*it)->Wait(); (*it)->ShutdownAndDrainCompletionQueue(); } // Drain the shutdown queue (if the previous call to AsyncNext() timed out // and we didn't remove the tag from the queue yet) while (shutdown_cq.Next(&tag, &ok)) { // Nothing to be done here. Just ignore ok and tag values } shutdown_notified_ = true; shutdown_cv_.notify_all(); } } void Server::Wait() { std::unique_lock lock(mu_); while (started_ && !shutdown_notified_) { shutdown_cv_.wait(lock); } } void Server::PerformOpsOnCall(CallOpSetInterface* ops, Call* call) { static const size_t MAX_OPS = 8; size_t nops = 0; grpc_op cops[MAX_OPS]; ops->FillOps(cops, &nops); auto result = grpc_call_start_batch(call->call(), cops, nops, ops, nullptr); GPR_ASSERT(GRPC_CALL_OK == result); } ServerInterface::BaseAsyncRequest::BaseAsyncRequest( ServerInterface* server, ServerContext* context, ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, void* tag, bool delete_on_finalize) : server_(server), context_(context), stream_(stream), call_cq_(call_cq), tag_(tag), delete_on_finalize_(delete_on_finalize), call_(nullptr) { call_cq_->RegisterAvalanching(); // This op will trigger more ops } ServerInterface::BaseAsyncRequest::~BaseAsyncRequest() { call_cq_->CompleteAvalanching(); } bool ServerInterface::BaseAsyncRequest::FinalizeResult(void** tag, bool* status) { if (*status) { context_->client_metadata_.FillMap(); } context_->set_call(call_); context_->cq_ = call_cq_; Call call(call_, server_, call_cq_, server_->max_receive_message_size()); if (*status && call_) { context_->BeginCompletionOp(&call); } // just the pointers inside call are copied here stream_->BindCall(&call); *tag = tag_; if (delete_on_finalize_) { delete this; } return true; } ServerInterface::RegisteredAsyncRequest::RegisteredAsyncRequest( ServerInterface* server, ServerContext* context, ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, void* tag) : BaseAsyncRequest(server, context, stream, call_cq, tag, true) {} void ServerInterface::RegisteredAsyncRequest::IssueRequest( void* registered_method, grpc_byte_buffer** payload, ServerCompletionQueue* notification_cq) { grpc_server_request_registered_call( server_->server(), registered_method, &call_, &context_->deadline_, context_->client_metadata_.arr(), payload, call_cq_->cq(), notification_cq->cq(), this); } ServerInterface::GenericAsyncRequest::GenericAsyncRequest( ServerInterface* server, GenericServerContext* context, ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, ServerCompletionQueue* notification_cq, void* tag, bool delete_on_finalize) : BaseAsyncRequest(server, context, stream, call_cq, tag, delete_on_finalize) { grpc_call_details_init(&call_details_); GPR_ASSERT(notification_cq); GPR_ASSERT(call_cq); grpc_server_request_call(server->server(), &call_, &call_details_, context->client_metadata_.arr(), call_cq->cq(), notification_cq->cq(), this); } bool ServerInterface::GenericAsyncRequest::FinalizeResult(void** tag, bool* status) { // TODO(yangg) remove the copy here. if (*status) { static_cast(context_)->method_ = StringFromCopiedSlice(call_details_.method); static_cast(context_)->host_ = StringFromCopiedSlice(call_details_.host); } grpc_slice_unref(call_details_.method); grpc_slice_unref(call_details_.host); return BaseAsyncRequest::FinalizeResult(tag, status); } bool Server::UnimplementedAsyncRequest::FinalizeResult(void** tag, bool* status) { if (GenericAsyncRequest::FinalizeResult(tag, status) && *status) { new UnimplementedAsyncRequest(server_, cq_); new UnimplementedAsyncResponse(this); } else { delete this; } return false; } Server::UnimplementedAsyncResponse::UnimplementedAsyncResponse( UnimplementedAsyncRequest* request) : request_(request) { Status status(StatusCode::UNIMPLEMENTED, ""); UnknownMethodHandler::FillOps(request_->context(), this); request_->stream()->call_.PerformOps(this); } ServerInitializer* Server::initializer() { return server_initializer_.get(); } } // namespace grpc grpc-1.3.2/src/cpp/server/server_context.cc000066400000000000000000000160251310511640000207030ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include "src/core/lib/surface/call.h" namespace grpc { // CompletionOp class ServerContext::CompletionOp final : public CallOpSetInterface { public: // initial refs: one in the server context, one in the cq CompletionOp() : has_tag_(false), tag_(nullptr), refs_(2), finalized_(false), cancelled_(0) {} void FillOps(grpc_op* ops, size_t* nops) override; bool FinalizeResult(void** tag, bool* status) override; bool CheckCancelled(CompletionQueue* cq) { cq->TryPluck(this); return CheckCancelledNoPluck(); } bool CheckCancelledAsync() { return CheckCancelledNoPluck(); } void set_tag(void* tag) { has_tag_ = true; tag_ = tag; } void Unref(); private: bool CheckCancelledNoPluck() { std::lock_guard g(mu_); return finalized_ ? (cancelled_ != 0) : false; } bool has_tag_; void* tag_; std::mutex mu_; int refs_; bool finalized_; int cancelled_; }; void ServerContext::CompletionOp::Unref() { std::unique_lock lock(mu_); if (--refs_ == 0) { lock.unlock(); delete this; } } void ServerContext::CompletionOp::FillOps(grpc_op* ops, size_t* nops) { ops->op = GRPC_OP_RECV_CLOSE_ON_SERVER; ops->data.recv_close_on_server.cancelled = &cancelled_; ops->flags = 0; ops->reserved = NULL; *nops = 1; } bool ServerContext::CompletionOp::FinalizeResult(void** tag, bool* status) { std::unique_lock lock(mu_); finalized_ = true; bool ret = false; if (has_tag_) { *tag = tag_; ret = true; } if (!*status) cancelled_ = 1; if (--refs_ == 0) { lock.unlock(); delete this; } return ret; } // ServerContext body ServerContext::ServerContext() : completion_op_(nullptr), has_notify_when_done_tag_(false), async_notify_when_done_tag_(nullptr), deadline_(gpr_inf_future(GPR_CLOCK_REALTIME)), call_(nullptr), cq_(nullptr), sent_initial_metadata_(false), compression_level_set_(false) {} ServerContext::ServerContext(gpr_timespec deadline, grpc_metadata_array* arr) : completion_op_(nullptr), has_notify_when_done_tag_(false), async_notify_when_done_tag_(nullptr), deadline_(deadline), call_(nullptr), cq_(nullptr), sent_initial_metadata_(false), compression_level_set_(false) { std::swap(*client_metadata_.arr(), *arr); client_metadata_.FillMap(); } ServerContext::~ServerContext() { if (call_) { grpc_call_destroy(call_); } if (completion_op_) { completion_op_->Unref(); } } void ServerContext::BeginCompletionOp(Call* call) { GPR_ASSERT(!completion_op_); completion_op_ = new CompletionOp(); if (has_notify_when_done_tag_) { completion_op_->set_tag(async_notify_when_done_tag_); } call->PerformOps(completion_op_); } void ServerContext::AddInitialMetadata(const grpc::string& key, const grpc::string& value) { initial_metadata_.insert(std::make_pair(key, value)); } void ServerContext::AddTrailingMetadata(const grpc::string& key, const grpc::string& value) { trailing_metadata_.insert(std::make_pair(key, value)); } void ServerContext::TryCancel() const { grpc_call_error err = grpc_call_cancel_with_status( call_, GRPC_STATUS_CANCELLED, "Cancelled on the server side", NULL); if (err != GRPC_CALL_OK) { gpr_log(GPR_ERROR, "TryCancel failed with: %d", err); } } bool ServerContext::IsCancelled() const { if (has_notify_when_done_tag_) { // when using async API, but the result is only valid // if the tag has already been delivered at the completion queue return completion_op_ && completion_op_->CheckCancelledAsync(); } else { // when using sync API return completion_op_ && completion_op_->CheckCancelled(cq_); } } void ServerContext::set_compression_algorithm( grpc_compression_algorithm algorithm) { char* algorithm_name = NULL; if (!grpc_compression_algorithm_name(algorithm, &algorithm_name)) { gpr_log(GPR_ERROR, "Name for compression algorithm '%d' unknown.", algorithm); abort(); } GPR_ASSERT(algorithm_name != NULL); AddInitialMetadata(GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY, algorithm_name); } grpc::string ServerContext::peer() const { grpc::string peer; if (call_) { char* c_peer = grpc_call_get_peer(call_); peer = c_peer; gpr_free(c_peer); } return peer; } const struct census_context* ServerContext::census_context() const { return grpc_census_call_get_context(call_); } void ServerContext::SetLoadReportingCosts( const std::vector& cost_data) { if (call_ == nullptr) return; grpc_load_reporting_cost_context* cost_ctx = static_cast( gpr_malloc(sizeof(*cost_ctx))); cost_ctx->values_count = cost_data.size(); cost_ctx->values = static_cast( gpr_malloc(sizeof(*cost_ctx->values) * cost_ctx->values_count)); for (size_t i = 0; i < cost_ctx->values_count; ++i) { cost_ctx->values[i] = grpc_slice_from_copied_buffer(cost_data[i].data(), cost_data[i].size()); } grpc_call_set_load_reporting_cost_context(call_, cost_ctx); } } // namespace grpc grpc-1.3.2/src/cpp/server/server_credentials.cc000066400000000000000000000032461310511640000215150ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include namespace grpc { ServerCredentials::~ServerCredentials() {} } // namespace grpc grpc-1.3.2/src/cpp/server/server_posix.cc000066400000000000000000000035341310511640000203620ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include namespace grpc { #ifdef GPR_SUPPORT_CHANNELS_FROM_FD void AddInsecureChannelFromFd(Server* server, int fd) { grpc_server_add_insecure_channel_from_fd(server->c_server(), NULL, fd); } #endif // GPR_SUPPORT_CHANNELS_FROM_FD } // namespace grpc grpc-1.3.2/src/cpp/server/thread_pool_interface.h000066400000000000000000000040331310511640000220070ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_CPP_THREAD_POOL_INTERFACE_H #define GRPC_INTERNAL_CPP_THREAD_POOL_INTERFACE_H #include namespace grpc { // A thread pool interface for running callbacks. class ThreadPoolInterface { public: virtual ~ThreadPoolInterface() {} // Schedule the given callback for execution. virtual void Add(const std::function& callback) = 0; }; ThreadPoolInterface* CreateDefaultThreadPool(); } // namespace grpc #endif // GRPC_INTERNAL_CPP_THREAD_POOL_INTERFACE_H grpc-1.3.2/src/cpp/thread_manager/000077500000000000000000000000001310511640000167515ustar00rootroot00000000000000grpc-1.3.2/src/cpp/thread_manager/thread_manager.cc000066400000000000000000000131061310511640000222220ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/cpp/thread_manager/thread_manager.h" #include #include #include #include namespace grpc { ThreadManager::WorkerThread::WorkerThread(ThreadManager* thd_mgr) : thd_mgr_(thd_mgr), thd_(&ThreadManager::WorkerThread::Run, this) {} void ThreadManager::WorkerThread::Run() { thd_mgr_->MainWorkLoop(); thd_mgr_->MarkAsCompleted(this); } ThreadManager::WorkerThread::~WorkerThread() { thd_.join(); } ThreadManager::ThreadManager(int min_pollers, int max_pollers) : shutdown_(false), num_pollers_(0), min_pollers_(min_pollers), max_pollers_(max_pollers == -1 ? INT_MAX : max_pollers), num_threads_(0) {} ThreadManager::~ThreadManager() { { std::unique_lock lock(mu_); GPR_ASSERT(num_threads_ == 0); } CleanupCompletedThreads(); } void ThreadManager::Wait() { std::unique_lock lock(mu_); while (num_threads_ != 0) { shutdown_cv_.wait(lock); } } void ThreadManager::Shutdown() { std::unique_lock lock(mu_); shutdown_ = true; } bool ThreadManager::IsShutdown() { std::unique_lock lock(mu_); return shutdown_; } void ThreadManager::MarkAsCompleted(WorkerThread* thd) { { std::unique_lock list_lock(list_mu_); completed_threads_.push_back(thd); } std::unique_lock lock(mu_); num_threads_--; if (num_threads_ == 0) { shutdown_cv_.notify_one(); } } void ThreadManager::CleanupCompletedThreads() { std::unique_lock lock(list_mu_); for (auto thd = completed_threads_.begin(); thd != completed_threads_.end(); thd = completed_threads_.erase(thd)) { delete *thd; } } void ThreadManager::Initialize() { for (int i = 0; i < min_pollers_; i++) { MaybeCreatePoller(); } } // If the number of pollers (i.e threads currently blocked in PollForWork()) is // less than max threshold (i.e max_pollers_) and the total number of threads is // below the maximum threshold, we can let the current thread continue as poller bool ThreadManager::MaybeContinueAsPoller() { std::unique_lock lock(mu_); if (shutdown_ || num_pollers_ > max_pollers_) { return false; } num_pollers_++; return true; } // Create a new poller if the current number of pollers i.e num_pollers_ (i.e // threads currently blocked in PollForWork()) is below the threshold (i.e // min_pollers_) and the total number of threads is below the maximum threshold void ThreadManager::MaybeCreatePoller() { std::unique_lock lock(mu_); if (!shutdown_ && num_pollers_ < min_pollers_) { num_pollers_++; num_threads_++; // Create a new thread (which ends up calling the MainWorkLoop() function new WorkerThread(this); } } void ThreadManager::MainWorkLoop() { void* tag; bool ok; /* 1. Poll for work (i.e PollForWork()) 2. After returning from PollForWork, reduce the number of pollers by 1. If PollForWork() returned a TIMEOUT, then it may indicate that we have more polling threads than needed. Check if the number of pollers is greater than min_pollers and if so, terminate the thread. 3. Since we are short of one poller now, see if a new poller has to be created (i.e see MaybeCreatePoller() for more details) 4. Do the actual work (DoWork()) 5. After doing the work, see it this thread can resume polling work (i.e see MaybeContinueAsPoller() for more details) */ do { WorkStatus work_status = PollForWork(&tag, &ok); { std::unique_lock lock(mu_); num_pollers_--; if (work_status == TIMEOUT && num_pollers_ > min_pollers_) { break; } } // Note that MaybeCreatePoller does check for shutdown and creates a new // thread only if ThreadManager is not shutdown if (work_status == WORK_FOUND) { MaybeCreatePoller(); DoWork(tag, ok); } } while (MaybeContinueAsPoller()); CleanupCompletedThreads(); // If we are here, either ThreadManager is shutting down or it already has // enough threads. } } // namespace grpc grpc-1.3.2/src/cpp/thread_manager/thread_manager.h000066400000000000000000000132721310511640000220700ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_INTERNAL_CPP_THREAD_MANAGER_H #define GRPC_INTERNAL_CPP_THREAD_MANAGER_H #include #include #include #include #include #include namespace grpc { class ThreadManager { public: explicit ThreadManager(int min_pollers, int max_pollers); virtual ~ThreadManager(); // Initializes and Starts the Rpc Manager threads void Initialize(); // The return type of PollForWork() function enum WorkStatus { WORK_FOUND, SHUTDOWN, TIMEOUT }; // "Polls" for new work. // If the return value is WORK_FOUND: // - The implementaion of PollForWork() MAY set some opaque identifier to // (identify the work item found) via the '*tag' parameter // - The implementaion MUST set the value of 'ok' to 'true' or 'false'. A // value of 'false' indicates some implemenation specific error (that is // neither SHUTDOWN nor TIMEOUT) // - ThreadManager does not interpret the values of 'tag' and 'ok' // - ThreadManager WILL call DoWork() and pass '*tag' and 'ok' as input to // DoWork() // // If the return value is SHUTDOWN:, // - ThreadManager WILL NOT call DoWork() and terminates the thead // // If the return value is TIMEOUT:, // - ThreadManager WILL NOT call DoWork() // - ThreadManager MAY terminate the thread depending on the current number // of active poller threads and mix_pollers/max_pollers settings // - Also, the value of timeout is specific to the derived class // implementation virtual WorkStatus PollForWork(void** tag, bool* ok) = 0; // The implementation of DoWork() is supposed to perform the work found by // PollForWork(). The tag and ok parameters are the same as returned by // PollForWork() // // The implementation of DoWork() should also do any setup needed to ensure // that the next call to PollForWork() (not necessarily by the current thread) // actually finds some work virtual void DoWork(void* tag, bool ok) = 0; // Mark the ThreadManager as shutdown and begin draining the work. This is a // non-blocking call and the caller should call Wait(), a blocking call which // returns only once the shutdown is complete void Shutdown(); // Has Shutdown() been called bool IsShutdown(); // A blocking call that returns only after the ThreadManager has shutdown and // all the threads have drained all the outstanding work void Wait(); private: // Helper wrapper class around std::thread. This takes a ThreadManager object // and starts a new std::thread to calls the Run() function. // // The Run() function calls ThreadManager::MainWorkLoop() function and once // that completes, it marks the WorkerThread completed by calling // ThreadManager::MarkAsCompleted() class WorkerThread { public: WorkerThread(ThreadManager* thd_mgr); ~WorkerThread(); private: // Calls thd_mgr_->MainWorkLoop() and once that completes, calls // thd_mgr_>MarkAsCompleted(this) to mark the thread as completed void Run(); ThreadManager* thd_mgr_; std::thread thd_; }; // The main funtion in ThreadManager void MainWorkLoop(); // Create a new poller if the number of current pollers is less than the // minimum number of pollers needed (i.e min_pollers). void MaybeCreatePoller(); // Returns true if the current thread can resume as a poller. i.e if the // current number of pollers is less than the max_pollers. bool MaybeContinueAsPoller(); void MarkAsCompleted(WorkerThread* thd); void CleanupCompletedThreads(); // Protects shutdown_, num_pollers_ and num_threads_ // TODO: sreek - Change num_pollers and num_threads_ to atomics std::mutex mu_; bool shutdown_; std::condition_variable shutdown_cv_; // Number of threads doing polling int num_pollers_; // The minimum and maximum number of threads that should be doing polling int min_pollers_; int max_pollers_; // The total number of threads (includes threads includes the threads that are // currently polling i.e num_pollers_) int num_threads_; std::mutex list_mu_; std::list completed_threads_; }; } // namespace grpc #endif // GRPC_INTERNAL_CPP_THREAD_MANAGER_H grpc-1.3.2/src/cpp/util/000077500000000000000000000000001310511640000147655ustar00rootroot00000000000000grpc-1.3.2/src/cpp/util/byte_buffer_cc.cc000066400000000000000000000075301310511640000202420ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include namespace grpc { ByteBuffer::ByteBuffer(const Slice* slices, size_t nslices) { // The following assertions check that the representation of a grpc::Slice is // identical to that of a grpc_slice: it has a grpc_slice field, and nothing // else. static_assert(std::is_same::value, "Slice must have same representation as grpc_slice"); static_assert(sizeof(Slice) == sizeof(grpc_slice), "Slice must have same representation as grpc_slice"); // The const_cast is legal if grpc_raw_byte_buffer_create() does no more // than its advertised side effect of increasing the reference count of the // slices it processes, and such an increase does not affect the semantics // seen by the caller of this constructor. buffer_ = grpc_raw_byte_buffer_create( reinterpret_cast(const_cast(slices)), nslices); } ByteBuffer::~ByteBuffer() { if (buffer_) { grpc_byte_buffer_destroy(buffer_); } } void ByteBuffer::Clear() { if (buffer_) { grpc_byte_buffer_destroy(buffer_); buffer_ = nullptr; } } Status ByteBuffer::Dump(std::vector* slices) const { slices->clear(); if (!buffer_) { return Status(StatusCode::FAILED_PRECONDITION, "Buffer not initialized"); } grpc_byte_buffer_reader reader; if (!grpc_byte_buffer_reader_init(&reader, buffer_)) { return Status(StatusCode::INTERNAL, "Couldn't initialize byte buffer reader"); } grpc_slice s; while (grpc_byte_buffer_reader_next(&reader, &s)) { slices->push_back(Slice(s, Slice::STEAL_REF)); } grpc_byte_buffer_reader_destroy(&reader); return Status::OK; } size_t ByteBuffer::Length() const { if (buffer_) { return grpc_byte_buffer_length(buffer_); } else { return 0; } } ByteBuffer::ByteBuffer(const ByteBuffer& buf) : buffer_(grpc_byte_buffer_copy(buf.buffer_)) {} ByteBuffer& ByteBuffer::operator=(const ByteBuffer& buf) { Clear(); // first remove existing data if (buf.buffer_) { buffer_ = grpc_byte_buffer_copy(buf.buffer_); // then copy } return *this; } void ByteBuffer::Swap(ByteBuffer* other) { grpc_byte_buffer* tmp = other->buffer_; other->buffer_ = buffer_; buffer_ = tmp; } } // namespace grpc grpc-1.3.2/src/cpp/util/error_details.cc000066400000000000000000000045461310511640000201430ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "src/proto/grpc/status/status.pb.h" namespace grpc { Status ExtractErrorDetails(const Status& from, ::google::rpc::Status* to) { if (to == nullptr) { return Status(StatusCode::FAILED_PRECONDITION, ""); } if (!to->ParseFromString(from.error_details())) { return Status(StatusCode::INVALID_ARGUMENT, ""); } return Status::OK; } Status SetErrorDetails(const ::google::rpc::Status& from, Status* to) { if (to == nullptr) { return Status(StatusCode::FAILED_PRECONDITION, ""); } StatusCode code = StatusCode::UNKNOWN; if (from.code() >= StatusCode::OK && from.code() <= StatusCode::DATA_LOSS) { code = static_cast(from.code()); } *to = Status(code, from.message(), from.SerializeAsString()); return Status::OK; } } // namespace grpc grpc-1.3.2/src/cpp/util/slice_cc.cc000066400000000000000000000036371310511640000170510ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include namespace grpc { Slice::Slice() : slice_(grpc_empty_slice()) {} Slice::~Slice() { grpc_slice_unref(slice_); } Slice::Slice(grpc_slice slice, AddRef) : slice_(grpc_slice_ref(slice)) {} Slice::Slice(grpc_slice slice, StealRef) : slice_(slice) {} Slice::Slice(const Slice& other) : slice_(grpc_slice_ref(other.slice_)) {} } // namespace grpc grpc-1.3.2/src/cpp/util/status.cc000066400000000000000000000033301310511640000166160ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include namespace grpc { const Status& Status::OK = Status(); const Status& Status::CANCELLED = Status(StatusCode::CANCELLED, ""); } // namespace grpc grpc-1.3.2/src/cpp/util/string_ref.cc000066400000000000000000000032361310511640000174420ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include namespace grpc { const size_t string_ref::npos = size_t(-1); } // namespace grpc grpc-1.3.2/src/cpp/util/time_cc.cc000066400000000000000000000067551310511640000167140ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include using std::chrono::duration_cast; using std::chrono::nanoseconds; using std::chrono::seconds; using std::chrono::system_clock; using std::chrono::high_resolution_clock; namespace grpc { void Timepoint2Timespec(const system_clock::time_point& from, gpr_timespec* to) { system_clock::duration deadline = from.time_since_epoch(); seconds secs = duration_cast(deadline); if (from == system_clock::time_point::max() || secs.count() >= gpr_inf_future(GPR_CLOCK_REALTIME).tv_sec || secs.count() < 0) { *to = gpr_inf_future(GPR_CLOCK_REALTIME); return; } nanoseconds nsecs = duration_cast(deadline - secs); to->tv_sec = (int64_t)secs.count(); to->tv_nsec = (int32_t)nsecs.count(); to->clock_type = GPR_CLOCK_REALTIME; } void TimepointHR2Timespec(const high_resolution_clock::time_point& from, gpr_timespec* to) { high_resolution_clock::duration deadline = from.time_since_epoch(); seconds secs = duration_cast(deadline); if (from == high_resolution_clock::time_point::max() || secs.count() >= gpr_inf_future(GPR_CLOCK_REALTIME).tv_sec || secs.count() < 0) { *to = gpr_inf_future(GPR_CLOCK_REALTIME); return; } nanoseconds nsecs = duration_cast(deadline - secs); to->tv_sec = (int64_t)secs.count(); to->tv_nsec = (int32_t)nsecs.count(); to->clock_type = GPR_CLOCK_REALTIME; } system_clock::time_point Timespec2Timepoint(gpr_timespec t) { if (gpr_time_cmp(t, gpr_inf_future(t.clock_type)) == 0) { return system_clock::time_point::max(); } t = gpr_convert_clock_type(t, GPR_CLOCK_REALTIME); system_clock::time_point tp; tp += duration_cast(seconds(t.tv_sec)); tp += duration_cast(nanoseconds(t.tv_nsec)); return tp; } } // namespace grpc grpc-1.3.2/src/csharp/000077500000000000000000000000001310511640000145065ustar00rootroot00000000000000grpc-1.3.2/src/csharp/.gitignore000066400000000000000000000002551310511640000165000ustar00rootroot00000000000000*.xproj.user *.userprefs *.csproj.user *.lock.json StyleCop.Cache test-results packages Grpc.v12.suo Grpc.sdf TestResult.xml coverage_results.xml /TestResults .vs/ *.nupkg grpc-1.3.2/src/csharp/Grpc.Auth/000077500000000000000000000000001310511640000163015ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Auth/.gitignore000066400000000000000000000000201310511640000202610ustar00rootroot00000000000000bin obj *.nupkg grpc-1.3.2/src/csharp/Grpc.Auth/GoogleAuthInterceptors.cs000066400000000000000000000072451310511640000233000ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Threading; using System.Threading.Tasks; using Google.Apis.Auth.OAuth2; using Grpc.Core; using Grpc.Core.Utils; namespace Grpc.Auth { /// /// Factory methods to create authorization interceptors for Google credentials. /// /// public static class GoogleAuthInterceptors { private const string AuthorizationHeader = "Authorization"; private const string Schema = "Bearer"; /// /// Creates an that will obtain access token from any credential type that implements /// ITokenAccess. (e.g. GoogleCredential). /// /// The credential to use to obtain access tokens. /// The interceptor. public static AsyncAuthInterceptor FromCredential(ITokenAccess credential) { return new AsyncAuthInterceptor(async (context, metadata) => { var accessToken = await credential.GetAccessTokenForRequestAsync(context.ServiceUrl, CancellationToken.None).ConfigureAwait(false); metadata.Add(CreateBearerTokenHeader(accessToken)); }); } /// /// Creates an that will use given access token as authorization. /// /// OAuth2 access token. /// The interceptor. public static AsyncAuthInterceptor FromAccessToken(string accessToken) { GrpcPreconditions.CheckNotNull(accessToken); return new AsyncAuthInterceptor((context, metadata) => { metadata.Add(CreateBearerTokenHeader(accessToken)); return TaskUtils.CompletedTask; }); } private static Metadata.Entry CreateBearerTokenHeader(string accessToken) { return new Metadata.Entry(AuthorizationHeader, Schema + " " + accessToken); } } } grpc-1.3.2/src/csharp/Grpc.Auth/GoogleGrpcCredentials.cs000066400000000000000000000105401310511640000230360ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Threading; using System.Threading.Tasks; using Google.Apis.Auth.OAuth2; using Grpc.Core; using Grpc.Core.Utils; namespace Grpc.Auth { /// /// Factory/extension methods to create instances of and classes /// based on credential objects originating from Google auth library. /// public static class GoogleGrpcCredentials { /// /// Retrieves an instance of Google's Application Default Credentials using /// GoogleCredential.GetApplicationDefaultAsync() and converts them /// into a gRPC that use the default SSL credentials. /// /// The ChannelCredentials instance. public static async Task GetApplicationDefaultAsync() { var googleCredential = await GoogleCredential.GetApplicationDefaultAsync().ConfigureAwait(false); return googleCredential.ToChannelCredentials(); } /// /// Creates an instance of that will use given access token to authenticate /// with a gRPC service. /// /// OAuth2 access token. /// /// The MetadataCredentials instance. public static CallCredentials FromAccessToken(string accessToken) { return CallCredentials.FromInterceptor(GoogleAuthInterceptors.FromAccessToken(accessToken)); } /// /// Converts a ITokenAccess (e.g. GoogleCredential) object /// into a gRPC object. /// /// The credential to use to obtain access tokens. /// The CallCredentials instance. public static CallCredentials ToCallCredentials(this ITokenAccess credential) { return CallCredentials.FromInterceptor(GoogleAuthInterceptors.FromCredential(credential)); } /// /// Converts a ITokenAccess (e.g. GoogleCredential) object /// into a gRPC object. /// Default SSL credentials are used. /// /// The credential to use to obtain access tokens. /// >The ChannelCredentials instance. public static ChannelCredentials ToChannelCredentials(this ITokenAccess googleCredential) { return ChannelCredentials.Create(new SslCredentials(), googleCredential.ToCallCredentials()); } } } grpc-1.3.2/src/csharp/Grpc.Auth/Grpc.Auth.csproj000077500000000000000000000025741310511640000213310ustar00rootroot00000000000000 Copyright 2015, Google Inc. gRPC C# Auth $(GrpcCsharpVersion) Google Inc. net45;netstandard1.5 $(DefineConstants);SIGNED Grpc.Auth Grpc.Auth gRPC RPC Protocol HTTP/2 Auth OAuth2 https://github.com/grpc/grpc https://github.com/grpc/grpc/blob/master/LICENSE 1.6.0 grpc-1.3.2/src/csharp/Grpc.Auth/Properties/000077500000000000000000000000001310511640000204355ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Auth/Properties/AssemblyInfo.cs000066400000000000000000000036761310511640000233730ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Grpc.Auth")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] grpc-1.3.2/src/csharp/Grpc.Core.Testing/000077500000000000000000000000001310511640000177045ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Core.Testing/.gitignore000066400000000000000000000000101310511640000216630ustar00rootroot00000000000000bin obj grpc-1.3.2/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj000077500000000000000000000025531310511640000243340ustar00rootroot00000000000000 Copyright 2017, Google Inc. gRPC C# Core Testing $(GrpcCsharpVersion) Google Inc. net45;netstandard1.5 true Grpc.Core.Testing Grpc.Core.Testing gRPC test testing https://github.com/grpc/grpc https://github.com/grpc/grpc/blob/master/LICENSE 1.6.0 grpc-1.3.2/src/csharp/Grpc.Core.Testing/Properties/000077500000000000000000000000001310511640000220405ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Core.Testing/Properties/AssemblyInfo.cs000066400000000000000000000037111310511640000247640ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Grpc.Core.Testing")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] grpc-1.3.2/src/csharp/Grpc.Core.Testing/Settings.StyleCop000066400000000000000000000004311310511640000231660ustar00rootroot00000000000000 Health.cs False grpc-1.3.2/src/csharp/Grpc.Core.Testing/TestCalls.cs000066400000000000000000000110741310511640000221340ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Threading.Tasks; using Grpc.Core; namespace Grpc.Core.Testing { /// /// Test doubles for client-side call objects. /// public static class TestCalls { /// /// Creates a test double for AsyncUnaryCall. Only for testing. /// Note: experimental API that can change or be removed without any prior notice. /// public static AsyncUnaryCall AsyncUnaryCall ( Task responseAsync, Task responseHeadersAsync, Func getStatusFunc, Func getTrailersFunc, Action disposeAction) { return new AsyncUnaryCall(responseAsync, responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction); } /// /// Creates a test double for AsyncClientStreamingCall. Only for testing. /// Note: experimental API that can change or be removed without any prior notice. /// public static AsyncClientStreamingCall AsyncClientStreamingCall( IClientStreamWriter requestStream, Task responseAsync, Task responseHeadersAsync, Func getStatusFunc, Func getTrailersFunc, Action disposeAction) { return new AsyncClientStreamingCall(requestStream, responseAsync, responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction); } /// /// Creates a test double for AsyncServerStreamingCall. Only for testing. /// Note: experimental API that can change or be removed without any prior notice. /// public static AsyncServerStreamingCall AsyncServerStreamingCall( IAsyncStreamReader responseStream, Task responseHeadersAsync, Func getStatusFunc, Func getTrailersFunc, Action disposeAction) { return new AsyncServerStreamingCall(responseStream, responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction); } /// /// Creates a test double for AsyncDuplexStreamingCall. Only for testing. /// Note: experimental API that can change or be removed without any prior notice. /// public static AsyncDuplexStreamingCall AsyncDuplexStreamingCall( IClientStreamWriter requestStream, IAsyncStreamReader responseStream, Task responseHeadersAsync, Func getStatusFunc, Func getTrailersFunc, Action disposeAction) { return new AsyncDuplexStreamingCall(requestStream, responseStream, responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/000077500000000000000000000000001310511640000173715ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Core.Tests/.gitignore000066400000000000000000000000241310511640000213550ustar00rootroot00000000000000test-results bin objgrpc-1.3.2/src/csharp/Grpc.Core.Tests/AppDomainUnloadTest.cs000066400000000000000000000072071310511640000236010ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Threading.Tasks; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { public class AppDomainUnloadTest { #if NETCOREAPP1_0 [Test] [Ignore("Not supported for CoreCLR")] public void AppDomainUnloadHookCanCleanupAbandonedCall() { } #else [Test] public void AppDomainUnloadHookCanCleanupAbandonedCall() { var setup = new AppDomainSetup { ApplicationBase = AppDomain.CurrentDomain.BaseDirectory }; var childDomain = AppDomain.CreateDomain("test", null, setup); var remoteObj = childDomain.CreateInstance(typeof(AppDomainTestClass).Assembly.GetName().Name, typeof(AppDomainTestClass).FullName); // Try to unload the appdomain once we've created a server and a channel inside the appdomain. AppDomain.Unload(childDomain); } public class AppDomainTestClass { const string Host = "127.0.0.1"; /// /// Creates a server and a channel and initiates a call. The code is invoked from inside of an AppDomain /// to test if AppDomain.Unload() work if Grpc is being used. /// public AppDomainTestClass() { var helper = new MockServiceHelper(Host); var server = helper.GetServer(); server.Start(); var channel = helper.GetChannel(); var readyToShutdown = new TaskCompletionSource(); helper.DuplexStreamingHandler = new DuplexStreamingServerMethod(async (requestStream, responseStream, context) => { readyToShutdown.SetResult(null); await requestStream.ToListAsync(); }); var call = Calls.AsyncDuplexStreamingCall(helper.CreateDuplexStreamingCall()); readyToShutdown.Task.Wait(); // make sure handler is running } } #endif } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/AuthContextTest.cs000066400000000000000000000072141310511640000230320ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using NUnit.Framework; using Grpc.Core; using System.Linq; namespace Grpc.Core.Tests { public class AuthContextTest { [Test] public void EmptyContext() { var context = new AuthContext(null, new Dictionary>()); Assert.IsFalse(context.IsPeerAuthenticated); Assert.IsNull(context.PeerIdentityPropertyName); Assert.AreEqual(0, context.PeerIdentity.Count()); Assert.AreEqual(0, context.Properties.Count()); Assert.AreEqual(0, context.FindPropertiesByName("nonexistent").Count()); } [Test] public void AuthenticatedContext() { var property1 = AuthProperty.Create("abc", new byte[] { 68, 69, 70 }); var context = new AuthContext("some_identity", new Dictionary> { {"some_identity", new List {property1}} }); Assert.IsTrue(context.IsPeerAuthenticated); Assert.AreEqual("some_identity", context.PeerIdentityPropertyName); Assert.AreEqual(1, context.PeerIdentity.Count()); } [Test] public void FindPropertiesByName() { var property1 = AuthProperty.Create("abc", new byte[] {68, 69, 70}); var property2 = AuthProperty.Create("abc", new byte[] {71, 72, 73 }); var property3 = AuthProperty.Create("abc", new byte[] {}); var context = new AuthContext(null, new Dictionary> { {"existent", new List {property1, property2}}, {"foobar", new List {property3}}, }); Assert.AreEqual(3, context.Properties.Count()); Assert.AreEqual(0, context.FindPropertiesByName("nonexistent").Count()); var existentProperties = new List(context.FindPropertiesByName("existent")); Assert.AreEqual(2, existentProperties.Count); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/AuthPropertyTest.cs000066400000000000000000000065641310511640000232410ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using NUnit.Framework; namespace Grpc.Core.Tests { public class AuthPropertyTest { [Test] public void Create_NameIsNotNull() { Assert.Throws(typeof(ArgumentNullException), () => AuthProperty.Create(null, new byte[0])); Assert.Throws(typeof(ArgumentNullException), () => AuthProperty.CreateUnsafe(null, new byte[0])); } [Test] public void Create_ValueIsNotNull() { Assert.Throws(typeof(ArgumentNullException), () => AuthProperty.Create("abc", null)); Assert.Throws(typeof(ArgumentNullException), () => AuthProperty.CreateUnsafe("abc", null)); } [Test] public void Create() { var valueBytes = new byte[] { 68, 69, 70 }; var authProperty = AuthProperty.Create("abc", valueBytes); Assert.AreEqual("abc", authProperty.Name); Assert.AreNotSame(valueBytes, authProperty.ValueBytesUnsafe); CollectionAssert.AreEqual(valueBytes, authProperty.ValueBytes); CollectionAssert.AreEqual(valueBytes, authProperty.ValueBytesUnsafe); Assert.AreEqual("DEF", authProperty.Value); } [Test] public void CreateUnsafe() { var valueBytes = new byte[] { 68, 69, 70 }; var authProperty = AuthProperty.CreateUnsafe("abc", valueBytes); Assert.AreEqual("abc", authProperty.Name); Assert.AreSame(valueBytes, authProperty.ValueBytesUnsafe); Assert.AreNotSame(valueBytes, authProperty.ValueBytes); CollectionAssert.AreEqual(valueBytes, authProperty.ValueBytes); CollectionAssert.AreEqual(valueBytes, authProperty.ValueBytesUnsafe); Assert.AreEqual("DEF", authProperty.Value); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/CallCredentialsTest.cs000066400000000000000000000047631310511640000236230ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { public class CallCredentialsTest { [Test] public void CallCredentials_ComposeAtLeastTwo() { Assert.Throws(typeof(ArgumentException), () => CallCredentials.Compose(new FakeCallCredentials())); } [Test] public void CallCredentials_ToNativeCredentials() { var composite = CallCredentials.Compose( CallCredentials.FromInterceptor(async (uri, m) => { await Task.Delay(1); }), CallCredentials.FromInterceptor(async (uri, m) => { await Task.Delay(2); })); using (var nativeComposite = composite.ToNativeCredentials()) { } } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs000066400000000000000000000124001310511640000230040ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Threading; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { public class CallOptionsTest { [Test] public void WithMethods() { var options = new CallOptions(); var metadata = new Metadata(); Assert.AreSame(metadata, options.WithHeaders(metadata).Headers); var deadline = DateTime.UtcNow; Assert.AreEqual(deadline, options.WithDeadline(deadline).Deadline.Value); var cancellationToken = new CancellationTokenSource().Token; Assert.AreEqual(cancellationToken, options.WithCancellationToken(cancellationToken).CancellationToken); var writeOptions = new WriteOptions(); Assert.AreSame(writeOptions, options.WithWriteOptions(writeOptions).WriteOptions); var propagationToken = new ContextPropagationToken(CallSafeHandle.NullInstance, DateTime.UtcNow, CancellationToken.None, ContextPropagationOptions.Default); Assert.AreSame(propagationToken, options.WithPropagationToken(propagationToken).PropagationToken); var credentials = new FakeCallCredentials(); Assert.AreSame(credentials, options.WithCredentials(credentials).Credentials); var flags = CallFlags.WaitForReady | CallFlags.CacheableRequest; Assert.AreEqual(flags, options.WithFlags(flags).Flags); // Check that the original instance is unchanged. Assert.IsNull(options.Headers); Assert.IsNull(options.Deadline); Assert.AreEqual(CancellationToken.None, options.CancellationToken); Assert.IsNull(options.WriteOptions); Assert.IsNull(options.PropagationToken); Assert.IsNull(options.Credentials); Assert.AreEqual(default(CallFlags), options.Flags); } [Test] public void Normalize() { Assert.AreSame(Metadata.Empty, new CallOptions().Normalize().Headers); Assert.AreEqual(DateTime.MaxValue, new CallOptions().Normalize().Deadline.Value); var deadline = DateTime.UtcNow; var propagationToken1 = new ContextPropagationToken(CallSafeHandle.NullInstance, deadline, CancellationToken.None, new ContextPropagationOptions(propagateDeadline: true, propagateCancellation: false)); Assert.AreEqual(deadline, new CallOptions(propagationToken: propagationToken1).Normalize().Deadline.Value); Assert.Throws(typeof(ArgumentException), () => new CallOptions(deadline: deadline, propagationToken: propagationToken1).Normalize()); var token = new CancellationTokenSource().Token; var propagationToken2 = new ContextPropagationToken(CallSafeHandle.NullInstance, deadline, token, new ContextPropagationOptions(propagateDeadline: false, propagateCancellation: true)); Assert.AreEqual(token, new CallOptions(propagationToken: propagationToken2).Normalize().CancellationToken); Assert.Throws(typeof(ArgumentException), () => new CallOptions(cancellationToken: token, propagationToken: propagationToken2).Normalize()); } [Test] public void WaitForReady() { var callOptions = new CallOptions(); Assert.IsFalse(callOptions.IsWaitForReady); Assert.AreEqual(CallFlags.WaitForReady, callOptions.WithWaitForReady().Flags); Assert.IsTrue(callOptions.WithWaitForReady().IsWaitForReady); Assert.IsFalse(callOptions.WithWaitForReady(true).WithWaitForReady(false).IsWaitForReady); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/ChannelCredentialsTest.cs000066400000000000000000000053601310511640000243120ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { public class ChannelCredentialsTest { [Test] public void InsecureCredentials_IsNonComposable() { Assert.IsFalse(ChannelCredentials.Insecure.IsComposable); } [Test] public void ChannelCredentials_CreateComposite() { var composite = ChannelCredentials.Create(new FakeChannelCredentials(true), new FakeCallCredentials()); Assert.IsFalse(composite.IsComposable); Assert.Throws(typeof(ArgumentNullException), () => ChannelCredentials.Create(null, new FakeCallCredentials())); Assert.Throws(typeof(ArgumentNullException), () => ChannelCredentials.Create(new FakeChannelCredentials(true), null)); // forbid composing non-composable Assert.Throws(typeof(ArgumentException), () => ChannelCredentials.Create(new FakeChannelCredentials(false), new FakeCallCredentials())); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/ChannelOptionsTest.cs000066400000000000000000000075611310511640000235150ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { public class ChannelOptionsTest { [Test] public void IntOption() { var option = new ChannelOption("somename", 1); Assert.AreEqual(ChannelOption.OptionType.Integer, option.Type); Assert.AreEqual("somename", option.Name); Assert.AreEqual(1, option.IntValue); Assert.Throws(typeof(InvalidOperationException), () => { var s = option.StringValue; }); } [Test] public void StringOption() { var option = new ChannelOption("somename", "ABCDEF"); Assert.AreEqual(ChannelOption.OptionType.String, option.Type); Assert.AreEqual("somename", option.Name); Assert.AreEqual("ABCDEF", option.StringValue); Assert.Throws(typeof(InvalidOperationException), () => { var s = option.IntValue; }); } [Test] public void ConstructorPreconditions() { Assert.Throws(typeof(ArgumentNullException), () => { new ChannelOption(null, "abc"); }); Assert.Throws(typeof(ArgumentNullException), () => { new ChannelOption(null, 1); }); Assert.Throws(typeof(ArgumentNullException), () => { new ChannelOption("abc", null); }); } [Test] public void CreateChannelArgsNull() { var channelArgs = ChannelOptions.CreateChannelArgs(null); Assert.IsTrue(channelArgs.IsInvalid); } [Test] public void CreateChannelArgsEmpty() { var options = new List(); var channelArgs = ChannelOptions.CreateChannelArgs(options); channelArgs.Dispose(); } [Test] public void CreateChannelArgs() { var options = new List { new ChannelOption("ABC", "XYZ"), new ChannelOption("somename", "IJKLM"), new ChannelOption("intoption", 12345), new ChannelOption("GHIJK", 12345), }; var channelArgs = ChannelOptions.CreateChannelArgs(options); channelArgs.Dispose(); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/ChannelTest.cs000066400000000000000000000123421310511640000221320ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { public class ChannelTest { [Test] public void Constructor_RejectsInvalidParams() { Assert.Throws(typeof(ArgumentNullException), () => new Channel(null, ChannelCredentials.Insecure)); } [Test] public void Constructor_RejectsDuplicateOptions() { var options = new ChannelOption[] { new ChannelOption(ChannelOptions.PrimaryUserAgentString, "ABC"), new ChannelOption(ChannelOptions.PrimaryUserAgentString, "XYZ") }; Assert.Throws(typeof(ArgumentException), () => new Channel("127.0.0.1", ChannelCredentials.Insecure, options)); } [Test] public void State_IdleAfterCreation() { var channel = new Channel("localhost", ChannelCredentials.Insecure); Assert.AreEqual(ChannelState.Idle, channel.State); channel.ShutdownAsync().Wait(); } [Test] public void WaitForStateChangedAsync_InvalidArgument() { var channel = new Channel("localhost", ChannelCredentials.Insecure); Assert.ThrowsAsync(typeof(ArgumentException), async () => await channel.WaitForStateChangedAsync(ChannelState.Shutdown)); channel.ShutdownAsync().Wait(); } [Test] public void ResolvedTarget() { var channel = new Channel("127.0.0.1", ChannelCredentials.Insecure); Assert.IsTrue(channel.ResolvedTarget.Contains("127.0.0.1")); channel.ShutdownAsync().Wait(); } [Test] public void Shutdown_AllowedOnlyOnce() { var channel = new Channel("localhost", ChannelCredentials.Insecure); channel.ShutdownAsync().Wait(); Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await channel.ShutdownAsync()); } [Test] public async Task ShutdownTokenCancelledAfterShutdown() { var channel = new Channel("localhost", ChannelCredentials.Insecure); Assert.IsFalse(channel.ShutdownToken.IsCancellationRequested); var shutdownTask = channel.ShutdownAsync(); Assert.IsTrue(channel.ShutdownToken.IsCancellationRequested); await shutdownTask; } [Test] public async Task StateIsShutdownAfterShutdown() { var channel = new Channel("localhost", ChannelCredentials.Insecure); await channel.ShutdownAsync(); Assert.AreEqual(ChannelState.Shutdown, channel.State); } [Test] public async Task ShutdownFinishesWaitForStateChangedAsync() { var channel = new Channel("localhost", ChannelCredentials.Insecure); var stateChangedTask = channel.WaitForStateChangedAsync(ChannelState.Idle); var shutdownTask = channel.ShutdownAsync(); await stateChangedTask; await shutdownTask; } [Test] public async Task OperationsThrowAfterShutdown() { var channel = new Channel("localhost", ChannelCredentials.Insecure); await channel.ShutdownAsync(); Assert.ThrowsAsync(typeof(ObjectDisposedException), async () => await channel.WaitForStateChangedAsync(ChannelState.Idle)); Assert.Throws(typeof(ObjectDisposedException), () => { var x = channel.ResolvedTarget; }); Assert.ThrowsAsync(typeof(TaskCanceledException), async () => await channel.ConnectAsync()); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/ClientServerTest.cs000066400000000000000000000404421310511640000231710ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Profiling; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { public class ClientServerTest { const string Host = "127.0.0.1"; MockServiceHelper helper; Server server; Channel channel; [SetUp] public void Init() { helper = new MockServiceHelper(Host); server = helper.GetServer(); server.Start(); channel = helper.GetChannel(); } [TearDown] public void Cleanup() { channel.ShutdownAsync().Wait(); server.ShutdownAsync().Wait(); } [Test] public async Task UnaryCall() { helper.UnaryHandler = new UnaryServerMethod(async (request, context) => { return request; }); Assert.AreEqual("ABC", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "ABC")); Assert.AreEqual("ABC", await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "ABC")); } [Test] public void UnaryCall_ServerHandlerThrows() { helper.UnaryHandler = new UnaryServerMethod((request, context) => { throw new Exception("This was thrown on purpose by a test"); }); var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc")); Assert.AreEqual(StatusCode.Unknown, ex.Status.StatusCode); var ex2 = Assert.ThrowsAsync(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc")); Assert.AreEqual(StatusCode.Unknown, ex2.Status.StatusCode); } [Test] public void UnaryCall_ServerHandlerThrowsRpcException() { helper.UnaryHandler = new UnaryServerMethod((request, context) => { throw new RpcException(new Status(StatusCode.Unauthenticated, "")); }); var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc")); Assert.AreEqual(StatusCode.Unauthenticated, ex.Status.StatusCode); var ex2 = Assert.ThrowsAsync(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc")); Assert.AreEqual(StatusCode.Unauthenticated, ex2.Status.StatusCode); } [Test] public void UnaryCall_ServerHandlerSetsStatus() { helper.UnaryHandler = new UnaryServerMethod(async (request, context) => { context.Status = new Status(StatusCode.Unauthenticated, ""); return ""; }); var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc")); Assert.AreEqual(StatusCode.Unauthenticated, ex.Status.StatusCode); var ex2 = Assert.ThrowsAsync(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc")); Assert.AreEqual(StatusCode.Unauthenticated, ex2.Status.StatusCode); } [Test] public async Task ClientStreamingCall() { helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => { string result = ""; await requestStream.ForEachAsync(async (request) => { result += request; }); await Task.Delay(100); return result; }); var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall()); await call.RequestStream.WriteAllAsync(new string[] { "A", "B", "C" }); Assert.AreEqual("ABC", await call.ResponseAsync); Assert.AreEqual(StatusCode.OK, call.GetStatus().StatusCode); Assert.IsNotNull(call.GetTrailers()); } [Test] public async Task ServerStreamingCall() { helper.ServerStreamingHandler = new ServerStreamingServerMethod(async (request, responseStream, context) => { await responseStream.WriteAllAsync(request.Split(new []{' '})); context.ResponseTrailers.Add("xyz", ""); }); var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), "A B C"); CollectionAssert.AreEqual(new string[] { "A", "B", "C" }, await call.ResponseStream.ToListAsync()); Assert.AreEqual(StatusCode.OK, call.GetStatus().StatusCode); Assert.IsNotNull("xyz", call.GetTrailers()[0].Key); } [Test] public async Task ServerStreamingCall_EndOfStreamIsIdempotent() { helper.ServerStreamingHandler = new ServerStreamingServerMethod(async (request, responseStream, context) => { }); var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), ""); Assert.IsFalse(await call.ResponseStream.MoveNext()); Assert.IsFalse(await call.ResponseStream.MoveNext()); } [Test] public async Task ServerStreamingCall_ErrorCanBeAwaitedTwice() { helper.ServerStreamingHandler = new ServerStreamingServerMethod(async (request, responseStream, context) => { context.Status = new Status(StatusCode.InvalidArgument, ""); }); var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), ""); var ex = Assert.ThrowsAsync(async () => await call.ResponseStream.MoveNext()); Assert.AreEqual(StatusCode.InvalidArgument, ex.Status.StatusCode); // attempting MoveNext again should result in throwing the same exception. var ex2 = Assert.ThrowsAsync(async () => await call.ResponseStream.MoveNext()); Assert.AreEqual(StatusCode.InvalidArgument, ex2.Status.StatusCode); } [Test] public async Task DuplexStreamingCall() { helper.DuplexStreamingHandler = new DuplexStreamingServerMethod(async (requestStream, responseStream, context) => { while (await requestStream.MoveNext()) { await responseStream.WriteAsync(requestStream.Current); } context.ResponseTrailers.Add("xyz", "xyz-value"); }); var call = Calls.AsyncDuplexStreamingCall(helper.CreateDuplexStreamingCall()); await call.RequestStream.WriteAllAsync(new string[] { "A", "B", "C" }); CollectionAssert.AreEqual(new string[] { "A", "B", "C" }, await call.ResponseStream.ToListAsync()); Assert.AreEqual(StatusCode.OK, call.GetStatus().StatusCode); Assert.IsNotNull("xyz-value", call.GetTrailers()[0].Value); } [Test] public async Task ClientStreamingCall_CancelAfterBegin() { var barrier = new TaskCompletionSource(); helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => { barrier.SetResult(null); await requestStream.ToListAsync(); return ""; }); var cts = new CancellationTokenSource(); var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall(new CallOptions(cancellationToken: cts.Token))); await barrier.Task; // make sure the handler has started. cts.Cancel(); try { // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock. await call.ResponseAsync; Assert.Fail(); } catch (RpcException ex) { Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode); } } [Test] public async Task ClientStreamingCall_ServerSideReadAfterCancelNotificationReturnsNull() { var handlerStartedBarrier = new TaskCompletionSource(); var cancelNotificationReceivedBarrier = new TaskCompletionSource(); var successTcs = new TaskCompletionSource(); helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => { handlerStartedBarrier.SetResult(null); // wait for cancellation to be delivered. context.CancellationToken.Register(() => cancelNotificationReceivedBarrier.SetResult(null)); await cancelNotificationReceivedBarrier.Task; var moveNextResult = await requestStream.MoveNext(); successTcs.SetResult(!moveNextResult ? "SUCCESS" : "FAIL"); return ""; }); var cts = new CancellationTokenSource(); var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall(new CallOptions(cancellationToken: cts.Token))); await handlerStartedBarrier.Task; cts.Cancel(); try { await call.ResponseAsync; Assert.Fail(); } catch (RpcException ex) { Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode); } Assert.AreEqual("SUCCESS", await successTcs.Task); } [Test] public async Task AsyncUnaryCall_EchoMetadata() { helper.UnaryHandler = new UnaryServerMethod(async (request, context) => { foreach (Metadata.Entry metadataEntry in context.RequestHeaders) { if (metadataEntry.Key != "user-agent") { context.ResponseTrailers.Add(metadataEntry); } } return ""; }); var headers = new Metadata { { "ascii-header", "abcdefg" }, { "binary-header-bin", new byte[] { 1, 2, 3, 0, 0xff } } }; var call = Calls.AsyncUnaryCall(helper.CreateUnaryCall(new CallOptions(headers: headers)), "ABC"); await call; Assert.AreEqual(StatusCode.OK, call.GetStatus().StatusCode); var trailers = call.GetTrailers(); Assert.AreEqual(2, trailers.Count); Assert.AreEqual(headers[0].Key, trailers[0].Key); Assert.AreEqual(headers[0].Value, trailers[0].Value); Assert.AreEqual(headers[1].Key, trailers[1].Key); CollectionAssert.AreEqual(headers[1].ValueBytes, trailers[1].ValueBytes); } [Test] public void UnknownMethodHandler() { var nonexistentMethod = new Method( MethodType.Unary, MockServiceHelper.ServiceName, "NonExistentMethod", Marshallers.StringMarshaller, Marshallers.StringMarshaller); var callDetails = new CallInvocationDetails(channel, nonexistentMethod, new CallOptions()); var ex = Assert.Throws(() => Calls.BlockingUnaryCall(callDetails, "abc")); Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode); } [Test] public void StatusDetailIsUtf8() { // some japanese and chinese characters var nonAsciiString = "\u30a1\u30a2\u30a3 \u62b5\u6297\u662f\u5f92\u52b3\u7684"; helper.UnaryHandler = new UnaryServerMethod(async (request, context) => { context.Status = new Status(StatusCode.Unknown, nonAsciiString); return ""; }); var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc")); Assert.AreEqual(StatusCode.Unknown, ex.Status.StatusCode); Assert.AreEqual(nonAsciiString, ex.Status.Detail); } [Test] public void ServerCallContext_PeerInfoPresent() { helper.UnaryHandler = new UnaryServerMethod(async (request, context) => { return context.Peer; }); string peer = Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc"); Assert.IsTrue(peer.Contains(Host)); } [Test] public void ServerCallContext_HostAndMethodPresent() { helper.UnaryHandler = new UnaryServerMethod(async (request, context) => { Assert.IsTrue(context.Host.Contains(Host)); Assert.AreEqual("/tests.Test/Unary", context.Method); return "PASS"; }); Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc")); } [Test] public void ServerCallContext_AuthContextNotPopulated() { helper.UnaryHandler = new UnaryServerMethod(async (request, context) => { Assert.IsFalse(context.AuthContext.IsPeerAuthenticated); Assert.AreEqual(0, context.AuthContext.Properties.Count()); return "PASS"; }); Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc")); } [Test] public async Task Channel_WaitForStateChangedAsync() { helper.UnaryHandler = new UnaryServerMethod(async (request, context) => { return request; }); Assert.ThrowsAsync(typeof(TaskCanceledException), async () => await channel.WaitForStateChangedAsync(channel.State, DateTime.UtcNow.AddMilliseconds(10))); var stateChangedTask = channel.WaitForStateChangedAsync(channel.State); await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc"); await stateChangedTask; Assert.AreEqual(ChannelState.Ready, channel.State); } [Test] public async Task Channel_ConnectAsync() { await channel.ConnectAsync(); Assert.AreEqual(ChannelState.Ready, channel.State); await channel.ConnectAsync(DateTime.UtcNow.AddMilliseconds(1000)); Assert.AreEqual(ChannelState.Ready, channel.State); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/CompressionTest.cs000066400000000000000000000124751310511640000230720ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { public class CompressionTest { MockServiceHelper helper; Server server; Channel channel; [SetUp] public void Init() { helper = new MockServiceHelper(); server = helper.GetServer(); server.Start(); channel = helper.GetChannel(); } [TearDown] public void Cleanup() { channel.ShutdownAsync().Wait(); server.ShutdownAsync().Wait(); } [Test] public void WriteOptions_Unary() { helper.UnaryHandler = new UnaryServerMethod(async (request, context) => { context.WriteOptions = new WriteOptions(WriteFlags.NoCompress); return request; }); var callOptions = new CallOptions(writeOptions: new WriteOptions(WriteFlags.NoCompress)); Calls.BlockingUnaryCall(helper.CreateUnaryCall(callOptions), "abc"); } [Test] public async Task WriteOptions_DuplexStreaming() { helper.DuplexStreamingHandler = new DuplexStreamingServerMethod(async (requestStream, responseStream, context) => { await requestStream.ToListAsync(); context.WriteOptions = new WriteOptions(WriteFlags.NoCompress); await context.WriteResponseHeadersAsync(new Metadata { { "ascii-header", "abcdefg" } }); await responseStream.WriteAsync("X"); responseStream.WriteOptions = null; await responseStream.WriteAsync("Y"); responseStream.WriteOptions = new WriteOptions(WriteFlags.NoCompress); await responseStream.WriteAsync("Z"); }); var callOptions = new CallOptions(writeOptions: new WriteOptions(WriteFlags.NoCompress)); var call = Calls.AsyncDuplexStreamingCall(helper.CreateDuplexStreamingCall(callOptions)); // check that write options from call options are propagated to request stream. Assert.IsTrue((call.RequestStream.WriteOptions.Flags & WriteFlags.NoCompress) != 0); call.RequestStream.WriteOptions = new WriteOptions(); await call.RequestStream.WriteAsync("A"); call.RequestStream.WriteOptions = null; await call.RequestStream.WriteAsync("B"); call.RequestStream.WriteOptions = new WriteOptions(WriteFlags.NoCompress); await call.RequestStream.WriteAsync("C"); await call.RequestStream.CompleteAsync(); await call.ResponseStream.ToListAsync(); } [Test] public void CanReadCompressedMessages() { var compressionMetadata = new Metadata { { new Metadata.Entry(Metadata.CompressionRequestAlgorithmMetadataKey, "gzip") } }; helper.UnaryHandler = new UnaryServerMethod(async (req, context) => { await context.WriteResponseHeadersAsync(compressionMetadata); return req; }); var stringBuilder = new StringBuilder(); for (int i = 0; i < 200000; i++) { stringBuilder.Append('a'); } var request = stringBuilder.ToString(); var response = Calls.BlockingUnaryCall(helper.CreateUnaryCall(new CallOptions(compressionMetadata)), request); Assert.AreEqual(request, response); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs000066400000000000000000000154771310511640000244260ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { public class ContextPropagationTest { MockServiceHelper helper; Server server; Channel channel; [SetUp] public void Init() { helper = new MockServiceHelper(); server = helper.GetServer(); server.Start(); channel = helper.GetChannel(); } [TearDown] public void Cleanup() { channel.ShutdownAsync().Wait(); server.ShutdownAsync().Wait(); } [Test] public async Task PropagateCancellation() { var readyToCancelTcs = new TaskCompletionSource(); var successTcs = new TaskCompletionSource(); helper.UnaryHandler = new UnaryServerMethod(async (request, context) => { readyToCancelTcs.SetResult(null); // child call running, ready to parent call while (!context.CancellationToken.IsCancellationRequested) { await Task.Delay(10); } successTcs.SetResult("CHILD_CALL_CANCELLED"); return ""; }); helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => { var propagationToken = context.CreatePropagationToken(); Assert.IsNotNull(propagationToken.ParentCall); var callOptions = new CallOptions(propagationToken: propagationToken); try { await Calls.AsyncUnaryCall(helper.CreateUnaryCall(callOptions), "xyz"); } catch(RpcException) { // Child call will get cancelled, eat the exception. } return ""; }); var cts = new CancellationTokenSource(); var parentCall = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall(new CallOptions(cancellationToken: cts.Token))); await readyToCancelTcs.Task; cts.Cancel(); try { // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock. await parentCall; Assert.Fail(); } catch (RpcException) { } Assert.AreEqual("CHILD_CALL_CANCELLED", await successTcs.Task); } [Test] public async Task PropagateDeadline() { var deadline = DateTime.UtcNow.AddDays(7); helper.UnaryHandler = new UnaryServerMethod(async (request, context) => { Assert.IsTrue(context.Deadline < deadline.AddMinutes(1)); Assert.IsTrue(context.Deadline > deadline.AddMinutes(-1)); return "PASS"; }); helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => { Assert.Throws(typeof(ArgumentException), () => { // Trying to override deadline while propagating deadline from parent call will throw. Calls.BlockingUnaryCall(helper.CreateUnaryCall( new CallOptions(deadline: DateTime.UtcNow.AddDays(8), propagationToken: context.CreatePropagationToken())), ""); }); var callOptions = new CallOptions(propagationToken: context.CreatePropagationToken()); return await Calls.AsyncUnaryCall(helper.CreateUnaryCall(callOptions), "xyz"); }); var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall(new CallOptions(deadline: deadline))); await call.RequestStream.CompleteAsync(); Assert.AreEqual("PASS", await call); } [Test] public async Task SuppressDeadlinePropagation() { helper.UnaryHandler = new UnaryServerMethod(async (request, context) => { Assert.AreEqual(DateTime.MaxValue, context.Deadline); return "PASS"; }); helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => { Assert.IsTrue(context.CancellationToken.CanBeCanceled); var callOptions = new CallOptions(propagationToken: context.CreatePropagationToken(new ContextPropagationOptions(propagateDeadline: false))); return await Calls.AsyncUnaryCall(helper.CreateUnaryCall(callOptions), "xyz"); }); var cts = new CancellationTokenSource(); var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall(new CallOptions(deadline: DateTime.UtcNow.AddDays(7)))); await call.RequestStream.CompleteAsync(); Assert.AreEqual("PASS", await call); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/FakeCredentials.cs000066400000000000000000000047061310511640000227530ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { internal class FakeChannelCredentials : ChannelCredentials { readonly bool composable; public FakeChannelCredentials(bool composable) { this.composable = composable; } internal override bool IsComposable { get { return composable; } } internal override ChannelCredentialsSafeHandle ToNativeCredentials() { return null; } } internal class FakeCallCredentials : CallCredentials { internal override CallCredentialsSafeHandle ToNativeCredentials() { return null; } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj000077500000000000000000000025701310511640000235050ustar00rootroot00000000000000 net45;netcoreapp1.0 Grpc.Core.Tests Exe Grpc.Core.Tests $(PackageTargetFallback);portable-net45 1.0.4 grpc-1.3.2/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs000066400000000000000000000064731310511640000237120ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Linq; using Grpc.Core; using NUnit.Framework; namespace Grpc.Core.Tests { public class GrpcEnvironmentTest { [Test] public void InitializeAndShutdownGrpcEnvironment() { var env = GrpcEnvironment.AddRef(); Assert.IsTrue(env.CompletionQueues.Count > 0); for (int i = 0; i < env.CompletionQueues.Count; i++) { Assert.IsNotNull(env.CompletionQueues.ElementAt(i)); } GrpcEnvironment.ReleaseAsync().Wait(); } [Test] public void SubsequentInvocations() { var env1 = GrpcEnvironment.AddRef(); var env2 = GrpcEnvironment.AddRef(); Assert.AreSame(env1, env2); GrpcEnvironment.ReleaseAsync().Wait(); GrpcEnvironment.ReleaseAsync().Wait(); } [Test] public void InitializeAfterShutdown() { Assert.AreEqual(0, GrpcEnvironment.GetRefCount()); var env1 = GrpcEnvironment.AddRef(); GrpcEnvironment.ReleaseAsync().Wait(); var env2 = GrpcEnvironment.AddRef(); GrpcEnvironment.ReleaseAsync().Wait(); Assert.AreNotSame(env1, env2); } [Test] public void ReleaseWithoutAddRef() { Assert.AreEqual(0, GrpcEnvironment.GetRefCount()); Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await GrpcEnvironment.ReleaseAsync()); } [Test] public void GetCoreVersionString() { var coreVersion = GrpcEnvironment.GetCoreVersionString(); var parts = coreVersion.Split('.'); Assert.AreEqual(3, parts.Length); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/HalfcloseTest.cs000066400000000000000000000070051310511640000224620ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { public class HalfcloseTest { MockServiceHelper helper; Server server; Channel channel; [SetUp] public void Init() { helper = new MockServiceHelper(); server = helper.GetServer(); server.Start(); channel = helper.GetChannel(); } [TearDown] public void Cleanup() { channel.ShutdownAsync().Wait(); server.ShutdownAsync().Wait(); } /// /// For client streaming and duplex streaming calls, if server does a full close /// before we halfclose the request stream, an attempt to halfclose /// (complete the request stream) shouldn't be treated as an error. /// [Test] public async Task HalfcloseAfterFullclose_ClientStreamingCall() { helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => { return "PASS"; }); var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall()); // make sure server has fullclosed on us Assert.AreEqual("PASS", await call.ResponseAsync); // sending close from client should be still fine because server can finish // the call anytime and we cannot do anything about it on the client side. await call.RequestStream.CompleteAsync(); // Second attempt to close from client is not allowed. Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await call.RequestStream.CompleteAsync()); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/Internal/000077500000000000000000000000001310511640000211455ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs000066400000000000000000000177751310511640000254150ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; using System.Threading.Tasks; using Grpc.Core.Internal; using NUnit.Framework; namespace Grpc.Core.Internal.Tests { /// /// Uses fake native call to test interaction of AsyncCallServer wrapping code with C core in different situations. /// public class AsyncCallServerTest { Server server; FakeNativeCall fakeCall; AsyncCallServer asyncCallServer; [SetUp] public void Init() { // Create a fake server just so we have an instance to refer to. // The server won't actually be used at all. server = new Server() { Ports = { { "localhost", 0, ServerCredentials.Insecure } } }; server.Start(); fakeCall = new FakeNativeCall(); asyncCallServer = new AsyncCallServer( Marshallers.StringMarshaller.Serializer, Marshallers.StringMarshaller.Deserializer, server); asyncCallServer.InitializeForTesting(fakeCall); } [TearDown] public void Cleanup() { server.ShutdownAsync().Wait(); } [Test] public void CancelNotificationAfterStartDisposes() { var finishedTask = asyncCallServer.ServerSideCallAsync(); fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true); AssertFinished(asyncCallServer, fakeCall, finishedTask); } [Test] public void CancelNotificationAfterStartDisposesAfterPendingReadFinishes() { var finishedTask = asyncCallServer.ServerSideCallAsync(); var requestStream = new ServerRequestStream(asyncCallServer); var moveNextTask = requestStream.MoveNext(); fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true); fakeCall.ReceivedMessageHandler(true, null); Assert.IsFalse(moveNextTask.Result); AssertFinished(asyncCallServer, fakeCall, finishedTask); } [Test] public void ReadAfterCancelNotificationCanSucceed() { var finishedTask = asyncCallServer.ServerSideCallAsync(); var requestStream = new ServerRequestStream(asyncCallServer); fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true); // Check that starting a read after cancel notification has been processed is legal. var moveNextTask = requestStream.MoveNext(); Assert.IsFalse(moveNextTask.Result); AssertFinished(asyncCallServer, fakeCall, finishedTask); } [Test] public void ReadCompletionFailureClosesRequestStream() { var finishedTask = asyncCallServer.ServerSideCallAsync(); var requestStream = new ServerRequestStream(asyncCallServer); // if a read completion's success==false, the request stream will silently finish // and we rely on C core cancelling the call. var moveNextTask = requestStream.MoveNext(); fakeCall.ReceivedMessageHandler(false, null); Assert.IsFalse(moveNextTask.Result); fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true); AssertFinished(asyncCallServer, fakeCall, finishedTask); } [Test] public void WriteAfterCancelNotificationFails() { var finishedTask = asyncCallServer.ServerSideCallAsync(); var responseStream = new ServerResponseStream(asyncCallServer); fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true); // TODO(jtattermusch): should we throw a different exception type instead? Assert.Throws(typeof(InvalidOperationException), () => responseStream.WriteAsync("request1")); AssertFinished(asyncCallServer, fakeCall, finishedTask); } [Test] public void WriteCompletionFailureThrows() { var finishedTask = asyncCallServer.ServerSideCallAsync(); var responseStream = new ServerResponseStream(asyncCallServer); var writeTask = responseStream.WriteAsync("request1"); fakeCall.SendCompletionHandler(false); Assert.ThrowsAsync(typeof(IOException), async () => await writeTask); fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true); AssertFinished(asyncCallServer, fakeCall, finishedTask); } [Test] public void WriteAndWriteStatusCanRunConcurrently() { var finishedTask = asyncCallServer.ServerSideCallAsync(); var responseStream = new ServerResponseStream(asyncCallServer); var writeTask = responseStream.WriteAsync("request1"); var writeStatusTask = asyncCallServer.SendStatusFromServerAsync(Status.DefaultSuccess, new Metadata(), null); fakeCall.SendCompletionHandler(true); fakeCall.SendStatusFromServerHandler(true); Assert.DoesNotThrowAsync(async () => await writeTask); Assert.DoesNotThrowAsync(async () => await writeStatusTask); fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true); AssertFinished(asyncCallServer, fakeCall, finishedTask); } [Test] public void WriteAfterWriteStatusThrowsInvalidOperationException() { var finishedTask = asyncCallServer.ServerSideCallAsync(); var responseStream = new ServerResponseStream(asyncCallServer); asyncCallServer.SendStatusFromServerAsync(Status.DefaultSuccess, new Metadata(), null); Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await responseStream.WriteAsync("request1")); fakeCall.SendStatusFromServerHandler(true); fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true); AssertFinished(asyncCallServer, fakeCall, finishedTask); } static void AssertFinished(AsyncCallServer asyncCallServer, FakeNativeCall fakeCall, Task finishedTask) { Assert.IsTrue(fakeCall.IsDisposed); Assert.IsTrue(finishedTask.IsCompleted); Assert.DoesNotThrow(() => finishedTask.Wait()); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs000066400000000000000000000636541310511640000242230ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Threading.Tasks; using Grpc.Core.Internal; using NUnit.Framework; namespace Grpc.Core.Internal.Tests { /// /// Uses fake native call to test interaction of AsyncCall wrapping code with C core in different situations. /// public class AsyncCallTest { Channel channel; FakeNativeCall fakeCall; AsyncCall asyncCall; [SetUp] public void Init() { channel = new Channel("localhost", ChannelCredentials.Insecure); fakeCall = new FakeNativeCall(); var callDetails = new CallInvocationDetails(channel, "someMethod", null, Marshallers.StringMarshaller, Marshallers.StringMarshaller, new CallOptions()); asyncCall = new AsyncCall(callDetails, fakeCall); } [TearDown] public void Cleanup() { channel.ShutdownAsync().Wait(); } [Test] public void AsyncUnary_CanBeStartedOnlyOnce() { asyncCall.UnaryCallAsync("request1"); Assert.Throws(typeof(InvalidOperationException), () => asyncCall.UnaryCallAsync("abc")); } [Test] public void AsyncUnary_StreamingOperationsNotAllowed() { asyncCall.UnaryCallAsync("request1"); Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await asyncCall.ReadMessageAsync()); Assert.Throws(typeof(InvalidOperationException), () => asyncCall.SendMessageAsync("abc", new WriteFlags())); } [Test] public void AsyncUnary_Success() { var resultTask = asyncCall.UnaryCallAsync("request1"); fakeCall.UnaryResponseClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata()), CreateResponsePayload(), new Metadata()); AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask); } [Test] public void AsyncUnary_NonSuccessStatusCode() { var resultTask = asyncCall.UnaryCallAsync("request1"); fakeCall.UnaryResponseClientHandler(true, CreateClientSideStatus(StatusCode.InvalidArgument), null, new Metadata()); AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.InvalidArgument); } [Test] public void AsyncUnary_NullResponsePayload() { var resultTask = asyncCall.UnaryCallAsync("request1"); fakeCall.UnaryResponseClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata()), null, new Metadata()); // failure to deserialize will result in InvalidArgument status. AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Internal); } [Test] public void ClientStreaming_StreamingReadNotAllowed() { asyncCall.ClientStreamingCallAsync(); Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await asyncCall.ReadMessageAsync()); } [Test] public void ClientStreaming_NoRequest_Success() { var resultTask = asyncCall.ClientStreamingCallAsync(); fakeCall.UnaryResponseClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata()), CreateResponsePayload(), new Metadata()); AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask); } [Test] public void ClientStreaming_NoRequest_NonSuccessStatusCode() { var resultTask = asyncCall.ClientStreamingCallAsync(); fakeCall.UnaryResponseClientHandler(true, CreateClientSideStatus(StatusCode.InvalidArgument), null, new Metadata()); AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.InvalidArgument); } [Test] public void ClientStreaming_MoreRequests_Success() { var resultTask = asyncCall.ClientStreamingCallAsync(); var requestStream = new ClientRequestStream(asyncCall); var writeTask = requestStream.WriteAsync("request1"); fakeCall.SendCompletionHandler(true); writeTask.Wait(); var writeTask2 = requestStream.WriteAsync("request2"); fakeCall.SendCompletionHandler(true); writeTask2.Wait(); var completeTask = requestStream.CompleteAsync(); fakeCall.SendCompletionHandler(true); completeTask.Wait(); fakeCall.UnaryResponseClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata()), CreateResponsePayload(), new Metadata()); AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask); } [Test] public void ClientStreaming_WriteFailureThrowsRpcException() { var resultTask = asyncCall.ClientStreamingCallAsync(); var requestStream = new ClientRequestStream(asyncCall); var writeTask = requestStream.WriteAsync("request1"); fakeCall.SendCompletionHandler(false); // The write will wait for call to finish to receive the status code. Assert.IsFalse(writeTask.IsCompleted); fakeCall.UnaryResponseClientHandler(true, CreateClientSideStatus(StatusCode.Internal), null, new Metadata()); var ex = Assert.ThrowsAsync(async () => await writeTask); Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode); AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Internal); } [Test] public void ClientStreaming_WriteFailureThrowsRpcException2() { var resultTask = asyncCall.ClientStreamingCallAsync(); var requestStream = new ClientRequestStream(asyncCall); var writeTask = requestStream.WriteAsync("request1"); fakeCall.UnaryResponseClientHandler(true, CreateClientSideStatus(StatusCode.Internal), null, new Metadata()); fakeCall.SendCompletionHandler(false); var ex = Assert.ThrowsAsync(async () => await writeTask); Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode); AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Internal); } [Test] public void ClientStreaming_WriteFailureThrowsRpcException3() { var resultTask = asyncCall.ClientStreamingCallAsync(); var requestStream = new ClientRequestStream(asyncCall); var writeTask = requestStream.WriteAsync("request1"); fakeCall.SendCompletionHandler(false); // Until the delayed write completion has been triggered, // we still act as if there was an active write. Assert.Throws(typeof(InvalidOperationException), () => requestStream.WriteAsync("request2")); fakeCall.UnaryResponseClientHandler(true, CreateClientSideStatus(StatusCode.Internal), null, new Metadata()); var ex = Assert.ThrowsAsync(async () => await writeTask); Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode); // Following attempts to write keep delivering the same status var ex2 = Assert.ThrowsAsync(async () => await requestStream.WriteAsync("after call has finished")); Assert.AreEqual(StatusCode.Internal, ex2.Status.StatusCode); AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Internal); } [Test] public void ClientStreaming_WriteAfterReceivingStatusThrowsRpcException() { var resultTask = asyncCall.ClientStreamingCallAsync(); var requestStream = new ClientRequestStream(asyncCall); fakeCall.UnaryResponseClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata()), CreateResponsePayload(), new Metadata()); AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask); var writeTask = requestStream.WriteAsync("request1"); var ex = Assert.ThrowsAsync(async () => await writeTask); Assert.AreEqual(Status.DefaultSuccess, ex.Status); } [Test] public void ClientStreaming_WriteAfterReceivingStatusThrowsRpcException2() { var resultTask = asyncCall.ClientStreamingCallAsync(); var requestStream = new ClientRequestStream(asyncCall); fakeCall.UnaryResponseClientHandler(true, new ClientSideStatus(new Status(StatusCode.OutOfRange, ""), new Metadata()), CreateResponsePayload(), new Metadata()); AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.OutOfRange); var writeTask = requestStream.WriteAsync("request1"); var ex = Assert.ThrowsAsync(async () => await writeTask); Assert.AreEqual(StatusCode.OutOfRange, ex.Status.StatusCode); } [Test] public void ClientStreaming_WriteAfterCompleteThrowsInvalidOperationException() { var resultTask = asyncCall.ClientStreamingCallAsync(); var requestStream = new ClientRequestStream(asyncCall); requestStream.CompleteAsync(); Assert.Throws(typeof(InvalidOperationException), () => requestStream.WriteAsync("request1")); fakeCall.SendCompletionHandler(true); fakeCall.UnaryResponseClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata()), CreateResponsePayload(), new Metadata()); AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask); } [Test] public void ClientStreaming_CompleteAfterReceivingStatusSucceeds() { var resultTask = asyncCall.ClientStreamingCallAsync(); var requestStream = new ClientRequestStream(asyncCall); fakeCall.UnaryResponseClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata()), CreateResponsePayload(), new Metadata()); AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask); Assert.DoesNotThrowAsync(async () => await requestStream.CompleteAsync()); } [Test] public void ClientStreaming_WriteAfterCancellationRequestThrowsTaskCanceledException() { var resultTask = asyncCall.ClientStreamingCallAsync(); var requestStream = new ClientRequestStream(asyncCall); asyncCall.Cancel(); Assert.IsTrue(fakeCall.IsCancelled); var writeTask = requestStream.WriteAsync("request1"); Assert.ThrowsAsync(typeof(TaskCanceledException), async () => await writeTask); fakeCall.UnaryResponseClientHandler(true, CreateClientSideStatus(StatusCode.Cancelled), null, new Metadata()); AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Cancelled); } [Test] public void ServerStreaming_StreamingSendNotAllowed() { asyncCall.StartServerStreamingCall("request1"); Assert.Throws(typeof(InvalidOperationException), () => asyncCall.SendMessageAsync("abc", new WriteFlags())); } [Test] public void ServerStreaming_NoResponse_Success1() { asyncCall.StartServerStreamingCall("request1"); var responseStream = new ClientResponseStream(asyncCall); var readTask = responseStream.MoveNext(); fakeCall.ReceivedResponseHeadersHandler(true, new Metadata()); Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count); fakeCall.ReceivedMessageHandler(true, null); fakeCall.ReceivedStatusOnClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata())); AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask); } [Test] public void ServerStreaming_NoResponse_Success2() { asyncCall.StartServerStreamingCall("request1"); var responseStream = new ClientResponseStream(asyncCall); var readTask = responseStream.MoveNext(); // try alternative order of completions fakeCall.ReceivedStatusOnClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata())); fakeCall.ReceivedMessageHandler(true, null); AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask); } [Test] public void ServerStreaming_NoResponse_ReadFailure() { asyncCall.StartServerStreamingCall("request1"); var responseStream = new ClientResponseStream(asyncCall); var readTask = responseStream.MoveNext(); fakeCall.ReceivedMessageHandler(false, null); // after a failed read, we rely on C core to deliver appropriate status code. fakeCall.ReceivedStatusOnClientHandler(true, CreateClientSideStatus(StatusCode.Internal)); AssertStreamingResponseError(asyncCall, fakeCall, readTask, StatusCode.Internal); } [Test] public void ServerStreaming_MoreResponses_Success() { asyncCall.StartServerStreamingCall("request1"); var responseStream = new ClientResponseStream(asyncCall); var readTask1 = responseStream.MoveNext(); fakeCall.ReceivedMessageHandler(true, CreateResponsePayload()); Assert.IsTrue(readTask1.Result); Assert.AreEqual("response1", responseStream.Current); var readTask2 = responseStream.MoveNext(); fakeCall.ReceivedMessageHandler(true, CreateResponsePayload()); Assert.IsTrue(readTask2.Result); Assert.AreEqual("response1", responseStream.Current); var readTask3 = responseStream.MoveNext(); fakeCall.ReceivedStatusOnClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata())); fakeCall.ReceivedMessageHandler(true, null); AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask3); } [Test] public void DuplexStreaming_NoRequestNoResponse_Success() { asyncCall.StartDuplexStreamingCall(); var requestStream = new ClientRequestStream(asyncCall); var responseStream = new ClientResponseStream(asyncCall); var writeTask1 = requestStream.CompleteAsync(); fakeCall.SendCompletionHandler(true); Assert.DoesNotThrowAsync(async () => await writeTask1); var readTask = responseStream.MoveNext(); fakeCall.ReceivedMessageHandler(true, null); fakeCall.ReceivedStatusOnClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata())); AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask); } [Test] public void DuplexStreaming_WriteAfterReceivingStatusThrowsRpcException() { asyncCall.StartDuplexStreamingCall(); var requestStream = new ClientRequestStream(asyncCall); var responseStream = new ClientResponseStream(asyncCall); var readTask = responseStream.MoveNext(); fakeCall.ReceivedMessageHandler(true, null); fakeCall.ReceivedStatusOnClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata())); AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask); var writeTask = requestStream.WriteAsync("request1"); var ex = Assert.ThrowsAsync(async () => await writeTask); Assert.AreEqual(Status.DefaultSuccess, ex.Status); } [Test] public void DuplexStreaming_CompleteAfterReceivingStatusSuceeds() { asyncCall.StartDuplexStreamingCall(); var requestStream = new ClientRequestStream(asyncCall); var responseStream = new ClientResponseStream(asyncCall); var readTask = responseStream.MoveNext(); fakeCall.ReceivedMessageHandler(true, null); fakeCall.ReceivedStatusOnClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata())); AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask); Assert.DoesNotThrowAsync(async () => await requestStream.CompleteAsync()); } [Test] public void DuplexStreaming_WriteFailureThrowsRpcException() { asyncCall.StartDuplexStreamingCall(); var requestStream = new ClientRequestStream(asyncCall); var responseStream = new ClientResponseStream(asyncCall); var writeTask = requestStream.WriteAsync("request1"); fakeCall.SendCompletionHandler(false); // The write will wait for call to finish to receive the status code. Assert.IsFalse(writeTask.IsCompleted); var readTask = responseStream.MoveNext(); fakeCall.ReceivedMessageHandler(true, null); fakeCall.ReceivedStatusOnClientHandler(true, CreateClientSideStatus(StatusCode.PermissionDenied)); var ex = Assert.ThrowsAsync(async () => await writeTask); Assert.AreEqual(StatusCode.PermissionDenied, ex.Status.StatusCode); AssertStreamingResponseError(asyncCall, fakeCall, readTask, StatusCode.PermissionDenied); } [Test] public void DuplexStreaming_WriteFailureThrowsRpcException2() { asyncCall.StartDuplexStreamingCall(); var requestStream = new ClientRequestStream(asyncCall); var responseStream = new ClientResponseStream(asyncCall); var writeTask = requestStream.WriteAsync("request1"); var readTask = responseStream.MoveNext(); fakeCall.ReceivedMessageHandler(true, null); fakeCall.ReceivedStatusOnClientHandler(true, CreateClientSideStatus(StatusCode.PermissionDenied)); fakeCall.SendCompletionHandler(false); var ex = Assert.ThrowsAsync(async () => await writeTask); Assert.AreEqual(StatusCode.PermissionDenied, ex.Status.StatusCode); AssertStreamingResponseError(asyncCall, fakeCall, readTask, StatusCode.PermissionDenied); } [Test] public void DuplexStreaming_WriteAfterCancellationRequestThrowsTaskCanceledException() { asyncCall.StartDuplexStreamingCall(); var requestStream = new ClientRequestStream(asyncCall); var responseStream = new ClientResponseStream(asyncCall); asyncCall.Cancel(); Assert.IsTrue(fakeCall.IsCancelled); var writeTask = requestStream.WriteAsync("request1"); Assert.ThrowsAsync(typeof(TaskCanceledException), async () => await writeTask); var readTask = responseStream.MoveNext(); fakeCall.ReceivedMessageHandler(true, null); fakeCall.ReceivedStatusOnClientHandler(true, CreateClientSideStatus(StatusCode.Cancelled)); AssertStreamingResponseError(asyncCall, fakeCall, readTask, StatusCode.Cancelled); } [Test] public void DuplexStreaming_ReadAfterCancellationRequestCanSucceed() { asyncCall.StartDuplexStreamingCall(); var responseStream = new ClientResponseStream(asyncCall); asyncCall.Cancel(); Assert.IsTrue(fakeCall.IsCancelled); var readTask1 = responseStream.MoveNext(); fakeCall.ReceivedMessageHandler(true, CreateResponsePayload()); Assert.IsTrue(readTask1.Result); Assert.AreEqual("response1", responseStream.Current); var readTask2 = responseStream.MoveNext(); fakeCall.ReceivedMessageHandler(true, null); fakeCall.ReceivedStatusOnClientHandler(true, CreateClientSideStatus(StatusCode.Cancelled)); AssertStreamingResponseError(asyncCall, fakeCall, readTask2, StatusCode.Cancelled); } [Test] public void DuplexStreaming_ReadStartedBeforeCancellationRequestCanSucceed() { asyncCall.StartDuplexStreamingCall(); var responseStream = new ClientResponseStream(asyncCall); var readTask1 = responseStream.MoveNext(); // initiate the read before cancel request asyncCall.Cancel(); Assert.IsTrue(fakeCall.IsCancelled); fakeCall.ReceivedMessageHandler(true, CreateResponsePayload()); Assert.IsTrue(readTask1.Result); Assert.AreEqual("response1", responseStream.Current); var readTask2 = responseStream.MoveNext(); fakeCall.ReceivedMessageHandler(true, null); fakeCall.ReceivedStatusOnClientHandler(true, CreateClientSideStatus(StatusCode.Cancelled)); AssertStreamingResponseError(asyncCall, fakeCall, readTask2, StatusCode.Cancelled); } ClientSideStatus CreateClientSideStatus(StatusCode statusCode) { return new ClientSideStatus(new Status(statusCode, ""), new Metadata()); } byte[] CreateResponsePayload() { return Marshallers.StringMarshaller.Serializer("response1"); } static void AssertUnaryResponseSuccess(AsyncCall asyncCall, FakeNativeCall fakeCall, Task resultTask) { Assert.IsTrue(resultTask.IsCompleted); Assert.IsTrue(fakeCall.IsDisposed); Assert.AreEqual(Status.DefaultSuccess, asyncCall.GetStatus()); Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count); Assert.AreEqual(0, asyncCall.GetTrailers().Count); Assert.AreEqual("response1", resultTask.Result); } static void AssertStreamingResponseSuccess(AsyncCall asyncCall, FakeNativeCall fakeCall, Task moveNextTask) { Assert.IsTrue(moveNextTask.IsCompleted); Assert.IsTrue(fakeCall.IsDisposed); Assert.IsFalse(moveNextTask.Result); Assert.AreEqual(Status.DefaultSuccess, asyncCall.GetStatus()); Assert.AreEqual(0, asyncCall.GetTrailers().Count); } static void AssertUnaryResponseError(AsyncCall asyncCall, FakeNativeCall fakeCall, Task resultTask, StatusCode expectedStatusCode) { Assert.IsTrue(resultTask.IsCompleted); Assert.IsTrue(fakeCall.IsDisposed); Assert.AreEqual(expectedStatusCode, asyncCall.GetStatus().StatusCode); var ex = Assert.ThrowsAsync(async () => await resultTask); Assert.AreEqual(expectedStatusCode, ex.Status.StatusCode); Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count); Assert.AreEqual(0, asyncCall.GetTrailers().Count); } static void AssertStreamingResponseError(AsyncCall asyncCall, FakeNativeCall fakeCall, Task moveNextTask, StatusCode expectedStatusCode) { Assert.IsTrue(moveNextTask.IsCompleted); Assert.IsTrue(fakeCall.IsDisposed); var ex = Assert.ThrowsAsync(async () => await moveNextTask); Assert.AreEqual(expectedStatusCode, ex.Status.StatusCode); Assert.AreEqual(expectedStatusCode, asyncCall.GetStatus().StatusCode); Assert.AreEqual(0, asyncCall.GetTrailers().Count); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/Internal/ChannelArgsSafeHandleTest.cs000066400000000000000000000052121310511640000264340ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Internal.Tests { public class ChannelArgsSafeHandleTest { [Test] public void CreateEmptyAndDestroy() { var channelArgs = ChannelArgsSafeHandle.Create(0); channelArgs.Dispose(); } [Test] public void CreateNonEmptyAndDestroy() { var channelArgs = ChannelArgsSafeHandle.Create(5); channelArgs.Dispose(); } [Test] public void CreateNullAndDestroy() { var channelArgs = ChannelArgsSafeHandle.CreateNull(); channelArgs.Dispose(); } [Test] public void CreateFillAndDestroy() { var channelArgs = ChannelArgsSafeHandle.Create(3); channelArgs.SetInteger(0, "somekey", 12345); channelArgs.SetString(1, "somekey", "abcdefghijkl"); channelArgs.SetString(2, "somekey", "XYZ"); channelArgs.Dispose(); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/Internal/CompletionQueueEventTest.cs000066400000000000000000000040061310511640000264540ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.InteropServices; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Internal.Tests { public class CompletionQueueEventTest { [Test] public void CreateAndDestroy() { Assert.AreEqual(CompletionQueueEvent.NativeSize, Marshal.SizeOf(typeof(CompletionQueueEvent))); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/Internal/CompletionQueueSafeHandleTest.cs000066400000000000000000000050271310511640000273710ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Internal.Tests { public class CompletionQueueSafeHandleTest { [Test] public void CreateAndDestroy() { GrpcEnvironment.AddRef(); var cq = CompletionQueueSafeHandle.Create(); cq.Dispose(); GrpcEnvironment.ReleaseAsync().Wait(); } [Test] public void CreateAndShutdown() { GrpcEnvironment.AddRef(); var cq = CompletionQueueSafeHandle.Create(); cq.Shutdown(); var ev = cq.Next(); cq.Dispose(); GrpcEnvironment.ReleaseAsync().Wait(); Assert.AreEqual(CompletionQueueEvent.CompletionType.Shutdown, ev.type); Assert.AreNotEqual(IntPtr.Zero, ev.success); Assert.AreEqual(IntPtr.Zero, ev.tag); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/Internal/FakeNativeCall.cs000066400000000000000000000131741310511640000243130ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading.Tasks; using Grpc.Core.Internal; using NUnit.Framework; namespace Grpc.Core.Internal.Tests { /// /// For testing purposes. /// internal class FakeNativeCall : INativeCall { public UnaryResponseClientHandler UnaryResponseClientHandler { get; set; } public ReceivedStatusOnClientHandler ReceivedStatusOnClientHandler { get; set; } public ReceivedMessageHandler ReceivedMessageHandler { get; set; } public ReceivedResponseHeadersHandler ReceivedResponseHeadersHandler { get; set; } public SendCompletionHandler SendCompletionHandler { get; set; } public SendCompletionHandler SendStatusFromServerHandler { get; set; } public ReceivedCloseOnServerHandler ReceivedCloseOnServerHandler { get; set; } public bool IsCancelled { get; set; } public bool IsDisposed { get; set; } public void Cancel() { IsCancelled = true; } public void CancelWithStatus(Status status) { IsCancelled = true; } public string GetPeer() { return "PEER"; } public void StartUnary(UnaryResponseClientHandler callback, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags) { UnaryResponseClientHandler = callback; } public void StartUnary(BatchContextSafeHandle ctx, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags) { throw new NotImplementedException(); } public void StartClientStreaming(UnaryResponseClientHandler callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags) { UnaryResponseClientHandler = callback; } public void StartServerStreaming(ReceivedStatusOnClientHandler callback, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags) { ReceivedStatusOnClientHandler = callback; } public void StartDuplexStreaming(ReceivedStatusOnClientHandler callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags) { ReceivedStatusOnClientHandler = callback; } public void StartReceiveMessage(ReceivedMessageHandler callback) { ReceivedMessageHandler = callback; } public void StartReceiveInitialMetadata(ReceivedResponseHeadersHandler callback) { ReceivedResponseHeadersHandler = callback; } public void StartSendInitialMetadata(SendCompletionHandler callback, MetadataArraySafeHandle metadataArray) { SendCompletionHandler = callback; } public void StartSendMessage(SendCompletionHandler callback, byte[] payload, WriteFlags writeFlags, bool sendEmptyInitialMetadata) { SendCompletionHandler = callback; } public void StartSendCloseFromClient(SendCompletionHandler callback) { SendCompletionHandler = callback; } public void StartSendStatusFromServer(SendCompletionHandler callback, Status status, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata, byte[] optionalPayload, WriteFlags writeFlags) { SendStatusFromServerHandler = callback; } public void StartServerSide(ReceivedCloseOnServerHandler callback) { ReceivedCloseOnServerHandler = callback; } public void Dispose() { IsDisposed = true; } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/Internal/MetadataArraySafeHandleTest.cs000066400000000000000000000057701310511640000267770ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Internal.Tests { public class MetadataArraySafeHandleTest { [Test] public void CreateEmptyAndDestroy() { var nativeMetadata = MetadataArraySafeHandle.Create(new Metadata()); nativeMetadata.Dispose(); } [Test] public void CreateAndDestroy() { var metadata = new Metadata { { "host", "somehost" }, { "header2", "header value" }, }; var nativeMetadata = MetadataArraySafeHandle.Create(metadata); nativeMetadata.Dispose(); } [Test] public void ReadMetadataFromPtrUnsafe() { var metadata = new Metadata { { "host", "somehost" }, { "header2", "header value" } }; var nativeMetadata = MetadataArraySafeHandle.Create(metadata); var copy = MetadataArraySafeHandle.ReadMetadataFromPtrUnsafe(nativeMetadata.Handle); Assert.AreEqual(2, copy.Count); Assert.AreEqual("host", copy[0].Key); Assert.AreEqual("somehost", copy[0].Value); Assert.AreEqual("header2", copy[1].Key); Assert.AreEqual("header value", copy[1].Value); nativeMetadata.Dispose(); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs000066400000000000000000000162511310511640000241120ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.InteropServices; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Internal.Tests { public class TimespecTest { [Test] public void Now_IsInUtc() { Assert.AreEqual(DateTimeKind.Utc, Timespec.Now.ToDateTime().Kind); } [Test] public void Now_AgreesWithUtcNow() { var timespec = Timespec.Now; var utcNow = DateTime.UtcNow; TimeSpan difference = utcNow - timespec.ToDateTime(); // This test is inherently a race - but the two timestamps // should really be way less that a minute apart. Assert.IsTrue(difference.TotalSeconds < 60); } [Test] public void InfFutureMatchesNativeValue() { Assert.AreEqual(Timespec.NativeInfFuture, Timespec.InfFuture); } [Test] public void InfPastMatchesNativeValue() { Assert.AreEqual(Timespec.NativeInfPast, Timespec.InfPast); } [Test] public void TimespecSizeIsNativeSize() { Assert.AreEqual(Timespec.NativeSize, Marshal.SizeOf(typeof(Timespec))); } [Test] public void ToDateTime() { Assert.AreEqual(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc), new Timespec(0, 0).ToDateTime()); Assert.AreEqual(new DateTime(1970, 1, 1, 0, 0, 10, DateTimeKind.Utc).AddTicks(50), new Timespec(10, 5000).ToDateTime()); Assert.AreEqual(new DateTime(2015, 7, 21, 4, 21, 48, DateTimeKind.Utc), new Timespec(1437452508, 0).ToDateTime()); // before epoch Assert.AreEqual(new DateTime(1969, 12, 31, 23, 59, 55, DateTimeKind.Utc).AddTicks(10), new Timespec(-5, 1000).ToDateTime()); // infinity Assert.AreEqual(DateTime.MaxValue, Timespec.InfFuture.ToDateTime()); Assert.AreEqual(DateTime.MinValue, Timespec.InfPast.ToDateTime()); // nanos are rounded to ticks are rounded up Assert.AreEqual(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddTicks(1), new Timespec(0, 99).ToDateTime()); // Illegal inputs Assert.Throws(typeof(InvalidOperationException), () => new Timespec(0, -2).ToDateTime()); Assert.Throws(typeof(InvalidOperationException), () => new Timespec(0, 1000 * 1000 * 1000).ToDateTime()); Assert.Throws(typeof(InvalidOperationException), () => new Timespec(0, 0, ClockType.Monotonic).ToDateTime()); } [Test] public void ToDateTime_ReturnsUtc() { Assert.AreEqual(DateTimeKind.Utc, new Timespec(1437452508, 0).ToDateTime().Kind); Assert.AreNotEqual(DateTimeKind.Unspecified, new Timespec(1437452508, 0).ToDateTime().Kind); } [Test] public void ToDateTime_Overflow() { var timespec = new Timespec(long.MaxValue - 100, 0); Assert.AreNotEqual(Timespec.InfFuture, timespec); Assert.AreEqual(DateTime.MaxValue, timespec.ToDateTime()); Assert.AreEqual(DateTime.MinValue, new Timespec(long.MinValue + 100, 0).ToDateTime()); } [Test] public void ToDateTime_OutOfDateTimeRange() { // DateTime range goes up to year 9999, 20000 years from now should // be out of range. long seconds = 20000L * 365L * 24L * 3600L; var timespec = new Timespec(seconds, 0); Assert.AreNotEqual(Timespec.InfFuture, timespec); Assert.AreEqual(DateTime.MaxValue, timespec.ToDateTime()); Assert.AreEqual(DateTime.MinValue, new Timespec(-seconds, 0).ToDateTime()); } [Test] public void FromDateTime() { Assert.AreEqual(new Timespec(0, 0), Timespec.FromDateTime(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc))); Assert.AreEqual(new Timespec(10, 5000), Timespec.FromDateTime(new DateTime(1970, 1, 1, 0, 0, 10, DateTimeKind.Utc).AddTicks(50))); Assert.AreEqual(new Timespec(1437452508, 0), Timespec.FromDateTime(new DateTime(2015, 7, 21, 4, 21, 48, DateTimeKind.Utc))); // before epoch Assert.AreEqual(new Timespec(-5, 1000), Timespec.FromDateTime(new DateTime(1969, 12, 31, 23, 59, 55, DateTimeKind.Utc).AddTicks(10))); // infinity Assert.AreEqual(Timespec.InfFuture, Timespec.FromDateTime(DateTime.MaxValue)); Assert.AreEqual(Timespec.InfPast, Timespec.FromDateTime(DateTime.MinValue)); // illegal inputs Assert.Throws(typeof(ArgumentException), () => Timespec.FromDateTime(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Unspecified))); } [Test] [Category("Performance")] [Ignore("Prevent running on Jenkins")] public void NowBenchmark() { // approx Timespec.Now latency <33ns BenchmarkUtil.RunBenchmark(10000000, 1000000000, () => { var now = Timespec.Now; }); } [Test] [Category("Performance")] [Ignore("Prevent running on Jenkins")] public void PreciseNowBenchmark() { // approx Timespec.PreciseNow latency <18ns (when compiled with GRPC_TIMERS_RDTSC) BenchmarkUtil.RunBenchmark(10000000, 1000000000, () => { var now = Timespec.PreciseNow; }); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/MarshallingErrorsTest.cs000066400000000000000000000160051310511640000242200ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { public class MarshallingErrorsTest { const string Host = "127.0.0.1"; MockServiceHelper helper; Server server; Channel channel; [SetUp] public void Init() { var marshaller = new Marshaller( (str) => { if (str == "UNSERIALIZABLE_VALUE") { // Google.Protobuf throws exception inherited from IOException throw new IOException("Error serializing the message."); } return System.Text.Encoding.UTF8.GetBytes(str); }, (payload) => { var s = System.Text.Encoding.UTF8.GetString(payload); if (s == "UNPARSEABLE_VALUE") { // Google.Protobuf throws exception inherited from IOException throw new IOException("Error parsing the message."); } return s; }); helper = new MockServiceHelper(Host, marshaller); server = helper.GetServer(); server.Start(); channel = helper.GetChannel(); } [TearDown] public void Cleanup() { channel.ShutdownAsync().Wait(); server.ShutdownAsync().Wait(); } [Test] public void ResponseParsingError_UnaryResponse() { helper.UnaryHandler = new UnaryServerMethod((request, context) => { return Task.FromResult("UNPARSEABLE_VALUE"); }); var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "REQUEST")); Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode); } [Test] public void ResponseParsingError_StreamingResponse() { helper.ServerStreamingHandler = new ServerStreamingServerMethod(async (request, responseStream, context) => { await responseStream.WriteAsync("UNPARSEABLE_VALUE"); await Task.Delay(10000); }); var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), "REQUEST"); var ex = Assert.ThrowsAsync(async () => await call.ResponseStream.MoveNext()); Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode); } [Test] public void RequestParsingError_UnaryRequest() { helper.UnaryHandler = new UnaryServerMethod((request, context) => { return Task.FromResult("RESPONSE"); }); var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "UNPARSEABLE_VALUE")); // Spec doesn't define the behavior. With the current implementation server handler throws exception which results in StatusCode.Unknown. Assert.AreEqual(StatusCode.Unknown, ex.Status.StatusCode); } [Test] public async Task RequestParsingError_StreamingRequest() { helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => { try { // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock. await requestStream.MoveNext(); Assert.Fail(); } catch (IOException) { } return "RESPONSE"; }); var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall()); await call.RequestStream.WriteAsync("UNPARSEABLE_VALUE"); Assert.AreEqual("RESPONSE", await call); } [Test] public void RequestSerializationError_BlockingUnary() { Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "UNSERIALIZABLE_VALUE")); } [Test] public void RequestSerializationError_AsyncUnary() { Assert.ThrowsAsync(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "UNSERIALIZABLE_VALUE")); } [Test] public async Task RequestSerializationError_ClientStreaming() { helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => { CollectionAssert.AreEqual(new[] { "A", "B" }, await requestStream.ToListAsync()); return "RESPONSE"; }); var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall()); await call.RequestStream.WriteAsync("A"); Assert.ThrowsAsync(async () => await call.RequestStream.WriteAsync("UNSERIALIZABLE_VALUE")); await call.RequestStream.WriteAsync("B"); await call.RequestStream.CompleteAsync(); Assert.AreEqual("RESPONSE", await call); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/MetadataTest.cs000066400000000000000000000215511310511640000223040ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { public class MetadataTest { [Test] public void AsciiEntry() { var entry = new Metadata.Entry("ABC", "XYZ"); Assert.IsFalse(entry.IsBinary); Assert.AreEqual("abc", entry.Key); // key is in lowercase. Assert.AreEqual("XYZ", entry.Value); CollectionAssert.AreEqual(new[] { (byte)'X', (byte)'Y', (byte)'Z' }, entry.ValueBytes); Assert.Throws(typeof(ArgumentException), () => new Metadata.Entry("abc-bin", "xyz")); Assert.AreEqual("[Entry: key=abc, value=XYZ]", entry.ToString()); } [Test] public void BinaryEntry() { var bytes = new byte[] { 1, 2, 3 }; var entry = new Metadata.Entry("ABC-BIN", bytes); Assert.IsTrue(entry.IsBinary); Assert.AreEqual("abc-bin", entry.Key); // key is in lowercase. Assert.Throws(typeof(InvalidOperationException), () => { var v = entry.Value; }); CollectionAssert.AreEqual(bytes, entry.ValueBytes); Assert.Throws(typeof(ArgumentException), () => new Metadata.Entry("abc", bytes)); Assert.AreEqual("[Entry: key=abc-bin, valueBytes=System.Byte[]]", entry.ToString()); } [Test] public void AsciiEntry_KeyValidity() { new Metadata.Entry("ABC", "XYZ"); new Metadata.Entry("0123456789abc", "XYZ"); new Metadata.Entry("-abc", "XYZ"); new Metadata.Entry("a_bc_", "XYZ"); Assert.Throws(typeof(ArgumentException), () => new Metadata.Entry("abc[", "xyz")); Assert.Throws(typeof(ArgumentException), () => new Metadata.Entry("abc/", "xyz")); } [Test] public void Entry_ConstructionPreconditions() { Assert.Throws(typeof(ArgumentNullException), () => new Metadata.Entry(null, "xyz")); Assert.Throws(typeof(ArgumentNullException), () => new Metadata.Entry("abc", (string)null)); Assert.Throws(typeof(ArgumentNullException), () => new Metadata.Entry("abc-bin", (byte[])null)); } [Test] public void Entry_Immutable() { var origBytes = new byte[] { 1, 2, 3 }; var bytes = new byte[] { 1, 2, 3 }; var entry = new Metadata.Entry("ABC-BIN", bytes); bytes[0] = 255; // changing the array passed to constructor should have any effect. CollectionAssert.AreEqual(origBytes, entry.ValueBytes); entry.ValueBytes[0] = 255; CollectionAssert.AreEqual(origBytes, entry.ValueBytes); } [Test] public void Entry_CreateUnsafe_Ascii() { var bytes = new byte[] { (byte)'X', (byte)'y' }; var entry = Metadata.Entry.CreateUnsafe("abc", bytes); Assert.IsFalse(entry.IsBinary); Assert.AreEqual("abc", entry.Key); Assert.AreEqual("Xy", entry.Value); CollectionAssert.AreEqual(bytes, entry.ValueBytes); } [Test] public void Entry_CreateUnsafe_Binary() { var bytes = new byte[] { 1, 2, 3 }; var entry = Metadata.Entry.CreateUnsafe("abc-bin", bytes); Assert.IsTrue(entry.IsBinary); Assert.AreEqual("abc-bin", entry.Key); Assert.Throws(typeof(InvalidOperationException), () => { var v = entry.Value; }); CollectionAssert.AreEqual(bytes, entry.ValueBytes); } [Test] public void IndexOf() { var metadata = CreateMetadata(); Assert.AreEqual(0, metadata.IndexOf(metadata[0])); Assert.AreEqual(1, metadata.IndexOf(metadata[1])); } [Test] public void Insert() { var metadata = CreateMetadata(); metadata.Insert(0, new Metadata.Entry("new-key", "new-value")); Assert.AreEqual(3, metadata.Count); Assert.AreEqual("new-key", metadata[0].Key); Assert.AreEqual("abc", metadata[1].Key); } [Test] public void RemoveAt() { var metadata = CreateMetadata(); metadata.RemoveAt(0); Assert.AreEqual(1, metadata.Count); Assert.AreEqual("xyz", metadata[0].Key); } [Test] public void Remove() { var metadata = CreateMetadata(); metadata.Remove(metadata[0]); Assert.AreEqual(1, metadata.Count); Assert.AreEqual("xyz", metadata[0].Key); } [Test] public void Indexer_Set() { var metadata = CreateMetadata(); var entry = new Metadata.Entry("new-key", "new-value"); metadata[1] = entry; Assert.AreEqual(entry, metadata[1]); } [Test] public void Clear() { var metadata = CreateMetadata(); metadata.Clear(); Assert.AreEqual(0, metadata.Count); } [Test] public void Contains() { var metadata = CreateMetadata(); Assert.IsTrue(metadata.Contains(metadata[0])); Assert.IsFalse(metadata.Contains(new Metadata.Entry("new-key", "new-value"))); } [Test] public void CopyTo() { var metadata = CreateMetadata(); var array = new Metadata.Entry[metadata.Count + 1]; metadata.CopyTo(array, 1); Assert.AreEqual(default(Metadata.Entry), array[0]); Assert.AreEqual(metadata[0], array[1]); } [Test] public void IEnumerableGetEnumerator() { var metadata = CreateMetadata(); var enumerator = (metadata as System.Collections.IEnumerable).GetEnumerator(); int i = 0; while (enumerator.MoveNext()) { Assert.AreEqual(metadata[i], enumerator.Current); i++; } } [Test] public void FreezeMakesReadOnly() { var entry = new Metadata.Entry("new-key", "new-value"); var metadata = CreateMetadata().Freeze(); Assert.IsTrue(metadata.IsReadOnly); Assert.Throws(() => metadata.Insert(0, entry)); Assert.Throws(() => metadata.RemoveAt(0)); Assert.Throws(() => metadata[0] = entry); Assert.Throws(() => metadata.Add(entry)); Assert.Throws(() => metadata.Add("new-key", "new-value")); Assert.Throws(() => metadata.Add("new-key-bin", new byte[] { 0xaa })); Assert.Throws(() => metadata.Clear()); Assert.Throws(() => metadata.Remove(metadata[0])); } private Metadata CreateMetadata() { return new Metadata { { "abc", "abc-value" }, { "xyz", "xyz-value" }, }; } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/MockServiceHelper.cs000066400000000000000000000215751310511640000233040ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { /// /// Allows setting up a mock service in the client-server tests easily. /// public class MockServiceHelper { public const string ServiceName = "tests.Test"; readonly string host; readonly ServerServiceDefinition serviceDefinition; readonly IEnumerable channelOptions; readonly Method unaryMethod; readonly Method clientStreamingMethod; readonly Method serverStreamingMethod; readonly Method duplexStreamingMethod; UnaryServerMethod unaryHandler; ClientStreamingServerMethod clientStreamingHandler; ServerStreamingServerMethod serverStreamingHandler; DuplexStreamingServerMethod duplexStreamingHandler; Server server; Channel channel; public MockServiceHelper(string host = null, Marshaller marshaller = null, IEnumerable channelOptions = null) { this.host = host ?? "localhost"; this.channelOptions = channelOptions; marshaller = marshaller ?? Marshallers.StringMarshaller; unaryMethod = new Method( MethodType.Unary, ServiceName, "Unary", marshaller, marshaller); clientStreamingMethod = new Method( MethodType.ClientStreaming, ServiceName, "ClientStreaming", marshaller, marshaller); serverStreamingMethod = new Method( MethodType.ServerStreaming, ServiceName, "ServerStreaming", marshaller, marshaller); duplexStreamingMethod = new Method( MethodType.DuplexStreaming, ServiceName, "DuplexStreaming", marshaller, marshaller); serviceDefinition = ServerServiceDefinition.CreateBuilder() .AddMethod(unaryMethod, (request, context) => unaryHandler(request, context)) .AddMethod(clientStreamingMethod, (requestStream, context) => clientStreamingHandler(requestStream, context)) .AddMethod(serverStreamingMethod, (request, responseStream, context) => serverStreamingHandler(request, responseStream, context)) .AddMethod(duplexStreamingMethod, (requestStream, responseStream, context) => duplexStreamingHandler(requestStream, responseStream, context)) .Build(); var defaultStatus = new Status(StatusCode.Unknown, "Default mock implementation. Please provide your own."); unaryHandler = new UnaryServerMethod(async (request, context) => { context.Status = defaultStatus; return ""; }); clientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => { context.Status = defaultStatus; return ""; }); serverStreamingHandler = new ServerStreamingServerMethod(async (request, responseStream, context) => { context.Status = defaultStatus; }); duplexStreamingHandler = new DuplexStreamingServerMethod(async (requestStream, responseStream, context) => { context.Status = defaultStatus; }); } /// /// Returns the default server for this service and creates one if not yet created. /// public Server GetServer() { if (server == null) { // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) { Services = { serviceDefinition }, Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } } }; } return server; } /// /// Returns the default channel for this service and creates one if not yet created. /// public Channel GetChannel() { if (channel == null) { channel = new Channel(Host, GetServer().Ports.Single().BoundPort, ChannelCredentials.Insecure, channelOptions); } return channel; } public CallInvocationDetails CreateUnaryCall(CallOptions options = default(CallOptions)) { return new CallInvocationDetails(channel, unaryMethod, options); } public CallInvocationDetails CreateClientStreamingCall(CallOptions options = default(CallOptions)) { return new CallInvocationDetails(channel, clientStreamingMethod, options); } public CallInvocationDetails CreateServerStreamingCall(CallOptions options = default(CallOptions)) { return new CallInvocationDetails(channel, serverStreamingMethod, options); } public CallInvocationDetails CreateDuplexStreamingCall(CallOptions options = default(CallOptions)) { return new CallInvocationDetails(channel, duplexStreamingMethod, options); } public string Host { get { return this.host; } } public ServerServiceDefinition ServiceDefinition { get { return this.serviceDefinition; } } public UnaryServerMethod UnaryHandler { get { return this.unaryHandler; } set { unaryHandler = value; } } public ClientStreamingServerMethod ClientStreamingHandler { get { return this.clientStreamingHandler; } set { clientStreamingHandler = value; } } public ServerStreamingServerMethod ServerStreamingHandler { get { return this.serverStreamingHandler; } set { serverStreamingHandler = value; } } public DuplexStreamingServerMethod DuplexStreamingHandler { get { return this.duplexStreamingHandler; } set { duplexStreamingHandler = value; } } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/NUnitMain.cs000066400000000000000000000044731310511640000215720ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Reflection; using Grpc.Core; using Grpc.Core.Logging; using NUnit.Common; using NUnitLite; namespace Grpc.Core.Tests { /// /// Provides entry point for NUnitLite /// public class NUnitMain { public static int Main(string[] args) { // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error)); #if NETCOREAPP1_0 return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In); #else return new AutoRun().Execute(args); #endif } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/PInvokeTest.cs000066400000000000000000000106131310511640000221340ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { public class PInvokeTest { static readonly NativeMethods Native = NativeMethods.Get(); int counter; /// /// (~1.26us .NET Windows) /// [Test] public void CompletionQueueCreateDestroyBenchmark() { GrpcEnvironment.AddRef(); // completion queue requires gRPC environment being initialized. BenchmarkUtil.RunBenchmark( 10, 10, () => { CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create(); cq.Dispose(); }); GrpcEnvironment.ReleaseAsync().Wait(); } /// /// Approximate results: /// (~80ns Mono Linux) /// (~110ns .NET Windows) /// [Test] [Category("Performance")] [Ignore("Prevent running on Jenkins")] public void NativeCallbackBenchmark() { OpCompletionDelegate handler = Handler; counter = 0; BenchmarkUtil.RunBenchmark( 1000000, 10000000, () => { Native.grpcsharp_test_callback(handler); }); Assert.AreNotEqual(0, counter); } /// /// Creating a new native-to-managed callback has significant overhead /// compared to using an existing one. We need to be aware of this. /// (~50us on Mono Linux!!!) /// (~1.1us on .NET Windows) /// [Test] [Category("Performance")] [Ignore("Prevent running on Jenkins")] public void NewNativeCallbackBenchmark() { counter = 0; BenchmarkUtil.RunBenchmark( 10000, 10000, () => { Native.grpcsharp_test_callback(new OpCompletionDelegate(Handler)); }); Assert.AreNotEqual(0, counter); } /// /// Tests overhead of a simple PInvoke call. /// (~46ns .NET Windows) /// [Test] [Category("Performance")] [Ignore("Prevent running on Jenkins")] public void NopPInvokeBenchmark() { BenchmarkUtil.RunBenchmark( 1000000, 100000000, () => { Native.grpcsharp_test_nop(IntPtr.Zero); }); } private void Handler(bool success) { counter++; } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/PerformanceTest.cs000066400000000000000000000062751310511640000230330ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Profiling; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { public class PerformanceTest { const string Host = "127.0.0.1"; MockServiceHelper helper; Server server; Channel channel; [SetUp] public void Init() { helper = new MockServiceHelper(Host); server = helper.GetServer(); server.Start(); channel = helper.GetChannel(); } [TearDown] public void Cleanup() { channel.ShutdownAsync().Wait(); server.ShutdownAsync().Wait(); } [Test] [Category("Performance")] [Ignore("Prevent running on Jenkins")] public void UnaryCallPerformance() { var profiler = new BasicProfiler(); Profilers.SetForCurrentThread(profiler); helper.UnaryHandler = new UnaryServerMethod(async (request, context) => { return request; }); var callDetails = helper.CreateUnaryCall(); for(int i = 0; i < 3000; i++) { Calls.BlockingUnaryCall(callDetails, "ABC"); } profiler.Reset(); for(int i = 0; i < 3000; i++) { Calls.BlockingUnaryCall(callDetails, "ABC"); } profiler.Dump("latency_trace_csharp.txt"); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/Properties/000077500000000000000000000000001310511640000215255ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Core.Tests/Properties/AssemblyInfo.cs000066400000000000000000000037041310511640000244530ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Grpc.Core.Tests")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] grpc-1.3.2/src/csharp/Grpc.Core.Tests/ResponseHeadersTest.cs000066400000000000000000000170201310511640000236520ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { /// /// Tests for response headers support. /// public class ResponseHeadersTest { MockServiceHelper helper; Server server; Channel channel; Metadata headers; [SetUp] public void Init() { helper = new MockServiceHelper(); server = helper.GetServer(); server.Start(); channel = helper.GetChannel(); headers = new Metadata { { "ascii-header", "abcdefg" } }; } [TearDown] public void Cleanup() { channel.ShutdownAsync().Wait(); server.ShutdownAsync().Wait(); } [Test] public async Task ResponseHeadersAsync_UnaryCall() { helper.UnaryHandler = new UnaryServerMethod(async (request, context) => { await context.WriteResponseHeadersAsync(headers); return "PASS"; }); var call = Calls.AsyncUnaryCall(helper.CreateUnaryCall(), ""); var responseHeaders = await call.ResponseHeadersAsync; Assert.AreEqual(headers.Count, responseHeaders.Count); Assert.AreEqual("ascii-header", responseHeaders[0].Key); Assert.AreEqual("abcdefg", responseHeaders[0].Value); Assert.AreEqual("PASS", await call.ResponseAsync); } [Test] public async Task ResponseHeadersAsync_ClientStreamingCall() { helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => { await context.WriteResponseHeadersAsync(headers); return "PASS"; }); var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall()); await call.RequestStream.CompleteAsync(); var responseHeaders = await call.ResponseHeadersAsync; Assert.AreEqual("ascii-header", responseHeaders[0].Key); Assert.AreEqual("PASS", await call.ResponseAsync); } [Test] public async Task ResponseHeadersAsync_ServerStreamingCall() { helper.ServerStreamingHandler = new ServerStreamingServerMethod(async (request, responseStream, context) => { await context.WriteResponseHeadersAsync(headers); await responseStream.WriteAsync("PASS"); }); var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), ""); var responseHeaders = await call.ResponseHeadersAsync; Assert.AreEqual("ascii-header", responseHeaders[0].Key); CollectionAssert.AreEqual(new[] { "PASS" }, await call.ResponseStream.ToListAsync()); } [Test] public async Task ResponseHeadersAsync_DuplexStreamingCall() { helper.DuplexStreamingHandler = new DuplexStreamingServerMethod(async (requestStream, responseStream, context) => { await context.WriteResponseHeadersAsync(headers); while (await requestStream.MoveNext()) { await responseStream.WriteAsync(requestStream.Current); } }); var call = Calls.AsyncDuplexStreamingCall(helper.CreateDuplexStreamingCall()); var responseHeaders = await call.ResponseHeadersAsync; var messages = new[] { "PASS" }; await call.RequestStream.WriteAllAsync(messages); Assert.AreEqual("ascii-header", responseHeaders[0].Key); CollectionAssert.AreEqual(messages, await call.ResponseStream.ToListAsync()); } [Test] public void WriteResponseHeaders_NullNotAllowed() { helper.UnaryHandler = new UnaryServerMethod(async (request, context) => { Assert.ThrowsAsync(typeof(ArgumentNullException), async () => await context.WriteResponseHeadersAsync(null)); return "PASS"; }); Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "")); } [Test] public void WriteResponseHeaders_AllowedOnlyOnce() { helper.UnaryHandler = new UnaryServerMethod(async (request, context) => { await context.WriteResponseHeadersAsync(headers); try { await context.WriteResponseHeadersAsync(headers); Assert.Fail(); } catch (InvalidOperationException expected) { } return "PASS"; }); Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "")); } [Test] public async Task WriteResponseHeaders_NotAllowedAfterWrite() { helper.ServerStreamingHandler = new ServerStreamingServerMethod(async (request, responseStream, context) => { await responseStream.WriteAsync("A"); try { await context.WriteResponseHeadersAsync(headers); Assert.Fail(); } catch (InvalidOperationException expected) { } await responseStream.WriteAsync("B"); }); var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), ""); var responses = await call.ResponseStream.ToListAsync(); CollectionAssert.AreEqual(new[] { "A", "B" }, responses); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/SanityTest.cs000066400000000000000000000120001310511640000220200ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.IO; using System.Reflection; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using Newtonsoft.Json; using NUnit.Framework; namespace Grpc.Core.Tests { public class SanityTest { // TODO: make sanity test work for CoreCLR as well #if !NETCOREAPP1_0 /// /// Because we depend on a native library, sometimes when things go wrong, the /// entire NUnit test process crashes. To be able to track down problems better, /// the NUnit tests are run by run_tests.py script in a separate process per test class. /// The list of tests to run is stored in src/csharp/tests.json. /// This test checks that the tests.json file is up to date by discovering all the /// existing NUnit tests in all test assemblies and comparing to contents of tests.json. /// [Test] public void TestsJsonUpToDate() { var discoveredTests = DiscoverAllTestClasses(); var testsFromFile = JsonConvert.DeserializeObject>>(ReadTestsJson()); Assert.AreEqual(discoveredTests, testsFromFile); } /// /// Gets list of all test classes obtained by inspecting all the test assemblies. /// private Dictionary> DiscoverAllTestClasses() { var assemblies = GetTestAssemblies(); var testsByAssembly = new Dictionary>(); foreach (var assembly in assemblies) { var testClasses = new List(); foreach (var t in assembly.GetTypes()) { foreach (var m in t.GetMethods()) { var attributes = m.GetCustomAttributes(typeof(NUnit.Framework.TestAttribute), true); if (attributes.Length > 0) { testClasses.Add(t.FullName); break; } } } testClasses.Sort(); testsByAssembly.Add(assembly.GetName().Name, testClasses); } return testsByAssembly; } /// /// Reads contents of tests.json file. /// private string ReadTestsJson() { var assemblyDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); var testsJsonFile = Path.Combine(assemblyDir, "..", "..", "..", "..", "tests.json"); return File.ReadAllText(testsJsonFile); } private List GetTestAssemblies() { var result = new List(); var executingAssembly = Assembly.GetExecutingAssembly(); result.Add(executingAssembly); var otherAssemblies = new[] { "Grpc.Examples.Tests", "Grpc.HealthCheck.Tests", "Grpc.IntegrationTesting", "Grpc.Reflection.Tests", }; foreach (var assemblyName in otherAssemblies) { var location = executingAssembly.Location.Replace("Grpc.Core.Tests", assemblyName); result.Add(Assembly.LoadFrom(location)); } return result; } #endif } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/ServerTest.cs000066400000000000000000000076421310511640000220370ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Linq; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { public class ServerTest { [Test] public void StartAndShutdownServer() { Server server = new Server { Ports = { new ServerPort("localhost", ServerPort.PickUnused, ServerCredentials.Insecure) } }; server.Start(); server.ShutdownAsync().Wait(); } [Test] public void StartAndKillServer() { Server server = new Server { Ports = { new ServerPort("localhost", ServerPort.PickUnused, ServerCredentials.Insecure) } }; server.Start(); server.KillAsync().Wait(); } [Test] public void PickUnusedPort() { Server server = new Server { Ports = { new ServerPort("localhost", ServerPort.PickUnused, ServerCredentials.Insecure) } }; var boundPort = server.Ports.Single(); Assert.AreEqual(0, boundPort.Port); Assert.Greater(boundPort.BoundPort, 0); server.Start(); server.ShutdownAsync().Wait(); } [Test] public void CannotModifyAfterStarted() { Server server = new Server { Ports = { new ServerPort("localhost", ServerPort.PickUnused, ServerCredentials.Insecure) } }; server.Start(); Assert.Throws(typeof(InvalidOperationException), () => server.Ports.Add("localhost", 9999, ServerCredentials.Insecure)); Assert.Throws(typeof(InvalidOperationException), () => server.Services.Add(ServerServiceDefinition.CreateBuilder().Build())); server.ShutdownAsync().Wait(); } [Test] public void UnstartedServerCanBeShutdown() { var server = new Server(); server.ShutdownAsync().Wait(); Assert.Throws(typeof(InvalidOperationException), () => server.Start()); } [Test] public void UnstartedServerDoesNotPreventShutdown() { // just create a server, don't start it, and make sure it doesn't prevent shutdown. var server = new Server(); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/ShutdownHookClientTest.cs000066400000000000000000000042231310511640000243540ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { public class ShutdownHookClientTest { const string Host = "127.0.0.1"; [Test] public void ProcessExitHookCanCleanupAbandonedChannels() { var channel = new Channel(Host, 1000, ChannelCredentials.Insecure); var channel2 = new Channel(Host, 1001, ChannelCredentials.Insecure); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/ShutdownHookPendingCallTest.cs000066400000000000000000000052361310511640000253230ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { public class ShutdownHookPendingCallTest { const string Host = "127.0.0.1"; [Test] public void ProcessExitHookCanCleanupAbandonedCall() { var helper = new MockServiceHelper(Host); var server = helper.GetServer(); server.Start(); var channel = helper.GetChannel(); var readyToShutdown = new TaskCompletionSource(); helper.DuplexStreamingHandler = new DuplexStreamingServerMethod(async (requestStream, responseStream, context) => { readyToShutdown.SetResult(null); await requestStream.ToListAsync(); }); var call = Calls.AsyncDuplexStreamingCall(helper.CreateDuplexStreamingCall()); readyToShutdown.Task.Wait(); // make sure handler is running } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/ShutdownHookServerTest.cs000066400000000000000000000041601310511640000244040ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { public class ShutdownHookServerTest { const string Host = "127.0.0.1"; [Test] public void ProcessExitHookCanCleanupAbandonedServers() { var helper = new MockServiceHelper(Host); var server = helper.GetServer(); server.Start(); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/ShutdownTest.cs000066400000000000000000000057531310511640000224050ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { public class ShutdownTest { const string Host = "127.0.0.1"; MockServiceHelper helper; Server server; Channel channel; [SetUp] public void Init() { helper = new MockServiceHelper(Host); server = helper.GetServer(); server.Start(); channel = helper.GetChannel(); } [Test] public async Task AbandonedCall_ServerKillAsync() { var readyToShutdown = new TaskCompletionSource(); helper.DuplexStreamingHandler = new DuplexStreamingServerMethod(async (requestStream, responseStream, context) => { readyToShutdown.SetResult(null); await requestStream.ToListAsync(); }); var call = Calls.AsyncDuplexStreamingCall(helper.CreateDuplexStreamingCall()); await readyToShutdown.Task; // make sure handler is running await channel.ShutdownAsync(); // channel.ShutdownAsync() works even if there's a pending call. await server.KillAsync(); // server.ShutdownAsync() would hang waiting for the call to finish. } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/TimeoutsTest.cs000066400000000000000000000143121310511640000223720ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { /// /// Tests for Deadline support. /// public class TimeoutsTest { MockServiceHelper helper; Server server; Channel channel; [SetUp] public void Init() { helper = new MockServiceHelper(); server = helper.GetServer(); server.Start(); channel = helper.GetChannel(); } [TearDown] public void Cleanup() { channel.ShutdownAsync().Wait(); server.ShutdownAsync().Wait(); } [Test] public void InfiniteDeadline() { helper.UnaryHandler = new UnaryServerMethod(async (request, context) => { Assert.AreEqual(DateTime.MaxValue, context.Deadline); return "PASS"; }); // no deadline specified, check server sees infinite deadline Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc")); // DateTime.MaxValue deadline specified, check server sees infinite deadline Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(new CallOptions(deadline: DateTime.MaxValue)), "abc")); } [Test] public void DeadlineTransferredToServer() { var clientDeadline = DateTime.UtcNow + TimeSpan.FromDays(7); helper.UnaryHandler = new UnaryServerMethod(async (request, context) => { // A fairly relaxed check that the deadline set by client and deadline seen by server // are in agreement. C core takes care of the work with transferring deadline over the wire, // so we don't need an exact check here. Assert.IsTrue(Math.Abs((clientDeadline - context.Deadline).TotalMilliseconds) < 5000); return "PASS"; }); Calls.BlockingUnaryCall(helper.CreateUnaryCall(new CallOptions(deadline: clientDeadline)), "abc"); } [Test] public void DeadlineInThePast() { helper.UnaryHandler = new UnaryServerMethod(async (request, context) => { await Task.Delay(60000); return "FAIL"; }); var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(new CallOptions(deadline: DateTime.MinValue)), "abc")); // We can't guarantee the status code always DeadlineExceeded. See issue #2685. Assert.Contains(ex.Status.StatusCode, new[] { StatusCode.DeadlineExceeded, StatusCode.Internal }); } [Test] public void DeadlineExceededStatusOnTimeout() { helper.UnaryHandler = new UnaryServerMethod(async (request, context) => { await Task.Delay(60000); return "FAIL"; }); var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(new CallOptions(deadline: DateTime.UtcNow.Add(TimeSpan.FromSeconds(5)))), "abc")); // We can't guarantee the status code always DeadlineExceeded. See issue #2685. Assert.Contains(ex.Status.StatusCode, new[] { StatusCode.DeadlineExceeded, StatusCode.Internal }); } [Test] public async Task ServerReceivesCancellationOnTimeout() { var serverReceivedCancellationTcs = new TaskCompletionSource(); helper.UnaryHandler = new UnaryServerMethod(async (request, context) => { // wait until cancellation token is fired. var tcs = new TaskCompletionSource(); context.CancellationToken.Register(() => { tcs.SetResult(null); }); await tcs.Task; serverReceivedCancellationTcs.SetResult(true); return ""; }); var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(new CallOptions(deadline: DateTime.UtcNow.Add(TimeSpan.FromSeconds(5)))), "abc")); // We can't guarantee the status code always DeadlineExceeded. See issue #2685. Assert.Contains(ex.Status.StatusCode, new[] { StatusCode.DeadlineExceeded, StatusCode.Internal }); Assert.IsTrue(await serverReceivedCancellationTcs.Task); } } } grpc-1.3.2/src/csharp/Grpc.Core.Tests/UserAgentStringTest.cs000066400000000000000000000075461310511640000236600ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Profiling; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.Core.Tests { public class UserAgentStringTest { const string Host = "127.0.0.1"; MockServiceHelper helper; Server server; Channel channel; [TearDown] public void Cleanup() { channel.ShutdownAsync().Wait(); server.ShutdownAsync().Wait(); } [Test] public void DefaultUserAgentString() { helper = new MockServiceHelper(Host); server = helper.GetServer(); server.Start(); channel = helper.GetChannel(); helper.UnaryHandler = new UnaryServerMethod((request, context) => { var userAgentString = context.RequestHeaders.First(m => (m.Key == "user-agent")).Value; var parts = userAgentString.Split(new [] {' '}, 2); Assert.AreEqual(string.Format("grpc-csharp/{0}", VersionInfo.CurrentVersion), parts[0]); Assert.IsTrue(parts[1].StartsWith("grpc-c/")); return Task.FromResult("PASS"); }); Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "")); } [Test] public void ApplicationUserAgentString() { helper = new MockServiceHelper(Host, channelOptions: new[] { new ChannelOption(ChannelOptions.PrimaryUserAgentString, "XYZ") }); server = helper.GetServer(); server.Start(); channel = helper.GetChannel(); channel = helper.GetChannel(); helper.UnaryHandler = new UnaryServerMethod((request, context) => { var userAgentString = context.RequestHeaders.First(m => (m.Key == "user-agent")).Value; var parts = userAgentString.Split(new[] { ' ' }, 3); Assert.AreEqual("XYZ", parts[0]); return Task.FromResult("PASS"); }); Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "")); } } } grpc-1.3.2/src/csharp/Grpc.Core/000077500000000000000000000000001310511640000162705ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Core/.gitignore000066400000000000000000000000101310511640000202470ustar00rootroot00000000000000bin obj grpc-1.3.2/src/csharp/Grpc.Core/AsyncAuthInterceptor.cs000066400000000000000000000061751310511640000227460ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Threading.Tasks; using Grpc.Core.Internal; using Grpc.Core.Utils; namespace Grpc.Core { /// /// Asynchronous authentication interceptor for . /// /// The interceptor context. /// Metadata to populate with entries that will be added to outgoing call's headers. /// public delegate Task AsyncAuthInterceptor(AuthInterceptorContext context, Metadata metadata); /// /// Context for an RPC being intercepted by . /// public class AuthInterceptorContext { readonly string serviceUrl; readonly string methodName; /// /// Initializes a new instance of AuthInterceptorContext. /// public AuthInterceptorContext(string serviceUrl, string methodName) { this.serviceUrl = GrpcPreconditions.CheckNotNull(serviceUrl); this.methodName = GrpcPreconditions.CheckNotNull(methodName); } /// /// The fully qualified service URL for the RPC being called. /// public string ServiceUrl { get { return serviceUrl; } } /// /// The method name of the RPC being called. /// public string MethodName { get { return methodName; } } } } grpc-1.3.2/src/csharp/Grpc.Core/AsyncClientStreamingCall.cs000066400000000000000000000121541310511640000235040ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.CompilerServices; using System.Threading.Tasks; namespace Grpc.Core { /// /// Return type for client streaming calls. /// /// Request message type for this call. /// Response message type for this call. public sealed class AsyncClientStreamingCall : IDisposable { readonly IClientStreamWriter requestStream; readonly Task responseAsync; readonly Task responseHeadersAsync; readonly Func getStatusFunc; readonly Func getTrailersFunc; readonly Action disposeAction; internal AsyncClientStreamingCall(IClientStreamWriter requestStream, Task responseAsync, Task responseHeadersAsync, Func getStatusFunc, Func getTrailersFunc, Action disposeAction) { this.requestStream = requestStream; this.responseAsync = responseAsync; this.responseHeadersAsync = responseHeadersAsync; this.getStatusFunc = getStatusFunc; this.getTrailersFunc = getTrailersFunc; this.disposeAction = disposeAction; } /// /// Asynchronous call result. /// public Task ResponseAsync { get { return this.responseAsync; } } /// /// Asynchronous access to response headers. /// public Task ResponseHeadersAsync { get { return this.responseHeadersAsync; } } /// /// Async stream to send streaming requests. /// public IClientStreamWriter RequestStream { get { return requestStream; } } /// /// Allows awaiting this object directly. /// /// public TaskAwaiter GetAwaiter() { return responseAsync.GetAwaiter(); } /// /// Gets the call status if the call has already finished. /// Throws InvalidOperationException otherwise. /// public Status GetStatus() { return getStatusFunc(); } /// /// Gets the call trailing metadata if the call has already finished. /// Throws InvalidOperationException otherwise. /// public Metadata GetTrailers() { return getTrailersFunc(); } /// /// Provides means to cleanup after the call. /// If the call has already finished normally (request stream has been completed and call result has been received), doesn't do anything. /// Otherwise, requests cancellation of the call which should terminate all pending async operations associated with the call. /// As a result, all resources being used by the call should be released eventually. /// /// /// Normally, there is no need for you to dispose the call unless you want to utilize the /// "Cancel" semantics of invoking Dispose. /// public void Dispose() { disposeAction.Invoke(); } } } grpc-1.3.2/src/csharp/Grpc.Core/AsyncDuplexStreamingCall.cs000066400000000000000000000116271310511640000235330ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Threading.Tasks; namespace Grpc.Core { /// /// Return type for bidirectional streaming calls. /// /// Request message type for this call. /// Response message type for this call. public sealed class AsyncDuplexStreamingCall : IDisposable { readonly IClientStreamWriter requestStream; readonly IAsyncStreamReader responseStream; readonly Task responseHeadersAsync; readonly Func getStatusFunc; readonly Func getTrailersFunc; readonly Action disposeAction; internal AsyncDuplexStreamingCall(IClientStreamWriter requestStream, IAsyncStreamReader responseStream, Task responseHeadersAsync, Func getStatusFunc, Func getTrailersFunc, Action disposeAction) { this.requestStream = requestStream; this.responseStream = responseStream; this.responseHeadersAsync = responseHeadersAsync; this.getStatusFunc = getStatusFunc; this.getTrailersFunc = getTrailersFunc; this.disposeAction = disposeAction; } /// /// Async stream to read streaming responses. /// public IAsyncStreamReader ResponseStream { get { return responseStream; } } /// /// Async stream to send streaming requests. /// public IClientStreamWriter RequestStream { get { return requestStream; } } /// /// Asynchronous access to response headers. /// public Task ResponseHeadersAsync { get { return this.responseHeadersAsync; } } /// /// Gets the call status if the call has already finished. /// Throws InvalidOperationException otherwise. /// public Status GetStatus() { return getStatusFunc(); } /// /// Gets the call trailing metadata if the call has already finished. /// Throws InvalidOperationException otherwise. /// public Metadata GetTrailers() { return getTrailersFunc(); } /// /// Provides means to cleanup after the call. /// If the call has already finished normally (request stream has been completed and response stream has been fully read), doesn't do anything. /// Otherwise, requests cancellation of the call which should terminate all pending async operations associated with the call. /// As a result, all resources being used by the call should be released eventually. /// /// /// Normally, there is no need for you to dispose the call unless you want to utilize the /// "Cancel" semantics of invoking Dispose. /// public void Dispose() { disposeAction.Invoke(); } } } grpc-1.3.2/src/csharp/Grpc.Core/AsyncServerStreamingCall.cs000066400000000000000000000105561310511640000235400ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Threading.Tasks; namespace Grpc.Core { /// /// Return type for server streaming calls. /// /// Response message type for this call. public sealed class AsyncServerStreamingCall : IDisposable { readonly IAsyncStreamReader responseStream; readonly Task responseHeadersAsync; readonly Func getStatusFunc; readonly Func getTrailersFunc; readonly Action disposeAction; internal AsyncServerStreamingCall(IAsyncStreamReader responseStream, Task responseHeadersAsync, Func getStatusFunc, Func getTrailersFunc, Action disposeAction) { this.responseStream = responseStream; this.responseHeadersAsync = responseHeadersAsync; this.getStatusFunc = getStatusFunc; this.getTrailersFunc = getTrailersFunc; this.disposeAction = disposeAction; } /// /// Async stream to read streaming responses. /// public IAsyncStreamReader ResponseStream { get { return responseStream; } } /// /// Asynchronous access to response headers. /// public Task ResponseHeadersAsync { get { return this.responseHeadersAsync; } } /// /// Gets the call status if the call has already finished. /// Throws InvalidOperationException otherwise. /// public Status GetStatus() { return getStatusFunc(); } /// /// Gets the call trailing metadata if the call has already finished. /// Throws InvalidOperationException otherwise. /// public Metadata GetTrailers() { return getTrailersFunc(); } /// /// Provides means to cleanup after the call. /// If the call has already finished normally (response stream has been fully read), doesn't do anything. /// Otherwise, requests cancellation of the call which should terminate all pending async operations associated with the call. /// As a result, all resources being used by the call should be released eventually. /// /// /// Normally, there is no need for you to dispose the call unless you want to utilize the /// "Cancel" semantics of invoking Dispose. /// public void Dispose() { disposeAction.Invoke(); } } } grpc-1.3.2/src/csharp/Grpc.Core/AsyncUnaryCall.cs000066400000000000000000000111131310511640000215040ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.CompilerServices; using System.Threading.Tasks; namespace Grpc.Core { /// /// Return type for single request - single response call. /// /// Response message type for this call. public sealed class AsyncUnaryCall : IDisposable { readonly Task responseAsync; readonly Task responseHeadersAsync; readonly Func getStatusFunc; readonly Func getTrailersFunc; readonly Action disposeAction; internal AsyncUnaryCall(Task responseAsync, Task responseHeadersAsync, Func getStatusFunc, Func getTrailersFunc, Action disposeAction) { this.responseAsync = responseAsync; this.responseHeadersAsync = responseHeadersAsync; this.getStatusFunc = getStatusFunc; this.getTrailersFunc = getTrailersFunc; this.disposeAction = disposeAction; } /// /// Asynchronous call result. /// public Task ResponseAsync { get { return this.responseAsync; } } /// /// Asynchronous access to response headers. /// public Task ResponseHeadersAsync { get { return this.responseHeadersAsync; } } /// /// Allows awaiting this object directly. /// public TaskAwaiter GetAwaiter() { return responseAsync.GetAwaiter(); } /// /// Gets the call status if the call has already finished. /// Throws InvalidOperationException otherwise. /// public Status GetStatus() { return getStatusFunc(); } /// /// Gets the call trailing metadata if the call has already finished. /// Throws InvalidOperationException otherwise. /// public Metadata GetTrailers() { return getTrailersFunc(); } /// /// Provides means to cleanup after the call. /// If the call has already finished normally (request stream has been completed and call result has been received), doesn't do anything. /// Otherwise, requests cancellation of the call which should terminate all pending async operations associated with the call. /// As a result, all resources being used by the call should be released eventually. /// /// /// Normally, there is no need for you to dispose the call unless you want to utilize the /// "Cancel" semantics of invoking Dispose. /// public void Dispose() { disposeAction.Invoke(); } } } grpc-1.3.2/src/csharp/Grpc.Core/AuthContext.cs000066400000000000000000000113241310511640000210660ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Linq; using Grpc.Core.Internal; using Grpc.Core.Utils; namespace Grpc.Core { /// /// Authentication context for a call. /// AuthContext is the only reliable source of truth when it comes to authenticating calls. /// Using any other call/context properties for authentication purposes is wrong and inherently unsafe. /// Note: experimental API that can change or be removed without any prior notice. /// public class AuthContext { string peerIdentityPropertyName; Dictionary> properties; /// /// Initializes a new instance of the class. /// /// Peer identity property name. /// Multimap of auth properties by name. internal AuthContext(string peerIdentityPropertyName, Dictionary> properties) { this.peerIdentityPropertyName = peerIdentityPropertyName; this.properties = GrpcPreconditions.CheckNotNull(properties); } /// /// Returns true if the peer is authenticated. /// public bool IsPeerAuthenticated { get { return peerIdentityPropertyName != null; } } /// /// Gets the name of the property that indicates the peer identity. Returns null /// if the peer is not authenticated. /// public string PeerIdentityPropertyName { get { return peerIdentityPropertyName; } } /// /// Gets properties that represent the peer identity (there can be more than one). Returns an empty collection /// if the peer is not authenticated. /// public IEnumerable PeerIdentity { get { if (peerIdentityPropertyName == null) { return Enumerable.Empty(); } return properties[peerIdentityPropertyName]; } } /// /// Gets the auth properties of this context. /// public IEnumerable Properties { get { return properties.Values.SelectMany(v => v); } } /// /// Returns the auth properties with given name (there can be more than one). /// If no properties of given name exist, an empty collection will be returned. /// public IEnumerable FindPropertiesByName(string propertyName) { List result; if (!properties.TryGetValue(propertyName, out result)) { return Enumerable.Empty(); } return result; } } } grpc-1.3.2/src/csharp/Grpc.Core/AuthProperty.cs000066400000000000000000000103261310511640000212670ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Linq; using Grpc.Core.Internal; using Grpc.Core.Utils; namespace Grpc.Core { /// /// A property of an . /// Note: experimental API that can change or be removed without any prior notice. /// public class AuthProperty { string name; byte[] valueBytes; Lazy value; private AuthProperty(string name, byte[] valueBytes) { this.name = GrpcPreconditions.CheckNotNull(name); this.valueBytes = GrpcPreconditions.CheckNotNull(valueBytes); this.value = new Lazy(() => MarshalUtils.GetStringUTF8(this.valueBytes)); } /// /// Gets the name of the property. /// public string Name { get { return name; } } /// /// Gets the string value of the property. /// public string Value { get { return value.Value; } } /// /// Gets the binary value of the property. /// public byte[] ValueBytes { get { var valueCopy = new byte[valueBytes.Length]; Buffer.BlockCopy(valueBytes, 0, valueCopy, 0, valueBytes.Length); return valueCopy; } } /// /// Creates an instance of AuthProperty. /// /// the name /// the binary value of the property public static AuthProperty Create(string name, byte[] valueBytes) { GrpcPreconditions.CheckNotNull(valueBytes); var valueCopy = new byte[valueBytes.Length]; Buffer.BlockCopy(valueBytes, 0, valueCopy, 0, valueBytes.Length); return new AuthProperty(name, valueCopy); } /// /// Gets the binary value of the property (without making a defensive copy). /// internal byte[] ValueBytesUnsafe { get { return valueBytes; } } /// /// Creates and instance of AuthProperty without making a defensive copy of valueBytes. /// internal static AuthProperty CreateUnsafe(string name, byte[] valueBytes) { return new AuthProperty(name, valueBytes); } } } grpc-1.3.2/src/csharp/Grpc.Core/CallCredentials.cs000066400000000000000000000137161310511640000216600ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Threading.Tasks; using Grpc.Core.Internal; using Grpc.Core.Utils; namespace Grpc.Core { /// /// Client-side call credentials. Provide authorization with per-call granularity. /// public abstract class CallCredentials { /// /// Composes multiple multiple CallCredentials objects into /// a single CallCredentials object. /// /// credentials to compose /// The new CompositeCallCredentials public static CallCredentials Compose(params CallCredentials[] credentials) { return new CompositeCallCredentials(credentials); } /// /// Creates a new instance of CallCredentials class from an /// interceptor that can attach metadata to outgoing calls. /// /// authentication interceptor public static CallCredentials FromInterceptor(AsyncAuthInterceptor interceptor) { return new MetadataCredentials(interceptor); } /// /// Creates native object for the credentials. /// /// The native credentials. internal abstract CallCredentialsSafeHandle ToNativeCredentials(); } /// /// Client-side credentials that delegate metadata based auth to an interceptor. /// The interceptor is automatically invoked for each remote call that uses MetadataCredentials. /// internal sealed class MetadataCredentials : CallCredentials { readonly AsyncAuthInterceptor interceptor; /// /// Initializes a new instance of MetadataCredentials class. /// /// authentication interceptor public MetadataCredentials(AsyncAuthInterceptor interceptor) { this.interceptor = GrpcPreconditions.CheckNotNull(interceptor); } internal override CallCredentialsSafeHandle ToNativeCredentials() { NativeMetadataCredentialsPlugin plugin = new NativeMetadataCredentialsPlugin(interceptor); return plugin.Credentials; } } /// /// Credentials that allow composing multiple credentials objects into one object. /// internal sealed class CompositeCallCredentials : CallCredentials { readonly List credentials; /// /// Initializes a new instance of CompositeCallCredentials class. /// The resulting credentials object will be composite of all the credentials specified as parameters. /// /// credentials to compose public CompositeCallCredentials(params CallCredentials[] credentials) { GrpcPreconditions.CheckArgument(credentials.Length >= 2, "Composite credentials object can only be created from 2 or more credentials."); this.credentials = new List(credentials); } internal override CallCredentialsSafeHandle ToNativeCredentials() { return ToNativeRecursive(0); } // Recursive descent makes managing lifetime of intermediate CredentialSafeHandle instances easier. // In practice, we won't usually see composites from more than two credentials anyway. private CallCredentialsSafeHandle ToNativeRecursive(int startIndex) { if (startIndex == credentials.Count - 1) { return credentials[startIndex].ToNativeCredentials(); } using (var cred1 = credentials[startIndex].ToNativeCredentials()) using (var cred2 = ToNativeRecursive(startIndex + 1)) { var nativeComposite = CallCredentialsSafeHandle.CreateComposite(cred1, cred2); if (nativeComposite.IsInvalid) { throw new ArgumentException("Error creating native composite credentials. Likely, this is because you are trying to compose incompatible credentials."); } return nativeComposite; } } } } grpc-1.3.2/src/csharp/Grpc.Core/CallInvocationDetails.cs000066400000000000000000000147321310511640000230410ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using Grpc.Core.Internal; using Grpc.Core.Utils; namespace Grpc.Core { /// /// Details about a client-side call to be invoked. /// /// Request message type for the call. /// Response message type for the call. public struct CallInvocationDetails { readonly Channel channel; readonly string method; readonly string host; readonly Marshaller requestMarshaller; readonly Marshaller responseMarshaller; CallOptions options; /// /// Initializes a new instance of the struct. /// /// Channel to use for this call. /// Method to call. /// Call options. public CallInvocationDetails(Channel channel, Method method, CallOptions options) : this(channel, method, null, options) { } /// /// Initializes a new instance of the struct. /// /// Channel to use for this call. /// Method to call. /// Host that contains the method. if null, default host will be used. /// Call options. public CallInvocationDetails(Channel channel, Method method, string host, CallOptions options) : this(channel, method.FullName, host, method.RequestMarshaller, method.ResponseMarshaller, options) { } /// /// Initializes a new instance of the struct. /// /// Channel to use for this call. /// Qualified method name. /// Host that contains the method. /// Request marshaller. /// Response marshaller. /// Call options. public CallInvocationDetails(Channel channel, string method, string host, Marshaller requestMarshaller, Marshaller responseMarshaller, CallOptions options) { this.channel = GrpcPreconditions.CheckNotNull(channel, "channel"); this.method = GrpcPreconditions.CheckNotNull(method, "method"); this.host = host; this.requestMarshaller = GrpcPreconditions.CheckNotNull(requestMarshaller, "requestMarshaller"); this.responseMarshaller = GrpcPreconditions.CheckNotNull(responseMarshaller, "responseMarshaller"); this.options = options; } /// /// Get channel associated with this call. /// public Channel Channel { get { return this.channel; } } /// /// Gets name of method to be called. /// public string Method { get { return this.method; } } /// /// Get name of host. /// public string Host { get { return this.host; } } /// /// Gets marshaller used to serialize requests. /// public Marshaller RequestMarshaller { get { return this.requestMarshaller; } } /// /// Gets marshaller used to deserialized responses. /// public Marshaller ResponseMarshaller { get { return this.responseMarshaller; } } /// /// Gets the call options. /// public CallOptions Options { get { return options; } } /// /// Returns new instance of with /// Options set to the value provided. Values of all other fields are preserved. /// public CallInvocationDetails WithOptions(CallOptions options) { var newDetails = this; newDetails.options = options; return newDetails; } } } grpc-1.3.2/src/csharp/Grpc.Core/CallInvoker.cs000066400000000000000000000100361310511640000210300ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Threading.Tasks; using Grpc.Core.Internal; namespace Grpc.Core { /// /// Abstraction of client-side RPC invocation. /// /// public abstract class CallInvoker { /// /// Invokes a simple remote call in a blocking fashion. /// public abstract TResponse BlockingUnaryCall(Method method, string host, CallOptions options, TRequest request) where TRequest : class where TResponse : class; /// /// Invokes a simple remote call asynchronously. /// public abstract AsyncUnaryCall AsyncUnaryCall(Method method, string host, CallOptions options, TRequest request) where TRequest : class where TResponse : class; /// /// Invokes a server streaming call asynchronously. /// In server streaming scenario, client sends on request and server responds with a stream of responses. /// public abstract AsyncServerStreamingCall AsyncServerStreamingCall(Method method, string host, CallOptions options, TRequest request) where TRequest : class where TResponse : class; /// /// Invokes a client streaming call asynchronously. /// In client streaming scenario, client sends a stream of requests and server responds with a single response. /// public abstract AsyncClientStreamingCall AsyncClientStreamingCall(Method method, string host, CallOptions options) where TRequest : class where TResponse : class; /// /// Invokes a duplex streaming call asynchronously. /// In duplex streaming scenario, client sends a stream of requests and server responds with a stream of responses. /// The response stream is completely independent and both side can be sending messages at the same time. /// public abstract AsyncDuplexStreamingCall AsyncDuplexStreamingCall(Method method, string host, CallOptions options) where TRequest : class where TResponse : class; } } grpc-1.3.2/src/csharp/Grpc.Core/CallOptions.cs000066400000000000000000000256561310511640000210640ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Threading; using Grpc.Core.Internal; using Grpc.Core.Utils; namespace Grpc.Core { /// /// Options for calls made by client. /// public struct CallOptions { Metadata headers; DateTime? deadline; CancellationToken cancellationToken; WriteOptions writeOptions; ContextPropagationToken propagationToken; CallCredentials credentials; CallFlags flags; /// /// Creates a new instance of CallOptions struct. /// /// Headers to be sent with the call. /// Deadline for the call to finish. null means no deadline. /// Can be used to request cancellation of the call. /// Write options that will be used for this call. /// Context propagation token obtained from . /// Credentials to use for this call. public CallOptions(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken), WriteOptions writeOptions = null, ContextPropagationToken propagationToken = null, CallCredentials credentials = null) { this.headers = headers; this.deadline = deadline; this.cancellationToken = cancellationToken; this.writeOptions = writeOptions; this.propagationToken = propagationToken; this.credentials = credentials; this.flags = default(CallFlags); } /// /// Headers to send at the beginning of the call. /// public Metadata Headers { get { return headers; } } /// /// Call deadline. /// public DateTime? Deadline { get { return deadline; } } /// /// Token that can be used for cancelling the call on the client side. /// Cancelling the token will request cancellation /// of the remote call. Best effort will be made to deliver the cancellation /// notification to the server and interaction of the call with the server side /// will be terminated. Unless the call finishes before the cancellation could /// happen (there is an inherent race), /// the call will finish with StatusCode.Cancelled status. /// public CancellationToken CancellationToken { get { return cancellationToken; } } /// /// Write options that will be used for this call. /// public WriteOptions WriteOptions { get { return this.writeOptions; } } /// /// Token for propagating parent call context. /// public ContextPropagationToken PropagationToken { get { return this.propagationToken; } } /// /// Credentials to use for this call. /// public CallCredentials Credentials { get { return this.credentials; } } /// /// If true and and channel is in ChannelState.TransientFailure, the call will attempt waiting for the channel to recover /// instead of failing immediately (which is the default "FailFast" semantics). /// Note: experimental API that can change or be removed without any prior notice. /// public bool IsWaitForReady { get { return (this.flags & CallFlags.WaitForReady) == CallFlags.WaitForReady; } } /// /// Flags to use for this call. /// internal CallFlags Flags { get { return this.flags; } } /// /// Returns new instance of with /// Headers set to the value provided. Values of all other fields are preserved. /// /// The headers. public CallOptions WithHeaders(Metadata headers) { var newOptions = this; newOptions.headers = headers; return newOptions; } /// /// Returns new instance of with /// Deadline set to the value provided. Values of all other fields are preserved. /// /// The deadline. public CallOptions WithDeadline(DateTime deadline) { var newOptions = this; newOptions.deadline = deadline; return newOptions; } /// /// Returns new instance of with /// CancellationToken set to the value provided. Values of all other fields are preserved. /// /// The cancellation token. public CallOptions WithCancellationToken(CancellationToken cancellationToken) { var newOptions = this; newOptions.cancellationToken = cancellationToken; return newOptions; } /// /// Returns new instance of with /// WriteOptions set to the value provided. Values of all other fields are preserved. /// /// The write options. public CallOptions WithWriteOptions(WriteOptions writeOptions) { var newOptions = this; newOptions.writeOptions = writeOptions; return newOptions; } /// /// Returns new instance of with /// PropagationToken set to the value provided. Values of all other fields are preserved. /// /// The context propagation token. public CallOptions WithPropagationToken(ContextPropagationToken propagationToken) { var newOptions = this; newOptions.propagationToken = propagationToken; return newOptions; } /// /// Returns new instance of with /// Credentials set to the value provided. Values of all other fields are preserved. /// /// The call credentials. public CallOptions WithCredentials(CallCredentials credentials) { var newOptions = this; newOptions.credentials = credentials; return newOptions; } /// /// Returns new instance of with "WaitForReady" semantics enabled/disabled. /// . /// Note: experimental API that can change or be removed without any prior notice. /// public CallOptions WithWaitForReady(bool waitForReady = true) { if (waitForReady) { return WithFlags(this.flags | CallFlags.WaitForReady); } return WithFlags(this.flags & ~CallFlags.WaitForReady); } /// /// Returns new instance of with /// Flags set to the value provided. Values of all other fields are preserved. /// /// The call flags. internal CallOptions WithFlags(CallFlags flags) { var newOptions = this; newOptions.flags = flags; return newOptions; } /// /// Returns a new instance of with /// all previously unset values set to their defaults and deadline and cancellation /// token propagated when appropriate. /// internal CallOptions Normalize() { var newOptions = this; if (propagationToken != null) { if (propagationToken.Options.IsPropagateDeadline) { GrpcPreconditions.CheckArgument(!newOptions.deadline.HasValue, "Cannot propagate deadline from parent call. The deadline has already been set explicitly."); newOptions.deadline = propagationToken.ParentDeadline; } if (propagationToken.Options.IsPropagateCancellation) { GrpcPreconditions.CheckArgument(!newOptions.cancellationToken.CanBeCanceled, "Cannot propagate cancellation token from parent call. The cancellation token has already been set to a non-default value."); newOptions.cancellationToken = propagationToken.ParentCancellationToken; } } newOptions.headers = newOptions.headers ?? Metadata.Empty; newOptions.deadline = newOptions.deadline ?? DateTime.MaxValue; return newOptions; } } } grpc-1.3.2/src/csharp/Grpc.Core/Calls.cs000066400000000000000000000166511310511640000176660ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Threading.Tasks; using Grpc.Core.Internal; namespace Grpc.Core { /// /// Helper methods for generated clients to make RPC calls. /// Most users will use this class only indirectly and will be /// making calls using client object generated from protocol /// buffer definition files. /// public static class Calls { /// /// Invokes a simple remote call in a blocking fashion. /// /// The response. /// The call defintion. /// Request message. /// Type of request message. /// The of response message. public static TResponse BlockingUnaryCall(CallInvocationDetails call, TRequest req) where TRequest : class where TResponse : class { var asyncCall = new AsyncCall(call); return asyncCall.UnaryCall(req); } /// /// Invokes a simple remote call asynchronously. /// /// An awaitable call object providing access to the response. /// The call defintion. /// Request message. /// Type of request message. /// The of response message. public static AsyncUnaryCall AsyncUnaryCall(CallInvocationDetails call, TRequest req) where TRequest : class where TResponse : class { var asyncCall = new AsyncCall(call); var asyncResult = asyncCall.UnaryCallAsync(req); return new AsyncUnaryCall(asyncResult, asyncCall.ResponseHeadersAsync, asyncCall.GetStatus, asyncCall.GetTrailers, asyncCall.Cancel); } /// /// Invokes a server streaming call asynchronously. /// In server streaming scenario, client sends on request and server responds with a stream of responses. /// /// A call object providing access to the asynchronous response stream. /// The call defintion. /// Request message. /// Type of request message. /// The of response messages. public static AsyncServerStreamingCall AsyncServerStreamingCall(CallInvocationDetails call, TRequest req) where TRequest : class where TResponse : class { var asyncCall = new AsyncCall(call); asyncCall.StartServerStreamingCall(req); var responseStream = new ClientResponseStream(asyncCall); return new AsyncServerStreamingCall(responseStream, asyncCall.ResponseHeadersAsync, asyncCall.GetStatus, asyncCall.GetTrailers, asyncCall.Cancel); } /// /// Invokes a client streaming call asynchronously. /// In client streaming scenario, client sends a stream of requests and server responds with a single response. /// /// The call defintion. /// An awaitable call object providing access to the response. /// Type of request messages. /// The of response message. public static AsyncClientStreamingCall AsyncClientStreamingCall(CallInvocationDetails call) where TRequest : class where TResponse : class { var asyncCall = new AsyncCall(call); var resultTask = asyncCall.ClientStreamingCallAsync(); var requestStream = new ClientRequestStream(asyncCall); return new AsyncClientStreamingCall(requestStream, resultTask, asyncCall.ResponseHeadersAsync, asyncCall.GetStatus, asyncCall.GetTrailers, asyncCall.Cancel); } /// /// Invokes a duplex streaming call asynchronously. /// In duplex streaming scenario, client sends a stream of requests and server responds with a stream of responses. /// The response stream is completely independent and both side can be sending messages at the same time. /// /// A call object providing access to the asynchronous request and response streams. /// The call definition. /// Type of request messages. /// Type of reponse messages. public static AsyncDuplexStreamingCall AsyncDuplexStreamingCall(CallInvocationDetails call) where TRequest : class where TResponse : class { var asyncCall = new AsyncCall(call); asyncCall.StartDuplexStreamingCall(); var requestStream = new ClientRequestStream(asyncCall); var responseStream = new ClientResponseStream(asyncCall); return new AsyncDuplexStreamingCall(requestStream, responseStream, asyncCall.ResponseHeadersAsync, asyncCall.GetStatus, asyncCall.GetTrailers, asyncCall.Cancel); } } } grpc-1.3.2/src/csharp/Grpc.Core/Channel.cs000066400000000000000000000311571310511640000201760ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Grpc.Core.Internal; using Grpc.Core.Logging; using Grpc.Core.Utils; namespace Grpc.Core { /// /// Represents a gRPC channel. Channels are an abstraction of long-lived connections to remote servers. /// More client objects can reuse the same channel. Creating a channel is an expensive operation compared to invoking /// a remote call so in general you should reuse a single channel for as many calls as possible. /// public class Channel { static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); readonly object myLock = new object(); readonly AtomicCounter activeCallCounter = new AtomicCounter(); readonly CancellationTokenSource shutdownTokenSource = new CancellationTokenSource(); readonly string target; readonly GrpcEnvironment environment; readonly CompletionQueueSafeHandle completionQueue; readonly ChannelSafeHandle handle; readonly Dictionary options; bool shutdownRequested; /// /// Creates a channel that connects to a specific host. /// Port will default to 80 for an unsecure channel and to 443 for a secure channel. /// /// Target of the channel. /// Credentials to secure the channel. public Channel(string target, ChannelCredentials credentials) : this(target, credentials, null) { } /// /// Creates a channel that connects to a specific host. /// Port will default to 80 for an unsecure channel and to 443 for a secure channel. /// /// Target of the channel. /// Credentials to secure the channel. /// Channel options. public Channel(string target, ChannelCredentials credentials, IEnumerable options) { this.target = GrpcPreconditions.CheckNotNull(target, "target"); this.options = CreateOptionsDictionary(options); EnsureUserAgentChannelOption(this.options); this.environment = GrpcEnvironment.AddRef(); this.completionQueue = this.environment.PickCompletionQueue(); using (var nativeCredentials = credentials.ToNativeCredentials()) using (var nativeChannelArgs = ChannelOptions.CreateChannelArgs(this.options.Values)) { if (nativeCredentials != null) { this.handle = ChannelSafeHandle.CreateSecure(nativeCredentials, target, nativeChannelArgs); } else { this.handle = ChannelSafeHandle.CreateInsecure(target, nativeChannelArgs); } } GrpcEnvironment.RegisterChannel(this); } /// /// Creates a channel that connects to a specific host and port. /// /// The name or IP address of the host. /// The port. /// Credentials to secure the channel. public Channel(string host, int port, ChannelCredentials credentials) : this(host, port, credentials, null) { } /// /// Creates a channel that connects to a specific host and port. /// /// The name or IP address of the host. /// The port. /// Credentials to secure the channel. /// Channel options. public Channel(string host, int port, ChannelCredentials credentials, IEnumerable options) : this(string.Format("{0}:{1}", host, port), credentials, options) { } /// /// Gets current connectivity state of this channel. /// After channel is has been shutdown, ChannelState.Shutdown will be returned. /// public ChannelState State { get { return GetConnectivityState(false); } } /// /// Returned tasks completes once channel state has become different from /// given lastObservedState. /// If deadline is reached or and error occurs, returned task is cancelled. /// public Task WaitForStateChangedAsync(ChannelState lastObservedState, DateTime? deadline = null) { GrpcPreconditions.CheckArgument(lastObservedState != ChannelState.Shutdown, "Shutdown is a terminal state. No further state changes can occur."); var tcs = new TaskCompletionSource(); var deadlineTimespec = deadline.HasValue ? Timespec.FromDateTime(deadline.Value) : Timespec.InfFuture; var handler = new BatchCompletionDelegate((success, ctx) => { if (success) { tcs.SetResult(null); } else { tcs.SetCanceled(); } }); handle.WatchConnectivityState(lastObservedState, deadlineTimespec, completionQueue, handler); return tcs.Task; } /// Resolved address of the remote endpoint in URI format. public string ResolvedTarget { get { return handle.GetTarget(); } } /// The original target used to create the channel. public string Target { get { return this.target; } } /// /// Returns a token that gets cancelled once ShutdownAsync is invoked. /// public CancellationToken ShutdownToken { get { return this.shutdownTokenSource.Token; } } /// /// Allows explicitly requesting channel to connect without starting an RPC. /// Returned task completes once state Ready was seen. If the deadline is reached, /// or channel enters the Shutdown state, the task is cancelled. /// There is no need to call this explicitly unless your use case requires that. /// Starting an RPC on a new channel will request connection implicitly. /// /// The deadline. null indicates no deadline. public async Task ConnectAsync(DateTime? deadline = null) { var currentState = GetConnectivityState(true); while (currentState != ChannelState.Ready) { if (currentState == ChannelState.Shutdown) { throw new OperationCanceledException("Channel has reached Shutdown state."); } await WaitForStateChangedAsync(currentState, deadline).ConfigureAwait(false); currentState = GetConnectivityState(false); } } /// /// Shuts down the channel cleanly. It is strongly recommended to shutdown /// all previously created channels before exiting from the process. /// /// /// This method doesn't wait for all calls on this channel to finish (nor does /// it explicitly cancel all outstanding calls). It is user's responsibility to make sure /// all the calls on this channel have finished (successfully or with an error) /// before shutting down the channel to ensure channel shutdown won't impact /// the outcome of those remote calls. /// public async Task ShutdownAsync() { lock (myLock) { GrpcPreconditions.CheckState(!shutdownRequested); shutdownRequested = true; } GrpcEnvironment.UnregisterChannel(this); shutdownTokenSource.Cancel(); var activeCallCount = activeCallCounter.Count; if (activeCallCount > 0) { Logger.Warning("Channel shutdown was called but there are still {0} active calls for that channel.", activeCallCount); } handle.Dispose(); await GrpcEnvironment.ReleaseAsync().ConfigureAwait(false); } internal ChannelSafeHandle Handle { get { return this.handle; } } internal GrpcEnvironment Environment { get { return this.environment; } } internal CompletionQueueSafeHandle CompletionQueue { get { return this.completionQueue; } } internal void AddCallReference(object call) { activeCallCounter.Increment(); bool success = false; handle.DangerousAddRef(ref success); GrpcPreconditions.CheckState(success); } internal void RemoveCallReference(object call) { handle.DangerousRelease(); activeCallCounter.Decrement(); } private ChannelState GetConnectivityState(bool tryToConnect) { try { return handle.CheckConnectivityState(tryToConnect); } catch (ObjectDisposedException) { return ChannelState.Shutdown; } } private static void EnsureUserAgentChannelOption(Dictionary options) { var key = ChannelOptions.PrimaryUserAgentString; var userAgentString = ""; ChannelOption option; if (options.TryGetValue(key, out option)) { // user-provided userAgentString needs to be at the beginning userAgentString = option.StringValue + " "; }; // TODO(jtattermusch): it would be useful to also provide .NET/mono version. userAgentString += string.Format("grpc-csharp/{0}", VersionInfo.CurrentVersion); options[ChannelOptions.PrimaryUserAgentString] = new ChannelOption(key, userAgentString); } private static Dictionary CreateOptionsDictionary(IEnumerable options) { var dict = new Dictionary(); if (options == null) { return dict; } foreach (var option in options) { dict.Add(option.Name, option); } return dict; } } } grpc-1.3.2/src/csharp/Grpc.Core/ChannelCredentials.cs000066400000000000000000000176401310511640000223550ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Threading.Tasks; using Grpc.Core.Internal; using Grpc.Core.Utils; namespace Grpc.Core { /// /// Client-side channel credentials. Used for creation of a secure channel. /// public abstract class ChannelCredentials { static readonly ChannelCredentials InsecureInstance = new InsecureCredentialsImpl(); /// /// Returns instance of credentials that provides no security and /// will result in creating an unsecure channel with no encryption whatsoever. /// public static ChannelCredentials Insecure { get { return InsecureInstance; } } /// /// Creates a new instance of ChannelCredentials class by composing /// given channel credentials with call credentials. /// /// Channel credentials. /// Call credentials. /// The new composite ChannelCredentials public static ChannelCredentials Create(ChannelCredentials channelCredentials, CallCredentials callCredentials) { return new CompositeChannelCredentials(channelCredentials, callCredentials); } /// /// Creates native object for the credentials. May return null if insecure channel /// should be created. /// /// The native credentials. internal abstract ChannelCredentialsSafeHandle ToNativeCredentials(); /// /// Returns true if this credential type allows being composed by CompositeCredentials. /// internal virtual bool IsComposable { get { return false; } } private sealed class InsecureCredentialsImpl : ChannelCredentials { internal override ChannelCredentialsSafeHandle ToNativeCredentials() { return null; } } } /// /// Client-side SSL credentials. /// public sealed class SslCredentials : ChannelCredentials { readonly string rootCertificates; readonly KeyCertificatePair keyCertificatePair; /// /// Creates client-side SSL credentials loaded from /// disk file pointed to by the GRPC_DEFAULT_SSL_ROOTS_FILE_PATH environment variable. /// If that fails, gets the roots certificates from a well known place on disk. /// public SslCredentials() : this(null, null) { } /// /// Creates client-side SSL credentials from /// a string containing PEM encoded root certificates. /// public SslCredentials(string rootCertificates) : this(rootCertificates, null) { } /// /// Creates client-side SSL credentials. /// /// string containing PEM encoded server root certificates. /// a key certificate pair. public SslCredentials(string rootCertificates, KeyCertificatePair keyCertificatePair) { this.rootCertificates = rootCertificates; this.keyCertificatePair = keyCertificatePair; } /// /// PEM encoding of the server root certificates. /// public string RootCertificates { get { return this.rootCertificates; } } /// /// Client side key and certificate pair. /// If null, client will not use key and certificate pair. /// public KeyCertificatePair KeyCertificatePair { get { return this.keyCertificatePair; } } // Composing composite makes no sense. internal override bool IsComposable { get { return true; } } internal override ChannelCredentialsSafeHandle ToNativeCredentials() { return ChannelCredentialsSafeHandle.CreateSslCredentials(rootCertificates, keyCertificatePair); } } /// /// Credentials that allow composing one object and /// one or more objects into a single . /// internal sealed class CompositeChannelCredentials : ChannelCredentials { readonly ChannelCredentials channelCredentials; readonly CallCredentials callCredentials; /// /// Initializes a new instance of CompositeChannelCredentials class. /// The resulting credentials object will be composite of all the credentials specified as parameters. /// /// channelCredentials to compose /// channelCredentials to compose public CompositeChannelCredentials(ChannelCredentials channelCredentials, CallCredentials callCredentials) { this.channelCredentials = GrpcPreconditions.CheckNotNull(channelCredentials); this.callCredentials = GrpcPreconditions.CheckNotNull(callCredentials); GrpcPreconditions.CheckArgument(channelCredentials.IsComposable, "Supplied channel credentials do not allow composition."); } internal override ChannelCredentialsSafeHandle ToNativeCredentials() { using (var channelCreds = channelCredentials.ToNativeCredentials()) using (var callCreds = callCredentials.ToNativeCredentials()) { var nativeComposite = ChannelCredentialsSafeHandle.CreateComposite(channelCreds, callCreds); if (nativeComposite.IsInvalid) { throw new ArgumentException("Error creating native composite credentials. Likely, this is because you are trying to compose incompatible credentials."); } return nativeComposite; } } } } grpc-1.3.2/src/csharp/Grpc.Core/ChannelOptions.cs000066400000000000000000000177161310511640000215570ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Grpc.Core.Internal; using Grpc.Core.Utils; namespace Grpc.Core { /// /// Channel option specified when creating a channel. /// Corresponds to grpc_channel_args from grpc/grpc.h. /// public sealed class ChannelOption { /// /// Type of ChannelOption. /// public enum OptionType { /// /// Channel option with integer value. /// Integer, /// /// Channel option with string value. /// String } private readonly OptionType type; private readonly string name; private readonly int intValue; private readonly string stringValue; /// /// Creates a channel option with a string value. /// /// Name. /// String value. public ChannelOption(string name, string stringValue) { this.type = OptionType.String; this.name = GrpcPreconditions.CheckNotNull(name, "name"); this.stringValue = GrpcPreconditions.CheckNotNull(stringValue, "stringValue"); } /// /// Creates a channel option with an integer value. /// /// Name. /// Integer value. public ChannelOption(string name, int intValue) { this.type = OptionType.Integer; this.name = GrpcPreconditions.CheckNotNull(name, "name"); this.intValue = intValue; } /// /// Gets the type of the ChannelOption. /// public OptionType Type { get { return type; } } /// /// Gets the name of the ChannelOption. /// public string Name { get { return name; } } /// /// Gets the integer value the ChannelOption. /// public int IntValue { get { GrpcPreconditions.CheckState(type == OptionType.Integer); return intValue; } } /// /// Gets the string value the ChannelOption. /// public string StringValue { get { GrpcPreconditions.CheckState(type == OptionType.String); return stringValue; } } } /// /// Defines names of supported channel options. /// public static class ChannelOptions { /// Override SSL target check. Only to be used for testing. public const string SslTargetNameOverride = "grpc.ssl_target_name_override"; /// Enable census for tracing and stats collection public const string Census = "grpc.census"; /// Maximum number of concurrent incoming streams to allow on a http2 connection public const string MaxConcurrentStreams = "grpc.max_concurrent_streams"; /// Maximum message length that the channel can receive public const string MaxReceiveMessageLength = "grpc.max_receive_message_length"; /// Maximum message length that the channel can send public const string MaxSendMessageLength = "grpc.max_send_message_length"; /// Obsolete, for backward compatibility only. [Obsolete("Use MaxReceiveMessageLength instead.")] public const string MaxMessageLength = MaxReceiveMessageLength; /// Initial sequence number for http2 transports public const string Http2InitialSequenceNumber = "grpc.http2.initial_sequence_number"; /// Default authority for calls. public const string DefaultAuthority = "grpc.default_authority"; /// Primary user agent: goes at the start of the user-agent metadata public const string PrimaryUserAgentString = "grpc.primary_user_agent"; /// Secondary user agent: goes at the end of the user-agent metadata public const string SecondaryUserAgentString = "grpc.secondary_user_agent"; /// If non-zero, allow the use of SO_REUSEPORT for server if it's available (default 1) public const string SoReuseport = "grpc.so_reuseport"; /// /// Creates native object for a collection of channel options. /// /// The native channel arguments. internal static ChannelArgsSafeHandle CreateChannelArgs(ICollection options) { if (options == null || options.Count == 0) { return ChannelArgsSafeHandle.CreateNull(); } ChannelArgsSafeHandle nativeArgs = null; try { nativeArgs = ChannelArgsSafeHandle.Create(options.Count); int i = 0; foreach (var option in options) { if (option.Type == ChannelOption.OptionType.Integer) { nativeArgs.SetInteger(i, option.Name, option.IntValue); } else if (option.Type == ChannelOption.OptionType.String) { nativeArgs.SetString(i, option.Name, option.StringValue); } else { throw new InvalidOperationException("Unknown option type"); } i++; } return nativeArgs; } catch (Exception) { if (nativeArgs != null) { nativeArgs.Dispose(); } throw; } } } } grpc-1.3.2/src/csharp/Grpc.Core/ChannelState.cs000066400000000000000000000045051310511640000211740ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; namespace Grpc.Core { /// /// Connectivity state of a channel. /// Based on grpc_connectivity_state from grpc/grpc.h /// public enum ChannelState { /// /// Channel is idle /// Idle, /// /// Channel is connecting /// Connecting, /// /// Channel is ready for work /// Ready, /// /// Channel has seen a failure but expects to recover /// TransientFailure, /// /// Channel has seen a failure that it cannot recover from /// Shutdown } } grpc-1.3.2/src/csharp/Grpc.Core/ClientBase.cs000066400000000000000000000161311310511640000206320ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using Grpc.Core.Internal; using Grpc.Core.Utils; namespace Grpc.Core { /// /// Generic base class for client-side stubs. /// public abstract class ClientBase : ClientBase where T : ClientBase { /// /// Initializes a new instance of ClientBase class that /// throws NotImplementedException upon invocation of any RPC. /// This constructor is only provided to allow creation of test doubles /// for client classes (e.g. mocking requires a parameterless constructor). /// protected ClientBase() : base() { } /// /// Initializes a new instance of ClientBase class. /// /// The configuration. protected ClientBase(ClientBaseConfiguration configuration) : base(configuration) { } /// /// Initializes a new instance of ClientBase class. /// /// The channel to use for remote call invocation. public ClientBase(Channel channel) : base(channel) { } /// /// Initializes a new instance of ClientBase class. /// /// The CallInvoker for remote call invocation. public ClientBase(CallInvoker callInvoker) : base(callInvoker) { } /// /// Creates a new client that sets host field for calls explicitly. /// gRPC supports multiple "hosts" being served by a single server. /// By default (if a client was not created by calling this method), /// host null with the meaning "use default host" is used. /// public T WithHost(string host) { var newConfiguration = this.Configuration.WithHost(host); return NewInstance(newConfiguration); } /// /// Creates a new instance of client from given ClientBaseConfiguration. /// protected abstract T NewInstance(ClientBaseConfiguration configuration); } /// /// Base class for client-side stubs. /// public abstract class ClientBase { readonly ClientBaseConfiguration configuration; readonly CallInvoker callInvoker; /// /// Initializes a new instance of ClientBase class that /// throws NotImplementedException upon invocation of any RPC. /// This constructor is only provided to allow creation of test doubles /// for client classes (e.g. mocking requires a parameterless constructor). /// protected ClientBase() : this(new UnimplementedCallInvoker()) { } /// /// Initializes a new instance of ClientBase class. /// /// The configuration. protected ClientBase(ClientBaseConfiguration configuration) { this.configuration = GrpcPreconditions.CheckNotNull(configuration, "configuration"); this.callInvoker = configuration.CreateDecoratedCallInvoker(); } /// /// Initializes a new instance of ClientBase class. /// /// The channel to use for remote call invocation. public ClientBase(Channel channel) : this(new DefaultCallInvoker(channel)) { } /// /// Initializes a new instance of ClientBase class. /// /// The CallInvoker for remote call invocation. public ClientBase(CallInvoker callInvoker) : this(new ClientBaseConfiguration(callInvoker, null)) { } /// /// Gets the call invoker. /// protected CallInvoker CallInvoker { get { return this.callInvoker; } } /// /// Gets the configuration. /// internal ClientBaseConfiguration Configuration { get { return this.configuration; } } /// /// Represents configuration of ClientBase. The class itself is visible to /// subclasses, but contents are marked as internal to make the instances opaque. /// The verbose name of this class was chosen to make name clash in generated code /// less likely. /// protected internal class ClientBaseConfiguration { readonly CallInvoker undecoratedCallInvoker; readonly string host; internal ClientBaseConfiguration(CallInvoker undecoratedCallInvoker, string host) { this.undecoratedCallInvoker = GrpcPreconditions.CheckNotNull(undecoratedCallInvoker); this.host = host; } internal CallInvoker CreateDecoratedCallInvoker() { return new InterceptingCallInvoker(undecoratedCallInvoker, hostInterceptor: (h) => host); } internal ClientBaseConfiguration WithHost(string host) { GrpcPreconditions.CheckNotNull(host, "host"); return new ClientBaseConfiguration(this.undecoratedCallInvoker, host); } } } } grpc-1.3.2/src/csharp/Grpc.Core/Common.csproj.include000077500000000000000000000035161310511640000223740ustar00rootroot00000000000000 false false false false false false false false false true $(DefineConstants);SIGNED ../keys/Grpc.snk true true /usr/lib/mono/4.5-api /usr/local/lib/mono/4.5-api /Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5-api grpc-1.3.2/src/csharp/Grpc.Core/CompressionLevel.cs000066400000000000000000000041751310511640000221170ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; namespace Grpc.Core { /// /// Compression level based on grpc_compression_level from grpc/compression.h /// public enum CompressionLevel { /// /// No compression. /// None = 0, /// /// Low compression. /// Low, /// /// Medium compression. /// Medium, /// /// High compression. /// High, } } grpc-1.3.2/src/csharp/Grpc.Core/ContextPropagationToken.cs000066400000000000000000000141341310511640000234530ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Threading; using Grpc.Core.Internal; using Grpc.Core.Utils; namespace Grpc.Core { /// /// Token for propagating context of server side handlers to child calls. /// In situations when a backend is making calls to another backend, /// it makes sense to propagate properties like deadline and cancellation /// token of the server call to the child call. /// The gRPC native layer provides some other contexts (like tracing context) that /// are not accessible to explicitly C# layer, but this token still allows propagating them. /// public class ContextPropagationToken { /// /// Default propagation mask used by C core. /// private const ContextPropagationFlags DefaultCoreMask = (ContextPropagationFlags)0xffff; /// /// Default propagation mask used by C# - we want to propagate deadline /// and cancellation token by our own means. /// internal const ContextPropagationFlags DefaultMask = DefaultCoreMask & ~ContextPropagationFlags.Deadline & ~ContextPropagationFlags.Cancellation; readonly CallSafeHandle parentCall; readonly DateTime deadline; readonly CancellationToken cancellationToken; readonly ContextPropagationOptions options; internal ContextPropagationToken(CallSafeHandle parentCall, DateTime deadline, CancellationToken cancellationToken, ContextPropagationOptions options) { this.parentCall = GrpcPreconditions.CheckNotNull(parentCall); this.deadline = deadline; this.cancellationToken = cancellationToken; this.options = options ?? ContextPropagationOptions.Default; } /// /// Gets the native handle of the parent call. /// internal CallSafeHandle ParentCall { get { return this.parentCall; } } /// /// Gets the parent call's deadline. /// internal DateTime ParentDeadline { get { return this.deadline; } } /// /// Gets the parent call's cancellation token. /// internal CancellationToken ParentCancellationToken { get { return this.cancellationToken; } } /// /// Get the context propagation options. /// internal ContextPropagationOptions Options { get { return this.options; } } } /// /// Options for . /// public class ContextPropagationOptions { /// /// The context propagation options that will be used by default. /// public static readonly ContextPropagationOptions Default = new ContextPropagationOptions(); bool propagateDeadline; bool propagateCancellation; /// /// Creates new context propagation options. /// /// If set to true parent call's deadline will be propagated to the child call. /// If set to true parent call's cancellation token will be propagated to the child call. public ContextPropagationOptions(bool propagateDeadline = true, bool propagateCancellation = true) { this.propagateDeadline = propagateDeadline; this.propagateCancellation = propagateCancellation; } /// true if parent call's deadline should be propagated to the child call. public bool IsPropagateDeadline { get { return this.propagateDeadline; } } /// true if parent call's cancellation token should be propagated to the child call. public bool IsPropagateCancellation { get { return this.propagateCancellation; } } } /// /// Context propagation flags from grpc/grpc.h. /// [Flags] internal enum ContextPropagationFlags { Deadline = 1, CensusStatsContext = 2, CensusTracingContext = 4, Cancellation = 8 } } grpc-1.3.2/src/csharp/Grpc.Core/DefaultCallInvoker.cs000066400000000000000000000122431310511640000223370ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Threading.Tasks; using Grpc.Core.Internal; using Grpc.Core.Utils; namespace Grpc.Core { /// /// Invokes client RPCs using . /// public class DefaultCallInvoker : CallInvoker { readonly Channel channel; /// /// Initializes a new instance of the class. /// /// Channel to use. public DefaultCallInvoker(Channel channel) { this.channel = GrpcPreconditions.CheckNotNull(channel); } /// /// Invokes a simple remote call in a blocking fashion. /// public override TResponse BlockingUnaryCall(Method method, string host, CallOptions options, TRequest request) { var call = CreateCall(method, host, options); return Calls.BlockingUnaryCall(call, request); } /// /// Invokes a simple remote call asynchronously. /// public override AsyncUnaryCall AsyncUnaryCall(Method method, string host, CallOptions options, TRequest request) { var call = CreateCall(method, host, options); return Calls.AsyncUnaryCall(call, request); } /// /// Invokes a server streaming call asynchronously. /// In server streaming scenario, client sends on request and server responds with a stream of responses. /// public override AsyncServerStreamingCall AsyncServerStreamingCall(Method method, string host, CallOptions options, TRequest request) { var call = CreateCall(method, host, options); return Calls.AsyncServerStreamingCall(call, request); } /// /// Invokes a client streaming call asynchronously. /// In client streaming scenario, client sends a stream of requests and server responds with a single response. /// public override AsyncClientStreamingCall AsyncClientStreamingCall(Method method, string host, CallOptions options) { var call = CreateCall(method, host, options); return Calls.AsyncClientStreamingCall(call); } /// /// Invokes a duplex streaming call asynchronously. /// In duplex streaming scenario, client sends a stream of requests and server responds with a stream of responses. /// The response stream is completely independent and both side can be sending messages at the same time. /// public override AsyncDuplexStreamingCall AsyncDuplexStreamingCall(Method method, string host, CallOptions options) { var call = CreateCall(method, host, options); return Calls.AsyncDuplexStreamingCall(call); } /// Creates call invocation details for given method. protected virtual CallInvocationDetails CreateCall(Method method, string host, CallOptions options) where TRequest : class where TResponse : class { return new CallInvocationDetails(channel, method, host, options); } } } grpc-1.3.2/src/csharp/Grpc.Core/Grpc.Core.csproj000077500000000000000000000053221310511640000213010ustar00rootroot00000000000000 Copyright 2015, Google Inc. gRPC C# Core $(GrpcCsharpVersion) Google Inc. net45;netstandard1.5 Grpc.Core Grpc.Core gRPC RPC Protocol HTTP/2 https://github.com/grpc/grpc https://github.com/grpc/grpc/blob/master/LICENSE 1.6.0 runtimes/osx/native/libgrpc_csharp_ext.x64.dylib true runtimes/osx/native/libgrpc_csharp_ext.x86.dylib true runtimes/linux/native/libgrpc_csharp_ext.x64.so true runtimes/linux/native/libgrpc_csharp_ext.x86.so true runtimes/win/native/grpc_csharp_ext.x64.dll true runtimes/win/native/grpc_csharp_ext.x86.dll true build/net45/ true grpc-1.3.2/src/csharp/Grpc.Core/Grpc.Core.targets000066400000000000000000000030341310511640000214450ustar00rootroot00000000000000 PreserveNewest grpc_csharp_ext.x86.dll PreserveNewest grpc_csharp_ext.x64.dll PreserveNewest libgrpc_csharp_ext.x86.so PreserveNewest libgrpc_csharp_ext.x64.so PreserveNewest libgrpc_csharp_ext.x86.dylib PreserveNewest libgrpc_csharp_ext.x64.dylib grpc-1.3.2/src/csharp/Grpc.Core/GrpcEnvironment.cs000066400000000000000000000321711310511640000217430ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Threading.Tasks; using Grpc.Core.Internal; using Grpc.Core.Logging; using Grpc.Core.Utils; namespace Grpc.Core { /// /// Encapsulates initialization and shutdown of gRPC library. /// public class GrpcEnvironment { const int MinDefaultThreadPoolSize = 4; static object staticLock = new object(); static GrpcEnvironment instance; static int refCount; static int? customThreadPoolSize; static int? customCompletionQueueCount; static readonly HashSet registeredChannels = new HashSet(); static readonly HashSet registeredServers = new HashSet(); static ILogger logger = new NullLogger(); readonly GrpcThreadPool threadPool; readonly DebugStats debugStats = new DebugStats(); readonly AtomicCounter cqPickerCounter = new AtomicCounter(); bool isClosed; /// /// Returns a reference-counted instance of initialized gRPC environment. /// Subsequent invocations return the same instance unless reference count has dropped to zero previously. /// internal static GrpcEnvironment AddRef() { ShutdownHooks.Register(); lock (staticLock) { refCount++; if (instance == null) { instance = new GrpcEnvironment(); } return instance; } } /// /// Decrements the reference count for currently active environment and asynchronously shuts down the gRPC environment if reference count drops to zero. /// internal static async Task ReleaseAsync() { GrpcEnvironment instanceToShutdown = null; lock (staticLock) { GrpcPreconditions.CheckState(refCount > 0); refCount--; if (refCount == 0) { instanceToShutdown = instance; instance = null; } } if (instanceToShutdown != null) { await instanceToShutdown.ShutdownAsync().ConfigureAwait(false); } } internal static int GetRefCount() { lock (staticLock) { return refCount; } } internal static void RegisterChannel(Channel channel) { lock (staticLock) { GrpcPreconditions.CheckNotNull(channel); registeredChannels.Add(channel); } } internal static void UnregisterChannel(Channel channel) { lock (staticLock) { GrpcPreconditions.CheckNotNull(channel); GrpcPreconditions.CheckArgument(registeredChannels.Remove(channel), "Channel not found in the registered channels set."); } } internal static void RegisterServer(Server server) { lock (staticLock) { GrpcPreconditions.CheckNotNull(server); registeredServers.Add(server); } } internal static void UnregisterServer(Server server) { lock (staticLock) { GrpcPreconditions.CheckNotNull(server); GrpcPreconditions.CheckArgument(registeredServers.Remove(server), "Server not found in the registered servers set."); } } /// /// Requests shutdown of all channels created by the current process. /// public static Task ShutdownChannelsAsync() { HashSet snapshot = null; lock (staticLock) { snapshot = new HashSet(registeredChannels); } return Task.WhenAll(snapshot.Select((channel) => channel.ShutdownAsync())); } /// /// Requests immediate shutdown of all servers created by the current process. /// public static Task KillServersAsync() { HashSet snapshot = null; lock (staticLock) { snapshot = new HashSet(registeredServers); } return Task.WhenAll(snapshot.Select((server) => server.KillAsync())); } /// /// Gets application-wide logger used by gRPC. /// /// The logger. public static ILogger Logger { get { return logger; } } /// /// Sets the application-wide logger that should be used by gRPC. /// public static void SetLogger(ILogger customLogger) { GrpcPreconditions.CheckNotNull(customLogger, "customLogger"); logger = customLogger; } /// /// Sets the number of threads in the gRPC thread pool that polls for internal RPC events. /// Can be only invoke before the GrpcEnviroment is started and cannot be changed afterwards. /// Setting thread pool size is an advanced setting and you should only use it if you know what you are doing. /// Most users should rely on the default value provided by gRPC library. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// public static void SetThreadPoolSize(int threadCount) { lock (staticLock) { GrpcPreconditions.CheckState(instance == null, "Can only be set before GrpcEnvironment is initialized"); GrpcPreconditions.CheckArgument(threadCount > 0, "threadCount needs to be a positive number"); customThreadPoolSize = threadCount; } } /// /// Sets the number of completion queues in the gRPC thread pool that polls for internal RPC events. /// Can be only invoke before the GrpcEnviroment is started and cannot be changed afterwards. /// Setting the number of completions queues is an advanced setting and you should only use it if you know what you are doing. /// Most users should rely on the default value provided by gRPC library. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// public static void SetCompletionQueueCount(int completionQueueCount) { lock (staticLock) { GrpcPreconditions.CheckState(instance == null, "Can only be set before GrpcEnvironment is initialized"); GrpcPreconditions.CheckArgument(completionQueueCount > 0, "threadCount needs to be a positive number"); customCompletionQueueCount = completionQueueCount; } } /// /// Creates gRPC environment. /// private GrpcEnvironment() { GrpcNativeInit(); threadPool = new GrpcThreadPool(this, GetThreadPoolSizeOrDefault(), GetCompletionQueueCountOrDefault()); threadPool.Start(); } /// /// Gets the completion queues used by this gRPC environment. /// internal IReadOnlyCollection CompletionQueues { get { return this.threadPool.CompletionQueues; } } internal bool IsAlive { get { return this.threadPool.IsAlive; } } /// /// Picks a completion queue in a round-robin fashion. /// Shouldn't be invoked on a per-call basis (used at per-channel basis). /// internal CompletionQueueSafeHandle PickCompletionQueue() { var cqIndex = (int) ((cqPickerCounter.Increment() - 1) % this.threadPool.CompletionQueues.Count); return this.threadPool.CompletionQueues.ElementAt(cqIndex); } /// /// Gets the completion queue used by this gRPC environment. /// internal DebugStats DebugStats { get { return this.debugStats; } } /// /// Gets version of gRPC C core. /// internal static string GetCoreVersionString() { var ptr = NativeMethods.Get().grpcsharp_version_string(); // the pointer is not owned return Marshal.PtrToStringAnsi(ptr); } internal static void GrpcNativeInit() { NativeMethods.Get().grpcsharp_init(); } internal static void GrpcNativeShutdown() { NativeMethods.Get().grpcsharp_shutdown(); } /// /// Shuts down this environment. /// private async Task ShutdownAsync() { if (isClosed) { throw new InvalidOperationException("Close has already been called"); } await threadPool.StopAsync().ConfigureAwait(false); GrpcNativeShutdown(); isClosed = true; debugStats.CheckOK(); } private int GetThreadPoolSizeOrDefault() { if (customThreadPoolSize.HasValue) { return customThreadPoolSize.Value; } // In systems with many cores, use half of the cores for GrpcThreadPool // and the other half for .NET thread pool. This heuristic definitely needs // more work, but seems to work reasonably well for a start. return Math.Max(MinDefaultThreadPoolSize, Environment.ProcessorCount / 2); } private int GetCompletionQueueCountOrDefault() { if (customCompletionQueueCount.HasValue) { return customCompletionQueueCount.Value; } // by default, create a completion queue for each thread return GetThreadPoolSizeOrDefault(); } private static class ShutdownHooks { static object staticLock = new object(); static bool hooksRegistered; public static void Register() { lock (staticLock) { if (!hooksRegistered) { #if NETSTANDARD1_5 System.Runtime.Loader.AssemblyLoadContext.Default.Unloading += (assemblyLoadContext) => { HandleShutdown(); }; #else AppDomain.CurrentDomain.ProcessExit += (sender, eventArgs) => { HandleShutdown(); }; AppDomain.CurrentDomain.DomainUnload += (sender, eventArgs) => { HandleShutdown(); }; #endif } hooksRegistered = true; } } /// /// Handler for AppDomain.DomainUnload, AppDomain.ProcessExit and AssemblyLoadContext.Unloading hooks. /// private static void HandleShutdown() { Task.WaitAll(GrpcEnvironment.ShutdownChannelsAsync(), GrpcEnvironment.KillServersAsync()); } } } } grpc-1.3.2/src/csharp/Grpc.Core/IAsyncStreamReader.cs000066400000000000000000000055631310511640000223150ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Grpc.Core { /// /// A stream of messages to be read. /// Messages can be awaited await reader.MoveNext(), that returns true /// if there is a message available and false if there are no more messages /// (i.e. the stream has been closed). /// /// On the client side, the last invocation of MoveNext() either returns false /// if the call has finished successfully or throws RpcException if call finished /// with an error. Once the call finishes, subsequent invocations of MoveNext() will /// continue yielding the same result (returning false or throwing an exception). /// /// /// On the server side, MoveNext() does not throw exceptions. /// In case of a failure, the request stream will appear to be finished /// (MoveNext will return false) and the CancellationToken /// associated with the call will be cancelled to signal the failure. /// /// /// The message type. public interface IAsyncStreamReader : IAsyncEnumerator { } } grpc-1.3.2/src/csharp/Grpc.Core/IAsyncStreamWriter.cs000066400000000000000000000046761310511640000223730ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Grpc.Core { /// /// A writable stream of messages. /// /// The message type. public interface IAsyncStreamWriter { /// /// Writes a single asynchronously. Only one write can be pending at a time. /// /// the message to be written. Cannot be null. Task WriteAsync(T message); /// /// Write options that will be used for the next write. /// If null, default options will be used. /// Once set, this property maintains its value across subsequent /// writes. /// WriteOptions WriteOptions { get; set; } } } grpc-1.3.2/src/csharp/Grpc.Core/IClientStreamWriter.cs000066400000000000000000000042321310511640000225200ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Grpc.Core { /// /// Client-side writable stream of messages with Close capability. /// /// The message type. public interface IClientStreamWriter : IAsyncStreamWriter { /// /// Completes/closes the stream. Can only be called once there is no pending write. No writes should follow calling this. /// Task CompleteAsync(); } } grpc-1.3.2/src/csharp/Grpc.Core/IServerStreamWriter.cs000066400000000000000000000037711310511640000225570ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Grpc.Core { /// /// A writable stream of messages that is used in server-side handlers. /// public interface IServerStreamWriter : IAsyncStreamWriter { // TODO(jtattermusch): consider just using IAsyncStreamWriter instead of this interface. } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/000077500000000000000000000000001310511640000200445ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Core/Internal/AsyncCall.cs000066400000000000000000000471451310511640000222570ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Threading.Tasks; using Grpc.Core.Logging; using Grpc.Core.Profiling; using Grpc.Core.Utils; namespace Grpc.Core.Internal { /// /// Manages client side native call lifecycle. /// internal class AsyncCall : AsyncCallBase { static readonly ILogger Logger = GrpcEnvironment.Logger.ForType>(); readonly CallInvocationDetails details; readonly INativeCall injectedNativeCall; // for testing // Completion of a pending unary response if not null. TaskCompletionSource unaryResponseTcs; // Completion of a streaming response call if not null. TaskCompletionSource streamingResponseCallFinishedTcs; // TODO(jtattermusch): this field could be lazy-initialized (only if someone requests the response headers). // Response headers set here once received. TaskCompletionSource responseHeadersTcs = new TaskCompletionSource(); // Set after status is received. Used for both unary and streaming response calls. ClientSideStatus? finishedStatus; public AsyncCall(CallInvocationDetails callDetails) : base(callDetails.RequestMarshaller.Serializer, callDetails.ResponseMarshaller.Deserializer) { this.details = callDetails.WithOptions(callDetails.Options.Normalize()); this.initialMetadataSent = true; // we always send metadata at the very beginning of the call. } /// /// This constructor should only be used for testing. /// public AsyncCall(CallInvocationDetails callDetails, INativeCall injectedNativeCall) : this(callDetails) { this.injectedNativeCall = injectedNativeCall; } // TODO: this method is not Async, so it shouldn't be in AsyncCall class, but // it is reusing fair amount of code in this class, so we are leaving it here. /// /// Blocking unary request - unary response call. /// public TResponse UnaryCall(TRequest msg) { var profiler = Profilers.ForCurrentThread(); using (profiler.NewScope("AsyncCall.UnaryCall")) using (CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create()) { byte[] payload = UnsafeSerialize(msg); unaryResponseTcs = new TaskCompletionSource(); lock (myLock) { GrpcPreconditions.CheckState(!started); started = true; Initialize(cq); halfcloseRequested = true; readingDone = true; } using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers)) using (var ctx = BatchContextSafeHandle.Create()) { call.StartUnary(ctx, payload, GetWriteFlagsForCall(), metadataArray, details.Options.Flags); var ev = cq.Pluck(ctx.Handle); bool success = (ev.success != 0); try { using (profiler.NewScope("AsyncCall.UnaryCall.HandleBatch")) { HandleUnaryResponse(success, ctx.GetReceivedStatusOnClient(), ctx.GetReceivedMessage(), ctx.GetReceivedInitialMetadata()); } } catch (Exception e) { Logger.Error(e, "Exception occured while invoking completion delegate."); } } // Once the blocking call returns, the result should be available synchronously. // Note that GetAwaiter().GetResult() doesn't wrap exceptions in AggregateException. return unaryResponseTcs.Task.GetAwaiter().GetResult(); } } /// /// Starts a unary request - unary response call. /// public Task UnaryCallAsync(TRequest msg) { lock (myLock) { GrpcPreconditions.CheckState(!started); started = true; Initialize(details.Channel.CompletionQueue); halfcloseRequested = true; readingDone = true; byte[] payload = UnsafeSerialize(msg); unaryResponseTcs = new TaskCompletionSource(); using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers)) { call.StartUnary(HandleUnaryResponse, payload, GetWriteFlagsForCall(), metadataArray, details.Options.Flags); } return unaryResponseTcs.Task; } } /// /// Starts a streamed request - unary response call. /// Use StartSendMessage and StartSendCloseFromClient to stream requests. /// public Task ClientStreamingCallAsync() { lock (myLock) { GrpcPreconditions.CheckState(!started); started = true; Initialize(details.Channel.CompletionQueue); readingDone = true; unaryResponseTcs = new TaskCompletionSource(); using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers)) { call.StartClientStreaming(HandleUnaryResponse, metadataArray, details.Options.Flags); } return unaryResponseTcs.Task; } } /// /// Starts a unary request - streamed response call. /// public void StartServerStreamingCall(TRequest msg) { lock (myLock) { GrpcPreconditions.CheckState(!started); started = true; Initialize(details.Channel.CompletionQueue); halfcloseRequested = true; byte[] payload = UnsafeSerialize(msg); streamingResponseCallFinishedTcs = new TaskCompletionSource(); using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers)) { call.StartServerStreaming(HandleFinished, payload, GetWriteFlagsForCall(), metadataArray, details.Options.Flags); } call.StartReceiveInitialMetadata(HandleReceivedResponseHeaders); } } /// /// Starts a streaming request - streaming response call. /// Use StartSendMessage and StartSendCloseFromClient to stream requests. /// public void StartDuplexStreamingCall() { lock (myLock) { GrpcPreconditions.CheckState(!started); started = true; Initialize(details.Channel.CompletionQueue); streamingResponseCallFinishedTcs = new TaskCompletionSource(); using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers)) { call.StartDuplexStreaming(HandleFinished, metadataArray, details.Options.Flags); } call.StartReceiveInitialMetadata(HandleReceivedResponseHeaders); } } /// /// Sends a streaming request. Only one pending send action is allowed at any given time. /// public Task SendMessageAsync(TRequest msg, WriteFlags writeFlags) { return SendMessageInternalAsync(msg, writeFlags); } /// /// Receives a streaming response. Only one pending read action is allowed at any given time. /// public Task ReadMessageAsync() { return ReadMessageInternalAsync(); } /// /// Sends halfclose, indicating client is done with streaming requests. /// Only one pending send action is allowed at any given time. /// public Task SendCloseFromClientAsync() { lock (myLock) { GrpcPreconditions.CheckState(started); var earlyResult = CheckSendPreconditionsClientSide(); if (earlyResult != null) { return earlyResult; } if (disposed || finished) { // In case the call has already been finished by the serverside, // the halfclose has already been done implicitly, so just return // completed task here. halfcloseRequested = true; return TaskUtils.CompletedTask; } call.StartSendCloseFromClient(HandleSendFinished); halfcloseRequested = true; streamingWriteTcs = new TaskCompletionSource(); return streamingWriteTcs.Task; } } /// /// Get the task that completes once if streaming response call finishes with ok status and throws RpcException with given status otherwise. /// public Task StreamingResponseCallFinishedTask { get { return streamingResponseCallFinishedTcs.Task; } } /// /// Get the task that completes once response headers are received. /// public Task ResponseHeadersAsync { get { return responseHeadersTcs.Task; } } /// /// Gets the resulting status if the call has already finished. /// Throws InvalidOperationException otherwise. /// public Status GetStatus() { lock (myLock) { GrpcPreconditions.CheckState(finishedStatus.HasValue, "Status can only be accessed once the call has finished."); return finishedStatus.Value.Status; } } /// /// Gets the trailing metadata if the call has already finished. /// Throws InvalidOperationException otherwise. /// public Metadata GetTrailers() { lock (myLock) { GrpcPreconditions.CheckState(finishedStatus.HasValue, "Trailers can only be accessed once the call has finished."); return finishedStatus.Value.Trailers; } } public CallInvocationDetails Details { get { return this.details; } } protected override void OnAfterReleaseResources() { details.Channel.RemoveCallReference(this); } protected override bool IsClient { get { return true; } } protected override Exception GetRpcExceptionClientOnly() { return new RpcException(finishedStatus.Value.Status); } protected override Task CheckSendAllowedOrEarlyResult() { var earlyResult = CheckSendPreconditionsClientSide(); if (earlyResult != null) { return earlyResult; } if (finishedStatus.HasValue) { // throwing RpcException if we already received status on client // side makes the most sense. // Note that this throws even for StatusCode.OK. // Writing after the call has finished is not a programming error because server can close // the call anytime, so don't throw directly, but let the write task finish with an error. var tcs = new TaskCompletionSource(); tcs.SetException(new RpcException(finishedStatus.Value.Status)); return tcs.Task; } return null; } private Task CheckSendPreconditionsClientSide() { GrpcPreconditions.CheckState(!halfcloseRequested, "Request stream has already been completed."); GrpcPreconditions.CheckState(streamingWriteTcs == null, "Only one write can be pending at a time."); if (cancelRequested) { // Return a cancelled task. var tcs = new TaskCompletionSource(); tcs.SetCanceled(); return tcs.Task; } return null; } private void Initialize(CompletionQueueSafeHandle cq) { var call = CreateNativeCall(cq); details.Channel.AddCallReference(this); InitializeInternal(call); RegisterCancellationCallback(); } private INativeCall CreateNativeCall(CompletionQueueSafeHandle cq) { if (injectedNativeCall != null) { return injectedNativeCall; // allows injecting a mock INativeCall in tests. } var parentCall = details.Options.PropagationToken != null ? details.Options.PropagationToken.ParentCall : CallSafeHandle.NullInstance; var credentials = details.Options.Credentials; using (var nativeCredentials = credentials != null ? credentials.ToNativeCredentials() : null) { var result = details.Channel.Handle.CreateCall( parentCall, ContextPropagationToken.DefaultMask, cq, details.Method, details.Host, Timespec.FromDateTime(details.Options.Deadline.Value), nativeCredentials); return result; } } // Make sure that once cancellationToken for this call is cancelled, Cancel() will be called. private void RegisterCancellationCallback() { var token = details.Options.CancellationToken; if (token.CanBeCanceled) { token.Register(() => this.Cancel()); } } /// /// Gets WriteFlags set in callDetails.Options.WriteOptions /// private WriteFlags GetWriteFlagsForCall() { var writeOptions = details.Options.WriteOptions; return writeOptions != null ? writeOptions.Flags : default(WriteFlags); } /// /// Handles receive status completion for calls with streaming response. /// private void HandleReceivedResponseHeaders(bool success, Metadata responseHeaders) { // TODO(jtattermusch): handle success==false responseHeadersTcs.SetResult(responseHeaders); } /// /// Handler for unary response completion. /// private void HandleUnaryResponse(bool success, ClientSideStatus receivedStatus, byte[] receivedMessage, Metadata responseHeaders) { // NOTE: because this event is a result of batch containing GRPC_OP_RECV_STATUS_ON_CLIENT, // success will be always set to true. TaskCompletionSource delayedStreamingWriteTcs = null; TResponse msg = default(TResponse); var deserializeException = TryDeserialize(receivedMessage, out msg); lock (myLock) { finished = true; if (deserializeException != null && receivedStatus.Status.StatusCode == StatusCode.OK) { receivedStatus = new ClientSideStatus(DeserializeResponseFailureStatus, receivedStatus.Trailers); } finishedStatus = receivedStatus; if (isStreamingWriteCompletionDelayed) { delayedStreamingWriteTcs = streamingWriteTcs; streamingWriteTcs = null; } ReleaseResourcesIfPossible(); } responseHeadersTcs.SetResult(responseHeaders); if (delayedStreamingWriteTcs != null) { delayedStreamingWriteTcs.SetException(GetRpcExceptionClientOnly()); } var status = receivedStatus.Status; if (status.StatusCode != StatusCode.OK) { unaryResponseTcs.SetException(new RpcException(status)); return; } unaryResponseTcs.SetResult(msg); } /// /// Handles receive status completion for calls with streaming response. /// private void HandleFinished(bool success, ClientSideStatus receivedStatus) { // NOTE: because this event is a result of batch containing GRPC_OP_RECV_STATUS_ON_CLIENT, // success will be always set to true. TaskCompletionSource delayedStreamingWriteTcs = null; lock (myLock) { finished = true; finishedStatus = receivedStatus; if (isStreamingWriteCompletionDelayed) { delayedStreamingWriteTcs = streamingWriteTcs; streamingWriteTcs = null; } ReleaseResourcesIfPossible(); } if (delayedStreamingWriteTcs != null) { delayedStreamingWriteTcs.SetException(GetRpcExceptionClientOnly()); } var status = receivedStatus.Status; if (status.StatusCode != StatusCode.OK) { streamingResponseCallFinishedTcs.SetException(new RpcException(status)); return; } streamingResponseCallFinishedTcs.SetResult(null); } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs000066400000000000000000000311501310511640000230370ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Diagnostics; using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Grpc.Core.Internal; using Grpc.Core.Logging; using Grpc.Core.Profiling; using Grpc.Core.Utils; namespace Grpc.Core.Internal { /// /// Base for handling both client side and server side calls. /// Manages native call lifecycle and provides convenience methods. /// internal abstract class AsyncCallBase { static readonly ILogger Logger = GrpcEnvironment.Logger.ForType>(); protected static readonly Status DeserializeResponseFailureStatus = new Status(StatusCode.Internal, "Failed to deserialize response message."); readonly Func serializer; readonly Func deserializer; protected readonly object myLock = new object(); protected INativeCall call; protected bool disposed; protected bool started; protected bool cancelRequested; protected TaskCompletionSource streamingReadTcs; // Completion of a pending streaming read if not null. protected TaskCompletionSource streamingWriteTcs; // Completion of a pending streaming write or send close from client if not null. protected TaskCompletionSource sendStatusFromServerTcs; protected bool isStreamingWriteCompletionDelayed; // Only used for the client side. protected bool readingDone; // True if last read (i.e. read with null payload) was already received. protected bool halfcloseRequested; // True if send close have been initiated. protected bool finished; // True if close has been received from the peer. protected bool initialMetadataSent; protected long streamingWritesCounter; // Number of streaming send operations started so far. public AsyncCallBase(Func serializer, Func deserializer) { this.serializer = GrpcPreconditions.CheckNotNull(serializer); this.deserializer = GrpcPreconditions.CheckNotNull(deserializer); } /// /// Requests cancelling the call. /// public void Cancel() { lock (myLock) { GrpcPreconditions.CheckState(started); cancelRequested = true; if (!disposed) { call.Cancel(); } } } /// /// Requests cancelling the call with given status. /// protected void CancelWithStatus(Status status) { lock (myLock) { cancelRequested = true; if (!disposed) { call.CancelWithStatus(status); } } } protected void InitializeInternal(INativeCall call) { lock (myLock) { this.call = call; } } /// /// Initiates sending a message. Only one send operation can be active at a time. /// protected Task SendMessageInternalAsync(TWrite msg, WriteFlags writeFlags) { byte[] payload = UnsafeSerialize(msg); lock (myLock) { GrpcPreconditions.CheckState(started); var earlyResult = CheckSendAllowedOrEarlyResult(); if (earlyResult != null) { return earlyResult; } call.StartSendMessage(HandleSendFinished, payload, writeFlags, !initialMetadataSent); initialMetadataSent = true; streamingWritesCounter++; streamingWriteTcs = new TaskCompletionSource(); return streamingWriteTcs.Task; } } /// /// Initiates reading a message. Only one read operation can be active at a time. /// protected Task ReadMessageInternalAsync() { lock (myLock) { GrpcPreconditions.CheckState(started); if (readingDone) { // the last read that returns null or throws an exception is idempotent // and maintains its state. GrpcPreconditions.CheckState(streamingReadTcs != null, "Call does not support streaming reads."); return streamingReadTcs.Task; } GrpcPreconditions.CheckState(streamingReadTcs == null, "Only one read can be pending at a time"); GrpcPreconditions.CheckState(!disposed); call.StartReceiveMessage(HandleReadFinished); streamingReadTcs = new TaskCompletionSource(); return streamingReadTcs.Task; } } /// /// If there are no more pending actions and no new actions can be started, releases /// the underlying native resources. /// protected bool ReleaseResourcesIfPossible() { if (!disposed && call != null) { bool noMoreSendCompletions = streamingWriteTcs == null && (halfcloseRequested || cancelRequested || finished); if (noMoreSendCompletions && readingDone && finished) { ReleaseResources(); return true; } } return false; } protected abstract bool IsClient { get; } /// /// Returns an exception to throw for a failed send operation. /// It is only allowed to call this method for a call that has already finished. /// protected abstract Exception GetRpcExceptionClientOnly(); private void ReleaseResources() { if (call != null) { call.Dispose(); } disposed = true; OnAfterReleaseResources(); } protected virtual void OnAfterReleaseResources() { } /// /// Checks if sending is allowed and possibly returns a Task that allows short-circuiting the send /// logic by directly returning the write operation result task. Normally, null is returned. /// protected abstract Task CheckSendAllowedOrEarlyResult(); protected byte[] UnsafeSerialize(TWrite msg) { return serializer(msg); } protected Exception TryDeserialize(byte[] payload, out TRead msg) { try { msg = deserializer(payload); return null; } catch (Exception e) { msg = default(TRead); return e; } } /// /// Handles send completion (including SendCloseFromClient). /// protected void HandleSendFinished(bool success) { bool delayCompletion = false; TaskCompletionSource origTcs = null; lock (myLock) { if (!success && !finished && IsClient) { // We should be setting this only once per call, following writes will be short circuited // because they cannot start until the entire call finishes. GrpcPreconditions.CheckState(!isStreamingWriteCompletionDelayed); // leave streamingWriteTcs set, it will be completed once call finished. isStreamingWriteCompletionDelayed = true; delayCompletion = true; } else { origTcs = streamingWriteTcs; streamingWriteTcs = null; } ReleaseResourcesIfPossible(); } if (!success) { if (!delayCompletion) { if (IsClient) { GrpcPreconditions.CheckState(finished); // implied by !success && !delayCompletion && IsClient origTcs.SetException(GetRpcExceptionClientOnly()); } else { origTcs.SetException (new IOException("Error sending from server.")); } } // if delayCompletion == true, postpone SetException until call finishes. } else { origTcs.SetResult(null); } } /// /// Handles send status from server completion. /// protected void HandleSendStatusFromServerFinished(bool success) { lock (myLock) { ReleaseResourcesIfPossible(); } if (!success) { sendStatusFromServerTcs.SetException(new IOException("Error sending status from server.")); } else { sendStatusFromServerTcs.SetResult(null); } } /// /// Handles streaming read completion. /// protected void HandleReadFinished(bool success, byte[] receivedMessage) { // if success == false, received message will be null. It that case we will // treat this completion as the last read an rely on C core to handle the failed // read (e.g. deliver approriate statusCode on the clientside). TRead msg = default(TRead); var deserializeException = (success && receivedMessage != null) ? TryDeserialize(receivedMessage, out msg) : null; TaskCompletionSource origTcs = null; lock (myLock) { origTcs = streamingReadTcs; if (receivedMessage == null) { // This was the last read. readingDone = true; } if (deserializeException != null && IsClient) { readingDone = true; // TODO(jtattermusch): it might be too late to set the status CancelWithStatus(DeserializeResponseFailureStatus); } if (!readingDone) { streamingReadTcs = null; } ReleaseResourcesIfPossible(); } if (deserializeException != null && !IsClient) { origTcs.SetException(new IOException("Failed to deserialize request message.", deserializeException)); return; } origTcs.SetResult(msg); } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs000066400000000000000000000220611310511640000234340ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Diagnostics; using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Grpc.Core.Internal; using Grpc.Core.Utils; namespace Grpc.Core.Internal { /// /// Manages server side native call lifecycle. /// internal class AsyncCallServer : AsyncCallBase { readonly TaskCompletionSource finishedServersideTcs = new TaskCompletionSource(); readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); readonly Server server; public AsyncCallServer(Func serializer, Func deserializer, Server server) : base(serializer, deserializer) { this.server = GrpcPreconditions.CheckNotNull(server); } public void Initialize(CallSafeHandle call, CompletionQueueSafeHandle completionQueue) { call.Initialize(completionQueue); server.AddCallReference(this); InitializeInternal(call); } /// /// Only for testing purposes. /// public void InitializeForTesting(INativeCall call) { server.AddCallReference(this); InitializeInternal(call); } /// /// Starts a server side call. /// public Task ServerSideCallAsync() { lock (myLock) { GrpcPreconditions.CheckNotNull(call); started = true; call.StartServerSide(HandleFinishedServerside); return finishedServersideTcs.Task; } } /// /// Sends a streaming response. Only one pending send action is allowed at any given time. /// public Task SendMessageAsync(TResponse msg, WriteFlags writeFlags) { return SendMessageInternalAsync(msg, writeFlags); } /// /// Receives a streaming request. Only one pending read action is allowed at any given time. /// public Task ReadMessageAsync() { return ReadMessageInternalAsync(); } /// /// Initiates sending a initial metadata. /// Even though C-core allows sending metadata in parallel to sending messages, we will treat sending metadata as a send message operation /// to make things simpler. /// public Task SendInitialMetadataAsync(Metadata headers) { lock (myLock) { GrpcPreconditions.CheckNotNull(headers, "metadata"); GrpcPreconditions.CheckState(started); GrpcPreconditions.CheckState(!initialMetadataSent, "Response headers can only be sent once per call."); GrpcPreconditions.CheckState(streamingWritesCounter == 0, "Response headers can only be sent before the first write starts."); var earlyResult = CheckSendAllowedOrEarlyResult(); if (earlyResult != null) { return earlyResult; } using (var metadataArray = MetadataArraySafeHandle.Create(headers)) { call.StartSendInitialMetadata(HandleSendFinished, metadataArray); } this.initialMetadataSent = true; streamingWriteTcs = new TaskCompletionSource(); return streamingWriteTcs.Task; } } /// /// Sends call result status, indicating we are done with writes. /// Sending a status different from StatusCode.OK will also implicitly cancel the call. /// public Task SendStatusFromServerAsync(Status status, Metadata trailers, Tuple optionalWrite) { byte[] payload = optionalWrite != null ? UnsafeSerialize(optionalWrite.Item1) : null; var writeFlags = optionalWrite != null ? optionalWrite.Item2 : default(WriteFlags); lock (myLock) { GrpcPreconditions.CheckState(started); GrpcPreconditions.CheckState(!disposed); GrpcPreconditions.CheckState(!halfcloseRequested, "Can only send status from server once."); using (var metadataArray = MetadataArraySafeHandle.Create(trailers)) { call.StartSendStatusFromServer(HandleSendStatusFromServerFinished, status, metadataArray, !initialMetadataSent, payload, writeFlags); } halfcloseRequested = true; initialMetadataSent = true; sendStatusFromServerTcs = new TaskCompletionSource(); if (optionalWrite != null) { streamingWritesCounter++; } return sendStatusFromServerTcs.Task; } } /// /// Gets cancellation token that gets cancelled once close completion /// is received and the cancelled flag is set. /// public CancellationToken CancellationToken { get { return cancellationTokenSource.Token; } } public string Peer { get { return call.GetPeer(); } } protected override bool IsClient { get { return false; } } protected override Exception GetRpcExceptionClientOnly() { throw new InvalidOperationException("Call be only called for client calls"); } protected override void OnAfterReleaseResources() { server.RemoveCallReference(this); } protected override Task CheckSendAllowedOrEarlyResult() { GrpcPreconditions.CheckState(!halfcloseRequested, "Response stream has already been completed."); GrpcPreconditions.CheckState(!finished, "Already finished."); GrpcPreconditions.CheckState(streamingWriteTcs == null, "Only one write can be pending at a time"); GrpcPreconditions.CheckState(!disposed); return null; } /// /// Handles the server side close completion. /// private void HandleFinishedServerside(bool success, bool cancelled) { // NOTE: because this event is a result of batch containing GRPC_OP_RECV_CLOSE_ON_SERVER, // success will be always set to true. lock (myLock) { finished = true; if (streamingReadTcs == null) { // if there's no pending read, readingDone=true will dispose now. // if there is a pending read, we will dispose once that read finishes. readingDone = true; streamingReadTcs = new TaskCompletionSource(); streamingReadTcs.SetResult(default(TRequest)); } ReleaseResourcesIfPossible(); } if (cancelled) { cancellationTokenSource.Cancel(); } finishedServersideTcs.SetResult(null); } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/AtomicCounter.cs000066400000000000000000000053411310511640000231520ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Threading; namespace Grpc.Core.Internal { internal class AtomicCounter { long counter = 0; public AtomicCounter(long initialCount = 0) { this.counter = initialCount; } public long Increment() { return Interlocked.Increment(ref counter); } public void IncrementIfNonzero(ref bool success) { long origValue = counter; while (true) { if (origValue == 0) { success = false; return; } long result = Interlocked.CompareExchange(ref counter, origValue + 1, origValue); if (result == origValue) { success = true; return; }; origValue = result; } } public long Decrement() { return Interlocked.Decrement(ref counter); } public long Count { get { return counter; } } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/AuthContextSafeHandle.cs000066400000000000000000000106131310511640000245550ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2017, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; using Grpc.Core; using Grpc.Core.Utils; namespace Grpc.Core.Internal { /// /// grpc_auth_context /// internal class AuthContextSafeHandle : SafeHandleZeroIsInvalid { static readonly NativeMethods Native = NativeMethods.Get(); private AuthContextSafeHandle() { } /// /// Copies contents of the native auth context into a new AuthContext instance. /// public AuthContext ToAuthContext() { if (IsInvalid) { return new AuthContext(null, new Dictionary>()); } var peerIdentityPropertyName = Marshal.PtrToStringAnsi(Native.grpcsharp_auth_context_peer_identity_property_name(this)); var propertiesDict = new Dictionary>(); var it = Native.grpcsharp_auth_context_property_iterator(this); IntPtr authPropertyPtr = IntPtr.Zero; while ((authPropertyPtr = Native.grpcsharp_auth_property_iterator_next(ref it)) != IntPtr.Zero) { var authProperty = PtrToAuthProperty(authPropertyPtr); if (!propertiesDict.ContainsKey(authProperty.Name)) { propertiesDict[authProperty.Name] = new List(); } propertiesDict[authProperty.Name].Add(authProperty); } return new AuthContext(peerIdentityPropertyName, propertiesDict); } protected override bool ReleaseHandle() { Native.grpcsharp_auth_context_release(handle); return true; } private AuthProperty PtrToAuthProperty(IntPtr authPropertyPtr) { var nativeAuthProperty = (NativeAuthProperty) Marshal.PtrToStructure(authPropertyPtr, typeof(NativeAuthProperty)); var name = Marshal.PtrToStringAnsi(nativeAuthProperty.Name); var valueBytes = new byte[(int) nativeAuthProperty.ValueLength]; Marshal.Copy(nativeAuthProperty.Value, valueBytes, 0, (int)nativeAuthProperty.ValueLength); return AuthProperty.CreateUnsafe(name, valueBytes); } /// /// grpc_auth_property /// internal struct NativeAuthProperty { public IntPtr Name; public IntPtr Value; public UIntPtr ValueLength; } /// /// grpc_auth_property_iterator /// internal struct NativeAuthPropertyIterator { public IntPtr AuthContext; public UIntPtr Index; public IntPtr Name; } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs000066400000000000000000000102361310511640000246760ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.InteropServices; using System.Text; using Grpc.Core; namespace Grpc.Core.Internal { /// /// grpcsharp_batch_context /// internal class BatchContextSafeHandle : SafeHandleZeroIsInvalid { static readonly NativeMethods Native = NativeMethods.Get(); private BatchContextSafeHandle() { } public static BatchContextSafeHandle Create() { return Native.grpcsharp_batch_context_create(); } public IntPtr Handle { get { return handle; } } // Gets data of recv_initial_metadata completion. public Metadata GetReceivedInitialMetadata() { IntPtr metadataArrayPtr = Native.grpcsharp_batch_context_recv_initial_metadata(this); return MetadataArraySafeHandle.ReadMetadataFromPtrUnsafe(metadataArrayPtr); } // Gets data of recv_status_on_client completion. public ClientSideStatus GetReceivedStatusOnClient() { UIntPtr detailsLength; IntPtr detailsPtr = Native.grpcsharp_batch_context_recv_status_on_client_details(this, out detailsLength); string details = MarshalUtils.PtrToStringUTF8(detailsPtr, (int) detailsLength.ToUInt32()); var status = new Status(Native.grpcsharp_batch_context_recv_status_on_client_status(this), details); IntPtr metadataArrayPtr = Native.grpcsharp_batch_context_recv_status_on_client_trailing_metadata(this); var metadata = MetadataArraySafeHandle.ReadMetadataFromPtrUnsafe(metadataArrayPtr); return new ClientSideStatus(status, metadata); } // Gets data of recv_message completion. public byte[] GetReceivedMessage() { IntPtr len = Native.grpcsharp_batch_context_recv_message_length(this); if (len == new IntPtr(-1)) { return null; } byte[] data = new byte[(int)len]; Native.grpcsharp_batch_context_recv_message_to_buffer(this, data, new UIntPtr((ulong)data.Length)); return data; } // Gets data of receive_close_on_server completion. public bool GetReceivedCloseOnServerCancelled() { return Native.grpcsharp_batch_context_recv_close_on_server_cancelled(this) != 0; } protected override bool ReleaseHandle() { Native.grpcsharp_batch_context_destroy(handle); return true; } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/CStringSafeHandle.cs000066400000000000000000000042631310511640000236640ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.InteropServices; using System.Threading.Tasks; namespace Grpc.Core.Internal { /// /// Owned char* object. /// internal class CStringSafeHandle : SafeHandleZeroIsInvalid { static readonly NativeMethods Native = NativeMethods.Get(); private CStringSafeHandle() { } public string GetValue() { return Marshal.PtrToStringAnsi(handle); } protected override bool ReleaseHandle() { Native.gprsharp_free(handle); return true; } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/CallCredentialsSafeHandle.cs000066400000000000000000000046311310511640000253430ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; namespace Grpc.Core.Internal { /// /// grpc_call_credentials from grpc/grpc_security.h /// internal class CallCredentialsSafeHandle : SafeHandleZeroIsInvalid { static readonly NativeMethods Native = NativeMethods.Get(); private CallCredentialsSafeHandle() { } public static CallCredentialsSafeHandle CreateComposite(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2) { return Native.grpcsharp_composite_call_credentials_create(creds1, creds2); } protected override bool ReleaseHandle() { Native.grpcsharp_call_credentials_release(handle); return true; } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/CallError.cs000066400000000000000000000056651310511640000222740ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.InteropServices; using Grpc.Core.Utils; namespace Grpc.Core.Internal { /// /// grpc_call_error from grpc/grpc.h /// internal enum CallError { /* everything went ok */ OK = 0, /* something failed, we don't know what */ Error, /* this method is not available on the server */ NotOnServer, /* this method is not available on the client */ NotOnClient, /* this method must be called before server_accept */ AlreadyAccepted, /* this method must be called before invoke */ AlreadyInvoked, /* this method must be called after invoke */ NotInvoked, /* this call is already finished (writes_done or write_status has already been called) */ AlreadyFinished, /* there is already an outstanding read/write operation on the call */ TooManyOperations, /* the flags value was illegal for this call */ InvalidFlags } internal static class CallErrorExtensions { /// /// Checks the call API invocation's result is OK. /// public static void CheckOk(this CallError callError) { GrpcPreconditions.CheckState(callError == CallError.OK, "Call error: " + callError); } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/CallFlags.cs000066400000000000000000000045051310511640000222270ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; namespace Grpc.Core.Internal { /// /// Flags to enable special call behaviors (client-side only). /// [Flags] internal enum CallFlags { /// /// The call is idempotent (retrying the call doesn't change the outcome of the operation). /// IdempotentRequest = 0x10, /// /// If channel is in ChannelState.TransientFailure, attempt waiting for the channel to recover /// instead of failing the call immediately. /// WaitForReady = 0x20, /// /// The call is cacheable. gRPC is free to use GET verb */ /// CacheableRequest = 0x40 } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs000066400000000000000000000241141310511640000231630ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; using Grpc.Core; using Grpc.Core.Utils; using Grpc.Core.Profiling; namespace Grpc.Core.Internal { /// /// grpc_call from grpc/grpc.h /// internal class CallSafeHandle : SafeHandleZeroIsInvalid, INativeCall { public static readonly CallSafeHandle NullInstance = new CallSafeHandle(); static readonly NativeMethods Native = NativeMethods.Get(); const uint GRPC_WRITE_BUFFER_HINT = 1; CompletionQueueSafeHandle completionQueue; private CallSafeHandle() { } public void Initialize(CompletionQueueSafeHandle completionQueue) { this.completionQueue = completionQueue; } public void SetCredentials(CallCredentialsSafeHandle credentials) { Native.grpcsharp_call_set_credentials(this, credentials).CheckOk(); } public void StartUnary(UnaryResponseClientHandler callback, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags) { using (completionQueue.NewScope()) { var ctx = BatchContextSafeHandle.Create(); completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient(), context.GetReceivedMessage(), context.GetReceivedInitialMetadata())); Native.grpcsharp_call_start_unary(this, ctx, payload, new UIntPtr((ulong)payload.Length), writeFlags, metadataArray, callFlags) .CheckOk(); } } public void StartUnary(BatchContextSafeHandle ctx, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags) { Native.grpcsharp_call_start_unary(this, ctx, payload, new UIntPtr((ulong)payload.Length), writeFlags, metadataArray, callFlags) .CheckOk(); } public void StartClientStreaming(UnaryResponseClientHandler callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags) { using (completionQueue.NewScope()) { var ctx = BatchContextSafeHandle.Create(); completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient(), context.GetReceivedMessage(), context.GetReceivedInitialMetadata())); Native.grpcsharp_call_start_client_streaming(this, ctx, metadataArray, callFlags).CheckOk(); } } public void StartServerStreaming(ReceivedStatusOnClientHandler callback, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags) { using (completionQueue.NewScope()) { var ctx = BatchContextSafeHandle.Create(); completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient())); Native.grpcsharp_call_start_server_streaming(this, ctx, payload, new UIntPtr((ulong)payload.Length), writeFlags, metadataArray, callFlags).CheckOk(); } } public void StartDuplexStreaming(ReceivedStatusOnClientHandler callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags) { using (completionQueue.NewScope()) { var ctx = BatchContextSafeHandle.Create(); completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient())); Native.grpcsharp_call_start_duplex_streaming(this, ctx, metadataArray, callFlags).CheckOk(); } } public void StartSendMessage(SendCompletionHandler callback, byte[] payload, WriteFlags writeFlags, bool sendEmptyInitialMetadata) { using (completionQueue.NewScope()) { var ctx = BatchContextSafeHandle.Create(); completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success)); Native.grpcsharp_call_send_message(this, ctx, payload, new UIntPtr((ulong)payload.Length), writeFlags, sendEmptyInitialMetadata).CheckOk(); } } public void StartSendCloseFromClient(SendCompletionHandler callback) { using (completionQueue.NewScope()) { var ctx = BatchContextSafeHandle.Create(); completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success)); Native.grpcsharp_call_send_close_from_client(this, ctx).CheckOk(); } } public void StartSendStatusFromServer(SendCompletionHandler callback, Status status, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata, byte[] optionalPayload, WriteFlags writeFlags) { using (completionQueue.NewScope()) { var ctx = BatchContextSafeHandle.Create(); var optionalPayloadLength = optionalPayload != null ? new UIntPtr((ulong)optionalPayload.Length) : UIntPtr.Zero; completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success)); var statusDetailBytes = MarshalUtils.GetBytesUTF8(status.Detail); Native.grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, statusDetailBytes, new UIntPtr((ulong)statusDetailBytes.Length), metadataArray, sendEmptyInitialMetadata, optionalPayload, optionalPayloadLength, writeFlags).CheckOk(); } } public void StartReceiveMessage(ReceivedMessageHandler callback) { using (completionQueue.NewScope()) { var ctx = BatchContextSafeHandle.Create(); completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedMessage())); Native.grpcsharp_call_recv_message(this, ctx).CheckOk(); } } public void StartReceiveInitialMetadata(ReceivedResponseHeadersHandler callback) { using (completionQueue.NewScope()) { var ctx = BatchContextSafeHandle.Create(); completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedInitialMetadata())); Native.grpcsharp_call_recv_initial_metadata(this, ctx).CheckOk(); } } public void StartServerSide(ReceivedCloseOnServerHandler callback) { using (completionQueue.NewScope()) { var ctx = BatchContextSafeHandle.Create(); completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedCloseOnServerCancelled())); Native.grpcsharp_call_start_serverside(this, ctx).CheckOk(); } } public void StartSendInitialMetadata(SendCompletionHandler callback, MetadataArraySafeHandle metadataArray) { using (completionQueue.NewScope()) { var ctx = BatchContextSafeHandle.Create(); completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success)); Native.grpcsharp_call_send_initial_metadata(this, ctx, metadataArray).CheckOk(); } } public void Cancel() { Native.grpcsharp_call_cancel(this).CheckOk(); } public void CancelWithStatus(Status status) { Native.grpcsharp_call_cancel_with_status(this, status.StatusCode, status.Detail).CheckOk(); } public string GetPeer() { using (var cstring = Native.grpcsharp_call_get_peer(this)) { return cstring.GetValue(); } } public AuthContextSafeHandle GetAuthContext() { return Native.grpcsharp_call_auth_context(this); } protected override bool ReleaseHandle() { Native.grpcsharp_call_destroy(handle); return true; } private static uint GetFlags(bool buffered) { return buffered ? 0 : GRPC_WRITE_BUFFER_HINT; } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs000066400000000000000000000054151310511640000245000ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.InteropServices; using System.Threading.Tasks; namespace Grpc.Core.Internal { /// /// grpc_channel_args from grpc/grpc.h /// internal class ChannelArgsSafeHandle : SafeHandleZeroIsInvalid { static readonly NativeMethods Native = NativeMethods.Get(); private ChannelArgsSafeHandle() { } public static ChannelArgsSafeHandle CreateNull() { return new ChannelArgsSafeHandle(); } public static ChannelArgsSafeHandle Create(int size) { return Native.grpcsharp_channel_args_create(new UIntPtr((uint)size)); } public void SetString(int index, string key, string value) { Native.grpcsharp_channel_args_set_string(this, new UIntPtr((uint)index), key, value); } public void SetInteger(int index, string key, int value) { Native.grpcsharp_channel_args_set_integer(this, new UIntPtr((uint)index), key, value); } protected override bool ReleaseHandle() { Native.grpcsharp_channel_args_destroy(handle); return true; } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs000066400000000000000000000061761310511640000260460ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; namespace Grpc.Core.Internal { /// /// grpc_channel_credentials from grpc/grpc_security.h /// internal class ChannelCredentialsSafeHandle : SafeHandleZeroIsInvalid { static readonly NativeMethods Native = NativeMethods.Get(); private ChannelCredentialsSafeHandle() { } public static ChannelCredentialsSafeHandle CreateNullCredentials() { var creds = new ChannelCredentialsSafeHandle(); creds.SetHandle(IntPtr.Zero); return creds; } public static ChannelCredentialsSafeHandle CreateSslCredentials(string pemRootCerts, KeyCertificatePair keyCertPair) { if (keyCertPair != null) { return Native.grpcsharp_ssl_credentials_create(pemRootCerts, keyCertPair.CertificateChain, keyCertPair.PrivateKey); } else { return Native.grpcsharp_ssl_credentials_create(pemRootCerts, null, null); } } public static ChannelCredentialsSafeHandle CreateComposite(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds) { return Native.grpcsharp_composite_channel_credentials_create(channelCreds, callCreds); } protected override bool ReleaseHandle() { Native.grpcsharp_channel_credentials_release(handle); return true; } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs000066400000000000000000000110611310511640000236550ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Grpc.Core.Profiling; namespace Grpc.Core.Internal { /// /// grpc_channel from grpc/grpc.h /// internal class ChannelSafeHandle : SafeHandleZeroIsInvalid { static readonly NativeMethods Native = NativeMethods.Get(); private ChannelSafeHandle() { } public static ChannelSafeHandle CreateInsecure(string target, ChannelArgsSafeHandle channelArgs) { // Increment reference count for the native gRPC environment to make sure we don't do grpc_shutdown() before destroying the server handle. // Doing so would make object finalizer crash if we end up abandoning the handle. GrpcEnvironment.GrpcNativeInit(); return Native.grpcsharp_insecure_channel_create(target, channelArgs); } public static ChannelSafeHandle CreateSecure(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs) { // Increment reference count for the native gRPC environment to make sure we don't do grpc_shutdown() before destroying the server handle. // Doing so would make object finalizer crash if we end up abandoning the handle. GrpcEnvironment.GrpcNativeInit(); return Native.grpcsharp_secure_channel_create(credentials, target, channelArgs); } public CallSafeHandle CreateCall(CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline, CallCredentialsSafeHandle credentials) { var result = Native.grpcsharp_channel_create_call(this, parentCall, propagationMask, cq, method, host, deadline); if (credentials != null) { result.SetCredentials(credentials); } result.Initialize(cq); return result; } public ChannelState CheckConnectivityState(bool tryToConnect) { return Native.grpcsharp_channel_check_connectivity_state(this, tryToConnect ? 1 : 0); } public void WatchConnectivityState(ChannelState lastObservedState, Timespec deadline, CompletionQueueSafeHandle cq, BatchCompletionDelegate callback) { var ctx = BatchContextSafeHandle.Create(); cq.CompletionRegistry.RegisterBatchCompletion(ctx, callback); Native.grpcsharp_channel_watch_connectivity_state(this, lastObservedState, deadline, cq, ctx); } public string GetTarget() { using (var cstring = Native.grpcsharp_channel_get_target(this)) { return cstring.GetValue(); } } protected override bool ReleaseHandle() { Native.grpcsharp_channel_destroy(handle); GrpcEnvironment.GrpcNativeShutdown(); return true; } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/ClientRequestStream.cs000066400000000000000000000054551310511640000243470ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Threading.Tasks; using Grpc.Core.Internal; namespace Grpc.Core.Internal { /// /// Writes requests asynchronously to an underlying AsyncCall object. /// internal class ClientRequestStream : IClientStreamWriter { readonly AsyncCall call; WriteOptions writeOptions; public ClientRequestStream(AsyncCall call) { this.call = call; this.writeOptions = call.Details.Options.WriteOptions; } public Task WriteAsync(TRequest message) { return call.SendMessageAsync(message, GetWriteFlags()); } public Task CompleteAsync() { return call.SendCloseFromClientAsync(); } public WriteOptions WriteOptions { get { return this.writeOptions; } set { writeOptions = value; } } private WriteFlags GetWriteFlags() { var options = writeOptions; return options != null ? options.Flags : default(WriteFlags); } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/ClientResponseStream.cs000066400000000000000000000060661310511640000245140ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; namespace Grpc.Core.Internal { internal class ClientResponseStream : IAsyncStreamReader where TRequest : class where TResponse : class { readonly AsyncCall call; TResponse current; public ClientResponseStream(AsyncCall call) { this.call = call; } public TResponse Current { get { if (current == null) { throw new InvalidOperationException("No current element is available."); } return current; } } public async Task MoveNext(CancellationToken token) { if (token != CancellationToken.None) { throw new InvalidOperationException("Cancellation of individual reads is not supported."); } var result = await call.ReadMessageAsync().ConfigureAwait(false); this.current = result; if (result == null) { await call.StreamingResponseCallFinishedTask.ConfigureAwait(false); return false; } return true; } public void Dispose() { // TODO(jtattermusch): implement the semantics of stream disposal. } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/ClientSideStatus.cs000066400000000000000000000045201310511640000236230ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using Grpc.Core; namespace Grpc.Core.Internal { /// /// Status + metadata received on client side when call finishes. /// (when receive_status_on_client operation finishes). /// internal struct ClientSideStatus { readonly Status status; readonly Metadata trailers; public ClientSideStatus(Status status, Metadata trailers) { this.status = status; this.trailers = trailers; } public Status Status { get { return this.status; } } public Metadata Trailers { get { return this.trailers; } } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/ClockType.cs000066400000000000000000000037441310511640000223000ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion namespace Grpc.Core.Internal { /// /// gpr_clock_type from grpc/support/time.h /// internal enum ClockType { /* Monotonic clock */ Monotonic, /* Realtime clock */ Realtime, /* Precise clock good for performance profiling. */ Precise, /* Timespan - the distance between two time points */ Timespan } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/CompletionQueueEvent.cs000066400000000000000000000047331310511640000245220ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.InteropServices; namespace Grpc.Core.Internal { /// /// grpc_event from grpc/grpc.h /// [StructLayout(LayoutKind.Sequential)] internal struct CompletionQueueEvent { static readonly NativeMethods Native = NativeMethods.Get(); public CompletionType type; public int success; public IntPtr tag; internal static int NativeSize { get { return Native.grpcsharp_sizeof_grpc_event(); } } /// /// grpc_completion_type from grpc/grpc.h /// internal enum CompletionType { /* Shutting down */ Shutdown, /* No event before timeout */ Timeout, /* operation completion */ OpComplete } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs000066400000000000000000000112701310511640000254250ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.InteropServices; using System.Threading.Tasks; using Grpc.Core.Profiling; using Grpc.Core.Utils; namespace Grpc.Core.Internal { /// /// grpc_completion_queue from grpc/grpc.h /// internal class CompletionQueueSafeHandle : SafeHandleZeroIsInvalid { static readonly NativeMethods Native = NativeMethods.Get(); AtomicCounter shutdownRefcount = new AtomicCounter(1); CompletionRegistry completionRegistry; private CompletionQueueSafeHandle() { } public static CompletionQueueSafeHandle Create() { return Native.grpcsharp_completion_queue_create(); } public static CompletionQueueSafeHandle Create(CompletionRegistry completionRegistry) { var cq = Native.grpcsharp_completion_queue_create(); cq.completionRegistry = completionRegistry; return cq; } public CompletionQueueEvent Next() { return Native.grpcsharp_completion_queue_next(this); } public CompletionQueueEvent Pluck(IntPtr tag) { return Native.grpcsharp_completion_queue_pluck(this, tag); } /// /// Creates a new usage scope for this completion queue. Once successfully created, /// the completion queue won't be shutdown before scope.Dispose() is called. /// public UsageScope NewScope() { return new UsageScope(this); } public void Shutdown() { DecrementShutdownRefcount(); } /// /// Completion registry associated with this completion queue. /// Doesn't need to be set if only using Pluck() operations. /// public CompletionRegistry CompletionRegistry { get { return completionRegistry; } } protected override bool ReleaseHandle() { Native.grpcsharp_completion_queue_destroy(handle); return true; } private void DecrementShutdownRefcount() { if (shutdownRefcount.Decrement() == 0) { Native.grpcsharp_completion_queue_shutdown(this); } } private void BeginOp() { bool success = false; shutdownRefcount.IncrementIfNonzero(ref success); GrpcPreconditions.CheckState(success, "Shutdown has already been called"); } private void EndOp() { DecrementShutdownRefcount(); } // Allows declaring BeginOp and EndOp of a completion queue with a using statement. // Declared as struct for better performance. public struct UsageScope : IDisposable { readonly CompletionQueueSafeHandle cq; public UsageScope(CompletionQueueSafeHandle cq) { this.cq = cq; this.cq.BeginOp(); } public void Dispose() { cq.EndOp(); } } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs000066400000000000000000000121651310511640000242420ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Runtime.InteropServices; using Grpc.Core.Logging; using Grpc.Core.Utils; namespace Grpc.Core.Internal { internal delegate void OpCompletionDelegate(bool success); internal delegate void BatchCompletionDelegate(bool success, BatchContextSafeHandle ctx); internal delegate void RequestCallCompletionDelegate(bool success, RequestCallContextSafeHandle ctx); internal class CompletionRegistry { static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); readonly GrpcEnvironment environment; readonly ConcurrentDictionary dict = new ConcurrentDictionary(new IntPtrComparer()); public CompletionRegistry(GrpcEnvironment environment) { this.environment = environment; } public void Register(IntPtr key, OpCompletionDelegate callback) { environment.DebugStats.PendingBatchCompletions.Increment(); GrpcPreconditions.CheckState(dict.TryAdd(key, callback)); } public void RegisterBatchCompletion(BatchContextSafeHandle ctx, BatchCompletionDelegate callback) { OpCompletionDelegate opCallback = ((success) => HandleBatchCompletion(success, ctx, callback)); Register(ctx.Handle, opCallback); } public void RegisterRequestCallCompletion(RequestCallContextSafeHandle ctx, RequestCallCompletionDelegate callback) { OpCompletionDelegate opCallback = ((success) => HandleRequestCallCompletion(success, ctx, callback)); Register(ctx.Handle, opCallback); } public OpCompletionDelegate Extract(IntPtr key) { OpCompletionDelegate value; GrpcPreconditions.CheckState(dict.TryRemove(key, out value)); environment.DebugStats.PendingBatchCompletions.Decrement(); return value; } private static void HandleBatchCompletion(bool success, BatchContextSafeHandle ctx, BatchCompletionDelegate callback) { try { callback(success, ctx); } catch (Exception e) { Logger.Error(e, "Exception occured while invoking batch completion delegate."); } finally { if (ctx != null) { ctx.Dispose(); } } } private static void HandleRequestCallCompletion(bool success, RequestCallContextSafeHandle ctx, RequestCallCompletionDelegate callback) { try { callback(success, ctx); } catch (Exception e) { Logger.Error(e, "Exception occured while invoking request call completion delegate."); } finally { if (ctx != null) { ctx.Dispose(); } } } /// /// IntPtr doesn't implement IEquatable{IntPtr} so we need to use custom comparer to avoid boxing. /// private class IntPtrComparer : IEqualityComparer { public bool Equals(IntPtr x, IntPtr y) { return x == y; } public int GetHashCode(IntPtr obj) { return obj.GetHashCode(); } } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/DebugStats.cs000066400000000000000000000045101310511640000224400ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Threading; namespace Grpc.Core.Internal { internal class DebugStats { public readonly AtomicCounter PendingBatchCompletions = new AtomicCounter(); /// /// Checks the debug stats and take action for any inconsistency found. /// public void CheckOK() { var pendingBatchCompletions = PendingBatchCompletions.Count; if (pendingBatchCompletions != 0) { DebugWarning(string.Format("Detected {0} pending batch completions.", pendingBatchCompletions)); } } private void DebugWarning(string message) { throw new Exception("Shutdown check: " + message); } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/DefaultSslRootsOverride.cs000066400000000000000000000055771310511640000252060ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Concurrent; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.InteropServices; using System.Threading; namespace Grpc.Core.Internal { /// /// Overrides the content of default SSL roots. /// internal static class DefaultSslRootsOverride { const string RootsPemResourceName = "Grpc.Core.roots.pem"; static object staticLock = new object(); /// /// Overrides C core's default roots with roots.pem loaded as embedded resource. /// public static void Override(NativeMethods native) { lock (staticLock) { var stream = typeof(DefaultSslRootsOverride).GetTypeInfo().Assembly.GetManifestResourceStream(RootsPemResourceName); if (stream == null) { throw new IOException(string.Format("Error loading the embedded resource \"{0}\"", RootsPemResourceName)); } using (var streamReader = new StreamReader(stream)) { var pemRootCerts = streamReader.ReadToEnd(); native.grpcsharp_override_default_ssl_roots(pemRootCerts); } } } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs000066400000000000000000000165631310511640000232630ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core.Logging; using Grpc.Core.Profiling; using Grpc.Core.Utils; namespace Grpc.Core.Internal { /// /// Pool of threads polling on a set of completions queues. /// internal class GrpcThreadPool { static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); readonly GrpcEnvironment environment; readonly object myLock = new object(); readonly List threads = new List(); readonly int poolSize; readonly int completionQueueCount; readonly List threadProfilers = new List(); // profilers assigned to threadpool threads bool stopRequested; IReadOnlyCollection completionQueues; /// /// Creates a thread pool threads polling on a set of completions queues. /// /// Environment. /// Pool size. /// Completion queue count. public GrpcThreadPool(GrpcEnvironment environment, int poolSize, int completionQueueCount) { this.environment = environment; this.poolSize = poolSize; this.completionQueueCount = completionQueueCount; GrpcPreconditions.CheckArgument(poolSize >= completionQueueCount, "Thread pool size cannot be smaller than the number of completion queues used."); } public void Start() { lock (myLock) { GrpcPreconditions.CheckState(completionQueues == null, "Already started."); completionQueues = CreateCompletionQueueList(environment, completionQueueCount); for (int i = 0; i < poolSize; i++) { var optionalProfiler = i < threadProfilers.Count ? threadProfilers[i] : null; threads.Add(CreateAndStartThread(i, optionalProfiler)); } } } public Task StopAsync() { lock (myLock) { GrpcPreconditions.CheckState(!stopRequested, "Stop already requested."); stopRequested = true; foreach (var cq in completionQueues) { cq.Shutdown(); } } return Task.Run(() => { foreach (var thread in threads) { thread.Join(); } foreach (var cq in completionQueues) { cq.Dispose(); } for (int i = 0; i < threadProfilers.Count; i++) { threadProfilers[i].Dump(string.Format("grpc_trace_thread_{0}.txt", i)); } }); } /// /// Returns true if there is at least one thread pool thread that hasn't /// already stopped. /// Threads can either stop because all completion queues shut down or /// because all foreground threads have already shutdown and process is /// going to exit. /// internal bool IsAlive { get { return threads.Any(t => t.ThreadState != ThreadState.Stopped); } } internal IReadOnlyCollection CompletionQueues { get { return completionQueues; } } private Thread CreateAndStartThread(int threadIndex, IProfiler optionalProfiler) { var cqIndex = threadIndex % completionQueues.Count; var cq = completionQueues.ElementAt(cqIndex); var thread = new Thread(new ThreadStart(() => RunHandlerLoop(cq, optionalProfiler))); thread.IsBackground = true; thread.Name = string.Format("grpc {0} (cq {1})", threadIndex, cqIndex); thread.Start(); return thread; } /// /// Body of the polling thread. /// private void RunHandlerLoop(CompletionQueueSafeHandle cq, IProfiler optionalProfiler) { if (optionalProfiler != null) { Profilers.SetForCurrentThread(optionalProfiler); } CompletionQueueEvent ev; do { ev = cq.Next(); if (ev.type == CompletionQueueEvent.CompletionType.OpComplete) { bool success = (ev.success != 0); IntPtr tag = ev.tag; try { var callback = cq.CompletionRegistry.Extract(tag); callback(success); } catch (Exception e) { Logger.Error(e, "Exception occured while invoking completion delegate"); } } } while (ev.type != CompletionQueueEvent.CompletionType.Shutdown); } private static IReadOnlyCollection CreateCompletionQueueList(GrpcEnvironment environment, int completionQueueCount) { var list = new List(); for (int i = 0; i < completionQueueCount; i++) { var completionRegistry = new CompletionRegistry(environment); list.Add(CompletionQueueSafeHandle.Create(completionRegistry)); } return list.AsReadOnly(); } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/INativeCall.cs000066400000000000000000000077531310511640000225420ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using Grpc.Core; namespace Grpc.Core.Internal { internal delegate void UnaryResponseClientHandler(bool success, ClientSideStatus receivedStatus, byte[] receivedMessage, Metadata responseHeaders); // Received status for streaming response calls. internal delegate void ReceivedStatusOnClientHandler(bool success, ClientSideStatus receivedStatus); internal delegate void ReceivedMessageHandler(bool success, byte[] receivedMessage); internal delegate void ReceivedResponseHeadersHandler(bool success, Metadata responseHeaders); internal delegate void SendCompletionHandler(bool success); internal delegate void ReceivedCloseOnServerHandler(bool success, bool cancelled); /// /// Abstraction of a native call object. /// internal interface INativeCall : IDisposable { void Cancel(); void CancelWithStatus(Status status); string GetPeer(); void StartUnary(UnaryResponseClientHandler callback, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags); void StartUnary(BatchContextSafeHandle ctx, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags); void StartClientStreaming(UnaryResponseClientHandler callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags); void StartServerStreaming(ReceivedStatusOnClientHandler callback, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags); void StartDuplexStreaming(ReceivedStatusOnClientHandler callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags); void StartReceiveMessage(ReceivedMessageHandler callback); void StartReceiveInitialMetadata(ReceivedResponseHeadersHandler callback); void StartSendInitialMetadata(SendCompletionHandler callback, MetadataArraySafeHandle metadataArray); void StartSendMessage(SendCompletionHandler callback, byte[] payload, WriteFlags writeFlags, bool sendEmptyInitialMetadata); void StartSendCloseFromClient(SendCompletionHandler callback); void StartSendStatusFromServer(SendCompletionHandler callback, Status status, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata, byte[] optionalPayload, WriteFlags writeFlags); void StartServerSide(ReceivedCloseOnServerHandler callback); } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/InterceptingCallInvoker.cs000066400000000000000000000135161310511640000251660ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Utils; namespace Grpc.Core.Internal { /// /// Decorates an underlying CallInvoker to intercept call invocations. /// internal class InterceptingCallInvoker : CallInvoker { readonly CallInvoker callInvoker; readonly Func hostInterceptor; readonly Func callOptionsInterceptor; /// /// Initializes a new instance of the class. /// public InterceptingCallInvoker(CallInvoker callInvoker, Func hostInterceptor = null, Func callOptionsInterceptor = null) { this.callInvoker = GrpcPreconditions.CheckNotNull(callInvoker); this.hostInterceptor = hostInterceptor; this.callOptionsInterceptor = callOptionsInterceptor; } /// /// Intercepts a unary call. /// public override TResponse BlockingUnaryCall(Method method, string host, CallOptions options, TRequest request) { host = InterceptHost(host); options = InterceptCallOptions(options); return callInvoker.BlockingUnaryCall(method, host, options, request); } /// /// Invokes a simple remote call asynchronously. /// public override AsyncUnaryCall AsyncUnaryCall(Method method, string host, CallOptions options, TRequest request) { host = InterceptHost(host); options = InterceptCallOptions(options); return callInvoker.AsyncUnaryCall(method, host, options, request); } /// /// Invokes a server streaming call asynchronously. /// In server streaming scenario, client sends on request and server responds with a stream of responses. /// public override AsyncServerStreamingCall AsyncServerStreamingCall(Method method, string host, CallOptions options, TRequest request) { host = InterceptHost(host); options = InterceptCallOptions(options); return callInvoker.AsyncServerStreamingCall(method, host, options, request); } /// /// Invokes a client streaming call asynchronously. /// In client streaming scenario, client sends a stream of requests and server responds with a single response. /// public override AsyncClientStreamingCall AsyncClientStreamingCall(Method method, string host, CallOptions options) { host = InterceptHost(host); options = InterceptCallOptions(options); return callInvoker.AsyncClientStreamingCall(method, host, options); } /// /// Invokes a duplex streaming call asynchronously. /// In duplex streaming scenario, client sends a stream of requests and server responds with a stream of responses. /// The response stream is completely independent and both side can be sending messages at the same time. /// public override AsyncDuplexStreamingCall AsyncDuplexStreamingCall(Method method, string host, CallOptions options) { host = InterceptHost(host); options = InterceptCallOptions(options); return callInvoker.AsyncDuplexStreamingCall(method, host, options); } private string InterceptHost(string host) { if (hostInterceptor == null) { return host; } return hostInterceptor(host); } private CallOptions InterceptCallOptions(CallOptions options) { if (callOptionsInterceptor == null) { return options; } return callOptionsInterceptor(options); } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/MarshalUtils.cs000066400000000000000000000063561310511640000230150ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.InteropServices; using System.Text; namespace Grpc.Core.Internal { /// /// Useful methods for native/managed marshalling. /// internal static class MarshalUtils { static readonly Encoding EncodingUTF8 = System.Text.Encoding.UTF8; static readonly Encoding EncodingASCII = System.Text.Encoding.ASCII; /// /// Converts IntPtr pointing to a UTF-8 encoded byte array to string. /// public static string PtrToStringUTF8(IntPtr ptr, int len) { var bytes = new byte[len]; Marshal.Copy(ptr, bytes, 0, len); return EncodingUTF8.GetString(bytes); } /// /// Returns byte array containing UTF-8 encoding of given string. /// public static byte[] GetBytesUTF8(string str) { return EncodingUTF8.GetBytes(str); } /// /// Get string from a UTF8 encoded byte array. /// public static string GetStringUTF8(byte[] bytes) { return EncodingUTF8.GetString(bytes); } /// /// Returns byte array containing ASCII encoding of given string. /// public static byte[] GetBytesASCII(string str) { return EncodingASCII.GetBytes(str); } /// /// Get string from an ASCII encoded byte array. /// public static string GetStringASCII(byte[] bytes) { return EncodingASCII.GetString(bytes); } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs000066400000000000000000000102161310511640000250250ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.InteropServices; using System.Threading.Tasks; using Grpc.Core.Profiling; namespace Grpc.Core.Internal { /// /// grpc_metadata_array from grpc/grpc.h /// internal class MetadataArraySafeHandle : SafeHandleZeroIsInvalid { static readonly NativeMethods Native = NativeMethods.Get(); private MetadataArraySafeHandle() { } public static MetadataArraySafeHandle Create(Metadata metadata) { if (metadata.Count == 0) { return new MetadataArraySafeHandle(); } // TODO(jtattermusch): we might wanna check that the metadata is readonly var metadataArray = Native.grpcsharp_metadata_array_create(new UIntPtr((ulong)metadata.Count)); for (int i = 0; i < metadata.Count; i++) { var valueBytes = metadata[i].GetSerializedValueUnsafe(); Native.grpcsharp_metadata_array_add(metadataArray, metadata[i].Key, valueBytes, new UIntPtr((ulong)valueBytes.Length)); } return metadataArray; } /// /// Reads metadata from pointer to grpc_metadata_array /// public static Metadata ReadMetadataFromPtrUnsafe(IntPtr metadataArray) { if (metadataArray == IntPtr.Zero) { return null; } ulong count = Native.grpcsharp_metadata_array_count(metadataArray).ToUInt64(); var metadata = new Metadata(); for (ulong i = 0; i < count; i++) { var index = new UIntPtr(i); UIntPtr keyLen; IntPtr keyPtr = Native.grpcsharp_metadata_array_get_key(metadataArray, index, out keyLen); string key = Marshal.PtrToStringAnsi(keyPtr, (int)keyLen.ToUInt32()); UIntPtr valueLen; IntPtr valuePtr = Native.grpcsharp_metadata_array_get_value(metadataArray, index, out valueLen); var bytes = new byte[valueLen.ToUInt64()]; Marshal.Copy(valuePtr, bytes, 0, bytes.Length); metadata.Add(Metadata.Entry.CreateUnsafe(key, bytes)); } return metadata; } internal IntPtr Handle { get { return handle; } } protected override bool ReleaseHandle() { Native.grpcsharp_metadata_array_destroy_full(handle); return true; } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/NativeExtension.cs000066400000000000000000000172711310511640000235260ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.IO; using System.Reflection; using Grpc.Core.Logging; namespace Grpc.Core.Internal { /// /// Takes care of loading C# native extension and provides access to PInvoke calls the library exports. /// internal sealed class NativeExtension { static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); static readonly object staticLock = new object(); static volatile NativeExtension instance; readonly NativeMethods nativeMethods; private NativeExtension() { this.nativeMethods = new NativeMethods(Load()); // Redirect the the native logs as the very first thing after loading the native extension // to make sure we don't lose any logs. NativeLogRedirector.Redirect(this.nativeMethods); DefaultSslRootsOverride.Override(this.nativeMethods); Logger.Debug("gRPC native library loaded successfully."); } /// /// Gets singleton instance of this class. /// The native extension is loaded when called for the first time. /// public static NativeExtension Get() { if (instance == null) { lock (staticLock) { if (instance == null) { instance = new NativeExtension(); } } } return instance; } /// /// Provides access to the exported native methods. /// public NativeMethods NativeMethods { get { return this.nativeMethods; } } /// /// Detects which configuration of native extension to load and load it. /// private static UnmanagedLibrary Load() { // TODO: allow customizing path to native extension (possibly through exposing a GrpcEnvironment property). // See https://github.com/grpc/grpc/pull/7303 for one option. var assemblyDirectory = Path.GetDirectoryName(GetAssemblyPath()); // With old-style VS projects, the native libraries get copied using a .targets rule to the build output folder // alongside the compiled assembly. // With dotnet cli projects targeting net45 framework, the native libraries (just the required ones) // are similarly copied to the built output folder, through the magic of Microsoft.NETCore.Platforms. var classicPath = Path.Combine(assemblyDirectory, GetNativeLibraryFilename()); // With dotnet cli project targeting netcoreapp1.0, projects will use Grpc.Core assembly directly in the location where it got restored // by nuget. We locate the native libraries based on known structure of Grpc.Core nuget package. // When "dotnet publish" is used, the runtimes directory is copied next to the published assemblies. string runtimesDirectory = string.Format("runtimes/{0}/native", GetPlatformString()); var netCorePublishedAppStylePath = Path.Combine(assemblyDirectory, runtimesDirectory, GetNativeLibraryFilename()); var netCoreAppStylePath = Path.Combine(assemblyDirectory, "../..", runtimesDirectory, GetNativeLibraryFilename()); // Look for all native library in all possible locations in given order. string[] paths = new[] { classicPath, netCorePublishedAppStylePath, netCoreAppStylePath}; return new UnmanagedLibrary(paths); } private static string GetAssemblyPath() { var assembly = typeof(NativeExtension).GetTypeInfo().Assembly; #if NETSTANDARD1_5 // Assembly.EscapedCodeBase does not exist under CoreCLR, but assemblies imported from a nuget package // don't seem to be shadowed by DNX-based projects at all. return assembly.Location; #else // If assembly is shadowed (e.g. in a webapp), EscapedCodeBase is pointing // to the original location of the assembly, and Location is pointing // to the shadow copy. We care about the original location because // the native dlls don't get shadowed. var escapedCodeBase = assembly.EscapedCodeBase; if (IsFileUri(escapedCodeBase)) { return new Uri(escapedCodeBase).LocalPath; } return assembly.Location; #endif } #if !NETSTANDARD1_5 private static bool IsFileUri(string uri) { return uri.ToLowerInvariant().StartsWith(Uri.UriSchemeFile); } #endif private static string GetPlatformString() { if (PlatformApis.IsWindows) { return "win"; } if (PlatformApis.IsLinux) { return "linux"; } if (PlatformApis.IsMacOSX) { return "osx"; } throw new InvalidOperationException("Unsupported platform."); } // Currently, only Intel platform is supported. private static string GetArchitectureString() { if (PlatformApis.Is64Bit) { return "x64"; } else { return "x86"; } } // platform specific file name of the extension library private static string GetNativeLibraryFilename() { string architecture = GetArchitectureString(); if (PlatformApis.IsWindows) { return string.Format("grpc_csharp_ext.{0}.dll", architecture); } if (PlatformApis.IsLinux) { return string.Format("libgrpc_csharp_ext.{0}.so", architecture); } if (PlatformApis.IsMacOSX) { return string.Format("libgrpc_csharp_ext.{0}.dylib", architecture); } throw new InvalidOperationException("Unsupported platform."); } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/NativeLogRedirector.cs000066400000000000000000000077241310511640000243200ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Concurrent; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Threading; namespace Grpc.Core.Internal { internal delegate void GprLogDelegate(IntPtr fileStringPtr, int line, ulong threadId, IntPtr severityStringPtr, IntPtr msgPtr); /// /// Logs from gRPC C core library can get lost if your application is not a console app. /// This class allows redirection of logs to gRPC logger. /// internal static class NativeLogRedirector { static object staticLock = new object(); static GprLogDelegate writeCallback; /// /// Redirects logs from native gRPC C core library to a general logger. /// public static void Redirect(NativeMethods native) { lock (staticLock) { if (writeCallback == null) { writeCallback = new GprLogDelegate(HandleWrite); native.grpcsharp_redirect_log(writeCallback); } } } private static void HandleWrite(IntPtr fileStringPtr, int line, ulong threadId, IntPtr severityStringPtr, IntPtr msgPtr) { try { var logger = GrpcEnvironment.Logger; string severityString = Marshal.PtrToStringAnsi(severityStringPtr); string message = string.Format("{0} {1}:{2}: {3}", threadId, Marshal.PtrToStringAnsi(fileStringPtr), line, Marshal.PtrToStringAnsi(msgPtr)); switch (severityString) { case "D": logger.Debug(message); break; case "I": logger.Info(message); break; case "E": logger.Error(message); break; default: // severity not recognized, default to error. logger.Error(message); break; } } catch (Exception e) { Console.WriteLine("Caught exception in native callback " + e); } } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs000066400000000000000000000117701310511640000266250ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Grpc.Core.Logging; using Grpc.Core.Utils; namespace Grpc.Core.Internal { internal delegate void NativeMetadataInterceptor(IntPtr statePtr, IntPtr serviceUrlPtr, IntPtr methodNamePtr, IntPtr callbackPtr, IntPtr userDataPtr, bool isDestroy); internal class NativeMetadataCredentialsPlugin { const string GetMetadataExceptionMsg = "Exception occured in metadata credentials plugin."; static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); static readonly NativeMethods Native = NativeMethods.Get(); AsyncAuthInterceptor interceptor; GCHandle gcHandle; NativeMetadataInterceptor nativeInterceptor; CallCredentialsSafeHandle credentials; public NativeMetadataCredentialsPlugin(AsyncAuthInterceptor interceptor) { this.interceptor = GrpcPreconditions.CheckNotNull(interceptor, "interceptor"); this.nativeInterceptor = NativeMetadataInterceptorHandler; // Make sure the callback doesn't get garbage collected until it is destroyed. this.gcHandle = GCHandle.Alloc(this.nativeInterceptor, GCHandleType.Normal); this.credentials = Native.grpcsharp_metadata_credentials_create_from_plugin(nativeInterceptor); } public CallCredentialsSafeHandle Credentials { get { return credentials; } } private void NativeMetadataInterceptorHandler(IntPtr statePtr, IntPtr serviceUrlPtr, IntPtr methodNamePtr, IntPtr callbackPtr, IntPtr userDataPtr, bool isDestroy) { if (isDestroy) { gcHandle.Free(); return; } try { var context = new AuthInterceptorContext(Marshal.PtrToStringAnsi(serviceUrlPtr), Marshal.PtrToStringAnsi(methodNamePtr)); // Don't await, we are in a native callback and need to return. #pragma warning disable 4014 GetMetadataAsync(context, callbackPtr, userDataPtr); #pragma warning restore 4014 } catch (Exception e) { Native.grpcsharp_metadata_credentials_notify_from_plugin(callbackPtr, userDataPtr, MetadataArraySafeHandle.Create(Metadata.Empty), StatusCode.Unknown, GetMetadataExceptionMsg); Logger.Error(e, GetMetadataExceptionMsg); } } private async Task GetMetadataAsync(AuthInterceptorContext context, IntPtr callbackPtr, IntPtr userDataPtr) { try { var metadata = new Metadata(); await interceptor(context, metadata).ConfigureAwait(false); using (var metadataArray = MetadataArraySafeHandle.Create(metadata)) { Native.grpcsharp_metadata_credentials_notify_from_plugin(callbackPtr, userDataPtr, metadataArray, StatusCode.OK, null); } } catch (Exception e) { Native.grpcsharp_metadata_credentials_notify_from_plugin(callbackPtr, userDataPtr, MetadataArraySafeHandle.Create(Metadata.Empty), StatusCode.Unknown, GetMetadataExceptionMsg); Logger.Error(e, GetMetadataExceptionMsg); } } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/NativeMethods.cs000066400000000000000000001126201310511640000231470ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Concurrent; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.InteropServices; using System.Threading; using Grpc.Core.Logging; using Grpc.Core.Utils; namespace Grpc.Core.Internal { /// /// Provides access to all native methods provided by NativeExtension. /// An extra level of indirection is added to P/Invoke calls to allow intelligent loading /// of the right configuration of the native extension based on current platform, architecture etc. /// internal class NativeMethods { #region Native methods public readonly Delegates.grpcsharp_init_delegate grpcsharp_init; public readonly Delegates.grpcsharp_shutdown_delegate grpcsharp_shutdown; public readonly Delegates.grpcsharp_version_string_delegate grpcsharp_version_string; public readonly Delegates.grpcsharp_batch_context_create_delegate grpcsharp_batch_context_create; public readonly Delegates.grpcsharp_batch_context_recv_initial_metadata_delegate grpcsharp_batch_context_recv_initial_metadata; public readonly Delegates.grpcsharp_batch_context_recv_message_length_delegate grpcsharp_batch_context_recv_message_length; public readonly Delegates.grpcsharp_batch_context_recv_message_to_buffer_delegate grpcsharp_batch_context_recv_message_to_buffer; public readonly Delegates.grpcsharp_batch_context_recv_status_on_client_status_delegate grpcsharp_batch_context_recv_status_on_client_status; public readonly Delegates.grpcsharp_batch_context_recv_status_on_client_details_delegate grpcsharp_batch_context_recv_status_on_client_details; public readonly Delegates.grpcsharp_batch_context_recv_status_on_client_trailing_metadata_delegate grpcsharp_batch_context_recv_status_on_client_trailing_metadata; public readonly Delegates.grpcsharp_batch_context_recv_close_on_server_cancelled_delegate grpcsharp_batch_context_recv_close_on_server_cancelled; public readonly Delegates.grpcsharp_batch_context_destroy_delegate grpcsharp_batch_context_destroy; public readonly Delegates.grpcsharp_request_call_context_create_delegate grpcsharp_request_call_context_create; public readonly Delegates.grpcsharp_request_call_context_call_delegate grpcsharp_request_call_context_call; public readonly Delegates.grpcsharp_request_call_context_method_delegate grpcsharp_request_call_context_method; public readonly Delegates.grpcsharp_request_call_context_host_delegate grpcsharp_request_call_context_host; public readonly Delegates.grpcsharp_request_call_context_deadline_delegate grpcsharp_request_call_context_deadline; public readonly Delegates.grpcsharp_request_call_context_request_metadata_delegate grpcsharp_request_call_context_request_metadata; public readonly Delegates.grpcsharp_request_call_context_destroy_delegate grpcsharp_request_call_context_destroy; public readonly Delegates.grpcsharp_composite_call_credentials_create_delegate grpcsharp_composite_call_credentials_create; public readonly Delegates.grpcsharp_call_credentials_release_delegate grpcsharp_call_credentials_release; public readonly Delegates.grpcsharp_call_cancel_delegate grpcsharp_call_cancel; public readonly Delegates.grpcsharp_call_cancel_with_status_delegate grpcsharp_call_cancel_with_status; public readonly Delegates.grpcsharp_call_start_unary_delegate grpcsharp_call_start_unary; public readonly Delegates.grpcsharp_call_start_client_streaming_delegate grpcsharp_call_start_client_streaming; public readonly Delegates.grpcsharp_call_start_server_streaming_delegate grpcsharp_call_start_server_streaming; public readonly Delegates.grpcsharp_call_start_duplex_streaming_delegate grpcsharp_call_start_duplex_streaming; public readonly Delegates.grpcsharp_call_send_message_delegate grpcsharp_call_send_message; public readonly Delegates.grpcsharp_call_send_close_from_client_delegate grpcsharp_call_send_close_from_client; public readonly Delegates.grpcsharp_call_send_status_from_server_delegate grpcsharp_call_send_status_from_server; public readonly Delegates.grpcsharp_call_recv_message_delegate grpcsharp_call_recv_message; public readonly Delegates.grpcsharp_call_recv_initial_metadata_delegate grpcsharp_call_recv_initial_metadata; public readonly Delegates.grpcsharp_call_start_serverside_delegate grpcsharp_call_start_serverside; public readonly Delegates.grpcsharp_call_send_initial_metadata_delegate grpcsharp_call_send_initial_metadata; public readonly Delegates.grpcsharp_call_set_credentials_delegate grpcsharp_call_set_credentials; public readonly Delegates.grpcsharp_call_get_peer_delegate grpcsharp_call_get_peer; public readonly Delegates.grpcsharp_call_destroy_delegate grpcsharp_call_destroy; public readonly Delegates.grpcsharp_channel_args_create_delegate grpcsharp_channel_args_create; public readonly Delegates.grpcsharp_channel_args_set_string_delegate grpcsharp_channel_args_set_string; public readonly Delegates.grpcsharp_channel_args_set_integer_delegate grpcsharp_channel_args_set_integer; public readonly Delegates.grpcsharp_channel_args_destroy_delegate grpcsharp_channel_args_destroy; public readonly Delegates.grpcsharp_override_default_ssl_roots grpcsharp_override_default_ssl_roots; public readonly Delegates.grpcsharp_ssl_credentials_create_delegate grpcsharp_ssl_credentials_create; public readonly Delegates.grpcsharp_composite_channel_credentials_create_delegate grpcsharp_composite_channel_credentials_create; public readonly Delegates.grpcsharp_channel_credentials_release_delegate grpcsharp_channel_credentials_release; public readonly Delegates.grpcsharp_insecure_channel_create_delegate grpcsharp_insecure_channel_create; public readonly Delegates.grpcsharp_secure_channel_create_delegate grpcsharp_secure_channel_create; public readonly Delegates.grpcsharp_channel_create_call_delegate grpcsharp_channel_create_call; public readonly Delegates.grpcsharp_channel_check_connectivity_state_delegate grpcsharp_channel_check_connectivity_state; public readonly Delegates.grpcsharp_channel_watch_connectivity_state_delegate grpcsharp_channel_watch_connectivity_state; public readonly Delegates.grpcsharp_channel_get_target_delegate grpcsharp_channel_get_target; public readonly Delegates.grpcsharp_channel_destroy_delegate grpcsharp_channel_destroy; public readonly Delegates.grpcsharp_sizeof_grpc_event_delegate grpcsharp_sizeof_grpc_event; public readonly Delegates.grpcsharp_completion_queue_create_delegate grpcsharp_completion_queue_create; public readonly Delegates.grpcsharp_completion_queue_shutdown_delegate grpcsharp_completion_queue_shutdown; public readonly Delegates.grpcsharp_completion_queue_next_delegate grpcsharp_completion_queue_next; public readonly Delegates.grpcsharp_completion_queue_pluck_delegate grpcsharp_completion_queue_pluck; public readonly Delegates.grpcsharp_completion_queue_destroy_delegate grpcsharp_completion_queue_destroy; public readonly Delegates.gprsharp_free_delegate gprsharp_free; public readonly Delegates.grpcsharp_metadata_array_create_delegate grpcsharp_metadata_array_create; public readonly Delegates.grpcsharp_metadata_array_add_delegate grpcsharp_metadata_array_add; public readonly Delegates.grpcsharp_metadata_array_count_delegate grpcsharp_metadata_array_count; public readonly Delegates.grpcsharp_metadata_array_get_key_delegate grpcsharp_metadata_array_get_key; public readonly Delegates.grpcsharp_metadata_array_get_value_delegate grpcsharp_metadata_array_get_value; public readonly Delegates.grpcsharp_metadata_array_destroy_full_delegate grpcsharp_metadata_array_destroy_full; public readonly Delegates.grpcsharp_redirect_log_delegate grpcsharp_redirect_log; public readonly Delegates.grpcsharp_metadata_credentials_create_from_plugin_delegate grpcsharp_metadata_credentials_create_from_plugin; public readonly Delegates.grpcsharp_metadata_credentials_notify_from_plugin_delegate grpcsharp_metadata_credentials_notify_from_plugin; public readonly Delegates.grpcsharp_ssl_server_credentials_create_delegate grpcsharp_ssl_server_credentials_create; public readonly Delegates.grpcsharp_server_credentials_release_delegate grpcsharp_server_credentials_release; public readonly Delegates.grpcsharp_server_create_delegate grpcsharp_server_create; public readonly Delegates.grpcsharp_server_register_completion_queue_delegate grpcsharp_server_register_completion_queue; public readonly Delegates.grpcsharp_server_add_insecure_http2_port_delegate grpcsharp_server_add_insecure_http2_port; public readonly Delegates.grpcsharp_server_add_secure_http2_port_delegate grpcsharp_server_add_secure_http2_port; public readonly Delegates.grpcsharp_server_start_delegate grpcsharp_server_start; public readonly Delegates.grpcsharp_server_request_call_delegate grpcsharp_server_request_call; public readonly Delegates.grpcsharp_server_cancel_all_calls_delegate grpcsharp_server_cancel_all_calls; public readonly Delegates.grpcsharp_server_shutdown_and_notify_callback_delegate grpcsharp_server_shutdown_and_notify_callback; public readonly Delegates.grpcsharp_server_destroy_delegate grpcsharp_server_destroy; public readonly Delegates.grpcsharp_call_auth_context_delegate grpcsharp_call_auth_context; public readonly Delegates.grpcsharp_auth_context_peer_identity_property_name_delegate grpcsharp_auth_context_peer_identity_property_name; public readonly Delegates.grpcsharp_auth_context_property_iterator_delegate grpcsharp_auth_context_property_iterator; public readonly Delegates.grpcsharp_auth_property_iterator_next_delegate grpcsharp_auth_property_iterator_next; public readonly Delegates.grpcsharp_auth_context_release_delegate grpcsharp_auth_context_release; public readonly Delegates.gprsharp_now_delegate gprsharp_now; public readonly Delegates.gprsharp_inf_future_delegate gprsharp_inf_future; public readonly Delegates.gprsharp_inf_past_delegate gprsharp_inf_past; public readonly Delegates.gprsharp_convert_clock_type_delegate gprsharp_convert_clock_type; public readonly Delegates.gprsharp_sizeof_timespec_delegate gprsharp_sizeof_timespec; public readonly Delegates.grpcsharp_test_callback_delegate grpcsharp_test_callback; public readonly Delegates.grpcsharp_test_nop_delegate grpcsharp_test_nop; #endregion public NativeMethods(UnmanagedLibrary library) { this.grpcsharp_init = GetMethodDelegate(library); this.grpcsharp_shutdown = GetMethodDelegate(library); this.grpcsharp_version_string = GetMethodDelegate(library); this.grpcsharp_batch_context_create = GetMethodDelegate(library); this.grpcsharp_batch_context_recv_initial_metadata = GetMethodDelegate(library); this.grpcsharp_batch_context_recv_message_length = GetMethodDelegate(library); this.grpcsharp_batch_context_recv_message_to_buffer = GetMethodDelegate(library); this.grpcsharp_batch_context_recv_status_on_client_status = GetMethodDelegate(library); this.grpcsharp_batch_context_recv_status_on_client_details = GetMethodDelegate(library); this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = GetMethodDelegate(library); this.grpcsharp_batch_context_recv_close_on_server_cancelled = GetMethodDelegate(library); this.grpcsharp_batch_context_destroy = GetMethodDelegate(library); this.grpcsharp_request_call_context_create = GetMethodDelegate(library); this.grpcsharp_request_call_context_call = GetMethodDelegate(library); this.grpcsharp_request_call_context_method = GetMethodDelegate(library); this.grpcsharp_request_call_context_host = GetMethodDelegate(library); this.grpcsharp_request_call_context_deadline = GetMethodDelegate(library); this.grpcsharp_request_call_context_request_metadata = GetMethodDelegate(library); this.grpcsharp_request_call_context_destroy = GetMethodDelegate(library); this.grpcsharp_composite_call_credentials_create = GetMethodDelegate(library); this.grpcsharp_call_credentials_release = GetMethodDelegate(library); this.grpcsharp_call_cancel = GetMethodDelegate(library); this.grpcsharp_call_cancel_with_status = GetMethodDelegate(library); this.grpcsharp_call_start_unary = GetMethodDelegate(library); this.grpcsharp_call_start_client_streaming = GetMethodDelegate(library); this.grpcsharp_call_start_server_streaming = GetMethodDelegate(library); this.grpcsharp_call_start_duplex_streaming = GetMethodDelegate(library); this.grpcsharp_call_send_message = GetMethodDelegate(library); this.grpcsharp_call_send_close_from_client = GetMethodDelegate(library); this.grpcsharp_call_send_status_from_server = GetMethodDelegate(library); this.grpcsharp_call_recv_message = GetMethodDelegate(library); this.grpcsharp_call_recv_initial_metadata = GetMethodDelegate(library); this.grpcsharp_call_start_serverside = GetMethodDelegate(library); this.grpcsharp_call_send_initial_metadata = GetMethodDelegate(library); this.grpcsharp_call_set_credentials = GetMethodDelegate(library); this.grpcsharp_call_get_peer = GetMethodDelegate(library); this.grpcsharp_call_destroy = GetMethodDelegate(library); this.grpcsharp_channel_args_create = GetMethodDelegate(library); this.grpcsharp_channel_args_set_string = GetMethodDelegate(library); this.grpcsharp_channel_args_set_integer = GetMethodDelegate(library); this.grpcsharp_channel_args_destroy = GetMethodDelegate(library); this.grpcsharp_override_default_ssl_roots = GetMethodDelegate(library); this.grpcsharp_ssl_credentials_create = GetMethodDelegate(library); this.grpcsharp_composite_channel_credentials_create = GetMethodDelegate(library); this.grpcsharp_channel_credentials_release = GetMethodDelegate(library); this.grpcsharp_insecure_channel_create = GetMethodDelegate(library); this.grpcsharp_secure_channel_create = GetMethodDelegate(library); this.grpcsharp_channel_create_call = GetMethodDelegate(library); this.grpcsharp_channel_check_connectivity_state = GetMethodDelegate(library); this.grpcsharp_channel_watch_connectivity_state = GetMethodDelegate(library); this.grpcsharp_channel_get_target = GetMethodDelegate(library); this.grpcsharp_channel_destroy = GetMethodDelegate(library); this.grpcsharp_sizeof_grpc_event = GetMethodDelegate(library); this.grpcsharp_completion_queue_create = GetMethodDelegate(library); this.grpcsharp_completion_queue_shutdown = GetMethodDelegate(library); this.grpcsharp_completion_queue_next = GetMethodDelegate(library); this.grpcsharp_completion_queue_pluck = GetMethodDelegate(library); this.grpcsharp_completion_queue_destroy = GetMethodDelegate(library); this.gprsharp_free = GetMethodDelegate(library); this.grpcsharp_metadata_array_create = GetMethodDelegate(library); this.grpcsharp_metadata_array_add = GetMethodDelegate(library); this.grpcsharp_metadata_array_count = GetMethodDelegate(library); this.grpcsharp_metadata_array_get_key = GetMethodDelegate(library); this.grpcsharp_metadata_array_get_value = GetMethodDelegate(library); this.grpcsharp_metadata_array_destroy_full = GetMethodDelegate(library); this.grpcsharp_redirect_log = GetMethodDelegate(library); this.grpcsharp_metadata_credentials_create_from_plugin = GetMethodDelegate(library); this.grpcsharp_metadata_credentials_notify_from_plugin = GetMethodDelegate(library); this.grpcsharp_ssl_server_credentials_create = GetMethodDelegate(library); this.grpcsharp_server_credentials_release = GetMethodDelegate(library); this.grpcsharp_server_create = GetMethodDelegate(library); this.grpcsharp_server_register_completion_queue = GetMethodDelegate(library); this.grpcsharp_server_add_insecure_http2_port = GetMethodDelegate(library); this.grpcsharp_server_add_secure_http2_port = GetMethodDelegate(library); this.grpcsharp_server_start = GetMethodDelegate(library); this.grpcsharp_server_request_call = GetMethodDelegate(library); this.grpcsharp_server_cancel_all_calls = GetMethodDelegate(library); this.grpcsharp_server_shutdown_and_notify_callback = GetMethodDelegate(library); this.grpcsharp_server_destroy = GetMethodDelegate(library); this.grpcsharp_call_auth_context = GetMethodDelegate(library); this.grpcsharp_auth_context_peer_identity_property_name = GetMethodDelegate(library); this.grpcsharp_auth_context_property_iterator = GetMethodDelegate(library); this.grpcsharp_auth_property_iterator_next = GetMethodDelegate(library); this.grpcsharp_auth_context_release = GetMethodDelegate(library); this.gprsharp_now = GetMethodDelegate(library); this.gprsharp_inf_future = GetMethodDelegate(library); this.gprsharp_inf_past = GetMethodDelegate(library); this.gprsharp_convert_clock_type = GetMethodDelegate(library); this.gprsharp_sizeof_timespec = GetMethodDelegate(library); this.grpcsharp_test_callback = GetMethodDelegate(library); this.grpcsharp_test_nop = GetMethodDelegate(library); } /// /// Gets singleton instance of this class. /// public static NativeMethods Get() { return NativeExtension.Get().NativeMethods; } static T GetMethodDelegate(UnmanagedLibrary library) where T : class { var methodName = RemoveStringSuffix(typeof(T).Name, "_delegate"); return library.GetNativeMethodDelegate(methodName); } static string RemoveStringSuffix(string str, string toRemove) { if (!str.EndsWith(toRemove)) { return str; } return str.Substring(0, str.Length - toRemove.Length); } /// /// Delegate types for all published native methods. Declared under inner class to prevent scope pollution. /// public class Delegates { public delegate void grpcsharp_init_delegate(); public delegate void grpcsharp_shutdown_delegate(); public delegate IntPtr grpcsharp_version_string_delegate(); // returns not-owned const char* public delegate BatchContextSafeHandle grpcsharp_batch_context_create_delegate(); public delegate IntPtr grpcsharp_batch_context_recv_initial_metadata_delegate(BatchContextSafeHandle ctx); public delegate IntPtr grpcsharp_batch_context_recv_message_length_delegate(BatchContextSafeHandle ctx); public delegate void grpcsharp_batch_context_recv_message_to_buffer_delegate(BatchContextSafeHandle ctx, byte[] buffer, UIntPtr bufferLen); public delegate StatusCode grpcsharp_batch_context_recv_status_on_client_status_delegate(BatchContextSafeHandle ctx); public delegate IntPtr grpcsharp_batch_context_recv_status_on_client_details_delegate(BatchContextSafeHandle ctx, out UIntPtr detailsLength); public delegate IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata_delegate(BatchContextSafeHandle ctx); public delegate int grpcsharp_batch_context_recv_close_on_server_cancelled_delegate(BatchContextSafeHandle ctx); public delegate void grpcsharp_batch_context_destroy_delegate(IntPtr ctx); public delegate RequestCallContextSafeHandle grpcsharp_request_call_context_create_delegate(); public delegate CallSafeHandle grpcsharp_request_call_context_call_delegate(RequestCallContextSafeHandle ctx); public delegate IntPtr grpcsharp_request_call_context_method_delegate(RequestCallContextSafeHandle ctx, out UIntPtr methodLength); public delegate IntPtr grpcsharp_request_call_context_host_delegate(RequestCallContextSafeHandle ctx, out UIntPtr hostLength); public delegate Timespec grpcsharp_request_call_context_deadline_delegate(RequestCallContextSafeHandle ctx); public delegate IntPtr grpcsharp_request_call_context_request_metadata_delegate(RequestCallContextSafeHandle ctx); public delegate void grpcsharp_request_call_context_destroy_delegate(IntPtr ctx); public delegate CallCredentialsSafeHandle grpcsharp_composite_call_credentials_create_delegate(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2); public delegate void grpcsharp_call_credentials_release_delegate(IntPtr credentials); public delegate CallError grpcsharp_call_cancel_delegate(CallSafeHandle call); public delegate CallError grpcsharp_call_cancel_with_status_delegate(CallSafeHandle call, StatusCode status, string description); public delegate CallError grpcsharp_call_start_unary_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); public delegate CallError grpcsharp_call_start_client_streaming_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); public delegate CallError grpcsharp_call_start_server_streaming_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); public delegate CallError grpcsharp_call_start_duplex_streaming_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); public delegate CallError grpcsharp_call_send_message_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, bool sendEmptyInitialMetadata); public delegate CallError grpcsharp_call_send_close_from_client_delegate(CallSafeHandle call, BatchContextSafeHandle ctx); public delegate CallError grpcsharp_call_send_status_from_server_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, byte[] statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata, byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags); public delegate CallError grpcsharp_call_recv_message_delegate(CallSafeHandle call, BatchContextSafeHandle ctx); public delegate CallError grpcsharp_call_recv_initial_metadata_delegate(CallSafeHandle call, BatchContextSafeHandle ctx); public delegate CallError grpcsharp_call_start_serverside_delegate(CallSafeHandle call, BatchContextSafeHandle ctx); public delegate CallError grpcsharp_call_send_initial_metadata_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); public delegate CallError grpcsharp_call_set_credentials_delegate(CallSafeHandle call, CallCredentialsSafeHandle credentials); public delegate CStringSafeHandle grpcsharp_call_get_peer_delegate(CallSafeHandle call); public delegate void grpcsharp_call_destroy_delegate(IntPtr call); public delegate ChannelArgsSafeHandle grpcsharp_channel_args_create_delegate(UIntPtr numArgs); public delegate void grpcsharp_channel_args_set_string_delegate(ChannelArgsSafeHandle args, UIntPtr index, string key, string value); public delegate void grpcsharp_channel_args_set_integer_delegate(ChannelArgsSafeHandle args, UIntPtr index, string key, int value); public delegate void grpcsharp_channel_args_destroy_delegate(IntPtr args); public delegate void grpcsharp_override_default_ssl_roots(string pemRootCerts); public delegate ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create_delegate(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey); public delegate ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create_delegate(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); public delegate void grpcsharp_channel_credentials_release_delegate(IntPtr credentials); public delegate ChannelSafeHandle grpcsharp_insecure_channel_create_delegate(string target, ChannelArgsSafeHandle channelArgs); public delegate ChannelSafeHandle grpcsharp_secure_channel_create_delegate(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs); public delegate CallSafeHandle grpcsharp_channel_create_call_delegate(ChannelSafeHandle channel, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline); public delegate ChannelState grpcsharp_channel_check_connectivity_state_delegate(ChannelSafeHandle channel, int tryToConnect); public delegate void grpcsharp_channel_watch_connectivity_state_delegate(ChannelSafeHandle channel, ChannelState lastObservedState, Timespec deadline, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); public delegate CStringSafeHandle grpcsharp_channel_get_target_delegate(ChannelSafeHandle call); public delegate void grpcsharp_channel_destroy_delegate(IntPtr channel); public delegate int grpcsharp_sizeof_grpc_event_delegate(); public delegate CompletionQueueSafeHandle grpcsharp_completion_queue_create_delegate(); public delegate void grpcsharp_completion_queue_shutdown_delegate(CompletionQueueSafeHandle cq); public delegate CompletionQueueEvent grpcsharp_completion_queue_next_delegate(CompletionQueueSafeHandle cq); public delegate CompletionQueueEvent grpcsharp_completion_queue_pluck_delegate(CompletionQueueSafeHandle cq, IntPtr tag); public delegate void grpcsharp_completion_queue_destroy_delegate(IntPtr cq); public delegate void gprsharp_free_delegate(IntPtr ptr); public delegate MetadataArraySafeHandle grpcsharp_metadata_array_create_delegate(UIntPtr capacity); public delegate void grpcsharp_metadata_array_add_delegate(MetadataArraySafeHandle array, string key, byte[] value, UIntPtr valueLength); public delegate UIntPtr grpcsharp_metadata_array_count_delegate(IntPtr metadataArray); public delegate IntPtr grpcsharp_metadata_array_get_key_delegate(IntPtr metadataArray, UIntPtr index, out UIntPtr keyLength); public delegate IntPtr grpcsharp_metadata_array_get_value_delegate(IntPtr metadataArray, UIntPtr index, out UIntPtr valueLength); public delegate void grpcsharp_metadata_array_destroy_full_delegate(IntPtr array); public delegate void grpcsharp_redirect_log_delegate(GprLogDelegate callback); public delegate CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin_delegate(NativeMetadataInterceptor interceptor); public delegate void grpcsharp_metadata_credentials_notify_from_plugin_delegate(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails); public delegate ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create_delegate(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, bool forceClientAuth); public delegate void grpcsharp_server_credentials_release_delegate(IntPtr credentials); public delegate ServerSafeHandle grpcsharp_server_create_delegate(ChannelArgsSafeHandle args); public delegate void grpcsharp_server_register_completion_queue_delegate(ServerSafeHandle server, CompletionQueueSafeHandle cq); public delegate int grpcsharp_server_add_insecure_http2_port_delegate(ServerSafeHandle server, string addr); public delegate int grpcsharp_server_add_secure_http2_port_delegate(ServerSafeHandle server, string addr, ServerCredentialsSafeHandle creds); public delegate void grpcsharp_server_start_delegate(ServerSafeHandle server); public delegate CallError grpcsharp_server_request_call_delegate(ServerSafeHandle server, CompletionQueueSafeHandle cq, RequestCallContextSafeHandle ctx); public delegate void grpcsharp_server_cancel_all_calls_delegate(ServerSafeHandle server); public delegate void grpcsharp_server_shutdown_and_notify_callback_delegate(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); public delegate void grpcsharp_server_destroy_delegate(IntPtr server); public delegate AuthContextSafeHandle grpcsharp_call_auth_context_delegate(CallSafeHandle call); public delegate IntPtr grpcsharp_auth_context_peer_identity_property_name_delegate(AuthContextSafeHandle authContext); // returns const char* public delegate AuthContextSafeHandle.NativeAuthPropertyIterator grpcsharp_auth_context_property_iterator_delegate(AuthContextSafeHandle authContext); public delegate IntPtr grpcsharp_auth_property_iterator_next_delegate(ref AuthContextSafeHandle.NativeAuthPropertyIterator iterator); // returns const auth_property* public delegate void grpcsharp_auth_context_release_delegate(IntPtr authContext); public delegate Timespec gprsharp_now_delegate(ClockType clockType); public delegate Timespec gprsharp_inf_future_delegate(ClockType clockType); public delegate Timespec gprsharp_inf_past_delegate(ClockType clockType); public delegate Timespec gprsharp_convert_clock_type_delegate(Timespec t, ClockType targetClock); public delegate int gprsharp_sizeof_timespec_delegate(); public delegate CallError grpcsharp_test_callback_delegate([MarshalAs(UnmanagedType.FunctionPtr)] OpCompletionDelegate callback); public delegate IntPtr grpcsharp_test_nop_delegate(IntPtr ptr); } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/PlatformApis.cs000066400000000000000000000105271310511640000230010ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Concurrent; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.InteropServices; using System.Threading; namespace Grpc.Core.Internal { /// /// Utility methods for detecting platform and architecture. /// internal static class PlatformApis { static readonly bool isLinux; static readonly bool isMacOSX; static readonly bool isWindows; static readonly bool isMono; static readonly bool isNetCore; static PlatformApis() { #if NETSTANDARD1_5 isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); isMacOSX = RuntimeInformation.IsOSPlatform(OSPlatform.OSX); isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); isNetCore = RuntimeInformation.FrameworkDescription.StartsWith(".NET Core"); #else var platform = Environment.OSVersion.Platform; // PlatformID.MacOSX is never returned, commonly used trick is to identify Mac is by using uname. isMacOSX = (platform == PlatformID.Unix && GetUname() == "Darwin"); isLinux = (platform == PlatformID.Unix && !isMacOSX); isWindows = (platform == PlatformID.Win32NT || platform == PlatformID.Win32S || platform == PlatformID.Win32Windows); isNetCore = false; #endif isMono = Type.GetType("Mono.Runtime") != null; } public static bool IsLinux { get { return isLinux; } } public static bool IsMacOSX { get { return isMacOSX; } } public static bool IsWindows { get { return isWindows; } } public static bool IsMono { get { return isMono; } } /// /// true if running on .NET Core (CoreCLR), false otherwise. /// public static bool IsNetCore { get { return isNetCore; } } public static bool Is64Bit { get { return IntPtr.Size == 8; } } [DllImport("libc")] static extern int uname(IntPtr buf); static string GetUname() { var buffer = Marshal.AllocHGlobal(8192); try { if (uname(buffer) == 0) { return Marshal.PtrToStringAnsi(buffer); } return string.Empty; } catch { return string.Empty; } finally { if (buffer != IntPtr.Zero) { Marshal.FreeHGlobal(buffer); } } } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/RequestCallContextSafeHandle.cs000066400000000000000000000065561310511640000261130ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.InteropServices; using Grpc.Core; namespace Grpc.Core.Internal { /// /// grpcsharp_request_call_context /// internal class RequestCallContextSafeHandle : SafeHandleZeroIsInvalid { static readonly NativeMethods Native = NativeMethods.Get(); private RequestCallContextSafeHandle() { } public static RequestCallContextSafeHandle Create() { return Native.grpcsharp_request_call_context_create(); } public IntPtr Handle { get { return handle; } } // Gets data of server_rpc_new completion. public ServerRpcNew GetServerRpcNew(Server server) { var call = Native.grpcsharp_request_call_context_call(this); UIntPtr methodLen; IntPtr methodPtr = Native.grpcsharp_request_call_context_method(this, out methodLen); var method = Marshal.PtrToStringAnsi(methodPtr, (int) methodLen.ToUInt32()); UIntPtr hostLen; IntPtr hostPtr = Native.grpcsharp_request_call_context_host(this, out hostLen); var host = Marshal.PtrToStringAnsi(hostPtr, (int) hostLen.ToUInt32()); var deadline = Native.grpcsharp_request_call_context_deadline(this); IntPtr metadataArrayPtr = Native.grpcsharp_request_call_context_request_metadata(this); var metadata = MetadataArraySafeHandle.ReadMetadataFromPtrUnsafe(metadataArrayPtr); return new ServerRpcNew(server, call, method, host, deadline, metadata); } protected override bool ReleaseHandle() { Native.grpcsharp_request_call_context_destroy(handle); return true; } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/SafeHandleZeroIsInvalid.cs000066400000000000000000000041071310511640000250320ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.InteropServices; namespace Grpc.Core.Internal { /// /// Safe handle to wrap native objects. /// internal abstract class SafeHandleZeroIsInvalid : System.Runtime.InteropServices.SafeHandle { public SafeHandleZeroIsInvalid() : base(IntPtr.Zero, true) { } public override bool IsInvalid { get { return handle == IntPtr.Zero; } } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs000066400000000000000000000330241310511640000237350ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core.Internal; using Grpc.Core.Logging; using Grpc.Core.Utils; namespace Grpc.Core.Internal { internal interface IServerCallHandler { Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq); } internal class UnaryServerCallHandler : IServerCallHandler where TRequest : class where TResponse : class { static readonly ILogger Logger = GrpcEnvironment.Logger.ForType>(); readonly Method method; readonly UnaryServerMethod handler; public UnaryServerCallHandler(Method method, UnaryServerMethod handler) { this.method = method; this.handler = handler; } public async Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq) { var asyncCall = new AsyncCallServer( method.ResponseMarshaller.Serializer, method.RequestMarshaller.Deserializer, newRpc.Server); asyncCall.Initialize(newRpc.Call, cq); var finishedTask = asyncCall.ServerSideCallAsync(); var requestStream = new ServerRequestStream(asyncCall); var responseStream = new ServerResponseStream(asyncCall); Status status; Tuple responseTuple = null; var context = HandlerUtils.NewContext(newRpc, responseStream, asyncCall.CancellationToken); try { GrpcPreconditions.CheckArgument(await requestStream.MoveNext().ConfigureAwait(false)); var request = requestStream.Current; var response = await handler(request, context).ConfigureAwait(false); status = context.Status; responseTuple = Tuple.Create(response, HandlerUtils.GetWriteFlags(context.WriteOptions)); } catch (Exception e) { if (!(e is RpcException)) { Logger.Warning(e, "Exception occured in handler."); } status = HandlerUtils.StatusFromException(e); } try { await asyncCall.SendStatusFromServerAsync(status, context.ResponseTrailers, responseTuple).ConfigureAwait(false); } catch (Exception) { asyncCall.Cancel(); throw; } await finishedTask.ConfigureAwait(false); } } internal class ServerStreamingServerCallHandler : IServerCallHandler where TRequest : class where TResponse : class { static readonly ILogger Logger = GrpcEnvironment.Logger.ForType>(); readonly Method method; readonly ServerStreamingServerMethod handler; public ServerStreamingServerCallHandler(Method method, ServerStreamingServerMethod handler) { this.method = method; this.handler = handler; } public async Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq) { var asyncCall = new AsyncCallServer( method.ResponseMarshaller.Serializer, method.RequestMarshaller.Deserializer, newRpc.Server); asyncCall.Initialize(newRpc.Call, cq); var finishedTask = asyncCall.ServerSideCallAsync(); var requestStream = new ServerRequestStream(asyncCall); var responseStream = new ServerResponseStream(asyncCall); Status status; var context = HandlerUtils.NewContext(newRpc, responseStream, asyncCall.CancellationToken); try { GrpcPreconditions.CheckArgument(await requestStream.MoveNext().ConfigureAwait(false)); var request = requestStream.Current; await handler(request, responseStream, context).ConfigureAwait(false); status = context.Status; } catch (Exception e) { if (!(e is RpcException)) { Logger.Warning(e, "Exception occured in handler."); } status = HandlerUtils.StatusFromException(e); } try { await asyncCall.SendStatusFromServerAsync(status, context.ResponseTrailers, null).ConfigureAwait(false); } catch (Exception) { asyncCall.Cancel(); throw; } await finishedTask.ConfigureAwait(false); } } internal class ClientStreamingServerCallHandler : IServerCallHandler where TRequest : class where TResponse : class { static readonly ILogger Logger = GrpcEnvironment.Logger.ForType>(); readonly Method method; readonly ClientStreamingServerMethod handler; public ClientStreamingServerCallHandler(Method method, ClientStreamingServerMethod handler) { this.method = method; this.handler = handler; } public async Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq) { var asyncCall = new AsyncCallServer( method.ResponseMarshaller.Serializer, method.RequestMarshaller.Deserializer, newRpc.Server); asyncCall.Initialize(newRpc.Call, cq); var finishedTask = asyncCall.ServerSideCallAsync(); var requestStream = new ServerRequestStream(asyncCall); var responseStream = new ServerResponseStream(asyncCall); Status status; Tuple responseTuple = null; var context = HandlerUtils.NewContext(newRpc, responseStream, asyncCall.CancellationToken); try { var response = await handler(requestStream, context).ConfigureAwait(false); status = context.Status; responseTuple = Tuple.Create(response, HandlerUtils.GetWriteFlags(context.WriteOptions)); } catch (Exception e) { if (!(e is RpcException)) { Logger.Warning(e, "Exception occured in handler."); } status = HandlerUtils.StatusFromException(e); } try { await asyncCall.SendStatusFromServerAsync(status, context.ResponseTrailers, responseTuple).ConfigureAwait(false); } catch (Exception) { asyncCall.Cancel(); throw; } await finishedTask.ConfigureAwait(false); } } internal class DuplexStreamingServerCallHandler : IServerCallHandler where TRequest : class where TResponse : class { static readonly ILogger Logger = GrpcEnvironment.Logger.ForType>(); readonly Method method; readonly DuplexStreamingServerMethod handler; public DuplexStreamingServerCallHandler(Method method, DuplexStreamingServerMethod handler) { this.method = method; this.handler = handler; } public async Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq) { var asyncCall = new AsyncCallServer( method.ResponseMarshaller.Serializer, method.RequestMarshaller.Deserializer, newRpc.Server); asyncCall.Initialize(newRpc.Call, cq); var finishedTask = asyncCall.ServerSideCallAsync(); var requestStream = new ServerRequestStream(asyncCall); var responseStream = new ServerResponseStream(asyncCall); Status status; var context = HandlerUtils.NewContext(newRpc, responseStream, asyncCall.CancellationToken); try { await handler(requestStream, responseStream, context).ConfigureAwait(false); status = context.Status; } catch (Exception e) { if (!(e is RpcException)) { Logger.Warning(e, "Exception occured in handler."); } status = HandlerUtils.StatusFromException(e); } try { await asyncCall.SendStatusFromServerAsync(status, context.ResponseTrailers, null).ConfigureAwait(false); } catch (Exception) { asyncCall.Cancel(); throw; } await finishedTask.ConfigureAwait(false); } } internal class UnimplementedMethodCallHandler : IServerCallHandler { public static readonly UnimplementedMethodCallHandler Instance = new UnimplementedMethodCallHandler(); DuplexStreamingServerCallHandler callHandlerImpl; public UnimplementedMethodCallHandler() { var marshaller = new Marshaller((payload) => payload, (payload) => payload); var method = new Method(MethodType.DuplexStreaming, "", "", marshaller, marshaller); this.callHandlerImpl = new DuplexStreamingServerCallHandler(method, new DuplexStreamingServerMethod(UnimplementedMethod)); } /// /// Handler used for unimplemented method. /// private Task UnimplementedMethod(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext ctx) { ctx.Status = new Status(StatusCode.Unimplemented, ""); return TaskUtils.CompletedTask; } public Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq) { return callHandlerImpl.HandleCall(newRpc, cq); } } internal static class HandlerUtils { public static Status StatusFromException(Exception e) { var rpcException = e as RpcException; if (rpcException != null) { // use the status thrown by handler. return rpcException.Status; } return new Status(StatusCode.Unknown, "Exception was thrown by handler."); } public static WriteFlags GetWriteFlags(WriteOptions writeOptions) { return writeOptions != null ? writeOptions.Flags : default(WriteFlags); } public static ServerCallContext NewContext(ServerRpcNew newRpc, ServerResponseStream serverResponseStream, CancellationToken cancellationToken) where TRequest : class where TResponse : class { DateTime realtimeDeadline = newRpc.Deadline.ToClockType(ClockType.Realtime).ToDateTime(); return new ServerCallContext(newRpc.Call, newRpc.Method, newRpc.Host, realtimeDeadline, newRpc.RequestMetadata, cancellationToken, serverResponseStream.WriteResponseHeadersAsync, serverResponseStream); } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/ServerCalls.cs000066400000000000000000000061751310511640000226310ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Threading; using System.Threading.Tasks; using Grpc.Core; namespace Grpc.Core.Internal { internal static class ServerCalls { public static IServerCallHandler UnaryCall(Method method, UnaryServerMethod handler) where TRequest : class where TResponse : class { return new UnaryServerCallHandler(method, handler); } public static IServerCallHandler ClientStreamingCall(Method method, ClientStreamingServerMethod handler) where TRequest : class where TResponse : class { return new ClientStreamingServerCallHandler(method, handler); } public static IServerCallHandler ServerStreamingCall(Method method, ServerStreamingServerMethod handler) where TRequest : class where TResponse : class { return new ServerStreamingServerCallHandler(method, handler); } public static IServerCallHandler DuplexStreamingCall(Method method, DuplexStreamingServerMethod handler) where TRequest : class where TResponse : class { return new DuplexStreamingServerCallHandler(method, handler); } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs000066400000000000000000000056411310511640000257400ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Grpc.Core.Utils; namespace Grpc.Core.Internal { /// /// grpc_server_credentials from grpc/grpc_security.h /// internal class ServerCredentialsSafeHandle : SafeHandleZeroIsInvalid { static readonly NativeMethods Native = NativeMethods.Get(); private ServerCredentialsSafeHandle() { } public static ServerCredentialsSafeHandle CreateSslCredentials(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, bool forceClientAuth) { GrpcPreconditions.CheckArgument(keyCertPairCertChainArray.Length == keyCertPairPrivateKeyArray.Length); return Native.grpcsharp_ssl_server_credentials_create(pemRootCerts, keyCertPairCertChainArray, keyCertPairPrivateKeyArray, new UIntPtr((ulong)keyCertPairCertChainArray.Length), forceClientAuth); } protected override bool ReleaseHandle() { Native.grpcsharp_server_credentials_release(handle); return true; } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/ServerRequestStream.cs000066400000000000000000000056301310511640000243720ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; namespace Grpc.Core.Internal { internal class ServerRequestStream : IAsyncStreamReader where TRequest : class where TResponse : class { readonly AsyncCallServer call; TRequest current; public ServerRequestStream(AsyncCallServer call) { this.call = call; } public TRequest Current { get { if (current == null) { throw new InvalidOperationException("No current element is available."); } return current; } } public async Task MoveNext(CancellationToken token) { if (token != CancellationToken.None) { throw new InvalidOperationException("Cancellation of individual reads is not supported."); } var result = await call.ReadMessageAsync().ConfigureAwait(false); this.current = result; return result != null; } public void Dispose() { // TODO(jtattermusch): implement the semantics of stream disposal. } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/ServerResponseStream.cs000066400000000000000000000055761310511640000245510ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Threading.Tasks; using Grpc.Core.Internal; namespace Grpc.Core.Internal { /// /// Writes responses asynchronously to an underlying AsyncCallServer object. /// internal class ServerResponseStream : IServerStreamWriter, IHasWriteOptions where TRequest : class where TResponse : class { readonly AsyncCallServer call; WriteOptions writeOptions; public ServerResponseStream(AsyncCallServer call) { this.call = call; } public Task WriteAsync(TResponse message) { return call.SendMessageAsync(message, GetWriteFlags()); } public Task WriteResponseHeadersAsync(Metadata responseHeaders) { return call.SendInitialMetadataAsync(responseHeaders); } public WriteOptions WriteOptions { get { return writeOptions; } set { writeOptions = value; } } private WriteFlags GetWriteFlags() { var options = writeOptions; return options != null ? options.Flags : default(WriteFlags); } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/ServerRpcNew.cs000066400000000000000000000061671310511640000227720ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using Grpc.Core; namespace Grpc.Core.Internal { /// /// Details of a newly received RPC. /// internal struct ServerRpcNew { readonly Server server; readonly CallSafeHandle call; readonly string method; readonly string host; readonly Timespec deadline; readonly Metadata requestMetadata; public ServerRpcNew(Server server, CallSafeHandle call, string method, string host, Timespec deadline, Metadata requestMetadata) { this.server = server; this.call = call; this.method = method; this.host = host; this.deadline = deadline; this.requestMetadata = requestMetadata; } public Server Server { get { return this.server; } } public CallSafeHandle Call { get { return this.call; } } public string Method { get { return this.method; } } public string Host { get { return this.host; } } public Timespec Deadline { get { return this.deadline; } } public Metadata RequestMetadata { get { return this.requestMetadata; } } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs000066400000000000000000000104021310511640000235510ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion namespace Grpc.Core.Internal { /// /// grpc_server from grpc/grpc.h /// internal sealed class ServerSafeHandle : SafeHandleZeroIsInvalid { static readonly NativeMethods Native = NativeMethods.Get(); private ServerSafeHandle() { } public static ServerSafeHandle NewServer(ChannelArgsSafeHandle args) { // Increment reference count for the native gRPC environment to make sure we don't do grpc_shutdown() before destroying the server handle. // Doing so would make object finalizer crash if we end up abandoning the handle. GrpcEnvironment.GrpcNativeInit(); return Native.grpcsharp_server_create(args); } public void RegisterCompletionQueue(CompletionQueueSafeHandle cq) { using (cq.NewScope()) { Native.grpcsharp_server_register_completion_queue(this, cq); } } public int AddInsecurePort(string addr) { return Native.grpcsharp_server_add_insecure_http2_port(this, addr); } public int AddSecurePort(string addr, ServerCredentialsSafeHandle credentials) { return Native.grpcsharp_server_add_secure_http2_port(this, addr, credentials); } public void Start() { Native.grpcsharp_server_start(this); } public void ShutdownAndNotify(BatchCompletionDelegate callback, CompletionQueueSafeHandle completionQueue) { using (completionQueue.NewScope()) { var ctx = BatchContextSafeHandle.Create(); completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, callback); Native.grpcsharp_server_shutdown_and_notify_callback(this, completionQueue, ctx); } } public void RequestCall(RequestCallCompletionDelegate callback, CompletionQueueSafeHandle completionQueue) { using (completionQueue.NewScope()) { var ctx = RequestCallContextSafeHandle.Create(); completionQueue.CompletionRegistry.RegisterRequestCallCompletion(ctx, callback); Native.grpcsharp_server_request_call(this, completionQueue, ctx).CheckOk(); } } protected override bool ReleaseHandle() { Native.grpcsharp_server_destroy(handle); GrpcEnvironment.GrpcNativeShutdown(); return true; } // Only to be called after ShutdownAndNotify. public void CancelAllCalls() { Native.grpcsharp_server_cancel_all_calls(this); } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/Timespec.cs000066400000000000000000000215021310511640000221440ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.InteropServices; using System.Threading; using Grpc.Core.Utils; namespace Grpc.Core.Internal { /// /// gpr_timespec from grpc/support/time.h /// [StructLayout(LayoutKind.Sequential)] internal struct Timespec { const long NanosPerSecond = 1000 * 1000 * 1000; const long NanosPerTick = 100; const long TicksPerSecond = NanosPerSecond / NanosPerTick; static readonly NativeMethods Native = NativeMethods.Get(); static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); public Timespec(long tv_sec, int tv_nsec) : this(tv_sec, tv_nsec, ClockType.Realtime) { } public Timespec(long tv_sec, int tv_nsec, ClockType clock_type) { this.tv_sec = tv_sec; this.tv_nsec = tv_nsec; this.clock_type = clock_type; } private long tv_sec; private int tv_nsec; private ClockType clock_type; /// /// Timespec a long time in the future. /// public static Timespec InfFuture { get { return new Timespec(long.MaxValue, 0, ClockType.Realtime); } } /// /// Timespec a long time in the past. /// public static Timespec InfPast { get { return new Timespec(long.MinValue, 0, ClockType.Realtime); } } /// /// Return Timespec representing the current time. /// public static Timespec Now { get { return Native.gprsharp_now(ClockType.Realtime); } } /// /// Seconds since unix epoch. /// public long TimevalSeconds { get { return tv_sec; } } /// /// The nanoseconds part of timeval. /// public int TimevalNanos { get { return tv_nsec; } } /// /// Converts the timespec to desired clock type. /// public Timespec ToClockType(ClockType targetClock) { return Native.gprsharp_convert_clock_type(this, targetClock); } /// /// Converts Timespec to DateTime. /// Timespec needs to be of type GPRClockType.Realtime and needs to represent a legal value. /// DateTime has lower resolution (100ns), so rounding can occurs. /// Value are always rounded up to the nearest DateTime value in the future. /// /// For Timespec.InfFuture or if timespec is after the largest representable DateTime, DateTime.MaxValue is returned. /// For Timespec.InfPast or if timespec is before the lowest representable DateTime, DateTime.MinValue is returned. /// /// Unless DateTime.MaxValue or DateTime.MinValue is returned, the resulting DateTime is always in UTC /// (DateTimeKind.Utc) /// public DateTime ToDateTime() { GrpcPreconditions.CheckState(tv_nsec >= 0 && tv_nsec < NanosPerSecond); GrpcPreconditions.CheckState(clock_type == ClockType.Realtime); // fast path for InfFuture if (this.Equals(InfFuture)) { return DateTime.MaxValue; } // fast path for InfPast if (this.Equals(InfPast)) { return DateTime.MinValue; } try { // convert nanos to ticks, round up to the nearest tick long ticksFromNanos = tv_nsec / NanosPerTick + ((tv_nsec % NanosPerTick != 0) ? 1 : 0); long ticksTotal = checked(tv_sec * TicksPerSecond + ticksFromNanos); return UnixEpoch.AddTicks(ticksTotal); } catch (OverflowException) { // ticks out of long range return tv_sec > 0 ? DateTime.MaxValue : DateTime.MinValue; } catch (ArgumentOutOfRangeException) { // resulting date time would be larger than MaxValue return tv_sec > 0 ? DateTime.MaxValue : DateTime.MinValue; } } /// /// Creates DateTime to Timespec. /// DateTime has to be in UTC (DateTimeKind.Utc) unless it's DateTime.MaxValue or DateTime.MinValue. /// For DateTime.MaxValue of date time after the largest representable Timespec, Timespec.InfFuture is returned. /// For DateTime.MinValue of date time before the lowest representable Timespec, Timespec.InfPast is returned. /// /// The date time. /// Date time. public static Timespec FromDateTime(DateTime dateTime) { if (dateTime == DateTime.MaxValue) { return Timespec.InfFuture; } if (dateTime == DateTime.MinValue) { return Timespec.InfPast; } GrpcPreconditions.CheckArgument(dateTime.Kind == DateTimeKind.Utc, "dateTime needs of kind DateTimeKind.Utc or be equal to DateTime.MaxValue or DateTime.MinValue."); try { TimeSpan timeSpan = dateTime - UnixEpoch; long ticks = timeSpan.Ticks; long seconds = ticks / TicksPerSecond; int nanos = (int)((ticks % TicksPerSecond) * NanosPerTick); if (nanos < 0) { // correct the result based on C# modulo semantics for negative dividend seconds--; nanos += (int)NanosPerSecond; } return new Timespec(seconds, nanos); } catch (ArgumentOutOfRangeException) { return dateTime > UnixEpoch ? Timespec.InfFuture : Timespec.InfPast; } } /// /// Gets current timestamp using GPRClockType.Precise. /// Only available internally because core needs to be compiled with /// GRPC_TIMERS_RDTSC support for this to use RDTSC. /// internal static Timespec PreciseNow { get { return Native.gprsharp_now(ClockType.Precise); } } // for tests only internal static int NativeSize { get { return Native.gprsharp_sizeof_timespec(); } } // for tests only internal static Timespec NativeInfFuture { get { return Native.gprsharp_inf_future(ClockType.Realtime); } } // for tests only public static Timespec NativeInfPast { get { return Native.gprsharp_inf_past(ClockType.Realtime); } } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/UnimplementedCallInvoker.cs000066400000000000000000000062401310511640000253350ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Utils; namespace Grpc.Core.Internal { /// /// Call invoker that throws NotImplementedException for all requests. /// internal class UnimplementedCallInvoker : CallInvoker { public UnimplementedCallInvoker() { } public override TResponse BlockingUnaryCall(Method method, string host, CallOptions options, TRequest request) { throw new NotImplementedException(); } public override AsyncUnaryCall AsyncUnaryCall(Method method, string host, CallOptions options, TRequest request) { throw new NotImplementedException(); } public override AsyncServerStreamingCall AsyncServerStreamingCall(Method method, string host, CallOptions options, TRequest request) { throw new NotImplementedException(); } public override AsyncClientStreamingCall AsyncClientStreamingCall(Method method, string host, CallOptions options) { throw new NotImplementedException(); } public override AsyncDuplexStreamingCall AsyncDuplexStreamingCall(Method method, string host, CallOptions options) { throw new NotImplementedException(); } } } grpc-1.3.2/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs000066400000000000000000000227041310511640000236240ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.IO; using System.Reflection; using System.Runtime.InteropServices; using System.Threading; using Grpc.Core.Logging; using Grpc.Core.Utils; namespace Grpc.Core.Internal { /// /// Represents a dynamically loaded unmanaged library in a (partially) platform independent manner. /// First, the native library is loaded using dlopen (on Unix systems) or using LoadLibrary (on Windows). /// dlsym or GetProcAddress are then used to obtain symbol addresses. Marshal.GetDelegateForFunctionPointer /// transforms the addresses into delegates to native methods. /// See http://stackoverflow.com/questions/13461989/p-invoke-to-dynamically-loaded-library-on-mono. /// internal class UnmanagedLibrary { static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); // flags for dlopen const int RTLD_LAZY = 1; const int RTLD_GLOBAL = 8; readonly string libraryPath; readonly IntPtr handle; public UnmanagedLibrary(string[] libraryPathAlternatives) { this.libraryPath = FirstValidLibraryPath(libraryPathAlternatives); Logger.Debug("Attempting to load native library \"{0}\"", this.libraryPath); this.handle = PlatformSpecificLoadLibrary(this.libraryPath); if (this.handle == IntPtr.Zero) { throw new IOException(string.Format("Error loading native library \"{0}\"", this.libraryPath)); } } /// /// Loads symbol in a platform specific way. /// /// /// public IntPtr LoadSymbol(string symbolName) { if (PlatformApis.IsWindows) { // See http://stackoverflow.com/questions/10473310 for background on this. if (PlatformApis.Is64Bit) { return Windows.GetProcAddress(this.handle, symbolName); } else { // Yes, we could potentially predict the size... but it's a lot simpler to just try // all the candidates. Most functions have a suffix of @0, @4 or @8 so we won't be trying // many options - and if it takes a little bit longer to fail if we've really got the wrong // library, that's not a big problem. This is only called once per function in the native library. symbolName = "_" + symbolName + "@"; for (int stackSize = 0; stackSize < 128; stackSize += 4) { IntPtr candidate = Windows.GetProcAddress(this.handle, symbolName + stackSize); if (candidate != IntPtr.Zero) { return candidate; } } // Fail. return IntPtr.Zero; } } if (PlatformApis.IsLinux) { if (PlatformApis.IsMono) { return Mono.dlsym(this.handle, symbolName); } if (PlatformApis.IsNetCore) { return CoreCLR.dlsym(this.handle, symbolName); } return Linux.dlsym(this.handle, symbolName); } if (PlatformApis.IsMacOSX) { return MacOSX.dlsym(this.handle, symbolName); } throw new InvalidOperationException("Unsupported platform."); } public T GetNativeMethodDelegate(string methodName) where T : class { var ptr = LoadSymbol(methodName); if (ptr == IntPtr.Zero) { throw new MissingMethodException(string.Format("The native method \"{0}\" does not exist", methodName)); } #if NETSTANDARD1_5 return Marshal.GetDelegateForFunctionPointer(ptr); // non-generic version is obsolete #else return Marshal.GetDelegateForFunctionPointer(ptr, typeof(T)) as T; // generic version not available in .NET45 #endif } /// /// Loads library in a platform specific way. /// private static IntPtr PlatformSpecificLoadLibrary(string libraryPath) { if (PlatformApis.IsWindows) { return Windows.LoadLibrary(libraryPath); } if (PlatformApis.IsLinux) { if (PlatformApis.IsMono) { return Mono.dlopen(libraryPath, RTLD_GLOBAL + RTLD_LAZY); } if (PlatformApis.IsNetCore) { return CoreCLR.dlopen(libraryPath, RTLD_GLOBAL + RTLD_LAZY); } return Linux.dlopen(libraryPath, RTLD_GLOBAL + RTLD_LAZY); } if (PlatformApis.IsMacOSX) { return MacOSX.dlopen(libraryPath, RTLD_GLOBAL + RTLD_LAZY); } throw new InvalidOperationException("Unsupported platform."); } private static string FirstValidLibraryPath(string[] libraryPathAlternatives) { GrpcPreconditions.CheckArgument(libraryPathAlternatives.Length > 0, "libraryPathAlternatives cannot be empty."); foreach (var path in libraryPathAlternatives) { if (File.Exists(path)) { return path; } } throw new FileNotFoundException( String.Format("Error loading native library. Not found in any of the possible locations: {0}", string.Join(",", libraryPathAlternatives))); } private static class Windows { [DllImport("kernel32.dll")] internal static extern IntPtr LoadLibrary(string filename); [DllImport("kernel32.dll")] internal static extern IntPtr GetProcAddress(IntPtr hModule, string procName); } private static class Linux { [DllImport("libdl.so")] internal static extern IntPtr dlopen(string filename, int flags); [DllImport("libdl.so")] internal static extern IntPtr dlsym(IntPtr handle, string symbol); } private static class MacOSX { [DllImport("libSystem.dylib")] internal static extern IntPtr dlopen(string filename, int flags); [DllImport("libSystem.dylib")] internal static extern IntPtr dlsym(IntPtr handle, string symbol); } /// /// On Linux systems, using using dlopen and dlsym results in /// DllNotFoundException("libdl.so not found") if libc6-dev /// is not installed. As a workaround, we load symbols for /// dlopen and dlsym from the current process as on Linux /// Mono sure is linked against these symbols. /// private static class Mono { [DllImport("__Internal")] internal static extern IntPtr dlopen(string filename, int flags); [DllImport("__Internal")] internal static extern IntPtr dlsym(IntPtr handle, string symbol); } /// /// Similarly as for Mono on Linux, we load symbols for /// dlopen and dlsym from the "libcoreclr.so", /// to avoid the dependency on libc-dev Linux. /// private static class CoreCLR { [DllImport("libcoreclr.so")] internal static extern IntPtr dlopen(string filename, int flags); [DllImport("libcoreclr.so")] internal static extern IntPtr dlsym(IntPtr handle, string symbol); } } } grpc-1.3.2/src/csharp/Grpc.Core/KeyCertificatePair.cs000066400000000000000000000056061310511640000223350ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using Grpc.Core.Internal; using Grpc.Core.Utils; namespace Grpc.Core { /// /// Key certificate pair (in PEM encoding). /// public sealed class KeyCertificatePair { readonly string certificateChain; readonly string privateKey; /// /// Creates a new certificate chain - private key pair. /// /// PEM encoded certificate chain. /// PEM encoded private key. public KeyCertificatePair(string certificateChain, string privateKey) { this.certificateChain = GrpcPreconditions.CheckNotNull(certificateChain, "certificateChain"); this.privateKey = GrpcPreconditions.CheckNotNull(privateKey, "privateKey"); } /// /// PEM encoded certificate chain. /// public string CertificateChain { get { return certificateChain; } } /// /// PEM encoded private key. /// public string PrivateKey { get { return privateKey; } } } } grpc-1.3.2/src/csharp/Grpc.Core/Logging/000077500000000000000000000000001310511640000176565ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Core/Logging/ConsoleLogger.cs000066400000000000000000000047401310511640000227540ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Globalization; namespace Grpc.Core.Logging { /// Logger that logs to System.Console. public class ConsoleLogger : TextWriterLogger { /// Creates a console logger not associated to any specific type. public ConsoleLogger() : this(null) { } /// Creates a console logger that logs messsage specific for given type. private ConsoleLogger(Type forType) : base(() => Console.Error, forType) { } /// /// Returns a logger associated with the specified type. /// public override ILogger ForType() { if (typeof(T) == AssociatedType) { return this; } return new ConsoleLogger(typeof(T)); } } } grpc-1.3.2/src/csharp/Grpc.Core/Logging/ILogger.cs000066400000000000000000000061621310511640000215420ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; namespace Grpc.Core.Logging { /// For logging messages. public interface ILogger { /// Returns a logger associated with the specified type. ILogger ForType(); /// Logs a message with severity Debug. void Debug(string message); /// Logs a formatted message with severity Debug. void Debug(string format, params object[] formatArgs); /// Logs a message with severity Info. void Info(string message); /// Logs a formatted message with severity Info. void Info(string format, params object[] formatArgs); /// Logs a message with severity Warning. void Warning(string message); /// Logs a formatted message with severity Warning. void Warning(string format, params object[] formatArgs); /// Logs a message and an associated exception with severity Warning. void Warning(Exception exception, string message); /// Logs a message with severity Error. void Error(string message); /// Logs a formatted message with severity Error. void Error(string format, params object[] formatArgs); /// Logs a message and an associated exception with severity Error. void Error(Exception exception, string message); } } grpc-1.3.2/src/csharp/Grpc.Core/Logging/LogLevel.cs000066400000000000000000000041261310511640000217210ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; namespace Grpc.Core.Logging { /// Standard logging levels. public enum LogLevel { /// /// Debug severity. /// Debug = 0, /// /// Info severity. /// Info, /// /// Warning severity. /// Warning, /// /// Error severity. /// Error } } grpc-1.3.2/src/csharp/Grpc.Core/Logging/LogLevelFilterLogger.cs000066400000000000000000000126001310511640000242230ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Globalization; using System.IO; using Grpc.Core.Utils; namespace Grpc.Core.Logging { /// Logger that filters out messages below certain log level. public class LogLevelFilterLogger : ILogger { readonly ILogger innerLogger; readonly LogLevel logLevel; /// /// Creates and instance of LogLevelFilter. /// public LogLevelFilterLogger(ILogger logger, LogLevel logLevel) { this.innerLogger = GrpcPreconditions.CheckNotNull(logger); this.logLevel = logLevel; } /// /// Returns a logger associated with the specified type. /// public virtual ILogger ForType() { var newInnerLogger = innerLogger.ForType(); if (object.ReferenceEquals(this.innerLogger, newInnerLogger)) { return this; } return new LogLevelFilterLogger(newInnerLogger, logLevel); } /// Logs a message with severity Debug. public void Debug(string message) { if (logLevel <= LogLevel.Debug) { innerLogger.Debug(message); } } /// Logs a formatted message with severity Debug. public void Debug(string format, params object[] formatArgs) { if (logLevel <= LogLevel.Debug) { innerLogger.Debug(format, formatArgs); } } /// Logs a message with severity Info. public void Info(string message) { if (logLevel <= LogLevel.Info) { innerLogger.Info(message); } } /// Logs a formatted message with severity Info. public void Info(string format, params object[] formatArgs) { if (logLevel <= LogLevel.Info) { innerLogger.Info(format, formatArgs); } } /// Logs a message with severity Warning. public void Warning(string message) { if (logLevel <= LogLevel.Warning) { innerLogger.Warning(message); } } /// Logs a formatted message with severity Warning. public void Warning(string format, params object[] formatArgs) { if (logLevel <= LogLevel.Warning) { innerLogger.Warning(format, formatArgs); } } /// Logs a message and an associated exception with severity Warning. public void Warning(Exception exception, string message) { if (logLevel <= LogLevel.Warning) { innerLogger.Warning(exception, message); } } /// Logs a message with severity Error. public void Error(string message) { if (logLevel <= LogLevel.Error) { innerLogger.Error(message); } } /// Logs a formatted message with severity Error. public void Error(string format, params object[] formatArgs) { if (logLevel <= LogLevel.Error) { innerLogger.Error(format, formatArgs); } } /// Logs a message and an associated exception with severity Error. public void Error(Exception exception, string message) { if (logLevel <= LogLevel.Error) { innerLogger.Error(exception, message); } } } } grpc-1.3.2/src/csharp/Grpc.Core/Logging/NullLogger.cs000066400000000000000000000077751310511640000222770ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; namespace Grpc.Core.Logging { /// /// Logger which doesn't log any information anywhere. /// public sealed class NullLogger : ILogger { /// /// As with all logging calls on this logger, this method is a no-op. /// public void Debug(string message) { } /// /// As with all logging calls on this logger, this method is a no-op. /// public void Debug(string format, params object[] formatArgs) { } /// /// As with all logging calls on this logger, this method is a no-op. /// public void Error(string message) { } /// /// As with all logging calls on this logger, this method is a no-op. /// public void Error(Exception exception, string message) { } /// /// As with all logging calls on this logger, this method is a no-op. /// public void Error(string format, params object[] formatArgs) { } /// /// Returns a reference to the instance on which the method is called, as /// instances aren't associated with specific types. /// public ILogger ForType() { return this; } /// /// As with all logging calls on this logger, this method is a no-op. /// public void Info(string message) { } /// /// As with all logging calls on this logger, this method is a no-op. /// public void Info(string format, params object[] formatArgs) { } /// /// As with all logging calls on this logger, this method is a no-op. /// public void Warning(string message) { } /// /// As with all logging calls on this logger, this method is a no-op. /// public void Warning(Exception exception, string message) { } /// /// As with all logging calls on this logger, this method is a no-op. /// public void Warning(string format, params object[] formatArgs) { } } } grpc-1.3.2/src/csharp/Grpc.Core/Logging/TextWriterLogger.cs000066400000000000000000000146701310511640000234760ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Globalization; using System.IO; using Grpc.Core.Utils; namespace Grpc.Core.Logging { /// Logger that logs to an arbitrary System.IO.TextWriter. public class TextWriterLogger : ILogger { // Format similar enough to C core log format except nanosecond precision is not supported. const string DateTimeFormatString = "MMdd HH:mm:ss.ffffff"; readonly Func textWriterProvider; readonly Type forType; readonly string forTypeString; /// /// Creates a console logger not associated to any specific type and writes to given System.IO.TextWriter. /// User is responsible for providing an instance of TextWriter that is thread-safe. /// public TextWriterLogger(TextWriter textWriter) : this(() => textWriter) { GrpcPreconditions.CheckNotNull(textWriter); } /// /// Creates a console logger not associated to any specific type and writes to a System.IO.TextWriter obtained from given provider. /// User is responsible for providing an instance of TextWriter that is thread-safe. /// public TextWriterLogger(Func textWriterProvider) : this(textWriterProvider, null) { } /// Creates a console logger that logs messsage specific for given type. protected TextWriterLogger(Func textWriterProvider, Type forType) { this.textWriterProvider = GrpcPreconditions.CheckNotNull(textWriterProvider); this.forType = forType; if (forType != null) { var namespaceStr = forType.Namespace ?? ""; if (namespaceStr.Length > 0) { namespaceStr += "."; } this.forTypeString = namespaceStr + forType.Name + " "; } else { this.forTypeString = ""; } } /// /// Returns a logger associated with the specified type. /// public virtual ILogger ForType() { if (typeof(T) == forType) { return this; } return new TextWriterLogger(this.textWriterProvider, typeof(T)); } /// Logs a message with severity Debug. public void Debug(string message) { Log("D", message); } /// Logs a formatted message with severity Debug. public void Debug(string format, params object[] formatArgs) { Debug(string.Format(format, formatArgs)); } /// Logs a message with severity Info. public void Info(string message) { Log("I", message); } /// Logs a formatted message with severity Info. public void Info(string format, params object[] formatArgs) { Info(string.Format(format, formatArgs)); } /// Logs a message with severity Warning. public void Warning(string message) { Log("W", message); } /// Logs a formatted message with severity Warning. public void Warning(string format, params object[] formatArgs) { Warning(string.Format(format, formatArgs)); } /// Logs a message and an associated exception with severity Warning. public void Warning(Exception exception, string message) { Warning(message + " " + exception); } /// Logs a message with severity Error. public void Error(string message) { Log("E", message); } /// Logs a formatted message with severity Error. public void Error(string format, params object[] formatArgs) { Error(string.Format(format, formatArgs)); } /// Logs a message and an associated exception with severity Error. public void Error(Exception exception, string message) { Error(message + " " + exception); } /// Gets the type associated with this logger. protected Type AssociatedType { get { return forType; } } private void Log(string severityString, string message) { textWriterProvider().WriteLine("{0}{1} {2}{3}", severityString, DateTime.Now.ToString(DateTimeFormatString, CultureInfo.InvariantCulture), forTypeString, message); } } } grpc-1.3.2/src/csharp/Grpc.Core/Marshaller.cs000066400000000000000000000073511310511640000207170ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using Grpc.Core.Utils; namespace Grpc.Core { /// /// Encapsulates the logic for serializing and deserializing messages. /// public class Marshaller { readonly Func serializer; readonly Func deserializer; /// /// Initializes a new marshaller. /// /// Function that will be used to serialize messages. /// Function that will be used to deserialize messages. public Marshaller(Func serializer, Func deserializer) { this.serializer = GrpcPreconditions.CheckNotNull(serializer, "serializer"); this.deserializer = GrpcPreconditions.CheckNotNull(deserializer, "deserializer"); } /// /// Gets the serializer function. /// public Func Serializer { get { return this.serializer; } } /// /// Gets the deserializer function. /// public Func Deserializer { get { return this.deserializer; } } } /// /// Utilities for creating marshallers. /// public static class Marshallers { /// /// Creates a marshaller from specified serializer and deserializer. /// public static Marshaller Create(Func serializer, Func deserializer) { return new Marshaller(serializer, deserializer); } /// /// Returns a marshaller for string type. This is useful for testing. /// public static Marshaller StringMarshaller { get { return new Marshaller(System.Text.Encoding.UTF8.GetBytes, System.Text.Encoding.UTF8.GetString); } } } } grpc-1.3.2/src/csharp/Grpc.Core/Metadata.cs000066400000000000000000000333061310511640000203440ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; using Grpc.Core.Internal; using Grpc.Core.Utils; namespace Grpc.Core { /// /// A collection of metadata entries that can be exchanged during a call. /// gRPC supports these types of metadata: /// /// Request headersare sent by the client at the beginning of a remote call before any request messages are sent. /// Response headersare sent by the server at the beginning of a remote call handler before any response messages are sent. /// Response trailersare sent by the server at the end of a remote call along with resulting call status. /// /// public sealed class Metadata : IList { /// /// All binary headers should have this suffix. /// public const string BinaryHeaderSuffix = "-bin"; /// /// An read-only instance of metadata containing no entries. /// public static readonly Metadata Empty = new Metadata().Freeze(); /// /// To be used in initial metadata to request specific compression algorithm /// for given call. Direct selection of compression algorithms is an internal /// feature and is not part of public API. /// internal const string CompressionRequestAlgorithmMetadataKey = "grpc-internal-encoding-request"; readonly List entries; bool readOnly; /// /// Initializes a new instance of Metadata. /// public Metadata() { this.entries = new List(); } /// /// Makes this object read-only. /// /// this object internal Metadata Freeze() { this.readOnly = true; return this; } // TODO: add support for access by key #region IList members /// /// /// public int IndexOf(Metadata.Entry item) { return entries.IndexOf(item); } /// /// /// public void Insert(int index, Metadata.Entry item) { GrpcPreconditions.CheckNotNull(item); CheckWriteable(); entries.Insert(index, item); } /// /// /// public void RemoveAt(int index) { CheckWriteable(); entries.RemoveAt(index); } /// /// /// public Metadata.Entry this[int index] { get { return entries[index]; } set { GrpcPreconditions.CheckNotNull(value); CheckWriteable(); entries[index] = value; } } /// /// /// public void Add(Metadata.Entry item) { GrpcPreconditions.CheckNotNull(item); CheckWriteable(); entries.Add(item); } /// /// /// public void Add(string key, string value) { Add(new Entry(key, value)); } /// /// /// public void Add(string key, byte[] valueBytes) { Add(new Entry(key, valueBytes)); } /// /// /// public void Clear() { CheckWriteable(); entries.Clear(); } /// /// /// public bool Contains(Metadata.Entry item) { return entries.Contains(item); } /// /// /// public void CopyTo(Metadata.Entry[] array, int arrayIndex) { entries.CopyTo(array, arrayIndex); } /// /// /// public int Count { get { return entries.Count; } } /// /// /// public bool IsReadOnly { get { return readOnly; } } /// /// /// public bool Remove(Metadata.Entry item) { CheckWriteable(); return entries.Remove(item); } /// /// /// public IEnumerator GetEnumerator() { return entries.GetEnumerator(); } IEnumerator System.Collections.IEnumerable.GetEnumerator() { return entries.GetEnumerator(); } private void CheckWriteable() { GrpcPreconditions.CheckState(!readOnly, "Object is read only"); } #endregion /// /// Metadata entry /// public class Entry { private static readonly Regex ValidKeyRegex = new Regex("^[a-z0-9_-]+$"); readonly string key; readonly string value; readonly byte[] valueBytes; private Entry(string key, string value, byte[] valueBytes) { this.key = key; this.value = value; this.valueBytes = valueBytes; } /// /// Initializes a new instance of the struct with a binary value. /// /// Metadata key, needs to have suffix indicating a binary valued metadata entry. /// Value bytes. public Entry(string key, byte[] valueBytes) { this.key = NormalizeKey(key); GrpcPreconditions.CheckArgument(HasBinaryHeaderSuffix(this.key), "Key for binary valued metadata entry needs to have suffix indicating binary value."); this.value = null; GrpcPreconditions.CheckNotNull(valueBytes, "valueBytes"); this.valueBytes = new byte[valueBytes.Length]; Buffer.BlockCopy(valueBytes, 0, this.valueBytes, 0, valueBytes.Length); // defensive copy to guarantee immutability } /// /// Initializes a new instance of the struct holding an ASCII value. /// /// Metadata key, must not use suffix indicating a binary valued metadata entry. /// Value string. Only ASCII characters are allowed. public Entry(string key, string value) { this.key = NormalizeKey(key); GrpcPreconditions.CheckArgument(!HasBinaryHeaderSuffix(this.key), "Key for ASCII valued metadata entry cannot have suffix indicating binary value."); this.value = GrpcPreconditions.CheckNotNull(value, "value"); this.valueBytes = null; } /// /// Gets the metadata entry key. /// public string Key { get { return this.key; } } /// /// Gets the binary value of this metadata entry. /// public byte[] ValueBytes { get { if (valueBytes == null) { return MarshalUtils.GetBytesASCII(value); } // defensive copy to guarantee immutability var bytes = new byte[valueBytes.Length]; Buffer.BlockCopy(valueBytes, 0, bytes, 0, valueBytes.Length); return bytes; } } /// /// Gets the string value of this metadata entry. /// public string Value { get { GrpcPreconditions.CheckState(!IsBinary, "Cannot access string value of a binary metadata entry"); return value ?? MarshalUtils.GetStringASCII(valueBytes); } } /// /// Returns true if this entry is a binary-value entry. /// public bool IsBinary { get { return value == null; } } /// /// Returns a that represents the current . /// public override string ToString() { if (IsBinary) { return string.Format("[Entry: key={0}, valueBytes={1}]", key, valueBytes); } return string.Format("[Entry: key={0}, value={1}]", key, value); } /// /// Gets the serialized value for this entry. For binary metadata entries, this leaks /// the internal valueBytes byte array and caller must not change contents of it. /// internal byte[] GetSerializedValueUnsafe() { return valueBytes ?? MarshalUtils.GetBytesASCII(value); } /// /// Creates a binary value or ascii value metadata entry from data received from the native layer. /// We trust C core to give us well-formed data, so we don't perform any checks or defensive copying. /// internal static Entry CreateUnsafe(string key, byte[] valueBytes) { if (HasBinaryHeaderSuffix(key)) { return new Entry(key, null, valueBytes); } return new Entry(key, MarshalUtils.GetStringASCII(valueBytes), null); } private static string NormalizeKey(string key) { var normalized = GrpcPreconditions.CheckNotNull(key, "key").ToLowerInvariant(); GrpcPreconditions.CheckArgument(ValidKeyRegex.IsMatch(normalized), "Metadata entry key not valid. Keys can only contain lowercase alphanumeric characters, underscores and hyphens."); return normalized; } /// /// Returns true if the key has "-bin" binary header suffix. /// private static bool HasBinaryHeaderSuffix(string key) { // We don't use just string.EndsWith because its implementation is extremely slow // on CoreCLR and we've seen significant differences in gRPC benchmarks caused by it. // See https://github.com/dotnet/coreclr/issues/5612 int len = key.Length; if (len >= 4 && key[len - 4] == '-' && key[len - 3] == 'b' && key[len - 2] == 'i' && key[len - 1] == 'n') { return true; } return false; } } } } grpc-1.3.2/src/csharp/Grpc.Core/Method.cs000066400000000000000000000147511310511640000200470ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using Grpc.Core.Utils; namespace Grpc.Core { /// /// Method types supported by gRPC. /// public enum MethodType { /// Single request sent from client, single response received from server. Unary, /// Stream of request sent from client, single response received from server. ClientStreaming, /// Single request sent from client, stream of responses received from server. ServerStreaming, /// Both server and client can stream arbitrary number of requests and responses simultaneously. DuplexStreaming } /// /// A non-generic representation of a remote method. /// public interface IMethod { /// /// Gets the type of the method. /// MethodType Type { get; } /// /// Gets the name of the service to which this method belongs. /// string ServiceName { get; } /// /// Gets the unqualified name of the method. /// string Name { get; } /// /// Gets the fully qualified name of the method. On the server side, methods are dispatched /// based on this name. /// string FullName { get; } } /// /// A description of a remote method. /// /// Request message type for this method. /// Response message type for this method. public class Method : IMethod { readonly MethodType type; readonly string serviceName; readonly string name; readonly Marshaller requestMarshaller; readonly Marshaller responseMarshaller; readonly string fullName; /// /// Initializes a new instance of the Method class. /// /// Type of method. /// Name of service this method belongs to. /// Unqualified name of the method. /// Marshaller used for request messages. /// Marshaller used for response messages. public Method(MethodType type, string serviceName, string name, Marshaller requestMarshaller, Marshaller responseMarshaller) { this.type = type; this.serviceName = GrpcPreconditions.CheckNotNull(serviceName, "serviceName"); this.name = GrpcPreconditions.CheckNotNull(name, "name"); this.requestMarshaller = GrpcPreconditions.CheckNotNull(requestMarshaller, "requestMarshaller"); this.responseMarshaller = GrpcPreconditions.CheckNotNull(responseMarshaller, "responseMarshaller"); this.fullName = GetFullName(serviceName, name); } /// /// Gets the type of the method. /// public MethodType Type { get { return this.type; } } /// /// Gets the name of the service to which this method belongs. /// public string ServiceName { get { return this.serviceName; } } /// /// Gets the unqualified name of the method. /// public string Name { get { return this.name; } } /// /// Gets the marshaller used for request messages. /// public Marshaller RequestMarshaller { get { return this.requestMarshaller; } } /// /// Gets the marshaller used for response messages. /// public Marshaller ResponseMarshaller { get { return this.responseMarshaller; } } /// /// Gets the fully qualified name of the method. On the server side, methods are dispatched /// based on this name. /// public string FullName { get { return this.fullName; } } /// /// Gets full name of the method including the service name. /// internal static string GetFullName(string serviceName, string methodName) { return "/" + serviceName + "/" + methodName; } } } grpc-1.3.2/src/csharp/Grpc.Core/NativeDeps.Linux.csproj.include000066400000000000000000000004551310511640000243000ustar00rootroot00000000000000 libgrpc_csharp_ext.x64.so PreserveNewest false grpc-1.3.2/src/csharp/Grpc.Core/NativeDeps.Mac.csproj.include000066400000000000000000000014451310511640000237010ustar00rootroot00000000000000 libgrpc_csharp_ext.x86.dylib PreserveNewest false libgrpc_csharp_ext.x64.dylib PreserveNewest false grpc-1.3.2/src/csharp/Grpc.Core/NativeDeps.Windows.csproj.include000066400000000000000000000004611310511640000246300ustar00rootroot00000000000000 PreserveNewest grpc_csharp_ext.x64.dll false grpc-1.3.2/src/csharp/Grpc.Core/NativeDeps.csproj.include000077500000000000000000000025431310511640000232050ustar00rootroot00000000000000 Debug Release dbg opt Windows Mac Linux grpc-1.3.2/src/csharp/Grpc.Core/Profiling/000077500000000000000000000000001310511640000202215ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Core/Profiling/IProfiler.cs000066400000000000000000000035101310511640000224420ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.IO; using System.Threading; using Grpc.Core.Internal; namespace Grpc.Core.Profiling { internal interface IProfiler { void Begin(string tag); void End(string tag); void Mark(string tag); } } grpc-1.3.2/src/csharp/Grpc.Core/Profiling/ProfilerEntry.cs000066400000000000000000000057211310511640000233610ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.IO; using System.Threading; using Grpc.Core.Internal; namespace Grpc.Core.Profiling { internal struct ProfilerEntry { public enum Type { BEGIN, END, MARK } public ProfilerEntry(Timespec timespec, Type type, string tag) { this.timespec = timespec; this.type = type; this.tag = tag; } public Timespec timespec; public Type type; public string tag; public override string ToString() { // mimic the output format used by C core. return string.Format( "{{\"t\": {0}.{1}, \"thd\":\"unknown\", \"type\": \"{2}\", \"tag\": \"{3}\", " + "\"file\": \"unknown\", \"line\": 0, \"imp\": 0}}", timespec.TimevalSeconds, timespec.TimevalNanos.ToString("D9"), GetTypeAbbreviation(type), tag); } internal static string GetTypeAbbreviation(Type type) { switch (type) { case Type.BEGIN: return "{"; case Type.END: return "}"; case Type.MARK: return "."; default: throw new ArgumentException("Unknown type"); } } } } grpc-1.3.2/src/csharp/Grpc.Core/Profiling/ProfilerScope.cs000066400000000000000000000043321310511640000233260ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.IO; using System.Threading; using Grpc.Core.Internal; namespace Grpc.Core.Profiling { // Allows declaring Begin and End of a profiler scope with a using statement. // declared as struct for better performance. internal struct ProfilerScope : IDisposable { readonly IProfiler profiler; readonly string tag; public ProfilerScope(IProfiler profiler, string tag) { this.profiler = profiler; this.tag = tag; this.profiler.Begin(this.tag); } public void Dispose() { profiler.End(tag); } } } grpc-1.3.2/src/csharp/Grpc.Core/Profiling/Profilers.cs000066400000000000000000000076021310511640000225220ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.IO; using System.Threading; using Grpc.Core.Internal; namespace Grpc.Core.Profiling { internal static class Profilers { static readonly NopProfiler DefaultProfiler = new NopProfiler(); static readonly ThreadLocal profilers = new ThreadLocal(); public static IProfiler ForCurrentThread() { return profilers.Value ?? DefaultProfiler; } public static void SetForCurrentThread(IProfiler profiler) { profilers.Value = profiler; } public static ProfilerScope NewScope(this IProfiler profiler, string tag) { return new ProfilerScope(profiler, tag); } } internal class NopProfiler : IProfiler { public void Begin(string tag) { } public void End(string tag) { } public void Mark(string tag) { } } // Profiler using Timespec.PreciseNow internal class BasicProfiler : IProfiler { ProfilerEntry[] entries; int count; public BasicProfiler() : this(20*1024*1024) { } public BasicProfiler(int capacity) { this.entries = new ProfilerEntry[capacity]; } public void Begin(string tag) { AddEntry(new ProfilerEntry(Timespec.PreciseNow, ProfilerEntry.Type.BEGIN, tag)); } public void End(string tag) { AddEntry(new ProfilerEntry(Timespec.PreciseNow, ProfilerEntry.Type.END, tag)); } public void Mark(string tag) { AddEntry(new ProfilerEntry(Timespec.PreciseNow, ProfilerEntry.Type.MARK, tag)); } public void Reset() { count = 0; } public void Dump(string filepath) { using (var stream = File.CreateText(filepath)) { Dump(stream); } } public void Dump(TextWriter stream) { for (int i = 0; i < count; i++) { var entry = entries[i]; stream.WriteLine(entry.ToString()); } } // NOT THREADSAFE! void AddEntry(ProfilerEntry entry) { entries[count++] = entry; } } } grpc-1.3.2/src/csharp/Grpc.Core/Properties/000077500000000000000000000000001310511640000204245ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs000066400000000000000000000065441310511640000233570ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Grpc.Core")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] #if SIGNED [assembly: InternalsVisibleTo("Grpc.Core.Tests,PublicKey=" + "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" + "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] [assembly: InternalsVisibleTo("Grpc.Core.Testing,PublicKey=" + "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" + "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] [assembly: InternalsVisibleTo("Grpc.IntegrationTesting,PublicKey=" + "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" + "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] #else [assembly: InternalsVisibleTo("Grpc.Core.Tests")] [assembly: InternalsVisibleTo("Grpc.Core.Testing")] [assembly: InternalsVisibleTo("Grpc.IntegrationTesting")] #endif grpc-1.3.2/src/csharp/Grpc.Core/RpcException.cs000066400000000000000000000054311310511640000212250ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; namespace Grpc.Core { /// /// Thrown when remote procedure call fails. Every RpcException is associated with a resulting of the call. /// public class RpcException : Exception { private readonly Status status; /// /// Creates a new RpcException associated with given status. /// /// Resulting status of a call. public RpcException(Status status) : base(status.ToString()) { this.status = status; } /// /// Creates a new RpcException associated with given status and message. /// /// Resulting status of a call. /// The exception message. public RpcException(Status status, string message) : base(message) { this.status = status; } /// /// Resulting status of the call. /// public Status Status { get { return status; } } } } grpc-1.3.2/src/csharp/Grpc.Core/Server.cs000066400000000000000000000403431310511640000200710ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Grpc.Core.Internal; using Grpc.Core.Logging; using Grpc.Core.Utils; namespace Grpc.Core { /// /// gRPC server. A single server can server arbitrary number of services and can listen on more than one ports. /// public class Server { const int DefaultRequestCallTokensPerCq = 2000; static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); readonly AtomicCounter activeCallCounter = new AtomicCounter(); readonly ServiceDefinitionCollection serviceDefinitions; readonly ServerPortCollection ports; readonly GrpcEnvironment environment; readonly List options; readonly ServerSafeHandle handle; readonly object myLock = new object(); readonly List serviceDefinitionsList = new List(); readonly List serverPortList = new List(); readonly Dictionary callHandlers = new Dictionary(); readonly TaskCompletionSource shutdownTcs = new TaskCompletionSource(); bool startRequested; volatile bool shutdownRequested; int requestCallTokensPerCq = DefaultRequestCallTokensPerCq; /// /// Creates a new server. /// public Server() : this(null) { } /// /// Creates a new server. /// /// Channel options. public Server(IEnumerable options) { this.serviceDefinitions = new ServiceDefinitionCollection(this); this.ports = new ServerPortCollection(this); this.environment = GrpcEnvironment.AddRef(); this.options = options != null ? new List(options) : new List(); using (var channelArgs = ChannelOptions.CreateChannelArgs(this.options)) { this.handle = ServerSafeHandle.NewServer(channelArgs); } foreach (var cq in environment.CompletionQueues) { this.handle.RegisterCompletionQueue(cq); } GrpcEnvironment.RegisterServer(this); } /// /// Services that will be exported by the server once started. Register a service with this /// server by adding its definition to this collection. /// public ServiceDefinitionCollection Services { get { return serviceDefinitions; } } /// /// Ports on which the server will listen once started. Register a port with this /// server by adding its definition to this collection. /// public ServerPortCollection Ports { get { return ports; } } /// /// To allow awaiting termination of the server. /// public Task ShutdownTask { get { return shutdownTcs.Task; } } /// /// Experimental API. Might anytime change without prior notice. /// Number or calls requested via grpc_server_request_call at any given time for each completion queue. /// public int RequestCallTokensPerCompletionQueue { get { return requestCallTokensPerCq; } set { lock (myLock) { GrpcPreconditions.CheckState(!startRequested); GrpcPreconditions.CheckArgument(value > 0); requestCallTokensPerCq = value; } } } /// /// Starts the server. /// public void Start() { lock (myLock) { GrpcPreconditions.CheckState(!startRequested); GrpcPreconditions.CheckState(!shutdownRequested); startRequested = true; handle.Start(); for (int i = 0; i < requestCallTokensPerCq; i++) { foreach (var cq in environment.CompletionQueues) { AllowOneRpc(cq); } } } } /// /// Requests server shutdown and when there are no more calls being serviced, /// cleans up used resources. The returned task finishes when shutdown procedure /// is complete. /// /// /// It is strongly recommended to shutdown all previously created servers before exiting from the process. /// public Task ShutdownAsync() { return ShutdownInternalAsync(false); } /// /// Requests server shutdown while cancelling all the in-progress calls. /// The returned task finishes when shutdown procedure is complete. /// /// /// It is strongly recommended to shutdown all previously created servers before exiting from the process. /// public Task KillAsync() { return ShutdownInternalAsync(true); } internal void AddCallReference(object call) { activeCallCounter.Increment(); bool success = false; handle.DangerousAddRef(ref success); GrpcPreconditions.CheckState(success); } internal void RemoveCallReference(object call) { handle.DangerousRelease(); activeCallCounter.Decrement(); } /// /// Shuts down the server. /// private async Task ShutdownInternalAsync(bool kill) { lock (myLock) { GrpcPreconditions.CheckState(!shutdownRequested); shutdownRequested = true; } GrpcEnvironment.UnregisterServer(this); var cq = environment.CompletionQueues.First(); // any cq will do handle.ShutdownAndNotify(HandleServerShutdown, cq); if (kill) { handle.CancelAllCalls(); } await ShutdownCompleteOrEnvironmentDeadAsync().ConfigureAwait(false); DisposeHandle(); await GrpcEnvironment.ReleaseAsync().ConfigureAwait(false); } /// /// In case the environment's threadpool becomes dead, the shutdown completion will /// never be delivered, but we need to release the environment's handle anyway. /// private async Task ShutdownCompleteOrEnvironmentDeadAsync() { while (true) { var task = await Task.WhenAny(shutdownTcs.Task, Task.Delay(20)).ConfigureAwait(false); if (shutdownTcs.Task == task) { return; } if (!environment.IsAlive) { return; } } } /// /// Adds a service definition. /// private void AddServiceDefinitionInternal(ServerServiceDefinition serviceDefinition) { lock (myLock) { GrpcPreconditions.CheckState(!startRequested); foreach (var entry in serviceDefinition.CallHandlers) { callHandlers.Add(entry.Key, entry.Value); } serviceDefinitionsList.Add(serviceDefinition); } } /// /// Adds a listening port. /// private int AddPortInternal(ServerPort serverPort) { lock (myLock) { GrpcPreconditions.CheckNotNull(serverPort.Credentials, "serverPort"); GrpcPreconditions.CheckState(!startRequested); var address = string.Format("{0}:{1}", serverPort.Host, serverPort.Port); int boundPort; using (var nativeCredentials = serverPort.Credentials.ToNativeCredentials()) { if (nativeCredentials != null) { boundPort = handle.AddSecurePort(address, nativeCredentials); } else { boundPort = handle.AddInsecurePort(address); } } var newServerPort = new ServerPort(serverPort, boundPort); this.serverPortList.Add(newServerPort); return boundPort; } } /// /// Allows one new RPC call to be received by server. /// private void AllowOneRpc(CompletionQueueSafeHandle cq) { if (!shutdownRequested) { handle.RequestCall((success, ctx) => HandleNewServerRpc(success, ctx, cq), cq); } } private void DisposeHandle() { var activeCallCount = activeCallCounter.Count; if (activeCallCount > 0) { Logger.Warning("Server shutdown has finished but there are still {0} active calls for that server.", activeCallCount); } handle.Dispose(); } /// /// Selects corresponding handler for given call and handles the call. /// private async Task HandleCallAsync(ServerRpcNew newRpc, CompletionQueueSafeHandle cq, Action continuation) { try { IServerCallHandler callHandler; if (!callHandlers.TryGetValue(newRpc.Method, out callHandler)) { callHandler = UnimplementedMethodCallHandler.Instance; } await callHandler.HandleCall(newRpc, cq).ConfigureAwait(false); } catch (Exception e) { Logger.Warning(e, "Exception while handling RPC."); } finally { continuation(); } } /// /// Handles the native callback. /// private void HandleNewServerRpc(bool success, RequestCallContextSafeHandle ctx, CompletionQueueSafeHandle cq) { bool nextRpcRequested = false; if (success) { var newRpc = ctx.GetServerRpcNew(this); // after server shutdown, the callback returns with null call if (!newRpc.Call.IsInvalid) { nextRpcRequested = true; // Start asynchronous handler for the call. // Don't await, the continuations will run on gRPC thread pool once triggered // by cq.Next(). #pragma warning disable 4014 HandleCallAsync(newRpc, cq, () => AllowOneRpc(cq)); #pragma warning restore 4014 } } if (!nextRpcRequested) { AllowOneRpc(cq); } } /// /// Handles native callback. /// private void HandleServerShutdown(bool success, BatchContextSafeHandle ctx) { shutdownTcs.SetResult(null); } /// /// Collection of service definitions. /// public class ServiceDefinitionCollection : IEnumerable { readonly Server server; internal ServiceDefinitionCollection(Server server) { this.server = server; } /// /// Adds a service definition to the server. This is how you register /// handlers for a service with the server. Only call this before Start(). /// public void Add(ServerServiceDefinition serviceDefinition) { server.AddServiceDefinitionInternal(serviceDefinition); } /// /// Gets enumerator for this collection. /// public IEnumerator GetEnumerator() { return server.serviceDefinitionsList.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return server.serviceDefinitionsList.GetEnumerator(); } } /// /// Collection of server ports. /// public class ServerPortCollection : IEnumerable { readonly Server server; internal ServerPortCollection(Server server) { this.server = server; } /// /// Adds a new port on which server should listen. /// Only call this before Start(). /// The port on which server will be listening. /// public int Add(ServerPort serverPort) { return server.AddPortInternal(serverPort); } /// /// Adds a new port on which server should listen. /// The port on which server will be listening. /// /// the host /// the port. If zero, an unused port is chosen automatically. /// credentials to use to secure this port. public int Add(string host, int port, ServerCredentials credentials) { return Add(new ServerPort(host, port, credentials)); } /// /// Gets enumerator for this collection. /// public IEnumerator GetEnumerator() { return server.serverPortList.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return server.serverPortList.GetEnumerator(); } } } } grpc-1.3.2/src/csharp/Grpc.Core/ServerCallContext.cs000066400000000000000000000170401310511640000222300ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Threading; using System.Threading.Tasks; using Grpc.Core.Internal; namespace Grpc.Core { /// /// Context for a server-side call. /// public class ServerCallContext { private readonly CallSafeHandle callHandle; private readonly string method; private readonly string host; private readonly DateTime deadline; private readonly Metadata requestHeaders; private readonly CancellationToken cancellationToken; private readonly Metadata responseTrailers = new Metadata(); private Status status = Status.DefaultSuccess; private Func writeHeadersFunc; private IHasWriteOptions writeOptionsHolder; private Lazy authContext; internal ServerCallContext(CallSafeHandle callHandle, string method, string host, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken, Func writeHeadersFunc, IHasWriteOptions writeOptionsHolder) { this.callHandle = callHandle; this.method = method; this.host = host; this.deadline = deadline; this.requestHeaders = requestHeaders; this.cancellationToken = cancellationToken; this.writeHeadersFunc = writeHeadersFunc; this.writeOptionsHolder = writeOptionsHolder; this.authContext = new Lazy(GetAuthContextEager); } /// /// Asynchronously sends response headers for the current call to the client. This method may only be invoked once for each call and needs to be invoked /// before any response messages are written. Writing the first response message implicitly sends empty response headers if WriteResponseHeadersAsync haven't /// been called yet. /// /// The response headers to send. /// The task that finished once response headers have been written. public Task WriteResponseHeadersAsync(Metadata responseHeaders) { return writeHeadersFunc(responseHeaders); } /// /// Creates a propagation token to be used to propagate call context to a child call. /// public ContextPropagationToken CreatePropagationToken(ContextPropagationOptions options = null) { return new ContextPropagationToken(callHandle, deadline, cancellationToken, options); } /// Name of method called in this RPC. public string Method { get { return this.method; } } /// Name of host called in this RPC. public string Host { get { return this.host; } } /// Address of the remote endpoint in URI format. public string Peer { get { // Getting the peer lazily is fine as the native call is guaranteed // not to be disposed before user-supplied server side handler returns. // Most users won't need to read this field anyway. return this.callHandle.GetPeer(); } } /// Deadline for this RPC. public DateTime Deadline { get { return this.deadline; } } /// Initial metadata sent by client. public Metadata RequestHeaders { get { return this.requestHeaders; } } /// Cancellation token signals when call is cancelled. public CancellationToken CancellationToken { get { return this.cancellationToken; } } /// Trailers to send back to client after RPC finishes. public Metadata ResponseTrailers { get { return this.responseTrailers; } } /// Status to send back to client after RPC finishes. public Status Status { get { return this.status; } set { status = value; } } /// /// Allows setting write options for the following write. /// For streaming response calls, this property is also exposed as on IServerStreamWriter for convenience. /// Both properties are backed by the same underlying value. /// public WriteOptions WriteOptions { get { return writeOptionsHolder.WriteOptions; } set { writeOptionsHolder.WriteOptions = value; } } /// /// Gets the AuthContext associated with this call. /// Note: Access to AuthContext is an experimental API that can change without any prior notice. /// public AuthContext AuthContext { get { return authContext.Value; } } private AuthContext GetAuthContextEager() { using (var authContextNative = callHandle.GetAuthContext()) { return authContextNative.ToAuthContext(); } } } /// /// Allows sharing write options between ServerCallContext and other objects. /// public interface IHasWriteOptions { /// /// Gets or sets the write options. /// WriteOptions WriteOptions { get; set; } } } grpc-1.3.2/src/csharp/Grpc.Core/ServerCredentials.cs000066400000000000000000000136541310511640000222540ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using Grpc.Core.Internal; using Grpc.Core.Utils; namespace Grpc.Core { /// /// Server side credentials. /// public abstract class ServerCredentials { static readonly ServerCredentials InsecureInstance = new InsecureServerCredentialsImpl(); /// /// Returns instance of credential that provides no security and /// will result in creating an unsecure server port with no encryption whatsoever. /// public static ServerCredentials Insecure { get { return InsecureInstance; } } /// /// Creates native object for the credentials. /// /// The native credentials. internal abstract ServerCredentialsSafeHandle ToNativeCredentials(); private sealed class InsecureServerCredentialsImpl : ServerCredentials { internal override ServerCredentialsSafeHandle ToNativeCredentials() { return null; } } } /// /// Server-side SSL credentials. /// public class SslServerCredentials : ServerCredentials { readonly IList keyCertificatePairs; readonly string rootCertificates; readonly bool forceClientAuth; /// /// Creates server-side SSL credentials. /// /// Key-certificates to use. /// PEM encoded client root certificates used to authenticate client. /// If true, client will be rejected unless it proves its unthenticity using against rootCertificates. public SslServerCredentials(IEnumerable keyCertificatePairs, string rootCertificates, bool forceClientAuth) { this.keyCertificatePairs = new List(keyCertificatePairs).AsReadOnly(); GrpcPreconditions.CheckArgument(this.keyCertificatePairs.Count > 0, "At least one KeyCertificatePair needs to be provided."); if (forceClientAuth) { GrpcPreconditions.CheckNotNull(rootCertificates, "Cannot force client authentication unless you provide rootCertificates."); } this.rootCertificates = rootCertificates; this.forceClientAuth = forceClientAuth; } /// /// Creates server-side SSL credentials. /// This constructor should be use if you do not wish to autheticate client /// using client root certificates. /// /// Key-certificates to use. public SslServerCredentials(IEnumerable keyCertificatePairs) : this(keyCertificatePairs, null, false) { } /// /// Key-certificate pairs. /// public IList KeyCertificatePairs { get { return this.keyCertificatePairs; } } /// /// PEM encoded client root certificates. /// public string RootCertificates { get { return this.rootCertificates; } } /// /// If true, the authenticity of client check will be enforced. /// public bool ForceClientAuthentication { get { return this.forceClientAuth; } } internal override ServerCredentialsSafeHandle ToNativeCredentials() { int count = keyCertificatePairs.Count; string[] certChains = new string[count]; string[] keys = new string[count]; for (int i = 0; i < count; i++) { certChains[i] = keyCertificatePairs[i].CertificateChain; keys[i] = keyCertificatePairs[i].PrivateKey; } return ServerCredentialsSafeHandle.CreateSslCredentials(rootCertificates, certChains, keys, forceClientAuth); } } } grpc-1.3.2/src/csharp/Grpc.Core/ServerMethods.cs000066400000000000000000000070161310511640000214150ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Threading.Tasks; namespace Grpc.Core { /// /// Server-side handler for unary call. /// /// Request message type for this method. /// Response message type for this method. public delegate Task UnaryServerMethod(TRequest request, ServerCallContext context) where TRequest : class where TResponse : class; /// /// Server-side handler for client streaming call. /// /// Request message type for this method. /// Response message type for this method. public delegate Task ClientStreamingServerMethod(IAsyncStreamReader requestStream, ServerCallContext context) where TRequest : class where TResponse : class; /// /// Server-side handler for server streaming call. /// /// Request message type for this method. /// Response message type for this method. public delegate Task ServerStreamingServerMethod(TRequest request, IServerStreamWriter responseStream, ServerCallContext context) where TRequest : class where TResponse : class; /// /// Server-side handler for bidi streaming call. /// /// Request message type for this method. /// Response message type for this method. public delegate Task DuplexStreamingServerMethod(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) where TRequest : class where TResponse : class; } grpc-1.3.2/src/csharp/Grpc.Core/ServerPort.cs000066400000000000000000000100561310511640000207340ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using Grpc.Core.Utils; namespace Grpc.Core { /// /// A port exposed by a server. /// public class ServerPort { /// /// Pass this value as port to have the server choose an unused listening port for you. /// Ports added to a server will contain the bound port in their property. /// public const int PickUnused = 0; readonly string host; readonly int port; readonly ServerCredentials credentials; readonly int boundPort; /// /// Creates a new port on which server should listen. /// /// The port on which server will be listening. /// the host /// the port. If zero, an unused port is chosen automatically. /// credentials to use to secure this port. public ServerPort(string host, int port, ServerCredentials credentials) { this.host = GrpcPreconditions.CheckNotNull(host, "host"); this.port = port; this.credentials = GrpcPreconditions.CheckNotNull(credentials, "credentials"); } /// /// Creates a port from an existing ServerPort instance and boundPort value. /// internal ServerPort(ServerPort serverPort, int boundPort) { this.host = serverPort.host; this.port = serverPort.port; this.credentials = serverPort.credentials; this.boundPort = boundPort; } /// The host. public string Host { get { return host; } } /// The port. public int Port { get { return port; } } /// The server credentials. public ServerCredentials Credentials { get { return credentials; } } /// /// The port actually bound by the server. This is useful if you let server /// pick port automatically. /// public int BoundPort { get { return boundPort; } } } } grpc-1.3.2/src/csharp/Grpc.Core/ServerServiceDefinition.cs000066400000000000000000000161131310511640000234210ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Collections.ObjectModel; using Grpc.Core.Internal; namespace Grpc.Core { /// /// Mapping of method names to server call handlers. /// Normally, the ServerServiceDefinition objects will be created by the BindService factory method /// that is part of the autogenerated code for a protocol buffers service definition. /// public class ServerServiceDefinition { readonly ReadOnlyDictionary callHandlers; private ServerServiceDefinition(Dictionary callHandlers) { this.callHandlers = new ReadOnlyDictionary(callHandlers); } internal IDictionary CallHandlers { get { return this.callHandlers; } } /// /// Creates a new builder object for ServerServiceDefinition. /// /// The builder object. public static Builder CreateBuilder() { return new Builder(); } /// /// Builder class for . /// public class Builder { readonly Dictionary callHandlers = new Dictionary(); /// /// Creates a new instance of builder. /// public Builder() { } /// /// Adds a definitions for a single request - single response method. /// /// The request message class. /// The response message class. /// The method. /// The method handler. /// This builder instance. public Builder AddMethod( Method method, UnaryServerMethod handler) where TRequest : class where TResponse : class { callHandlers.Add(method.FullName, ServerCalls.UnaryCall(method, handler)); return this; } /// /// Adds a definitions for a client streaming method. /// /// The request message class. /// The response message class. /// The method. /// The method handler. /// This builder instance. public Builder AddMethod( Method method, ClientStreamingServerMethod handler) where TRequest : class where TResponse : class { callHandlers.Add(method.FullName, ServerCalls.ClientStreamingCall(method, handler)); return this; } /// /// Adds a definitions for a server streaming method. /// /// The request message class. /// The response message class. /// The method. /// The method handler. /// This builder instance. public Builder AddMethod( Method method, ServerStreamingServerMethod handler) where TRequest : class where TResponse : class { callHandlers.Add(method.FullName, ServerCalls.ServerStreamingCall(method, handler)); return this; } /// /// Adds a definitions for a bidirectional streaming method. /// /// The request message class. /// The response message class. /// The method. /// The method handler. /// This builder instance. public Builder AddMethod( Method method, DuplexStreamingServerMethod handler) where TRequest : class where TResponse : class { callHandlers.Add(method.FullName, ServerCalls.DuplexStreamingCall(method, handler)); return this; } /// /// Creates an immutable ServerServiceDefinition from this builder. /// /// The ServerServiceDefinition object. public ServerServiceDefinition Build() { return new ServerServiceDefinition(callHandlers); } } } } grpc-1.3.2/src/csharp/Grpc.Core/Status.cs000066400000000000000000000066661310511640000201200ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using Grpc.Core.Utils; namespace Grpc.Core { /// /// Represents RPC result, which consists of and an optional detail string. /// public struct Status { /// /// Default result of a successful RPC. StatusCode=OK, empty details message. /// public static readonly Status DefaultSuccess = new Status(StatusCode.OK, ""); /// /// Default result of a cancelled RPC. StatusCode=Cancelled, empty details message. /// public static readonly Status DefaultCancelled = new Status(StatusCode.Cancelled, ""); readonly StatusCode statusCode; readonly string detail; /// /// Creates a new instance of Status. /// /// Status code. /// Detail. public Status(StatusCode statusCode, string detail) { this.statusCode = statusCode; this.detail = detail; } /// /// Gets the gRPC status code. OK indicates success, all other values indicate an error. /// public StatusCode StatusCode { get { return statusCode; } } /// /// Gets the detail. /// public string Detail { get { return detail; } } /// /// Returns a that represents the current . /// public override string ToString() { return string.Format("Status(StatusCode={0}, Detail=\"{1}\")", statusCode, detail); } } } grpc-1.3.2/src/csharp/Grpc.Core/StatusCode.cs000066400000000000000000000131261310511640000207000ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion namespace Grpc.Core { /// /// Result of a remote procedure call. /// Based on grpc_status_code from grpc/status.h /// public enum StatusCode { /// Not an error; returned on success. OK = 0, /// The operation was cancelled (typically by the caller). Cancelled = 1, /// /// Unknown error. An example of where this error may be returned is /// if a Status value received from another address space belongs to /// an error-space that is not known in this address space. Also /// errors raised by APIs that do not return enough error information /// may be converted to this error. /// Unknown = 2, /// /// Client specified an invalid argument. Note that this differs /// from FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments /// that are problematic regardless of the state of the system /// (e.g., a malformed file name). /// InvalidArgument = 3, /// /// Deadline expired before operation could complete. For operations /// that change the state of the system, this error may be returned /// even if the operation has completed successfully. For example, a /// successful response from a server could have been delayed long /// enough for the deadline to expire. /// DeadlineExceeded = 4, /// Some requested entity (e.g., file or directory) was not found. NotFound = 5, /// Some entity that we attempted to create (e.g., file or directory) already exists. AlreadyExists = 6, /// /// The caller does not have permission to execute the specified /// operation. PERMISSION_DENIED must not be used for rejections /// caused by exhausting some resource (use RESOURCE_EXHAUSTED /// instead for those errors). PERMISSION_DENIED must not be /// used if the caller can not be identified (use UNAUTHENTICATED /// instead for those errors). /// PermissionDenied = 7, /// The request does not have valid authentication credentials for the operation. Unauthenticated = 16, /// /// Some resource has been exhausted, perhaps a per-user quota, or /// perhaps the entire file system is out of space. /// ResourceExhausted = 8, /// /// Operation was rejected because the system is not in a state /// required for the operation's execution. For example, directory /// to be deleted may be non-empty, an rmdir operation is applied to /// a non-directory, etc. /// FailedPrecondition = 9, /// /// The operation was aborted, typically due to a concurrency issue /// like sequencer check failures, transaction aborts, etc. /// Aborted = 10, /// /// Operation was attempted past the valid range. E.g., seeking or /// reading past end of file. /// OutOfRange = 11, /// Operation is not implemented or not supported/enabled in this service. Unimplemented = 12, /// /// Internal errors. Means some invariants expected by underlying /// system has been broken. If you see one of these errors, /// something is very broken. /// Internal = 13, /// /// The service is currently unavailable. This is a most likely a /// transient condition and may be corrected by retrying with /// a backoff. /// Unavailable = 14, /// Unrecoverable data loss or corruption. DataLoss = 15 } } grpc-1.3.2/src/csharp/Grpc.Core/Utils/000077500000000000000000000000001310511640000173705ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Core/Utils/AsyncStreamExtensions.cs000066400000000000000000000075351310511640000242420ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Threading.Tasks; namespace Grpc.Core.Utils { /// /// Extension methods that simplify work with gRPC streaming calls. /// public static class AsyncStreamExtensions { /// /// Reads the entire stream and executes an async action for each element. /// public static async Task ForEachAsync(this IAsyncStreamReader streamReader, Func asyncAction) where T : class { while (await streamReader.MoveNext().ConfigureAwait(false)) { await asyncAction(streamReader.Current).ConfigureAwait(false); } } /// /// Reads the entire stream and creates a list containing all the elements read. /// public static async Task> ToListAsync(this IAsyncStreamReader streamReader) where T : class { var result = new List(); while (await streamReader.MoveNext().ConfigureAwait(false)) { result.Add(streamReader.Current); } return result; } /// /// Writes all elements from given enumerable to the stream. /// Completes the stream afterwards unless close = false. /// public static async Task WriteAllAsync(this IClientStreamWriter streamWriter, IEnumerable elements, bool complete = true) where T : class { foreach (var element in elements) { await streamWriter.WriteAsync(element).ConfigureAwait(false); } if (complete) { await streamWriter.CompleteAsync().ConfigureAwait(false); } } /// /// Writes all elements from given enumerable to the stream. /// public static async Task WriteAllAsync(this IServerStreamWriter streamWriter, IEnumerable elements) where T : class { foreach (var element in elements) { await streamWriter.WriteAsync(element).ConfigureAwait(false); } } } } grpc-1.3.2/src/csharp/Grpc.Core/Utils/BenchmarkUtil.cs000066400000000000000000000055001310511640000224470ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Threading.Tasks; namespace Grpc.Core.Utils { /// /// Utility methods to run microbenchmarks. /// public static class BenchmarkUtil { /// /// Runs a simple benchmark preceded by warmup phase. /// public static void RunBenchmark(int warmupIterations, int benchmarkIterations, Action action) { var logger = GrpcEnvironment.Logger; logger.Info("Warmup iterations: {0}", warmupIterations); for (int i = 0; i < warmupIterations; i++) { action(); } logger.Info("Benchmark iterations: {0}", benchmarkIterations); var stopwatch = new Stopwatch(); stopwatch.Start(); for (int i = 0; i < benchmarkIterations; i++) { action(); } stopwatch.Stop(); logger.Info("Elapsed time: {0}ms", stopwatch.ElapsedMilliseconds); logger.Info("Ops per second: {0}", (int)((double)benchmarkIterations * 1000 / stopwatch.ElapsedMilliseconds)); } } } grpc-1.3.2/src/csharp/Grpc.Core/Utils/GrpcPreconditions.cs000066400000000000000000000104611310511640000233550ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; namespace Grpc.Core.Utils { /// /// Utility methods to simplify checking preconditions in the code. /// public static class GrpcPreconditions { /// /// Throws if condition is false. /// /// The condition. public static void CheckArgument(bool condition) { if (!condition) { throw new ArgumentException(); } } /// /// Throws with given message if condition is false. /// /// The condition. /// The error message. public static void CheckArgument(bool condition, string errorMessage) { if (!condition) { throw new ArgumentException(errorMessage); } } /// /// Throws if reference is null. /// /// The reference. public static T CheckNotNull(T reference) { if (reference == null) { throw new ArgumentNullException(); } return reference; } /// /// Throws if reference is null. /// /// The reference. /// The parameter name. public static T CheckNotNull(T reference, string paramName) { if (reference == null) { throw new ArgumentNullException(paramName); } return reference; } /// /// Throws if condition is false. /// /// The condition. public static void CheckState(bool condition) { if (!condition) { throw new InvalidOperationException(); } } /// /// Throws with given message if condition is false. /// /// The condition. /// The error message. public static void CheckState(bool condition, string errorMessage) { if (!condition) { throw new InvalidOperationException(errorMessage); } } } } grpc-1.3.2/src/csharp/Grpc.Core/Utils/TaskUtils.cs000066400000000000000000000042441310511640000216460ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Threading.Tasks; namespace Grpc.Core.Utils { /// /// Utility methods for task parallel library. /// public static class TaskUtils { /// /// Framework independent equivalent of Task.CompletedTask. /// public static Task CompletedTask { get { #if NETSTANDARD1_5 return Task.CompletedTask; #else return Task.FromResult(null); // for .NET45, emulate the functionality #endif } } } } grpc-1.3.2/src/csharp/Grpc.Core/Version.cs000066400000000000000000000035141310511640000202470ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; [assembly: AssemblyVersion(Grpc.Core.VersionInfo.CurrentAssemblyVersion)] [assembly: AssemblyFileVersion(Grpc.Core.VersionInfo.CurrentAssemblyFileVersion)] [assembly: AssemblyInformationalVersion(Grpc.Core.VersionInfo.CurrentVersion)] grpc-1.3.2/src/csharp/Grpc.Core/Version.csproj.include000077500000000000000000000003041310511640000225610ustar00rootroot00000000000000 1.3.2 3.2.0 grpc-1.3.2/src/csharp/Grpc.Core/VersionInfo.cs000066400000000000000000000046011310511640000210610ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion namespace Grpc.Core { /// /// Provides info about current version of gRPC. /// See https://codingforsmarties.wordpress.com/2016/01/21/how-to-version-assemblies-destined-for-nuget/ /// for rationale about assembly versioning. /// public static class VersionInfo { /// /// Current AssemblyVersion attribute of gRPC C# assemblies /// public const string CurrentAssemblyVersion = "1.0.0.0"; /// /// Current AssemblyFileVersion of gRPC C# assemblies /// public const string CurrentAssemblyFileVersion = "1.3.2.0"; /// /// Current version of gRPC C# /// public const string CurrentVersion = "1.3.2"; } } grpc-1.3.2/src/csharp/Grpc.Core/WriteOptions.cs000066400000000000000000000060131310511640000212650ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; namespace Grpc.Core { /// /// Flags for write operations. /// [Flags] public enum WriteFlags { /// /// Hint that the write may be buffered and need not go out on the wire immediately. /// gRPC is free to buffer the message until the next non-buffered /// write, or until write stream completion, but it need not buffer completely or at all. /// BufferHint = 0x1, /// /// Force compression to be disabled for a particular write. /// NoCompress = 0x2 } /// /// Options for write operations. /// public class WriteOptions { /// /// Default write options. /// public static readonly WriteOptions Default = new WriteOptions(); private readonly WriteFlags flags; /// /// Initializes a new instance of WriteOptions class. /// /// The write flags. public WriteOptions(WriteFlags flags = default(WriteFlags)) { this.flags = flags; } /// /// Gets the write flags. /// public WriteFlags Flags { get { return this.flags; } } } } grpc-1.3.2/src/csharp/Grpc.Examples.MathClient/000077500000000000000000000000001310511640000212055ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Examples.MathClient/.gitignore000066400000000000000000000000101310511640000231640ustar00rootroot00000000000000bin obj grpc-1.3.2/src/csharp/Grpc.Examples.MathClient/Grpc.Examples.MathClient.csproj000077500000000000000000000015371310511640000271370ustar00rootroot00000000000000 net45;netcoreapp1.0 Grpc.Examples.MathClient Exe Grpc.Examples.MathClient 1.0.4 grpc-1.3.2/src/csharp/Grpc.Examples.MathClient/MathClient.cs000066400000000000000000000044631310511640000235730ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.InteropServices; using System.Threading; using Grpc.Core; namespace Math { class MathClient { public static void Main(string[] args) { var channel = new Channel("127.0.0.1", 23456, ChannelCredentials.Insecure); Math.MathClient client = new Math.MathClient(channel); MathExamples.DivExample(client); MathExamples.DivAsyncExample(client).Wait(); MathExamples.FibExample(client).Wait(); MathExamples.SumExample(client).Wait(); MathExamples.DivManyExample(client).Wait(); MathExamples.DependendRequestsExample(client).Wait(); channel.ShutdownAsync().Wait(); } } } grpc-1.3.2/src/csharp/Grpc.Examples.MathClient/Properties/000077500000000000000000000000001310511640000233415ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Examples.MathClient/Properties/AssemblyInfo.cs000066400000000000000000000037151310511640000262710ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Grpc.Examples.MathClient")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] grpc-1.3.2/src/csharp/Grpc.Examples.MathServer/000077500000000000000000000000001310511640000212355ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Examples.MathServer/.gitignore000066400000000000000000000000101310511640000232140ustar00rootroot00000000000000bin obj grpc-1.3.2/src/csharp/Grpc.Examples.MathServer/Grpc.Examples.MathServer.csproj000077500000000000000000000015371310511640000272170ustar00rootroot00000000000000 net45;netcoreapp1.0 Grpc.Examples.MathServer Exe Grpc.Examples.MathServer 1.0.4 grpc-1.3.2/src/csharp/Grpc.Examples.MathServer/MathServer.cs000066400000000000000000000044521310511640000236510ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Runtime.InteropServices; using System.Threading; using Grpc.Core; namespace Math { class MainClass { const string Host = "0.0.0.0"; const int Port = 23456; public static void Main(string[] args) { Server server = new Server { Services = { Math.BindService(new MathServiceImpl()) }, Ports = { { Host, Port, ServerCredentials.Insecure } } }; server.Start(); Console.WriteLine("MathServer listening on port " + Port); Console.WriteLine("Press any key to stop the server..."); Console.ReadKey(); server.ShutdownAsync().Wait(); } } } grpc-1.3.2/src/csharp/Grpc.Examples.MathServer/Properties/000077500000000000000000000000001310511640000233715ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Examples.MathServer/Properties/AssemblyInfo.cs000066400000000000000000000037151310511640000263210ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Grpc.Examples.MathServer")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] grpc-1.3.2/src/csharp/Grpc.Examples.Tests/000077500000000000000000000000001310511640000202575ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Examples.Tests/.gitignore000066400000000000000000000000251310511640000222440ustar00rootroot00000000000000test-results bin obj grpc-1.3.2/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj000077500000000000000000000021721310511640000252570ustar00rootroot00000000000000 net45;netcoreapp1.0 Grpc.Examples.Tests Exe Grpc.Examples.Tests $(PackageTargetFallback);portable-net45 1.0.4 grpc-1.3.2/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs000066400000000000000000000156331310511640000250600ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Utils; using NUnit.Framework; namespace Math.Tests { /// /// Math client talks to local math server. /// public class MathClientServerTest { const string Host = "localhost"; Server server; Channel channel; Math.MathClient client; [TestFixtureSetUp] public void Init() { // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) { Services = { Math.BindService(new MathServiceImpl()) }, Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } } }; server.Start(); channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure); client = new Math.MathClient(channel); } [TestFixtureTearDown] public void Cleanup() { channel.ShutdownAsync().Wait(); server.ShutdownAsync().Wait(); } [Test] public void Div1() { DivReply response = client.Div(new DivArgs { Dividend = 10, Divisor = 3 }); Assert.AreEqual(3, response.Quotient); Assert.AreEqual(1, response.Remainder); } [Test] public void Div2() { DivReply response = client.Div(new DivArgs { Dividend = 0, Divisor = 1 }); Assert.AreEqual(0, response.Quotient); Assert.AreEqual(0, response.Remainder); } [Test] public void DivByZero() { var ex = Assert.Throws(() => client.Div(new DivArgs { Dividend = 0, Divisor = 0 })); Assert.AreEqual(StatusCode.InvalidArgument, ex.Status.StatusCode); } [Test] public async Task DivAsync() { DivReply response = await client.DivAsync(new DivArgs { Dividend = 10, Divisor = 3 }); Assert.AreEqual(3, response.Quotient); Assert.AreEqual(1, response.Remainder); } [Test] public async Task Fib() { using (var call = client.Fib(new FibArgs { Limit = 6 })) { var responses = await call.ResponseStream.ToListAsync(); CollectionAssert.AreEqual(new List { 1, 1, 2, 3, 5, 8 }, responses.Select((n) => n.Num_)); } } [Test] public async Task FibWithCancel() { var cts = new CancellationTokenSource(); using (var call = client.Fib(new FibArgs { Limit = 0 }, cancellationToken: cts.Token)) { List responses = new List(); try { while (await call.ResponseStream.MoveNext()) { if (responses.Count == 0) { cts.CancelAfter(500); // make sure we cancel soon } responses.Add(call.ResponseStream.Current.Num_); } Assert.Fail(); } catch (RpcException e) { Assert.IsTrue(responses.Count > 0); Assert.AreEqual(StatusCode.Cancelled, e.Status.StatusCode); } } } [Test] public async Task FibWithDeadline() { using (var call = client.Fib(new FibArgs { Limit = 0 }, deadline: DateTime.UtcNow.AddMilliseconds(500))) { var ex = Assert.ThrowsAsync(async () => await call.ResponseStream.ToListAsync()); // We can't guarantee the status code always DeadlineExceeded. See issue #2685. Assert.Contains(ex.Status.StatusCode, new[] { StatusCode.DeadlineExceeded, StatusCode.Internal }); } } // TODO: test Fib with limit=0 and cancellation [Test] public async Task Sum() { using (var call = client.Sum()) { var numbers = new List { 10, 20, 30 }.Select(n => new Num { Num_ = n }); await call.RequestStream.WriteAllAsync(numbers); var result = await call.ResponseAsync; Assert.AreEqual(60, result.Num_); } } [Test] public async Task DivMany() { var divArgsList = new List { new DivArgs { Dividend = 10, Divisor = 3 }, new DivArgs { Dividend = 100, Divisor = 21 }, new DivArgs { Dividend = 7, Divisor = 2 } }; using (var call = client.DivMany()) { await call.RequestStream.WriteAllAsync(divArgsList); var result = await call.ResponseStream.ToListAsync(); CollectionAssert.AreEqual(new long[] { 3, 4, 3 }, result.Select((divReply) => divReply.Quotient)); CollectionAssert.AreEqual(new long[] { 1, 16, 1 }, result.Select((divReply) => divReply.Remainder)); } } } } grpc-1.3.2/src/csharp/Grpc.Examples.Tests/NUnitMain.cs000066400000000000000000000044771310511640000224640ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Reflection; using Grpc.Core; using Grpc.Core.Logging; using NUnit.Common; using NUnitLite; namespace Grpc.Examples.Tests { /// /// Provides entry point for NUnitLite /// public class NUnitMain { public static int Main(string[] args) { // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error)); #if NETCOREAPP1_0 return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In); #else return new AutoRun().Execute(args); #endif } } } grpc-1.3.2/src/csharp/Grpc.Examples.Tests/Properties/000077500000000000000000000000001310511640000224135ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Examples.Tests/Properties/AssemblyInfo.cs000066400000000000000000000037101310511640000253360ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Grpc.Examples.Tests")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] grpc-1.3.2/src/csharp/Grpc.Examples/000077500000000000000000000000001310511640000171565ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Examples/.gitignore000066400000000000000000000000251310511640000211430ustar00rootroot00000000000000test-results bin obj grpc-1.3.2/src/csharp/Grpc.Examples/Grpc.Examples.csproj000077500000000000000000000016241310511640000230560ustar00rootroot00000000000000 net45;netcoreapp1.0 Grpc.Examples Grpc.Examples 1.0.4 grpc-1.3.2/src/csharp/Grpc.Examples/Math.cs000066400000000000000000000506521310511640000204060ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: math/math.proto #pragma warning disable 1591, 0612, 3021 #region Designer generated code using pb = global::Google.Protobuf; using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; namespace Math { /// Holder for reflection information generated from math/math.proto public static partial class MathReflection { #region Descriptor /// File descriptor for math/math.proto public static pbr::FileDescriptor Descriptor { get { return descriptor; } } private static pbr::FileDescriptor descriptor; static MathReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "Cg9tYXRoL21hdGgucHJvdG8SBG1hdGgiLAoHRGl2QXJncxIQCghkaXZpZGVu", "ZBgBIAEoAxIPCgdkaXZpc29yGAIgASgDIi8KCERpdlJlcGx5EhAKCHF1b3Rp", "ZW50GAEgASgDEhEKCXJlbWFpbmRlchgCIAEoAyIYCgdGaWJBcmdzEg0KBWxp", "bWl0GAEgASgDIhIKA051bRILCgNudW0YASABKAMiGQoIRmliUmVwbHkSDQoF", "Y291bnQYASABKAMypAEKBE1hdGgSJgoDRGl2Eg0ubWF0aC5EaXZBcmdzGg4u", "bWF0aC5EaXZSZXBseSIAEi4KB0Rpdk1hbnkSDS5tYXRoLkRpdkFyZ3MaDi5t", "YXRoLkRpdlJlcGx5IgAoATABEiMKA0ZpYhINLm1hdGguRmliQXJncxoJLm1h", "dGguTnVtIgAwARIfCgNTdW0SCS5tYXRoLk51bRoJLm1hdGguTnVtIgAoAWIG", "cHJvdG8z")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Math.DivArgs), global::Math.DivArgs.Parser, new[]{ "Dividend", "Divisor" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Math.DivReply), global::Math.DivReply.Parser, new[]{ "Quotient", "Remainder" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Math.FibArgs), global::Math.FibArgs.Parser, new[]{ "Limit" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Math.Num), global::Math.Num.Parser, new[]{ "Num_" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Math.FibReply), global::Math.FibReply.Parser, new[]{ "Count" }, null, null, null) })); } #endregion } #region Messages public sealed partial class DivArgs : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DivArgs()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Math.MathReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public DivArgs() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public DivArgs(DivArgs other) : this() { dividend_ = other.dividend_; divisor_ = other.divisor_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public DivArgs Clone() { return new DivArgs(this); } /// Field number for the "dividend" field. public const int DividendFieldNumber = 1; private long dividend_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public long Dividend { get { return dividend_; } set { dividend_ = value; } } /// Field number for the "divisor" field. public const int DivisorFieldNumber = 2; private long divisor_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public long Divisor { get { return divisor_; } set { divisor_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as DivArgs); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(DivArgs other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Dividend != other.Dividend) return false; if (Divisor != other.Divisor) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Dividend != 0L) hash ^= Dividend.GetHashCode(); if (Divisor != 0L) hash ^= Divisor.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Dividend != 0L) { output.WriteRawTag(8); output.WriteInt64(Dividend); } if (Divisor != 0L) { output.WriteRawTag(16); output.WriteInt64(Divisor); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Dividend != 0L) { size += 1 + pb::CodedOutputStream.ComputeInt64Size(Dividend); } if (Divisor != 0L) { size += 1 + pb::CodedOutputStream.ComputeInt64Size(Divisor); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(DivArgs other) { if (other == null) { return; } if (other.Dividend != 0L) { Dividend = other.Dividend; } if (other.Divisor != 0L) { Divisor = other.Divisor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { Dividend = input.ReadInt64(); break; } case 16: { Divisor = input.ReadInt64(); break; } } } } } public sealed partial class DivReply : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DivReply()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Math.MathReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public DivReply() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public DivReply(DivReply other) : this() { quotient_ = other.quotient_; remainder_ = other.remainder_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public DivReply Clone() { return new DivReply(this); } /// Field number for the "quotient" field. public const int QuotientFieldNumber = 1; private long quotient_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public long Quotient { get { return quotient_; } set { quotient_ = value; } } /// Field number for the "remainder" field. public const int RemainderFieldNumber = 2; private long remainder_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public long Remainder { get { return remainder_; } set { remainder_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as DivReply); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(DivReply other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Quotient != other.Quotient) return false; if (Remainder != other.Remainder) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Quotient != 0L) hash ^= Quotient.GetHashCode(); if (Remainder != 0L) hash ^= Remainder.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Quotient != 0L) { output.WriteRawTag(8); output.WriteInt64(Quotient); } if (Remainder != 0L) { output.WriteRawTag(16); output.WriteInt64(Remainder); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Quotient != 0L) { size += 1 + pb::CodedOutputStream.ComputeInt64Size(Quotient); } if (Remainder != 0L) { size += 1 + pb::CodedOutputStream.ComputeInt64Size(Remainder); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(DivReply other) { if (other == null) { return; } if (other.Quotient != 0L) { Quotient = other.Quotient; } if (other.Remainder != 0L) { Remainder = other.Remainder; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { Quotient = input.ReadInt64(); break; } case 16: { Remainder = input.ReadInt64(); break; } } } } } public sealed partial class FibArgs : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FibArgs()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Math.MathReflection.Descriptor.MessageTypes[2]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public FibArgs() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public FibArgs(FibArgs other) : this() { limit_ = other.limit_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public FibArgs Clone() { return new FibArgs(this); } /// Field number for the "limit" field. public const int LimitFieldNumber = 1; private long limit_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public long Limit { get { return limit_; } set { limit_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as FibArgs); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(FibArgs other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Limit != other.Limit) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Limit != 0L) hash ^= Limit.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Limit != 0L) { output.WriteRawTag(8); output.WriteInt64(Limit); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Limit != 0L) { size += 1 + pb::CodedOutputStream.ComputeInt64Size(Limit); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(FibArgs other) { if (other == null) { return; } if (other.Limit != 0L) { Limit = other.Limit; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { Limit = input.ReadInt64(); break; } } } } } public sealed partial class Num : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Num()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Math.MathReflection.Descriptor.MessageTypes[3]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Num() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Num(Num other) : this() { num_ = other.num_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Num Clone() { return new Num(this); } /// Field number for the "num" field. public const int Num_FieldNumber = 1; private long num_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public long Num_ { get { return num_; } set { num_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as Num); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(Num other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Num_ != other.Num_) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Num_ != 0L) hash ^= Num_.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Num_ != 0L) { output.WriteRawTag(8); output.WriteInt64(Num_); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Num_ != 0L) { size += 1 + pb::CodedOutputStream.ComputeInt64Size(Num_); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(Num other) { if (other == null) { return; } if (other.Num_ != 0L) { Num_ = other.Num_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { Num_ = input.ReadInt64(); break; } } } } } public sealed partial class FibReply : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FibReply()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Math.MathReflection.Descriptor.MessageTypes[4]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public FibReply() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public FibReply(FibReply other) : this() { count_ = other.count_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public FibReply Clone() { return new FibReply(this); } /// Field number for the "count" field. public const int CountFieldNumber = 1; private long count_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public long Count { get { return count_; } set { count_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as FibReply); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(FibReply other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Count != other.Count) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Count != 0L) hash ^= Count.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Count != 0L) { output.WriteRawTag(8); output.WriteInt64(Count); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Count != 0L) { size += 1 + pb::CodedOutputStream.ComputeInt64Size(Count); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(FibReply other) { if (other == null) { return; } if (other.Count != 0L) { Count = other.Count; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { Count = input.ReadInt64(); break; } } } } } #endregion } #endregion Designer generated code grpc-1.3.2/src/csharp/Grpc.Examples/MathExamples.cs000066400000000000000000000130171310511640000220770ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Utils; namespace Math { public static class MathExamples { public static void DivExample(Math.MathClient client) { DivReply result = client.Div(new DivArgs { Dividend = 10, Divisor = 3 }); Console.WriteLine("Div Result: " + result); } public static async Task DivAsyncExample(Math.MathClient client) { DivReply result = await client.DivAsync(new DivArgs { Dividend = 4, Divisor = 5 }); Console.WriteLine("DivAsync Result: " + result); } public static async Task FibExample(Math.MathClient client) { using (var call = client.Fib(new FibArgs { Limit = 5 })) { List result = await call.ResponseStream.ToListAsync(); Console.WriteLine("Fib Result: " + string.Join("|", result)); } } public static async Task SumExample(Math.MathClient client) { var numbers = new List { new Num { Num_ = 1 }, new Num { Num_ = 2 }, new Num { Num_ = 3 } }; using (var call = client.Sum()) { await call.RequestStream.WriteAllAsync(numbers); Console.WriteLine("Sum Result: " + await call.ResponseAsync); } } public static async Task DivManyExample(Math.MathClient client) { var divArgsList = new List { new DivArgs { Dividend = 10, Divisor = 3 }, new DivArgs { Dividend = 100, Divisor = 21 }, new DivArgs { Dividend = 7, Divisor = 2 } }; using (var call = client.DivMany()) { await call.RequestStream.WriteAllAsync(divArgsList); Console.WriteLine("DivMany Result: " + string.Join("|", await call.ResponseStream.ToListAsync())); } } public static async Task DependendRequestsExample(Math.MathClient client) { var numbers = new List { new Num { Num_ = 1 }, new Num { Num_ = 2 }, new Num { Num_ = 3 } }; Num sum; using (var sumCall = client.Sum()) { await sumCall.RequestStream.WriteAllAsync(numbers); sum = await sumCall.ResponseAsync; } DivReply result = await client.DivAsync(new DivArgs { Dividend = sum.Num_, Divisor = numbers.Count }); Console.WriteLine("Avg Result: " + result); } /// /// Shows how to handle a call ending with non-OK status. /// public static async Task HandleErrorExample(Math.MathClient client) { try { DivReply result = await client.DivAsync(new DivArgs { Dividend = 5, Divisor = 0 }); } catch (RpcException ex) { Console.WriteLine(string.Format("RPC ended with status {0}", ex.Status)); } } /// /// Shows how to send request headers and how to access response headers /// and response trailers. /// public static async Task MetadataExample(Math.MathClient client) { var requestHeaders = new Metadata { { "custom-header", "custom-value" } }; var call = client.DivAsync(new DivArgs { Dividend = 5, Divisor = 0 }, requestHeaders); // Get response headers Metadata responseHeaders = await call.ResponseHeadersAsync; var result = await call; // Get response trailers after the call has finished. Metadata responseTrailers = call.GetTrailers(); } } } grpc-1.3.2/src/csharp/Grpc.Examples/MathGrpc.cs000066400000000000000000000416661310511640000212270ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: math/math.proto // Original file comments: // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #region Designer generated code using System; using System.Threading; using System.Threading.Tasks; using grpc = global::Grpc.Core; namespace Math { public static partial class Math { static readonly string __ServiceName = "math.Math"; static readonly grpc::Marshaller __Marshaller_DivArgs = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Math.DivArgs.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_DivReply = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Math.DivReply.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_FibArgs = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Math.FibArgs.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_Num = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Math.Num.Parser.ParseFrom); static readonly grpc::Method __Method_Div = new grpc::Method( grpc::MethodType.Unary, __ServiceName, "Div", __Marshaller_DivArgs, __Marshaller_DivReply); static readonly grpc::Method __Method_DivMany = new grpc::Method( grpc::MethodType.DuplexStreaming, __ServiceName, "DivMany", __Marshaller_DivArgs, __Marshaller_DivReply); static readonly grpc::Method __Method_Fib = new grpc::Method( grpc::MethodType.ServerStreaming, __ServiceName, "Fib", __Marshaller_FibArgs, __Marshaller_Num); static readonly grpc::Method __Method_Sum = new grpc::Method( grpc::MethodType.ClientStreaming, __ServiceName, "Sum", __Marshaller_Num, __Marshaller_Num); /// Service descriptor public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor { get { return global::Math.MathReflection.Descriptor.Services[0]; } } /// Base class for server-side implementations of Math public abstract partial class MathBase { /// /// Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient /// and remainder. /// /// The request received from the client. /// The context of the server-side call handler being invoked. /// The response to send back to the client (wrapped by a task). public virtual global::System.Threading.Tasks.Task Div(global::Math.DivArgs request, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } /// /// DivMany accepts an arbitrary number of division args from the client stream /// and sends back the results in the reply stream. The stream continues until /// the client closes its end; the server does the same after sending all the /// replies. The stream ends immediately if either end aborts. /// /// Used for reading requests from the client. /// Used for sending responses back to the client. /// The context of the server-side call handler being invoked. /// A task indicating completion of the handler. public virtual global::System.Threading.Tasks.Task DivMany(grpc::IAsyncStreamReader requestStream, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } /// /// Fib generates numbers in the Fibonacci sequence. If FibArgs.limit > 0, Fib /// generates up to limit numbers; otherwise it continues until the call is /// canceled. Unlike Fib above, Fib has no final FibReply. /// /// The request received from the client. /// Used for sending responses back to the client. /// The context of the server-side call handler being invoked. /// A task indicating completion of the handler. public virtual global::System.Threading.Tasks.Task Fib(global::Math.FibArgs request, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } /// /// Sum sums a stream of numbers, returning the final result once the stream /// is closed. /// /// Used for reading requests from the client. /// The context of the server-side call handler being invoked. /// The response to send back to the client (wrapped by a task). public virtual global::System.Threading.Tasks.Task Sum(grpc::IAsyncStreamReader requestStream, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } } /// Client for Math public partial class MathClient : grpc::ClientBase { /// Creates a new client for Math /// The channel to use to make remote calls. public MathClient(grpc::Channel channel) : base(channel) { } /// Creates a new client for Math that uses a custom CallInvoker. /// The callInvoker to use to make remote calls. public MathClient(grpc::CallInvoker callInvoker) : base(callInvoker) { } /// Protected parameterless constructor to allow creation of test doubles. protected MathClient() : base() { } /// Protected constructor to allow creation of configured clients. /// The client configuration. protected MathClient(ClientBaseConfiguration configuration) : base(configuration) { } /// /// Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient /// and remainder. /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The response received from the server. public virtual global::Math.DivReply Div(global::Math.DivArgs request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return Div(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient /// and remainder. /// /// The request to send to the server. /// The options for the call. /// The response received from the server. public virtual global::Math.DivReply Div(global::Math.DivArgs request, grpc::CallOptions options) { return CallInvoker.BlockingUnaryCall(__Method_Div, null, options, request); } /// /// Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient /// and remainder. /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncUnaryCall DivAsync(global::Math.DivArgs request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return DivAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient /// and remainder. /// /// The request to send to the server. /// The options for the call. /// The call object. public virtual grpc::AsyncUnaryCall DivAsync(global::Math.DivArgs request, grpc::CallOptions options) { return CallInvoker.AsyncUnaryCall(__Method_Div, null, options, request); } /// /// DivMany accepts an arbitrary number of division args from the client stream /// and sends back the results in the reply stream. The stream continues until /// the client closes its end; the server does the same after sending all the /// replies. The stream ends immediately if either end aborts. /// /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncDuplexStreamingCall DivMany(grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return DivMany(new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// DivMany accepts an arbitrary number of division args from the client stream /// and sends back the results in the reply stream. The stream continues until /// the client closes its end; the server does the same after sending all the /// replies. The stream ends immediately if either end aborts. /// /// The options for the call. /// The call object. public virtual grpc::AsyncDuplexStreamingCall DivMany(grpc::CallOptions options) { return CallInvoker.AsyncDuplexStreamingCall(__Method_DivMany, null, options); } /// /// Fib generates numbers in the Fibonacci sequence. If FibArgs.limit > 0, Fib /// generates up to limit numbers; otherwise it continues until the call is /// canceled. Unlike Fib above, Fib has no final FibReply. /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncServerStreamingCall Fib(global::Math.FibArgs request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return Fib(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// Fib generates numbers in the Fibonacci sequence. If FibArgs.limit > 0, Fib /// generates up to limit numbers; otherwise it continues until the call is /// canceled. Unlike Fib above, Fib has no final FibReply. /// /// The request to send to the server. /// The options for the call. /// The call object. public virtual grpc::AsyncServerStreamingCall Fib(global::Math.FibArgs request, grpc::CallOptions options) { return CallInvoker.AsyncServerStreamingCall(__Method_Fib, null, options, request); } /// /// Sum sums a stream of numbers, returning the final result once the stream /// is closed. /// /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncClientStreamingCall Sum(grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return Sum(new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// Sum sums a stream of numbers, returning the final result once the stream /// is closed. /// /// The options for the call. /// The call object. public virtual grpc::AsyncClientStreamingCall Sum(grpc::CallOptions options) { return CallInvoker.AsyncClientStreamingCall(__Method_Sum, null, options); } /// Creates a new instance of client from given ClientBaseConfiguration. protected override MathClient NewInstance(ClientBaseConfiguration configuration) { return new MathClient(configuration); } } /// Creates service definition that can be registered with a server /// An object implementing the server-side handling logic. public static grpc::ServerServiceDefinition BindService(MathBase serviceImpl) { return grpc::ServerServiceDefinition.CreateBuilder() .AddMethod(__Method_Div, serviceImpl.Div) .AddMethod(__Method_DivMany, serviceImpl.DivMany) .AddMethod(__Method_Fib, serviceImpl.Fib) .AddMethod(__Method_Sum, serviceImpl.Sum).Build(); } } } #endregion grpc-1.3.2/src/csharp/Grpc.Examples/MathServiceImpl.cs000066400000000000000000000104521310511640000225430ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Utils; namespace Math { /// /// Implementation of MathService server /// public class MathServiceImpl : Math.MathBase { public override Task Div(DivArgs request, ServerCallContext context) { return Task.FromResult(DivInternal(request)); } public override async Task Fib(FibArgs request, IServerStreamWriter responseStream, ServerCallContext context) { var limit = request.Limit > 0 ? request.Limit : long.MaxValue; var fibEnumerator = FibInternal(limit).GetEnumerator(); // Keep streaming the sequence until the call is cancelled. // Use CancellationToken from ServerCallContext to detect the cancellation. while (!context.CancellationToken.IsCancellationRequested && fibEnumerator.MoveNext()) { await responseStream.WriteAsync(fibEnumerator.Current); await Task.Delay(100); } } public override async Task Sum(IAsyncStreamReader requestStream, ServerCallContext context) { long sum = 0; await requestStream.ForEachAsync(async num => { sum += num.Num_; }); return new Num { Num_ = sum }; } public override async Task DivMany(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) { await requestStream.ForEachAsync(async divArgs => await responseStream.WriteAsync(DivInternal(divArgs))); } static DivReply DivInternal(DivArgs args) { if (args.Divisor == 0) { // One can finish the RPC with non-ok status by throwing RpcException instance. // Alternatively, resulting status can be set using ServerCallContext.Status throw new RpcException(new Status(StatusCode.InvalidArgument, "Division by zero")); } long quotient = args.Dividend / args.Divisor; long remainder = args.Dividend % args.Divisor; return new DivReply { Quotient = quotient, Remainder = remainder }; } static IEnumerable FibInternal(long n) { long a = 1; yield return new Num { Num_ = a }; long b = 1; for (long i = 0; i < n - 1; i++) { long temp = a; a = b; b = temp + b; yield return new Num { Num_ = a }; } } } } grpc-1.3.2/src/csharp/Grpc.Examples/Properties/000077500000000000000000000000001310511640000213125ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Examples/Properties/AssemblyInfo.cs000066400000000000000000000037021310511640000242360ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Grpc.Examples")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] grpc-1.3.2/src/csharp/Grpc.Examples/Settings.StyleCop000066400000000000000000000004261310511640000224440ustar00rootroot00000000000000 Math.cs False grpc-1.3.2/src/csharp/Grpc.HealthCheck.Tests/000077500000000000000000000000001310511640000206445ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.HealthCheck.Tests/.gitignore000066400000000000000000000000101310511640000226230ustar00rootroot00000000000000bin obj grpc-1.3.2/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj000077500000000000000000000022061310511640000262270ustar00rootroot00000000000000 net45;netcoreapp1.0 Grpc.HealthCheck.Tests Exe Grpc.HealthCheck.Tests $(PackageTargetFallback);portable-net45 1.0.4 grpc-1.3.2/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs000066400000000000000000000072251310511640000255740ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Grpc.Core; using Grpc.Health.V1; using NUnit.Framework; namespace Grpc.HealthCheck.Tests { /// /// Health client talks to health server. /// public class HealthClientServerTest { const string Host = "localhost"; Server server; Channel channel; Grpc.Health.V1.Health.HealthClient client; Grpc.HealthCheck.HealthServiceImpl serviceImpl; [TestFixtureSetUp] public void Init() { serviceImpl = new HealthServiceImpl(); // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) { Services = { Grpc.Health.V1.Health.BindService(serviceImpl) }, Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } } }; server.Start(); channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure); client = new Grpc.Health.V1.Health.HealthClient(channel); } [TestFixtureTearDown] public void Cleanup() { channel.ShutdownAsync().Wait(); server.ShutdownAsync().Wait(); } [Test] public void ServiceIsRunning() { serviceImpl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Serving); var response = client.Check(new HealthCheckRequest { Service = "" }); Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Serving, response.Status); } [Test] public void ServiceDoesntExist() { var ex = Assert.Throws(() => client.Check(new HealthCheckRequest { Service = "nonexistent.service" })); Assert.AreEqual(StatusCode.NotFound, ex.Status.StatusCode); } // TODO(jtattermusch): add test with timeout once timeouts are supported } } grpc-1.3.2/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs000066400000000000000000000107401310511640000254050ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Grpc.Core; using Grpc.Health.V1; using NUnit.Framework; namespace Grpc.HealthCheck.Tests { /// /// Tests for HealthCheckServiceImpl /// public class HealthServiceImplTest { [Test] public void SetStatus() { var impl = new HealthServiceImpl(); impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Serving); Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Serving, GetStatusHelper(impl, "")); impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.NotServing); Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.NotServing, GetStatusHelper(impl, "")); impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Unknown); Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Unknown, GetStatusHelper(impl, "")); impl.SetStatus("grpc.test.TestService", HealthCheckResponse.Types.ServingStatus.Serving); Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Serving, GetStatusHelper(impl, "grpc.test.TestService")); } [Test] public void ClearStatus() { var impl = new HealthServiceImpl(); impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Serving); impl.SetStatus("grpc.test.TestService", HealthCheckResponse.Types.ServingStatus.Unknown); impl.ClearStatus(""); var ex = Assert.Throws(() => GetStatusHelper(impl, "")); Assert.AreEqual(StatusCode.NotFound, ex.Status.StatusCode); Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Unknown, GetStatusHelper(impl, "grpc.test.TestService")); } [Test] public void ClearAll() { var impl = new HealthServiceImpl(); impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Serving); impl.SetStatus("grpc.test.TestService", HealthCheckResponse.Types.ServingStatus.Unknown); impl.ClearAll(); Assert.Throws(typeof(RpcException), () => GetStatusHelper(impl, "")); Assert.Throws(typeof(RpcException), () => GetStatusHelper(impl, "grpc.test.TestService")); } [Test] public void NullsRejected() { var impl = new HealthServiceImpl(); Assert.Throws(typeof(ArgumentNullException), () => impl.SetStatus(null, HealthCheckResponse.Types.ServingStatus.Serving)); Assert.Throws(typeof(ArgumentNullException), () => impl.ClearStatus(null)); } private static HealthCheckResponse.Types.ServingStatus GetStatusHelper(HealthServiceImpl impl, string service) { return impl.Check(new HealthCheckRequest { Service = service }, null).Result.Status; } } } grpc-1.3.2/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs000066400000000000000000000045021310511640000230360ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Reflection; using Grpc.Core; using Grpc.Core.Logging; using NUnit.Common; using NUnitLite; namespace Grpc.HealthCheck.Tests { /// /// Provides entry point for NUnitLite /// public class NUnitMain { public static int Main(string[] args) { // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error)); #if NETCOREAPP1_0 return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In); #else return new AutoRun().Execute(args); #endif } } } grpc-1.3.2/src/csharp/Grpc.HealthCheck.Tests/Properties/000077500000000000000000000000001310511640000230005ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.HealthCheck.Tests/Properties/AssemblyInfo.cs000066400000000000000000000037161310511640000257310ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Grpc.HealthCheck.Tests")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] grpc-1.3.2/src/csharp/Grpc.HealthCheck/000077500000000000000000000000001310511640000175435ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.HealthCheck/.gitignore000066400000000000000000000000101310511640000215220ustar00rootroot00000000000000bin obj grpc-1.3.2/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj000077500000000000000000000025211310511640000240250ustar00rootroot00000000000000 Copyright 2015, Google Inc. gRPC C# Healthchecking $(GrpcCsharpVersion) Google Inc. net45;netstandard1.5 Grpc.HealthCheck Grpc.HealthCheck gRPC health check https://github.com/grpc/grpc https://github.com/grpc/grpc/blob/master/LICENSE 1.6.0 grpc-1.3.2/src/csharp/Grpc.HealthCheck/Health.cs000066400000000000000000000235011310511640000213000ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: grpc/health/v1/health.proto #pragma warning disable 1591, 0612, 3021 #region Designer generated code using pb = global::Google.Protobuf; using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; namespace Grpc.Health.V1 { /// Holder for reflection information generated from grpc/health/v1/health.proto public static partial class HealthReflection { #region Descriptor /// File descriptor for grpc/health/v1/health.proto public static pbr::FileDescriptor Descriptor { get { return descriptor; } } private static pbr::FileDescriptor descriptor; static HealthReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "ChtncnBjL2hlYWx0aC92MS9oZWFsdGgucHJvdG8SDmdycGMuaGVhbHRoLnYx", "IiUKEkhlYWx0aENoZWNrUmVxdWVzdBIPCgdzZXJ2aWNlGAEgASgJIpQBChNI", "ZWFsdGhDaGVja1Jlc3BvbnNlEkEKBnN0YXR1cxgBIAEoDjIxLmdycGMuaGVh", "bHRoLnYxLkhlYWx0aENoZWNrUmVzcG9uc2UuU2VydmluZ1N0YXR1cyI6Cg1T", "ZXJ2aW5nU3RhdHVzEgsKB1VOS05PV04QABILCgdTRVJWSU5HEAESDwoLTk9U", "X1NFUlZJTkcQAjJaCgZIZWFsdGgSUAoFQ2hlY2sSIi5ncnBjLmhlYWx0aC52", "MS5IZWFsdGhDaGVja1JlcXVlc3QaIy5ncnBjLmhlYWx0aC52MS5IZWFsdGhD", "aGVja1Jlc3BvbnNlQhGqAg5HcnBjLkhlYWx0aC5WMWIGcHJvdG8z")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Health.V1.HealthCheckRequest), global::Grpc.Health.V1.HealthCheckRequest.Parser, new[]{ "Service" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Health.V1.HealthCheckResponse), global::Grpc.Health.V1.HealthCheckResponse.Parser, new[]{ "Status" }, null, new[]{ typeof(global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus) }, null) })); } #endregion } #region Messages public sealed partial class HealthCheckRequest : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new HealthCheckRequest()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Health.V1.HealthReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public HealthCheckRequest() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public HealthCheckRequest(HealthCheckRequest other) : this() { service_ = other.service_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public HealthCheckRequest Clone() { return new HealthCheckRequest(this); } /// Field number for the "service" field. public const int ServiceFieldNumber = 1; private string service_ = ""; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Service { get { return service_; } set { service_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as HealthCheckRequest); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(HealthCheckRequest other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Service != other.Service) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Service.Length != 0) hash ^= Service.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Service.Length != 0) { output.WriteRawTag(10); output.WriteString(Service); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Service.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Service); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(HealthCheckRequest other) { if (other == null) { return; } if (other.Service.Length != 0) { Service = other.Service; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { Service = input.ReadString(); break; } } } } } public sealed partial class HealthCheckResponse : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new HealthCheckResponse()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Health.V1.HealthReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public HealthCheckResponse() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public HealthCheckResponse(HealthCheckResponse other) : this() { status_ = other.status_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public HealthCheckResponse Clone() { return new HealthCheckResponse(this); } /// Field number for the "status" field. public const int StatusFieldNumber = 1; private global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus status_ = 0; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus Status { get { return status_; } set { status_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as HealthCheckResponse); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(HealthCheckResponse other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Status != other.Status) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Status != 0) hash ^= Status.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Status != 0) { output.WriteRawTag(8); output.WriteEnum((int) Status); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Status != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Status); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(HealthCheckResponse other) { if (other == null) { return; } if (other.Status != 0) { Status = other.Status; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { status_ = (global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus) input.ReadEnum(); break; } } } } #region Nested types /// Container for nested types declared in the HealthCheckResponse message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { public enum ServingStatus { [pbr::OriginalName("UNKNOWN")] Unknown = 0, [pbr::OriginalName("SERVING")] Serving = 1, [pbr::OriginalName("NOT_SERVING")] NotServing = 2, } } #endregion } #endregion } #endregion Designer generated code grpc-1.3.2/src/csharp/Grpc.HealthCheck/HealthGrpc.cs000066400000000000000000000146501310511640000221210ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: grpc/health/v1/health.proto // Original file comments: // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #region Designer generated code using System; using System.Threading; using System.Threading.Tasks; using grpc = global::Grpc.Core; namespace Grpc.Health.V1 { public static partial class Health { static readonly string __ServiceName = "grpc.health.v1.Health"; static readonly grpc::Marshaller __Marshaller_HealthCheckRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Health.V1.HealthCheckRequest.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_HealthCheckResponse = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Health.V1.HealthCheckResponse.Parser.ParseFrom); static readonly grpc::Method __Method_Check = new grpc::Method( grpc::MethodType.Unary, __ServiceName, "Check", __Marshaller_HealthCheckRequest, __Marshaller_HealthCheckResponse); /// Service descriptor public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor { get { return global::Grpc.Health.V1.HealthReflection.Descriptor.Services[0]; } } /// Base class for server-side implementations of Health public abstract partial class HealthBase { public virtual global::System.Threading.Tasks.Task Check(global::Grpc.Health.V1.HealthCheckRequest request, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } } /// Client for Health public partial class HealthClient : grpc::ClientBase { /// Creates a new client for Health /// The channel to use to make remote calls. public HealthClient(grpc::Channel channel) : base(channel) { } /// Creates a new client for Health that uses a custom CallInvoker. /// The callInvoker to use to make remote calls. public HealthClient(grpc::CallInvoker callInvoker) : base(callInvoker) { } /// Protected parameterless constructor to allow creation of test doubles. protected HealthClient() : base() { } /// Protected constructor to allow creation of configured clients. /// The client configuration. protected HealthClient(ClientBaseConfiguration configuration) : base(configuration) { } public virtual global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return Check(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } public virtual global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, grpc::CallOptions options) { return CallInvoker.BlockingUnaryCall(__Method_Check, null, options, request); } public virtual grpc::AsyncUnaryCall CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return CheckAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } public virtual grpc::AsyncUnaryCall CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, grpc::CallOptions options) { return CallInvoker.AsyncUnaryCall(__Method_Check, null, options, request); } /// Creates a new instance of client from given ClientBaseConfiguration. protected override HealthClient NewInstance(ClientBaseConfiguration configuration) { return new HealthClient(configuration); } } /// Creates service definition that can be registered with a server /// An object implementing the server-side handling logic. public static grpc::ServerServiceDefinition BindService(HealthBase serviceImpl) { return grpc::ServerServiceDefinition.CreateBuilder() .AddMethod(__Method_Check, serviceImpl.Check).Build(); } } } #endregion grpc-1.3.2/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs000066400000000000000000000105541310511640000234470ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Utils; using Grpc.Health.V1; namespace Grpc.HealthCheck { /// /// Implementation of a simple Health service. Useful for health checking. /// /// Registering service with a server: /// /// var serviceImpl = new HealthServiceImpl(); /// server = new Server(); /// server.AddServiceDefinition(Grpc.Health.V1.Health.BindService(serviceImpl)); /// /// public class HealthServiceImpl : Grpc.Health.V1.Health.HealthBase { private readonly object myLock = new object(); private readonly Dictionary statusMap = new Dictionary(); /// /// Sets the health status for given service. /// /// The service. Cannot be null. /// the health status public void SetStatus(string service, HealthCheckResponse.Types.ServingStatus status) { lock (myLock) { statusMap[service] = status; } } /// /// Clears health status for given service. /// /// The service. Cannot be null. public void ClearStatus(string service) { lock (myLock) { statusMap.Remove(service); } } /// /// Clears statuses for all services. /// public void ClearAll() { lock (myLock) { statusMap.Clear(); } } /// /// Performs a health status check. /// /// The check request. /// The call context. /// The asynchronous response. public override Task Check(HealthCheckRequest request, ServerCallContext context) { lock (myLock) { var service = request.Service; HealthCheckResponse.Types.ServingStatus status; if (!statusMap.TryGetValue(service, out status)) { // TODO(jtattermusch): returning specific status from server handler is not supported yet. throw new RpcException(new Status(StatusCode.NotFound, "")); } return Task.FromResult(new HealthCheckResponse { Status = status }); } } } } grpc-1.3.2/src/csharp/Grpc.HealthCheck/Properties/000077500000000000000000000000001310511640000216775ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.HealthCheck/Properties/AssemblyInfo.cs000066400000000000000000000037101310511640000246220ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Grpc.HealthCheck")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] grpc-1.3.2/src/csharp/Grpc.HealthCheck/Settings.StyleCop000066400000000000000000000004311310511640000230250ustar00rootroot00000000000000 Health.cs False grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.Client/000077500000000000000000000000001310511640000224365ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.Client/.gitignore000066400000000000000000000000111310511640000244160ustar00rootroot00000000000000bin obj grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj000077500000000000000000000020201310511640000316050ustar00rootroot00000000000000 net45;netcoreapp1.0 Grpc.IntegrationTesting.Client Exe Grpc.IntegrationTesting.Client $(PackageTargetFallback);portable-net45 1.0.4 grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.Client/Program.cs000066400000000000000000000034501310511640000243760ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using Grpc.IntegrationTesting; namespace Grpc.IntegrationTesting.Client { class Program { public static void Main(string[] args) { InteropClient.Run(args); } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.Client/Properties/000077500000000000000000000000001310511640000245725ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.Client/Properties/AssemblyInfo.cs000066400000000000000000000037231310511640000275210ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Grpc.IntegrationTesting.Client")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.QpsWorker/000077500000000000000000000000001310511640000231555ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.QpsWorker/.gitignore000066400000000000000000000000111310511640000251350ustar00rootroot00000000000000bin obj grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj000077500000000000000000000021221310511640000330460ustar00rootroot00000000000000 net45;netcoreapp1.0 Grpc.IntegrationTesting.QpsWorker Exe Grpc.IntegrationTesting.QpsWorker true $(PackageTargetFallback);portable-net45 1.0.4 grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.QpsWorker/Program.cs000066400000000000000000000034401310511640000251140ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using Grpc.IntegrationTesting; namespace Grpc.IntegrationTesting { class Program { public static void Main(string[] args) { QpsWorker.Run(args); } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.QpsWorker/Properties/000077500000000000000000000000001310511640000253115ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.QpsWorker/Properties/AssemblyInfo.cs000066400000000000000000000037311310511640000302370ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Grpc.IntegrationTesting.QpsWorker")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.Server/000077500000000000000000000000001310511640000224665ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.Server/.gitignore000066400000000000000000000000111310511640000244460ustar00rootroot00000000000000bin obj grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj000077500000000000000000000020221310511640000316670ustar00rootroot00000000000000 net45;netcoreapp1.0 Grpc.IntegrationTesting.Server Exe Grpc.IntegrationTesting.Server $(PackageTargetFallback);portable-net45 1.0.4 grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.Server/Program.cs000066400000000000000000000034111310511640000244230ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; namespace Grpc.IntegrationTesting.Server { class Program { public static void Main(string[] args) { InteropServer.Run(args); } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.Server/Properties/000077500000000000000000000000001310511640000246225ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.Server/Properties/AssemblyInfo.cs000066400000000000000000000037231310511640000275510ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Grpc.IntegrationTesting.Server")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.StressClient/000077500000000000000000000000001310511640000236425ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.StressClient/.gitignore000066400000000000000000000000111310511640000256220ustar00rootroot00000000000000bin obj Grpc.IntegrationTesting.StressClient.csproj000077500000000000000000000020341310511640000341430ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.StressClient net45;netcoreapp1.0 Grpc.IntegrationTesting.StressClient Exe Grpc.IntegrationTesting.StressClient $(PackageTargetFallback);portable-net45 1.0.4 grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.StressClient/Program.cs000066400000000000000000000034271310511640000256060ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; namespace Grpc.IntegrationTesting.StressClient { class MainClass { public static void Main(string[] args) { StressTestClient.Run(args); } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.StressClient/Properties/000077500000000000000000000000001310511640000257765ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.IntegrationTesting.StressClient/Properties/AssemblyInfo.cs000066400000000000000000000037341310511640000307270ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Grpc.IntegrationTesting.StressClient")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/000077500000000000000000000000001310511640000212215ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/.gitignore000066400000000000000000000000071310511640000232060ustar00rootroot00000000000000bin objgrpc-1.3.2/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs000066400000000000000000000055611310511640000256140ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Google.Protobuf; using Grpc.Core; using Grpc.Core.Utils; namespace Grpc.Testing { /// /// Implementation of BenchmarkService server /// public class BenchmarkServiceImpl : BenchmarkService.BenchmarkServiceBase { public BenchmarkServiceImpl() { } public override Task UnaryCall(SimpleRequest request, ServerCallContext context) { var response = new SimpleResponse { Payload = CreateZerosPayload(request.ResponseSize) }; return Task.FromResult(response); } public override async Task StreamingCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) { await requestStream.ForEachAsync(async request => { var response = new SimpleResponse { Payload = CreateZerosPayload(request.ResponseSize) }; await responseStream.WriteAsync(response); }); } private static Payload CreateZerosPayload(int size) { return new Payload { Body = ByteString.CopyFrom(new byte[size]) }; } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs000066400000000000000000000347401310511640000243530ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Google.Protobuf; using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Logging; using Grpc.Core.Profiling; using Grpc.Core.Utils; using NUnit.Framework; using Grpc.Testing; namespace Grpc.IntegrationTesting { /// /// Helper methods to start client runners for performance testing. /// public class ClientRunners { static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); // Profilers to use for clients. static readonly BlockingCollection profilers = new BlockingCollection(); internal static void AddProfiler(BasicProfiler profiler) { GrpcPreconditions.CheckNotNull(profiler); profilers.Add(profiler); } /// /// Creates a started client runner. /// public static IClientRunner CreateStarted(ClientConfig config) { Logger.Debug("ClientConfig: {0}", config); if (config.AsyncClientThreads != 0) { Logger.Warning("ClientConfig.AsyncClientThreads is not supported for C#. Ignoring the value"); } if (config.CoreLimit != 0) { Logger.Warning("ClientConfig.CoreLimit is not supported for C#. Ignoring the value"); } if (config.CoreList.Count > 0) { Logger.Warning("ClientConfig.CoreList is not supported for C#. Ignoring the value"); } var channels = CreateChannels(config.ClientChannels, config.ServerTargets, config.SecurityParams); return new ClientRunnerImpl(channels, config.ClientType, config.RpcType, config.OutstandingRpcsPerChannel, config.LoadParams, config.PayloadConfig, config.HistogramParams, () => GetNextProfiler()); } private static List CreateChannels(int clientChannels, IEnumerable serverTargets, SecurityParams securityParams) { GrpcPreconditions.CheckArgument(clientChannels > 0, "clientChannels needs to be at least 1."); GrpcPreconditions.CheckArgument(serverTargets.Count() > 0, "at least one serverTarget needs to be specified."); var credentials = securityParams != null ? TestCredentials.CreateSslCredentials() : ChannelCredentials.Insecure; List channelOptions = null; if (securityParams != null && securityParams.ServerHostOverride != "") { channelOptions = new List { new ChannelOption(ChannelOptions.SslTargetNameOverride, securityParams.ServerHostOverride) }; } var result = new List(); for (int i = 0; i < clientChannels; i++) { var target = serverTargets.ElementAt(i % serverTargets.Count()); var channel = new Channel(target, credentials, channelOptions); result.Add(channel); } return result; } private static BasicProfiler GetNextProfiler() { BasicProfiler result = null; profilers.TryTake(out result); return result; } } internal class ClientRunnerImpl : IClientRunner { const double SecondsToNanos = 1e9; readonly List channels; readonly ClientType clientType; readonly RpcType rpcType; readonly PayloadConfig payloadConfig; readonly Histogram histogram; readonly List runnerTasks; readonly CancellationTokenSource stoppedCts = new CancellationTokenSource(); readonly WallClockStopwatch wallClockStopwatch = new WallClockStopwatch(); readonly AtomicCounter statsResetCount = new AtomicCounter(); public ClientRunnerImpl(List channels, ClientType clientType, RpcType rpcType, int outstandingRpcsPerChannel, LoadParams loadParams, PayloadConfig payloadConfig, HistogramParams histogramParams, Func profilerFactory) { GrpcPreconditions.CheckArgument(outstandingRpcsPerChannel > 0, "outstandingRpcsPerChannel"); GrpcPreconditions.CheckNotNull(histogramParams, "histogramParams"); this.channels = new List(channels); this.clientType = clientType; this.rpcType = rpcType; this.payloadConfig = payloadConfig; this.histogram = new Histogram(histogramParams.Resolution, histogramParams.MaxPossible); this.runnerTasks = new List(); foreach (var channel in this.channels) { for (int i = 0; i < outstandingRpcsPerChannel; i++) { var timer = CreateTimer(loadParams, 1.0 / this.channels.Count / outstandingRpcsPerChannel); var optionalProfiler = profilerFactory(); this.runnerTasks.Add(RunClientAsync(channel, timer, optionalProfiler)); } } } public ClientStats GetStats(bool reset) { var histogramData = histogram.GetSnapshot(reset); var secondsElapsed = wallClockStopwatch.GetElapsedSnapshot(reset).TotalSeconds; if (reset) { statsResetCount.Increment(); } // TODO: populate user time and system time return new ClientStats { Latencies = histogramData, TimeElapsed = secondsElapsed, TimeUser = 0, TimeSystem = 0 }; } public async Task StopAsync() { stoppedCts.Cancel(); foreach (var runnerTask in runnerTasks) { await runnerTask; } foreach (var channel in channels) { await channel.ShutdownAsync(); } } private void RunUnary(Channel channel, IInterarrivalTimer timer, BasicProfiler optionalProfiler) { if (optionalProfiler != null) { Profilers.SetForCurrentThread(optionalProfiler); } bool profilerReset = false; var client = new BenchmarkService.BenchmarkServiceClient(channel); var request = CreateSimpleRequest(); var stopwatch = new Stopwatch(); while (!stoppedCts.Token.IsCancellationRequested) { // after the first stats reset, also reset the profiler. if (optionalProfiler != null && !profilerReset && statsResetCount.Count > 0) { optionalProfiler.Reset(); profilerReset = true; } stopwatch.Restart(); client.UnaryCall(request); stopwatch.Stop(); // spec requires data point in nanoseconds. histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos); timer.WaitForNext(); } } private async Task RunUnaryAsync(Channel channel, IInterarrivalTimer timer) { var client = new BenchmarkService.BenchmarkServiceClient(channel); var request = CreateSimpleRequest(); var stopwatch = new Stopwatch(); while (!stoppedCts.Token.IsCancellationRequested) { stopwatch.Restart(); await client.UnaryCallAsync(request); stopwatch.Stop(); // spec requires data point in nanoseconds. histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos); await timer.WaitForNextAsync(); } } private async Task RunStreamingPingPongAsync(Channel channel, IInterarrivalTimer timer) { var client = new BenchmarkService.BenchmarkServiceClient(channel); var request = CreateSimpleRequest(); var stopwatch = new Stopwatch(); using (var call = client.StreamingCall()) { while (!stoppedCts.Token.IsCancellationRequested) { stopwatch.Restart(); await call.RequestStream.WriteAsync(request); await call.ResponseStream.MoveNext(); stopwatch.Stop(); // spec requires data point in nanoseconds. histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos); await timer.WaitForNextAsync(); } // finish the streaming call await call.RequestStream.CompleteAsync(); Assert.IsFalse(await call.ResponseStream.MoveNext()); } } private async Task RunGenericStreamingAsync(Channel channel, IInterarrivalTimer timer) { var request = CreateByteBufferRequest(); var stopwatch = new Stopwatch(); var callDetails = new CallInvocationDetails(channel, GenericService.StreamingCallMethod, new CallOptions()); using (var call = Calls.AsyncDuplexStreamingCall(callDetails)) { while (!stoppedCts.Token.IsCancellationRequested) { stopwatch.Restart(); await call.RequestStream.WriteAsync(request); await call.ResponseStream.MoveNext(); stopwatch.Stop(); // spec requires data point in nanoseconds. histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos); await timer.WaitForNextAsync(); } // finish the streaming call await call.RequestStream.CompleteAsync(); Assert.IsFalse(await call.ResponseStream.MoveNext()); } } private Task RunClientAsync(Channel channel, IInterarrivalTimer timer, BasicProfiler optionalProfiler) { if (payloadConfig.PayloadCase == PayloadConfig.PayloadOneofCase.BytebufParams) { GrpcPreconditions.CheckArgument(clientType == ClientType.AsyncClient, "Generic client only supports async API"); GrpcPreconditions.CheckArgument(rpcType == RpcType.Streaming, "Generic client only supports streaming calls"); return RunGenericStreamingAsync(channel, timer); } GrpcPreconditions.CheckNotNull(payloadConfig.SimpleParams); if (clientType == ClientType.SyncClient) { GrpcPreconditions.CheckArgument(rpcType == RpcType.Unary, "Sync client can only be used for Unary calls in C#"); // create a dedicated thread for the synchronous client return Task.Factory.StartNew(() => RunUnary(channel, timer, optionalProfiler), TaskCreationOptions.LongRunning); } else if (clientType == ClientType.AsyncClient) { switch (rpcType) { case RpcType.Unary: return RunUnaryAsync(channel, timer); case RpcType.Streaming: return RunStreamingPingPongAsync(channel, timer); } } throw new ArgumentException("Unsupported configuration."); } private SimpleRequest CreateSimpleRequest() { GrpcPreconditions.CheckNotNull(payloadConfig.SimpleParams); return new SimpleRequest { Payload = CreateZerosPayload(payloadConfig.SimpleParams.ReqSize), ResponseSize = payloadConfig.SimpleParams.RespSize }; } private byte[] CreateByteBufferRequest() { return new byte[payloadConfig.BytebufParams.ReqSize]; } private static Payload CreateZerosPayload(int size) { return new Payload { Body = ByteString.CopyFrom(new byte[size]) }; } private static IInterarrivalTimer CreateTimer(LoadParams loadParams, double loadMultiplier) { switch (loadParams.LoadCase) { case LoadParams.LoadOneofCase.ClosedLoop: return new ClosedLoopInterarrivalTimer(); case LoadParams.LoadOneofCase.Poisson: return new PoissonInterarrivalTimer(loadParams.Poisson.OfferedLoad * loadMultiplier); default: throw new ArgumentException("Unknown load type"); } } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/Control.cs000066400000000000000000004344171310511640000232050ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: src/proto/grpc/testing/control.proto #pragma warning disable 1591, 0612, 3021 #region Designer generated code using pb = global::Google.Protobuf; using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; namespace Grpc.Testing { /// Holder for reflection information generated from src/proto/grpc/testing/control.proto public static partial class ControlReflection { #region Descriptor /// File descriptor for src/proto/grpc/testing/control.proto public static pbr::FileDescriptor Descriptor { get { return descriptor; } } private static pbr::FileDescriptor descriptor; static ControlReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "CiRzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL2NvbnRyb2wucHJvdG8SDGdycGMu", "dGVzdGluZxolc3JjL3Byb3RvL2dycGMvdGVzdGluZy9wYXlsb2Fkcy5wcm90", "bxoic3JjL3Byb3RvL2dycGMvdGVzdGluZy9zdGF0cy5wcm90byIlCg1Qb2lz", "c29uUGFyYW1zEhQKDG9mZmVyZWRfbG9hZBgBIAEoASISChBDbG9zZWRMb29w", "UGFyYW1zInsKCkxvYWRQYXJhbXMSNQoLY2xvc2VkX2xvb3AYASABKAsyHi5n", "cnBjLnRlc3RpbmcuQ2xvc2VkTG9vcFBhcmFtc0gAEi4KB3BvaXNzb24YAiAB", "KAsyGy5ncnBjLnRlc3RpbmcuUG9pc3NvblBhcmFtc0gAQgYKBGxvYWQiQwoO", "U2VjdXJpdHlQYXJhbXMSEwoLdXNlX3Rlc3RfY2EYASABKAgSHAoUc2VydmVy", "X2hvc3Rfb3ZlcnJpZGUYAiABKAkiTQoKQ2hhbm5lbEFyZxIMCgRuYW1lGAEg", "ASgJEhMKCXN0cl92YWx1ZRgCIAEoCUgAEhMKCWludF92YWx1ZRgDIAEoBUgA", "QgcKBXZhbHVlIqAECgxDbGllbnRDb25maWcSFgoOc2VydmVyX3RhcmdldHMY", "ASADKAkSLQoLY2xpZW50X3R5cGUYAiABKA4yGC5ncnBjLnRlc3RpbmcuQ2xp", "ZW50VHlwZRI1Cg9zZWN1cml0eV9wYXJhbXMYAyABKAsyHC5ncnBjLnRlc3Rp", "bmcuU2VjdXJpdHlQYXJhbXMSJAocb3V0c3RhbmRpbmdfcnBjc19wZXJfY2hh", "bm5lbBgEIAEoBRIXCg9jbGllbnRfY2hhbm5lbHMYBSABKAUSHAoUYXN5bmNf", "Y2xpZW50X3RocmVhZHMYByABKAUSJwoIcnBjX3R5cGUYCCABKA4yFS5ncnBj", "LnRlc3RpbmcuUnBjVHlwZRItCgtsb2FkX3BhcmFtcxgKIAEoCzIYLmdycGMu", "dGVzdGluZy5Mb2FkUGFyYW1zEjMKDnBheWxvYWRfY29uZmlnGAsgASgLMhsu", "Z3JwYy50ZXN0aW5nLlBheWxvYWRDb25maWcSNwoQaGlzdG9ncmFtX3BhcmFt", "cxgMIAEoCzIdLmdycGMudGVzdGluZy5IaXN0b2dyYW1QYXJhbXMSEQoJY29y", "ZV9saXN0GA0gAygFEhIKCmNvcmVfbGltaXQYDiABKAUSGAoQb3RoZXJfY2xp", "ZW50X2FwaRgPIAEoCRIuCgxjaGFubmVsX2FyZ3MYECADKAsyGC5ncnBjLnRl", "c3RpbmcuQ2hhbm5lbEFyZyI4CgxDbGllbnRTdGF0dXMSKAoFc3RhdHMYASAB", "KAsyGS5ncnBjLnRlc3RpbmcuQ2xpZW50U3RhdHMiFQoETWFyaxINCgVyZXNl", "dBgBIAEoCCJoCgpDbGllbnRBcmdzEisKBXNldHVwGAEgASgLMhouZ3JwYy50", "ZXN0aW5nLkNsaWVudENvbmZpZ0gAEiIKBG1hcmsYAiABKAsyEi5ncnBjLnRl", "c3RpbmcuTWFya0gAQgkKB2FyZ3R5cGUitAIKDFNlcnZlckNvbmZpZxItCgtz", "ZXJ2ZXJfdHlwZRgBIAEoDjIYLmdycGMudGVzdGluZy5TZXJ2ZXJUeXBlEjUK", "D3NlY3VyaXR5X3BhcmFtcxgCIAEoCzIcLmdycGMudGVzdGluZy5TZWN1cml0", "eVBhcmFtcxIMCgRwb3J0GAQgASgFEhwKFGFzeW5jX3NlcnZlcl90aHJlYWRz", "GAcgASgFEhIKCmNvcmVfbGltaXQYCCABKAUSMwoOcGF5bG9hZF9jb25maWcY", "CSABKAsyGy5ncnBjLnRlc3RpbmcuUGF5bG9hZENvbmZpZxIRCgljb3JlX2xp", "c3QYCiADKAUSGAoQb3RoZXJfc2VydmVyX2FwaRgLIAEoCRIcChNyZXNvdXJj", "ZV9xdW90YV9zaXplGOkHIAEoBSJoCgpTZXJ2ZXJBcmdzEisKBXNldHVwGAEg", "ASgLMhouZ3JwYy50ZXN0aW5nLlNlcnZlckNvbmZpZ0gAEiIKBG1hcmsYAiAB", "KAsyEi5ncnBjLnRlc3RpbmcuTWFya0gAQgkKB2FyZ3R5cGUiVQoMU2VydmVy", "U3RhdHVzEigKBXN0YXRzGAEgASgLMhkuZ3JwYy50ZXN0aW5nLlNlcnZlclN0", "YXRzEgwKBHBvcnQYAiABKAUSDQoFY29yZXMYAyABKAUiDQoLQ29yZVJlcXVl", "c3QiHQoMQ29yZVJlc3BvbnNlEg0KBWNvcmVzGAEgASgFIgYKBFZvaWQi/QEK", "CFNjZW5hcmlvEgwKBG5hbWUYASABKAkSMQoNY2xpZW50X2NvbmZpZxgCIAEo", "CzIaLmdycGMudGVzdGluZy5DbGllbnRDb25maWcSEwoLbnVtX2NsaWVudHMY", "AyABKAUSMQoNc2VydmVyX2NvbmZpZxgEIAEoCzIaLmdycGMudGVzdGluZy5T", "ZXJ2ZXJDb25maWcSEwoLbnVtX3NlcnZlcnMYBSABKAUSFgoOd2FybXVwX3Nl", "Y29uZHMYBiABKAUSGQoRYmVuY2htYXJrX3NlY29uZHMYByABKAUSIAoYc3Bh", "d25fbG9jYWxfd29ya2VyX2NvdW50GAggASgFIjYKCVNjZW5hcmlvcxIpCglz", "Y2VuYXJpb3MYASADKAsyFi5ncnBjLnRlc3RpbmcuU2NlbmFyaW8i+AIKFVNj", "ZW5hcmlvUmVzdWx0U3VtbWFyeRILCgNxcHMYASABKAESGwoTcXBzX3Blcl9z", "ZXJ2ZXJfY29yZRgCIAEoARIaChJzZXJ2ZXJfc3lzdGVtX3RpbWUYAyABKAES", "GAoQc2VydmVyX3VzZXJfdGltZRgEIAEoARIaChJjbGllbnRfc3lzdGVtX3Rp", "bWUYBSABKAESGAoQY2xpZW50X3VzZXJfdGltZRgGIAEoARISCgpsYXRlbmN5", "XzUwGAcgASgBEhIKCmxhdGVuY3lfOTAYCCABKAESEgoKbGF0ZW5jeV85NRgJ", "IAEoARISCgpsYXRlbmN5Xzk5GAogASgBEhMKC2xhdGVuY3lfOTk5GAsgASgB", "EhgKEHNlcnZlcl9jcHVfdXNhZ2UYDCABKAESJgoec3VjY2Vzc2Z1bF9yZXF1", "ZXN0c19wZXJfc2Vjb25kGA0gASgBEiIKGmZhaWxlZF9yZXF1ZXN0c19wZXJf", "c2Vjb25kGA4gASgBIoMDCg5TY2VuYXJpb1Jlc3VsdBIoCghzY2VuYXJpbxgB", "IAEoCzIWLmdycGMudGVzdGluZy5TY2VuYXJpbxIuCglsYXRlbmNpZXMYAiAB", "KAsyGy5ncnBjLnRlc3RpbmcuSGlzdG9ncmFtRGF0YRIvCgxjbGllbnRfc3Rh", "dHMYAyADKAsyGS5ncnBjLnRlc3RpbmcuQ2xpZW50U3RhdHMSLwoMc2VydmVy", "X3N0YXRzGAQgAygLMhkuZ3JwYy50ZXN0aW5nLlNlcnZlclN0YXRzEhQKDHNl", "cnZlcl9jb3JlcxgFIAMoBRI0CgdzdW1tYXJ5GAYgASgLMiMuZ3JwYy50ZXN0", "aW5nLlNjZW5hcmlvUmVzdWx0U3VtbWFyeRIWCg5jbGllbnRfc3VjY2VzcxgH", "IAMoCBIWCg5zZXJ2ZXJfc3VjY2VzcxgIIAMoCBI5Cg9yZXF1ZXN0X3Jlc3Vs", "dHMYCSADKAsyIC5ncnBjLnRlc3RpbmcuUmVxdWVzdFJlc3VsdENvdW50KkEK", "CkNsaWVudFR5cGUSDwoLU1lOQ19DTElFTlQQABIQCgxBU1lOQ19DTElFTlQQ", "ARIQCgxPVEhFUl9DTElFTlQQAipbCgpTZXJ2ZXJUeXBlEg8KC1NZTkNfU0VS", "VkVSEAASEAoMQVNZTkNfU0VSVkVSEAESGAoUQVNZTkNfR0VORVJJQ19TRVJW", "RVIQAhIQCgxPVEhFUl9TRVJWRVIQAyojCgdScGNUeXBlEgkKBVVOQVJZEAAS", "DQoJU1RSRUFNSU5HEAFiBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Grpc.Testing.PayloadsReflection.Descriptor, global::Grpc.Testing.StatsReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Grpc.Testing.ClientType), typeof(global::Grpc.Testing.ServerType), typeof(global::Grpc.Testing.RpcType), }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.PoissonParams), global::Grpc.Testing.PoissonParams.Parser, new[]{ "OfferedLoad" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClosedLoopParams), global::Grpc.Testing.ClosedLoopParams.Parser, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.LoadParams), global::Grpc.Testing.LoadParams.Parser, new[]{ "ClosedLoop", "Poisson" }, new[]{ "Load" }, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SecurityParams), global::Grpc.Testing.SecurityParams.Parser, new[]{ "UseTestCa", "ServerHostOverride" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ChannelArg), global::Grpc.Testing.ChannelArg.Parser, new[]{ "Name", "StrValue", "IntValue" }, new[]{ "Value" }, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientConfig), global::Grpc.Testing.ClientConfig.Parser, new[]{ "ServerTargets", "ClientType", "SecurityParams", "OutstandingRpcsPerChannel", "ClientChannels", "AsyncClientThreads", "RpcType", "LoadParams", "PayloadConfig", "HistogramParams", "CoreList", "CoreLimit", "OtherClientApi", "ChannelArgs" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientStatus), global::Grpc.Testing.ClientStatus.Parser, new[]{ "Stats" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Mark), global::Grpc.Testing.Mark.Parser, new[]{ "Reset" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientArgs), global::Grpc.Testing.ClientArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerConfig), global::Grpc.Testing.ServerConfig.Parser, new[]{ "ServerType", "SecurityParams", "Port", "AsyncServerThreads", "CoreLimit", "PayloadConfig", "CoreList", "OtherServerApi", "ResourceQuotaSize" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerArgs), global::Grpc.Testing.ServerArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerStatus), global::Grpc.Testing.ServerStatus.Parser, new[]{ "Stats", "Port", "Cores" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.CoreRequest), global::Grpc.Testing.CoreRequest.Parser, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.CoreResponse), global::Grpc.Testing.CoreResponse.Parser, new[]{ "Cores" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Void), global::Grpc.Testing.Void.Parser, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Scenario), global::Grpc.Testing.Scenario.Parser, new[]{ "Name", "ClientConfig", "NumClients", "ServerConfig", "NumServers", "WarmupSeconds", "BenchmarkSeconds", "SpawnLocalWorkerCount" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Scenarios), global::Grpc.Testing.Scenarios.Parser, new[]{ "Scenarios_" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ScenarioResultSummary), global::Grpc.Testing.ScenarioResultSummary.Parser, new[]{ "Qps", "QpsPerServerCore", "ServerSystemTime", "ServerUserTime", "ClientSystemTime", "ClientUserTime", "Latency50", "Latency90", "Latency95", "Latency99", "Latency999", "ServerCpuUsage", "SuccessfulRequestsPerSecond", "FailedRequestsPerSecond" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ScenarioResult), global::Grpc.Testing.ScenarioResult.Parser, new[]{ "Scenario", "Latencies", "ClientStats", "ServerStats", "ServerCores", "Summary", "ClientSuccess", "ServerSuccess", "RequestResults" }, null, null, null) })); } #endregion } #region Enums public enum ClientType { /// /// Many languages support a basic distinction between using /// sync or async client, and this allows the specification /// [pbr::OriginalName("SYNC_CLIENT")] SyncClient = 0, [pbr::OriginalName("ASYNC_CLIENT")] AsyncClient = 1, /// /// used for some language-specific variants /// [pbr::OriginalName("OTHER_CLIENT")] OtherClient = 2, } public enum ServerType { [pbr::OriginalName("SYNC_SERVER")] SyncServer = 0, [pbr::OriginalName("ASYNC_SERVER")] AsyncServer = 1, [pbr::OriginalName("ASYNC_GENERIC_SERVER")] AsyncGenericServer = 2, /// /// used for some language-specific variants /// [pbr::OriginalName("OTHER_SERVER")] OtherServer = 3, } public enum RpcType { [pbr::OriginalName("UNARY")] Unary = 0, [pbr::OriginalName("STREAMING")] Streaming = 1, } #endregion #region Messages /// /// Parameters of poisson process distribution, which is a good representation /// of activity coming in from independent identical stationary sources. /// public sealed partial class PoissonParams : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new PoissonParams()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public PoissonParams() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public PoissonParams(PoissonParams other) : this() { offeredLoad_ = other.offeredLoad_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public PoissonParams Clone() { return new PoissonParams(this); } /// Field number for the "offered_load" field. public const int OfferedLoadFieldNumber = 1; private double offeredLoad_; /// /// The rate of arrivals (a.k.a. lambda parameter of the exp distribution). /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double OfferedLoad { get { return offeredLoad_; } set { offeredLoad_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as PoissonParams); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(PoissonParams other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (OfferedLoad != other.OfferedLoad) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (OfferedLoad != 0D) hash ^= OfferedLoad.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (OfferedLoad != 0D) { output.WriteRawTag(9); output.WriteDouble(OfferedLoad); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (OfferedLoad != 0D) { size += 1 + 8; } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(PoissonParams other) { if (other == null) { return; } if (other.OfferedLoad != 0D) { OfferedLoad = other.OfferedLoad; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 9: { OfferedLoad = input.ReadDouble(); break; } } } } } /// /// Once an RPC finishes, immediately start a new one. /// No configuration parameters needed. /// public sealed partial class ClosedLoopParams : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ClosedLoopParams()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ClosedLoopParams() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ClosedLoopParams(ClosedLoopParams other) : this() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ClosedLoopParams Clone() { return new ClosedLoopParams(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ClosedLoopParams); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ClosedLoopParams other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ClosedLoopParams other) { if (other == null) { return; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; } } } } public sealed partial class LoadParams : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new LoadParams()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[2]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public LoadParams() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public LoadParams(LoadParams other) : this() { switch (other.LoadCase) { case LoadOneofCase.ClosedLoop: ClosedLoop = other.ClosedLoop.Clone(); break; case LoadOneofCase.Poisson: Poisson = other.Poisson.Clone(); break; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public LoadParams Clone() { return new LoadParams(this); } /// Field number for the "closed_loop" field. public const int ClosedLoopFieldNumber = 1; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.ClosedLoopParams ClosedLoop { get { return loadCase_ == LoadOneofCase.ClosedLoop ? (global::Grpc.Testing.ClosedLoopParams) load_ : null; } set { load_ = value; loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.ClosedLoop; } } /// Field number for the "poisson" field. public const int PoissonFieldNumber = 2; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.PoissonParams Poisson { get { return loadCase_ == LoadOneofCase.Poisson ? (global::Grpc.Testing.PoissonParams) load_ : null; } set { load_ = value; loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.Poisson; } } private object load_; /// Enum of possible cases for the "load" oneof. public enum LoadOneofCase { None = 0, ClosedLoop = 1, Poisson = 2, } private LoadOneofCase loadCase_ = LoadOneofCase.None; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public LoadOneofCase LoadCase { get { return loadCase_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearLoad() { loadCase_ = LoadOneofCase.None; load_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as LoadParams); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(LoadParams other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (!object.Equals(ClosedLoop, other.ClosedLoop)) return false; if (!object.Equals(Poisson, other.Poisson)) return false; if (LoadCase != other.LoadCase) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (loadCase_ == LoadOneofCase.ClosedLoop) hash ^= ClosedLoop.GetHashCode(); if (loadCase_ == LoadOneofCase.Poisson) hash ^= Poisson.GetHashCode(); hash ^= (int) loadCase_; return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (loadCase_ == LoadOneofCase.ClosedLoop) { output.WriteRawTag(10); output.WriteMessage(ClosedLoop); } if (loadCase_ == LoadOneofCase.Poisson) { output.WriteRawTag(18); output.WriteMessage(Poisson); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (loadCase_ == LoadOneofCase.ClosedLoop) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(ClosedLoop); } if (loadCase_ == LoadOneofCase.Poisson) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Poisson); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(LoadParams other) { if (other == null) { return; } switch (other.LoadCase) { case LoadOneofCase.ClosedLoop: ClosedLoop = other.ClosedLoop; break; case LoadOneofCase.Poisson: Poisson = other.Poisson; break; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { global::Grpc.Testing.ClosedLoopParams subBuilder = new global::Grpc.Testing.ClosedLoopParams(); if (loadCase_ == LoadOneofCase.ClosedLoop) { subBuilder.MergeFrom(ClosedLoop); } input.ReadMessage(subBuilder); ClosedLoop = subBuilder; break; } case 18: { global::Grpc.Testing.PoissonParams subBuilder = new global::Grpc.Testing.PoissonParams(); if (loadCase_ == LoadOneofCase.Poisson) { subBuilder.MergeFrom(Poisson); } input.ReadMessage(subBuilder); Poisson = subBuilder; break; } } } } } /// /// presence of SecurityParams implies use of TLS /// public sealed partial class SecurityParams : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SecurityParams()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[3]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public SecurityParams() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public SecurityParams(SecurityParams other) : this() { useTestCa_ = other.useTestCa_; serverHostOverride_ = other.serverHostOverride_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public SecurityParams Clone() { return new SecurityParams(this); } /// Field number for the "use_test_ca" field. public const int UseTestCaFieldNumber = 1; private bool useTestCa_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool UseTestCa { get { return useTestCa_; } set { useTestCa_ = value; } } /// Field number for the "server_host_override" field. public const int ServerHostOverrideFieldNumber = 2; private string serverHostOverride_ = ""; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string ServerHostOverride { get { return serverHostOverride_; } set { serverHostOverride_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as SecurityParams); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(SecurityParams other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (UseTestCa != other.UseTestCa) return false; if (ServerHostOverride != other.ServerHostOverride) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (UseTestCa != false) hash ^= UseTestCa.GetHashCode(); if (ServerHostOverride.Length != 0) hash ^= ServerHostOverride.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (UseTestCa != false) { output.WriteRawTag(8); output.WriteBool(UseTestCa); } if (ServerHostOverride.Length != 0) { output.WriteRawTag(18); output.WriteString(ServerHostOverride); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (UseTestCa != false) { size += 1 + 1; } if (ServerHostOverride.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(ServerHostOverride); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(SecurityParams other) { if (other == null) { return; } if (other.UseTestCa != false) { UseTestCa = other.UseTestCa; } if (other.ServerHostOverride.Length != 0) { ServerHostOverride = other.ServerHostOverride; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { UseTestCa = input.ReadBool(); break; } case 18: { ServerHostOverride = input.ReadString(); break; } } } } } public sealed partial class ChannelArg : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ChannelArg()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[4]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ChannelArg() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ChannelArg(ChannelArg other) : this() { name_ = other.name_; switch (other.ValueCase) { case ValueOneofCase.StrValue: StrValue = other.StrValue; break; case ValueOneofCase.IntValue: IntValue = other.IntValue; break; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ChannelArg Clone() { return new ChannelArg(this); } /// Field number for the "name" field. public const int NameFieldNumber = 1; private string name_ = ""; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Name { get { return name_; } set { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Field number for the "str_value" field. public const int StrValueFieldNumber = 2; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string StrValue { get { return valueCase_ == ValueOneofCase.StrValue ? (string) value_ : ""; } set { value_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); valueCase_ = ValueOneofCase.StrValue; } } /// Field number for the "int_value" field. public const int IntValueFieldNumber = 3; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int IntValue { get { return valueCase_ == ValueOneofCase.IntValue ? (int) value_ : 0; } set { value_ = value; valueCase_ = ValueOneofCase.IntValue; } } private object value_; /// Enum of possible cases for the "value" oneof. public enum ValueOneofCase { None = 0, StrValue = 2, IntValue = 3, } private ValueOneofCase valueCase_ = ValueOneofCase.None; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ValueOneofCase ValueCase { get { return valueCase_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearValue() { valueCase_ = ValueOneofCase.None; value_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ChannelArg); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ChannelArg other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Name != other.Name) return false; if (StrValue != other.StrValue) return false; if (IntValue != other.IntValue) return false; if (ValueCase != other.ValueCase) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Name.Length != 0) hash ^= Name.GetHashCode(); if (valueCase_ == ValueOneofCase.StrValue) hash ^= StrValue.GetHashCode(); if (valueCase_ == ValueOneofCase.IntValue) hash ^= IntValue.GetHashCode(); hash ^= (int) valueCase_; return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); } if (valueCase_ == ValueOneofCase.StrValue) { output.WriteRawTag(18); output.WriteString(StrValue); } if (valueCase_ == ValueOneofCase.IntValue) { output.WriteRawTag(24); output.WriteInt32(IntValue); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Name.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } if (valueCase_ == ValueOneofCase.StrValue) { size += 1 + pb::CodedOutputStream.ComputeStringSize(StrValue); } if (valueCase_ == ValueOneofCase.IntValue) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntValue); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ChannelArg other) { if (other == null) { return; } if (other.Name.Length != 0) { Name = other.Name; } switch (other.ValueCase) { case ValueOneofCase.StrValue: StrValue = other.StrValue; break; case ValueOneofCase.IntValue: IntValue = other.IntValue; break; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { Name = input.ReadString(); break; } case 18: { StrValue = input.ReadString(); break; } case 24: { IntValue = input.ReadInt32(); break; } } } } } public sealed partial class ClientConfig : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ClientConfig()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[5]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ClientConfig() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ClientConfig(ClientConfig other) : this() { serverTargets_ = other.serverTargets_.Clone(); clientType_ = other.clientType_; SecurityParams = other.securityParams_ != null ? other.SecurityParams.Clone() : null; outstandingRpcsPerChannel_ = other.outstandingRpcsPerChannel_; clientChannels_ = other.clientChannels_; asyncClientThreads_ = other.asyncClientThreads_; rpcType_ = other.rpcType_; LoadParams = other.loadParams_ != null ? other.LoadParams.Clone() : null; PayloadConfig = other.payloadConfig_ != null ? other.PayloadConfig.Clone() : null; HistogramParams = other.histogramParams_ != null ? other.HistogramParams.Clone() : null; coreList_ = other.coreList_.Clone(); coreLimit_ = other.coreLimit_; otherClientApi_ = other.otherClientApi_; channelArgs_ = other.channelArgs_.Clone(); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ClientConfig Clone() { return new ClientConfig(this); } /// Field number for the "server_targets" field. public const int ServerTargetsFieldNumber = 1; private static readonly pb::FieldCodec _repeated_serverTargets_codec = pb::FieldCodec.ForString(10); private readonly pbc::RepeatedField serverTargets_ = new pbc::RepeatedField(); /// /// List of targets to connect to. At least one target needs to be specified. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::RepeatedField ServerTargets { get { return serverTargets_; } } /// Field number for the "client_type" field. public const int ClientTypeFieldNumber = 2; private global::Grpc.Testing.ClientType clientType_ = 0; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.ClientType ClientType { get { return clientType_; } set { clientType_ = value; } } /// Field number for the "security_params" field. public const int SecurityParamsFieldNumber = 3; private global::Grpc.Testing.SecurityParams securityParams_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.SecurityParams SecurityParams { get { return securityParams_; } set { securityParams_ = value; } } /// Field number for the "outstanding_rpcs_per_channel" field. public const int OutstandingRpcsPerChannelFieldNumber = 4; private int outstandingRpcsPerChannel_; /// /// How many concurrent RPCs to start for each channel. /// For synchronous client, use a separate thread for each outstanding RPC. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int OutstandingRpcsPerChannel { get { return outstandingRpcsPerChannel_; } set { outstandingRpcsPerChannel_ = value; } } /// Field number for the "client_channels" field. public const int ClientChannelsFieldNumber = 5; private int clientChannels_; /// /// Number of independent client channels to create. /// i-th channel will connect to server_target[i % server_targets.size()] /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int ClientChannels { get { return clientChannels_; } set { clientChannels_ = value; } } /// Field number for the "async_client_threads" field. public const int AsyncClientThreadsFieldNumber = 7; private int asyncClientThreads_; /// /// Only for async client. Number of threads to use to start/manage RPCs. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int AsyncClientThreads { get { return asyncClientThreads_; } set { asyncClientThreads_ = value; } } /// Field number for the "rpc_type" field. public const int RpcTypeFieldNumber = 8; private global::Grpc.Testing.RpcType rpcType_ = 0; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.RpcType RpcType { get { return rpcType_; } set { rpcType_ = value; } } /// Field number for the "load_params" field. public const int LoadParamsFieldNumber = 10; private global::Grpc.Testing.LoadParams loadParams_; /// /// The requested load for the entire client (aggregated over all the threads). /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.LoadParams LoadParams { get { return loadParams_; } set { loadParams_ = value; } } /// Field number for the "payload_config" field. public const int PayloadConfigFieldNumber = 11; private global::Grpc.Testing.PayloadConfig payloadConfig_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.PayloadConfig PayloadConfig { get { return payloadConfig_; } set { payloadConfig_ = value; } } /// Field number for the "histogram_params" field. public const int HistogramParamsFieldNumber = 12; private global::Grpc.Testing.HistogramParams histogramParams_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.HistogramParams HistogramParams { get { return histogramParams_; } set { histogramParams_ = value; } } /// Field number for the "core_list" field. public const int CoreListFieldNumber = 13; private static readonly pb::FieldCodec _repeated_coreList_codec = pb::FieldCodec.ForInt32(106); private readonly pbc::RepeatedField coreList_ = new pbc::RepeatedField(); /// /// Specify the cores we should run the client on, if desired /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::RepeatedField CoreList { get { return coreList_; } } /// Field number for the "core_limit" field. public const int CoreLimitFieldNumber = 14; private int coreLimit_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CoreLimit { get { return coreLimit_; } set { coreLimit_ = value; } } /// Field number for the "other_client_api" field. public const int OtherClientApiFieldNumber = 15; private string otherClientApi_ = ""; /// /// If we use an OTHER_CLIENT client_type, this string gives more detail /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string OtherClientApi { get { return otherClientApi_; } set { otherClientApi_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Field number for the "channel_args" field. public const int ChannelArgsFieldNumber = 16; private static readonly pb::FieldCodec _repeated_channelArgs_codec = pb::FieldCodec.ForMessage(130, global::Grpc.Testing.ChannelArg.Parser); private readonly pbc::RepeatedField channelArgs_ = new pbc::RepeatedField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::RepeatedField ChannelArgs { get { return channelArgs_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ClientConfig); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ClientConfig other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if(!serverTargets_.Equals(other.serverTargets_)) return false; if (ClientType != other.ClientType) return false; if (!object.Equals(SecurityParams, other.SecurityParams)) return false; if (OutstandingRpcsPerChannel != other.OutstandingRpcsPerChannel) return false; if (ClientChannels != other.ClientChannels) return false; if (AsyncClientThreads != other.AsyncClientThreads) return false; if (RpcType != other.RpcType) return false; if (!object.Equals(LoadParams, other.LoadParams)) return false; if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false; if (!object.Equals(HistogramParams, other.HistogramParams)) return false; if(!coreList_.Equals(other.coreList_)) return false; if (CoreLimit != other.CoreLimit) return false; if (OtherClientApi != other.OtherClientApi) return false; if(!channelArgs_.Equals(other.channelArgs_)) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; hash ^= serverTargets_.GetHashCode(); if (ClientType != 0) hash ^= ClientType.GetHashCode(); if (securityParams_ != null) hash ^= SecurityParams.GetHashCode(); if (OutstandingRpcsPerChannel != 0) hash ^= OutstandingRpcsPerChannel.GetHashCode(); if (ClientChannels != 0) hash ^= ClientChannels.GetHashCode(); if (AsyncClientThreads != 0) hash ^= AsyncClientThreads.GetHashCode(); if (RpcType != 0) hash ^= RpcType.GetHashCode(); if (loadParams_ != null) hash ^= LoadParams.GetHashCode(); if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode(); if (histogramParams_ != null) hash ^= HistogramParams.GetHashCode(); hash ^= coreList_.GetHashCode(); if (CoreLimit != 0) hash ^= CoreLimit.GetHashCode(); if (OtherClientApi.Length != 0) hash ^= OtherClientApi.GetHashCode(); hash ^= channelArgs_.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { serverTargets_.WriteTo(output, _repeated_serverTargets_codec); if (ClientType != 0) { output.WriteRawTag(16); output.WriteEnum((int) ClientType); } if (securityParams_ != null) { output.WriteRawTag(26); output.WriteMessage(SecurityParams); } if (OutstandingRpcsPerChannel != 0) { output.WriteRawTag(32); output.WriteInt32(OutstandingRpcsPerChannel); } if (ClientChannels != 0) { output.WriteRawTag(40); output.WriteInt32(ClientChannels); } if (AsyncClientThreads != 0) { output.WriteRawTag(56); output.WriteInt32(AsyncClientThreads); } if (RpcType != 0) { output.WriteRawTag(64); output.WriteEnum((int) RpcType); } if (loadParams_ != null) { output.WriteRawTag(82); output.WriteMessage(LoadParams); } if (payloadConfig_ != null) { output.WriteRawTag(90); output.WriteMessage(PayloadConfig); } if (histogramParams_ != null) { output.WriteRawTag(98); output.WriteMessage(HistogramParams); } coreList_.WriteTo(output, _repeated_coreList_codec); if (CoreLimit != 0) { output.WriteRawTag(112); output.WriteInt32(CoreLimit); } if (OtherClientApi.Length != 0) { output.WriteRawTag(122); output.WriteString(OtherClientApi); } channelArgs_.WriteTo(output, _repeated_channelArgs_codec); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; size += serverTargets_.CalculateSize(_repeated_serverTargets_codec); if (ClientType != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ClientType); } if (securityParams_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(SecurityParams); } if (OutstandingRpcsPerChannel != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(OutstandingRpcsPerChannel); } if (ClientChannels != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(ClientChannels); } if (AsyncClientThreads != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(AsyncClientThreads); } if (RpcType != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) RpcType); } if (loadParams_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(LoadParams); } if (payloadConfig_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(PayloadConfig); } if (histogramParams_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(HistogramParams); } size += coreList_.CalculateSize(_repeated_coreList_codec); if (CoreLimit != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(CoreLimit); } if (OtherClientApi.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(OtherClientApi); } size += channelArgs_.CalculateSize(_repeated_channelArgs_codec); return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ClientConfig other) { if (other == null) { return; } serverTargets_.Add(other.serverTargets_); if (other.ClientType != 0) { ClientType = other.ClientType; } if (other.securityParams_ != null) { if (securityParams_ == null) { securityParams_ = new global::Grpc.Testing.SecurityParams(); } SecurityParams.MergeFrom(other.SecurityParams); } if (other.OutstandingRpcsPerChannel != 0) { OutstandingRpcsPerChannel = other.OutstandingRpcsPerChannel; } if (other.ClientChannels != 0) { ClientChannels = other.ClientChannels; } if (other.AsyncClientThreads != 0) { AsyncClientThreads = other.AsyncClientThreads; } if (other.RpcType != 0) { RpcType = other.RpcType; } if (other.loadParams_ != null) { if (loadParams_ == null) { loadParams_ = new global::Grpc.Testing.LoadParams(); } LoadParams.MergeFrom(other.LoadParams); } if (other.payloadConfig_ != null) { if (payloadConfig_ == null) { payloadConfig_ = new global::Grpc.Testing.PayloadConfig(); } PayloadConfig.MergeFrom(other.PayloadConfig); } if (other.histogramParams_ != null) { if (histogramParams_ == null) { histogramParams_ = new global::Grpc.Testing.HistogramParams(); } HistogramParams.MergeFrom(other.HistogramParams); } coreList_.Add(other.coreList_); if (other.CoreLimit != 0) { CoreLimit = other.CoreLimit; } if (other.OtherClientApi.Length != 0) { OtherClientApi = other.OtherClientApi; } channelArgs_.Add(other.channelArgs_); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { serverTargets_.AddEntriesFrom(input, _repeated_serverTargets_codec); break; } case 16: { clientType_ = (global::Grpc.Testing.ClientType) input.ReadEnum(); break; } case 26: { if (securityParams_ == null) { securityParams_ = new global::Grpc.Testing.SecurityParams(); } input.ReadMessage(securityParams_); break; } case 32: { OutstandingRpcsPerChannel = input.ReadInt32(); break; } case 40: { ClientChannels = input.ReadInt32(); break; } case 56: { AsyncClientThreads = input.ReadInt32(); break; } case 64: { rpcType_ = (global::Grpc.Testing.RpcType) input.ReadEnum(); break; } case 82: { if (loadParams_ == null) { loadParams_ = new global::Grpc.Testing.LoadParams(); } input.ReadMessage(loadParams_); break; } case 90: { if (payloadConfig_ == null) { payloadConfig_ = new global::Grpc.Testing.PayloadConfig(); } input.ReadMessage(payloadConfig_); break; } case 98: { if (histogramParams_ == null) { histogramParams_ = new global::Grpc.Testing.HistogramParams(); } input.ReadMessage(histogramParams_); break; } case 106: case 104: { coreList_.AddEntriesFrom(input, _repeated_coreList_codec); break; } case 112: { CoreLimit = input.ReadInt32(); break; } case 122: { OtherClientApi = input.ReadString(); break; } case 130: { channelArgs_.AddEntriesFrom(input, _repeated_channelArgs_codec); break; } } } } } public sealed partial class ClientStatus : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ClientStatus()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[6]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ClientStatus() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ClientStatus(ClientStatus other) : this() { Stats = other.stats_ != null ? other.Stats.Clone() : null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ClientStatus Clone() { return new ClientStatus(this); } /// Field number for the "stats" field. public const int StatsFieldNumber = 1; private global::Grpc.Testing.ClientStats stats_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.ClientStats Stats { get { return stats_; } set { stats_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ClientStatus); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ClientStatus other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (!object.Equals(Stats, other.Stats)) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (stats_ != null) hash ^= Stats.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (stats_ != null) { output.WriteRawTag(10); output.WriteMessage(Stats); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (stats_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Stats); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ClientStatus other) { if (other == null) { return; } if (other.stats_ != null) { if (stats_ == null) { stats_ = new global::Grpc.Testing.ClientStats(); } Stats.MergeFrom(other.Stats); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { if (stats_ == null) { stats_ = new global::Grpc.Testing.ClientStats(); } input.ReadMessage(stats_); break; } } } } } /// /// Request current stats /// public sealed partial class Mark : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Mark()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[7]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Mark() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Mark(Mark other) : this() { reset_ = other.reset_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Mark Clone() { return new Mark(this); } /// Field number for the "reset" field. public const int ResetFieldNumber = 1; private bool reset_; /// /// if true, the stats will be reset after taking their snapshot. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Reset { get { return reset_; } set { reset_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as Mark); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(Mark other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Reset != other.Reset) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Reset != false) hash ^= Reset.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Reset != false) { output.WriteRawTag(8); output.WriteBool(Reset); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Reset != false) { size += 1 + 1; } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(Mark other) { if (other == null) { return; } if (other.Reset != false) { Reset = other.Reset; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { Reset = input.ReadBool(); break; } } } } } public sealed partial class ClientArgs : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ClientArgs()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[8]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ClientArgs() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ClientArgs(ClientArgs other) : this() { switch (other.ArgtypeCase) { case ArgtypeOneofCase.Setup: Setup = other.Setup.Clone(); break; case ArgtypeOneofCase.Mark: Mark = other.Mark.Clone(); break; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ClientArgs Clone() { return new ClientArgs(this); } /// Field number for the "setup" field. public const int SetupFieldNumber = 1; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.ClientConfig Setup { get { return argtypeCase_ == ArgtypeOneofCase.Setup ? (global::Grpc.Testing.ClientConfig) argtype_ : null; } set { argtype_ = value; argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Setup; } } /// Field number for the "mark" field. public const int MarkFieldNumber = 2; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.Mark Mark { get { return argtypeCase_ == ArgtypeOneofCase.Mark ? (global::Grpc.Testing.Mark) argtype_ : null; } set { argtype_ = value; argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Mark; } } private object argtype_; /// Enum of possible cases for the "argtype" oneof. public enum ArgtypeOneofCase { None = 0, Setup = 1, Mark = 2, } private ArgtypeOneofCase argtypeCase_ = ArgtypeOneofCase.None; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ArgtypeOneofCase ArgtypeCase { get { return argtypeCase_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearArgtype() { argtypeCase_ = ArgtypeOneofCase.None; argtype_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ClientArgs); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ClientArgs other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (!object.Equals(Setup, other.Setup)) return false; if (!object.Equals(Mark, other.Mark)) return false; if (ArgtypeCase != other.ArgtypeCase) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (argtypeCase_ == ArgtypeOneofCase.Setup) hash ^= Setup.GetHashCode(); if (argtypeCase_ == ArgtypeOneofCase.Mark) hash ^= Mark.GetHashCode(); hash ^= (int) argtypeCase_; return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (argtypeCase_ == ArgtypeOneofCase.Setup) { output.WriteRawTag(10); output.WriteMessage(Setup); } if (argtypeCase_ == ArgtypeOneofCase.Mark) { output.WriteRawTag(18); output.WriteMessage(Mark); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (argtypeCase_ == ArgtypeOneofCase.Setup) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Setup); } if (argtypeCase_ == ArgtypeOneofCase.Mark) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Mark); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ClientArgs other) { if (other == null) { return; } switch (other.ArgtypeCase) { case ArgtypeOneofCase.Setup: Setup = other.Setup; break; case ArgtypeOneofCase.Mark: Mark = other.Mark; break; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { global::Grpc.Testing.ClientConfig subBuilder = new global::Grpc.Testing.ClientConfig(); if (argtypeCase_ == ArgtypeOneofCase.Setup) { subBuilder.MergeFrom(Setup); } input.ReadMessage(subBuilder); Setup = subBuilder; break; } case 18: { global::Grpc.Testing.Mark subBuilder = new global::Grpc.Testing.Mark(); if (argtypeCase_ == ArgtypeOneofCase.Mark) { subBuilder.MergeFrom(Mark); } input.ReadMessage(subBuilder); Mark = subBuilder; break; } } } } } public sealed partial class ServerConfig : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ServerConfig()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[9]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServerConfig() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServerConfig(ServerConfig other) : this() { serverType_ = other.serverType_; SecurityParams = other.securityParams_ != null ? other.SecurityParams.Clone() : null; port_ = other.port_; asyncServerThreads_ = other.asyncServerThreads_; coreLimit_ = other.coreLimit_; PayloadConfig = other.payloadConfig_ != null ? other.PayloadConfig.Clone() : null; coreList_ = other.coreList_.Clone(); otherServerApi_ = other.otherServerApi_; resourceQuotaSize_ = other.resourceQuotaSize_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServerConfig Clone() { return new ServerConfig(this); } /// Field number for the "server_type" field. public const int ServerTypeFieldNumber = 1; private global::Grpc.Testing.ServerType serverType_ = 0; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.ServerType ServerType { get { return serverType_; } set { serverType_ = value; } } /// Field number for the "security_params" field. public const int SecurityParamsFieldNumber = 2; private global::Grpc.Testing.SecurityParams securityParams_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.SecurityParams SecurityParams { get { return securityParams_; } set { securityParams_ = value; } } /// Field number for the "port" field. public const int PortFieldNumber = 4; private int port_; /// /// Port on which to listen. Zero means pick unused port. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int Port { get { return port_; } set { port_ = value; } } /// Field number for the "async_server_threads" field. public const int AsyncServerThreadsFieldNumber = 7; private int asyncServerThreads_; /// /// Only for async server. Number of threads used to serve the requests. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int AsyncServerThreads { get { return asyncServerThreads_; } set { asyncServerThreads_ = value; } } /// Field number for the "core_limit" field. public const int CoreLimitFieldNumber = 8; private int coreLimit_; /// /// Specify the number of cores to limit server to, if desired /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CoreLimit { get { return coreLimit_; } set { coreLimit_ = value; } } /// Field number for the "payload_config" field. public const int PayloadConfigFieldNumber = 9; private global::Grpc.Testing.PayloadConfig payloadConfig_; /// /// payload config, used in generic server. /// Note this must NOT be used in proto (non-generic) servers. For proto servers, /// 'response sizes' must be configured from the 'response_size' field of the /// 'SimpleRequest' objects in RPC requests. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.PayloadConfig PayloadConfig { get { return payloadConfig_; } set { payloadConfig_ = value; } } /// Field number for the "core_list" field. public const int CoreListFieldNumber = 10; private static readonly pb::FieldCodec _repeated_coreList_codec = pb::FieldCodec.ForInt32(82); private readonly pbc::RepeatedField coreList_ = new pbc::RepeatedField(); /// /// Specify the cores we should run the server on, if desired /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::RepeatedField CoreList { get { return coreList_; } } /// Field number for the "other_server_api" field. public const int OtherServerApiFieldNumber = 11; private string otherServerApi_ = ""; /// /// If we use an OTHER_SERVER client_type, this string gives more detail /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string OtherServerApi { get { return otherServerApi_; } set { otherServerApi_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Field number for the "resource_quota_size" field. public const int ResourceQuotaSizeFieldNumber = 1001; private int resourceQuotaSize_; /// /// Buffer pool size (no buffer pool specified if unset) /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int ResourceQuotaSize { get { return resourceQuotaSize_; } set { resourceQuotaSize_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ServerConfig); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ServerConfig other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (ServerType != other.ServerType) return false; if (!object.Equals(SecurityParams, other.SecurityParams)) return false; if (Port != other.Port) return false; if (AsyncServerThreads != other.AsyncServerThreads) return false; if (CoreLimit != other.CoreLimit) return false; if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false; if(!coreList_.Equals(other.coreList_)) return false; if (OtherServerApi != other.OtherServerApi) return false; if (ResourceQuotaSize != other.ResourceQuotaSize) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (ServerType != 0) hash ^= ServerType.GetHashCode(); if (securityParams_ != null) hash ^= SecurityParams.GetHashCode(); if (Port != 0) hash ^= Port.GetHashCode(); if (AsyncServerThreads != 0) hash ^= AsyncServerThreads.GetHashCode(); if (CoreLimit != 0) hash ^= CoreLimit.GetHashCode(); if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode(); hash ^= coreList_.GetHashCode(); if (OtherServerApi.Length != 0) hash ^= OtherServerApi.GetHashCode(); if (ResourceQuotaSize != 0) hash ^= ResourceQuotaSize.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (ServerType != 0) { output.WriteRawTag(8); output.WriteEnum((int) ServerType); } if (securityParams_ != null) { output.WriteRawTag(18); output.WriteMessage(SecurityParams); } if (Port != 0) { output.WriteRawTag(32); output.WriteInt32(Port); } if (AsyncServerThreads != 0) { output.WriteRawTag(56); output.WriteInt32(AsyncServerThreads); } if (CoreLimit != 0) { output.WriteRawTag(64); output.WriteInt32(CoreLimit); } if (payloadConfig_ != null) { output.WriteRawTag(74); output.WriteMessage(PayloadConfig); } coreList_.WriteTo(output, _repeated_coreList_codec); if (OtherServerApi.Length != 0) { output.WriteRawTag(90); output.WriteString(OtherServerApi); } if (ResourceQuotaSize != 0) { output.WriteRawTag(200, 62); output.WriteInt32(ResourceQuotaSize); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (ServerType != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ServerType); } if (securityParams_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(SecurityParams); } if (Port != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(Port); } if (AsyncServerThreads != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(AsyncServerThreads); } if (CoreLimit != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(CoreLimit); } if (payloadConfig_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(PayloadConfig); } size += coreList_.CalculateSize(_repeated_coreList_codec); if (OtherServerApi.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(OtherServerApi); } if (ResourceQuotaSize != 0) { size += 2 + pb::CodedOutputStream.ComputeInt32Size(ResourceQuotaSize); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ServerConfig other) { if (other == null) { return; } if (other.ServerType != 0) { ServerType = other.ServerType; } if (other.securityParams_ != null) { if (securityParams_ == null) { securityParams_ = new global::Grpc.Testing.SecurityParams(); } SecurityParams.MergeFrom(other.SecurityParams); } if (other.Port != 0) { Port = other.Port; } if (other.AsyncServerThreads != 0) { AsyncServerThreads = other.AsyncServerThreads; } if (other.CoreLimit != 0) { CoreLimit = other.CoreLimit; } if (other.payloadConfig_ != null) { if (payloadConfig_ == null) { payloadConfig_ = new global::Grpc.Testing.PayloadConfig(); } PayloadConfig.MergeFrom(other.PayloadConfig); } coreList_.Add(other.coreList_); if (other.OtherServerApi.Length != 0) { OtherServerApi = other.OtherServerApi; } if (other.ResourceQuotaSize != 0) { ResourceQuotaSize = other.ResourceQuotaSize; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { serverType_ = (global::Grpc.Testing.ServerType) input.ReadEnum(); break; } case 18: { if (securityParams_ == null) { securityParams_ = new global::Grpc.Testing.SecurityParams(); } input.ReadMessage(securityParams_); break; } case 32: { Port = input.ReadInt32(); break; } case 56: { AsyncServerThreads = input.ReadInt32(); break; } case 64: { CoreLimit = input.ReadInt32(); break; } case 74: { if (payloadConfig_ == null) { payloadConfig_ = new global::Grpc.Testing.PayloadConfig(); } input.ReadMessage(payloadConfig_); break; } case 82: case 80: { coreList_.AddEntriesFrom(input, _repeated_coreList_codec); break; } case 90: { OtherServerApi = input.ReadString(); break; } case 8008: { ResourceQuotaSize = input.ReadInt32(); break; } } } } } public sealed partial class ServerArgs : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ServerArgs()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[10]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServerArgs() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServerArgs(ServerArgs other) : this() { switch (other.ArgtypeCase) { case ArgtypeOneofCase.Setup: Setup = other.Setup.Clone(); break; case ArgtypeOneofCase.Mark: Mark = other.Mark.Clone(); break; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServerArgs Clone() { return new ServerArgs(this); } /// Field number for the "setup" field. public const int SetupFieldNumber = 1; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.ServerConfig Setup { get { return argtypeCase_ == ArgtypeOneofCase.Setup ? (global::Grpc.Testing.ServerConfig) argtype_ : null; } set { argtype_ = value; argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Setup; } } /// Field number for the "mark" field. public const int MarkFieldNumber = 2; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.Mark Mark { get { return argtypeCase_ == ArgtypeOneofCase.Mark ? (global::Grpc.Testing.Mark) argtype_ : null; } set { argtype_ = value; argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Mark; } } private object argtype_; /// Enum of possible cases for the "argtype" oneof. public enum ArgtypeOneofCase { None = 0, Setup = 1, Mark = 2, } private ArgtypeOneofCase argtypeCase_ = ArgtypeOneofCase.None; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ArgtypeOneofCase ArgtypeCase { get { return argtypeCase_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearArgtype() { argtypeCase_ = ArgtypeOneofCase.None; argtype_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ServerArgs); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ServerArgs other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (!object.Equals(Setup, other.Setup)) return false; if (!object.Equals(Mark, other.Mark)) return false; if (ArgtypeCase != other.ArgtypeCase) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (argtypeCase_ == ArgtypeOneofCase.Setup) hash ^= Setup.GetHashCode(); if (argtypeCase_ == ArgtypeOneofCase.Mark) hash ^= Mark.GetHashCode(); hash ^= (int) argtypeCase_; return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (argtypeCase_ == ArgtypeOneofCase.Setup) { output.WriteRawTag(10); output.WriteMessage(Setup); } if (argtypeCase_ == ArgtypeOneofCase.Mark) { output.WriteRawTag(18); output.WriteMessage(Mark); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (argtypeCase_ == ArgtypeOneofCase.Setup) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Setup); } if (argtypeCase_ == ArgtypeOneofCase.Mark) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Mark); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ServerArgs other) { if (other == null) { return; } switch (other.ArgtypeCase) { case ArgtypeOneofCase.Setup: Setup = other.Setup; break; case ArgtypeOneofCase.Mark: Mark = other.Mark; break; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { global::Grpc.Testing.ServerConfig subBuilder = new global::Grpc.Testing.ServerConfig(); if (argtypeCase_ == ArgtypeOneofCase.Setup) { subBuilder.MergeFrom(Setup); } input.ReadMessage(subBuilder); Setup = subBuilder; break; } case 18: { global::Grpc.Testing.Mark subBuilder = new global::Grpc.Testing.Mark(); if (argtypeCase_ == ArgtypeOneofCase.Mark) { subBuilder.MergeFrom(Mark); } input.ReadMessage(subBuilder); Mark = subBuilder; break; } } } } } public sealed partial class ServerStatus : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ServerStatus()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[11]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServerStatus() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServerStatus(ServerStatus other) : this() { Stats = other.stats_ != null ? other.Stats.Clone() : null; port_ = other.port_; cores_ = other.cores_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServerStatus Clone() { return new ServerStatus(this); } /// Field number for the "stats" field. public const int StatsFieldNumber = 1; private global::Grpc.Testing.ServerStats stats_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.ServerStats Stats { get { return stats_; } set { stats_ = value; } } /// Field number for the "port" field. public const int PortFieldNumber = 2; private int port_; /// /// the port bound by the server /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int Port { get { return port_; } set { port_ = value; } } /// Field number for the "cores" field. public const int CoresFieldNumber = 3; private int cores_; /// /// Number of cores available to the server /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int Cores { get { return cores_; } set { cores_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ServerStatus); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ServerStatus other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (!object.Equals(Stats, other.Stats)) return false; if (Port != other.Port) return false; if (Cores != other.Cores) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (stats_ != null) hash ^= Stats.GetHashCode(); if (Port != 0) hash ^= Port.GetHashCode(); if (Cores != 0) hash ^= Cores.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (stats_ != null) { output.WriteRawTag(10); output.WriteMessage(Stats); } if (Port != 0) { output.WriteRawTag(16); output.WriteInt32(Port); } if (Cores != 0) { output.WriteRawTag(24); output.WriteInt32(Cores); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (stats_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Stats); } if (Port != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(Port); } if (Cores != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(Cores); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ServerStatus other) { if (other == null) { return; } if (other.stats_ != null) { if (stats_ == null) { stats_ = new global::Grpc.Testing.ServerStats(); } Stats.MergeFrom(other.Stats); } if (other.Port != 0) { Port = other.Port; } if (other.Cores != 0) { Cores = other.Cores; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { if (stats_ == null) { stats_ = new global::Grpc.Testing.ServerStats(); } input.ReadMessage(stats_); break; } case 16: { Port = input.ReadInt32(); break; } case 24: { Cores = input.ReadInt32(); break; } } } } } public sealed partial class CoreRequest : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CoreRequest()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[12]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public CoreRequest() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public CoreRequest(CoreRequest other) : this() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public CoreRequest Clone() { return new CoreRequest(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as CoreRequest); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(CoreRequest other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(CoreRequest other) { if (other == null) { return; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; } } } } public sealed partial class CoreResponse : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CoreResponse()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[13]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public CoreResponse() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public CoreResponse(CoreResponse other) : this() { cores_ = other.cores_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public CoreResponse Clone() { return new CoreResponse(this); } /// Field number for the "cores" field. public const int CoresFieldNumber = 1; private int cores_; /// /// Number of cores available on the server /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int Cores { get { return cores_; } set { cores_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as CoreResponse); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(CoreResponse other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Cores != other.Cores) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Cores != 0) hash ^= Cores.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Cores != 0) { output.WriteRawTag(8); output.WriteInt32(Cores); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Cores != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(Cores); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(CoreResponse other) { if (other == null) { return; } if (other.Cores != 0) { Cores = other.Cores; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { Cores = input.ReadInt32(); break; } } } } } public sealed partial class Void : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Void()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[14]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Void() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Void(Void other) : this() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Void Clone() { return new Void(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as Void); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(Void other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(Void other) { if (other == null) { return; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; } } } } /// /// A single performance scenario: input to qps_json_driver /// public sealed partial class Scenario : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Scenario()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[15]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Scenario() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Scenario(Scenario other) : this() { name_ = other.name_; ClientConfig = other.clientConfig_ != null ? other.ClientConfig.Clone() : null; numClients_ = other.numClients_; ServerConfig = other.serverConfig_ != null ? other.ServerConfig.Clone() : null; numServers_ = other.numServers_; warmupSeconds_ = other.warmupSeconds_; benchmarkSeconds_ = other.benchmarkSeconds_; spawnLocalWorkerCount_ = other.spawnLocalWorkerCount_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Scenario Clone() { return new Scenario(this); } /// Field number for the "name" field. public const int NameFieldNumber = 1; private string name_ = ""; /// /// Human readable name for this scenario /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Name { get { return name_; } set { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Field number for the "client_config" field. public const int ClientConfigFieldNumber = 2; private global::Grpc.Testing.ClientConfig clientConfig_; /// /// Client configuration /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.ClientConfig ClientConfig { get { return clientConfig_; } set { clientConfig_ = value; } } /// Field number for the "num_clients" field. public const int NumClientsFieldNumber = 3; private int numClients_; /// /// Number of clients to start for the test /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int NumClients { get { return numClients_; } set { numClients_ = value; } } /// Field number for the "server_config" field. public const int ServerConfigFieldNumber = 4; private global::Grpc.Testing.ServerConfig serverConfig_; /// /// Server configuration /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.ServerConfig ServerConfig { get { return serverConfig_; } set { serverConfig_ = value; } } /// Field number for the "num_servers" field. public const int NumServersFieldNumber = 5; private int numServers_; /// /// Number of servers to start for the test /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int NumServers { get { return numServers_; } set { numServers_ = value; } } /// Field number for the "warmup_seconds" field. public const int WarmupSecondsFieldNumber = 6; private int warmupSeconds_; /// /// Warmup period, in seconds /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int WarmupSeconds { get { return warmupSeconds_; } set { warmupSeconds_ = value; } } /// Field number for the "benchmark_seconds" field. public const int BenchmarkSecondsFieldNumber = 7; private int benchmarkSeconds_; /// /// Benchmark time, in seconds /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int BenchmarkSeconds { get { return benchmarkSeconds_; } set { benchmarkSeconds_ = value; } } /// Field number for the "spawn_local_worker_count" field. public const int SpawnLocalWorkerCountFieldNumber = 8; private int spawnLocalWorkerCount_; /// /// Number of workers to spawn locally (usually zero) /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int SpawnLocalWorkerCount { get { return spawnLocalWorkerCount_; } set { spawnLocalWorkerCount_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as Scenario); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(Scenario other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Name != other.Name) return false; if (!object.Equals(ClientConfig, other.ClientConfig)) return false; if (NumClients != other.NumClients) return false; if (!object.Equals(ServerConfig, other.ServerConfig)) return false; if (NumServers != other.NumServers) return false; if (WarmupSeconds != other.WarmupSeconds) return false; if (BenchmarkSeconds != other.BenchmarkSeconds) return false; if (SpawnLocalWorkerCount != other.SpawnLocalWorkerCount) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Name.Length != 0) hash ^= Name.GetHashCode(); if (clientConfig_ != null) hash ^= ClientConfig.GetHashCode(); if (NumClients != 0) hash ^= NumClients.GetHashCode(); if (serverConfig_ != null) hash ^= ServerConfig.GetHashCode(); if (NumServers != 0) hash ^= NumServers.GetHashCode(); if (WarmupSeconds != 0) hash ^= WarmupSeconds.GetHashCode(); if (BenchmarkSeconds != 0) hash ^= BenchmarkSeconds.GetHashCode(); if (SpawnLocalWorkerCount != 0) hash ^= SpawnLocalWorkerCount.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); } if (clientConfig_ != null) { output.WriteRawTag(18); output.WriteMessage(ClientConfig); } if (NumClients != 0) { output.WriteRawTag(24); output.WriteInt32(NumClients); } if (serverConfig_ != null) { output.WriteRawTag(34); output.WriteMessage(ServerConfig); } if (NumServers != 0) { output.WriteRawTag(40); output.WriteInt32(NumServers); } if (WarmupSeconds != 0) { output.WriteRawTag(48); output.WriteInt32(WarmupSeconds); } if (BenchmarkSeconds != 0) { output.WriteRawTag(56); output.WriteInt32(BenchmarkSeconds); } if (SpawnLocalWorkerCount != 0) { output.WriteRawTag(64); output.WriteInt32(SpawnLocalWorkerCount); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Name.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } if (clientConfig_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(ClientConfig); } if (NumClients != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(NumClients); } if (serverConfig_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(ServerConfig); } if (NumServers != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(NumServers); } if (WarmupSeconds != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(WarmupSeconds); } if (BenchmarkSeconds != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(BenchmarkSeconds); } if (SpawnLocalWorkerCount != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(SpawnLocalWorkerCount); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(Scenario other) { if (other == null) { return; } if (other.Name.Length != 0) { Name = other.Name; } if (other.clientConfig_ != null) { if (clientConfig_ == null) { clientConfig_ = new global::Grpc.Testing.ClientConfig(); } ClientConfig.MergeFrom(other.ClientConfig); } if (other.NumClients != 0) { NumClients = other.NumClients; } if (other.serverConfig_ != null) { if (serverConfig_ == null) { serverConfig_ = new global::Grpc.Testing.ServerConfig(); } ServerConfig.MergeFrom(other.ServerConfig); } if (other.NumServers != 0) { NumServers = other.NumServers; } if (other.WarmupSeconds != 0) { WarmupSeconds = other.WarmupSeconds; } if (other.BenchmarkSeconds != 0) { BenchmarkSeconds = other.BenchmarkSeconds; } if (other.SpawnLocalWorkerCount != 0) { SpawnLocalWorkerCount = other.SpawnLocalWorkerCount; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { Name = input.ReadString(); break; } case 18: { if (clientConfig_ == null) { clientConfig_ = new global::Grpc.Testing.ClientConfig(); } input.ReadMessage(clientConfig_); break; } case 24: { NumClients = input.ReadInt32(); break; } case 34: { if (serverConfig_ == null) { serverConfig_ = new global::Grpc.Testing.ServerConfig(); } input.ReadMessage(serverConfig_); break; } case 40: { NumServers = input.ReadInt32(); break; } case 48: { WarmupSeconds = input.ReadInt32(); break; } case 56: { BenchmarkSeconds = input.ReadInt32(); break; } case 64: { SpawnLocalWorkerCount = input.ReadInt32(); break; } } } } } /// /// A set of scenarios to be run with qps_json_driver /// public sealed partial class Scenarios : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Scenarios()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[16]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Scenarios() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Scenarios(Scenarios other) : this() { scenarios_ = other.scenarios_.Clone(); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Scenarios Clone() { return new Scenarios(this); } /// Field number for the "scenarios" field. public const int Scenarios_FieldNumber = 1; private static readonly pb::FieldCodec _repeated_scenarios_codec = pb::FieldCodec.ForMessage(10, global::Grpc.Testing.Scenario.Parser); private readonly pbc::RepeatedField scenarios_ = new pbc::RepeatedField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::RepeatedField Scenarios_ { get { return scenarios_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as Scenarios); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(Scenarios other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if(!scenarios_.Equals(other.scenarios_)) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; hash ^= scenarios_.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { scenarios_.WriteTo(output, _repeated_scenarios_codec); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; size += scenarios_.CalculateSize(_repeated_scenarios_codec); return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(Scenarios other) { if (other == null) { return; } scenarios_.Add(other.scenarios_); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { scenarios_.AddEntriesFrom(input, _repeated_scenarios_codec); break; } } } } } /// /// Basic summary that can be computed from ClientStats and ServerStats /// once the scenario has finished. /// public sealed partial class ScenarioResultSummary : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ScenarioResultSummary()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[17]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ScenarioResultSummary() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ScenarioResultSummary(ScenarioResultSummary other) : this() { qps_ = other.qps_; qpsPerServerCore_ = other.qpsPerServerCore_; serverSystemTime_ = other.serverSystemTime_; serverUserTime_ = other.serverUserTime_; clientSystemTime_ = other.clientSystemTime_; clientUserTime_ = other.clientUserTime_; latency50_ = other.latency50_; latency90_ = other.latency90_; latency95_ = other.latency95_; latency99_ = other.latency99_; latency999_ = other.latency999_; serverCpuUsage_ = other.serverCpuUsage_; successfulRequestsPerSecond_ = other.successfulRequestsPerSecond_; failedRequestsPerSecond_ = other.failedRequestsPerSecond_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ScenarioResultSummary Clone() { return new ScenarioResultSummary(this); } /// Field number for the "qps" field. public const int QpsFieldNumber = 1; private double qps_; /// /// Total number of operations per second over all clients. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double Qps { get { return qps_; } set { qps_ = value; } } /// Field number for the "qps_per_server_core" field. public const int QpsPerServerCoreFieldNumber = 2; private double qpsPerServerCore_; /// /// QPS per one server core. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double QpsPerServerCore { get { return qpsPerServerCore_; } set { qpsPerServerCore_ = value; } } /// Field number for the "server_system_time" field. public const int ServerSystemTimeFieldNumber = 3; private double serverSystemTime_; /// /// server load based on system_time (0.85 => 85%) /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double ServerSystemTime { get { return serverSystemTime_; } set { serverSystemTime_ = value; } } /// Field number for the "server_user_time" field. public const int ServerUserTimeFieldNumber = 4; private double serverUserTime_; /// /// server load based on user_time (0.85 => 85%) /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double ServerUserTime { get { return serverUserTime_; } set { serverUserTime_ = value; } } /// Field number for the "client_system_time" field. public const int ClientSystemTimeFieldNumber = 5; private double clientSystemTime_; /// /// client load based on system_time (0.85 => 85%) /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double ClientSystemTime { get { return clientSystemTime_; } set { clientSystemTime_ = value; } } /// Field number for the "client_user_time" field. public const int ClientUserTimeFieldNumber = 6; private double clientUserTime_; /// /// client load based on user_time (0.85 => 85%) /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double ClientUserTime { get { return clientUserTime_; } set { clientUserTime_ = value; } } /// Field number for the "latency_50" field. public const int Latency50FieldNumber = 7; private double latency50_; /// /// X% latency percentiles (in nanoseconds) /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double Latency50 { get { return latency50_; } set { latency50_ = value; } } /// Field number for the "latency_90" field. public const int Latency90FieldNumber = 8; private double latency90_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double Latency90 { get { return latency90_; } set { latency90_ = value; } } /// Field number for the "latency_95" field. public const int Latency95FieldNumber = 9; private double latency95_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double Latency95 { get { return latency95_; } set { latency95_ = value; } } /// Field number for the "latency_99" field. public const int Latency99FieldNumber = 10; private double latency99_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double Latency99 { get { return latency99_; } set { latency99_ = value; } } /// Field number for the "latency_999" field. public const int Latency999FieldNumber = 11; private double latency999_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double Latency999 { get { return latency999_; } set { latency999_ = value; } } /// Field number for the "server_cpu_usage" field. public const int ServerCpuUsageFieldNumber = 12; private double serverCpuUsage_; /// /// server cpu usage percentage /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double ServerCpuUsage { get { return serverCpuUsage_; } set { serverCpuUsage_ = value; } } /// Field number for the "successful_requests_per_second" field. public const int SuccessfulRequestsPerSecondFieldNumber = 13; private double successfulRequestsPerSecond_; /// /// Number of requests that succeeded/failed /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double SuccessfulRequestsPerSecond { get { return successfulRequestsPerSecond_; } set { successfulRequestsPerSecond_ = value; } } /// Field number for the "failed_requests_per_second" field. public const int FailedRequestsPerSecondFieldNumber = 14; private double failedRequestsPerSecond_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double FailedRequestsPerSecond { get { return failedRequestsPerSecond_; } set { failedRequestsPerSecond_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ScenarioResultSummary); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ScenarioResultSummary other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Qps != other.Qps) return false; if (QpsPerServerCore != other.QpsPerServerCore) return false; if (ServerSystemTime != other.ServerSystemTime) return false; if (ServerUserTime != other.ServerUserTime) return false; if (ClientSystemTime != other.ClientSystemTime) return false; if (ClientUserTime != other.ClientUserTime) return false; if (Latency50 != other.Latency50) return false; if (Latency90 != other.Latency90) return false; if (Latency95 != other.Latency95) return false; if (Latency99 != other.Latency99) return false; if (Latency999 != other.Latency999) return false; if (ServerCpuUsage != other.ServerCpuUsage) return false; if (SuccessfulRequestsPerSecond != other.SuccessfulRequestsPerSecond) return false; if (FailedRequestsPerSecond != other.FailedRequestsPerSecond) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Qps != 0D) hash ^= Qps.GetHashCode(); if (QpsPerServerCore != 0D) hash ^= QpsPerServerCore.GetHashCode(); if (ServerSystemTime != 0D) hash ^= ServerSystemTime.GetHashCode(); if (ServerUserTime != 0D) hash ^= ServerUserTime.GetHashCode(); if (ClientSystemTime != 0D) hash ^= ClientSystemTime.GetHashCode(); if (ClientUserTime != 0D) hash ^= ClientUserTime.GetHashCode(); if (Latency50 != 0D) hash ^= Latency50.GetHashCode(); if (Latency90 != 0D) hash ^= Latency90.GetHashCode(); if (Latency95 != 0D) hash ^= Latency95.GetHashCode(); if (Latency99 != 0D) hash ^= Latency99.GetHashCode(); if (Latency999 != 0D) hash ^= Latency999.GetHashCode(); if (ServerCpuUsage != 0D) hash ^= ServerCpuUsage.GetHashCode(); if (SuccessfulRequestsPerSecond != 0D) hash ^= SuccessfulRequestsPerSecond.GetHashCode(); if (FailedRequestsPerSecond != 0D) hash ^= FailedRequestsPerSecond.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Qps != 0D) { output.WriteRawTag(9); output.WriteDouble(Qps); } if (QpsPerServerCore != 0D) { output.WriteRawTag(17); output.WriteDouble(QpsPerServerCore); } if (ServerSystemTime != 0D) { output.WriteRawTag(25); output.WriteDouble(ServerSystemTime); } if (ServerUserTime != 0D) { output.WriteRawTag(33); output.WriteDouble(ServerUserTime); } if (ClientSystemTime != 0D) { output.WriteRawTag(41); output.WriteDouble(ClientSystemTime); } if (ClientUserTime != 0D) { output.WriteRawTag(49); output.WriteDouble(ClientUserTime); } if (Latency50 != 0D) { output.WriteRawTag(57); output.WriteDouble(Latency50); } if (Latency90 != 0D) { output.WriteRawTag(65); output.WriteDouble(Latency90); } if (Latency95 != 0D) { output.WriteRawTag(73); output.WriteDouble(Latency95); } if (Latency99 != 0D) { output.WriteRawTag(81); output.WriteDouble(Latency99); } if (Latency999 != 0D) { output.WriteRawTag(89); output.WriteDouble(Latency999); } if (ServerCpuUsage != 0D) { output.WriteRawTag(97); output.WriteDouble(ServerCpuUsage); } if (SuccessfulRequestsPerSecond != 0D) { output.WriteRawTag(105); output.WriteDouble(SuccessfulRequestsPerSecond); } if (FailedRequestsPerSecond != 0D) { output.WriteRawTag(113); output.WriteDouble(FailedRequestsPerSecond); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Qps != 0D) { size += 1 + 8; } if (QpsPerServerCore != 0D) { size += 1 + 8; } if (ServerSystemTime != 0D) { size += 1 + 8; } if (ServerUserTime != 0D) { size += 1 + 8; } if (ClientSystemTime != 0D) { size += 1 + 8; } if (ClientUserTime != 0D) { size += 1 + 8; } if (Latency50 != 0D) { size += 1 + 8; } if (Latency90 != 0D) { size += 1 + 8; } if (Latency95 != 0D) { size += 1 + 8; } if (Latency99 != 0D) { size += 1 + 8; } if (Latency999 != 0D) { size += 1 + 8; } if (ServerCpuUsage != 0D) { size += 1 + 8; } if (SuccessfulRequestsPerSecond != 0D) { size += 1 + 8; } if (FailedRequestsPerSecond != 0D) { size += 1 + 8; } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ScenarioResultSummary other) { if (other == null) { return; } if (other.Qps != 0D) { Qps = other.Qps; } if (other.QpsPerServerCore != 0D) { QpsPerServerCore = other.QpsPerServerCore; } if (other.ServerSystemTime != 0D) { ServerSystemTime = other.ServerSystemTime; } if (other.ServerUserTime != 0D) { ServerUserTime = other.ServerUserTime; } if (other.ClientSystemTime != 0D) { ClientSystemTime = other.ClientSystemTime; } if (other.ClientUserTime != 0D) { ClientUserTime = other.ClientUserTime; } if (other.Latency50 != 0D) { Latency50 = other.Latency50; } if (other.Latency90 != 0D) { Latency90 = other.Latency90; } if (other.Latency95 != 0D) { Latency95 = other.Latency95; } if (other.Latency99 != 0D) { Latency99 = other.Latency99; } if (other.Latency999 != 0D) { Latency999 = other.Latency999; } if (other.ServerCpuUsage != 0D) { ServerCpuUsage = other.ServerCpuUsage; } if (other.SuccessfulRequestsPerSecond != 0D) { SuccessfulRequestsPerSecond = other.SuccessfulRequestsPerSecond; } if (other.FailedRequestsPerSecond != 0D) { FailedRequestsPerSecond = other.FailedRequestsPerSecond; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 9: { Qps = input.ReadDouble(); break; } case 17: { QpsPerServerCore = input.ReadDouble(); break; } case 25: { ServerSystemTime = input.ReadDouble(); break; } case 33: { ServerUserTime = input.ReadDouble(); break; } case 41: { ClientSystemTime = input.ReadDouble(); break; } case 49: { ClientUserTime = input.ReadDouble(); break; } case 57: { Latency50 = input.ReadDouble(); break; } case 65: { Latency90 = input.ReadDouble(); break; } case 73: { Latency95 = input.ReadDouble(); break; } case 81: { Latency99 = input.ReadDouble(); break; } case 89: { Latency999 = input.ReadDouble(); break; } case 97: { ServerCpuUsage = input.ReadDouble(); break; } case 105: { SuccessfulRequestsPerSecond = input.ReadDouble(); break; } case 113: { FailedRequestsPerSecond = input.ReadDouble(); break; } } } } } /// /// Results of a single benchmark scenario. /// public sealed partial class ScenarioResult : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ScenarioResult()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[18]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ScenarioResult() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ScenarioResult(ScenarioResult other) : this() { Scenario = other.scenario_ != null ? other.Scenario.Clone() : null; Latencies = other.latencies_ != null ? other.Latencies.Clone() : null; clientStats_ = other.clientStats_.Clone(); serverStats_ = other.serverStats_.Clone(); serverCores_ = other.serverCores_.Clone(); Summary = other.summary_ != null ? other.Summary.Clone() : null; clientSuccess_ = other.clientSuccess_.Clone(); serverSuccess_ = other.serverSuccess_.Clone(); requestResults_ = other.requestResults_.Clone(); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ScenarioResult Clone() { return new ScenarioResult(this); } /// Field number for the "scenario" field. public const int ScenarioFieldNumber = 1; private global::Grpc.Testing.Scenario scenario_; /// /// Inputs used to run the scenario. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.Scenario Scenario { get { return scenario_; } set { scenario_ = value; } } /// Field number for the "latencies" field. public const int LatenciesFieldNumber = 2; private global::Grpc.Testing.HistogramData latencies_; /// /// Histograms from all clients merged into one histogram. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.HistogramData Latencies { get { return latencies_; } set { latencies_ = value; } } /// Field number for the "client_stats" field. public const int ClientStatsFieldNumber = 3; private static readonly pb::FieldCodec _repeated_clientStats_codec = pb::FieldCodec.ForMessage(26, global::Grpc.Testing.ClientStats.Parser); private readonly pbc::RepeatedField clientStats_ = new pbc::RepeatedField(); /// /// Client stats for each client /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::RepeatedField ClientStats { get { return clientStats_; } } /// Field number for the "server_stats" field. public const int ServerStatsFieldNumber = 4; private static readonly pb::FieldCodec _repeated_serverStats_codec = pb::FieldCodec.ForMessage(34, global::Grpc.Testing.ServerStats.Parser); private readonly pbc::RepeatedField serverStats_ = new pbc::RepeatedField(); /// /// Server stats for each server /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::RepeatedField ServerStats { get { return serverStats_; } } /// Field number for the "server_cores" field. public const int ServerCoresFieldNumber = 5; private static readonly pb::FieldCodec _repeated_serverCores_codec = pb::FieldCodec.ForInt32(42); private readonly pbc::RepeatedField serverCores_ = new pbc::RepeatedField(); /// /// Number of cores available to each server /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::RepeatedField ServerCores { get { return serverCores_; } } /// Field number for the "summary" field. public const int SummaryFieldNumber = 6; private global::Grpc.Testing.ScenarioResultSummary summary_; /// /// An after-the-fact computed summary /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.ScenarioResultSummary Summary { get { return summary_; } set { summary_ = value; } } /// Field number for the "client_success" field. public const int ClientSuccessFieldNumber = 7; private static readonly pb::FieldCodec _repeated_clientSuccess_codec = pb::FieldCodec.ForBool(58); private readonly pbc::RepeatedField clientSuccess_ = new pbc::RepeatedField(); /// /// Information on success or failure of each worker /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::RepeatedField ClientSuccess { get { return clientSuccess_; } } /// Field number for the "server_success" field. public const int ServerSuccessFieldNumber = 8; private static readonly pb::FieldCodec _repeated_serverSuccess_codec = pb::FieldCodec.ForBool(66); private readonly pbc::RepeatedField serverSuccess_ = new pbc::RepeatedField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::RepeatedField ServerSuccess { get { return serverSuccess_; } } /// Field number for the "request_results" field. public const int RequestResultsFieldNumber = 9; private static readonly pb::FieldCodec _repeated_requestResults_codec = pb::FieldCodec.ForMessage(74, global::Grpc.Testing.RequestResultCount.Parser); private readonly pbc::RepeatedField requestResults_ = new pbc::RepeatedField(); /// /// Number of failed requests (one row per status code seen) /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::RepeatedField RequestResults { get { return requestResults_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ScenarioResult); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ScenarioResult other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (!object.Equals(Scenario, other.Scenario)) return false; if (!object.Equals(Latencies, other.Latencies)) return false; if(!clientStats_.Equals(other.clientStats_)) return false; if(!serverStats_.Equals(other.serverStats_)) return false; if(!serverCores_.Equals(other.serverCores_)) return false; if (!object.Equals(Summary, other.Summary)) return false; if(!clientSuccess_.Equals(other.clientSuccess_)) return false; if(!serverSuccess_.Equals(other.serverSuccess_)) return false; if(!requestResults_.Equals(other.requestResults_)) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (scenario_ != null) hash ^= Scenario.GetHashCode(); if (latencies_ != null) hash ^= Latencies.GetHashCode(); hash ^= clientStats_.GetHashCode(); hash ^= serverStats_.GetHashCode(); hash ^= serverCores_.GetHashCode(); if (summary_ != null) hash ^= Summary.GetHashCode(); hash ^= clientSuccess_.GetHashCode(); hash ^= serverSuccess_.GetHashCode(); hash ^= requestResults_.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (scenario_ != null) { output.WriteRawTag(10); output.WriteMessage(Scenario); } if (latencies_ != null) { output.WriteRawTag(18); output.WriteMessage(Latencies); } clientStats_.WriteTo(output, _repeated_clientStats_codec); serverStats_.WriteTo(output, _repeated_serverStats_codec); serverCores_.WriteTo(output, _repeated_serverCores_codec); if (summary_ != null) { output.WriteRawTag(50); output.WriteMessage(Summary); } clientSuccess_.WriteTo(output, _repeated_clientSuccess_codec); serverSuccess_.WriteTo(output, _repeated_serverSuccess_codec); requestResults_.WriteTo(output, _repeated_requestResults_codec); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (scenario_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Scenario); } if (latencies_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Latencies); } size += clientStats_.CalculateSize(_repeated_clientStats_codec); size += serverStats_.CalculateSize(_repeated_serverStats_codec); size += serverCores_.CalculateSize(_repeated_serverCores_codec); if (summary_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Summary); } size += clientSuccess_.CalculateSize(_repeated_clientSuccess_codec); size += serverSuccess_.CalculateSize(_repeated_serverSuccess_codec); size += requestResults_.CalculateSize(_repeated_requestResults_codec); return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ScenarioResult other) { if (other == null) { return; } if (other.scenario_ != null) { if (scenario_ == null) { scenario_ = new global::Grpc.Testing.Scenario(); } Scenario.MergeFrom(other.Scenario); } if (other.latencies_ != null) { if (latencies_ == null) { latencies_ = new global::Grpc.Testing.HistogramData(); } Latencies.MergeFrom(other.Latencies); } clientStats_.Add(other.clientStats_); serverStats_.Add(other.serverStats_); serverCores_.Add(other.serverCores_); if (other.summary_ != null) { if (summary_ == null) { summary_ = new global::Grpc.Testing.ScenarioResultSummary(); } Summary.MergeFrom(other.Summary); } clientSuccess_.Add(other.clientSuccess_); serverSuccess_.Add(other.serverSuccess_); requestResults_.Add(other.requestResults_); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { if (scenario_ == null) { scenario_ = new global::Grpc.Testing.Scenario(); } input.ReadMessage(scenario_); break; } case 18: { if (latencies_ == null) { latencies_ = new global::Grpc.Testing.HistogramData(); } input.ReadMessage(latencies_); break; } case 26: { clientStats_.AddEntriesFrom(input, _repeated_clientStats_codec); break; } case 34: { serverStats_.AddEntriesFrom(input, _repeated_serverStats_codec); break; } case 42: case 40: { serverCores_.AddEntriesFrom(input, _repeated_serverCores_codec); break; } case 50: { if (summary_ == null) { summary_ = new global::Grpc.Testing.ScenarioResultSummary(); } input.ReadMessage(summary_); break; } case 58: case 56: { clientSuccess_.AddEntriesFrom(input, _repeated_clientSuccess_codec); break; } case 66: case 64: { serverSuccess_.AddEntriesFrom(input, _repeated_serverSuccess_codec); break; } case 74: { requestResults_.AddEntriesFrom(input, _repeated_requestResults_codec); break; } } } } } #endregion } #endregion Designer generated code grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/Empty.cs000066400000000000000000000104271310511640000226520ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: src/proto/grpc/testing/empty.proto #pragma warning disable 1591, 0612, 3021 #region Designer generated code using pb = global::Google.Protobuf; using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; namespace Grpc.Testing { /// Holder for reflection information generated from src/proto/grpc/testing/empty.proto public static partial class EmptyReflection { #region Descriptor /// File descriptor for src/proto/grpc/testing/empty.proto public static pbr::FileDescriptor Descriptor { get { return descriptor; } } private static pbr::FileDescriptor descriptor; static EmptyReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "CiJzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL2VtcHR5LnByb3RvEgxncnBjLnRl", "c3RpbmciBwoFRW1wdHliBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Empty), global::Grpc.Testing.Empty.Parser, null, null, null, null) })); } #endregion } #region Messages /// /// An empty message that you can re-use to avoid defining duplicated empty /// messages in your project. A typical example is to use it as argument or the /// return value of a service API. For instance: /// /// service Foo { /// rpc Bar (grpc.testing.Empty) returns (grpc.testing.Empty) { }; /// }; /// public sealed partial class Empty : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Empty()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.EmptyReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Empty() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Empty(Empty other) : this() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Empty Clone() { return new Empty(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as Empty); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(Empty other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(Empty other) { if (other == null) { return; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; } } } } #endregion } #endregion Designer generated code grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs000066400000000000000000000100141310511640000254410ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Utils; using Grpc.Testing; using NUnit.Framework; namespace Grpc.IntegrationTesting { public class GeneratedClientTest { TestService.TestServiceClient unimplementedClient = new UnimplementedTestServiceClient(); [Test] public void ExpandedParamOverloadCanBeMocked() { var expected = new SimpleResponse(); var mockClient = new Moq.Mock(); // mocking is relatively clumsy because one needs to specify value for all the optional params. mockClient.Setup(m => m.UnaryCall(Moq.It.IsAny(), null, null, CancellationToken.None)).Returns(expected); Assert.AreSame(expected, mockClient.Object.UnaryCall(new SimpleRequest())); } [Test] public void CallOptionsOverloadCanBeMocked() { var expected = new SimpleResponse(); var mockClient = new Moq.Mock(); mockClient.Setup(m => m.UnaryCall(Moq.It.IsAny(), Moq.It.IsAny())).Returns(expected); Assert.AreSame(expected, mockClient.Object.UnaryCall(new SimpleRequest(), new CallOptions())); } [Test] public void DefaultMethodStubThrows_UnaryCall() { Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.UnaryCall(new SimpleRequest())); } [Test] public void DefaultMethodStubThrows_ClientStreaming() { Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.StreamingInputCall()); } [Test] public void DefaultMethodStubThrows_ServerStreaming() { Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.StreamingOutputCall(new StreamingOutputCallRequest())); } [Test] public void DefaultMethodStubThrows_DuplexStreaming() { Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.FullDuplexCall()); } /// /// Subclass of the generated client that doesn't override any method stubs. /// private class UnimplementedTestServiceClient : TestService.TestServiceClient { } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/GeneratedServiceBaseTest.cs000066400000000000000000000104351310511640000264250ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Utils; using Grpc.Testing; using NUnit.Framework; namespace Grpc.IntegrationTesting { public class GeneratedServiceBaseTest { const string Host = "localhost"; Server server; Channel channel; TestService.TestServiceClient client; [SetUp] public void Init() { // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) { Services = { TestService.BindService(new UnimplementedTestServiceImpl()) }, Ports = { { Host, ServerPort.PickUnused, SslServerCredentials.Insecure } } }; server.Start(); channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure); client = new TestService.TestServiceClient(channel); } [TearDown] public void Cleanup() { channel.ShutdownAsync().Wait(); server.ShutdownAsync().Wait(); } [Test] public void UnimplementedByDefault_Unary() { var ex = Assert.Throws(() => client.UnaryCall(new SimpleRequest { })); Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode); } [Test] public async Task UnimplementedByDefault_ClientStreaming() { var call = client.StreamingInputCall(); var ex = Assert.ThrowsAsync(async () => await call); Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode); } [Test] public async Task UnimplementedByDefault_ServerStreamingCall() { var call = client.StreamingOutputCall(new StreamingOutputCallRequest()); var ex = Assert.ThrowsAsync(async () => await call.ResponseStream.MoveNext()); Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode); } [Test] public async Task UnimplementedByDefault_DuplexStreamingCall() { var call = client.FullDuplexCall(); var ex = Assert.ThrowsAsync(async () => await call.ResponseStream.MoveNext()); Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode); } /// /// Implementation of TestService that doesn't override any methods. /// private class UnimplementedTestServiceImpl : TestService.TestServiceBase { } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/GenericService.cs000066400000000000000000000053701310511640000244520ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; using Google.Protobuf; using Grpc.Core; using Grpc.Core.Utils; using NUnit.Framework; using Grpc.Testing; namespace Grpc.IntegrationTesting { /// /// Utility methods for defining and calling a service that doesn't use protobufs /// for serialization/deserialization. /// public static class GenericService { readonly static Marshaller ByteArrayMarshaller = new Marshaller((b) => b, (b) => b); public readonly static Method StreamingCallMethod = new Method( MethodType.DuplexStreaming, "grpc.testing.BenchmarkService", "StreamingCall", ByteArrayMarshaller, ByteArrayMarshaller ); public static ServerServiceDefinition BindHandler(DuplexStreamingServerMethod handler) { return ServerServiceDefinition.CreateBuilder() .AddMethod(StreamingCallMethod, handler).Build(); } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj000077500000000000000000000040111310511640000271550ustar00rootroot00000000000000 net45;netcoreapp1.0 Grpc.IntegrationTesting Exe Grpc.IntegrationTesting $(PackageTargetFallback);portable-net45 1.0.4 PreserveNewest false PreserveNewest false PreserveNewest false grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/Histogram.cs000066400000000000000000000113361310511640000235110ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Google.Protobuf; using Grpc.Core; using Grpc.Core.Utils; using NUnit.Framework; using Grpc.Testing; namespace Grpc.IntegrationTesting { /// /// Basic implementation of histogram based on grpc/support/histogram.h. /// public class Histogram { readonly object myLock = new object(); readonly double multiplier; readonly double oneOnLogMultiplier; readonly double maxPossible; readonly uint[] buckets; int count; double sum; double sumOfSquares; double min; double max; public Histogram(double resolution, double maxPossible) { GrpcPreconditions.CheckArgument(resolution > 0); GrpcPreconditions.CheckArgument(maxPossible > 0); this.maxPossible = maxPossible; this.multiplier = 1.0 + resolution; this.oneOnLogMultiplier = 1.0 / Math.Log(1.0 + resolution); this.buckets = new uint[FindBucket(maxPossible) + 1]; ResetUnsafe(); } public void AddObservation(double value) { lock (myLock) { AddObservationUnsafe(value); } } /// /// Gets snapshot of stats and reset /// public HistogramData GetSnapshot(bool reset = false) { lock (myLock) { return GetSnapshotUnsafe(reset); } } /// /// Finds bucket index to which given observation should go. /// private int FindBucket(double value) { value = Math.Max(value, 1.0); value = Math.Min(value, this.maxPossible); return (int)(Math.Log(value) * oneOnLogMultiplier); } private void AddObservationUnsafe(double value) { this.count++; this.sum += value; this.sumOfSquares += value * value; this.min = Math.Min(this.min, value); this.max = Math.Max(this.max, value); this.buckets[FindBucket(value)]++; } private HistogramData GetSnapshotUnsafe(bool reset) { var data = new HistogramData { Count = count, Sum = sum, SumOfSquares = sumOfSquares, MinSeen = min, MaxSeen = max, Bucket = { buckets } }; if (reset) { ResetUnsafe(); } return data; } private void ResetUnsafe() { this.count = 0; this.sum = 0; this.sumOfSquares = 0; this.min = double.PositiveInfinity; this.max = double.NegativeInfinity; for (int i = 0; i < this.buckets.Length; i++) { this.buckets[i] = 0; } } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/HistogramTest.cs000066400000000000000000000075631310511640000243600ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Utils; using Grpc.Testing; using NUnit.Framework; namespace Grpc.IntegrationTesting { public class HistogramTest { [Test] public void Simple() { var hist = new Histogram(0.01, 60e9); hist.AddObservation(10000); hist.AddObservation(10000); hist.AddObservation(11000); hist.AddObservation(11000); var data = hist.GetSnapshot(); Assert.AreEqual(4, data.Count); Assert.AreEqual(42000.0, data.Sum, 1e-6); Assert.AreEqual(10000, data.MinSeen); Assert.AreEqual(11000, data.MaxSeen); Assert.AreEqual(2.0*10000*10000 + 2.0*11000*11000, data.SumOfSquares, 1e-6); // 1.01^925 < 10000 < 1.01^926 Assert.AreEqual(2, data.Bucket[925]); Assert.AreEqual(2, data.Bucket[935]); } [Test] public void ExtremeObservations() { var hist = new Histogram(0.01, 60e9); hist.AddObservation(-0.5); // should be in the first bucket hist.AddObservation(1e12); // should be in the last bucket var data = hist.GetSnapshot(); Assert.AreEqual(1, data.Bucket[0]); Assert.AreEqual(1, data.Bucket[data.Bucket.Count - 1]); } [Test] public void Reset() { var hist = new Histogram(0.01, 60e9); hist.AddObservation(10000); hist.AddObservation(11000); var data = hist.GetSnapshot(true); // snapshot contains data before reset Assert.AreEqual(2, data.Count); Assert.AreEqual(10000, data.MinSeen); Assert.AreEqual(11000, data.MaxSeen); data = hist.GetSnapshot(); // snapshot contains state after reset Assert.AreEqual(0, data.Count); Assert.AreEqual(double.PositiveInfinity, data.MinSeen); Assert.AreEqual(double.NegativeInfinity, data.MaxSeen); Assert.AreEqual(0, data.Sum); Assert.AreEqual(0, data.SumOfSquares); CollectionAssert.AreEqual(new uint[data.Bucket.Count], data.Bucket); } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/IClientRunner.cs000066400000000000000000000045651310511640000243030ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; using Google.Protobuf; using Grpc.Core; using Grpc.Core.Utils; using NUnit.Framework; using Grpc.Testing; namespace Grpc.IntegrationTesting { /// /// Abstract client runner. /// public interface IClientRunner { /// /// Gets stats snapshot. /// /// The stats. ClientStats GetStats(bool reset); /// /// Asynchronously stops the client. /// /// Task that finishes when client has come to a full stop. Task StopAsync(); } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/IServerRunner.cs000066400000000000000000000047601310511640000243300ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; using Google.Protobuf; using Grpc.Core; using Grpc.Core.Utils; using NUnit.Framework; using Grpc.Testing; namespace Grpc.IntegrationTesting { /// /// Abstract server runner. /// public interface IServerRunner { /// /// Port on which the server is listening. /// int BoundPort { get; } /// /// Gets server stats. /// /// The stats. ServerStats GetStats(bool reset); /// /// Asynchronously stops the server. /// /// Task that finishes when server has shutdown. Task StopAsync(); } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/InterarrivalTimers.cs000066400000000000000000000115161310511640000254020ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Google.Protobuf; using Grpc.Core; using Grpc.Core.Utils; using Grpc.Testing; namespace Grpc.IntegrationTesting { public interface IInterarrivalTimer { void WaitForNext(); Task WaitForNextAsync(); } /// /// Interarrival timer that doesn't wait at all. /// public class ClosedLoopInterarrivalTimer : IInterarrivalTimer { public ClosedLoopInterarrivalTimer() { } public void WaitForNext() { // NOP } public Task WaitForNextAsync() { return TaskUtils.CompletedTask; } } /// /// Interarrival timer that generates Poisson process load. /// public class PoissonInterarrivalTimer : IInterarrivalTimer { readonly ExponentialDistribution exponentialDistribution; DateTime? lastEventTime; public PoissonInterarrivalTimer(double offeredLoad) { this.exponentialDistribution = new ExponentialDistribution(new Random(), offeredLoad); this.lastEventTime = DateTime.UtcNow; } public void WaitForNext() { var waitDuration = GetNextWaitDuration(); int millisTimeout = (int) Math.Round(waitDuration.TotalMilliseconds); if (millisTimeout > 0) { // TODO(jtattermusch): probably only works well for a relatively low interarrival rate Thread.Sleep(millisTimeout); } } public async Task WaitForNextAsync() { var waitDuration = GetNextWaitDuration(); int millisTimeout = (int) Math.Round(waitDuration.TotalMilliseconds); if (millisTimeout > 0) { // TODO(jtattermusch): probably only works well for a relatively low interarrival rate await Task.Delay(millisTimeout); } } private TimeSpan GetNextWaitDuration() { if (!lastEventTime.HasValue) { this.lastEventTime = DateTime.Now; } var origLastEventTime = this.lastEventTime.Value; this.lastEventTime = origLastEventTime + TimeSpan.FromSeconds(exponentialDistribution.Next()); return this.lastEventTime.Value - origLastEventTime; } /// /// Exp generator. /// private class ExponentialDistribution { readonly Random random; readonly double lambda; readonly double lambdaReciprocal; public ExponentialDistribution(Random random, double lambda) { this.random = random; this.lambda = lambda; this.lambdaReciprocal = 1.0 / lambda; } public double Next() { double uniform = random.NextDouble(); // Use 1.0-uni above to avoid NaN if uni is 0 return lambdaReciprocal * (-Math.Log(1.0 - uniform)); } } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/InteropClient.cs000066400000000000000000000716311310511640000243370ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using CommandLine; using CommandLine.Text; using Google.Apis.Auth.OAuth2; using Google.Protobuf; using Grpc.Auth; using Grpc.Core; using Grpc.Core.Logging; using Grpc.Core.Utils; using Grpc.Testing; using Newtonsoft.Json.Linq; using NUnit.Framework; namespace Grpc.IntegrationTesting { public class InteropClient { private class ClientOptions { [Option("server_host", Default = "localhost")] public string ServerHost { get; set; } [Option("server_host_override", Default = TestCredentials.DefaultHostOverride)] public string ServerHostOverride { get; set; } [Option("server_port", Required = true)] public int ServerPort { get; set; } [Option("test_case", Default = "large_unary")] public string TestCase { get; set; } // Deliberately using nullable bool type to allow --use_tls=true syntax (as opposed to --use_tls) [Option("use_tls", Default = false)] public bool? UseTls { get; set; } // Deliberately using nullable bool type to allow --use_test_ca=true syntax (as opposed to --use_test_ca) [Option("use_test_ca", Default = false)] public bool? UseTestCa { get; set; } [Option("default_service_account", Required = false)] public string DefaultServiceAccount { get; set; } [Option("oauth_scope", Required = false)] public string OAuthScope { get; set; } [Option("service_account_key_file", Required = false)] public string ServiceAccountKeyFile { get; set; } } ClientOptions options; private InteropClient(ClientOptions options) { this.options = options; } public static void Run(string[] args) { GrpcEnvironment.SetLogger(new ConsoleLogger()); var parserResult = Parser.Default.ParseArguments(args) .WithNotParsed(errors => Environment.Exit(1)) .WithParsed(options => { var interopClient = new InteropClient(options); interopClient.Run().Wait(); }); } private async Task Run() { var credentials = await CreateCredentialsAsync(); List channelOptions = null; if (!string.IsNullOrEmpty(options.ServerHostOverride)) { channelOptions = new List { new ChannelOption(ChannelOptions.SslTargetNameOverride, options.ServerHostOverride) }; } var channel = new Channel(options.ServerHost, options.ServerPort, credentials, channelOptions); await RunTestCaseAsync(channel, options); await channel.ShutdownAsync(); } private async Task CreateCredentialsAsync() { var credentials = ChannelCredentials.Insecure; if (options.UseTls.Value) { credentials = options.UseTestCa.Value ? TestCredentials.CreateSslCredentials() : new SslCredentials(); } if (options.TestCase == "jwt_token_creds") { var googleCredential = await GoogleCredential.GetApplicationDefaultAsync(); Assert.IsTrue(googleCredential.IsCreateScopedRequired); credentials = ChannelCredentials.Create(credentials, googleCredential.ToCallCredentials()); } if (options.TestCase == "compute_engine_creds") { var googleCredential = await GoogleCredential.GetApplicationDefaultAsync(); Assert.IsFalse(googleCredential.IsCreateScopedRequired); credentials = ChannelCredentials.Create(credentials, googleCredential.ToCallCredentials()); } return credentials; } private async Task RunTestCaseAsync(Channel channel, ClientOptions options) { var client = new TestService.TestServiceClient(channel); switch (options.TestCase) { case "empty_unary": RunEmptyUnary(client); break; case "large_unary": RunLargeUnary(client); break; case "client_streaming": await RunClientStreamingAsync(client); break; case "server_streaming": await RunServerStreamingAsync(client); break; case "ping_pong": await RunPingPongAsync(client); break; case "empty_stream": await RunEmptyStreamAsync(client); break; case "compute_engine_creds": RunComputeEngineCreds(client, options.DefaultServiceAccount, options.OAuthScope); break; case "jwt_token_creds": RunJwtTokenCreds(client); break; case "oauth2_auth_token": await RunOAuth2AuthTokenAsync(client, options.OAuthScope); break; case "per_rpc_creds": await RunPerRpcCredsAsync(client, options.OAuthScope); break; case "cancel_after_begin": await RunCancelAfterBeginAsync(client); break; case "cancel_after_first_response": await RunCancelAfterFirstResponseAsync(client); break; case "timeout_on_sleeping_server": await RunTimeoutOnSleepingServerAsync(client); break; case "custom_metadata": await RunCustomMetadataAsync(client); break; case "status_code_and_message": await RunStatusCodeAndMessageAsync(client); break; case "unimplemented_service": RunUnimplementedService(new UnimplementedService.UnimplementedServiceClient(channel)); break; case "unimplemented_method": RunUnimplementedMethod(client); break; case "client_compressed_unary": RunClientCompressedUnary(client); break; case "client_compressed_streaming": await RunClientCompressedStreamingAsync(client); break; default: throw new ArgumentException("Unknown test case " + options.TestCase); } } public static void RunEmptyUnary(TestService.TestServiceClient client) { Console.WriteLine("running empty_unary"); var response = client.EmptyCall(new Empty()); Assert.IsNotNull(response); Console.WriteLine("Passed!"); } public static void RunLargeUnary(TestService.TestServiceClient client) { Console.WriteLine("running large_unary"); var request = new SimpleRequest { ResponseSize = 314159, Payload = CreateZerosPayload(271828) }; var response = client.UnaryCall(request); Assert.AreEqual(314159, response.Payload.Body.Length); Console.WriteLine("Passed!"); } public static async Task RunClientStreamingAsync(TestService.TestServiceClient client) { Console.WriteLine("running client_streaming"); var bodySizes = new List { 27182, 8, 1828, 45904 }.Select((size) => new StreamingInputCallRequest { Payload = CreateZerosPayload(size) }); using (var call = client.StreamingInputCall()) { await call.RequestStream.WriteAllAsync(bodySizes); var response = await call.ResponseAsync; Assert.AreEqual(74922, response.AggregatedPayloadSize); } Console.WriteLine("Passed!"); } public static async Task RunServerStreamingAsync(TestService.TestServiceClient client) { Console.WriteLine("running server_streaming"); var bodySizes = new List { 31415, 9, 2653, 58979 }; var request = new StreamingOutputCallRequest { ResponseParameters = { bodySizes.Select((size) => new ResponseParameters { Size = size }) } }; using (var call = client.StreamingOutputCall(request)) { var responseList = await call.ResponseStream.ToListAsync(); CollectionAssert.AreEqual(bodySizes, responseList.Select((item) => item.Payload.Body.Length)); } Console.WriteLine("Passed!"); } public static async Task RunPingPongAsync(TestService.TestServiceClient client) { Console.WriteLine("running ping_pong"); using (var call = client.FullDuplexCall()) { await call.RequestStream.WriteAsync(new StreamingOutputCallRequest { ResponseParameters = { new ResponseParameters { Size = 31415 } }, Payload = CreateZerosPayload(27182) }); Assert.IsTrue(await call.ResponseStream.MoveNext()); Assert.AreEqual(31415, call.ResponseStream.Current.Payload.Body.Length); await call.RequestStream.WriteAsync(new StreamingOutputCallRequest { ResponseParameters = { new ResponseParameters { Size = 9 } }, Payload = CreateZerosPayload(8) }); Assert.IsTrue(await call.ResponseStream.MoveNext()); Assert.AreEqual(9, call.ResponseStream.Current.Payload.Body.Length); await call.RequestStream.WriteAsync(new StreamingOutputCallRequest { ResponseParameters = { new ResponseParameters { Size = 2653 } }, Payload = CreateZerosPayload(1828) }); Assert.IsTrue(await call.ResponseStream.MoveNext()); Assert.AreEqual(2653, call.ResponseStream.Current.Payload.Body.Length); await call.RequestStream.WriteAsync(new StreamingOutputCallRequest { ResponseParameters = { new ResponseParameters { Size = 58979 } }, Payload = CreateZerosPayload(45904) }); Assert.IsTrue(await call.ResponseStream.MoveNext()); Assert.AreEqual(58979, call.ResponseStream.Current.Payload.Body.Length); await call.RequestStream.CompleteAsync(); Assert.IsFalse(await call.ResponseStream.MoveNext()); } Console.WriteLine("Passed!"); } public static async Task RunEmptyStreamAsync(TestService.TestServiceClient client) { Console.WriteLine("running empty_stream"); using (var call = client.FullDuplexCall()) { await call.RequestStream.CompleteAsync(); var responseList = await call.ResponseStream.ToListAsync(); Assert.AreEqual(0, responseList.Count); } Console.WriteLine("Passed!"); } public static void RunComputeEngineCreds(TestService.TestServiceClient client, string defaultServiceAccount, string oauthScope) { Console.WriteLine("running compute_engine_creds"); var request = new SimpleRequest { ResponseSize = 314159, Payload = CreateZerosPayload(271828), FillUsername = true, FillOauthScope = true }; // not setting credentials here because they were set on channel already var response = client.UnaryCall(request); Assert.AreEqual(314159, response.Payload.Body.Length); Assert.False(string.IsNullOrEmpty(response.OauthScope)); Assert.True(oauthScope.Contains(response.OauthScope)); Assert.AreEqual(defaultServiceAccount, response.Username); Console.WriteLine("Passed!"); } public static void RunJwtTokenCreds(TestService.TestServiceClient client) { Console.WriteLine("running jwt_token_creds"); var request = new SimpleRequest { ResponseSize = 314159, Payload = CreateZerosPayload(271828), FillUsername = true, }; // not setting credentials here because they were set on channel already var response = client.UnaryCall(request); Assert.AreEqual(314159, response.Payload.Body.Length); Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username); Console.WriteLine("Passed!"); } public static async Task RunOAuth2AuthTokenAsync(TestService.TestServiceClient client, string oauthScope) { Console.WriteLine("running oauth2_auth_token"); ITokenAccess credential = (await GoogleCredential.GetApplicationDefaultAsync()).CreateScoped(new[] { oauthScope }); string oauth2Token = await credential.GetAccessTokenForRequestAsync(); var credentials = GoogleGrpcCredentials.FromAccessToken(oauth2Token); var request = new SimpleRequest { FillUsername = true, FillOauthScope = true }; var response = client.UnaryCall(request, new CallOptions(credentials: credentials)); Assert.False(string.IsNullOrEmpty(response.OauthScope)); Assert.True(oauthScope.Contains(response.OauthScope)); Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username); Console.WriteLine("Passed!"); } public static async Task RunPerRpcCredsAsync(TestService.TestServiceClient client, string oauthScope) { Console.WriteLine("running per_rpc_creds"); ITokenAccess googleCredential = await GoogleCredential.GetApplicationDefaultAsync(); var credentials = googleCredential.ToCallCredentials(); var request = new SimpleRequest { FillUsername = true, }; var response = client.UnaryCall(request, new CallOptions(credentials: credentials)); Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username); Console.WriteLine("Passed!"); } public static async Task RunCancelAfterBeginAsync(TestService.TestServiceClient client) { Console.WriteLine("running cancel_after_begin"); var cts = new CancellationTokenSource(); using (var call = client.StreamingInputCall(cancellationToken: cts.Token)) { // TODO(jtattermusch): we need this to ensure call has been initiated once we cancel it. await Task.Delay(1000); cts.Cancel(); var ex = Assert.ThrowsAsync(async () => await call.ResponseAsync); Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode); } Console.WriteLine("Passed!"); } public static async Task RunCancelAfterFirstResponseAsync(TestService.TestServiceClient client) { Console.WriteLine("running cancel_after_first_response"); var cts = new CancellationTokenSource(); using (var call = client.FullDuplexCall(cancellationToken: cts.Token)) { await call.RequestStream.WriteAsync(new StreamingOutputCallRequest { ResponseParameters = { new ResponseParameters { Size = 31415 } }, Payload = CreateZerosPayload(27182) }); Assert.IsTrue(await call.ResponseStream.MoveNext()); Assert.AreEqual(31415, call.ResponseStream.Current.Payload.Body.Length); cts.Cancel(); try { // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock. await call.ResponseStream.MoveNext(); Assert.Fail(); } catch (RpcException ex) { Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode); } } Console.WriteLine("Passed!"); } public static async Task RunTimeoutOnSleepingServerAsync(TestService.TestServiceClient client) { Console.WriteLine("running timeout_on_sleeping_server"); var deadline = DateTime.UtcNow.AddMilliseconds(1); using (var call = client.FullDuplexCall(deadline: deadline)) { try { await call.RequestStream.WriteAsync(new StreamingOutputCallRequest { Payload = CreateZerosPayload(27182) }); } catch (InvalidOperationException) { // Deadline was reached before write has started. Eat the exception and continue. } catch (RpcException) { // Deadline was reached before write has started. Eat the exception and continue. } try { await call.ResponseStream.MoveNext(); Assert.Fail(); } catch (RpcException ex) { // We can't guarantee the status code always DeadlineExceeded. See issue #2685. Assert.Contains(ex.Status.StatusCode, new[] { StatusCode.DeadlineExceeded, StatusCode.Internal }); } } Console.WriteLine("Passed!"); } public static async Task RunCustomMetadataAsync(TestService.TestServiceClient client) { Console.WriteLine("running custom_metadata"); { // step 1: test unary call var request = new SimpleRequest { ResponseSize = 314159, Payload = CreateZerosPayload(271828) }; var call = client.UnaryCallAsync(request, headers: CreateTestMetadata()); await call.ResponseAsync; var responseHeaders = await call.ResponseHeadersAsync; var responseTrailers = call.GetTrailers(); Assert.AreEqual("test_initial_metadata_value", responseHeaders.First((entry) => entry.Key == "x-grpc-test-echo-initial").Value); CollectionAssert.AreEqual(new byte[] { 0xab, 0xab, 0xab }, responseTrailers.First((entry) => entry.Key == "x-grpc-test-echo-trailing-bin").ValueBytes); } { // step 2: test full duplex call var request = new StreamingOutputCallRequest { ResponseParameters = { new ResponseParameters { Size = 31415 } }, Payload = CreateZerosPayload(27182) }; var call = client.FullDuplexCall(headers: CreateTestMetadata()); await call.RequestStream.WriteAsync(request); await call.RequestStream.CompleteAsync(); await call.ResponseStream.ToListAsync(); var responseHeaders = await call.ResponseHeadersAsync; var responseTrailers = call.GetTrailers(); Assert.AreEqual("test_initial_metadata_value", responseHeaders.First((entry) => entry.Key == "x-grpc-test-echo-initial").Value); CollectionAssert.AreEqual(new byte[] { 0xab, 0xab, 0xab }, responseTrailers.First((entry) => entry.Key == "x-grpc-test-echo-trailing-bin").ValueBytes); } Console.WriteLine("Passed!"); } public static async Task RunStatusCodeAndMessageAsync(TestService.TestServiceClient client) { Console.WriteLine("running status_code_and_message"); var echoStatus = new EchoStatus { Code = 2, Message = "test status message" }; { // step 1: test unary call var request = new SimpleRequest { ResponseStatus = echoStatus }; var e = Assert.Throws(() => client.UnaryCall(request)); Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode); Assert.AreEqual(echoStatus.Message, e.Status.Detail); } { // step 2: test full duplex call var request = new StreamingOutputCallRequest { ResponseStatus = echoStatus }; var call = client.FullDuplexCall(); await call.RequestStream.WriteAsync(request); await call.RequestStream.CompleteAsync(); try { // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock. await call.ResponseStream.ToListAsync(); Assert.Fail(); } catch (RpcException e) { Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode); Assert.AreEqual(echoStatus.Message, e.Status.Detail); } } Console.WriteLine("Passed!"); } public static void RunUnimplementedService(UnimplementedService.UnimplementedServiceClient client) { Console.WriteLine("running unimplemented_service"); var e = Assert.Throws(() => client.UnimplementedCall(new Empty())); Assert.AreEqual(StatusCode.Unimplemented, e.Status.StatusCode); Console.WriteLine("Passed!"); } public static void RunUnimplementedMethod(TestService.TestServiceClient client) { Console.WriteLine("running unimplemented_method"); var e = Assert.Throws(() => client.UnimplementedCall(new Empty())); Assert.AreEqual(StatusCode.Unimplemented, e.Status.StatusCode); Console.WriteLine("Passed!"); } public static void RunClientCompressedUnary(TestService.TestServiceClient client) { Console.WriteLine("running client_compressed_unary"); var probeRequest = new SimpleRequest { ExpectCompressed = new BoolValue { Value = true // lie about compression }, ResponseSize = 314159, Payload = CreateZerosPayload(271828) }; var e = Assert.Throws(() => client.UnaryCall(probeRequest, CreateClientCompressionMetadata(false))); Assert.AreEqual(StatusCode.InvalidArgument, e.Status.StatusCode); var compressedRequest = new SimpleRequest { ExpectCompressed = new BoolValue { Value = true }, ResponseSize = 314159, Payload = CreateZerosPayload(271828) }; var response1 = client.UnaryCall(compressedRequest, CreateClientCompressionMetadata(true)); Assert.AreEqual(314159, response1.Payload.Body.Length); var uncompressedRequest = new SimpleRequest { ExpectCompressed = new BoolValue { Value = false }, ResponseSize = 314159, Payload = CreateZerosPayload(271828) }; var response2 = client.UnaryCall(uncompressedRequest, CreateClientCompressionMetadata(false)); Assert.AreEqual(314159, response2.Payload.Body.Length); Console.WriteLine("Passed!"); } public static async Task RunClientCompressedStreamingAsync(TestService.TestServiceClient client) { Console.WriteLine("running client_compressed_streaming"); try { var probeCall = client.StreamingInputCall(CreateClientCompressionMetadata(false)); await probeCall.RequestStream.WriteAsync(new StreamingInputCallRequest { ExpectCompressed = new BoolValue { Value = true }, Payload = CreateZerosPayload(27182) }); // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock. await probeCall; Assert.Fail(); } catch (RpcException e) { Assert.AreEqual(StatusCode.InvalidArgument, e.Status.StatusCode); } var call = client.StreamingInputCall(CreateClientCompressionMetadata(true)); await call.RequestStream.WriteAsync(new StreamingInputCallRequest { ExpectCompressed = new BoolValue { Value = true }, Payload = CreateZerosPayload(27182) }); call.RequestStream.WriteOptions = new WriteOptions(WriteFlags.NoCompress); await call.RequestStream.WriteAsync(new StreamingInputCallRequest { ExpectCompressed = new BoolValue { Value = false }, Payload = CreateZerosPayload(45904) }); await call.RequestStream.CompleteAsync(); var response = await call.ResponseAsync; Assert.AreEqual(73086, response.AggregatedPayloadSize); Console.WriteLine("Passed!"); } private static Payload CreateZerosPayload(int size) { return new Payload { Body = ByteString.CopyFrom(new byte[size]) }; } private static Metadata CreateClientCompressionMetadata(bool compressed) { var algorithmName = compressed ? "gzip" : "identity"; return new Metadata { { new Metadata.Entry(Metadata.CompressionRequestAlgorithmMetadataKey, algorithmName) } }; } // extracts the client_email field from service account file used for auth test cases private static string GetEmailFromServiceAccountFile() { string keyFile = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS"); Assert.IsNotNull(keyFile); var jobject = JObject.Parse(File.ReadAllText(keyFile)); string email = jobject.GetValue("client_email").Value(); Assert.IsTrue(email.Length > 0); // spec requires nonempty client email. return email; } private static Metadata CreateTestMetadata() { return new Metadata { {"x-grpc-test-echo-initial", "test_initial_metadata_value"}, {"x-grpc-test-echo-trailing-bin", new byte[] {0xab, 0xab, 0xab}} }; } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs000066400000000000000000000117251310511640000263640ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Utils; using Grpc.Testing; using NUnit.Framework; namespace Grpc.IntegrationTesting { /// /// Runs interop tests in-process. /// public class InteropClientServerTest { const string Host = "localhost"; Server server; Channel channel; TestService.TestServiceClient client; [TestFixtureSetUp] public void Init() { // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) { Services = { TestService.BindService(new TestServiceImpl()) }, Ports = { { Host, ServerPort.PickUnused, TestCredentials.CreateSslServerCredentials() } } }; server.Start(); var options = new List { new ChannelOption(ChannelOptions.SslTargetNameOverride, TestCredentials.DefaultHostOverride) }; int port = server.Ports.Single().BoundPort; channel = new Channel(Host, port, TestCredentials.CreateSslCredentials(), options); client = new TestService.TestServiceClient(channel); } [TestFixtureTearDown] public void Cleanup() { channel.ShutdownAsync().Wait(); server.ShutdownAsync().Wait(); } [Test] public void EmptyUnary() { InteropClient.RunEmptyUnary(client); } [Test] public void LargeUnary() { InteropClient.RunLargeUnary(client); } [Test] public async Task ClientStreaming() { await InteropClient.RunClientStreamingAsync(client); } [Test] public async Task ServerStreaming() { await InteropClient.RunServerStreamingAsync(client); } [Test] public async Task PingPong() { await InteropClient.RunPingPongAsync(client); } [Test] public async Task EmptyStream() { await InteropClient.RunEmptyStreamAsync(client); } [Test] public async Task CancelAfterBegin() { await InteropClient.RunCancelAfterBeginAsync(client); } [Test] public async Task CancelAfterFirstResponse() { await InteropClient.RunCancelAfterFirstResponseAsync(client); } [Test] public async Task TimeoutOnSleepingServer() { await InteropClient.RunTimeoutOnSleepingServerAsync(client); } [Test] public async Task CustomMetadata() { await InteropClient.RunCustomMetadataAsync(client); } [Test] public async Task StatusCodeAndMessage() { await InteropClient.RunStatusCodeAndMessageAsync(client); } [Test] public void UnimplementedService() { InteropClient.RunUnimplementedService(new UnimplementedService.UnimplementedServiceClient(channel)); } [Test] public void UnimplementedMethod() { InteropClient.RunUnimplementedMethod(client); } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/InteropServer.cs000066400000000000000000000071141310511640000243620ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Text.RegularExpressions; using System.Threading.Tasks; using CommandLine; using CommandLine.Text; using Grpc.Core; using Grpc.Core.Logging; using Grpc.Core.Utils; using Grpc.Testing; using NUnit.Framework; namespace Grpc.IntegrationTesting { public class InteropServer { private class ServerOptions { [Option("port", Default = 8070)] public int Port { get; set; } // Deliberately using nullable bool type to allow --use_tls=true syntax (as opposed to --use_tls) [Option("use_tls", Default = false)] public bool? UseTls { get; set; } } ServerOptions options; private InteropServer(ServerOptions options) { this.options = options; } public static void Run(string[] args) { GrpcEnvironment.SetLogger(new ConsoleLogger()); var parserResult = Parser.Default.ParseArguments(args) .WithNotParsed(errors => Environment.Exit(1)) .WithParsed(options => { var interopServer = new InteropServer(options); interopServer.Run(); }); } private void Run() { var server = new Server { Services = { TestService.BindService(new TestServiceImpl()) } }; string host = "0.0.0.0"; int port = options.Port; if (options.UseTls.Value) { server.Ports.Add(host, port, TestCredentials.CreateSslServerCredentials()); } else { server.Ports.Add(host, options.Port, ServerCredentials.Insecure); } Console.WriteLine("Running server on " + string.Format("{0}:{1}", host, port)); server.Start(); server.ShutdownTask.Wait(); } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/Messages.cs000066400000000000000000002224561310511640000233320ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: src/proto/grpc/testing/messages.proto #pragma warning disable 1591, 0612, 3021 #region Designer generated code using pb = global::Google.Protobuf; using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; namespace Grpc.Testing { /// Holder for reflection information generated from src/proto/grpc/testing/messages.proto public static partial class MessagesReflection { #region Descriptor /// File descriptor for src/proto/grpc/testing/messages.proto public static pbr::FileDescriptor Descriptor { get { return descriptor; } } private static pbr::FileDescriptor descriptor; static MessagesReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "CiVzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL21lc3NhZ2VzLnByb3RvEgxncnBj", "LnRlc3RpbmciGgoJQm9vbFZhbHVlEg0KBXZhbHVlGAEgASgIIkAKB1BheWxv", "YWQSJwoEdHlwZRgBIAEoDjIZLmdycGMudGVzdGluZy5QYXlsb2FkVHlwZRIM", "CgRib2R5GAIgASgMIisKCkVjaG9TdGF0dXMSDAoEY29kZRgBIAEoBRIPCgdt", "ZXNzYWdlGAIgASgJIs4CCg1TaW1wbGVSZXF1ZXN0EjAKDXJlc3BvbnNlX3R5", "cGUYASABKA4yGS5ncnBjLnRlc3RpbmcuUGF5bG9hZFR5cGUSFQoNcmVzcG9u", "c2Vfc2l6ZRgCIAEoBRImCgdwYXlsb2FkGAMgASgLMhUuZ3JwYy50ZXN0aW5n", "LlBheWxvYWQSFQoNZmlsbF91c2VybmFtZRgEIAEoCBIYChBmaWxsX29hdXRo", "X3Njb3BlGAUgASgIEjQKE3Jlc3BvbnNlX2NvbXByZXNzZWQYBiABKAsyFy5n", "cnBjLnRlc3RpbmcuQm9vbFZhbHVlEjEKD3Jlc3BvbnNlX3N0YXR1cxgHIAEo", "CzIYLmdycGMudGVzdGluZy5FY2hvU3RhdHVzEjIKEWV4cGVjdF9jb21wcmVz", "c2VkGAggASgLMhcuZ3JwYy50ZXN0aW5nLkJvb2xWYWx1ZSJfCg5TaW1wbGVS", "ZXNwb25zZRImCgdwYXlsb2FkGAEgASgLMhUuZ3JwYy50ZXN0aW5nLlBheWxv", "YWQSEAoIdXNlcm5hbWUYAiABKAkSEwoLb2F1dGhfc2NvcGUYAyABKAkidwoZ", "U3RyZWFtaW5nSW5wdXRDYWxsUmVxdWVzdBImCgdwYXlsb2FkGAEgASgLMhUu", "Z3JwYy50ZXN0aW5nLlBheWxvYWQSMgoRZXhwZWN0X2NvbXByZXNzZWQYAiAB", "KAsyFy5ncnBjLnRlc3RpbmcuQm9vbFZhbHVlIj0KGlN0cmVhbWluZ0lucHV0", "Q2FsbFJlc3BvbnNlEh8KF2FnZ3JlZ2F0ZWRfcGF5bG9hZF9zaXplGAEgASgF", "ImQKElJlc3BvbnNlUGFyYW1ldGVycxIMCgRzaXplGAEgASgFEhMKC2ludGVy", "dmFsX3VzGAIgASgFEisKCmNvbXByZXNzZWQYAyABKAsyFy5ncnBjLnRlc3Rp", "bmcuQm9vbFZhbHVlIugBChpTdHJlYW1pbmdPdXRwdXRDYWxsUmVxdWVzdBIw", "Cg1yZXNwb25zZV90eXBlGAEgASgOMhkuZ3JwYy50ZXN0aW5nLlBheWxvYWRU", "eXBlEj0KE3Jlc3BvbnNlX3BhcmFtZXRlcnMYAiADKAsyIC5ncnBjLnRlc3Rp", "bmcuUmVzcG9uc2VQYXJhbWV0ZXJzEiYKB3BheWxvYWQYAyABKAsyFS5ncnBj", "LnRlc3RpbmcuUGF5bG9hZBIxCg9yZXNwb25zZV9zdGF0dXMYByABKAsyGC5n", "cnBjLnRlc3RpbmcuRWNob1N0YXR1cyJFChtTdHJlYW1pbmdPdXRwdXRDYWxs", "UmVzcG9uc2USJgoHcGF5bG9hZBgBIAEoCzIVLmdycGMudGVzdGluZy5QYXls", "b2FkIjMKD1JlY29ubmVjdFBhcmFtcxIgChhtYXhfcmVjb25uZWN0X2JhY2tv", "ZmZfbXMYASABKAUiMwoNUmVjb25uZWN0SW5mbxIOCgZwYXNzZWQYASABKAgS", "EgoKYmFja29mZl9tcxgCIAMoBSofCgtQYXlsb2FkVHlwZRIQCgxDT01QUkVT", "U0FCTEUQAGIGcHJvdG8z")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Grpc.Testing.PayloadType), }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.BoolValue), global::Grpc.Testing.BoolValue.Parser, new[]{ "Value" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Payload), global::Grpc.Testing.Payload.Parser, new[]{ "Type", "Body" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.EchoStatus), global::Grpc.Testing.EchoStatus.Parser, new[]{ "Code", "Message" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SimpleRequest), global::Grpc.Testing.SimpleRequest.Parser, new[]{ "ResponseType", "ResponseSize", "Payload", "FillUsername", "FillOauthScope", "ResponseCompressed", "ResponseStatus", "ExpectCompressed" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SimpleResponse), global::Grpc.Testing.SimpleResponse.Parser, new[]{ "Payload", "Username", "OauthScope" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.StreamingInputCallRequest), global::Grpc.Testing.StreamingInputCallRequest.Parser, new[]{ "Payload", "ExpectCompressed" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.StreamingInputCallResponse), global::Grpc.Testing.StreamingInputCallResponse.Parser, new[]{ "AggregatedPayloadSize" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ResponseParameters), global::Grpc.Testing.ResponseParameters.Parser, new[]{ "Size", "IntervalUs", "Compressed" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.StreamingOutputCallRequest), global::Grpc.Testing.StreamingOutputCallRequest.Parser, new[]{ "ResponseType", "ResponseParameters", "Payload", "ResponseStatus" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.StreamingOutputCallResponse), global::Grpc.Testing.StreamingOutputCallResponse.Parser, new[]{ "Payload" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ReconnectParams), global::Grpc.Testing.ReconnectParams.Parser, new[]{ "MaxReconnectBackoffMs" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ReconnectInfo), global::Grpc.Testing.ReconnectInfo.Parser, new[]{ "Passed", "BackoffMs" }, null, null, null) })); } #endregion } #region Enums /// /// DEPRECATED, don't use. To be removed shortly. /// The type of payload that should be returned. /// public enum PayloadType { /// /// Compressable text format. /// [pbr::OriginalName("COMPRESSABLE")] Compressable = 0, } #endregion #region Messages /// /// TODO(dgq): Go back to using well-known types once /// https://github.com/grpc/grpc/issues/6980 has been fixed. /// import "google/protobuf/wrappers.proto"; /// public sealed partial class BoolValue : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BoolValue()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public BoolValue() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public BoolValue(BoolValue other) : this() { value_ = other.value_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public BoolValue Clone() { return new BoolValue(this); } /// Field number for the "value" field. public const int ValueFieldNumber = 1; private bool value_; /// /// The bool value. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Value { get { return value_; } set { value_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as BoolValue); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(BoolValue other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Value != other.Value) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Value != false) hash ^= Value.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Value != false) { output.WriteRawTag(8); output.WriteBool(Value); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Value != false) { size += 1 + 1; } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(BoolValue other) { if (other == null) { return; } if (other.Value != false) { Value = other.Value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { Value = input.ReadBool(); break; } } } } } /// /// A block of data, to simply increase gRPC message size. /// public sealed partial class Payload : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Payload()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Payload() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Payload(Payload other) : this() { type_ = other.type_; body_ = other.body_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Payload Clone() { return new Payload(this); } /// Field number for the "type" field. public const int TypeFieldNumber = 1; private global::Grpc.Testing.PayloadType type_ = 0; /// /// DEPRECATED, don't use. To be removed shortly. /// The type of data in body. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.PayloadType Type { get { return type_; } set { type_ = value; } } /// Field number for the "body" field. public const int BodyFieldNumber = 2; private pb::ByteString body_ = pb::ByteString.Empty; /// /// Primary contents of payload. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pb::ByteString Body { get { return body_; } set { body_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as Payload); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(Payload other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Type != other.Type) return false; if (Body != other.Body) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Type != 0) hash ^= Type.GetHashCode(); if (Body.Length != 0) hash ^= Body.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Type != 0) { output.WriteRawTag(8); output.WriteEnum((int) Type); } if (Body.Length != 0) { output.WriteRawTag(18); output.WriteBytes(Body); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Type != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type); } if (Body.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeBytesSize(Body); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(Payload other) { if (other == null) { return; } if (other.Type != 0) { Type = other.Type; } if (other.Body.Length != 0) { Body = other.Body; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { type_ = (global::Grpc.Testing.PayloadType) input.ReadEnum(); break; } case 18: { Body = input.ReadBytes(); break; } } } } } /// /// A protobuf representation for grpc status. This is used by test /// clients to specify a status that the server should attempt to return. /// public sealed partial class EchoStatus : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new EchoStatus()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[2]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public EchoStatus() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public EchoStatus(EchoStatus other) : this() { code_ = other.code_; message_ = other.message_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public EchoStatus Clone() { return new EchoStatus(this); } /// Field number for the "code" field. public const int CodeFieldNumber = 1; private int code_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int Code { get { return code_; } set { code_ = value; } } /// Field number for the "message" field. public const int MessageFieldNumber = 2; private string message_ = ""; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Message { get { return message_; } set { message_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as EchoStatus); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(EchoStatus other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Code != other.Code) return false; if (Message != other.Message) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Code != 0) hash ^= Code.GetHashCode(); if (Message.Length != 0) hash ^= Message.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Code != 0) { output.WriteRawTag(8); output.WriteInt32(Code); } if (Message.Length != 0) { output.WriteRawTag(18); output.WriteString(Message); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Code != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(Code); } if (Message.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Message); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(EchoStatus other) { if (other == null) { return; } if (other.Code != 0) { Code = other.Code; } if (other.Message.Length != 0) { Message = other.Message; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { Code = input.ReadInt32(); break; } case 18: { Message = input.ReadString(); break; } } } } } /// /// Unary request. /// public sealed partial class SimpleRequest : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SimpleRequest()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[3]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public SimpleRequest() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public SimpleRequest(SimpleRequest other) : this() { responseType_ = other.responseType_; responseSize_ = other.responseSize_; Payload = other.payload_ != null ? other.Payload.Clone() : null; fillUsername_ = other.fillUsername_; fillOauthScope_ = other.fillOauthScope_; ResponseCompressed = other.responseCompressed_ != null ? other.ResponseCompressed.Clone() : null; ResponseStatus = other.responseStatus_ != null ? other.ResponseStatus.Clone() : null; ExpectCompressed = other.expectCompressed_ != null ? other.ExpectCompressed.Clone() : null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public SimpleRequest Clone() { return new SimpleRequest(this); } /// Field number for the "response_type" field. public const int ResponseTypeFieldNumber = 1; private global::Grpc.Testing.PayloadType responseType_ = 0; /// /// DEPRECATED, don't use. To be removed shortly. /// Desired payload type in the response from the server. /// If response_type is RANDOM, server randomly chooses one from other formats. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.PayloadType ResponseType { get { return responseType_; } set { responseType_ = value; } } /// Field number for the "response_size" field. public const int ResponseSizeFieldNumber = 2; private int responseSize_; /// /// Desired payload size in the response from the server. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int ResponseSize { get { return responseSize_; } set { responseSize_ = value; } } /// Field number for the "payload" field. public const int PayloadFieldNumber = 3; private global::Grpc.Testing.Payload payload_; /// /// Optional input payload sent along with the request. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.Payload Payload { get { return payload_; } set { payload_ = value; } } /// Field number for the "fill_username" field. public const int FillUsernameFieldNumber = 4; private bool fillUsername_; /// /// Whether SimpleResponse should include username. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool FillUsername { get { return fillUsername_; } set { fillUsername_ = value; } } /// Field number for the "fill_oauth_scope" field. public const int FillOauthScopeFieldNumber = 5; private bool fillOauthScope_; /// /// Whether SimpleResponse should include OAuth scope. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool FillOauthScope { get { return fillOauthScope_; } set { fillOauthScope_ = value; } } /// Field number for the "response_compressed" field. public const int ResponseCompressedFieldNumber = 6; private global::Grpc.Testing.BoolValue responseCompressed_; /// /// Whether to request the server to compress the response. This field is /// "nullable" in order to interoperate seamlessly with clients not able to /// implement the full compression tests by introspecting the call to verify /// the response's compression status. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.BoolValue ResponseCompressed { get { return responseCompressed_; } set { responseCompressed_ = value; } } /// Field number for the "response_status" field. public const int ResponseStatusFieldNumber = 7; private global::Grpc.Testing.EchoStatus responseStatus_; /// /// Whether server should return a given status /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.EchoStatus ResponseStatus { get { return responseStatus_; } set { responseStatus_ = value; } } /// Field number for the "expect_compressed" field. public const int ExpectCompressedFieldNumber = 8; private global::Grpc.Testing.BoolValue expectCompressed_; /// /// Whether the server should expect this request to be compressed. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.BoolValue ExpectCompressed { get { return expectCompressed_; } set { expectCompressed_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as SimpleRequest); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(SimpleRequest other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (ResponseType != other.ResponseType) return false; if (ResponseSize != other.ResponseSize) return false; if (!object.Equals(Payload, other.Payload)) return false; if (FillUsername != other.FillUsername) return false; if (FillOauthScope != other.FillOauthScope) return false; if (!object.Equals(ResponseCompressed, other.ResponseCompressed)) return false; if (!object.Equals(ResponseStatus, other.ResponseStatus)) return false; if (!object.Equals(ExpectCompressed, other.ExpectCompressed)) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (ResponseType != 0) hash ^= ResponseType.GetHashCode(); if (ResponseSize != 0) hash ^= ResponseSize.GetHashCode(); if (payload_ != null) hash ^= Payload.GetHashCode(); if (FillUsername != false) hash ^= FillUsername.GetHashCode(); if (FillOauthScope != false) hash ^= FillOauthScope.GetHashCode(); if (responseCompressed_ != null) hash ^= ResponseCompressed.GetHashCode(); if (responseStatus_ != null) hash ^= ResponseStatus.GetHashCode(); if (expectCompressed_ != null) hash ^= ExpectCompressed.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (ResponseType != 0) { output.WriteRawTag(8); output.WriteEnum((int) ResponseType); } if (ResponseSize != 0) { output.WriteRawTag(16); output.WriteInt32(ResponseSize); } if (payload_ != null) { output.WriteRawTag(26); output.WriteMessage(Payload); } if (FillUsername != false) { output.WriteRawTag(32); output.WriteBool(FillUsername); } if (FillOauthScope != false) { output.WriteRawTag(40); output.WriteBool(FillOauthScope); } if (responseCompressed_ != null) { output.WriteRawTag(50); output.WriteMessage(ResponseCompressed); } if (responseStatus_ != null) { output.WriteRawTag(58); output.WriteMessage(ResponseStatus); } if (expectCompressed_ != null) { output.WriteRawTag(66); output.WriteMessage(ExpectCompressed); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (ResponseType != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ResponseType); } if (ResponseSize != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(ResponseSize); } if (payload_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload); } if (FillUsername != false) { size += 1 + 1; } if (FillOauthScope != false) { size += 1 + 1; } if (responseCompressed_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(ResponseCompressed); } if (responseStatus_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(ResponseStatus); } if (expectCompressed_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(ExpectCompressed); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(SimpleRequest other) { if (other == null) { return; } if (other.ResponseType != 0) { ResponseType = other.ResponseType; } if (other.ResponseSize != 0) { ResponseSize = other.ResponseSize; } if (other.payload_ != null) { if (payload_ == null) { payload_ = new global::Grpc.Testing.Payload(); } Payload.MergeFrom(other.Payload); } if (other.FillUsername != false) { FillUsername = other.FillUsername; } if (other.FillOauthScope != false) { FillOauthScope = other.FillOauthScope; } if (other.responseCompressed_ != null) { if (responseCompressed_ == null) { responseCompressed_ = new global::Grpc.Testing.BoolValue(); } ResponseCompressed.MergeFrom(other.ResponseCompressed); } if (other.responseStatus_ != null) { if (responseStatus_ == null) { responseStatus_ = new global::Grpc.Testing.EchoStatus(); } ResponseStatus.MergeFrom(other.ResponseStatus); } if (other.expectCompressed_ != null) { if (expectCompressed_ == null) { expectCompressed_ = new global::Grpc.Testing.BoolValue(); } ExpectCompressed.MergeFrom(other.ExpectCompressed); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { responseType_ = (global::Grpc.Testing.PayloadType) input.ReadEnum(); break; } case 16: { ResponseSize = input.ReadInt32(); break; } case 26: { if (payload_ == null) { payload_ = new global::Grpc.Testing.Payload(); } input.ReadMessage(payload_); break; } case 32: { FillUsername = input.ReadBool(); break; } case 40: { FillOauthScope = input.ReadBool(); break; } case 50: { if (responseCompressed_ == null) { responseCompressed_ = new global::Grpc.Testing.BoolValue(); } input.ReadMessage(responseCompressed_); break; } case 58: { if (responseStatus_ == null) { responseStatus_ = new global::Grpc.Testing.EchoStatus(); } input.ReadMessage(responseStatus_); break; } case 66: { if (expectCompressed_ == null) { expectCompressed_ = new global::Grpc.Testing.BoolValue(); } input.ReadMessage(expectCompressed_); break; } } } } } /// /// Unary response, as configured by the request. /// public sealed partial class SimpleResponse : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SimpleResponse()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[4]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public SimpleResponse() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public SimpleResponse(SimpleResponse other) : this() { Payload = other.payload_ != null ? other.Payload.Clone() : null; username_ = other.username_; oauthScope_ = other.oauthScope_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public SimpleResponse Clone() { return new SimpleResponse(this); } /// Field number for the "payload" field. public const int PayloadFieldNumber = 1; private global::Grpc.Testing.Payload payload_; /// /// Payload to increase message size. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.Payload Payload { get { return payload_; } set { payload_ = value; } } /// Field number for the "username" field. public const int UsernameFieldNumber = 2; private string username_ = ""; /// /// The user the request came from, for verifying authentication was /// successful when the client expected it. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Username { get { return username_; } set { username_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Field number for the "oauth_scope" field. public const int OauthScopeFieldNumber = 3; private string oauthScope_ = ""; /// /// OAuth scope. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string OauthScope { get { return oauthScope_; } set { oauthScope_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as SimpleResponse); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(SimpleResponse other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (!object.Equals(Payload, other.Payload)) return false; if (Username != other.Username) return false; if (OauthScope != other.OauthScope) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (payload_ != null) hash ^= Payload.GetHashCode(); if (Username.Length != 0) hash ^= Username.GetHashCode(); if (OauthScope.Length != 0) hash ^= OauthScope.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (payload_ != null) { output.WriteRawTag(10); output.WriteMessage(Payload); } if (Username.Length != 0) { output.WriteRawTag(18); output.WriteString(Username); } if (OauthScope.Length != 0) { output.WriteRawTag(26); output.WriteString(OauthScope); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (payload_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload); } if (Username.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Username); } if (OauthScope.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(OauthScope); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(SimpleResponse other) { if (other == null) { return; } if (other.payload_ != null) { if (payload_ == null) { payload_ = new global::Grpc.Testing.Payload(); } Payload.MergeFrom(other.Payload); } if (other.Username.Length != 0) { Username = other.Username; } if (other.OauthScope.Length != 0) { OauthScope = other.OauthScope; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { if (payload_ == null) { payload_ = new global::Grpc.Testing.Payload(); } input.ReadMessage(payload_); break; } case 18: { Username = input.ReadString(); break; } case 26: { OauthScope = input.ReadString(); break; } } } } } /// /// Client-streaming request. /// public sealed partial class StreamingInputCallRequest : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new StreamingInputCallRequest()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[5]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public StreamingInputCallRequest() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public StreamingInputCallRequest(StreamingInputCallRequest other) : this() { Payload = other.payload_ != null ? other.Payload.Clone() : null; ExpectCompressed = other.expectCompressed_ != null ? other.ExpectCompressed.Clone() : null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public StreamingInputCallRequest Clone() { return new StreamingInputCallRequest(this); } /// Field number for the "payload" field. public const int PayloadFieldNumber = 1; private global::Grpc.Testing.Payload payload_; /// /// Optional input payload sent along with the request. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.Payload Payload { get { return payload_; } set { payload_ = value; } } /// Field number for the "expect_compressed" field. public const int ExpectCompressedFieldNumber = 2; private global::Grpc.Testing.BoolValue expectCompressed_; /// /// Whether the server should expect this request to be compressed. This field /// is "nullable" in order to interoperate seamlessly with servers not able to /// implement the full compression tests by introspecting the call to verify /// the request's compression status. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.BoolValue ExpectCompressed { get { return expectCompressed_; } set { expectCompressed_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as StreamingInputCallRequest); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(StreamingInputCallRequest other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (!object.Equals(Payload, other.Payload)) return false; if (!object.Equals(ExpectCompressed, other.ExpectCompressed)) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (payload_ != null) hash ^= Payload.GetHashCode(); if (expectCompressed_ != null) hash ^= ExpectCompressed.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (payload_ != null) { output.WriteRawTag(10); output.WriteMessage(Payload); } if (expectCompressed_ != null) { output.WriteRawTag(18); output.WriteMessage(ExpectCompressed); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (payload_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload); } if (expectCompressed_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(ExpectCompressed); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(StreamingInputCallRequest other) { if (other == null) { return; } if (other.payload_ != null) { if (payload_ == null) { payload_ = new global::Grpc.Testing.Payload(); } Payload.MergeFrom(other.Payload); } if (other.expectCompressed_ != null) { if (expectCompressed_ == null) { expectCompressed_ = new global::Grpc.Testing.BoolValue(); } ExpectCompressed.MergeFrom(other.ExpectCompressed); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { if (payload_ == null) { payload_ = new global::Grpc.Testing.Payload(); } input.ReadMessage(payload_); break; } case 18: { if (expectCompressed_ == null) { expectCompressed_ = new global::Grpc.Testing.BoolValue(); } input.ReadMessage(expectCompressed_); break; } } } } } /// /// Client-streaming response. /// public sealed partial class StreamingInputCallResponse : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new StreamingInputCallResponse()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[6]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public StreamingInputCallResponse() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public StreamingInputCallResponse(StreamingInputCallResponse other) : this() { aggregatedPayloadSize_ = other.aggregatedPayloadSize_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public StreamingInputCallResponse Clone() { return new StreamingInputCallResponse(this); } /// Field number for the "aggregated_payload_size" field. public const int AggregatedPayloadSizeFieldNumber = 1; private int aggregatedPayloadSize_; /// /// Aggregated size of payloads received from the client. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int AggregatedPayloadSize { get { return aggregatedPayloadSize_; } set { aggregatedPayloadSize_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as StreamingInputCallResponse); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(StreamingInputCallResponse other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (AggregatedPayloadSize != other.AggregatedPayloadSize) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (AggregatedPayloadSize != 0) hash ^= AggregatedPayloadSize.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (AggregatedPayloadSize != 0) { output.WriteRawTag(8); output.WriteInt32(AggregatedPayloadSize); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (AggregatedPayloadSize != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(AggregatedPayloadSize); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(StreamingInputCallResponse other) { if (other == null) { return; } if (other.AggregatedPayloadSize != 0) { AggregatedPayloadSize = other.AggregatedPayloadSize; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { AggregatedPayloadSize = input.ReadInt32(); break; } } } } } /// /// Configuration for a particular response. /// public sealed partial class ResponseParameters : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ResponseParameters()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[7]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ResponseParameters() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ResponseParameters(ResponseParameters other) : this() { size_ = other.size_; intervalUs_ = other.intervalUs_; Compressed = other.compressed_ != null ? other.Compressed.Clone() : null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ResponseParameters Clone() { return new ResponseParameters(this); } /// Field number for the "size" field. public const int SizeFieldNumber = 1; private int size_; /// /// Desired payload sizes in responses from the server. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int Size { get { return size_; } set { size_ = value; } } /// Field number for the "interval_us" field. public const int IntervalUsFieldNumber = 2; private int intervalUs_; /// /// Desired interval between consecutive responses in the response stream in /// microseconds. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int IntervalUs { get { return intervalUs_; } set { intervalUs_ = value; } } /// Field number for the "compressed" field. public const int CompressedFieldNumber = 3; private global::Grpc.Testing.BoolValue compressed_; /// /// Whether to request the server to compress the response. This field is /// "nullable" in order to interoperate seamlessly with clients not able to /// implement the full compression tests by introspecting the call to verify /// the response's compression status. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.BoolValue Compressed { get { return compressed_; } set { compressed_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ResponseParameters); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ResponseParameters other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Size != other.Size) return false; if (IntervalUs != other.IntervalUs) return false; if (!object.Equals(Compressed, other.Compressed)) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Size != 0) hash ^= Size.GetHashCode(); if (IntervalUs != 0) hash ^= IntervalUs.GetHashCode(); if (compressed_ != null) hash ^= Compressed.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Size != 0) { output.WriteRawTag(8); output.WriteInt32(Size); } if (IntervalUs != 0) { output.WriteRawTag(16); output.WriteInt32(IntervalUs); } if (compressed_ != null) { output.WriteRawTag(26); output.WriteMessage(Compressed); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Size != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(Size); } if (IntervalUs != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntervalUs); } if (compressed_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Compressed); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ResponseParameters other) { if (other == null) { return; } if (other.Size != 0) { Size = other.Size; } if (other.IntervalUs != 0) { IntervalUs = other.IntervalUs; } if (other.compressed_ != null) { if (compressed_ == null) { compressed_ = new global::Grpc.Testing.BoolValue(); } Compressed.MergeFrom(other.Compressed); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { Size = input.ReadInt32(); break; } case 16: { IntervalUs = input.ReadInt32(); break; } case 26: { if (compressed_ == null) { compressed_ = new global::Grpc.Testing.BoolValue(); } input.ReadMessage(compressed_); break; } } } } } /// /// Server-streaming request. /// public sealed partial class StreamingOutputCallRequest : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new StreamingOutputCallRequest()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[8]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public StreamingOutputCallRequest() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public StreamingOutputCallRequest(StreamingOutputCallRequest other) : this() { responseType_ = other.responseType_; responseParameters_ = other.responseParameters_.Clone(); Payload = other.payload_ != null ? other.Payload.Clone() : null; ResponseStatus = other.responseStatus_ != null ? other.ResponseStatus.Clone() : null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public StreamingOutputCallRequest Clone() { return new StreamingOutputCallRequest(this); } /// Field number for the "response_type" field. public const int ResponseTypeFieldNumber = 1; private global::Grpc.Testing.PayloadType responseType_ = 0; /// /// DEPRECATED, don't use. To be removed shortly. /// Desired payload type in the response from the server. /// If response_type is RANDOM, the payload from each response in the stream /// might be of different types. This is to simulate a mixed type of payload /// stream. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.PayloadType ResponseType { get { return responseType_; } set { responseType_ = value; } } /// Field number for the "response_parameters" field. public const int ResponseParametersFieldNumber = 2; private static readonly pb::FieldCodec _repeated_responseParameters_codec = pb::FieldCodec.ForMessage(18, global::Grpc.Testing.ResponseParameters.Parser); private readonly pbc::RepeatedField responseParameters_ = new pbc::RepeatedField(); /// /// Configuration for each expected response message. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::RepeatedField ResponseParameters { get { return responseParameters_; } } /// Field number for the "payload" field. public const int PayloadFieldNumber = 3; private global::Grpc.Testing.Payload payload_; /// /// Optional input payload sent along with the request. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.Payload Payload { get { return payload_; } set { payload_ = value; } } /// Field number for the "response_status" field. public const int ResponseStatusFieldNumber = 7; private global::Grpc.Testing.EchoStatus responseStatus_; /// /// Whether server should return a given status /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.EchoStatus ResponseStatus { get { return responseStatus_; } set { responseStatus_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as StreamingOutputCallRequest); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(StreamingOutputCallRequest other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (ResponseType != other.ResponseType) return false; if(!responseParameters_.Equals(other.responseParameters_)) return false; if (!object.Equals(Payload, other.Payload)) return false; if (!object.Equals(ResponseStatus, other.ResponseStatus)) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (ResponseType != 0) hash ^= ResponseType.GetHashCode(); hash ^= responseParameters_.GetHashCode(); if (payload_ != null) hash ^= Payload.GetHashCode(); if (responseStatus_ != null) hash ^= ResponseStatus.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (ResponseType != 0) { output.WriteRawTag(8); output.WriteEnum((int) ResponseType); } responseParameters_.WriteTo(output, _repeated_responseParameters_codec); if (payload_ != null) { output.WriteRawTag(26); output.WriteMessage(Payload); } if (responseStatus_ != null) { output.WriteRawTag(58); output.WriteMessage(ResponseStatus); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (ResponseType != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ResponseType); } size += responseParameters_.CalculateSize(_repeated_responseParameters_codec); if (payload_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload); } if (responseStatus_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(ResponseStatus); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(StreamingOutputCallRequest other) { if (other == null) { return; } if (other.ResponseType != 0) { ResponseType = other.ResponseType; } responseParameters_.Add(other.responseParameters_); if (other.payload_ != null) { if (payload_ == null) { payload_ = new global::Grpc.Testing.Payload(); } Payload.MergeFrom(other.Payload); } if (other.responseStatus_ != null) { if (responseStatus_ == null) { responseStatus_ = new global::Grpc.Testing.EchoStatus(); } ResponseStatus.MergeFrom(other.ResponseStatus); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { responseType_ = (global::Grpc.Testing.PayloadType) input.ReadEnum(); break; } case 18: { responseParameters_.AddEntriesFrom(input, _repeated_responseParameters_codec); break; } case 26: { if (payload_ == null) { payload_ = new global::Grpc.Testing.Payload(); } input.ReadMessage(payload_); break; } case 58: { if (responseStatus_ == null) { responseStatus_ = new global::Grpc.Testing.EchoStatus(); } input.ReadMessage(responseStatus_); break; } } } } } /// /// Server-streaming response, as configured by the request and parameters. /// public sealed partial class StreamingOutputCallResponse : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new StreamingOutputCallResponse()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[9]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public StreamingOutputCallResponse() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public StreamingOutputCallResponse(StreamingOutputCallResponse other) : this() { Payload = other.payload_ != null ? other.Payload.Clone() : null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public StreamingOutputCallResponse Clone() { return new StreamingOutputCallResponse(this); } /// Field number for the "payload" field. public const int PayloadFieldNumber = 1; private global::Grpc.Testing.Payload payload_; /// /// Payload to increase response size. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.Payload Payload { get { return payload_; } set { payload_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as StreamingOutputCallResponse); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(StreamingOutputCallResponse other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (!object.Equals(Payload, other.Payload)) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (payload_ != null) hash ^= Payload.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (payload_ != null) { output.WriteRawTag(10); output.WriteMessage(Payload); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (payload_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(StreamingOutputCallResponse other) { if (other == null) { return; } if (other.payload_ != null) { if (payload_ == null) { payload_ = new global::Grpc.Testing.Payload(); } Payload.MergeFrom(other.Payload); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { if (payload_ == null) { payload_ = new global::Grpc.Testing.Payload(); } input.ReadMessage(payload_); break; } } } } } /// /// For reconnect interop test only. /// Client tells server what reconnection parameters it used. /// public sealed partial class ReconnectParams : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ReconnectParams()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[10]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ReconnectParams() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ReconnectParams(ReconnectParams other) : this() { maxReconnectBackoffMs_ = other.maxReconnectBackoffMs_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ReconnectParams Clone() { return new ReconnectParams(this); } /// Field number for the "max_reconnect_backoff_ms" field. public const int MaxReconnectBackoffMsFieldNumber = 1; private int maxReconnectBackoffMs_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int MaxReconnectBackoffMs { get { return maxReconnectBackoffMs_; } set { maxReconnectBackoffMs_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ReconnectParams); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ReconnectParams other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (MaxReconnectBackoffMs != other.MaxReconnectBackoffMs) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (MaxReconnectBackoffMs != 0) hash ^= MaxReconnectBackoffMs.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (MaxReconnectBackoffMs != 0) { output.WriteRawTag(8); output.WriteInt32(MaxReconnectBackoffMs); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (MaxReconnectBackoffMs != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(MaxReconnectBackoffMs); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ReconnectParams other) { if (other == null) { return; } if (other.MaxReconnectBackoffMs != 0) { MaxReconnectBackoffMs = other.MaxReconnectBackoffMs; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { MaxReconnectBackoffMs = input.ReadInt32(); break; } } } } } /// /// For reconnect interop test only. /// Server tells client whether its reconnects are following the spec and the /// reconnect backoffs it saw. /// public sealed partial class ReconnectInfo : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ReconnectInfo()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[11]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ReconnectInfo() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ReconnectInfo(ReconnectInfo other) : this() { passed_ = other.passed_; backoffMs_ = other.backoffMs_.Clone(); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ReconnectInfo Clone() { return new ReconnectInfo(this); } /// Field number for the "passed" field. public const int PassedFieldNumber = 1; private bool passed_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Passed { get { return passed_; } set { passed_ = value; } } /// Field number for the "backoff_ms" field. public const int BackoffMsFieldNumber = 2; private static readonly pb::FieldCodec _repeated_backoffMs_codec = pb::FieldCodec.ForInt32(18); private readonly pbc::RepeatedField backoffMs_ = new pbc::RepeatedField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::RepeatedField BackoffMs { get { return backoffMs_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ReconnectInfo); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ReconnectInfo other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Passed != other.Passed) return false; if(!backoffMs_.Equals(other.backoffMs_)) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Passed != false) hash ^= Passed.GetHashCode(); hash ^= backoffMs_.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Passed != false) { output.WriteRawTag(8); output.WriteBool(Passed); } backoffMs_.WriteTo(output, _repeated_backoffMs_codec); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Passed != false) { size += 1 + 1; } size += backoffMs_.CalculateSize(_repeated_backoffMs_codec); return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ReconnectInfo other) { if (other == null) { return; } if (other.Passed != false) { Passed = other.Passed; } backoffMs_.Add(other.backoffMs_); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { Passed = input.ReadBool(); break; } case 18: case 16: { backoffMs_.AddEntriesFrom(input, _repeated_backoffMs_codec); break; } } } } } #endregion } #endregion Designer generated code grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs000066400000000000000000000141311310511640000263060ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Utils; using Grpc.Testing; using NUnit.Framework; namespace Grpc.IntegrationTesting { public class MetadataCredentialsTest { const string Host = "localhost"; Server server; Channel channel; TestService.TestServiceClient client; List options; AsyncAuthInterceptor asyncAuthInterceptor; [SetUp] public void Init() { // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) { Services = { TestService.BindService(new FakeTestService()) }, Ports = { { Host, ServerPort.PickUnused, TestCredentials.CreateSslServerCredentials() } } }; server.Start(); options = new List { new ChannelOption(ChannelOptions.SslTargetNameOverride, TestCredentials.DefaultHostOverride) }; asyncAuthInterceptor = new AsyncAuthInterceptor(async (context, metadata) => { await Task.Delay(100).ConfigureAwait(false); // make sure the operation is asynchronous. metadata.Add("authorization", "SECRET_TOKEN"); }); } [TearDown] public void Cleanup() { channel.ShutdownAsync().Wait(); server.ShutdownAsync().Wait(); } [Test] public void MetadataCredentials() { var channelCredentials = ChannelCredentials.Create(TestCredentials.CreateSslCredentials(), CallCredentials.FromInterceptor(asyncAuthInterceptor)); channel = new Channel(Host, server.Ports.Single().BoundPort, channelCredentials, options); client = new TestService.TestServiceClient(channel); client.UnaryCall(new SimpleRequest { }); } [Test] public void MetadataCredentials_PerCall() { channel = new Channel(Host, server.Ports.Single().BoundPort, TestCredentials.CreateSslCredentials(), options); client = new TestService.TestServiceClient(channel); var callCredentials = CallCredentials.FromInterceptor(asyncAuthInterceptor); client.UnaryCall(new SimpleRequest { }, new CallOptions(credentials: callCredentials)); } [Test] public void MetadataCredentials_InterceptorLeavesMetadataEmpty() { var channelCredentials = ChannelCredentials.Create(TestCredentials.CreateSslCredentials(), CallCredentials.FromInterceptor(new AsyncAuthInterceptor((context, metadata) => TaskUtils.CompletedTask))); channel = new Channel(Host, server.Ports.Single().BoundPort, channelCredentials, options); client = new TestService.TestServiceClient(channel); var ex = Assert.Throws(() => client.UnaryCall(new SimpleRequest { })); // StatusCode.Unknown as the server-side handler throws an exception after not receiving the authorization header. Assert.AreEqual(StatusCode.Unknown, ex.Status.StatusCode); } [Test] public void MetadataCredentials_InterceptorThrows() { var callCredentials = CallCredentials.FromInterceptor(new AsyncAuthInterceptor((context, metadata) => { throw new Exception("Auth interceptor throws"); })); var channelCredentials = ChannelCredentials.Create(TestCredentials.CreateSslCredentials(), callCredentials); channel = new Channel(Host, server.Ports.Single().BoundPort, channelCredentials, options); client = new TestService.TestServiceClient(channel); var ex = Assert.Throws(() => client.UnaryCall(new SimpleRequest { })); Assert.AreEqual(StatusCode.Unauthenticated, ex.Status.StatusCode); } private class FakeTestService : TestService.TestServiceBase { public override Task UnaryCall(SimpleRequest request, ServerCallContext context) { var authToken = context.RequestHeaders.First((entry) => entry.Key == "authorization").Value; Assert.AreEqual("SECRET_TOKEN", authToken); return Task.FromResult(new SimpleResponse()); } } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/Metrics.cs000066400000000000000000000375551310511640000231750ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: src/proto/grpc/testing/metrics.proto #pragma warning disable 1591, 0612, 3021 #region Designer generated code using pb = global::Google.Protobuf; using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; namespace Grpc.Testing { /// Holder for reflection information generated from src/proto/grpc/testing/metrics.proto public static partial class MetricsReflection { #region Descriptor /// File descriptor for src/proto/grpc/testing/metrics.proto public static pbr::FileDescriptor Descriptor { get { return descriptor; } } private static pbr::FileDescriptor descriptor; static MetricsReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "CiRzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL21ldHJpY3MucHJvdG8SDGdycGMu", "dGVzdGluZyJsCg1HYXVnZVJlc3BvbnNlEgwKBG5hbWUYASABKAkSFAoKbG9u", "Z192YWx1ZRgCIAEoA0gAEhYKDGRvdWJsZV92YWx1ZRgDIAEoAUgAEhYKDHN0", "cmluZ192YWx1ZRgEIAEoCUgAQgcKBXZhbHVlIhwKDEdhdWdlUmVxdWVzdBIM", "CgRuYW1lGAEgASgJIg4KDEVtcHR5TWVzc2FnZTKgAQoOTWV0cmljc1NlcnZp", "Y2USSQoMR2V0QWxsR2F1Z2VzEhouZ3JwYy50ZXN0aW5nLkVtcHR5TWVzc2Fn", "ZRobLmdycGMudGVzdGluZy5HYXVnZVJlc3BvbnNlMAESQwoIR2V0R2F1Z2US", "Gi5ncnBjLnRlc3RpbmcuR2F1Z2VSZXF1ZXN0GhsuZ3JwYy50ZXN0aW5nLkdh", "dWdlUmVzcG9uc2ViBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.GaugeResponse), global::Grpc.Testing.GaugeResponse.Parser, new[]{ "Name", "LongValue", "DoubleValue", "StringValue" }, new[]{ "Value" }, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.GaugeRequest), global::Grpc.Testing.GaugeRequest.Parser, new[]{ "Name" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.EmptyMessage), global::Grpc.Testing.EmptyMessage.Parser, null, null, null, null) })); } #endregion } #region Messages /// /// Reponse message containing the gauge name and value /// public sealed partial class GaugeResponse : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new GaugeResponse()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.MetricsReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public GaugeResponse() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public GaugeResponse(GaugeResponse other) : this() { name_ = other.name_; switch (other.ValueCase) { case ValueOneofCase.LongValue: LongValue = other.LongValue; break; case ValueOneofCase.DoubleValue: DoubleValue = other.DoubleValue; break; case ValueOneofCase.StringValue: StringValue = other.StringValue; break; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public GaugeResponse Clone() { return new GaugeResponse(this); } /// Field number for the "name" field. public const int NameFieldNumber = 1; private string name_ = ""; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Name { get { return name_; } set { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Field number for the "long_value" field. public const int LongValueFieldNumber = 2; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public long LongValue { get { return valueCase_ == ValueOneofCase.LongValue ? (long) value_ : 0L; } set { value_ = value; valueCase_ = ValueOneofCase.LongValue; } } /// Field number for the "double_value" field. public const int DoubleValueFieldNumber = 3; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double DoubleValue { get { return valueCase_ == ValueOneofCase.DoubleValue ? (double) value_ : 0D; } set { value_ = value; valueCase_ = ValueOneofCase.DoubleValue; } } /// Field number for the "string_value" field. public const int StringValueFieldNumber = 4; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string StringValue { get { return valueCase_ == ValueOneofCase.StringValue ? (string) value_ : ""; } set { value_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); valueCase_ = ValueOneofCase.StringValue; } } private object value_; /// Enum of possible cases for the "value" oneof. public enum ValueOneofCase { None = 0, LongValue = 2, DoubleValue = 3, StringValue = 4, } private ValueOneofCase valueCase_ = ValueOneofCase.None; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ValueOneofCase ValueCase { get { return valueCase_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearValue() { valueCase_ = ValueOneofCase.None; value_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as GaugeResponse); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(GaugeResponse other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Name != other.Name) return false; if (LongValue != other.LongValue) return false; if (DoubleValue != other.DoubleValue) return false; if (StringValue != other.StringValue) return false; if (ValueCase != other.ValueCase) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Name.Length != 0) hash ^= Name.GetHashCode(); if (valueCase_ == ValueOneofCase.LongValue) hash ^= LongValue.GetHashCode(); if (valueCase_ == ValueOneofCase.DoubleValue) hash ^= DoubleValue.GetHashCode(); if (valueCase_ == ValueOneofCase.StringValue) hash ^= StringValue.GetHashCode(); hash ^= (int) valueCase_; return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); } if (valueCase_ == ValueOneofCase.LongValue) { output.WriteRawTag(16); output.WriteInt64(LongValue); } if (valueCase_ == ValueOneofCase.DoubleValue) { output.WriteRawTag(25); output.WriteDouble(DoubleValue); } if (valueCase_ == ValueOneofCase.StringValue) { output.WriteRawTag(34); output.WriteString(StringValue); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Name.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } if (valueCase_ == ValueOneofCase.LongValue) { size += 1 + pb::CodedOutputStream.ComputeInt64Size(LongValue); } if (valueCase_ == ValueOneofCase.DoubleValue) { size += 1 + 8; } if (valueCase_ == ValueOneofCase.StringValue) { size += 1 + pb::CodedOutputStream.ComputeStringSize(StringValue); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(GaugeResponse other) { if (other == null) { return; } if (other.Name.Length != 0) { Name = other.Name; } switch (other.ValueCase) { case ValueOneofCase.LongValue: LongValue = other.LongValue; break; case ValueOneofCase.DoubleValue: DoubleValue = other.DoubleValue; break; case ValueOneofCase.StringValue: StringValue = other.StringValue; break; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { Name = input.ReadString(); break; } case 16: { LongValue = input.ReadInt64(); break; } case 25: { DoubleValue = input.ReadDouble(); break; } case 34: { StringValue = input.ReadString(); break; } } } } } /// /// Request message containing the gauge name /// public sealed partial class GaugeRequest : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new GaugeRequest()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.MetricsReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public GaugeRequest() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public GaugeRequest(GaugeRequest other) : this() { name_ = other.name_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public GaugeRequest Clone() { return new GaugeRequest(this); } /// Field number for the "name" field. public const int NameFieldNumber = 1; private string name_ = ""; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Name { get { return name_; } set { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as GaugeRequest); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(GaugeRequest other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Name != other.Name) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Name.Length != 0) hash ^= Name.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Name.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(GaugeRequest other) { if (other == null) { return; } if (other.Name.Length != 0) { Name = other.Name; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { Name = input.ReadString(); break; } } } } } public sealed partial class EmptyMessage : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new EmptyMessage()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.MetricsReflection.Descriptor.MessageTypes[2]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public EmptyMessage() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public EmptyMessage(EmptyMessage other) : this() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public EmptyMessage Clone() { return new EmptyMessage(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as EmptyMessage); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(EmptyMessage other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(EmptyMessage other) { if (other == null) { return; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; } } } } #endregion } #endregion Designer generated code grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs000066400000000000000000000272701310511640000240020ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: src/proto/grpc/testing/metrics.proto // Original file comments: // Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Contains the definitions for a metrics service and the type of metrics // exposed by the service. // // Currently, 'Gauge' (i.e a metric that represents the measured value of // something at an instant of time) is the only metric type supported by the // service. #region Designer generated code using System; using System.Threading; using System.Threading.Tasks; using grpc = global::Grpc.Core; namespace Grpc.Testing { public static partial class MetricsService { static readonly string __ServiceName = "grpc.testing.MetricsService"; static readonly grpc::Marshaller __Marshaller_EmptyMessage = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.EmptyMessage.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_GaugeResponse = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.GaugeResponse.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_GaugeRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.GaugeRequest.Parser.ParseFrom); static readonly grpc::Method __Method_GetAllGauges = new grpc::Method( grpc::MethodType.ServerStreaming, __ServiceName, "GetAllGauges", __Marshaller_EmptyMessage, __Marshaller_GaugeResponse); static readonly grpc::Method __Method_GetGauge = new grpc::Method( grpc::MethodType.Unary, __ServiceName, "GetGauge", __Marshaller_GaugeRequest, __Marshaller_GaugeResponse); /// Service descriptor public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor { get { return global::Grpc.Testing.MetricsReflection.Descriptor.Services[0]; } } /// Base class for server-side implementations of MetricsService public abstract partial class MetricsServiceBase { /// /// Returns the values of all the gauges that are currently being maintained by /// the service /// /// The request received from the client. /// Used for sending responses back to the client. /// The context of the server-side call handler being invoked. /// A task indicating completion of the handler. public virtual global::System.Threading.Tasks.Task GetAllGauges(global::Grpc.Testing.EmptyMessage request, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } /// /// Returns the value of one gauge /// /// The request received from the client. /// The context of the server-side call handler being invoked. /// The response to send back to the client (wrapped by a task). public virtual global::System.Threading.Tasks.Task GetGauge(global::Grpc.Testing.GaugeRequest request, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } } /// Client for MetricsService public partial class MetricsServiceClient : grpc::ClientBase { /// Creates a new client for MetricsService /// The channel to use to make remote calls. public MetricsServiceClient(grpc::Channel channel) : base(channel) { } /// Creates a new client for MetricsService that uses a custom CallInvoker. /// The callInvoker to use to make remote calls. public MetricsServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker) { } /// Protected parameterless constructor to allow creation of test doubles. protected MetricsServiceClient() : base() { } /// Protected constructor to allow creation of configured clients. /// The client configuration. protected MetricsServiceClient(ClientBaseConfiguration configuration) : base(configuration) { } /// /// Returns the values of all the gauges that are currently being maintained by /// the service /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncServerStreamingCall GetAllGauges(global::Grpc.Testing.EmptyMessage request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return GetAllGauges(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// Returns the values of all the gauges that are currently being maintained by /// the service /// /// The request to send to the server. /// The options for the call. /// The call object. public virtual grpc::AsyncServerStreamingCall GetAllGauges(global::Grpc.Testing.EmptyMessage request, grpc::CallOptions options) { return CallInvoker.AsyncServerStreamingCall(__Method_GetAllGauges, null, options, request); } /// /// Returns the value of one gauge /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The response received from the server. public virtual global::Grpc.Testing.GaugeResponse GetGauge(global::Grpc.Testing.GaugeRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return GetGauge(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// Returns the value of one gauge /// /// The request to send to the server. /// The options for the call. /// The response received from the server. public virtual global::Grpc.Testing.GaugeResponse GetGauge(global::Grpc.Testing.GaugeRequest request, grpc::CallOptions options) { return CallInvoker.BlockingUnaryCall(__Method_GetGauge, null, options, request); } /// /// Returns the value of one gauge /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncUnaryCall GetGaugeAsync(global::Grpc.Testing.GaugeRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return GetGaugeAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// Returns the value of one gauge /// /// The request to send to the server. /// The options for the call. /// The call object. public virtual grpc::AsyncUnaryCall GetGaugeAsync(global::Grpc.Testing.GaugeRequest request, grpc::CallOptions options) { return CallInvoker.AsyncUnaryCall(__Method_GetGauge, null, options, request); } /// Creates a new instance of client from given ClientBaseConfiguration. protected override MetricsServiceClient NewInstance(ClientBaseConfiguration configuration) { return new MetricsServiceClient(configuration); } } /// Creates service definition that can be registered with a server /// An object implementing the server-side handling logic. public static grpc::ServerServiceDefinition BindService(MetricsServiceBase serviceImpl) { return grpc::ServerServiceDefinition.CreateBuilder() .AddMethod(__Method_GetAllGauges, serviceImpl.GetAllGauges) .AddMethod(__Method_GetGauge, serviceImpl.GetGauge).Build(); } } } #endregion grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs000066400000000000000000000045031310511640000234140ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Reflection; using Grpc.Core; using Grpc.Core.Logging; using NUnit.Common; using NUnitLite; namespace Grpc.IntegrationTesting { /// /// Provides entry point for NUnitLite /// public class NUnitMain { public static int Main(string[] args) { // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error)); #if NETCOREAPP1_0 return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In); #else return new AutoRun().Execute(args); #endif } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/Payloads.cs000066400000000000000000000536351310511640000233400ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: src/proto/grpc/testing/payloads.proto #pragma warning disable 1591, 0612, 3021 #region Designer generated code using pb = global::Google.Protobuf; using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; namespace Grpc.Testing { /// Holder for reflection information generated from src/proto/grpc/testing/payloads.proto public static partial class PayloadsReflection { #region Descriptor /// File descriptor for src/proto/grpc/testing/payloads.proto public static pbr::FileDescriptor Descriptor { get { return descriptor; } } private static pbr::FileDescriptor descriptor; static PayloadsReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "CiVzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL3BheWxvYWRzLnByb3RvEgxncnBj", "LnRlc3RpbmciNwoQQnl0ZUJ1ZmZlclBhcmFtcxIQCghyZXFfc2l6ZRgBIAEo", "BRIRCglyZXNwX3NpemUYAiABKAUiOAoRU2ltcGxlUHJvdG9QYXJhbXMSEAoI", "cmVxX3NpemUYASABKAUSEQoJcmVzcF9zaXplGAIgASgFIhQKEkNvbXBsZXhQ", "cm90b1BhcmFtcyLKAQoNUGF5bG9hZENvbmZpZxI4Cg5ieXRlYnVmX3BhcmFt", "cxgBIAEoCzIeLmdycGMudGVzdGluZy5CeXRlQnVmZmVyUGFyYW1zSAASOAoN", "c2ltcGxlX3BhcmFtcxgCIAEoCzIfLmdycGMudGVzdGluZy5TaW1wbGVQcm90", "b1BhcmFtc0gAEjoKDmNvbXBsZXhfcGFyYW1zGAMgASgLMiAuZ3JwYy50ZXN0", "aW5nLkNvbXBsZXhQcm90b1BhcmFtc0gAQgkKB3BheWxvYWRiBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ByteBufferParams), global::Grpc.Testing.ByteBufferParams.Parser, new[]{ "ReqSize", "RespSize" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SimpleProtoParams), global::Grpc.Testing.SimpleProtoParams.Parser, new[]{ "ReqSize", "RespSize" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ComplexProtoParams), global::Grpc.Testing.ComplexProtoParams.Parser, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.PayloadConfig), global::Grpc.Testing.PayloadConfig.Parser, new[]{ "BytebufParams", "SimpleParams", "ComplexParams" }, new[]{ "Payload" }, null, null) })); } #endregion } #region Messages public sealed partial class ByteBufferParams : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ByteBufferParams()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.PayloadsReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ByteBufferParams() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ByteBufferParams(ByteBufferParams other) : this() { reqSize_ = other.reqSize_; respSize_ = other.respSize_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ByteBufferParams Clone() { return new ByteBufferParams(this); } /// Field number for the "req_size" field. public const int ReqSizeFieldNumber = 1; private int reqSize_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int ReqSize { get { return reqSize_; } set { reqSize_ = value; } } /// Field number for the "resp_size" field. public const int RespSizeFieldNumber = 2; private int respSize_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int RespSize { get { return respSize_; } set { respSize_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ByteBufferParams); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ByteBufferParams other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (ReqSize != other.ReqSize) return false; if (RespSize != other.RespSize) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (ReqSize != 0) hash ^= ReqSize.GetHashCode(); if (RespSize != 0) hash ^= RespSize.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (ReqSize != 0) { output.WriteRawTag(8); output.WriteInt32(ReqSize); } if (RespSize != 0) { output.WriteRawTag(16); output.WriteInt32(RespSize); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (ReqSize != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(ReqSize); } if (RespSize != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(RespSize); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ByteBufferParams other) { if (other == null) { return; } if (other.ReqSize != 0) { ReqSize = other.ReqSize; } if (other.RespSize != 0) { RespSize = other.RespSize; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { ReqSize = input.ReadInt32(); break; } case 16: { RespSize = input.ReadInt32(); break; } } } } } public sealed partial class SimpleProtoParams : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SimpleProtoParams()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.PayloadsReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public SimpleProtoParams() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public SimpleProtoParams(SimpleProtoParams other) : this() { reqSize_ = other.reqSize_; respSize_ = other.respSize_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public SimpleProtoParams Clone() { return new SimpleProtoParams(this); } /// Field number for the "req_size" field. public const int ReqSizeFieldNumber = 1; private int reqSize_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int ReqSize { get { return reqSize_; } set { reqSize_ = value; } } /// Field number for the "resp_size" field. public const int RespSizeFieldNumber = 2; private int respSize_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int RespSize { get { return respSize_; } set { respSize_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as SimpleProtoParams); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(SimpleProtoParams other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (ReqSize != other.ReqSize) return false; if (RespSize != other.RespSize) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (ReqSize != 0) hash ^= ReqSize.GetHashCode(); if (RespSize != 0) hash ^= RespSize.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (ReqSize != 0) { output.WriteRawTag(8); output.WriteInt32(ReqSize); } if (RespSize != 0) { output.WriteRawTag(16); output.WriteInt32(RespSize); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (ReqSize != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(ReqSize); } if (RespSize != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(RespSize); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(SimpleProtoParams other) { if (other == null) { return; } if (other.ReqSize != 0) { ReqSize = other.ReqSize; } if (other.RespSize != 0) { RespSize = other.RespSize; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { ReqSize = input.ReadInt32(); break; } case 16: { RespSize = input.ReadInt32(); break; } } } } } /// /// TODO (vpai): Fill this in once the details of complex, representative /// protos are decided /// public sealed partial class ComplexProtoParams : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ComplexProtoParams()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.PayloadsReflection.Descriptor.MessageTypes[2]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ComplexProtoParams() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ComplexProtoParams(ComplexProtoParams other) : this() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ComplexProtoParams Clone() { return new ComplexProtoParams(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ComplexProtoParams); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ComplexProtoParams other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ComplexProtoParams other) { if (other == null) { return; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; } } } } public sealed partial class PayloadConfig : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new PayloadConfig()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.PayloadsReflection.Descriptor.MessageTypes[3]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public PayloadConfig() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public PayloadConfig(PayloadConfig other) : this() { switch (other.PayloadCase) { case PayloadOneofCase.BytebufParams: BytebufParams = other.BytebufParams.Clone(); break; case PayloadOneofCase.SimpleParams: SimpleParams = other.SimpleParams.Clone(); break; case PayloadOneofCase.ComplexParams: ComplexParams = other.ComplexParams.Clone(); break; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public PayloadConfig Clone() { return new PayloadConfig(this); } /// Field number for the "bytebuf_params" field. public const int BytebufParamsFieldNumber = 1; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.ByteBufferParams BytebufParams { get { return payloadCase_ == PayloadOneofCase.BytebufParams ? (global::Grpc.Testing.ByteBufferParams) payload_ : null; } set { payload_ = value; payloadCase_ = value == null ? PayloadOneofCase.None : PayloadOneofCase.BytebufParams; } } /// Field number for the "simple_params" field. public const int SimpleParamsFieldNumber = 2; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.SimpleProtoParams SimpleParams { get { return payloadCase_ == PayloadOneofCase.SimpleParams ? (global::Grpc.Testing.SimpleProtoParams) payload_ : null; } set { payload_ = value; payloadCase_ = value == null ? PayloadOneofCase.None : PayloadOneofCase.SimpleParams; } } /// Field number for the "complex_params" field. public const int ComplexParamsFieldNumber = 3; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.ComplexProtoParams ComplexParams { get { return payloadCase_ == PayloadOneofCase.ComplexParams ? (global::Grpc.Testing.ComplexProtoParams) payload_ : null; } set { payload_ = value; payloadCase_ = value == null ? PayloadOneofCase.None : PayloadOneofCase.ComplexParams; } } private object payload_; /// Enum of possible cases for the "payload" oneof. public enum PayloadOneofCase { None = 0, BytebufParams = 1, SimpleParams = 2, ComplexParams = 3, } private PayloadOneofCase payloadCase_ = PayloadOneofCase.None; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public PayloadOneofCase PayloadCase { get { return payloadCase_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearPayload() { payloadCase_ = PayloadOneofCase.None; payload_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as PayloadConfig); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(PayloadConfig other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (!object.Equals(BytebufParams, other.BytebufParams)) return false; if (!object.Equals(SimpleParams, other.SimpleParams)) return false; if (!object.Equals(ComplexParams, other.ComplexParams)) return false; if (PayloadCase != other.PayloadCase) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (payloadCase_ == PayloadOneofCase.BytebufParams) hash ^= BytebufParams.GetHashCode(); if (payloadCase_ == PayloadOneofCase.SimpleParams) hash ^= SimpleParams.GetHashCode(); if (payloadCase_ == PayloadOneofCase.ComplexParams) hash ^= ComplexParams.GetHashCode(); hash ^= (int) payloadCase_; return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (payloadCase_ == PayloadOneofCase.BytebufParams) { output.WriteRawTag(10); output.WriteMessage(BytebufParams); } if (payloadCase_ == PayloadOneofCase.SimpleParams) { output.WriteRawTag(18); output.WriteMessage(SimpleParams); } if (payloadCase_ == PayloadOneofCase.ComplexParams) { output.WriteRawTag(26); output.WriteMessage(ComplexParams); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (payloadCase_ == PayloadOneofCase.BytebufParams) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(BytebufParams); } if (payloadCase_ == PayloadOneofCase.SimpleParams) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(SimpleParams); } if (payloadCase_ == PayloadOneofCase.ComplexParams) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(ComplexParams); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(PayloadConfig other) { if (other == null) { return; } switch (other.PayloadCase) { case PayloadOneofCase.BytebufParams: BytebufParams = other.BytebufParams; break; case PayloadOneofCase.SimpleParams: SimpleParams = other.SimpleParams; break; case PayloadOneofCase.ComplexParams: ComplexParams = other.ComplexParams; break; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { global::Grpc.Testing.ByteBufferParams subBuilder = new global::Grpc.Testing.ByteBufferParams(); if (payloadCase_ == PayloadOneofCase.BytebufParams) { subBuilder.MergeFrom(BytebufParams); } input.ReadMessage(subBuilder); BytebufParams = subBuilder; break; } case 18: { global::Grpc.Testing.SimpleProtoParams subBuilder = new global::Grpc.Testing.SimpleProtoParams(); if (payloadCase_ == PayloadOneofCase.SimpleParams) { subBuilder.MergeFrom(SimpleParams); } input.ReadMessage(subBuilder); SimpleParams = subBuilder; break; } case 26: { global::Grpc.Testing.ComplexProtoParams subBuilder = new global::Grpc.Testing.ComplexProtoParams(); if (payloadCase_ == PayloadOneofCase.ComplexParams) { subBuilder.MergeFrom(ComplexParams); } input.ReadMessage(subBuilder); ComplexParams = subBuilder; break; } } } } } #endregion } #endregion Designer generated code grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/Properties/000077500000000000000000000000001310511640000233555ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/Properties/AssemblyInfo.cs000066400000000000000000000037141310511640000263040ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Grpc.IntegrationTesting")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs000066400000000000000000000074541310511640000235170ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; using CommandLine; using CommandLine.Text; using Grpc.Core; using Grpc.Core.Logging; using Grpc.Core.Utils; using Grpc.Testing; using NUnit.Framework; namespace Grpc.IntegrationTesting { public class QpsWorker { private class ServerOptions { [Option("driver_port", Default = 0)] public int DriverPort { get; set; } } ServerOptions options; private QpsWorker(ServerOptions options) { this.options = options; } public static void Run(string[] args) { GrpcEnvironment.SetLogger(new ConsoleLogger()); var parserResult = Parser.Default.ParseArguments(args) .WithNotParsed((x) => Environment.Exit(1)) .WithParsed(options => { var workerServer = new QpsWorker(options); workerServer.RunAsync().Wait(); }); } private async Task RunAsync() { // (ThreadPoolSize == ProcessorCount) gives best throughput in benchmarks // and doesn't seem to harm performance even when server and client // are running on the same machine. GrpcEnvironment.SetThreadPoolSize(Environment.ProcessorCount); string host = "0.0.0.0"; int port = options.DriverPort; var tcs = new TaskCompletionSource(); var workerServiceImpl = new WorkerServiceImpl(() => { Task.Run(() => tcs.SetResult(null)); }); var server = new Server { Services = { WorkerService.BindService(workerServiceImpl) }, Ports = { new ServerPort(host, options.DriverPort, ServerCredentials.Insecure )} }; int boundPort = server.Ports.Single().BoundPort; Console.WriteLine("Running qps worker server on " + string.Format("{0}:{1}", host, boundPort)); server.Start(); await tcs.Task; await server.ShutdownAsync(); } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs000066400000000000000000000074401310511640000262140ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Utils; using Grpc.Testing; using NUnit.Framework; namespace Grpc.IntegrationTesting { /// /// Runs performance tests in-process. /// public class RunnerClientServerTest { IServerRunner serverRunner; [TestFixtureSetUp] public void Init() { var serverConfig = new ServerConfig { ServerType = ServerType.AsyncServer }; serverRunner = ServerRunners.CreateStarted(serverConfig); } [TestFixtureTearDown] public void Cleanup() { serverRunner.StopAsync().Wait(); } [Test] [Category("Performance")] [Ignore("Prevent running on Jenkins")] public async Task ClientServerRunner() { var config = new ClientConfig { ServerTargets = { string.Format("{0}:{1}", "localhost", serverRunner.BoundPort) }, RpcType = RpcType.Unary, LoadParams = new LoadParams { ClosedLoop = new ClosedLoopParams() }, PayloadConfig = new PayloadConfig { SimpleParams = new SimpleProtoParams { ReqSize = 100, RespSize = 100 } }, HistogramParams = new HistogramParams { Resolution = 0.01, MaxPossible = 60e9 } }; var runner = ClientRunners.CreateStarted(config); System.Console.WriteLine("Warming up"); await Task.Delay(3000); runner.GetStats(true); // throw away warm-up data System.Console.WriteLine("Benchmarking"); await Task.Delay(3000); var stats = runner.GetStats(true); await runner.StopAsync(); System.Console.WriteLine(stats); System.Console.WriteLine("avg micros/call " + (long) (stats.Latencies.Sum / stats.Latencies.Count / 1000.0)); } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs000066400000000000000000000140651310511640000244010ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Google.Protobuf; using Grpc.Core; using Grpc.Core.Logging; using Grpc.Core.Utils; using NUnit.Framework; using Grpc.Testing; namespace Grpc.IntegrationTesting { /// /// Helper methods to start server runners for performance testing. /// public class ServerRunners { static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); /// /// Creates a started server runner. /// public static IServerRunner CreateStarted(ServerConfig config) { Logger.Debug("ServerConfig: {0}", config); var credentials = config.SecurityParams != null ? TestCredentials.CreateSslServerCredentials() : ServerCredentials.Insecure; if (config.AsyncServerThreads != 0) { Logger.Warning("ServerConfig.AsyncServerThreads is not supported for C#. Ignoring the value"); } if (config.CoreLimit != 0) { Logger.Warning("ServerConfig.CoreLimit is not supported for C#. Ignoring the value"); } if (config.CoreList.Count > 0) { Logger.Warning("ServerConfig.CoreList is not supported for C#. Ignoring the value"); } ServerServiceDefinition service = null; if (config.ServerType == ServerType.AsyncServer) { GrpcPreconditions.CheckArgument(config.PayloadConfig == null, "ServerConfig.PayloadConfig shouldn't be set for BenchmarkService based server."); service = BenchmarkService.BindService(new BenchmarkServiceImpl()); } else if (config.ServerType == ServerType.AsyncGenericServer) { var genericService = new GenericServiceImpl(config.PayloadConfig.BytebufParams.RespSize); service = GenericService.BindHandler(genericService.StreamingCall); } else { throw new ArgumentException("Unsupported ServerType"); } var server = new Server { Services = { service }, Ports = { new ServerPort("[::]", config.Port, credentials) } }; server.Start(); return new ServerRunnerImpl(server); } private class GenericServiceImpl { readonly byte[] response; public GenericServiceImpl(int responseSize) { this.response = new byte[responseSize]; } /// /// Generic streaming call handler. /// public async Task StreamingCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) { await requestStream.ForEachAsync(async request => { await responseStream.WriteAsync(response); }); } } } /// /// Server runner. /// public class ServerRunnerImpl : IServerRunner { readonly Server server; readonly WallClockStopwatch wallClockStopwatch = new WallClockStopwatch(); public ServerRunnerImpl(Server server) { this.server = GrpcPreconditions.CheckNotNull(server); } public int BoundPort { get { return server.Ports.Single().BoundPort; } } /// /// Gets server stats. /// /// The stats. public ServerStats GetStats(bool reset) { var secondsElapsed = wallClockStopwatch.GetElapsedSnapshot(reset).TotalSeconds; // TODO: populate user time and system time return new ServerStats { TimeElapsed = secondsElapsed, TimeUser = 0, TimeSystem = 0 }; } /// /// Asynchronously stops the server. /// /// Task that finishes when server has shutdown. public Task StopAsync() { return server.ShutdownAsync(); } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/Services.cs000066400000000000000000000043571310511640000233440ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: src/proto/grpc/testing/services.proto #pragma warning disable 1591, 0612, 3021 #region Designer generated code using pb = global::Google.Protobuf; using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; namespace Grpc.Testing { /// Holder for reflection information generated from src/proto/grpc/testing/services.proto public static partial class ServicesReflection { #region Descriptor /// File descriptor for src/proto/grpc/testing/services.proto public static pbr::FileDescriptor Descriptor { get { return descriptor; } } private static pbr::FileDescriptor descriptor; static ServicesReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "CiVzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL3NlcnZpY2VzLnByb3RvEgxncnBj", "LnRlc3RpbmcaJXNyYy9wcm90by9ncnBjL3Rlc3RpbmcvbWVzc2FnZXMucHJv", "dG8aJHNyYy9wcm90by9ncnBjL3Rlc3RpbmcvY29udHJvbC5wcm90bzKqAQoQ", "QmVuY2htYXJrU2VydmljZRJGCglVbmFyeUNhbGwSGy5ncnBjLnRlc3Rpbmcu", "U2ltcGxlUmVxdWVzdBocLmdycGMudGVzdGluZy5TaW1wbGVSZXNwb25zZRJO", "Cg1TdHJlYW1pbmdDYWxsEhsuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlcXVlc3Qa", "HC5ncnBjLnRlc3RpbmcuU2ltcGxlUmVzcG9uc2UoATABMpcCCg1Xb3JrZXJT", "ZXJ2aWNlEkUKCVJ1blNlcnZlchIYLmdycGMudGVzdGluZy5TZXJ2ZXJBcmdz", "GhouZ3JwYy50ZXN0aW5nLlNlcnZlclN0YXR1cygBMAESRQoJUnVuQ2xpZW50", "EhguZ3JwYy50ZXN0aW5nLkNsaWVudEFyZ3MaGi5ncnBjLnRlc3RpbmcuQ2xp", "ZW50U3RhdHVzKAEwARJCCglDb3JlQ291bnQSGS5ncnBjLnRlc3RpbmcuQ29y", "ZVJlcXVlc3QaGi5ncnBjLnRlc3RpbmcuQ29yZVJlc3BvbnNlEjQKClF1aXRX", "b3JrZXISEi5ncnBjLnRlc3RpbmcuVm9pZBoSLmdycGMudGVzdGluZy5Wb2lk", "YgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Grpc.Testing.MessagesReflection.Descriptor, global::Grpc.Testing.ControlReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(null, null)); } #endregion } } #endregion Designer generated code grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs000066400000000000000000000735271310511640000241650ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: src/proto/grpc/testing/services.proto // Original file comments: // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // An integration test service that covers all the method signature permutations // of unary/streaming requests/responses. #region Designer generated code using System; using System.Threading; using System.Threading.Tasks; using grpc = global::Grpc.Core; namespace Grpc.Testing { public static partial class BenchmarkService { static readonly string __ServiceName = "grpc.testing.BenchmarkService"; static readonly grpc::Marshaller __Marshaller_SimpleRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleRequest.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_SimpleResponse = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleResponse.Parser.ParseFrom); static readonly grpc::Method __Method_UnaryCall = new grpc::Method( grpc::MethodType.Unary, __ServiceName, "UnaryCall", __Marshaller_SimpleRequest, __Marshaller_SimpleResponse); static readonly grpc::Method __Method_StreamingCall = new grpc::Method( grpc::MethodType.DuplexStreaming, __ServiceName, "StreamingCall", __Marshaller_SimpleRequest, __Marshaller_SimpleResponse); /// Service descriptor public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor { get { return global::Grpc.Testing.ServicesReflection.Descriptor.Services[0]; } } /// Base class for server-side implementations of BenchmarkService public abstract partial class BenchmarkServiceBase { /// /// One request followed by one response. /// The server returns the client payload as-is. /// /// The request received from the client. /// The context of the server-side call handler being invoked. /// The response to send back to the client (wrapped by a task). public virtual global::System.Threading.Tasks.Task UnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } /// /// One request followed by one response. /// The server returns the client payload as-is. /// /// Used for reading requests from the client. /// Used for sending responses back to the client. /// The context of the server-side call handler being invoked. /// A task indicating completion of the handler. public virtual global::System.Threading.Tasks.Task StreamingCall(grpc::IAsyncStreamReader requestStream, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } } /// Client for BenchmarkService public partial class BenchmarkServiceClient : grpc::ClientBase { /// Creates a new client for BenchmarkService /// The channel to use to make remote calls. public BenchmarkServiceClient(grpc::Channel channel) : base(channel) { } /// Creates a new client for BenchmarkService that uses a custom CallInvoker. /// The callInvoker to use to make remote calls. public BenchmarkServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker) { } /// Protected parameterless constructor to allow creation of test doubles. protected BenchmarkServiceClient() : base() { } /// Protected constructor to allow creation of configured clients. /// The client configuration. protected BenchmarkServiceClient(ClientBaseConfiguration configuration) : base(configuration) { } /// /// One request followed by one response. /// The server returns the client payload as-is. /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The response received from the server. public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return UnaryCall(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// One request followed by one response. /// The server returns the client payload as-is. /// /// The request to send to the server. /// The options for the call. /// The response received from the server. public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::CallOptions options) { return CallInvoker.BlockingUnaryCall(__Method_UnaryCall, null, options, request); } /// /// One request followed by one response. /// The server returns the client payload as-is. /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncUnaryCall UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return UnaryCallAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// One request followed by one response. /// The server returns the client payload as-is. /// /// The request to send to the server. /// The options for the call. /// The call object. public virtual grpc::AsyncUnaryCall UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, grpc::CallOptions options) { return CallInvoker.AsyncUnaryCall(__Method_UnaryCall, null, options, request); } /// /// One request followed by one response. /// The server returns the client payload as-is. /// /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncDuplexStreamingCall StreamingCall(grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return StreamingCall(new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// One request followed by one response. /// The server returns the client payload as-is. /// /// The options for the call. /// The call object. public virtual grpc::AsyncDuplexStreamingCall StreamingCall(grpc::CallOptions options) { return CallInvoker.AsyncDuplexStreamingCall(__Method_StreamingCall, null, options); } /// Creates a new instance of client from given ClientBaseConfiguration. protected override BenchmarkServiceClient NewInstance(ClientBaseConfiguration configuration) { return new BenchmarkServiceClient(configuration); } } /// Creates service definition that can be registered with a server /// An object implementing the server-side handling logic. public static grpc::ServerServiceDefinition BindService(BenchmarkServiceBase serviceImpl) { return grpc::ServerServiceDefinition.CreateBuilder() .AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall) .AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall).Build(); } } public static partial class WorkerService { static readonly string __ServiceName = "grpc.testing.WorkerService"; static readonly grpc::Marshaller __Marshaller_ServerArgs = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ServerArgs.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_ServerStatus = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ServerStatus.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_ClientArgs = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ClientArgs.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_ClientStatus = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ClientStatus.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_CoreRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.CoreRequest.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_CoreResponse = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.CoreResponse.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_Void = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.Void.Parser.ParseFrom); static readonly grpc::Method __Method_RunServer = new grpc::Method( grpc::MethodType.DuplexStreaming, __ServiceName, "RunServer", __Marshaller_ServerArgs, __Marshaller_ServerStatus); static readonly grpc::Method __Method_RunClient = new grpc::Method( grpc::MethodType.DuplexStreaming, __ServiceName, "RunClient", __Marshaller_ClientArgs, __Marshaller_ClientStatus); static readonly grpc::Method __Method_CoreCount = new grpc::Method( grpc::MethodType.Unary, __ServiceName, "CoreCount", __Marshaller_CoreRequest, __Marshaller_CoreResponse); static readonly grpc::Method __Method_QuitWorker = new grpc::Method( grpc::MethodType.Unary, __ServiceName, "QuitWorker", __Marshaller_Void, __Marshaller_Void); /// Service descriptor public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor { get { return global::Grpc.Testing.ServicesReflection.Descriptor.Services[1]; } } /// Base class for server-side implementations of WorkerService public abstract partial class WorkerServiceBase { /// /// Start server with specified workload. /// First request sent specifies the ServerConfig followed by ServerStatus /// response. After that, a "Mark" can be sent anytime to request the latest /// stats. Closing the stream will initiate shutdown of the test server /// and once the shutdown has finished, the OK status is sent to terminate /// this RPC. /// /// Used for reading requests from the client. /// Used for sending responses back to the client. /// The context of the server-side call handler being invoked. /// A task indicating completion of the handler. public virtual global::System.Threading.Tasks.Task RunServer(grpc::IAsyncStreamReader requestStream, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } /// /// Start client with specified workload. /// First request sent specifies the ClientConfig followed by ClientStatus /// response. After that, a "Mark" can be sent anytime to request the latest /// stats. Closing the stream will initiate shutdown of the test client /// and once the shutdown has finished, the OK status is sent to terminate /// this RPC. /// /// Used for reading requests from the client. /// Used for sending responses back to the client. /// The context of the server-side call handler being invoked. /// A task indicating completion of the handler. public virtual global::System.Threading.Tasks.Task RunClient(grpc::IAsyncStreamReader requestStream, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } /// /// Just return the core count - unary call /// /// The request received from the client. /// The context of the server-side call handler being invoked. /// The response to send back to the client (wrapped by a task). public virtual global::System.Threading.Tasks.Task CoreCount(global::Grpc.Testing.CoreRequest request, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } /// /// Quit this worker /// /// The request received from the client. /// The context of the server-side call handler being invoked. /// The response to send back to the client (wrapped by a task). public virtual global::System.Threading.Tasks.Task QuitWorker(global::Grpc.Testing.Void request, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } } /// Client for WorkerService public partial class WorkerServiceClient : grpc::ClientBase { /// Creates a new client for WorkerService /// The channel to use to make remote calls. public WorkerServiceClient(grpc::Channel channel) : base(channel) { } /// Creates a new client for WorkerService that uses a custom CallInvoker. /// The callInvoker to use to make remote calls. public WorkerServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker) { } /// Protected parameterless constructor to allow creation of test doubles. protected WorkerServiceClient() : base() { } /// Protected constructor to allow creation of configured clients. /// The client configuration. protected WorkerServiceClient(ClientBaseConfiguration configuration) : base(configuration) { } /// /// Start server with specified workload. /// First request sent specifies the ServerConfig followed by ServerStatus /// response. After that, a "Mark" can be sent anytime to request the latest /// stats. Closing the stream will initiate shutdown of the test server /// and once the shutdown has finished, the OK status is sent to terminate /// this RPC. /// /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncDuplexStreamingCall RunServer(grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return RunServer(new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// Start server with specified workload. /// First request sent specifies the ServerConfig followed by ServerStatus /// response. After that, a "Mark" can be sent anytime to request the latest /// stats. Closing the stream will initiate shutdown of the test server /// and once the shutdown has finished, the OK status is sent to terminate /// this RPC. /// /// The options for the call. /// The call object. public virtual grpc::AsyncDuplexStreamingCall RunServer(grpc::CallOptions options) { return CallInvoker.AsyncDuplexStreamingCall(__Method_RunServer, null, options); } /// /// Start client with specified workload. /// First request sent specifies the ClientConfig followed by ClientStatus /// response. After that, a "Mark" can be sent anytime to request the latest /// stats. Closing the stream will initiate shutdown of the test client /// and once the shutdown has finished, the OK status is sent to terminate /// this RPC. /// /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncDuplexStreamingCall RunClient(grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return RunClient(new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// Start client with specified workload. /// First request sent specifies the ClientConfig followed by ClientStatus /// response. After that, a "Mark" can be sent anytime to request the latest /// stats. Closing the stream will initiate shutdown of the test client /// and once the shutdown has finished, the OK status is sent to terminate /// this RPC. /// /// The options for the call. /// The call object. public virtual grpc::AsyncDuplexStreamingCall RunClient(grpc::CallOptions options) { return CallInvoker.AsyncDuplexStreamingCall(__Method_RunClient, null, options); } /// /// Just return the core count - unary call /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The response received from the server. public virtual global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return CoreCount(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// Just return the core count - unary call /// /// The request to send to the server. /// The options for the call. /// The response received from the server. public virtual global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, grpc::CallOptions options) { return CallInvoker.BlockingUnaryCall(__Method_CoreCount, null, options, request); } /// /// Just return the core count - unary call /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncUnaryCall CoreCountAsync(global::Grpc.Testing.CoreRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return CoreCountAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// Just return the core count - unary call /// /// The request to send to the server. /// The options for the call. /// The call object. public virtual grpc::AsyncUnaryCall CoreCountAsync(global::Grpc.Testing.CoreRequest request, grpc::CallOptions options) { return CallInvoker.AsyncUnaryCall(__Method_CoreCount, null, options, request); } /// /// Quit this worker /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The response received from the server. public virtual global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return QuitWorker(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// Quit this worker /// /// The request to send to the server. /// The options for the call. /// The response received from the server. public virtual global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, grpc::CallOptions options) { return CallInvoker.BlockingUnaryCall(__Method_QuitWorker, null, options, request); } /// /// Quit this worker /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncUnaryCall QuitWorkerAsync(global::Grpc.Testing.Void request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return QuitWorkerAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// Quit this worker /// /// The request to send to the server. /// The options for the call. /// The call object. public virtual grpc::AsyncUnaryCall QuitWorkerAsync(global::Grpc.Testing.Void request, grpc::CallOptions options) { return CallInvoker.AsyncUnaryCall(__Method_QuitWorker, null, options, request); } /// Creates a new instance of client from given ClientBaseConfiguration. protected override WorkerServiceClient NewInstance(ClientBaseConfiguration configuration) { return new WorkerServiceClient(configuration); } } /// Creates service definition that can be registered with a server /// An object implementing the server-side handling logic. public static grpc::ServerServiceDefinition BindService(WorkerServiceBase serviceImpl) { return grpc::ServerServiceDefinition.CreateBuilder() .AddMethod(__Method_RunServer, serviceImpl.RunServer) .AddMethod(__Method_RunClient, serviceImpl.RunClient) .AddMethod(__Method_CoreCount, serviceImpl.CoreCount) .AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker).Build(); } } } #endregion grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/Settings.StyleCop000066400000000000000000000006671310511640000245160ustar00rootroot00000000000000 Empty.cs Control.cs Messages.cs Payloads.cs Stats.cs False grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs000066400000000000000000000126461310511640000253400ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using Google.Protobuf; using Grpc.Core; using Grpc.Core.Utils; using Grpc.Testing; using NUnit.Framework; namespace Grpc.IntegrationTesting { /// /// Test SSL credentials where server authenticates client /// and client authenticates the server. /// public class SslCredentialsTest { const string Host = "localhost"; Server server; Channel channel; TestService.TestServiceClient client; [TestFixtureSetUp] public void Init() { var rootCert = File.ReadAllText(TestCredentials.ClientCertAuthorityPath); var keyCertPair = new KeyCertificatePair( File.ReadAllText(TestCredentials.ServerCertChainPath), File.ReadAllText(TestCredentials.ServerPrivateKeyPath)); var serverCredentials = new SslServerCredentials(new[] { keyCertPair }, rootCert, true); var clientCredentials = new SslCredentials(rootCert, keyCertPair); // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) { Services = { TestService.BindService(new SslCredentialsTestServiceImpl()) }, Ports = { { Host, ServerPort.PickUnused, serverCredentials } } }; server.Start(); var options = new List { new ChannelOption(ChannelOptions.SslTargetNameOverride, TestCredentials.DefaultHostOverride) }; channel = new Channel(Host, server.Ports.Single().BoundPort, clientCredentials, options); client = new TestService.TestServiceClient(channel); } [TestFixtureTearDown] public void Cleanup() { channel.ShutdownAsync().Wait(); server.ShutdownAsync().Wait(); } [Test] public void AuthenticatedClientAndServer() { var response = client.UnaryCall(new SimpleRequest { ResponseSize = 10 }); Assert.AreEqual(10, response.Payload.Body.Length); } [Test] public async Task AuthContextIsPopulated() { var call = client.StreamingInputCall(); await call.RequestStream.CompleteAsync(); var response = await call.ResponseAsync; Assert.AreEqual(12345, response.AggregatedPayloadSize); } private class SslCredentialsTestServiceImpl : TestService.TestServiceBase { public override async Task UnaryCall(SimpleRequest request, ServerCallContext context) { return new SimpleResponse { Payload = CreateZerosPayload(request.ResponseSize) }; } public override async Task StreamingInputCall(IAsyncStreamReader requestStream, ServerCallContext context) { var authContext = context.AuthContext; await requestStream.ForEachAsync(async request => {}); Assert.IsTrue(authContext.IsPeerAuthenticated); Assert.AreEqual("x509_subject_alternative_name", authContext.PeerIdentityPropertyName); Assert.IsTrue(authContext.PeerIdentity.Count() > 0); Assert.AreEqual("ssl", authContext.FindPropertiesByName("transport_security_type").First().Value); return new StreamingInputCallResponse { AggregatedPayloadSize = 12345 }; } private static Payload CreateZerosPayload(int size) { return new Payload { Body = ByteString.CopyFrom(new byte[size]) }; } } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/Stats.cs000066400000000000000000001045031310511640000226510ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: src/proto/grpc/testing/stats.proto #pragma warning disable 1591, 0612, 3021 #region Designer generated code using pb = global::Google.Protobuf; using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; namespace Grpc.Testing { /// Holder for reflection information generated from src/proto/grpc/testing/stats.proto public static partial class StatsReflection { #region Descriptor /// File descriptor for src/proto/grpc/testing/stats.proto public static pbr::FileDescriptor Descriptor { get { return descriptor; } } private static pbr::FileDescriptor descriptor; static StatsReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "CiJzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL3N0YXRzLnByb3RvEgxncnBjLnRl", "c3RpbmciegoLU2VydmVyU3RhdHMSFAoMdGltZV9lbGFwc2VkGAEgASgBEhEK", "CXRpbWVfdXNlchgCIAEoARITCgt0aW1lX3N5c3RlbRgDIAEoARIWCg50b3Rh", "bF9jcHVfdGltZRgEIAEoBBIVCg1pZGxlX2NwdV90aW1lGAUgASgEIjsKD0hp", "c3RvZ3JhbVBhcmFtcxISCgpyZXNvbHV0aW9uGAEgASgBEhQKDG1heF9wb3Nz", "aWJsZRgCIAEoASJ3Cg1IaXN0b2dyYW1EYXRhEg4KBmJ1Y2tldBgBIAMoDRIQ", "CghtaW5fc2VlbhgCIAEoARIQCghtYXhfc2VlbhgDIAEoARILCgNzdW0YBCAB", "KAESFgoOc3VtX29mX3NxdWFyZXMYBSABKAESDQoFY291bnQYBiABKAEiOAoS", "UmVxdWVzdFJlc3VsdENvdW50EhMKC3N0YXR1c19jb2RlGAEgASgFEg0KBWNv", "dW50GAIgASgDIrYBCgtDbGllbnRTdGF0cxIuCglsYXRlbmNpZXMYASABKAsy", "Gy5ncnBjLnRlc3RpbmcuSGlzdG9ncmFtRGF0YRIUCgx0aW1lX2VsYXBzZWQY", "AiABKAESEQoJdGltZV91c2VyGAMgASgBEhMKC3RpbWVfc3lzdGVtGAQgASgB", "EjkKD3JlcXVlc3RfcmVzdWx0cxgFIAMoCzIgLmdycGMudGVzdGluZy5SZXF1", "ZXN0UmVzdWx0Q291bnRiBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerStats), global::Grpc.Testing.ServerStats.Parser, new[]{ "TimeElapsed", "TimeUser", "TimeSystem", "TotalCpuTime", "IdleCpuTime" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.HistogramParams), global::Grpc.Testing.HistogramParams.Parser, new[]{ "Resolution", "MaxPossible" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.HistogramData), global::Grpc.Testing.HistogramData.Parser, new[]{ "Bucket", "MinSeen", "MaxSeen", "Sum", "SumOfSquares", "Count" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.RequestResultCount), global::Grpc.Testing.RequestResultCount.Parser, new[]{ "StatusCode", "Count" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientStats), global::Grpc.Testing.ClientStats.Parser, new[]{ "Latencies", "TimeElapsed", "TimeUser", "TimeSystem", "RequestResults" }, null, null, null) })); } #endregion } #region Messages public sealed partial class ServerStats : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ServerStats()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.StatsReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServerStats() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServerStats(ServerStats other) : this() { timeElapsed_ = other.timeElapsed_; timeUser_ = other.timeUser_; timeSystem_ = other.timeSystem_; totalCpuTime_ = other.totalCpuTime_; idleCpuTime_ = other.idleCpuTime_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServerStats Clone() { return new ServerStats(this); } /// Field number for the "time_elapsed" field. public const int TimeElapsedFieldNumber = 1; private double timeElapsed_; /// /// wall clock time change in seconds since last reset /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double TimeElapsed { get { return timeElapsed_; } set { timeElapsed_ = value; } } /// Field number for the "time_user" field. public const int TimeUserFieldNumber = 2; private double timeUser_; /// /// change in user time (in seconds) used by the server since last reset /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double TimeUser { get { return timeUser_; } set { timeUser_ = value; } } /// Field number for the "time_system" field. public const int TimeSystemFieldNumber = 3; private double timeSystem_; /// /// change in server time (in seconds) used by the server process and all /// threads since last reset /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double TimeSystem { get { return timeSystem_; } set { timeSystem_ = value; } } /// Field number for the "total_cpu_time" field. public const int TotalCpuTimeFieldNumber = 4; private ulong totalCpuTime_; /// /// change in total cpu time of the server (data from proc/stat) /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ulong TotalCpuTime { get { return totalCpuTime_; } set { totalCpuTime_ = value; } } /// Field number for the "idle_cpu_time" field. public const int IdleCpuTimeFieldNumber = 5; private ulong idleCpuTime_; /// /// change in idle time of the server (data from proc/stat) /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ulong IdleCpuTime { get { return idleCpuTime_; } set { idleCpuTime_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ServerStats); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ServerStats other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (TimeElapsed != other.TimeElapsed) return false; if (TimeUser != other.TimeUser) return false; if (TimeSystem != other.TimeSystem) return false; if (TotalCpuTime != other.TotalCpuTime) return false; if (IdleCpuTime != other.IdleCpuTime) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (TimeElapsed != 0D) hash ^= TimeElapsed.GetHashCode(); if (TimeUser != 0D) hash ^= TimeUser.GetHashCode(); if (TimeSystem != 0D) hash ^= TimeSystem.GetHashCode(); if (TotalCpuTime != 0UL) hash ^= TotalCpuTime.GetHashCode(); if (IdleCpuTime != 0UL) hash ^= IdleCpuTime.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (TimeElapsed != 0D) { output.WriteRawTag(9); output.WriteDouble(TimeElapsed); } if (TimeUser != 0D) { output.WriteRawTag(17); output.WriteDouble(TimeUser); } if (TimeSystem != 0D) { output.WriteRawTag(25); output.WriteDouble(TimeSystem); } if (TotalCpuTime != 0UL) { output.WriteRawTag(32); output.WriteUInt64(TotalCpuTime); } if (IdleCpuTime != 0UL) { output.WriteRawTag(40); output.WriteUInt64(IdleCpuTime); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (TimeElapsed != 0D) { size += 1 + 8; } if (TimeUser != 0D) { size += 1 + 8; } if (TimeSystem != 0D) { size += 1 + 8; } if (TotalCpuTime != 0UL) { size += 1 + pb::CodedOutputStream.ComputeUInt64Size(TotalCpuTime); } if (IdleCpuTime != 0UL) { size += 1 + pb::CodedOutputStream.ComputeUInt64Size(IdleCpuTime); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ServerStats other) { if (other == null) { return; } if (other.TimeElapsed != 0D) { TimeElapsed = other.TimeElapsed; } if (other.TimeUser != 0D) { TimeUser = other.TimeUser; } if (other.TimeSystem != 0D) { TimeSystem = other.TimeSystem; } if (other.TotalCpuTime != 0UL) { TotalCpuTime = other.TotalCpuTime; } if (other.IdleCpuTime != 0UL) { IdleCpuTime = other.IdleCpuTime; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 9: { TimeElapsed = input.ReadDouble(); break; } case 17: { TimeUser = input.ReadDouble(); break; } case 25: { TimeSystem = input.ReadDouble(); break; } case 32: { TotalCpuTime = input.ReadUInt64(); break; } case 40: { IdleCpuTime = input.ReadUInt64(); break; } } } } } /// /// Histogram params based on grpc/support/histogram.c /// public sealed partial class HistogramParams : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new HistogramParams()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.StatsReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public HistogramParams() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public HistogramParams(HistogramParams other) : this() { resolution_ = other.resolution_; maxPossible_ = other.maxPossible_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public HistogramParams Clone() { return new HistogramParams(this); } /// Field number for the "resolution" field. public const int ResolutionFieldNumber = 1; private double resolution_; /// /// first bucket is [0, 1 + resolution) /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double Resolution { get { return resolution_; } set { resolution_ = value; } } /// Field number for the "max_possible" field. public const int MaxPossibleFieldNumber = 2; private double maxPossible_; /// /// use enough buckets to allow this value /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double MaxPossible { get { return maxPossible_; } set { maxPossible_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as HistogramParams); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(HistogramParams other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Resolution != other.Resolution) return false; if (MaxPossible != other.MaxPossible) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Resolution != 0D) hash ^= Resolution.GetHashCode(); if (MaxPossible != 0D) hash ^= MaxPossible.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Resolution != 0D) { output.WriteRawTag(9); output.WriteDouble(Resolution); } if (MaxPossible != 0D) { output.WriteRawTag(17); output.WriteDouble(MaxPossible); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Resolution != 0D) { size += 1 + 8; } if (MaxPossible != 0D) { size += 1 + 8; } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(HistogramParams other) { if (other == null) { return; } if (other.Resolution != 0D) { Resolution = other.Resolution; } if (other.MaxPossible != 0D) { MaxPossible = other.MaxPossible; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 9: { Resolution = input.ReadDouble(); break; } case 17: { MaxPossible = input.ReadDouble(); break; } } } } } /// /// Histogram data based on grpc/support/histogram.c /// public sealed partial class HistogramData : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new HistogramData()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.StatsReflection.Descriptor.MessageTypes[2]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public HistogramData() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public HistogramData(HistogramData other) : this() { bucket_ = other.bucket_.Clone(); minSeen_ = other.minSeen_; maxSeen_ = other.maxSeen_; sum_ = other.sum_; sumOfSquares_ = other.sumOfSquares_; count_ = other.count_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public HistogramData Clone() { return new HistogramData(this); } /// Field number for the "bucket" field. public const int BucketFieldNumber = 1; private static readonly pb::FieldCodec _repeated_bucket_codec = pb::FieldCodec.ForUInt32(10); private readonly pbc::RepeatedField bucket_ = new pbc::RepeatedField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::RepeatedField Bucket { get { return bucket_; } } /// Field number for the "min_seen" field. public const int MinSeenFieldNumber = 2; private double minSeen_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double MinSeen { get { return minSeen_; } set { minSeen_ = value; } } /// Field number for the "max_seen" field. public const int MaxSeenFieldNumber = 3; private double maxSeen_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double MaxSeen { get { return maxSeen_; } set { maxSeen_ = value; } } /// Field number for the "sum" field. public const int SumFieldNumber = 4; private double sum_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double Sum { get { return sum_; } set { sum_ = value; } } /// Field number for the "sum_of_squares" field. public const int SumOfSquaresFieldNumber = 5; private double sumOfSquares_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double SumOfSquares { get { return sumOfSquares_; } set { sumOfSquares_ = value; } } /// Field number for the "count" field. public const int CountFieldNumber = 6; private double count_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double Count { get { return count_; } set { count_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as HistogramData); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(HistogramData other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if(!bucket_.Equals(other.bucket_)) return false; if (MinSeen != other.MinSeen) return false; if (MaxSeen != other.MaxSeen) return false; if (Sum != other.Sum) return false; if (SumOfSquares != other.SumOfSquares) return false; if (Count != other.Count) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; hash ^= bucket_.GetHashCode(); if (MinSeen != 0D) hash ^= MinSeen.GetHashCode(); if (MaxSeen != 0D) hash ^= MaxSeen.GetHashCode(); if (Sum != 0D) hash ^= Sum.GetHashCode(); if (SumOfSquares != 0D) hash ^= SumOfSquares.GetHashCode(); if (Count != 0D) hash ^= Count.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { bucket_.WriteTo(output, _repeated_bucket_codec); if (MinSeen != 0D) { output.WriteRawTag(17); output.WriteDouble(MinSeen); } if (MaxSeen != 0D) { output.WriteRawTag(25); output.WriteDouble(MaxSeen); } if (Sum != 0D) { output.WriteRawTag(33); output.WriteDouble(Sum); } if (SumOfSquares != 0D) { output.WriteRawTag(41); output.WriteDouble(SumOfSquares); } if (Count != 0D) { output.WriteRawTag(49); output.WriteDouble(Count); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; size += bucket_.CalculateSize(_repeated_bucket_codec); if (MinSeen != 0D) { size += 1 + 8; } if (MaxSeen != 0D) { size += 1 + 8; } if (Sum != 0D) { size += 1 + 8; } if (SumOfSquares != 0D) { size += 1 + 8; } if (Count != 0D) { size += 1 + 8; } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(HistogramData other) { if (other == null) { return; } bucket_.Add(other.bucket_); if (other.MinSeen != 0D) { MinSeen = other.MinSeen; } if (other.MaxSeen != 0D) { MaxSeen = other.MaxSeen; } if (other.Sum != 0D) { Sum = other.Sum; } if (other.SumOfSquares != 0D) { SumOfSquares = other.SumOfSquares; } if (other.Count != 0D) { Count = other.Count; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: case 8: { bucket_.AddEntriesFrom(input, _repeated_bucket_codec); break; } case 17: { MinSeen = input.ReadDouble(); break; } case 25: { MaxSeen = input.ReadDouble(); break; } case 33: { Sum = input.ReadDouble(); break; } case 41: { SumOfSquares = input.ReadDouble(); break; } case 49: { Count = input.ReadDouble(); break; } } } } } public sealed partial class RequestResultCount : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new RequestResultCount()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.StatsReflection.Descriptor.MessageTypes[3]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public RequestResultCount() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public RequestResultCount(RequestResultCount other) : this() { statusCode_ = other.statusCode_; count_ = other.count_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public RequestResultCount Clone() { return new RequestResultCount(this); } /// Field number for the "status_code" field. public const int StatusCodeFieldNumber = 1; private int statusCode_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int StatusCode { get { return statusCode_; } set { statusCode_ = value; } } /// Field number for the "count" field. public const int CountFieldNumber = 2; private long count_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public long Count { get { return count_; } set { count_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as RequestResultCount); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(RequestResultCount other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (StatusCode != other.StatusCode) return false; if (Count != other.Count) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (StatusCode != 0) hash ^= StatusCode.GetHashCode(); if (Count != 0L) hash ^= Count.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (StatusCode != 0) { output.WriteRawTag(8); output.WriteInt32(StatusCode); } if (Count != 0L) { output.WriteRawTag(16); output.WriteInt64(Count); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (StatusCode != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(StatusCode); } if (Count != 0L) { size += 1 + pb::CodedOutputStream.ComputeInt64Size(Count); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(RequestResultCount other) { if (other == null) { return; } if (other.StatusCode != 0) { StatusCode = other.StatusCode; } if (other.Count != 0L) { Count = other.Count; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { StatusCode = input.ReadInt32(); break; } case 16: { Count = input.ReadInt64(); break; } } } } } public sealed partial class ClientStats : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ClientStats()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Testing.StatsReflection.Descriptor.MessageTypes[4]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ClientStats() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ClientStats(ClientStats other) : this() { Latencies = other.latencies_ != null ? other.Latencies.Clone() : null; timeElapsed_ = other.timeElapsed_; timeUser_ = other.timeUser_; timeSystem_ = other.timeSystem_; requestResults_ = other.requestResults_.Clone(); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ClientStats Clone() { return new ClientStats(this); } /// Field number for the "latencies" field. public const int LatenciesFieldNumber = 1; private global::Grpc.Testing.HistogramData latencies_; /// /// Latency histogram. Data points are in nanoseconds. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Testing.HistogramData Latencies { get { return latencies_; } set { latencies_ = value; } } /// Field number for the "time_elapsed" field. public const int TimeElapsedFieldNumber = 2; private double timeElapsed_; /// /// See ServerStats for details. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double TimeElapsed { get { return timeElapsed_; } set { timeElapsed_ = value; } } /// Field number for the "time_user" field. public const int TimeUserFieldNumber = 3; private double timeUser_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double TimeUser { get { return timeUser_; } set { timeUser_ = value; } } /// Field number for the "time_system" field. public const int TimeSystemFieldNumber = 4; private double timeSystem_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double TimeSystem { get { return timeSystem_; } set { timeSystem_ = value; } } /// Field number for the "request_results" field. public const int RequestResultsFieldNumber = 5; private static readonly pb::FieldCodec _repeated_requestResults_codec = pb::FieldCodec.ForMessage(42, global::Grpc.Testing.RequestResultCount.Parser); private readonly pbc::RepeatedField requestResults_ = new pbc::RepeatedField(); /// /// Number of failed requests (one row per status code seen) /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::RepeatedField RequestResults { get { return requestResults_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ClientStats); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ClientStats other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (!object.Equals(Latencies, other.Latencies)) return false; if (TimeElapsed != other.TimeElapsed) return false; if (TimeUser != other.TimeUser) return false; if (TimeSystem != other.TimeSystem) return false; if(!requestResults_.Equals(other.requestResults_)) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (latencies_ != null) hash ^= Latencies.GetHashCode(); if (TimeElapsed != 0D) hash ^= TimeElapsed.GetHashCode(); if (TimeUser != 0D) hash ^= TimeUser.GetHashCode(); if (TimeSystem != 0D) hash ^= TimeSystem.GetHashCode(); hash ^= requestResults_.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (latencies_ != null) { output.WriteRawTag(10); output.WriteMessage(Latencies); } if (TimeElapsed != 0D) { output.WriteRawTag(17); output.WriteDouble(TimeElapsed); } if (TimeUser != 0D) { output.WriteRawTag(25); output.WriteDouble(TimeUser); } if (TimeSystem != 0D) { output.WriteRawTag(33); output.WriteDouble(TimeSystem); } requestResults_.WriteTo(output, _repeated_requestResults_codec); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (latencies_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Latencies); } if (TimeElapsed != 0D) { size += 1 + 8; } if (TimeUser != 0D) { size += 1 + 8; } if (TimeSystem != 0D) { size += 1 + 8; } size += requestResults_.CalculateSize(_repeated_requestResults_codec); return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ClientStats other) { if (other == null) { return; } if (other.latencies_ != null) { if (latencies_ == null) { latencies_ = new global::Grpc.Testing.HistogramData(); } Latencies.MergeFrom(other.Latencies); } if (other.TimeElapsed != 0D) { TimeElapsed = other.TimeElapsed; } if (other.TimeUser != 0D) { TimeUser = other.TimeUser; } if (other.TimeSystem != 0D) { TimeSystem = other.TimeSystem; } requestResults_.Add(other.requestResults_); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { if (latencies_ == null) { latencies_ = new global::Grpc.Testing.HistogramData(); } input.ReadMessage(latencies_); break; } case 17: { TimeElapsed = input.ReadDouble(); break; } case 25: { TimeUser = input.ReadDouble(); break; } case 33: { TimeSystem = input.ReadDouble(); break; } case 42: { requestResults_.AddEntriesFrom(input, _repeated_requestResults_codec); break; } } } } } #endregion } #endregion Designer generated code grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs000066400000000000000000000273121310511640000250370ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using CommandLine; using CommandLine.Text; using Grpc.Core; using Grpc.Core.Logging; using Grpc.Core.Utils; using Grpc.Testing; namespace Grpc.IntegrationTesting { public class StressTestClient { static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); const double SecondsToNanos = 1e9; private class ClientOptions { [Option("server_addresses", Default = "localhost:8080")] public string ServerAddresses { get; set; } [Option("test_cases", Default = "large_unary:100")] public string TestCases { get; set; } [Option("test_duration_secs", Default = -1)] public int TestDurationSecs { get; set; } [Option("num_channels_per_server", Default = 1)] public int NumChannelsPerServer { get; set; } [Option("num_stubs_per_channel", Default = 1)] public int NumStubsPerChannel { get; set; } [Option("metrics_port", Default = 8081)] public int MetricsPort { get; set; } } ClientOptions options; List serverAddresses; Dictionary weightedTestCases; WeightedRandomGenerator testCaseGenerator; // cancellation will be emitted once test_duration_secs has elapsed. CancellationTokenSource finishedTokenSource = new CancellationTokenSource(); Histogram histogram = new Histogram(0.01, 60 * SecondsToNanos); private StressTestClient(ClientOptions options, List serverAddresses, Dictionary weightedTestCases) { this.options = options; this.serverAddresses = serverAddresses; this.weightedTestCases = weightedTestCases; this.testCaseGenerator = new WeightedRandomGenerator(this.weightedTestCases); } public static void Run(string[] args) { GrpcEnvironment.SetLogger(new ConsoleLogger()); var parserResult = Parser.Default.ParseArguments(args) .WithNotParsed((x) => Environment.Exit(1)) .WithParsed(options => { GrpcPreconditions.CheckArgument(options.NumChannelsPerServer > 0); GrpcPreconditions.CheckArgument(options.NumStubsPerChannel > 0); var serverAddresses = options.ServerAddresses.Split(','); GrpcPreconditions.CheckArgument(serverAddresses.Length > 0, "You need to provide at least one server address"); var testCases = ParseWeightedTestCases(options.TestCases); GrpcPreconditions.CheckArgument(testCases.Count > 0, "You need to provide at least one test case"); var interopClient = new StressTestClient(options, serverAddresses.ToList(), testCases); interopClient.Run().Wait(); }); } async Task Run() { var metricsServer = new Server() { Services = { MetricsService.BindService(new MetricsServiceImpl(histogram)) }, Ports = { { "[::]", options.MetricsPort, ServerCredentials.Insecure } } }; metricsServer.Start(); if (options.TestDurationSecs >= 0) { finishedTokenSource.CancelAfter(TimeSpan.FromSeconds(options.TestDurationSecs)); } var tasks = new List(); var channels = new List(); foreach (var serverAddress in serverAddresses) { for (int i = 0; i < options.NumChannelsPerServer; i++) { var channel = new Channel(serverAddress, ChannelCredentials.Insecure); channels.Add(channel); for (int j = 0; j < options.NumStubsPerChannel; j++) { var client = new TestService.TestServiceClient(channel); var task = Task.Factory.StartNew(() => RunBodyAsync(client).GetAwaiter().GetResult(), TaskCreationOptions.LongRunning); tasks.Add(task); } } } await Task.WhenAll(tasks); foreach (var channel in channels) { await channel.ShutdownAsync(); } await metricsServer.ShutdownAsync(); } async Task RunBodyAsync(TestService.TestServiceClient client) { Logger.Info("Starting stress test client thread."); while (!finishedTokenSource.Token.IsCancellationRequested) { var testCase = testCaseGenerator.GetNext(); var stopwatch = Stopwatch.StartNew(); await RunTestCaseAsync(client, testCase); stopwatch.Stop(); histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos); } Logger.Info("Stress test client thread finished."); } async Task RunTestCaseAsync(TestService.TestServiceClient client, string testCase) { switch (testCase) { case "empty_unary": InteropClient.RunEmptyUnary(client); break; case "large_unary": InteropClient.RunLargeUnary(client); break; case "client_streaming": await InteropClient.RunClientStreamingAsync(client); break; case "server_streaming": await InteropClient.RunServerStreamingAsync(client); break; case "ping_pong": await InteropClient.RunPingPongAsync(client); break; case "empty_stream": await InteropClient.RunEmptyStreamAsync(client); break; case "cancel_after_begin": await InteropClient.RunCancelAfterBeginAsync(client); break; case "cancel_after_first_response": await InteropClient.RunCancelAfterFirstResponseAsync(client); break; case "timeout_on_sleeping_server": await InteropClient.RunTimeoutOnSleepingServerAsync(client); break; case "custom_metadata": await InteropClient.RunCustomMetadataAsync(client); break; case "status_code_and_message": await InteropClient.RunStatusCodeAndMessageAsync(client); break; default: throw new ArgumentException("Unsupported test case " + testCase); } } static Dictionary ParseWeightedTestCases(string weightedTestCases) { var result = new Dictionary(); foreach (var weightedTestCase in weightedTestCases.Split(',')) { var parts = weightedTestCase.Split(new char[] {':'}, 2); GrpcPreconditions.CheckArgument(parts.Length == 2, "Malformed test_cases option."); result.Add(parts[0], int.Parse(parts[1])); } return result; } class WeightedRandomGenerator { readonly Random random = new Random(); readonly List> cumulativeSums; readonly int weightSum; public WeightedRandomGenerator(Dictionary weightedItems) { cumulativeSums = new List>(); weightSum = 0; foreach (var entry in weightedItems) { weightSum += entry.Value; cumulativeSums.Add(Tuple.Create(weightSum, entry.Key)); } } public string GetNext() { int rand = random.Next(weightSum); foreach (var entry in cumulativeSums) { if (rand < entry.Item1) { return entry.Item2; } } throw new InvalidOperationException("GetNext() failed."); } } class MetricsServiceImpl : MetricsService.MetricsServiceBase { const string GaugeName = "csharp_overall_qps"; readonly Histogram histogram; readonly WallClockStopwatch wallClockStopwatch = new WallClockStopwatch(); public MetricsServiceImpl(Histogram histogram) { this.histogram = histogram; } public override Task GetGauge(GaugeRequest request, ServerCallContext context) { if (request.Name == GaugeName) { long qps = GetQpsAndReset(); return Task.FromResult(new GaugeResponse { Name = GaugeName, LongValue = qps }); } throw new RpcException(new Status(StatusCode.InvalidArgument, "Gauge does not exist")); } public override async Task GetAllGauges(EmptyMessage request, IServerStreamWriter responseStream, ServerCallContext context) { long qps = GetQpsAndReset(); var response = new GaugeResponse { Name = GaugeName, LongValue = qps }; await responseStream.WriteAsync(response); } long GetQpsAndReset() { var snapshot = histogram.GetSnapshot(true); var elapsedSnapshot = wallClockStopwatch.GetElapsedSnapshot(true); return (long) (snapshot.Count / elapsedSnapshot.TotalSeconds); } } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/Test.cs000066400000000000000000000057751310511640000225050ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: src/proto/grpc/testing/test.proto #pragma warning disable 1591, 0612, 3021 #region Designer generated code using pb = global::Google.Protobuf; using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; namespace Grpc.Testing { /// Holder for reflection information generated from src/proto/grpc/testing/test.proto public static partial class TestReflection { #region Descriptor /// File descriptor for src/proto/grpc/testing/test.proto public static pbr::FileDescriptor Descriptor { get { return descriptor; } } private static pbr::FileDescriptor descriptor; static TestReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "CiFzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL3Rlc3QucHJvdG8SDGdycGMudGVz", "dGluZxoic3JjL3Byb3RvL2dycGMvdGVzdGluZy9lbXB0eS5wcm90bxolc3Jj", "L3Byb3RvL2dycGMvdGVzdGluZy9tZXNzYWdlcy5wcm90bzLLBQoLVGVzdFNl", "cnZpY2USNQoJRW1wdHlDYWxsEhMuZ3JwYy50ZXN0aW5nLkVtcHR5GhMuZ3Jw", "Yy50ZXN0aW5nLkVtcHR5EkYKCVVuYXJ5Q2FsbBIbLmdycGMudGVzdGluZy5T", "aW1wbGVSZXF1ZXN0GhwuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlc3BvbnNlEk8K", "EkNhY2hlYWJsZVVuYXJ5Q2FsbBIbLmdycGMudGVzdGluZy5TaW1wbGVSZXF1", "ZXN0GhwuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlc3BvbnNlEmwKE1N0cmVhbWlu", "Z091dHB1dENhbGwSKC5ncnBjLnRlc3RpbmcuU3RyZWFtaW5nT3V0cHV0Q2Fs", "bFJlcXVlc3QaKS5ncnBjLnRlc3RpbmcuU3RyZWFtaW5nT3V0cHV0Q2FsbFJl", "c3BvbnNlMAESaQoSU3RyZWFtaW5nSW5wdXRDYWxsEicuZ3JwYy50ZXN0aW5n", "LlN0cmVhbWluZ0lucHV0Q2FsbFJlcXVlc3QaKC5ncnBjLnRlc3RpbmcuU3Ry", "ZWFtaW5nSW5wdXRDYWxsUmVzcG9uc2UoARJpCg5GdWxsRHVwbGV4Q2FsbBIo", "LmdycGMudGVzdGluZy5TdHJlYW1pbmdPdXRwdXRDYWxsUmVxdWVzdBopLmdy", "cGMudGVzdGluZy5TdHJlYW1pbmdPdXRwdXRDYWxsUmVzcG9uc2UoATABEmkK", "DkhhbGZEdXBsZXhDYWxsEiguZ3JwYy50ZXN0aW5nLlN0cmVhbWluZ091dHB1", "dENhbGxSZXF1ZXN0GikuZ3JwYy50ZXN0aW5nLlN0cmVhbWluZ091dHB1dENh", "bGxSZXNwb25zZSgBMAESPQoRVW5pbXBsZW1lbnRlZENhbGwSEy5ncnBjLnRl", "c3RpbmcuRW1wdHkaEy5ncnBjLnRlc3RpbmcuRW1wdHkyVQoUVW5pbXBsZW1l", "bnRlZFNlcnZpY2USPQoRVW5pbXBsZW1lbnRlZENhbGwSEy5ncnBjLnRlc3Rp", "bmcuRW1wdHkaEy5ncnBjLnRlc3RpbmcuRW1wdHkyiQEKEFJlY29ubmVjdFNl", "cnZpY2USOwoFU3RhcnQSHS5ncnBjLnRlc3RpbmcuUmVjb25uZWN0UGFyYW1z", "GhMuZ3JwYy50ZXN0aW5nLkVtcHR5EjgKBFN0b3ASEy5ncnBjLnRlc3Rpbmcu", "RW1wdHkaGy5ncnBjLnRlc3RpbmcuUmVjb25uZWN0SW5mb2IGcHJvdG8z")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Grpc.Testing.EmptyReflection.Descriptor, global::Grpc.Testing.MessagesReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(null, null)); } #endregion } } #endregion Designer generated code grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs000066400000000000000000000064011310511640000246460ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Text.RegularExpressions; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Utils; using NUnit.Framework; namespace Grpc.IntegrationTesting { /// /// SSL Credentials for testing. /// public static class TestCredentials { public const string DefaultHostOverride = "foo.test.google.fr"; public static string ClientCertAuthorityPath { get { return GetPath("data/ca.pem"); } } public static string ServerCertChainPath { get { return GetPath("data/server1.pem"); } } public static string ServerPrivateKeyPath { get { return GetPath("data/server1.key"); } } public static SslCredentials CreateSslCredentials() { return new SslCredentials(File.ReadAllText(ClientCertAuthorityPath)); } public static SslServerCredentials CreateSslServerCredentials() { var keyCertPair = new KeyCertificatePair( File.ReadAllText(ServerCertChainPath), File.ReadAllText(ServerPrivateKeyPath)); return new SslServerCredentials(new[] { keyCertPair }); } private static string GetPath(string relativePath) { var assemblyDir = Path.GetDirectoryName(typeof(TestCredentials).GetTypeInfo().Assembly.Location); return Path.Combine(assemblyDir, relativePath); } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs000066400000000000000000001411061310511640000233060ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: src/proto/grpc/testing/test.proto // Original file comments: // Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // An integration test service that covers all the method signature permutations // of unary/streaming requests/responses. // #region Designer generated code using System; using System.Threading; using System.Threading.Tasks; using grpc = global::Grpc.Core; namespace Grpc.Testing { /// /// A simple service to test the various types of RPCs and experiment with /// performance with various types of payload. /// public static partial class TestService { static readonly string __ServiceName = "grpc.testing.TestService"; static readonly grpc::Marshaller __Marshaller_Empty = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.Empty.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_SimpleRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleRequest.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_SimpleResponse = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleResponse.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_StreamingOutputCallRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.StreamingOutputCallRequest.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_StreamingOutputCallResponse = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.StreamingOutputCallResponse.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_StreamingInputCallRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.StreamingInputCallRequest.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_StreamingInputCallResponse = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.StreamingInputCallResponse.Parser.ParseFrom); static readonly grpc::Method __Method_EmptyCall = new grpc::Method( grpc::MethodType.Unary, __ServiceName, "EmptyCall", __Marshaller_Empty, __Marshaller_Empty); static readonly grpc::Method __Method_UnaryCall = new grpc::Method( grpc::MethodType.Unary, __ServiceName, "UnaryCall", __Marshaller_SimpleRequest, __Marshaller_SimpleResponse); static readonly grpc::Method __Method_CacheableUnaryCall = new grpc::Method( grpc::MethodType.Unary, __ServiceName, "CacheableUnaryCall", __Marshaller_SimpleRequest, __Marshaller_SimpleResponse); static readonly grpc::Method __Method_StreamingOutputCall = new grpc::Method( grpc::MethodType.ServerStreaming, __ServiceName, "StreamingOutputCall", __Marshaller_StreamingOutputCallRequest, __Marshaller_StreamingOutputCallResponse); static readonly grpc::Method __Method_StreamingInputCall = new grpc::Method( grpc::MethodType.ClientStreaming, __ServiceName, "StreamingInputCall", __Marshaller_StreamingInputCallRequest, __Marshaller_StreamingInputCallResponse); static readonly grpc::Method __Method_FullDuplexCall = new grpc::Method( grpc::MethodType.DuplexStreaming, __ServiceName, "FullDuplexCall", __Marshaller_StreamingOutputCallRequest, __Marshaller_StreamingOutputCallResponse); static readonly grpc::Method __Method_HalfDuplexCall = new grpc::Method( grpc::MethodType.DuplexStreaming, __ServiceName, "HalfDuplexCall", __Marshaller_StreamingOutputCallRequest, __Marshaller_StreamingOutputCallResponse); static readonly grpc::Method __Method_UnimplementedCall = new grpc::Method( grpc::MethodType.Unary, __ServiceName, "UnimplementedCall", __Marshaller_Empty, __Marshaller_Empty); /// Service descriptor public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor { get { return global::Grpc.Testing.TestReflection.Descriptor.Services[0]; } } /// Base class for server-side implementations of TestService public abstract partial class TestServiceBase { /// /// One empty request followed by one empty response. /// /// The request received from the client. /// The context of the server-side call handler being invoked. /// The response to send back to the client (wrapped by a task). public virtual global::System.Threading.Tasks.Task EmptyCall(global::Grpc.Testing.Empty request, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } /// /// One request followed by one response. /// /// The request received from the client. /// The context of the server-side call handler being invoked. /// The response to send back to the client (wrapped by a task). public virtual global::System.Threading.Tasks.Task UnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } /// /// One request followed by one response. Response has cache control /// headers set such that a caching HTTP proxy (such as GFE) can /// satisfy subsequent requests. /// /// The request received from the client. /// The context of the server-side call handler being invoked. /// The response to send back to the client (wrapped by a task). public virtual global::System.Threading.Tasks.Task CacheableUnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } /// /// One request followed by a sequence of responses (streamed download). /// The server returns the payload with client desired type and sizes. /// /// The request received from the client. /// Used for sending responses back to the client. /// The context of the server-side call handler being invoked. /// A task indicating completion of the handler. public virtual global::System.Threading.Tasks.Task StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } /// /// A sequence of requests followed by one response (streamed upload). /// The server returns the aggregated size of client payload as the result. /// /// Used for reading requests from the client. /// The context of the server-side call handler being invoked. /// The response to send back to the client (wrapped by a task). public virtual global::System.Threading.Tasks.Task StreamingInputCall(grpc::IAsyncStreamReader requestStream, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } /// /// A sequence of requests with each request served by the server immediately. /// As one request could lead to multiple responses, this interface /// demonstrates the idea of full duplexing. /// /// Used for reading requests from the client. /// Used for sending responses back to the client. /// The context of the server-side call handler being invoked. /// A task indicating completion of the handler. public virtual global::System.Threading.Tasks.Task FullDuplexCall(grpc::IAsyncStreamReader requestStream, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } /// /// A sequence of requests followed by a sequence of responses. /// The server buffers all the client requests and then serves them in order. A /// stream of responses are returned to the client when the server starts with /// first request. /// /// Used for reading requests from the client. /// Used for sending responses back to the client. /// The context of the server-side call handler being invoked. /// A task indicating completion of the handler. public virtual global::System.Threading.Tasks.Task HalfDuplexCall(grpc::IAsyncStreamReader requestStream, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } /// /// The test server will not implement this method. It will be used /// to test the behavior when clients call unimplemented methods. /// /// The request received from the client. /// The context of the server-side call handler being invoked. /// The response to send back to the client (wrapped by a task). public virtual global::System.Threading.Tasks.Task UnimplementedCall(global::Grpc.Testing.Empty request, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } } /// Client for TestService public partial class TestServiceClient : grpc::ClientBase { /// Creates a new client for TestService /// The channel to use to make remote calls. public TestServiceClient(grpc::Channel channel) : base(channel) { } /// Creates a new client for TestService that uses a custom CallInvoker. /// The callInvoker to use to make remote calls. public TestServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker) { } /// Protected parameterless constructor to allow creation of test doubles. protected TestServiceClient() : base() { } /// Protected constructor to allow creation of configured clients. /// The client configuration. protected TestServiceClient(ClientBaseConfiguration configuration) : base(configuration) { } /// /// One empty request followed by one empty response. /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The response received from the server. public virtual global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return EmptyCall(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// One empty request followed by one empty response. /// /// The request to send to the server. /// The options for the call. /// The response received from the server. public virtual global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, grpc::CallOptions options) { return CallInvoker.BlockingUnaryCall(__Method_EmptyCall, null, options, request); } /// /// One empty request followed by one empty response. /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncUnaryCall EmptyCallAsync(global::Grpc.Testing.Empty request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return EmptyCallAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// One empty request followed by one empty response. /// /// The request to send to the server. /// The options for the call. /// The call object. public virtual grpc::AsyncUnaryCall EmptyCallAsync(global::Grpc.Testing.Empty request, grpc::CallOptions options) { return CallInvoker.AsyncUnaryCall(__Method_EmptyCall, null, options, request); } /// /// One request followed by one response. /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The response received from the server. public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return UnaryCall(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// One request followed by one response. /// /// The request to send to the server. /// The options for the call. /// The response received from the server. public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::CallOptions options) { return CallInvoker.BlockingUnaryCall(__Method_UnaryCall, null, options, request); } /// /// One request followed by one response. /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncUnaryCall UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return UnaryCallAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// One request followed by one response. /// /// The request to send to the server. /// The options for the call. /// The call object. public virtual grpc::AsyncUnaryCall UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, grpc::CallOptions options) { return CallInvoker.AsyncUnaryCall(__Method_UnaryCall, null, options, request); } /// /// One request followed by one response. Response has cache control /// headers set such that a caching HTTP proxy (such as GFE) can /// satisfy subsequent requests. /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The response received from the server. public virtual global::Grpc.Testing.SimpleResponse CacheableUnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return CacheableUnaryCall(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// One request followed by one response. Response has cache control /// headers set such that a caching HTTP proxy (such as GFE) can /// satisfy subsequent requests. /// /// The request to send to the server. /// The options for the call. /// The response received from the server. public virtual global::Grpc.Testing.SimpleResponse CacheableUnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::CallOptions options) { return CallInvoker.BlockingUnaryCall(__Method_CacheableUnaryCall, null, options, request); } /// /// One request followed by one response. Response has cache control /// headers set such that a caching HTTP proxy (such as GFE) can /// satisfy subsequent requests. /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncUnaryCall CacheableUnaryCallAsync(global::Grpc.Testing.SimpleRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return CacheableUnaryCallAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// One request followed by one response. Response has cache control /// headers set such that a caching HTTP proxy (such as GFE) can /// satisfy subsequent requests. /// /// The request to send to the server. /// The options for the call. /// The call object. public virtual grpc::AsyncUnaryCall CacheableUnaryCallAsync(global::Grpc.Testing.SimpleRequest request, grpc::CallOptions options) { return CallInvoker.AsyncUnaryCall(__Method_CacheableUnaryCall, null, options, request); } /// /// One request followed by a sequence of responses (streamed download). /// The server returns the payload with client desired type and sizes. /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncServerStreamingCall StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return StreamingOutputCall(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// One request followed by a sequence of responses (streamed download). /// The server returns the payload with client desired type and sizes. /// /// The request to send to the server. /// The options for the call. /// The call object. public virtual grpc::AsyncServerStreamingCall StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, grpc::CallOptions options) { return CallInvoker.AsyncServerStreamingCall(__Method_StreamingOutputCall, null, options, request); } /// /// A sequence of requests followed by one response (streamed upload). /// The server returns the aggregated size of client payload as the result. /// /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncClientStreamingCall StreamingInputCall(grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return StreamingInputCall(new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// A sequence of requests followed by one response (streamed upload). /// The server returns the aggregated size of client payload as the result. /// /// The options for the call. /// The call object. public virtual grpc::AsyncClientStreamingCall StreamingInputCall(grpc::CallOptions options) { return CallInvoker.AsyncClientStreamingCall(__Method_StreamingInputCall, null, options); } /// /// A sequence of requests with each request served by the server immediately. /// As one request could lead to multiple responses, this interface /// demonstrates the idea of full duplexing. /// /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncDuplexStreamingCall FullDuplexCall(grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return FullDuplexCall(new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// A sequence of requests with each request served by the server immediately. /// As one request could lead to multiple responses, this interface /// demonstrates the idea of full duplexing. /// /// The options for the call. /// The call object. public virtual grpc::AsyncDuplexStreamingCall FullDuplexCall(grpc::CallOptions options) { return CallInvoker.AsyncDuplexStreamingCall(__Method_FullDuplexCall, null, options); } /// /// A sequence of requests followed by a sequence of responses. /// The server buffers all the client requests and then serves them in order. A /// stream of responses are returned to the client when the server starts with /// first request. /// /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncDuplexStreamingCall HalfDuplexCall(grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return HalfDuplexCall(new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// A sequence of requests followed by a sequence of responses. /// The server buffers all the client requests and then serves them in order. A /// stream of responses are returned to the client when the server starts with /// first request. /// /// The options for the call. /// The call object. public virtual grpc::AsyncDuplexStreamingCall HalfDuplexCall(grpc::CallOptions options) { return CallInvoker.AsyncDuplexStreamingCall(__Method_HalfDuplexCall, null, options); } /// /// The test server will not implement this method. It will be used /// to test the behavior when clients call unimplemented methods. /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The response received from the server. public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return UnimplementedCall(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// The test server will not implement this method. It will be used /// to test the behavior when clients call unimplemented methods. /// /// The request to send to the server. /// The options for the call. /// The response received from the server. public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, grpc::CallOptions options) { return CallInvoker.BlockingUnaryCall(__Method_UnimplementedCall, null, options, request); } /// /// The test server will not implement this method. It will be used /// to test the behavior when clients call unimplemented methods. /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncUnaryCall UnimplementedCallAsync(global::Grpc.Testing.Empty request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return UnimplementedCallAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// The test server will not implement this method. It will be used /// to test the behavior when clients call unimplemented methods. /// /// The request to send to the server. /// The options for the call. /// The call object. public virtual grpc::AsyncUnaryCall UnimplementedCallAsync(global::Grpc.Testing.Empty request, grpc::CallOptions options) { return CallInvoker.AsyncUnaryCall(__Method_UnimplementedCall, null, options, request); } /// Creates a new instance of client from given ClientBaseConfiguration. protected override TestServiceClient NewInstance(ClientBaseConfiguration configuration) { return new TestServiceClient(configuration); } } /// Creates service definition that can be registered with a server /// An object implementing the server-side handling logic. public static grpc::ServerServiceDefinition BindService(TestServiceBase serviceImpl) { return grpc::ServerServiceDefinition.CreateBuilder() .AddMethod(__Method_EmptyCall, serviceImpl.EmptyCall) .AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall) .AddMethod(__Method_CacheableUnaryCall, serviceImpl.CacheableUnaryCall) .AddMethod(__Method_StreamingOutputCall, serviceImpl.StreamingOutputCall) .AddMethod(__Method_StreamingInputCall, serviceImpl.StreamingInputCall) .AddMethod(__Method_FullDuplexCall, serviceImpl.FullDuplexCall) .AddMethod(__Method_HalfDuplexCall, serviceImpl.HalfDuplexCall) .AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build(); } } /// /// A simple service NOT implemented at servers so clients can test for /// that case. /// public static partial class UnimplementedService { static readonly string __ServiceName = "grpc.testing.UnimplementedService"; static readonly grpc::Marshaller __Marshaller_Empty = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.Empty.Parser.ParseFrom); static readonly grpc::Method __Method_UnimplementedCall = new grpc::Method( grpc::MethodType.Unary, __ServiceName, "UnimplementedCall", __Marshaller_Empty, __Marshaller_Empty); /// Service descriptor public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor { get { return global::Grpc.Testing.TestReflection.Descriptor.Services[1]; } } /// Base class for server-side implementations of UnimplementedService public abstract partial class UnimplementedServiceBase { /// /// A call that no server should implement /// /// The request received from the client. /// The context of the server-side call handler being invoked. /// The response to send back to the client (wrapped by a task). public virtual global::System.Threading.Tasks.Task UnimplementedCall(global::Grpc.Testing.Empty request, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } } /// Client for UnimplementedService public partial class UnimplementedServiceClient : grpc::ClientBase { /// Creates a new client for UnimplementedService /// The channel to use to make remote calls. public UnimplementedServiceClient(grpc::Channel channel) : base(channel) { } /// Creates a new client for UnimplementedService that uses a custom CallInvoker. /// The callInvoker to use to make remote calls. public UnimplementedServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker) { } /// Protected parameterless constructor to allow creation of test doubles. protected UnimplementedServiceClient() : base() { } /// Protected constructor to allow creation of configured clients. /// The client configuration. protected UnimplementedServiceClient(ClientBaseConfiguration configuration) : base(configuration) { } /// /// A call that no server should implement /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The response received from the server. public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return UnimplementedCall(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// A call that no server should implement /// /// The request to send to the server. /// The options for the call. /// The response received from the server. public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, grpc::CallOptions options) { return CallInvoker.BlockingUnaryCall(__Method_UnimplementedCall, null, options, request); } /// /// A call that no server should implement /// /// The request to send to the server. /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncUnaryCall UnimplementedCallAsync(global::Grpc.Testing.Empty request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return UnimplementedCallAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// A call that no server should implement /// /// The request to send to the server. /// The options for the call. /// The call object. public virtual grpc::AsyncUnaryCall UnimplementedCallAsync(global::Grpc.Testing.Empty request, grpc::CallOptions options) { return CallInvoker.AsyncUnaryCall(__Method_UnimplementedCall, null, options, request); } /// Creates a new instance of client from given ClientBaseConfiguration. protected override UnimplementedServiceClient NewInstance(ClientBaseConfiguration configuration) { return new UnimplementedServiceClient(configuration); } } /// Creates service definition that can be registered with a server /// An object implementing the server-side handling logic. public static grpc::ServerServiceDefinition BindService(UnimplementedServiceBase serviceImpl) { return grpc::ServerServiceDefinition.CreateBuilder() .AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build(); } } /// /// A service used to control reconnect server. /// public static partial class ReconnectService { static readonly string __ServiceName = "grpc.testing.ReconnectService"; static readonly grpc::Marshaller __Marshaller_ReconnectParams = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ReconnectParams.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_Empty = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.Empty.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_ReconnectInfo = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ReconnectInfo.Parser.ParseFrom); static readonly grpc::Method __Method_Start = new grpc::Method( grpc::MethodType.Unary, __ServiceName, "Start", __Marshaller_ReconnectParams, __Marshaller_Empty); static readonly grpc::Method __Method_Stop = new grpc::Method( grpc::MethodType.Unary, __ServiceName, "Stop", __Marshaller_Empty, __Marshaller_ReconnectInfo); /// Service descriptor public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor { get { return global::Grpc.Testing.TestReflection.Descriptor.Services[2]; } } /// Base class for server-side implementations of ReconnectService public abstract partial class ReconnectServiceBase { public virtual global::System.Threading.Tasks.Task Start(global::Grpc.Testing.ReconnectParams request, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } public virtual global::System.Threading.Tasks.Task Stop(global::Grpc.Testing.Empty request, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } } /// Client for ReconnectService public partial class ReconnectServiceClient : grpc::ClientBase { /// Creates a new client for ReconnectService /// The channel to use to make remote calls. public ReconnectServiceClient(grpc::Channel channel) : base(channel) { } /// Creates a new client for ReconnectService that uses a custom CallInvoker. /// The callInvoker to use to make remote calls. public ReconnectServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker) { } /// Protected parameterless constructor to allow creation of test doubles. protected ReconnectServiceClient() : base() { } /// Protected constructor to allow creation of configured clients. /// The client configuration. protected ReconnectServiceClient(ClientBaseConfiguration configuration) : base(configuration) { } public virtual global::Grpc.Testing.Empty Start(global::Grpc.Testing.ReconnectParams request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return Start(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } public virtual global::Grpc.Testing.Empty Start(global::Grpc.Testing.ReconnectParams request, grpc::CallOptions options) { return CallInvoker.BlockingUnaryCall(__Method_Start, null, options, request); } public virtual grpc::AsyncUnaryCall StartAsync(global::Grpc.Testing.ReconnectParams request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return StartAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } public virtual grpc::AsyncUnaryCall StartAsync(global::Grpc.Testing.ReconnectParams request, grpc::CallOptions options) { return CallInvoker.AsyncUnaryCall(__Method_Start, null, options, request); } public virtual global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return Stop(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } public virtual global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, grpc::CallOptions options) { return CallInvoker.BlockingUnaryCall(__Method_Stop, null, options, request); } public virtual grpc::AsyncUnaryCall StopAsync(global::Grpc.Testing.Empty request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return StopAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); } public virtual grpc::AsyncUnaryCall StopAsync(global::Grpc.Testing.Empty request, grpc::CallOptions options) { return CallInvoker.AsyncUnaryCall(__Method_Stop, null, options, request); } /// Creates a new instance of client from given ClientBaseConfiguration. protected override ReconnectServiceClient NewInstance(ClientBaseConfiguration configuration) { return new ReconnectServiceClient(configuration); } } /// Creates service definition that can be registered with a server /// An object implementing the server-side handling logic. public static grpc::ServerServiceDefinition BindService(ReconnectServiceBase serviceImpl) { return grpc::ServerServiceDefinition.CreateBuilder() .AddMethod(__Method_Start, serviceImpl.Start) .AddMethod(__Method_Stop, serviceImpl.Stop).Build(); } } } #endregion grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs000066400000000000000000000132351310511640000246360ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Google.Protobuf; using Grpc.Core; using Grpc.Core.Utils; namespace Grpc.Testing { /// /// Implementation of TestService server /// public class TestServiceImpl : TestService.TestServiceBase { public override Task EmptyCall(Empty request, ServerCallContext context) { return Task.FromResult(new Empty()); } public override async Task UnaryCall(SimpleRequest request, ServerCallContext context) { await EnsureEchoMetadataAsync(context); EnsureEchoStatus(request.ResponseStatus, context); var response = new SimpleResponse { Payload = CreateZerosPayload(request.ResponseSize) }; return response; } public override async Task StreamingOutputCall(StreamingOutputCallRequest request, IServerStreamWriter responseStream, ServerCallContext context) { await EnsureEchoMetadataAsync(context); EnsureEchoStatus(request.ResponseStatus, context); foreach (var responseParam in request.ResponseParameters) { var response = new StreamingOutputCallResponse { Payload = CreateZerosPayload(responseParam.Size) }; await responseStream.WriteAsync(response); } } public override async Task StreamingInputCall(IAsyncStreamReader requestStream, ServerCallContext context) { await EnsureEchoMetadataAsync(context); int sum = 0; await requestStream.ForEachAsync(async request => { sum += request.Payload.Body.Length; }); return new StreamingInputCallResponse { AggregatedPayloadSize = sum }; } public override async Task FullDuplexCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) { await EnsureEchoMetadataAsync(context); await requestStream.ForEachAsync(async request => { EnsureEchoStatus(request.ResponseStatus, context); foreach (var responseParam in request.ResponseParameters) { var response = new StreamingOutputCallResponse { Payload = CreateZerosPayload(responseParam.Size) }; await responseStream.WriteAsync(response); } }); } public override async Task HalfDuplexCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) { throw new NotImplementedException(); } private static Payload CreateZerosPayload(int size) { return new Payload { Body = ByteString.CopyFrom(new byte[size]) }; } private static async Task EnsureEchoMetadataAsync(ServerCallContext context) { var echoInitialList = context.RequestHeaders.Where((entry) => entry.Key == "x-grpc-test-echo-initial").ToList(); if (echoInitialList.Any()) { var entry = echoInitialList.Single(); await context.WriteResponseHeadersAsync(new Metadata { entry }); } var echoTrailingList = context.RequestHeaders.Where((entry) => entry.Key == "x-grpc-test-echo-trailing-bin").ToList(); if (echoTrailingList.Any()) { context.ResponseTrailers.Add(echoTrailingList.Single()); } } private static void EnsureEchoStatus(EchoStatus responseStatus, ServerCallContext context) { if (responseStatus != null) { var statusCode = (StatusCode)responseStatus.Code; context.Status = new Status(statusCode, responseStatus.Message); } } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/WallClockStopwatch.cs000066400000000000000000000051661310511640000253300ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Google.Protobuf; using Grpc.Core; using Grpc.Core.Utils; using NUnit.Framework; using Grpc.Testing; namespace Grpc.IntegrationTesting { /// /// Snapshottable wall clock stopwatch. /// public class WallClockStopwatch { long startTicks; public WallClockStopwatch() { this.startTicks = DateTime.UtcNow.Ticks; } public TimeSpan GetElapsedSnapshot(bool reset) { var utcNow = DateTime.UtcNow; long oldStartTicks; if (reset) { oldStartTicks = Interlocked.Exchange(ref this.startTicks, utcNow.Ticks); } else { oldStartTicks = this.startTicks; } return utcNow - new DateTime(oldStartTicks, DateTimeKind.Utc); } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs000066400000000000000000000105561310511640000251730ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Google.Protobuf; using Grpc.Core; using Grpc.Core.Utils; using Grpc.IntegrationTesting; namespace Grpc.Testing { /// /// Implementation of WorkerService server /// public class WorkerServiceImpl : WorkerService.WorkerServiceBase { readonly Action stopRequestHandler; public WorkerServiceImpl(Action stopRequestHandler) { this.stopRequestHandler = GrpcPreconditions.CheckNotNull(stopRequestHandler); } public override async Task RunServer(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) { GrpcPreconditions.CheckState(await requestStream.MoveNext()); var serverConfig = requestStream.Current.Setup; var runner = ServerRunners.CreateStarted(serverConfig); await responseStream.WriteAsync(new ServerStatus { Stats = runner.GetStats(false), Port = runner.BoundPort, Cores = Environment.ProcessorCount, }); while (await requestStream.MoveNext()) { var reset = requestStream.Current.Mark.Reset; await responseStream.WriteAsync(new ServerStatus { Stats = runner.GetStats(reset) }); } await runner.StopAsync(); } public override async Task RunClient(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) { GrpcPreconditions.CheckState(await requestStream.MoveNext()); var clientConfig = requestStream.Current.Setup; var runner = ClientRunners.CreateStarted(clientConfig); await responseStream.WriteAsync(new ClientStatus { Stats = runner.GetStats(false) }); while (await requestStream.MoveNext()) { var reset = requestStream.Current.Mark.Reset; await responseStream.WriteAsync(new ClientStatus { Stats = runner.GetStats(reset) }); } await runner.StopAsync(); } public override Task CoreCount(CoreRequest request, ServerCallContext context) { return Task.FromResult(new CoreResponse { Cores = Environment.ProcessorCount }); } public override Task QuitWorker(Void request, ServerCallContext context) { stopRequestHandler(); return Task.FromResult(new Void()); } } } grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/data/000077500000000000000000000000001310511640000221325ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/data/README000066400000000000000000000000211310511640000230030ustar00rootroot00000000000000CONFIRMEDTESTKEY grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/data/ca.pem000066400000000000000000000015271310511640000232250ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIICSjCCAbOgAwIBAgIJAJHGGR4dGioHMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnRlc3RjYTAeFw0xNDExMTEyMjMxMjla Fw0yNDExMDgyMjMxMjlaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0 YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDzANBgNVBAMT BnRlc3RjYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwEDfBV5MYdlHVHJ7 +L4nxrZy7mBfAVXpOc5vMYztssUI7mL2/iYujiIXM+weZYNTEpLdjyJdu7R5gGUu g1jSVK/EPHfc74O7AyZU34PNIP4Sh33N+/A5YexrNgJlPY+E3GdVYi4ldWJjgkAd Qah2PH5ACLrIIC6tRka9hcaBlIECAwEAAaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNV HQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADgYEAHzC7jdYlzAVmddi/gdAeKPau sPBG/C2HCWqHzpCUHcKuvMzDVkY/MP2o6JIW2DBbY64bO/FceExhjcykgaYtCH/m oIU63+CFOTtR7otyQAWHqXa7q4SbCDlG7DyRFxqG0txPtGvy12lgldA2+RgcigQG Dfcog5wrJytaQ6UA0wE= -----END CERTIFICATE----- grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/data/server1.key000066400000000000000000000016201310511640000242320ustar00rootroot00000000000000-----BEGIN PRIVATE KEY----- MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOHDFScoLCVJpYDD M4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1BgzkWF+slf 3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd9N8YwbBY AckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAECgYAn7qGnM2vbjJNBm0VZCkOkTIWm V10okw7EPJrdL2mkre9NasghNXbE1y5zDshx5Nt3KsazKOxTT8d0Jwh/3KbaN+YY tTCbKGW0pXDRBhwUHRcuRzScjli8Rih5UOCiZkhefUTcRb6xIhZJuQy71tjaSy0p dHZRmYyBYO2YEQ8xoQJBAPrJPhMBkzmEYFtyIEqAxQ/o/A6E+E4w8i+KM7nQCK7q K4JXzyXVAjLfyBZWHGM2uro/fjqPggGD6QH1qXCkI4MCQQDmdKeb2TrKRh5BY1LR 81aJGKcJ2XbcDu6wMZK4oqWbTX2KiYn9GB0woM6nSr/Y6iy1u145YzYxEV/iMwff DJULAkB8B2MnyzOg0pNFJqBJuH29bKCcHa8gHJzqXhNO5lAlEbMK95p/P2Wi+4Hd aiEIAF1BF326QJcvYKmwSmrORp85AkAlSNxRJ50OWrfMZnBgzVjDx3xG6KsFQVk2 ol6VhqL6dFgKUORFUWBvnKSyhjJxurlPEahV6oo6+A+mPhFY8eUvAkAZQyTdupP3 XEFQKctGz+9+gKkemDp7LBBMEMBXrGTLPhpEfcjv/7KPdnFHYmhYeBTBnuVmTVWe F98XJ7tIFfJq -----END PRIVATE KEY----- grpc-1.3.2/src/csharp/Grpc.IntegrationTesting/data/server1.pem000066400000000000000000000017041310511640000242260ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50 ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd 9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6 hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8 -----END CERTIFICATE----- grpc-1.3.2/src/csharp/Grpc.Reflection.Tests/000077500000000000000000000000001310511640000205735ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Reflection.Tests/.gitignore000066400000000000000000000000101310511640000225520ustar00rootroot00000000000000bin obj grpc-1.3.2/src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.csproj000077500000000000000000000022021310511640000261010ustar00rootroot00000000000000 net45;netcoreapp1.0 Grpc.Reflection.Tests Exe Grpc.Reflection.Tests $(PackageTargetFallback);portable-net45 1.0.4 grpc-1.3.2/src/csharp/Grpc.Reflection.Tests/NUnitMain.cs000066400000000000000000000045011310511640000227640ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Reflection; using Grpc.Core; using Grpc.Core.Logging; using NUnit.Common; using NUnitLite; namespace Grpc.Reflection.Tests { /// /// Provides entry point for NUnitLite /// public class NUnitMain { public static int Main(string[] args) { // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error)); #if NETCOREAPP1_0 return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In); #else return new AutoRun().Execute(args); #endif } } } grpc-1.3.2/src/csharp/Grpc.Reflection.Tests/Properties/000077500000000000000000000000001310511640000227275ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Reflection.Tests/Properties/AssemblyInfo.cs000066400000000000000000000037151310511640000256570ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Grpc.Reflection.Tests")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] grpc-1.3.2/src/csharp/Grpc.Reflection.Tests/ReflectionClientServerTest.cs000066400000000000000000000136721310511640000264130ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Grpc.Core; using Grpc.Reflection; using Grpc.Reflection.V1Alpha; using NUnit.Framework; namespace Grpc.Reflection.Tests { /// /// Reflection client talks to reflection server. /// public class ReflectionClientServerTest { const string Host = "localhost"; Server server; Channel channel; ServerReflection.ServerReflectionClient client; ReflectionServiceImpl serviceImpl; [TestFixtureSetUp] public void Init() { serviceImpl = new ReflectionServiceImpl(ServerReflection.Descriptor); // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) { Services = { ServerReflection.BindService(serviceImpl) }, Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } } }; server.Start(); channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure); client = new ServerReflection.ServerReflectionClient(channel); } [TestFixtureTearDown] public void Cleanup() { channel.ShutdownAsync().Wait(); server.ShutdownAsync().Wait(); } [Test] public async Task FileByFilename_NotFound() { var response = await SingleRequestAsync(new ServerReflectionRequest { FileByFilename = "somepackage/nonexistent.proto" }); Assert.AreEqual((int)StatusCode.NotFound, response.ErrorResponse.ErrorCode); } [Test] public async Task FileByFilename() { var response = await SingleRequestAsync(new ServerReflectionRequest { FileByFilename = "grpc/reflection/v1alpha/reflection.proto" }); Assert.AreEqual(1, response.FileDescriptorResponse.FileDescriptorProto.Count); Assert.AreEqual(ReflectionReflection.Descriptor.SerializedData, response.FileDescriptorResponse.FileDescriptorProto[0]); } [Test] public async Task FileContainingSymbol() { var response = await SingleRequestAsync(new ServerReflectionRequest { FileContainingSymbol = "grpc.reflection.v1alpha.ServerReflection" }); Assert.AreEqual(1, response.FileDescriptorResponse.FileDescriptorProto.Count); Assert.AreEqual(ReflectionReflection.Descriptor.SerializedData, response.FileDescriptorResponse.FileDescriptorProto[0]); } [Test] public async Task FileContainingSymbol_NotFound() { var response = await SingleRequestAsync(new ServerReflectionRequest { FileContainingSymbol = "somepackage.Nonexistent" }); Assert.AreEqual((int)StatusCode.NotFound, response.ErrorResponse.ErrorCode); } [Test] public async Task ListServices() { var response = await SingleRequestAsync(new ServerReflectionRequest { ListServices = "" }); Assert.AreEqual(1, response.ListServicesResponse.Service.Count); Assert.AreEqual(ServerReflection.Descriptor.FullName, response.ListServicesResponse.Service[0].Name); } [Test] public async Task FileContainingExtension() { var response = await SingleRequestAsync(new ServerReflectionRequest { FileContainingExtension = new ExtensionRequest() }); Assert.AreEqual((int)StatusCode.Unimplemented, response.ErrorResponse.ErrorCode); } private async Task SingleRequestAsync(ServerReflectionRequest request) { var call = client.ServerReflectionInfo(); await call.RequestStream.WriteAsync(request); Assert.IsTrue(await call.ResponseStream.MoveNext()); var response = call.ResponseStream.Current; await call.RequestStream.CompleteAsync(); Assert.IsFalse(await call.ResponseStream.MoveNext()); return response; } } } grpc-1.3.2/src/csharp/Grpc.Reflection.Tests/SymbolRegistryTest.cs000066400000000000000000000060051310511640000247610ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using Grpc.Reflection; using Grpc.Reflection.V1Alpha; using NUnit.Framework; namespace Grpc.Reflection.Tests { /// /// Tests for ReflectionServiceImpl /// public class SymbolRegistryTest { SymbolRegistry registry = SymbolRegistry.FromFiles(new[] { ReflectionReflection.Descriptor, Google.Protobuf.WellKnownTypes.Duration.Descriptor.File }); [Test] public void FileByName() { Assert.AreSame(Google.Protobuf.WellKnownTypes.Duration.Descriptor.File, registry.FileByName("google/protobuf/duration.proto")); Assert.IsNull(registry.FileByName("somepackage/nonexistent.proto")); } [Test] public void FileContainingSymbol() { Assert.AreSame(Google.Protobuf.WellKnownTypes.Duration.Descriptor.File, registry.FileContainingSymbol("google.protobuf.Duration")); Assert.AreSame(ReflectionReflection.Descriptor, registry.FileContainingSymbol("grpc.reflection.v1alpha.ServerReflection.ServerReflectionInfo")); // method Assert.AreSame(ReflectionReflection.Descriptor, registry.FileContainingSymbol("grpc.reflection.v1alpha.ServerReflection")); // service Assert.AreSame(ReflectionReflection.Descriptor, registry.FileContainingSymbol("grpc.reflection.v1alpha.ServerReflectionRequest")); // message Assert.IsNull(registry.FileContainingSymbol("somepackage.Nonexistent")); } } } grpc-1.3.2/src/csharp/Grpc.Reflection/000077500000000000000000000000001310511640000174725ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Reflection/.gitignore000066400000000000000000000000101310511640000214510ustar00rootroot00000000000000bin obj grpc-1.3.2/src/csharp/Grpc.Reflection/Grpc.Reflection.csproj000077500000000000000000000025111310511640000237020ustar00rootroot00000000000000 Copyright 2016, Google Inc. gRPC C# Reflection $(GrpcCsharpVersion) Google Inc. net45;netstandard1.5 Grpc.Reflection Grpc.Reflection gRPC reflection https://github.com/grpc/grpc https://github.com/grpc/grpc/blob/master/LICENSE 1.6.0 grpc-1.3.2/src/csharp/Grpc.Reflection/Properties/000077500000000000000000000000001310511640000216265ustar00rootroot00000000000000grpc-1.3.2/src/csharp/Grpc.Reflection/Properties/AssemblyInfo.cs000066400000000000000000000037071310511640000245570ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Reflection; using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Grpc.Reflection")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] grpc-1.3.2/src/csharp/Grpc.Reflection/Reflection.cs000066400000000000000000001674231310511640000221300ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: grpc/reflection/v1alpha/reflection.proto #pragma warning disable 1591, 0612, 3021 #region Designer generated code using pb = global::Google.Protobuf; using pbc = global::Google.Protobuf.Collections; using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; namespace Grpc.Reflection.V1Alpha { /// Holder for reflection information generated from grpc/reflection/v1alpha/reflection.proto public static partial class ReflectionReflection { #region Descriptor /// File descriptor for grpc/reflection/v1alpha/reflection.proto public static pbr::FileDescriptor Descriptor { get { return descriptor; } } private static pbr::FileDescriptor descriptor; static ReflectionReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "CihncnBjL3JlZmxlY3Rpb24vdjFhbHBoYS9yZWZsZWN0aW9uLnByb3RvEhdn", "cnBjLnJlZmxlY3Rpb24udjFhbHBoYSKKAgoXU2VydmVyUmVmbGVjdGlvblJl", "cXVlc3QSDAoEaG9zdBgBIAEoCRIaChBmaWxlX2J5X2ZpbGVuYW1lGAMgASgJ", "SAASIAoWZmlsZV9jb250YWluaW5nX3N5bWJvbBgEIAEoCUgAEk4KGWZpbGVf", "Y29udGFpbmluZ19leHRlbnNpb24YBSABKAsyKS5ncnBjLnJlZmxlY3Rpb24u", "djFhbHBoYS5FeHRlbnNpb25SZXF1ZXN0SAASJwodYWxsX2V4dGVuc2lvbl9u", "dW1iZXJzX29mX3R5cGUYBiABKAlIABIXCg1saXN0X3NlcnZpY2VzGAcgASgJ", "SABCEQoPbWVzc2FnZV9yZXF1ZXN0IkUKEEV4dGVuc2lvblJlcXVlc3QSFwoP", "Y29udGFpbmluZ190eXBlGAEgASgJEhgKEGV4dGVuc2lvbl9udW1iZXIYAiAB", "KAUi0QMKGFNlcnZlclJlZmxlY3Rpb25SZXNwb25zZRISCgp2YWxpZF9ob3N0", "GAEgASgJEkoKEG9yaWdpbmFsX3JlcXVlc3QYAiABKAsyMC5ncnBjLnJlZmxl", "Y3Rpb24udjFhbHBoYS5TZXJ2ZXJSZWZsZWN0aW9uUmVxdWVzdBJTChhmaWxl", "X2Rlc2NyaXB0b3JfcmVzcG9uc2UYBCABKAsyLy5ncnBjLnJlZmxlY3Rpb24u", "djFhbHBoYS5GaWxlRGVzY3JpcHRvclJlc3BvbnNlSAASWgoeYWxsX2V4dGVu", "c2lvbl9udW1iZXJzX3Jlc3BvbnNlGAUgASgLMjAuZ3JwYy5yZWZsZWN0aW9u", "LnYxYWxwaGEuRXh0ZW5zaW9uTnVtYmVyUmVzcG9uc2VIABJOChZsaXN0X3Nl", "cnZpY2VzX3Jlc3BvbnNlGAYgASgLMiwuZ3JwYy5yZWZsZWN0aW9uLnYxYWxw", "aGEuTGlzdFNlcnZpY2VSZXNwb25zZUgAEkAKDmVycm9yX3Jlc3BvbnNlGAcg", "ASgLMiYuZ3JwYy5yZWZsZWN0aW9uLnYxYWxwaGEuRXJyb3JSZXNwb25zZUgA", "QhIKEG1lc3NhZ2VfcmVzcG9uc2UiNwoWRmlsZURlc2NyaXB0b3JSZXNwb25z", "ZRIdChVmaWxlX2Rlc2NyaXB0b3JfcHJvdG8YASADKAwiSwoXRXh0ZW5zaW9u", "TnVtYmVyUmVzcG9uc2USFgoOYmFzZV90eXBlX25hbWUYASABKAkSGAoQZXh0", "ZW5zaW9uX251bWJlchgCIAMoBSJQChNMaXN0U2VydmljZVJlc3BvbnNlEjkK", "B3NlcnZpY2UYASADKAsyKC5ncnBjLnJlZmxlY3Rpb24udjFhbHBoYS5TZXJ2", "aWNlUmVzcG9uc2UiHwoPU2VydmljZVJlc3BvbnNlEgwKBG5hbWUYASABKAki", "OgoNRXJyb3JSZXNwb25zZRISCgplcnJvcl9jb2RlGAEgASgFEhUKDWVycm9y", "X21lc3NhZ2UYAiABKAkykwEKEFNlcnZlclJlZmxlY3Rpb24SfwoUU2VydmVy", "UmVmbGVjdGlvbkluZm8SMC5ncnBjLnJlZmxlY3Rpb24udjFhbHBoYS5TZXJ2", "ZXJSZWZsZWN0aW9uUmVxdWVzdBoxLmdycGMucmVmbGVjdGlvbi52MWFscGhh", "LlNlcnZlclJlZmxlY3Rpb25SZXNwb25zZSgBMAFiBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ServerReflectionRequest), global::Grpc.Reflection.V1Alpha.ServerReflectionRequest.Parser, new[]{ "Host", "FileByFilename", "FileContainingSymbol", "FileContainingExtension", "AllExtensionNumbersOfType", "ListServices" }, new[]{ "MessageRequest" }, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ExtensionRequest), global::Grpc.Reflection.V1Alpha.ExtensionRequest.Parser, new[]{ "ContainingType", "ExtensionNumber" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ServerReflectionResponse), global::Grpc.Reflection.V1Alpha.ServerReflectionResponse.Parser, new[]{ "ValidHost", "OriginalRequest", "FileDescriptorResponse", "AllExtensionNumbersResponse", "ListServicesResponse", "ErrorResponse" }, new[]{ "MessageResponse" }, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.FileDescriptorResponse), global::Grpc.Reflection.V1Alpha.FileDescriptorResponse.Parser, new[]{ "FileDescriptorProto" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse), global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse.Parser, new[]{ "BaseTypeName", "ExtensionNumber" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ListServiceResponse), global::Grpc.Reflection.V1Alpha.ListServiceResponse.Parser, new[]{ "Service" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ServiceResponse), global::Grpc.Reflection.V1Alpha.ServiceResponse.Parser, new[]{ "Name" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ErrorResponse), global::Grpc.Reflection.V1Alpha.ErrorResponse.Parser, new[]{ "ErrorCode", "ErrorMessage" }, null, null, null) })); } #endregion } #region Messages /// /// The message sent by the client when calling ServerReflectionInfo method. /// public sealed partial class ServerReflectionRequest : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ServerReflectionRequest()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServerReflectionRequest() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServerReflectionRequest(ServerReflectionRequest other) : this() { host_ = other.host_; switch (other.MessageRequestCase) { case MessageRequestOneofCase.FileByFilename: FileByFilename = other.FileByFilename; break; case MessageRequestOneofCase.FileContainingSymbol: FileContainingSymbol = other.FileContainingSymbol; break; case MessageRequestOneofCase.FileContainingExtension: FileContainingExtension = other.FileContainingExtension.Clone(); break; case MessageRequestOneofCase.AllExtensionNumbersOfType: AllExtensionNumbersOfType = other.AllExtensionNumbersOfType; break; case MessageRequestOneofCase.ListServices: ListServices = other.ListServices; break; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServerReflectionRequest Clone() { return new ServerReflectionRequest(this); } /// Field number for the "host" field. public const int HostFieldNumber = 1; private string host_ = ""; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Host { get { return host_; } set { host_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Field number for the "file_by_filename" field. public const int FileByFilenameFieldNumber = 3; /// /// Find a proto file by the file name. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string FileByFilename { get { return messageRequestCase_ == MessageRequestOneofCase.FileByFilename ? (string) messageRequest_ : ""; } set { messageRequest_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); messageRequestCase_ = MessageRequestOneofCase.FileByFilename; } } /// Field number for the "file_containing_symbol" field. public const int FileContainingSymbolFieldNumber = 4; /// /// Find the proto file that declares the given fully-qualified symbol name. /// This field should be a fully-qualified symbol name /// (e.g. <package>.<service>[.<method>] or <package>.<type>). /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string FileContainingSymbol { get { return messageRequestCase_ == MessageRequestOneofCase.FileContainingSymbol ? (string) messageRequest_ : ""; } set { messageRequest_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); messageRequestCase_ = MessageRequestOneofCase.FileContainingSymbol; } } /// Field number for the "file_containing_extension" field. public const int FileContainingExtensionFieldNumber = 5; /// /// Find the proto file which defines an extension extending the given /// message type with the given field number. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Reflection.V1Alpha.ExtensionRequest FileContainingExtension { get { return messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension ? (global::Grpc.Reflection.V1Alpha.ExtensionRequest) messageRequest_ : null; } set { messageRequest_ = value; messageRequestCase_ = value == null ? MessageRequestOneofCase.None : MessageRequestOneofCase.FileContainingExtension; } } /// Field number for the "all_extension_numbers_of_type" field. public const int AllExtensionNumbersOfTypeFieldNumber = 6; /// /// Finds the tag numbers used by all known extensions of the given message /// type, and appends them to ExtensionNumberResponse in an undefined order. /// Its corresponding method is best-effort: it's not guaranteed that the /// reflection service will implement this method, and it's not guaranteed /// that this method will provide all extensions. Returns /// StatusCode::UNIMPLEMENTED if it's not implemented. /// This field should be a fully-qualified type name. The format is /// <package>.<type> /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string AllExtensionNumbersOfType { get { return messageRequestCase_ == MessageRequestOneofCase.AllExtensionNumbersOfType ? (string) messageRequest_ : ""; } set { messageRequest_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); messageRequestCase_ = MessageRequestOneofCase.AllExtensionNumbersOfType; } } /// Field number for the "list_services" field. public const int ListServicesFieldNumber = 7; /// /// List the full names of registered services. The content will not be /// checked. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string ListServices { get { return messageRequestCase_ == MessageRequestOneofCase.ListServices ? (string) messageRequest_ : ""; } set { messageRequest_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); messageRequestCase_ = MessageRequestOneofCase.ListServices; } } private object messageRequest_; /// Enum of possible cases for the "message_request" oneof. public enum MessageRequestOneofCase { None = 0, FileByFilename = 3, FileContainingSymbol = 4, FileContainingExtension = 5, AllExtensionNumbersOfType = 6, ListServices = 7, } private MessageRequestOneofCase messageRequestCase_ = MessageRequestOneofCase.None; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public MessageRequestOneofCase MessageRequestCase { get { return messageRequestCase_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearMessageRequest() { messageRequestCase_ = MessageRequestOneofCase.None; messageRequest_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ServerReflectionRequest); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ServerReflectionRequest other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Host != other.Host) return false; if (FileByFilename != other.FileByFilename) return false; if (FileContainingSymbol != other.FileContainingSymbol) return false; if (!object.Equals(FileContainingExtension, other.FileContainingExtension)) return false; if (AllExtensionNumbersOfType != other.AllExtensionNumbersOfType) return false; if (ListServices != other.ListServices) return false; if (MessageRequestCase != other.MessageRequestCase) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Host.Length != 0) hash ^= Host.GetHashCode(); if (messageRequestCase_ == MessageRequestOneofCase.FileByFilename) hash ^= FileByFilename.GetHashCode(); if (messageRequestCase_ == MessageRequestOneofCase.FileContainingSymbol) hash ^= FileContainingSymbol.GetHashCode(); if (messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension) hash ^= FileContainingExtension.GetHashCode(); if (messageRequestCase_ == MessageRequestOneofCase.AllExtensionNumbersOfType) hash ^= AllExtensionNumbersOfType.GetHashCode(); if (messageRequestCase_ == MessageRequestOneofCase.ListServices) hash ^= ListServices.GetHashCode(); hash ^= (int) messageRequestCase_; return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Host.Length != 0) { output.WriteRawTag(10); output.WriteString(Host); } if (messageRequestCase_ == MessageRequestOneofCase.FileByFilename) { output.WriteRawTag(26); output.WriteString(FileByFilename); } if (messageRequestCase_ == MessageRequestOneofCase.FileContainingSymbol) { output.WriteRawTag(34); output.WriteString(FileContainingSymbol); } if (messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension) { output.WriteRawTag(42); output.WriteMessage(FileContainingExtension); } if (messageRequestCase_ == MessageRequestOneofCase.AllExtensionNumbersOfType) { output.WriteRawTag(50); output.WriteString(AllExtensionNumbersOfType); } if (messageRequestCase_ == MessageRequestOneofCase.ListServices) { output.WriteRawTag(58); output.WriteString(ListServices); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Host.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Host); } if (messageRequestCase_ == MessageRequestOneofCase.FileByFilename) { size += 1 + pb::CodedOutputStream.ComputeStringSize(FileByFilename); } if (messageRequestCase_ == MessageRequestOneofCase.FileContainingSymbol) { size += 1 + pb::CodedOutputStream.ComputeStringSize(FileContainingSymbol); } if (messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(FileContainingExtension); } if (messageRequestCase_ == MessageRequestOneofCase.AllExtensionNumbersOfType) { size += 1 + pb::CodedOutputStream.ComputeStringSize(AllExtensionNumbersOfType); } if (messageRequestCase_ == MessageRequestOneofCase.ListServices) { size += 1 + pb::CodedOutputStream.ComputeStringSize(ListServices); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ServerReflectionRequest other) { if (other == null) { return; } if (other.Host.Length != 0) { Host = other.Host; } switch (other.MessageRequestCase) { case MessageRequestOneofCase.FileByFilename: FileByFilename = other.FileByFilename; break; case MessageRequestOneofCase.FileContainingSymbol: FileContainingSymbol = other.FileContainingSymbol; break; case MessageRequestOneofCase.FileContainingExtension: FileContainingExtension = other.FileContainingExtension; break; case MessageRequestOneofCase.AllExtensionNumbersOfType: AllExtensionNumbersOfType = other.AllExtensionNumbersOfType; break; case MessageRequestOneofCase.ListServices: ListServices = other.ListServices; break; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { Host = input.ReadString(); break; } case 26: { FileByFilename = input.ReadString(); break; } case 34: { FileContainingSymbol = input.ReadString(); break; } case 42: { global::Grpc.Reflection.V1Alpha.ExtensionRequest subBuilder = new global::Grpc.Reflection.V1Alpha.ExtensionRequest(); if (messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension) { subBuilder.MergeFrom(FileContainingExtension); } input.ReadMessage(subBuilder); FileContainingExtension = subBuilder; break; } case 50: { AllExtensionNumbersOfType = input.ReadString(); break; } case 58: { ListServices = input.ReadString(); break; } } } } } /// /// The type name and extension number sent by the client when requesting /// file_containing_extension. /// public sealed partial class ExtensionRequest : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ExtensionRequest()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ExtensionRequest() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ExtensionRequest(ExtensionRequest other) : this() { containingType_ = other.containingType_; extensionNumber_ = other.extensionNumber_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ExtensionRequest Clone() { return new ExtensionRequest(this); } /// Field number for the "containing_type" field. public const int ContainingTypeFieldNumber = 1; private string containingType_ = ""; /// /// Fully-qualified type name. The format should be <package>.<type> /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string ContainingType { get { return containingType_; } set { containingType_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Field number for the "extension_number" field. public const int ExtensionNumberFieldNumber = 2; private int extensionNumber_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int ExtensionNumber { get { return extensionNumber_; } set { extensionNumber_ = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ExtensionRequest); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ExtensionRequest other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (ContainingType != other.ContainingType) return false; if (ExtensionNumber != other.ExtensionNumber) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (ContainingType.Length != 0) hash ^= ContainingType.GetHashCode(); if (ExtensionNumber != 0) hash ^= ExtensionNumber.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (ContainingType.Length != 0) { output.WriteRawTag(10); output.WriteString(ContainingType); } if (ExtensionNumber != 0) { output.WriteRawTag(16); output.WriteInt32(ExtensionNumber); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (ContainingType.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(ContainingType); } if (ExtensionNumber != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(ExtensionNumber); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ExtensionRequest other) { if (other == null) { return; } if (other.ContainingType.Length != 0) { ContainingType = other.ContainingType; } if (other.ExtensionNumber != 0) { ExtensionNumber = other.ExtensionNumber; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { ContainingType = input.ReadString(); break; } case 16: { ExtensionNumber = input.ReadInt32(); break; } } } } } /// /// The message sent by the server to answer ServerReflectionInfo method. /// public sealed partial class ServerReflectionResponse : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ServerReflectionResponse()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[2]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServerReflectionResponse() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServerReflectionResponse(ServerReflectionResponse other) : this() { validHost_ = other.validHost_; OriginalRequest = other.originalRequest_ != null ? other.OriginalRequest.Clone() : null; switch (other.MessageResponseCase) { case MessageResponseOneofCase.FileDescriptorResponse: FileDescriptorResponse = other.FileDescriptorResponse.Clone(); break; case MessageResponseOneofCase.AllExtensionNumbersResponse: AllExtensionNumbersResponse = other.AllExtensionNumbersResponse.Clone(); break; case MessageResponseOneofCase.ListServicesResponse: ListServicesResponse = other.ListServicesResponse.Clone(); break; case MessageResponseOneofCase.ErrorResponse: ErrorResponse = other.ErrorResponse.Clone(); break; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServerReflectionResponse Clone() { return new ServerReflectionResponse(this); } /// Field number for the "valid_host" field. public const int ValidHostFieldNumber = 1; private string validHost_ = ""; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string ValidHost { get { return validHost_; } set { validHost_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Field number for the "original_request" field. public const int OriginalRequestFieldNumber = 2; private global::Grpc.Reflection.V1Alpha.ServerReflectionRequest originalRequest_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Reflection.V1Alpha.ServerReflectionRequest OriginalRequest { get { return originalRequest_; } set { originalRequest_ = value; } } /// Field number for the "file_descriptor_response" field. public const int FileDescriptorResponseFieldNumber = 4; /// /// This message is used to answer file_by_filename, file_containing_symbol, /// file_containing_extension requests with transitive dependencies. As /// the repeated label is not allowed in oneof fields, we use a /// FileDescriptorResponse message to encapsulate the repeated fields. /// The reflection service is allowed to avoid sending FileDescriptorProtos /// that were previously sent in response to earlier requests in the stream. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Reflection.V1Alpha.FileDescriptorResponse FileDescriptorResponse { get { return messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse ? (global::Grpc.Reflection.V1Alpha.FileDescriptorResponse) messageResponse_ : null; } set { messageResponse_ = value; messageResponseCase_ = value == null ? MessageResponseOneofCase.None : MessageResponseOneofCase.FileDescriptorResponse; } } /// Field number for the "all_extension_numbers_response" field. public const int AllExtensionNumbersResponseFieldNumber = 5; /// /// This message is used to answer all_extension_numbers_of_type requst. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse AllExtensionNumbersResponse { get { return messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse ? (global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse) messageResponse_ : null; } set { messageResponse_ = value; messageResponseCase_ = value == null ? MessageResponseOneofCase.None : MessageResponseOneofCase.AllExtensionNumbersResponse; } } /// Field number for the "list_services_response" field. public const int ListServicesResponseFieldNumber = 6; /// /// This message is used to answer list_services request. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Reflection.V1Alpha.ListServiceResponse ListServicesResponse { get { return messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse ? (global::Grpc.Reflection.V1Alpha.ListServiceResponse) messageResponse_ : null; } set { messageResponse_ = value; messageResponseCase_ = value == null ? MessageResponseOneofCase.None : MessageResponseOneofCase.ListServicesResponse; } } /// Field number for the "error_response" field. public const int ErrorResponseFieldNumber = 7; /// /// This message is used when an error occurs. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Grpc.Reflection.V1Alpha.ErrorResponse ErrorResponse { get { return messageResponseCase_ == MessageResponseOneofCase.ErrorResponse ? (global::Grpc.Reflection.V1Alpha.ErrorResponse) messageResponse_ : null; } set { messageResponse_ = value; messageResponseCase_ = value == null ? MessageResponseOneofCase.None : MessageResponseOneofCase.ErrorResponse; } } private object messageResponse_; /// Enum of possible cases for the "message_response" oneof. public enum MessageResponseOneofCase { None = 0, FileDescriptorResponse = 4, AllExtensionNumbersResponse = 5, ListServicesResponse = 6, ErrorResponse = 7, } private MessageResponseOneofCase messageResponseCase_ = MessageResponseOneofCase.None; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public MessageResponseOneofCase MessageResponseCase { get { return messageResponseCase_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearMessageResponse() { messageResponseCase_ = MessageResponseOneofCase.None; messageResponse_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ServerReflectionResponse); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ServerReflectionResponse other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (ValidHost != other.ValidHost) return false; if (!object.Equals(OriginalRequest, other.OriginalRequest)) return false; if (!object.Equals(FileDescriptorResponse, other.FileDescriptorResponse)) return false; if (!object.Equals(AllExtensionNumbersResponse, other.AllExtensionNumbersResponse)) return false; if (!object.Equals(ListServicesResponse, other.ListServicesResponse)) return false; if (!object.Equals(ErrorResponse, other.ErrorResponse)) return false; if (MessageResponseCase != other.MessageResponseCase) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (ValidHost.Length != 0) hash ^= ValidHost.GetHashCode(); if (originalRequest_ != null) hash ^= OriginalRequest.GetHashCode(); if (messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse) hash ^= FileDescriptorResponse.GetHashCode(); if (messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse) hash ^= AllExtensionNumbersResponse.GetHashCode(); if (messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse) hash ^= ListServicesResponse.GetHashCode(); if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) hash ^= ErrorResponse.GetHashCode(); hash ^= (int) messageResponseCase_; return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (ValidHost.Length != 0) { output.WriteRawTag(10); output.WriteString(ValidHost); } if (originalRequest_ != null) { output.WriteRawTag(18); output.WriteMessage(OriginalRequest); } if (messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse) { output.WriteRawTag(34); output.WriteMessage(FileDescriptorResponse); } if (messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse) { output.WriteRawTag(42); output.WriteMessage(AllExtensionNumbersResponse); } if (messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse) { output.WriteRawTag(50); output.WriteMessage(ListServicesResponse); } if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) { output.WriteRawTag(58); output.WriteMessage(ErrorResponse); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (ValidHost.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(ValidHost); } if (originalRequest_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(OriginalRequest); } if (messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(FileDescriptorResponse); } if (messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(AllExtensionNumbersResponse); } if (messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(ListServicesResponse); } if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(ErrorResponse); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ServerReflectionResponse other) { if (other == null) { return; } if (other.ValidHost.Length != 0) { ValidHost = other.ValidHost; } if (other.originalRequest_ != null) { if (originalRequest_ == null) { originalRequest_ = new global::Grpc.Reflection.V1Alpha.ServerReflectionRequest(); } OriginalRequest.MergeFrom(other.OriginalRequest); } switch (other.MessageResponseCase) { case MessageResponseOneofCase.FileDescriptorResponse: FileDescriptorResponse = other.FileDescriptorResponse; break; case MessageResponseOneofCase.AllExtensionNumbersResponse: AllExtensionNumbersResponse = other.AllExtensionNumbersResponse; break; case MessageResponseOneofCase.ListServicesResponse: ListServicesResponse = other.ListServicesResponse; break; case MessageResponseOneofCase.ErrorResponse: ErrorResponse = other.ErrorResponse; break; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { ValidHost = input.ReadString(); break; } case 18: { if (originalRequest_ == null) { originalRequest_ = new global::Grpc.Reflection.V1Alpha.ServerReflectionRequest(); } input.ReadMessage(originalRequest_); break; } case 34: { global::Grpc.Reflection.V1Alpha.FileDescriptorResponse subBuilder = new global::Grpc.Reflection.V1Alpha.FileDescriptorResponse(); if (messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse) { subBuilder.MergeFrom(FileDescriptorResponse); } input.ReadMessage(subBuilder); FileDescriptorResponse = subBuilder; break; } case 42: { global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse subBuilder = new global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse(); if (messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse) { subBuilder.MergeFrom(AllExtensionNumbersResponse); } input.ReadMessage(subBuilder); AllExtensionNumbersResponse = subBuilder; break; } case 50: { global::Grpc.Reflection.V1Alpha.ListServiceResponse subBuilder = new global::Grpc.Reflection.V1Alpha.ListServiceResponse(); if (messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse) { subBuilder.MergeFrom(ListServicesResponse); } input.ReadMessage(subBuilder); ListServicesResponse = subBuilder; break; } case 58: { global::Grpc.Reflection.V1Alpha.ErrorResponse subBuilder = new global::Grpc.Reflection.V1Alpha.ErrorResponse(); if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) { subBuilder.MergeFrom(ErrorResponse); } input.ReadMessage(subBuilder); ErrorResponse = subBuilder; break; } } } } } /// /// Serialized FileDescriptorProto messages sent by the server answering /// a file_by_filename, file_containing_symbol, or file_containing_extension /// request. /// public sealed partial class FileDescriptorResponse : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FileDescriptorResponse()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[3]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public FileDescriptorResponse() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public FileDescriptorResponse(FileDescriptorResponse other) : this() { fileDescriptorProto_ = other.fileDescriptorProto_.Clone(); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public FileDescriptorResponse Clone() { return new FileDescriptorResponse(this); } /// Field number for the "file_descriptor_proto" field. public const int FileDescriptorProtoFieldNumber = 1; private static readonly pb::FieldCodec _repeated_fileDescriptorProto_codec = pb::FieldCodec.ForBytes(10); private readonly pbc::RepeatedField fileDescriptorProto_ = new pbc::RepeatedField(); /// /// Serialized FileDescriptorProto messages. We avoid taking a dependency on /// descriptor.proto, which uses proto2 only features, by making them opaque /// bytes instead. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::RepeatedField FileDescriptorProto { get { return fileDescriptorProto_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as FileDescriptorResponse); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(FileDescriptorResponse other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if(!fileDescriptorProto_.Equals(other.fileDescriptorProto_)) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; hash ^= fileDescriptorProto_.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { fileDescriptorProto_.WriteTo(output, _repeated_fileDescriptorProto_codec); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; size += fileDescriptorProto_.CalculateSize(_repeated_fileDescriptorProto_codec); return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(FileDescriptorResponse other) { if (other == null) { return; } fileDescriptorProto_.Add(other.fileDescriptorProto_); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { fileDescriptorProto_.AddEntriesFrom(input, _repeated_fileDescriptorProto_codec); break; } } } } } /// /// A list of extension numbers sent by the server answering /// all_extension_numbers_of_type request. /// public sealed partial class ExtensionNumberResponse : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ExtensionNumberResponse()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[4]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ExtensionNumberResponse() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ExtensionNumberResponse(ExtensionNumberResponse other) : this() { baseTypeName_ = other.baseTypeName_; extensionNumber_ = other.extensionNumber_.Clone(); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ExtensionNumberResponse Clone() { return new ExtensionNumberResponse(this); } /// Field number for the "base_type_name" field. public const int BaseTypeNameFieldNumber = 1; private string baseTypeName_ = ""; /// /// Full name of the base type, including the package name. The format /// is <package>.<type> /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string BaseTypeName { get { return baseTypeName_; } set { baseTypeName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } /// Field number for the "extension_number" field. public const int ExtensionNumberFieldNumber = 2; private static readonly pb::FieldCodec _repeated_extensionNumber_codec = pb::FieldCodec.ForInt32(18); private readonly pbc::RepeatedField extensionNumber_ = new pbc::RepeatedField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::RepeatedField ExtensionNumber { get { return extensionNumber_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ExtensionNumberResponse); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ExtensionNumberResponse other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (BaseTypeName != other.BaseTypeName) return false; if(!extensionNumber_.Equals(other.extensionNumber_)) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (BaseTypeName.Length != 0) hash ^= BaseTypeName.GetHashCode(); hash ^= extensionNumber_.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (BaseTypeName.Length != 0) { output.WriteRawTag(10); output.WriteString(BaseTypeName); } extensionNumber_.WriteTo(output, _repeated_extensionNumber_codec); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (BaseTypeName.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(BaseTypeName); } size += extensionNumber_.CalculateSize(_repeated_extensionNumber_codec); return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ExtensionNumberResponse other) { if (other == null) { return; } if (other.BaseTypeName.Length != 0) { BaseTypeName = other.BaseTypeName; } extensionNumber_.Add(other.extensionNumber_); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { BaseTypeName = input.ReadString(); break; } case 18: case 16: { extensionNumber_.AddEntriesFrom(input, _repeated_extensionNumber_codec); break; } } } } } /// /// A list of ServiceResponse sent by the server answering list_services request. /// public sealed partial class ListServiceResponse : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ListServiceResponse()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[5]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ListServiceResponse() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ListServiceResponse(ListServiceResponse other) : this() { service_ = other.service_.Clone(); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ListServiceResponse Clone() { return new ListServiceResponse(this); } /// Field number for the "service" field. public const int ServiceFieldNumber = 1; private static readonly pb::FieldCodec _repeated_service_codec = pb::FieldCodec.ForMessage(10, global::Grpc.Reflection.V1Alpha.ServiceResponse.Parser); private readonly pbc::RepeatedField service_ = new pbc::RepeatedField(); /// /// The information of each service may be expanded in the future, so we use /// ServiceResponse message to encapsulate it. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::RepeatedField Service { get { return service_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ListServiceResponse); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ListServiceResponse other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if(!service_.Equals(other.service_)) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; hash ^= service_.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { service_.WriteTo(output, _repeated_service_codec); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; size += service_.CalculateSize(_repeated_service_codec); return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ListServiceResponse other) { if (other == null) { return; } service_.Add(other.service_); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { service_.AddEntriesFrom(input, _repeated_service_codec); break; } } } } } /// /// The information of a single service used by ListServiceResponse to answer /// list_services request. /// public sealed partial class ServiceResponse : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ServiceResponse()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[6]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServiceResponse() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServiceResponse(ServiceResponse other) : this() { name_ = other.name_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServiceResponse Clone() { return new ServiceResponse(this); } /// Field number for the "name" field. public const int NameFieldNumber = 1; private string name_ = ""; /// /// Full name of a registered service, including its package name. The format /// is <package>.<service> /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Name { get { return name_; } set { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ServiceResponse); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ServiceResponse other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (Name != other.Name) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Name.Length != 0) hash ^= Name.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Name.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ServiceResponse other) { if (other == null) { return; } if (other.Name.Length != 0) { Name = other.Name; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 10: { Name = input.ReadString(); break; } } } } } /// /// The error code and error message sent by the server when an error occurs. /// public sealed partial class ErrorResponse : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ErrorResponse()); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[7]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ErrorResponse() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ErrorResponse(ErrorResponse other) : this() { errorCode_ = other.errorCode_; errorMessage_ = other.errorMessage_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ErrorResponse Clone() { return new ErrorResponse(this); } /// Field number for the "error_code" field. public const int ErrorCodeFieldNumber = 1; private int errorCode_; /// /// This field uses the error codes defined in grpc::StatusCode. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int ErrorCode { get { return errorCode_; } set { errorCode_ = value; } } /// Field number for the "error_message" field. public const int ErrorMessageFieldNumber = 2; private string errorMessage_ = ""; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string ErrorMessage { get { return errorMessage_; } set { errorMessage_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ErrorResponse); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(ErrorResponse other) { if (ReferenceEquals(other, null)) { return false; } if (ReferenceEquals(other, this)) { return true; } if (ErrorCode != other.ErrorCode) return false; if (ErrorMessage != other.ErrorMessage) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (ErrorCode != 0) hash ^= ErrorCode.GetHashCode(); if (ErrorMessage.Length != 0) hash ^= ErrorMessage.GetHashCode(); return hash; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { if (ErrorCode != 0) { output.WriteRawTag(8); output.WriteInt32(ErrorCode); } if (ErrorMessage.Length != 0) { output.WriteRawTag(18); output.WriteString(ErrorMessage); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (ErrorCode != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(ErrorCode); } if (ErrorMessage.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(ErrorMessage); } return size; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(ErrorResponse other) { if (other == null) { return; } if (other.ErrorCode != 0) { ErrorCode = other.ErrorCode; } if (other.ErrorMessage.Length != 0) { ErrorMessage = other.ErrorMessage; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: input.SkipLastField(); break; case 8: { ErrorCode = input.ReadInt32(); break; } case 18: { ErrorMessage = input.ReadString(); break; } } } } } #endregion } #endregion Designer generated code grpc-1.3.2/src/csharp/Grpc.Reflection/ReflectionGrpc.cs000066400000000000000000000175041310511640000227360ustar00rootroot00000000000000// Generated by the protocol buffer compiler. DO NOT EDIT! // source: grpc/reflection/v1alpha/reflection.proto // Original file comments: // Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Service exported by server reflection // #region Designer generated code using System; using System.Threading; using System.Threading.Tasks; using grpc = global::Grpc.Core; namespace Grpc.Reflection.V1Alpha { public static partial class ServerReflection { static readonly string __ServiceName = "grpc.reflection.v1alpha.ServerReflection"; static readonly grpc::Marshaller __Marshaller_ServerReflectionRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Reflection.V1Alpha.ServerReflectionRequest.Parser.ParseFrom); static readonly grpc::Marshaller __Marshaller_ServerReflectionResponse = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Reflection.V1Alpha.ServerReflectionResponse.Parser.ParseFrom); static readonly grpc::Method __Method_ServerReflectionInfo = new grpc::Method( grpc::MethodType.DuplexStreaming, __ServiceName, "ServerReflectionInfo", __Marshaller_ServerReflectionRequest, __Marshaller_ServerReflectionResponse); /// Service descriptor public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor { get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.Services[0]; } } /// Base class for server-side implementations of ServerReflection public abstract partial class ServerReflectionBase { /// /// The reflection service is structured as a bidirectional stream, ensuring /// all related requests go to a single server. /// /// Used for reading requests from the client. /// Used for sending responses back to the client. /// The context of the server-side call handler being invoked. /// A task indicating completion of the handler. public virtual global::System.Threading.Tasks.Task ServerReflectionInfo(grpc::IAsyncStreamReader requestStream, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } } /// Client for ServerReflection public partial class ServerReflectionClient : grpc::ClientBase { /// Creates a new client for ServerReflection /// The channel to use to make remote calls. public ServerReflectionClient(grpc::Channel channel) : base(channel) { } /// Creates a new client for ServerReflection that uses a custom CallInvoker. /// The callInvoker to use to make remote calls. public ServerReflectionClient(grpc::CallInvoker callInvoker) : base(callInvoker) { } /// Protected parameterless constructor to allow creation of test doubles. protected ServerReflectionClient() : base() { } /// Protected constructor to allow creation of configured clients. /// The client configuration. protected ServerReflectionClient(ClientBaseConfiguration configuration) : base(configuration) { } /// /// The reflection service is structured as a bidirectional stream, ensuring /// all related requests go to a single server. /// /// The initial metadata to send with the call. This parameter is optional. /// An optional deadline for the call. The call will be cancelled if deadline is hit. /// An optional token for canceling the call. /// The call object. public virtual grpc::AsyncDuplexStreamingCall ServerReflectionInfo(grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { return ServerReflectionInfo(new grpc::CallOptions(headers, deadline, cancellationToken)); } /// /// The reflection service is structured as a bidirectional stream, ensuring /// all related requests go to a single server. /// /// The options for the call. /// The call object. public virtual grpc::AsyncDuplexStreamingCall ServerReflectionInfo(grpc::CallOptions options) { return CallInvoker.AsyncDuplexStreamingCall(__Method_ServerReflectionInfo, null, options); } /// Creates a new instance of client from given ClientBaseConfiguration. protected override ServerReflectionClient NewInstance(ClientBaseConfiguration configuration) { return new ServerReflectionClient(configuration); } } /// Creates service definition that can be registered with a server /// An object implementing the server-side handling logic. public static grpc::ServerServiceDefinition BindService(ServerReflectionBase serviceImpl) { return grpc::ServerServiceDefinition.CreateBuilder() .AddMethod(__Method_ServerReflectionInfo, serviceImpl.ServerReflectionInfo).Build(); } } } #endregion grpc-1.3.2/src/csharp/Grpc.Reflection/ReflectionServiceImpl.cs000066400000000000000000000160451310511640000242640ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Utils; using Grpc.Reflection.V1Alpha; using Google.Protobuf.Reflection; namespace Grpc.Reflection { /// /// Implementation of server reflection service. /// public class ReflectionServiceImpl : Grpc.Reflection.V1Alpha.ServerReflection.ServerReflectionBase { readonly List services; readonly SymbolRegistry symbolRegistry; /// /// Creates a new instance of ReflectionServiceIml. /// public ReflectionServiceImpl(IEnumerable services, SymbolRegistry symbolRegistry) { this.services = new List(services); this.symbolRegistry = symbolRegistry; } /// /// Creates a new instance of ReflectionServiceIml. /// public ReflectionServiceImpl(IEnumerable serviceDescriptors) { this.services = new List(serviceDescriptors.Select((serviceDescriptor) => serviceDescriptor.FullName)); this.symbolRegistry = SymbolRegistry.FromFiles(serviceDescriptors.Select((serviceDescriptor) => serviceDescriptor.File)); } /// /// Creates a new instance of ReflectionServiceIml. /// public ReflectionServiceImpl(params ServiceDescriptor[] serviceDescriptors) : this((IEnumerable) serviceDescriptors) { } public override async Task ServerReflectionInfo(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) { while (await requestStream.MoveNext()) { var response = ProcessRequest(requestStream.Current); await responseStream.WriteAsync(response); } } ServerReflectionResponse ProcessRequest(ServerReflectionRequest request) { switch (request.MessageRequestCase) { case ServerReflectionRequest.MessageRequestOneofCase.FileByFilename: return FileByFilename(request.FileByFilename); case ServerReflectionRequest.MessageRequestOneofCase.FileContainingSymbol: return FileContainingSymbol(request.FileContainingSymbol); case ServerReflectionRequest.MessageRequestOneofCase.ListServices: return ListServices(); case ServerReflectionRequest.MessageRequestOneofCase.AllExtensionNumbersOfType: case ServerReflectionRequest.MessageRequestOneofCase.FileContainingExtension: default: return CreateErrorResponse(StatusCode.Unimplemented, "Request type not supported by C# reflection service."); } } ServerReflectionResponse FileByFilename(string filename) { FileDescriptor file = symbolRegistry.FileByName(filename); if (file == null) { return CreateErrorResponse(StatusCode.NotFound, "File not found."); } var transitiveDependencies = new HashSet(); CollectTransitiveDependencies(file, transitiveDependencies); return new ServerReflectionResponse { FileDescriptorResponse = new FileDescriptorResponse { FileDescriptorProto = { transitiveDependencies.Select((d) => d.SerializedData) } } }; } ServerReflectionResponse FileContainingSymbol(string symbol) { FileDescriptor file = symbolRegistry.FileContainingSymbol(symbol); if (file == null) { return CreateErrorResponse(StatusCode.NotFound, "Symbol not found."); } var transitiveDependencies = new HashSet(); CollectTransitiveDependencies(file, transitiveDependencies); return new ServerReflectionResponse { FileDescriptorResponse = new FileDescriptorResponse { FileDescriptorProto = { transitiveDependencies.Select((d) => d.SerializedData) } } }; } ServerReflectionResponse ListServices() { var serviceResponses = new ListServiceResponse(); foreach (string serviceName in services) { serviceResponses.Service.Add(new ServiceResponse { Name = serviceName }); } return new ServerReflectionResponse { ListServicesResponse = serviceResponses }; } ServerReflectionResponse CreateErrorResponse(StatusCode status, string message) { return new ServerReflectionResponse { ErrorResponse = new ErrorResponse { ErrorCode = (int) status, ErrorMessage = message } }; } void CollectTransitiveDependencies(FileDescriptor descriptor, HashSet pool) { pool.Add(descriptor); foreach (var dependency in descriptor.Dependencies) { if (pool.Add(dependency)) { // descriptors cannot have circular dependencies CollectTransitiveDependencies(dependency, pool); } } } } } grpc-1.3.2/src/csharp/Grpc.Reflection/Settings.StyleCop000066400000000000000000000004311310511640000227540ustar00rootroot00000000000000 Health.cs False grpc-1.3.2/src/csharp/Grpc.Reflection/SymbolRegistry.cs000066400000000000000000000143641310511640000230270ustar00rootroot00000000000000#region Copyright notice and license // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System.Collections.Generic; using Grpc.Core.Utils; using Google.Protobuf.Reflection; namespace Grpc.Reflection { /// Registry of protobuf symbols public class SymbolRegistry { private readonly Dictionary filesByName; private readonly Dictionary filesBySymbol; private SymbolRegistry(Dictionary filesByName, Dictionary filesBySymbol) { this.filesByName = new Dictionary(filesByName); this.filesBySymbol = new Dictionary(filesBySymbol); } /// /// Creates a symbol registry from the specified set of file descriptors. /// /// The set of files to include in the registry. Must not contain null values. /// A symbol registry for the given files. public static SymbolRegistry FromFiles(IEnumerable fileDescriptors) { GrpcPreconditions.CheckNotNull(fileDescriptors); var builder = new Builder(); foreach (var file in fileDescriptors) { builder.AddFile(file); } return builder.Build(); } /// /// Gets file descriptor for given file name (including package path). Returns null if not found. /// public FileDescriptor FileByName(string filename) { FileDescriptor file; filesByName.TryGetValue(filename, out file); return file; } /// /// Gets file descriptor that contains definition of given symbol full name (including package path). Returns null if not found. /// public FileDescriptor FileContainingSymbol(string symbol) { FileDescriptor file; filesBySymbol.TryGetValue(symbol, out file); return file; } /// /// Builder class which isn't exposed, but acts as a convenient alternative to passing round two dictionaries in recursive calls. /// private class Builder { private readonly Dictionary filesByName; private readonly Dictionary filesBySymbol; internal Builder() { filesByName = new Dictionary(); filesBySymbol = new Dictionary(); } internal void AddFile(FileDescriptor fileDescriptor) { if (filesByName.ContainsKey(fileDescriptor.Name)) { return; } filesByName.Add(fileDescriptor.Name, fileDescriptor); foreach (var dependency in fileDescriptor.Dependencies) { AddFile(dependency); } foreach (var enumeration in fileDescriptor.EnumTypes) { AddEnum(enumeration); } foreach (var message in fileDescriptor.MessageTypes) { AddMessage(message); } foreach (var service in fileDescriptor.Services) { AddService(service); } } private void AddEnum(EnumDescriptor enumDescriptor) { filesBySymbol[enumDescriptor.FullName] = enumDescriptor.File; } private void AddMessage(MessageDescriptor messageDescriptor) { foreach (var nestedEnum in messageDescriptor.EnumTypes) { AddEnum(nestedEnum); } foreach (var nestedType in messageDescriptor.NestedTypes) { AddMessage(nestedType); } filesBySymbol[messageDescriptor.FullName] = messageDescriptor.File; } private void AddService(ServiceDescriptor serviceDescriptor) { foreach (var method in serviceDescriptor.Methods) { filesBySymbol[method.FullName] = method.File; } filesBySymbol[serviceDescriptor.FullName] = serviceDescriptor.File; } internal SymbolRegistry Build() { return new SymbolRegistry(filesByName, filesBySymbol); } } } } grpc-1.3.2/src/csharp/Grpc.Tools.nuspec000066400000000000000000000041561310511640000177250ustar00rootroot00000000000000 Grpc.Tools gRPC C# Tools Tools for C# implementation of gRPC - an RPC library and framework Precompiled protobuf compiler and gRPC protobuf compiler plugin for generating gRPC client/server C# code. Binaries are available for Windows, Linux and MacOS. $version$ Google Inc. grpc-packages https://github.com/grpc/grpc/blob/master/LICENSE https://github.com/grpc/grpc false Release $version$ Copyright 2015, Google Inc. gRPC RPC Protocol HTTP/2 grpc-1.3.2/src/csharp/Grpc.nuspec000066400000000000000000000016041310511640000166210ustar00rootroot00000000000000 Grpc gRPC C# C# implementation of gRPC - an RPC library and framework C# implementation of gRPC - an RPC library and framework. See project site for more info. $version$ Google Inc. grpc-packages https://github.com/grpc/grpc/blob/master/LICENSE https://github.com/grpc/grpc false Release $version$ of gRPC C# Copyright 2015, Google Inc. gRPC RPC Protocol HTTP/2 grpc-1.3.2/src/csharp/Grpc.sln000066400000000000000000000217351310511640000161270ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Core", "Grpc.Core\Grpc.Core.csproj", "{BD878CB3-BDB4-46AB-84EF-C3B4729F56BC}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Auth", "Grpc.Auth\Grpc.Auth.csproj", "{2A16007A-5D67-4C53-BEC8-51E5064D18BF}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Core.Testing", "Grpc.Core.Testing\Grpc.Core.Testing.csproj", "{05DC61DF-26F3-4F51-8577-1ABE4F4388B0}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Core.Tests", "Grpc.Core.Tests\Grpc.Core.Tests.csproj", "{02C79983-6011-43E2-A52D-75F9FC64663F}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Examples", "Grpc.Examples\Grpc.Examples.csproj", "{C643975D-5D26-4860-8002-3B62A132DA2B}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Examples.MathClient", "Grpc.Examples.MathClient\Grpc.Examples.MathClient.csproj", "{1F498972-FD16-4A02-B133-C24652F14869}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Examples.MathServer", "Grpc.Examples.MathServer\Grpc.Examples.MathServer.csproj", "{9F2A873E-83E0-44C4-81D0-DDBC1D36F8B0}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Examples.Tests", "Grpc.Examples.Tests\Grpc.Examples.Tests.csproj", "{7022461C-0D5E-4817-9A5A-3C027FD22457}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.HealthCheck", "Grpc.HealthCheck\Grpc.HealthCheck.csproj", "{DBD57899-0148-4B0D-A8EA-DE3954FA657C}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.HealthCheck.Tests", "Grpc.HealthCheck.Tests\Grpc.HealthCheck.Tests.csproj", "{033E4DC1-5D79-4308-B8B1-9A1B71E39BA1}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.IntegrationTesting", "Grpc.IntegrationTesting\Grpc.IntegrationTesting.csproj", "{CB43BF5B-4D31-4347-A97A-0164B1248B39}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.IntegrationTesting.Client", "Grpc.IntegrationTesting.Client\Grpc.IntegrationTesting.Client.csproj", "{83CCB684-54E6-4552-A00D-3CF9291A1B27}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.IntegrationTesting.QpsWorker", "Grpc.IntegrationTesting.QpsWorker\Grpc.IntegrationTesting.QpsWorker.csproj", "{8ED094CD-DF46-4272-A981-99F3DD184590}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.IntegrationTesting.Server", "Grpc.IntegrationTesting.Server\Grpc.IntegrationTesting.Server.csproj", "{F3A264BE-A62F-4B6A-89A0-7CF7BB275460}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.IntegrationTesting.StressClient", "Grpc.IntegrationTesting.StressClient\Grpc.IntegrationTesting.StressClient.csproj", "{0BB94A8B-9CE3-4A87-95BC-90F8A53CC154}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Reflection", "Grpc.Reflection\Grpc.Reflection.csproj", "{26807744-FD0B-494A-9F99-0B171E9A892E}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Reflection.Tests", "Grpc.Reflection.Tests\Grpc.Reflection.Tests.csproj", "{335AD0A2-F2CC-4C2E-853C-26174206BEE7}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {BD878CB3-BDB4-46AB-84EF-C3B4729F56BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BD878CB3-BDB4-46AB-84EF-C3B4729F56BC}.Debug|Any CPU.Build.0 = Debug|Any CPU {BD878CB3-BDB4-46AB-84EF-C3B4729F56BC}.Release|Any CPU.ActiveCfg = Release|Any CPU {BD878CB3-BDB4-46AB-84EF-C3B4729F56BC}.Release|Any CPU.Build.0 = Release|Any CPU {2A16007A-5D67-4C53-BEC8-51E5064D18BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2A16007A-5D67-4C53-BEC8-51E5064D18BF}.Debug|Any CPU.Build.0 = Debug|Any CPU {2A16007A-5D67-4C53-BEC8-51E5064D18BF}.Release|Any CPU.ActiveCfg = Release|Any CPU {2A16007A-5D67-4C53-BEC8-51E5064D18BF}.Release|Any CPU.Build.0 = Release|Any CPU {05DC61DF-26F3-4F51-8577-1ABE4F4388B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {05DC61DF-26F3-4F51-8577-1ABE4F4388B0}.Debug|Any CPU.Build.0 = Debug|Any CPU {05DC61DF-26F3-4F51-8577-1ABE4F4388B0}.Release|Any CPU.ActiveCfg = Release|Any CPU {05DC61DF-26F3-4F51-8577-1ABE4F4388B0}.Release|Any CPU.Build.0 = Release|Any CPU {02C79983-6011-43E2-A52D-75F9FC64663F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {02C79983-6011-43E2-A52D-75F9FC64663F}.Debug|Any CPU.Build.0 = Debug|Any CPU {02C79983-6011-43E2-A52D-75F9FC64663F}.Release|Any CPU.ActiveCfg = Release|Any CPU {02C79983-6011-43E2-A52D-75F9FC64663F}.Release|Any CPU.Build.0 = Release|Any CPU {C643975D-5D26-4860-8002-3B62A132DA2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C643975D-5D26-4860-8002-3B62A132DA2B}.Debug|Any CPU.Build.0 = Debug|Any CPU {C643975D-5D26-4860-8002-3B62A132DA2B}.Release|Any CPU.ActiveCfg = Release|Any CPU {C643975D-5D26-4860-8002-3B62A132DA2B}.Release|Any CPU.Build.0 = Release|Any CPU {1F498972-FD16-4A02-B133-C24652F14869}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1F498972-FD16-4A02-B133-C24652F14869}.Debug|Any CPU.Build.0 = Debug|Any CPU {1F498972-FD16-4A02-B133-C24652F14869}.Release|Any CPU.ActiveCfg = Release|Any CPU {1F498972-FD16-4A02-B133-C24652F14869}.Release|Any CPU.Build.0 = Release|Any CPU {9F2A873E-83E0-44C4-81D0-DDBC1D36F8B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9F2A873E-83E0-44C4-81D0-DDBC1D36F8B0}.Debug|Any CPU.Build.0 = Debug|Any CPU {9F2A873E-83E0-44C4-81D0-DDBC1D36F8B0}.Release|Any CPU.ActiveCfg = Release|Any CPU {9F2A873E-83E0-44C4-81D0-DDBC1D36F8B0}.Release|Any CPU.Build.0 = Release|Any CPU {7022461C-0D5E-4817-9A5A-3C027FD22457}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7022461C-0D5E-4817-9A5A-3C027FD22457}.Debug|Any CPU.Build.0 = Debug|Any CPU {7022461C-0D5E-4817-9A5A-3C027FD22457}.Release|Any CPU.ActiveCfg = Release|Any CPU {7022461C-0D5E-4817-9A5A-3C027FD22457}.Release|Any CPU.Build.0 = Release|Any CPU {DBD57899-0148-4B0D-A8EA-DE3954FA657C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DBD57899-0148-4B0D-A8EA-DE3954FA657C}.Debug|Any CPU.Build.0 = Debug|Any CPU {DBD57899-0148-4B0D-A8EA-DE3954FA657C}.Release|Any CPU.ActiveCfg = Release|Any CPU {DBD57899-0148-4B0D-A8EA-DE3954FA657C}.Release|Any CPU.Build.0 = Release|Any CPU {033E4DC1-5D79-4308-B8B1-9A1B71E39BA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {033E4DC1-5D79-4308-B8B1-9A1B71E39BA1}.Debug|Any CPU.Build.0 = Debug|Any CPU {033E4DC1-5D79-4308-B8B1-9A1B71E39BA1}.Release|Any CPU.ActiveCfg = Release|Any CPU {033E4DC1-5D79-4308-B8B1-9A1B71E39BA1}.Release|Any CPU.Build.0 = Release|Any CPU {CB43BF5B-4D31-4347-A97A-0164B1248B39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CB43BF5B-4D31-4347-A97A-0164B1248B39}.Debug|Any CPU.Build.0 = Debug|Any CPU {CB43BF5B-4D31-4347-A97A-0164B1248B39}.Release|Any CPU.ActiveCfg = Release|Any CPU {CB43BF5B-4D31-4347-A97A-0164B1248B39}.Release|Any CPU.Build.0 = Release|Any CPU {83CCB684-54E6-4552-A00D-3CF9291A1B27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {83CCB684-54E6-4552-A00D-3CF9291A1B27}.Debug|Any CPU.Build.0 = Debug|Any CPU {83CCB684-54E6-4552-A00D-3CF9291A1B27}.Release|Any CPU.ActiveCfg = Release|Any CPU {83CCB684-54E6-4552-A00D-3CF9291A1B27}.Release|Any CPU.Build.0 = Release|Any CPU {8ED094CD-DF46-4272-A981-99F3DD184590}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8ED094CD-DF46-4272-A981-99F3DD184590}.Debug|Any CPU.Build.0 = Debug|Any CPU {8ED094CD-DF46-4272-A981-99F3DD184590}.Release|Any CPU.ActiveCfg = Release|Any CPU {8ED094CD-DF46-4272-A981-99F3DD184590}.Release|Any CPU.Build.0 = Release|Any CPU {F3A264BE-A62F-4B6A-89A0-7CF7BB275460}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F3A264BE-A62F-4B6A-89A0-7CF7BB275460}.Debug|Any CPU.Build.0 = Debug|Any CPU {F3A264BE-A62F-4B6A-89A0-7CF7BB275460}.Release|Any CPU.ActiveCfg = Release|Any CPU {F3A264BE-A62F-4B6A-89A0-7CF7BB275460}.Release|Any CPU.Build.0 = Release|Any CPU {0BB94A8B-9CE3-4A87-95BC-90F8A53CC154}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0BB94A8B-9CE3-4A87-95BC-90F8A53CC154}.Debug|Any CPU.Build.0 = Debug|Any CPU {0BB94A8B-9CE3-4A87-95BC-90F8A53CC154}.Release|Any CPU.ActiveCfg = Release|Any CPU {0BB94A8B-9CE3-4A87-95BC-90F8A53CC154}.Release|Any CPU.Build.0 = Release|Any CPU {26807744-FD0B-494A-9F99-0B171E9A892E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {26807744-FD0B-494A-9F99-0B171E9A892E}.Debug|Any CPU.Build.0 = Debug|Any CPU {26807744-FD0B-494A-9F99-0B171E9A892E}.Release|Any CPU.ActiveCfg = Release|Any CPU {26807744-FD0B-494A-9F99-0B171E9A892E}.Release|Any CPU.Build.0 = Release|Any CPU {335AD0A2-F2CC-4C2E-853C-26174206BEE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {335AD0A2-F2CC-4C2E-853C-26174206BEE7}.Debug|Any CPU.Build.0 = Debug|Any CPU {335AD0A2-F2CC-4C2E-853C-26174206BEE7}.Release|Any CPU.ActiveCfg = Release|Any CPU {335AD0A2-F2CC-4C2E-853C-26174206BEE7}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal grpc-1.3.2/src/csharp/README.md000066400000000000000000000061471310511640000157750ustar00rootroot00000000000000[![Nuget](https://img.shields.io/nuget/v/Grpc.svg)](http://www.nuget.org/packages/Grpc/) gRPC C# ======= A C# implementation of gRPC. SUPPORTED PLATFORMS ------------------ - [.NET Core](https://dotnet.github.io/) on Linux, Windows and Mac OS X - .NET Framework 4.5+ (Windows) - Mono 4+ on Linux, Windows and Mac OS X PREREQUISITES -------------- When using gRPC C# under .NET Core you only need to [install .NET Core](https://www.microsoft.com/net/core). - Windows: .NET Framework 4.5+, Visual Studio 2013, 2015, 2017 - Linux: Mono 4+, MonoDevelop 5.9+ (with NuGet add-in installed) - Mac OS X: Xamarin Studio 5.9+ HOW TO USE -------------- **Windows, Linux, Mac OS X** - Open Visual Studio / MonoDevelop / Xamarin Studio and start a new project/solution. - Add the [Grpc](https://www.nuget.org/packages/Grpc/) NuGet package as a dependency (Project options -> Manage NuGet Packages). - To be able to generate code from Protocol Buffer (`.proto`) file definitions, add the [Grpc.Tools](https://www.nuget.org/packages/Grpc.Tools/) NuGet package that contains Protocol Buffers compiler (_protoc_) and the gRPC _protoc_ plugin. BUILD FROM SOURCE ----------------- You only need to go through these steps if you are planning to develop gRPC C#. If you are a user of gRPC C#, go to Usage section above. **Windows, Linux or Mac OS X** - The easiest way to build is using the `run_tests.py` script that will take care of building the `grpc_csharp_ext` native library: ``` # from the gRPC repository root $ python tools/run_tests/run_tests.py -c dbg -l csharp --build_only ``` - Use Visual Studio 2017 (on Windows) to open the solution `Grpc.sln` or use Visual Studio Code with C# extension (on Linux and Mac). gRPC C# code has been migrated to dotnet SDK `.csproj` projects that are much simpler to maintain, but are not yet supported by Xamarin Studio or Monodevelop (the NuGet packages still support both `net45` and `netstandard` and can be used in all IDEs). RUNNING TESTS ------------- gRPC C# is using NUnit as the testing framework. Under Visual Studio, make sure NUnit test adapter is installed (under "Extensions and Updates"). Then you should be able to run all the tests using Test Explorer. gRPC team uses a Python script to simplify facilitate running tests for different languages. ``` tools/run_tests/run_tests.py -l csharp ``` DOCUMENTATION ------------- - [API Reference][] - [Helloworld Example][] - [RouteGuide Tutorial][] PERFORMANCE ----------- For best gRPC C# performance, use [.NET Core](https://dotnet.github.io/) and the Server GC mode `"System.GC.Server": true` for your applications. THE NATIVE DEPENDENCY --------------- Internally, gRPC C# uses a native library written in C (gRPC C core) and invokes its functionality via P/Invoke. The fact that a native library is used should be fully transparent to the users and just installing the `Grpc.Core` NuGet package is the only step needed to use gRPC C# on all supported platforms. [API Reference]: http://www.grpc.io/grpc/csharp/ [Helloworld Example]: ../../examples/csharp/helloworld [RouteGuide Tutorial]: http://www.grpc.io/docs/tutorials/basic/csharp.html grpc-1.3.2/src/csharp/Settings.StyleCop000066400000000000000000000463631310511640000200060ustar00rootroot00000000000000 False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False grpc-1.3.2/src/csharp/build_packages_dotnetcli.bat000077500000000000000000000112261310511640000222050ustar00rootroot00000000000000@rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or without @rem modification, are permitted provided that the following conditions are @rem met: @rem @rem * Redistributions of source code must retain the above copyright @rem notice, this list of conditions and the following disclaimer. @rem * Redistributions in binary form must reproduce the above @rem copyright notice, this list of conditions and the following disclaimer @rem in the documentation and/or other materials provided with the @rem distribution. @rem * Neither the name of Google Inc. nor the names of its @rem contributors may be used to endorse or promote products derived from @rem this software without specific prior written permission. @rem @rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS @rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @rem A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT @rem OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, @rem SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT @rem LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, @rem DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY @rem THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT @rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE @rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @rem Current package versions set VERSION=1.3.2 @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe set DOTNET=dotnet set -ex mkdir -p ..\..\artifacts\ @rem Collect the artifacts built by the previous build step if running on Jenkins @rem TODO(jtattermusch): is there a better way to do this? xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=windows\artifacts\* nativelibs\windows_x86\ xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=windows\artifacts\* nativelibs\windows_x64\ xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=linux\artifacts\* nativelibs\linux_x86\ xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=linux\artifacts\* nativelibs\linux_x64\ xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=macos\artifacts\* nativelibs\macosx_x86\ xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=macos\artifacts\* nativelibs\macosx_x64\ @rem Collect protoc artifacts built by the previous build step xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=windows\artifacts\* protoc_plugins\windows_x86\ xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=windows\artifacts\* protoc_plugins\windows_x64\ xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=linux\artifacts\* protoc_plugins\linux_x86\ xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=linux\artifacts\* protoc_plugins\linux_x64\ xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=macos\artifacts\* protoc_plugins\macosx_x86\ xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=macos\artifacts\* protoc_plugins\macosx_x64\ %DOTNET% restore Grpc.sln || goto :error @rem To be able to build, we also need to put grpc_csharp_ext to its normal location xcopy /Y /I nativelibs\windows_x64\grpc_csharp_ext.dll ..\..\cmake\build\x64\Release\ %DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Core --output ..\..\..\artifacts || goto :error %DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Core.Testing --output ..\..\..\artifacts || goto :error %DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Auth --output ..\..\..\artifacts || goto :error %DOTNET% pack --configuration Release --include-symbols --include-source Grpc.HealthCheck --output ..\..\..\artifacts || goto :error %DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Reflection --output ..\..\..\artifacts || goto :error %NUGET% pack Grpc.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts || goto :error %NUGET% pack Grpc.Tools.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts @rem copy resulting nuget packages to artifacts directory xcopy /Y /I *.nupkg ..\..\artifacts\ || goto :error @rem create a zipfile with the artifacts as well powershell -Command "Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('..\..\artifacts', 'csharp_nugets_windows_dotnetcli.zip');" xcopy /Y /I csharp_nugets_windows_dotnetcli.zip ..\..\artifacts\ || goto :error goto :EOF :error echo Failed! exit /b %errorlevel% grpc-1.3.2/src/csharp/build_packages_dotnetcli.sh000077500000000000000000000105051310511640000220500ustar00rootroot00000000000000#!/bin/bash # Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. set -ex cd $(dirname $0) mkdir -p ../../artifacts/ mkdir -p nativelibs/windows_x86 nativelibs/windows_x64 \ nativelibs/linux_x86 nativelibs/linux_x64 \ nativelibs/macosx_x86 nativelibs/macosx_x64 mkdir -p protoc_plugins/windows_x86 protoc_plugins/windows_x64 \ protoc_plugins/linux_x86 protoc_plugins/linux_x64 \ protoc_plugins/macosx_x86 protoc_plugins/macosx_x64 # Collect the artifacts built by the previous build step if running on Jenkins cp $EXTERNAL_GIT_ROOT/architecture=x86,language=csharp,platform=windows/artifacts/* nativelibs/windows_x86 || true cp $EXTERNAL_GIT_ROOT/architecture=x64,language=csharp,platform=windows/artifacts/* nativelibs/windows_x64 || true cp $EXTERNAL_GIT_ROOT/architecture=x86,language=csharp,platform=linux/artifacts/* nativelibs/linux_x86 || true cp $EXTERNAL_GIT_ROOT/architecture=x64,language=csharp,platform=linux/artifacts/* nativelibs/linux_x64 || true cp $EXTERNAL_GIT_ROOT/architecture=x86,language=csharp,platform=macos/artifacts/* nativelibs/macosx_x86 || true cp $EXTERNAL_GIT_ROOT/architecture=x64,language=csharp,platform=macos/artifacts/* nativelibs/macosx_x64 || true # Collect protoc artifacts built by the previous build step cp $EXTERNAL_GIT_ROOT/architecture=x86,language=protoc,platform=windows/artifacts/* protoc_plugins/windows_x86 || true cp $EXTERNAL_GIT_ROOT/architecture=x64,language=protoc,platform=windows/artifacts/* protoc_plugins/windows_x64 || true cp $EXTERNAL_GIT_ROOT/architecture=x86,language=protoc,platform=linux/artifacts/* protoc_plugins/linux_x86 || true cp $EXTERNAL_GIT_ROOT/architecture=x64,language=protoc,platform=linux/artifacts/* protoc_plugins/linux_x64 || true cp $EXTERNAL_GIT_ROOT/architecture=x86,language=protoc,platform=macos/artifacts/* protoc_plugins/macosx_x86 || true cp $EXTERNAL_GIT_ROOT/architecture=x64,language=protoc,platform=macos/artifacts/* protoc_plugins/macosx_x64 || true dotnet restore Grpc.sln # To be able to build, we also need to put grpc_csharp_ext to its normal location mkdir -p ../../libs/opt cp nativelibs/linux_x64/libgrpc_csharp_ext.so ../../libs/opt dotnet pack --configuration Release --include-symbols --include-source Grpc.Core --output ../../../artifacts dotnet pack --configuration Release --include-symbols --include-source Grpc.Core.Testing --output ../../../artifacts dotnet pack --configuration Release --include-symbols --include-source Grpc.Auth --output ../../../artifacts dotnet pack --configuration Release --include-symbols --include-source Grpc.HealthCheck --output ../../../artifacts dotnet pack --configuration Release --include-symbols --include-source Grpc.Reflection --output ../../../artifacts nuget pack Grpc.nuspec -Version "1.3.2" -OutputDirectory ../../artifacts nuget pack Grpc.Tools.nuspec -Version "1.3.2" -OutputDirectory ../../artifacts (cd ../../artifacts && zip csharp_nugets_dotnetcli.zip *.nupkg) grpc-1.3.2/src/csharp/doc/000077500000000000000000000000001310511640000152535ustar00rootroot00000000000000grpc-1.3.2/src/csharp/doc/README.md000066400000000000000000000001031310511640000165240ustar00rootroot00000000000000 SandCastle project files to generate HTML reference documentation.grpc-1.3.2/src/csharp/doc/grpc_csharp_public.shfbproj000066400000000000000000000114221310511640000226430ustar00rootroot00000000000000 Debug AnyCPU 2.0 {77e3da09-fc92-486f-a90a-99ca788e8b59} 2015.6.5.0 Documentation Documentation Documentation .NET Framework 4.5 ..\..\..\doc\ref\csharp\html en-US OnlyWarningsAndErrors Website False True False True 1.0.0.0 2 False Standard Blank True VS2013 False MemberName gRPC C# AboveNamespaces Documentation Provides OAuth2 based authentication for gRPC. <c>Grpc.Auth</c> currently consists of a set of very lightweight wrappers and uses C# <a href="https://www.nuget.org/packages/Google.Apis.Auth/">Google.Apis.Auth</a> library. Main namespace for gRPC C# functionality. Contains concepts representing both client side and server side gRPC logic. <seealso cref="Grpc.Core.Channel"/> <seealso cref="Grpc.Core.Server"/> Provides functionality to redirect gRPC logs to application-specified destination. Various utilities for gRPC C#. Summary, Parameter, AutoDocumentCtors, Namespace, TypeParameter, AutoDocumentDispose OnBuildSuccess grpc-1.3.2/src/csharp/ext/000077500000000000000000000000001310511640000153065ustar00rootroot00000000000000grpc-1.3.2/src/csharp/ext/grpc_csharp_ext.c000066400000000000000000001125651310511640000206370ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "src/core/lib/support/string.h" #include #include #include #include #include #include #include #include #include #include #ifdef GPR_WINDOWS #define GPR_EXPORT __declspec(dllexport) #define GPR_CALLTYPE __stdcall #endif #ifndef GPR_EXPORT #define GPR_EXPORT #endif #ifndef GPR_CALLTYPE #define GPR_CALLTYPE #endif grpc_byte_buffer *string_to_byte_buffer(const char *buffer, size_t len) { grpc_slice slice = grpc_slice_from_copied_buffer(buffer, len); grpc_byte_buffer *bb = grpc_raw_byte_buffer_create(&slice, 1); grpc_slice_unref(slice); return bb; } /* * Helper to maintain lifetime of batch op inputs and store batch op outputs. */ typedef struct grpcsharp_batch_context { grpc_metadata_array send_initial_metadata; grpc_byte_buffer *send_message; struct { grpc_metadata_array trailing_metadata; } send_status_from_server; grpc_metadata_array recv_initial_metadata; grpc_byte_buffer *recv_message; struct { grpc_metadata_array trailing_metadata; grpc_status_code status; grpc_slice status_details; } recv_status_on_client; int recv_close_on_server_cancelled; } grpcsharp_batch_context; GPR_EXPORT grpcsharp_batch_context *GPR_CALLTYPE grpcsharp_batch_context_create() { grpcsharp_batch_context *ctx = gpr_malloc(sizeof(grpcsharp_batch_context)); memset(ctx, 0, sizeof(grpcsharp_batch_context)); return ctx; } typedef struct { grpc_call *call; grpc_call_details call_details; grpc_metadata_array request_metadata; } grpcsharp_request_call_context; GPR_EXPORT grpcsharp_request_call_context *GPR_CALLTYPE grpcsharp_request_call_context_create() { grpcsharp_request_call_context *ctx = gpr_malloc(sizeof(grpcsharp_request_call_context)); memset(ctx, 0, sizeof(grpcsharp_request_call_context)); return ctx; } /* * Destroys array->metadata. * The array pointer itself is not freed. */ void grpcsharp_metadata_array_destroy_metadata_only( grpc_metadata_array *array) { gpr_free(array->metadata); } /* * Destroys keys, values and array->metadata. * The array pointer itself is not freed. */ void grpcsharp_metadata_array_destroy_metadata_including_entries( grpc_metadata_array *array) { size_t i; if (array->metadata) { for (i = 0; i < array->count; i++) { grpc_slice_unref(array->metadata[i].key); grpc_slice_unref(array->metadata[i].value); } } gpr_free(array->metadata); } /* * Fully destroys the metadata array. */ GPR_EXPORT void GPR_CALLTYPE grpcsharp_metadata_array_destroy_full(grpc_metadata_array *array) { if (!array) { return; } grpcsharp_metadata_array_destroy_metadata_including_entries(array); gpr_free(array); } /* * Creates an empty metadata array with given capacity. * Array can later be destroyed by grpc_metadata_array_destroy_full. */ GPR_EXPORT grpc_metadata_array *GPR_CALLTYPE grpcsharp_metadata_array_create(size_t capacity) { grpc_metadata_array *array = (grpc_metadata_array *)gpr_malloc(sizeof(grpc_metadata_array)); grpc_metadata_array_init(array); array->capacity = capacity; array->count = 0; if (capacity > 0) { array->metadata = (grpc_metadata *)gpr_malloc(sizeof(grpc_metadata) * capacity); memset(array->metadata, 0, sizeof(grpc_metadata) * capacity); } else { array->metadata = NULL; } return array; } GPR_EXPORT void GPR_CALLTYPE grpcsharp_metadata_array_add(grpc_metadata_array *array, const char *key, const char *value, size_t value_length) { size_t i = array->count; GPR_ASSERT(array->count < array->capacity); array->metadata[i].key = grpc_slice_from_copied_string(key); array->metadata[i].value = grpc_slice_from_copied_buffer(value, value_length); array->count++; } GPR_EXPORT intptr_t GPR_CALLTYPE grpcsharp_metadata_array_count(grpc_metadata_array *array) { return (intptr_t)array->count; } GPR_EXPORT const char *GPR_CALLTYPE grpcsharp_metadata_array_get_key(grpc_metadata_array *array, size_t index, size_t *key_length) { GPR_ASSERT(index < array->count); *key_length = GRPC_SLICE_LENGTH(array->metadata[index].key); return (char *)GRPC_SLICE_START_PTR(array->metadata[index].key); } GPR_EXPORT const char *GPR_CALLTYPE grpcsharp_metadata_array_get_value(grpc_metadata_array *array, size_t index, size_t *value_length) { GPR_ASSERT(index < array->count); *value_length = GRPC_SLICE_LENGTH(array->metadata[index].value); return (char *)GRPC_SLICE_START_PTR(array->metadata[index].value); } /* Move contents of metadata array */ void grpcsharp_metadata_array_move(grpc_metadata_array *dest, grpc_metadata_array *src) { if (!src) { dest->capacity = 0; dest->count = 0; dest->metadata = NULL; return; } dest->capacity = src->capacity; dest->count = src->count; dest->metadata = src->metadata; src->capacity = 0; src->count = 0; src->metadata = NULL; } GPR_EXPORT void GPR_CALLTYPE grpcsharp_batch_context_destroy(grpcsharp_batch_context *ctx) { if (!ctx) { return; } grpcsharp_metadata_array_destroy_metadata_including_entries( &(ctx->send_initial_metadata)); grpc_byte_buffer_destroy(ctx->send_message); grpcsharp_metadata_array_destroy_metadata_including_entries( &(ctx->send_status_from_server.trailing_metadata)); grpcsharp_metadata_array_destroy_metadata_only(&(ctx->recv_initial_metadata)); grpc_byte_buffer_destroy(ctx->recv_message); grpcsharp_metadata_array_destroy_metadata_only( &(ctx->recv_status_on_client.trailing_metadata)); grpc_slice_unref(ctx->recv_status_on_client.status_details); gpr_free(ctx); } GPR_EXPORT void GPR_CALLTYPE grpcsharp_request_call_context_destroy(grpcsharp_request_call_context *ctx) { if (!ctx) { return; } /* NOTE: ctx->server_rpc_new.call is not destroyed because callback handler is supposed to take its ownership. */ grpc_call_details_destroy(&(ctx->call_details)); grpcsharp_metadata_array_destroy_metadata_only( &(ctx->request_metadata)); gpr_free(ctx); } GPR_EXPORT const grpc_metadata_array *GPR_CALLTYPE grpcsharp_batch_context_recv_initial_metadata( const grpcsharp_batch_context *ctx) { return &(ctx->recv_initial_metadata); } GPR_EXPORT intptr_t GPR_CALLTYPE grpcsharp_batch_context_recv_message_length( const grpcsharp_batch_context *ctx) { grpc_byte_buffer_reader reader; if (!ctx->recv_message) { return -1; } GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, ctx->recv_message)); intptr_t result = (intptr_t)grpc_byte_buffer_length(reader.buffer_out); grpc_byte_buffer_reader_destroy(&reader); return result; } /* * Copies data from recv_message to a buffer. Fatal error occurs if * buffer is too small. */ GPR_EXPORT void GPR_CALLTYPE grpcsharp_batch_context_recv_message_to_buffer( const grpcsharp_batch_context *ctx, char *buffer, size_t buffer_len) { grpc_byte_buffer_reader reader; grpc_slice slice; size_t offset = 0; GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, ctx->recv_message)); while (grpc_byte_buffer_reader_next(&reader, &slice)) { size_t len = GRPC_SLICE_LENGTH(slice); GPR_ASSERT(offset + len <= buffer_len); memcpy(buffer + offset, GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice)); offset += len; grpc_slice_unref(slice); } grpc_byte_buffer_reader_destroy(&reader); } GPR_EXPORT grpc_status_code GPR_CALLTYPE grpcsharp_batch_context_recv_status_on_client_status( const grpcsharp_batch_context *ctx) { return ctx->recv_status_on_client.status; } GPR_EXPORT const char *GPR_CALLTYPE grpcsharp_batch_context_recv_status_on_client_details( const grpcsharp_batch_context *ctx, size_t *details_length) { *details_length = GRPC_SLICE_LENGTH(ctx->recv_status_on_client.status_details); return (char *)GRPC_SLICE_START_PTR(ctx->recv_status_on_client.status_details); } GPR_EXPORT const grpc_metadata_array *GPR_CALLTYPE grpcsharp_batch_context_recv_status_on_client_trailing_metadata( const grpcsharp_batch_context *ctx) { return &(ctx->recv_status_on_client.trailing_metadata); } GPR_EXPORT grpc_call *GPR_CALLTYPE grpcsharp_request_call_context_call( const grpcsharp_request_call_context *ctx) { return ctx->call; } GPR_EXPORT const char *GPR_CALLTYPE grpcsharp_request_call_context_method( const grpcsharp_request_call_context *ctx, size_t *method_length) { *method_length = GRPC_SLICE_LENGTH(ctx->call_details.method); return (char *)GRPC_SLICE_START_PTR(ctx->call_details.method); } GPR_EXPORT const char *GPR_CALLTYPE grpcsharp_request_call_context_host( const grpcsharp_request_call_context *ctx, size_t *host_length) { *host_length = GRPC_SLICE_LENGTH(ctx->call_details.host); return (char *)GRPC_SLICE_START_PTR(ctx->call_details.host); } GPR_EXPORT gpr_timespec GPR_CALLTYPE grpcsharp_request_call_context_deadline( const grpcsharp_request_call_context *ctx) { return ctx->call_details.deadline; } GPR_EXPORT const grpc_metadata_array *GPR_CALLTYPE grpcsharp_request_call_context_request_metadata( const grpcsharp_request_call_context *ctx) { return &(ctx->request_metadata); } GPR_EXPORT int32_t GPR_CALLTYPE grpcsharp_batch_context_recv_close_on_server_cancelled( const grpcsharp_batch_context *ctx) { return (int32_t) ctx->recv_close_on_server_cancelled; } /* Init & shutdown */ GPR_EXPORT void GPR_CALLTYPE grpcsharp_init(void) { grpc_init(); } GPR_EXPORT void GPR_CALLTYPE grpcsharp_shutdown(void) { grpc_shutdown(); } /* Completion queue */ GPR_EXPORT grpc_completion_queue *GPR_CALLTYPE grpcsharp_completion_queue_create(void) { return grpc_completion_queue_create(NULL); } GPR_EXPORT void GPR_CALLTYPE grpcsharp_completion_queue_shutdown(grpc_completion_queue *cq) { grpc_completion_queue_shutdown(cq); } GPR_EXPORT void GPR_CALLTYPE grpcsharp_completion_queue_destroy(grpc_completion_queue *cq) { grpc_completion_queue_destroy(cq); } GPR_EXPORT grpc_event GPR_CALLTYPE grpcsharp_completion_queue_next(grpc_completion_queue *cq) { return grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); } GPR_EXPORT grpc_event GPR_CALLTYPE grpcsharp_completion_queue_pluck(grpc_completion_queue *cq, void *tag) { return grpc_completion_queue_pluck(cq, tag, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); } /* Channel */ GPR_EXPORT grpc_channel *GPR_CALLTYPE grpcsharp_insecure_channel_create(const char *target, const grpc_channel_args *args) { return grpc_insecure_channel_create(target, args, NULL); } GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_destroy(grpc_channel *channel) { grpc_channel_destroy(channel); } GPR_EXPORT grpc_call *GPR_CALLTYPE grpcsharp_channel_create_call(grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_completion_queue *cq, const char *method, const char *host, gpr_timespec deadline) { grpc_slice method_slice = grpc_slice_from_copied_string(method); grpc_slice *host_slice_ptr = NULL; grpc_slice host_slice; if (host != NULL) { host_slice = grpc_slice_from_copied_string(host); host_slice_ptr = &host_slice; } return grpc_channel_create_call(channel, parent_call, propagation_mask, cq, method_slice, host_slice_ptr, deadline, NULL); } GPR_EXPORT grpc_connectivity_state GPR_CALLTYPE grpcsharp_channel_check_connectivity_state(grpc_channel *channel, int32_t try_to_connect) { return grpc_channel_check_connectivity_state(channel, try_to_connect); } GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_watch_connectivity_state( grpc_channel *channel, grpc_connectivity_state last_observed_state, gpr_timespec deadline, grpc_completion_queue *cq, grpcsharp_batch_context *ctx) { grpc_channel_watch_connectivity_state(channel, last_observed_state, deadline, cq, ctx); } GPR_EXPORT char *GPR_CALLTYPE grpcsharp_channel_get_target(grpc_channel *channel) { return grpc_channel_get_target(channel); } /* Channel args */ GPR_EXPORT grpc_channel_args *GPR_CALLTYPE grpcsharp_channel_args_create(size_t num_args) { grpc_channel_args *args = (grpc_channel_args *)gpr_malloc(sizeof(grpc_channel_args)); memset(args, 0, sizeof(grpc_channel_args)); args->num_args = num_args; args->args = (grpc_arg *)gpr_malloc(sizeof(grpc_arg) * num_args); memset(args->args, 0, sizeof(grpc_arg) * num_args); return args; } GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_args_set_string(grpc_channel_args *args, size_t index, const char *key, const char *value) { GPR_ASSERT(args); GPR_ASSERT(index < args->num_args); args->args[index].type = GRPC_ARG_STRING; args->args[index].key = gpr_strdup(key); args->args[index].value.string = gpr_strdup(value); } GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_args_set_integer(grpc_channel_args *args, size_t index, const char *key, int value) { GPR_ASSERT(args); GPR_ASSERT(index < args->num_args); args->args[index].type = GRPC_ARG_INTEGER; args->args[index].key = gpr_strdup(key); args->args[index].value.integer = value; } GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_args_destroy(grpc_channel_args *args) { size_t i; if (args) { for (i = 0; i < args->num_args; i++) { gpr_free(args->args[i].key); if (args->args[i].type == GRPC_ARG_STRING) { gpr_free(args->args[i].value.string); } } gpr_free(args->args); gpr_free(args); } } /* Timespec */ GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_now(gpr_clock_type clock_type) { return gpr_now(clock_type); } GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_inf_future(gpr_clock_type clock_type) { return gpr_inf_future(clock_type); } GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_inf_past(gpr_clock_type clock_type) { return gpr_inf_past(clock_type); } GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_convert_clock_type(gpr_timespec t, gpr_clock_type target_clock) { return gpr_convert_clock_type(t, target_clock); } GPR_EXPORT int32_t GPR_CALLTYPE gprsharp_sizeof_timespec(void) { return sizeof(gpr_timespec); } /* Call */ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_cancel(grpc_call *call) { return grpc_call_cancel(call, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_cancel_with_status(grpc_call *call, grpc_status_code status, const char *description) { return grpc_call_cancel_with_status(call, status, description, NULL); } GPR_EXPORT char *GPR_CALLTYPE grpcsharp_call_get_peer(grpc_call *call) { return grpc_call_get_peer(call); } GPR_EXPORT void GPR_CALLTYPE gprsharp_free(void *p) { gpr_free(p); } GPR_EXPORT void GPR_CALLTYPE grpcsharp_call_destroy(grpc_call *call) { grpc_call_destroy(call); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_unary(grpc_call *call, grpcsharp_batch_context *ctx, const char *send_buffer, size_t send_buffer_len, uint32_t write_flags, grpc_metadata_array *initial_metadata, uint32_t initial_metadata_flags) { /* TODO: don't use magic number */ grpc_op ops[6]; memset(ops, 0, sizeof(ops)); ops[0].op = GRPC_OP_SEND_INITIAL_METADATA; grpcsharp_metadata_array_move(&(ctx->send_initial_metadata), initial_metadata); ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count; ops[0].data.send_initial_metadata.metadata = ctx->send_initial_metadata.metadata; ops[0].flags = initial_metadata_flags; ops[0].reserved = NULL; ops[1].op = GRPC_OP_SEND_MESSAGE; ctx->send_message = string_to_byte_buffer(send_buffer, send_buffer_len); ops[1].data.send_message.send_message = ctx->send_message; ops[1].flags = write_flags; ops[1].reserved = NULL; ops[2].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; ops[2].flags = 0; ops[2].reserved = NULL; ops[3].op = GRPC_OP_RECV_INITIAL_METADATA; ops[3].data.recv_initial_metadata.recv_initial_metadata = &(ctx->recv_initial_metadata); ops[3].flags = 0; ops[3].reserved = NULL; ops[4].op = GRPC_OP_RECV_MESSAGE; ops[4].data.recv_message.recv_message = &(ctx->recv_message); ops[4].flags = 0; ops[4].reserved = NULL; ops[5].op = GRPC_OP_RECV_STATUS_ON_CLIENT; ops[5].data.recv_status_on_client.trailing_metadata = &(ctx->recv_status_on_client.trailing_metadata); ops[5].data.recv_status_on_client.status = &(ctx->recv_status_on_client.status); ops[5].data.recv_status_on_client.status_details = &(ctx->recv_status_on_client.status_details); ops[5].flags = 0; ops[5].reserved = NULL; return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_client_streaming(grpc_call *call, grpcsharp_batch_context *ctx, grpc_metadata_array *initial_metadata, uint32_t initial_metadata_flags) { /* TODO: don't use magic number */ grpc_op ops[4]; memset(ops, 0, sizeof(ops)); ops[0].op = GRPC_OP_SEND_INITIAL_METADATA; grpcsharp_metadata_array_move(&(ctx->send_initial_metadata), initial_metadata); ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count; ops[0].data.send_initial_metadata.metadata = ctx->send_initial_metadata.metadata; ops[0].flags = initial_metadata_flags; ops[0].reserved = NULL; ops[1].op = GRPC_OP_RECV_INITIAL_METADATA; ops[1].data.recv_initial_metadata.recv_initial_metadata = &(ctx->recv_initial_metadata); ops[1].flags = 0; ops[1].reserved = NULL; ops[2].op = GRPC_OP_RECV_MESSAGE; ops[2].data.recv_message.recv_message = &(ctx->recv_message); ops[2].flags = 0; ops[2].reserved = NULL; ops[3].op = GRPC_OP_RECV_STATUS_ON_CLIENT; ops[3].data.recv_status_on_client.trailing_metadata = &(ctx->recv_status_on_client.trailing_metadata); ops[3].data.recv_status_on_client.status = &(ctx->recv_status_on_client.status); ops[3].data.recv_status_on_client.status_details = &(ctx->recv_status_on_client.status_details); ops[3].flags = 0; ops[3].reserved = NULL; return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming( grpc_call *call, grpcsharp_batch_context *ctx, const char *send_buffer, size_t send_buffer_len, uint32_t write_flags, grpc_metadata_array *initial_metadata, uint32_t initial_metadata_flags) { /* TODO: don't use magic number */ grpc_op ops[4]; memset(ops, 0, sizeof(ops)); ops[0].op = GRPC_OP_SEND_INITIAL_METADATA; grpcsharp_metadata_array_move(&(ctx->send_initial_metadata), initial_metadata); ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count; ops[0].data.send_initial_metadata.metadata = ctx->send_initial_metadata.metadata; ops[0].flags = initial_metadata_flags; ops[0].reserved = NULL; ops[1].op = GRPC_OP_SEND_MESSAGE; ctx->send_message = string_to_byte_buffer(send_buffer, send_buffer_len); ops[1].data.send_message.send_message = ctx->send_message; ops[1].flags = write_flags; ops[1].reserved = NULL; ops[2].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; ops[2].flags = 0; ops[2].reserved = NULL; ops[3].op = GRPC_OP_RECV_STATUS_ON_CLIENT; ops[3].data.recv_status_on_client.trailing_metadata = &(ctx->recv_status_on_client.trailing_metadata); ops[3].data.recv_status_on_client.status = &(ctx->recv_status_on_client.status); ops[3].data.recv_status_on_client.status_details = &(ctx->recv_status_on_client.status_details); ops[3].flags = 0; ops[3].reserved = NULL; return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_duplex_streaming(grpc_call *call, grpcsharp_batch_context *ctx, grpc_metadata_array *initial_metadata, uint32_t initial_metadata_flags) { /* TODO: don't use magic number */ grpc_op ops[2]; memset(ops, 0, sizeof(ops)); ops[0].op = GRPC_OP_SEND_INITIAL_METADATA; grpcsharp_metadata_array_move(&(ctx->send_initial_metadata), initial_metadata); ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count; ops[0].data.send_initial_metadata.metadata = ctx->send_initial_metadata.metadata; ops[0].flags = initial_metadata_flags; ops[0].reserved = NULL; ops[1].op = GRPC_OP_RECV_STATUS_ON_CLIENT; ops[1].data.recv_status_on_client.trailing_metadata = &(ctx->recv_status_on_client.trailing_metadata); ops[1].data.recv_status_on_client.status = &(ctx->recv_status_on_client.status); ops[1].data.recv_status_on_client.status_details = &(ctx->recv_status_on_client.status_details); ops[1].flags = 0; ops[1].reserved = NULL; return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_recv_initial_metadata( grpc_call *call, grpcsharp_batch_context *ctx) { /* TODO: don't use magic number */ grpc_op ops[1]; ops[0].op = GRPC_OP_RECV_INITIAL_METADATA; ops[0].data.recv_initial_metadata.recv_initial_metadata = &(ctx->recv_initial_metadata); ops[0].flags = 0; ops[0].reserved = NULL; return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_message(grpc_call *call, grpcsharp_batch_context *ctx, const char *send_buffer, size_t send_buffer_len, uint32_t write_flags, int32_t send_empty_initial_metadata) { /* TODO: don't use magic number */ grpc_op ops[2]; memset(ops, 0, sizeof(ops)); size_t nops = send_empty_initial_metadata ? 2 : 1; ops[0].op = GRPC_OP_SEND_MESSAGE; ctx->send_message = string_to_byte_buffer(send_buffer, send_buffer_len); ops[0].data.send_message.send_message = ctx->send_message; ops[0].flags = write_flags; ops[0].reserved = NULL; ops[1].op = GRPC_OP_SEND_INITIAL_METADATA; ops[1].flags = 0; ops[1].reserved = NULL; return grpc_call_start_batch(call, ops, nops, ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_close_from_client(grpc_call *call, grpcsharp_batch_context *ctx) { /* TODO: don't use magic number */ grpc_op ops[1]; ops[0].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; ops[0].flags = 0; ops[0].reserved = NULL; return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_status_from_server( grpc_call *call, grpcsharp_batch_context *ctx, grpc_status_code status_code, const char *status_details, size_t status_details_len, grpc_metadata_array *trailing_metadata, int32_t send_empty_initial_metadata, const char* optional_send_buffer, size_t optional_send_buffer_len, uint32_t write_flags) { /* TODO: don't use magic number */ grpc_op ops[3]; memset(ops, 0, sizeof(ops)); size_t nops = 1; grpc_slice status_details_slice = grpc_slice_from_copied_buffer(status_details, status_details_len); ops[0].op = GRPC_OP_SEND_STATUS_FROM_SERVER; ops[0].data.send_status_from_server.status = status_code; ops[0].data.send_status_from_server.status_details = &status_details_slice; grpcsharp_metadata_array_move( &(ctx->send_status_from_server.trailing_metadata), trailing_metadata); ops[0].data.send_status_from_server.trailing_metadata_count = ctx->send_status_from_server.trailing_metadata.count; ops[0].data.send_status_from_server.trailing_metadata = ctx->send_status_from_server.trailing_metadata.metadata; ops[0].flags = 0; ops[0].reserved = NULL; if (optional_send_buffer) { ops[nops].op = GRPC_OP_SEND_MESSAGE; ctx->send_message = string_to_byte_buffer(optional_send_buffer, optional_send_buffer_len); ops[nops].data.send_message.send_message = ctx->send_message; ops[nops].flags = write_flags; ops[nops].reserved = NULL; nops++; } if (send_empty_initial_metadata) { ops[nops].op = GRPC_OP_SEND_INITIAL_METADATA; ops[nops].flags = 0; ops[nops].reserved = NULL; nops++; } return grpc_call_start_batch(call, ops, nops, ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_recv_message(grpc_call *call, grpcsharp_batch_context *ctx) { /* TODO: don't use magic number */ grpc_op ops[1]; ops[0].op = GRPC_OP_RECV_MESSAGE; ops[0].data.recv_message.recv_message = &(ctx->recv_message); ops[0].flags = 0; ops[0].reserved = NULL; return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_serverside(grpc_call *call, grpcsharp_batch_context *ctx) { /* TODO: don't use magic number */ grpc_op ops[1]; ops[0].op = GRPC_OP_RECV_CLOSE_ON_SERVER; ops[0].data.recv_close_on_server.cancelled = (&ctx->recv_close_on_server_cancelled); ops[0].flags = 0; ops[0].reserved = NULL; return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_initial_metadata(grpc_call *call, grpcsharp_batch_context *ctx, grpc_metadata_array *initial_metadata) { /* TODO: don't use magic number */ grpc_op ops[1]; memset(ops, 0, sizeof(ops)); ops[0].op = GRPC_OP_SEND_INITIAL_METADATA; grpcsharp_metadata_array_move(&(ctx->send_initial_metadata), initial_metadata); ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count; ops[0].data.send_initial_metadata.metadata = ctx->send_initial_metadata.metadata; ops[0].flags = 0; ops[0].reserved = NULL; return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_set_credentials( grpc_call *call, grpc_call_credentials *creds) { return grpc_call_set_credentials(call, creds); } /* Server */ GPR_EXPORT grpc_server *GPR_CALLTYPE grpcsharp_server_create(const grpc_channel_args *args) { return grpc_server_create(args, NULL); } GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_register_completion_queue(grpc_server *server, grpc_completion_queue *cq) { grpc_server_register_completion_queue(server, cq, NULL); } GPR_EXPORT int32_t GPR_CALLTYPE grpcsharp_server_add_insecure_http2_port(grpc_server *server, const char *addr) { return grpc_server_add_insecure_http2_port(server, addr); } GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_start(grpc_server *server) { grpc_server_start(server); } GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_shutdown_and_notify_callback(grpc_server *server, grpc_completion_queue *cq, grpcsharp_batch_context *ctx) { grpc_server_shutdown_and_notify(server, cq, ctx); } GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_cancel_all_calls(grpc_server *server) { grpc_server_cancel_all_calls(server); } GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_destroy(grpc_server *server) { grpc_server_destroy(server); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_server_request_call(grpc_server *server, grpc_completion_queue *cq, grpcsharp_request_call_context *ctx) { return grpc_server_request_call( server, &(ctx->call), &(ctx->call_details), &(ctx->request_metadata), cq, cq, ctx); } /* Security */ static char *default_pem_root_certs = NULL; static grpc_ssl_roots_override_result override_ssl_roots_handler( char **pem_root_certs) { if (!default_pem_root_certs) { *pem_root_certs = NULL; return GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY; } *pem_root_certs = gpr_strdup(default_pem_root_certs); return GRPC_SSL_ROOTS_OVERRIDE_OK; } GPR_EXPORT void GPR_CALLTYPE grpcsharp_override_default_ssl_roots( const char *pem_root_certs) { /* * This currently wastes ~300kB of memory by keeping a copy of roots * in a static variable, but for desktop/server use, the overhead * is negligible. In the future, we might want to change the behavior * for mobile (e.g. Xamarin). */ default_pem_root_certs = gpr_strdup(pem_root_certs); grpc_set_ssl_roots_override_callback(override_ssl_roots_handler); } GPR_EXPORT grpc_channel_credentials *GPR_CALLTYPE grpcsharp_ssl_credentials_create(const char *pem_root_certs, const char *key_cert_pair_cert_chain, const char *key_cert_pair_private_key) { grpc_ssl_pem_key_cert_pair key_cert_pair; if (key_cert_pair_cert_chain || key_cert_pair_private_key) { key_cert_pair.cert_chain = key_cert_pair_cert_chain; key_cert_pair.private_key = key_cert_pair_private_key; return grpc_ssl_credentials_create(pem_root_certs, &key_cert_pair, NULL); } else { GPR_ASSERT(!key_cert_pair_cert_chain); GPR_ASSERT(!key_cert_pair_private_key); return grpc_ssl_credentials_create(pem_root_certs, NULL, NULL); } } GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_credentials_release( grpc_channel_credentials *creds) { grpc_channel_credentials_release(creds); } GPR_EXPORT void GPR_CALLTYPE grpcsharp_call_credentials_release( grpc_call_credentials *creds) { grpc_call_credentials_release(creds); } GPR_EXPORT grpc_channel *GPR_CALLTYPE grpcsharp_secure_channel_create(grpc_channel_credentials *creds, const char *target, const grpc_channel_args *args) { return grpc_secure_channel_create(creds, target, args, NULL); } GPR_EXPORT grpc_server_credentials *GPR_CALLTYPE grpcsharp_ssl_server_credentials_create( const char *pem_root_certs, const char **key_cert_pair_cert_chain_array, const char **key_cert_pair_private_key_array, size_t num_key_cert_pairs, int force_client_auth) { size_t i; grpc_server_credentials *creds; grpc_ssl_pem_key_cert_pair *key_cert_pairs = gpr_malloc(sizeof(grpc_ssl_pem_key_cert_pair) * num_key_cert_pairs); memset(key_cert_pairs, 0, sizeof(grpc_ssl_pem_key_cert_pair) * num_key_cert_pairs); for (i = 0; i < num_key_cert_pairs; i++) { if (key_cert_pair_cert_chain_array[i] || key_cert_pair_private_key_array[i]) { key_cert_pairs[i].cert_chain = key_cert_pair_cert_chain_array[i]; key_cert_pairs[i].private_key = key_cert_pair_private_key_array[i]; } } creds = grpc_ssl_server_credentials_create_ex( pem_root_certs, key_cert_pairs, num_key_cert_pairs, force_client_auth ? GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY : GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, NULL); gpr_free(key_cert_pairs); return creds; } GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_credentials_release( grpc_server_credentials *creds) { grpc_server_credentials_release(creds); } GPR_EXPORT int32_t GPR_CALLTYPE grpcsharp_server_add_secure_http2_port(grpc_server *server, const char *addr, grpc_server_credentials *creds) { return grpc_server_add_secure_http2_port(server, addr, creds); } GPR_EXPORT grpc_channel_credentials *GPR_CALLTYPE grpcsharp_composite_channel_credentials_create( grpc_channel_credentials *channel_creds, grpc_call_credentials *call_creds) { return grpc_composite_channel_credentials_create(channel_creds, call_creds, NULL); } GPR_EXPORT grpc_call_credentials *GPR_CALLTYPE grpcsharp_composite_call_credentials_create( grpc_call_credentials *creds1, grpc_call_credentials *creds2) { return grpc_composite_call_credentials_create(creds1, creds2, NULL); } /* Metadata credentials plugin */ GPR_EXPORT void GPR_CALLTYPE grpcsharp_metadata_credentials_notify_from_plugin( grpc_credentials_plugin_metadata_cb cb, void *user_data, grpc_metadata_array *metadata, grpc_status_code status, const char *error_details) { if (metadata) { cb(user_data, metadata->metadata, metadata->count, status, error_details); } else { cb(user_data, NULL, 0, status, error_details); } } typedef void(GPR_CALLTYPE *grpcsharp_metadata_interceptor_func)( void *state, const char *service_url, const char *method_name, grpc_credentials_plugin_metadata_cb cb, void *user_data, int32_t is_destroy); static void grpcsharp_get_metadata_handler( void *state, grpc_auth_metadata_context context, grpc_credentials_plugin_metadata_cb cb, void *user_data) { grpcsharp_metadata_interceptor_func interceptor = (grpcsharp_metadata_interceptor_func)(intptr_t)state; interceptor(state, context.service_url, context.method_name, cb, user_data, 0); } static void grpcsharp_metadata_credentials_destroy_handler(void *state) { grpcsharp_metadata_interceptor_func interceptor = (grpcsharp_metadata_interceptor_func)(intptr_t)state; interceptor(state, NULL, NULL, NULL, NULL, 1); } GPR_EXPORT grpc_call_credentials *GPR_CALLTYPE grpcsharp_metadata_credentials_create_from_plugin( grpcsharp_metadata_interceptor_func metadata_interceptor) { grpc_metadata_credentials_plugin plugin; plugin.get_metadata = grpcsharp_get_metadata_handler; plugin.destroy = grpcsharp_metadata_credentials_destroy_handler; plugin.state = (void*)(intptr_t)metadata_interceptor; plugin.type = ""; return grpc_metadata_credentials_create_from_plugin(plugin, NULL); } /* Auth context */ GPR_EXPORT grpc_auth_context *GPR_CALLTYPE grpcsharp_call_auth_context(grpc_call *call) { return grpc_call_auth_context(call); } GPR_EXPORT const char *GPR_CALLTYPE grpcsharp_auth_context_peer_identity_property_name( const grpc_auth_context *ctx) { return grpc_auth_context_peer_identity_property_name(ctx); } GPR_EXPORT grpc_auth_property_iterator GPR_CALLTYPE grpcsharp_auth_context_property_iterator(const grpc_auth_context *ctx) { return grpc_auth_context_property_iterator(ctx); } GPR_EXPORT const grpc_auth_property *GPR_CALLTYPE grpcsharp_auth_property_iterator_next( grpc_auth_property_iterator *it) { return grpc_auth_property_iterator_next(it); } GPR_EXPORT void GPR_CALLTYPE grpcsharp_auth_context_release(grpc_auth_context *ctx) { grpc_auth_context_release(ctx); } /* Logging */ typedef void(GPR_CALLTYPE *grpcsharp_log_func)(const char *file, int32_t line, uint64_t thd_id, const char *severity_string, const char *msg); static grpcsharp_log_func log_func = NULL; /* Redirects gpr_log to log_func callback */ static void grpcsharp_log_handler(gpr_log_func_args *args) { log_func(args->file, args->line, gpr_thd_currentid(), gpr_log_severity_string(args->severity), args->message); } GPR_EXPORT void GPR_CALLTYPE grpcsharp_redirect_log(grpcsharp_log_func func) { GPR_ASSERT(func); log_func = func; gpr_set_log_function(grpcsharp_log_handler); } typedef void(GPR_CALLTYPE *test_callback_funcptr)(int32_t success); /* Version info */ GPR_EXPORT const char *GPR_CALLTYPE grpcsharp_version_string() { return grpc_version_string(); } /* For testing */ GPR_EXPORT void GPR_CALLTYPE grpcsharp_test_callback(test_callback_funcptr callback) { callback(1); } /* For testing */ GPR_EXPORT void *GPR_CALLTYPE grpcsharp_test_nop(void *ptr) { return ptr; } /* For testing */ GPR_EXPORT int32_t GPR_CALLTYPE grpcsharp_sizeof_grpc_event(void) { return sizeof(grpc_event); } grpc-1.3.2/src/csharp/generate_proto_csharp.sh000077500000000000000000000051421310511640000214240ustar00rootroot00000000000000#!/bin/sh # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Regenerates gRPC service stubs from proto files. set +e cd $(dirname $0)/../.. PROTOC=bins/opt/protobuf/protoc PLUGIN=protoc-gen-grpc=bins/opt/grpc_csharp_plugin EXAMPLES_DIR=src/csharp/Grpc.Examples HEALTHCHECK_DIR=src/csharp/Grpc.HealthCheck REFLECTION_DIR=src/csharp/Grpc.Reflection TESTING_DIR=src/csharp/Grpc.IntegrationTesting $PROTOC --plugin=$PLUGIN --csharp_out=$EXAMPLES_DIR --grpc_out=$EXAMPLES_DIR \ -I src/proto src/proto/math/math.proto $PROTOC --plugin=$PLUGIN --csharp_out=$HEALTHCHECK_DIR --grpc_out=$HEALTHCHECK_DIR \ -I src/proto src/proto/grpc/health/v1/health.proto $PROTOC --plugin=$PLUGIN --csharp_out=$REFLECTION_DIR --grpc_out=$REFLECTION_DIR \ -I src/proto src/proto/grpc/reflection/v1alpha/reflection.proto # TODO(jtattermusch): following .proto files are a bit broken and import paths # don't match the package names. Setting -I to the correct value src/proto # breaks the code generation. $PROTOC --plugin=$PLUGIN --csharp_out=$TESTING_DIR --grpc_out=$TESTING_DIR \ -I . src/proto/grpc/testing/{control,empty,messages,metrics,payloads,services,stats,test}.proto grpc-1.3.2/src/csharp/keys/000077500000000000000000000000001310511640000154615ustar00rootroot00000000000000grpc-1.3.2/src/csharp/keys/Grpc.public.snk000066400000000000000000000002401310511640000203420ustar00rootroot00000000000000$€”$RSA1/W—©,oÍèÔ CB»Žv‡"Þ ±±^•[2¡RtåŸ,”ÄŽÜŽ}RSkŠÆQ¼áåÚ:'ü•¯óÜ`JiqAtSùH<{^ƒgVÕ²q¿$þn1•aHÀ=€D‡Ïd/ŒÀq9Nég-þ[Uê•ßÕ§÷}"ÉbÌõ Ógrpc-1.3.2/src/csharp/keys/Grpc.snk000066400000000000000000000011241310511640000170670ustar00rootroot00000000000000$RSA2/W—©,oÍèÔ CB»Žv‡"Þ ±±^•[2¡RtåŸ,”ÄŽÜŽ}RSkŠÆQ¼áåÚ:'ü•¯óÜ`JiqAtSùH<{^ƒgVÕ²q¿$þn1•aHÀ=€D‡Ïd/ŒÀq9Nég-þ[Uê•ßÕ§÷}"ÉbÌõ Ó‡>H[.¡E\J´ž±z"FCó¡#ÍQÒè` PвIHÐñ–ý<ÔÜ êVëå”û“8Úæ±HÉz†î'_CyûäŸ^“x¡®ŸÀS!ß‹Òì$cÝø¾Ã”†‘tüT¯Áy®¥²‘J±T%ÔJ‹-GùMºs© žÓêåìÖ›°¿Ên2çi2—4Ç‘+ÙOâbÁ².‚ÐUl JµÕÝ-+õ–®BB,ÃÍš;1Þ穼¦Jò×/Iòš£eÑ p€ºª¯_#'˜±ö†ø–ŒØëüs‡å¯ð °grpc-1.3.2/src/csharp/keys/README.md000066400000000000000000000004401310511640000167360ustar00rootroot00000000000000Contents -------- - Grpc.public.snk: Public key to verify strong name of gRPC assemblies. - Grpc.snk: Signing key to provide strong name of gRPC assemblies. As per https://msdn.microsoft.com/en-us/library/wd40t7ad(v=vs.110).aspx signing key should be checked into the repository.grpc-1.3.2/src/csharp/tests.json000066400000000000000000000042441310511640000165470ustar00rootroot00000000000000{ "Grpc.Core.Tests": [ "Grpc.Core.Internal.Tests.AsyncCallServerTest", "Grpc.Core.Internal.Tests.AsyncCallTest", "Grpc.Core.Internal.Tests.ChannelArgsSafeHandleTest", "Grpc.Core.Internal.Tests.CompletionQueueEventTest", "Grpc.Core.Internal.Tests.CompletionQueueSafeHandleTest", "Grpc.Core.Internal.Tests.MetadataArraySafeHandleTest", "Grpc.Core.Internal.Tests.TimespecTest", "Grpc.Core.Tests.AppDomainUnloadTest", "Grpc.Core.Tests.AuthContextTest", "Grpc.Core.Tests.AuthPropertyTest", "Grpc.Core.Tests.CallCredentialsTest", "Grpc.Core.Tests.CallOptionsTest", "Grpc.Core.Tests.ChannelCredentialsTest", "Grpc.Core.Tests.ChannelOptionsTest", "Grpc.Core.Tests.ChannelTest", "Grpc.Core.Tests.ClientServerTest", "Grpc.Core.Tests.CompressionTest", "Grpc.Core.Tests.ContextPropagationTest", "Grpc.Core.Tests.GrpcEnvironmentTest", "Grpc.Core.Tests.HalfcloseTest", "Grpc.Core.Tests.MarshallingErrorsTest", "Grpc.Core.Tests.MetadataTest", "Grpc.Core.Tests.PerformanceTest", "Grpc.Core.Tests.PInvokeTest", "Grpc.Core.Tests.ResponseHeadersTest", "Grpc.Core.Tests.SanityTest", "Grpc.Core.Tests.ServerTest", "Grpc.Core.Tests.ShutdownHookClientTest", "Grpc.Core.Tests.ShutdownHookPendingCallTest", "Grpc.Core.Tests.ShutdownHookServerTest", "Grpc.Core.Tests.ShutdownTest", "Grpc.Core.Tests.TimeoutsTest", "Grpc.Core.Tests.UserAgentStringTest" ], "Grpc.Examples.Tests": [ "Math.Tests.MathClientServerTest" ], "Grpc.HealthCheck.Tests": [ "Grpc.HealthCheck.Tests.HealthClientServerTest", "Grpc.HealthCheck.Tests.HealthServiceImplTest" ], "Grpc.IntegrationTesting": [ "Grpc.IntegrationTesting.GeneratedClientTest", "Grpc.IntegrationTesting.GeneratedServiceBaseTest", "Grpc.IntegrationTesting.HistogramTest", "Grpc.IntegrationTesting.InteropClientServerTest", "Grpc.IntegrationTesting.MetadataCredentialsTest", "Grpc.IntegrationTesting.RunnerClientServerTest", "Grpc.IntegrationTesting.SslCredentialsTest" ], "Grpc.Reflection.Tests": [ "Grpc.Reflection.Tests.ReflectionClientServerTest", "Grpc.Reflection.Tests.SymbolRegistryTest" ] }grpc-1.3.2/src/node/000077500000000000000000000000001310511640000141535ustar00rootroot00000000000000grpc-1.3.2/src/node/.jshintignore000066400000000000000000000000121310511640000166500ustar00rootroot00000000000000**/*_pb.jsgrpc-1.3.2/src/node/README.md000066400000000000000000000063371310511640000154430ustar00rootroot00000000000000[![npm](https://img.shields.io/npm/v/grpc.svg)](https://www.npmjs.com/package/grpc) # Node.js gRPC Library ## 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. - **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). ## INSTALLATION Install the gRPC NPM package ```sh npm install grpc ``` ## BUILD FROM SOURCE 1. Clone [the grpc Git Repository](https://github.com/grpc/grpc). 2. Run `npm install` 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): ``` .. Building the projects in this solution one at a time. To enable parallel build, please add the "/m" switch. WINDOWS_BUILD_WARNING "..\IMPORTANT: Due to https:\github.com\nodejs\node\issues\4932, to build this library on Windows, you must first remove C:\Users\jenkins\.node-gyp\4.4.0\include\node\openssl" ... .. ``` To fix this, you will have to delete the folder `C:\Users\\.node-gyp\\include\node\openssl` and retry `npm install` ## TESTING 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. grpc-1.3.2/src/node/ext/000077500000000000000000000000001310511640000147535ustar00rootroot00000000000000grpc-1.3.2/src/node/ext/byte_buffer.cc000066400000000000000000000061001310511640000175530ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include "grpc/grpc.h" #include "grpc/byte_buffer_reader.h" #include "grpc/slice.h" #include "byte_buffer.h" #include "slice.h" namespace grpc { namespace node { using Nan::Callback; using Nan::MaybeLocal; using v8::Function; using v8::Local; using v8::Object; using v8::Number; using v8::Value; grpc_byte_buffer *BufferToByteBuffer(Local buffer) { Nan::HandleScope scope; grpc_slice slice = CreateSliceFromBuffer(buffer); grpc_byte_buffer *byte_buffer(grpc_raw_byte_buffer_create(&slice, 1)); grpc_slice_unref(slice); return byte_buffer; } namespace { void delete_buffer(char *data, void *hint) { grpc_slice *slice = static_cast(hint); grpc_slice_unref(*slice); delete slice; } } Local ByteBufferToBuffer(grpc_byte_buffer *buffer) { Nan::EscapableHandleScope scope; if (buffer == NULL) { return scope.Escape(Nan::Null()); } grpc_byte_buffer_reader reader; if (!grpc_byte_buffer_reader_init(&reader, buffer)) { Nan::ThrowError("Error initializing byte buffer reader."); return scope.Escape(Nan::Undefined()); } grpc_slice *slice = new grpc_slice; *slice = grpc_byte_buffer_reader_readall(&reader); grpc_byte_buffer_reader_destroy(&reader); char *result = reinterpret_cast(GRPC_SLICE_START_PTR(*slice)); size_t length = GRPC_SLICE_LENGTH(*slice); Local buf = Nan::NewBuffer(result, length, delete_buffer, slice).ToLocalChecked(); return scope.Escape(buf); } } // namespace node } // namespace grpc grpc-1.3.2/src/node/ext/byte_buffer.h000066400000000000000000000041311310511640000174170ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef NET_GRPC_NODE_BYTE_BUFFER_H_ #define NET_GRPC_NODE_BYTE_BUFFER_H_ #include #include #include #include "grpc/grpc.h" namespace grpc { namespace node { /* Convert a Node.js Buffer to grpc_byte_buffer. Requires that ::node::Buffer::HasInstance(buffer) */ grpc_byte_buffer *BufferToByteBuffer(v8::Local buffer); /* Convert a grpc_byte_buffer to a Node.js Buffer */ v8::Local ByteBufferToBuffer(grpc_byte_buffer *buffer); } // namespace node } // namespace grpc #endif // NET_GRPC_NODE_BYTE_BUFFER_H_ grpc-1.3.2/src/node/ext/call.cc000066400000000000000000000641351310511640000162060ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include "grpc/support/log.h" #include "grpc/grpc.h" #include "grpc/grpc_security.h" #include "grpc/support/alloc.h" #include "grpc/support/time.h" #include "byte_buffer.h" #include "call.h" #include "channel.h" #include "completion_queue.h" #include "call_credentials.h" #include "slice.h" #include "timeval.h" using std::unique_ptr; using std::shared_ptr; using std::vector; namespace grpc { namespace node { using Nan::Callback; using Nan::EscapableHandleScope; using Nan::HandleScope; using Nan::Maybe; using Nan::MaybeLocal; using Nan::ObjectWrap; using Nan::Persistent; using Nan::Utf8String; using v8::Array; using v8::Boolean; using v8::Exception; using v8::External; using v8::Function; using v8::FunctionTemplate; using v8::Integer; using v8::Local; using v8::Number; using v8::Object; using v8::ObjectTemplate; using v8::Uint32; using v8::String; using v8::Value; Callback *Call::constructor; Persistent Call::fun_tpl; /** * Helper function for throwing errors with a grpc_call_error value. * Modified from the answer by Gus Goose to * http://stackoverflow.com/questions/31794200. */ Local nanErrorWithCode(const char *msg, grpc_call_error code) { EscapableHandleScope scope; Local err = Nan::Error(msg).As(); Nan::Set(err, Nan::New("code").ToLocalChecked(), Nan::New(code)); return scope.Escape(err); } bool CreateMetadataArray(Local metadata, grpc_metadata_array *array) { HandleScope scope; Local keys = Nan::GetOwnPropertyNames(metadata).ToLocalChecked(); for (unsigned int i = 0; i < keys->Length(); i++) { Local current_key = Nan::To( Nan::Get(keys, i).ToLocalChecked()).ToLocalChecked(); Local value_array = Nan::Get(metadata, current_key).ToLocalChecked(); if (!value_array->IsArray()) { return false; } array->capacity += Local::Cast(value_array)->Length(); } array->metadata = reinterpret_cast( gpr_zalloc(array->capacity * sizeof(grpc_metadata))); for (unsigned int i = 0; i < keys->Length(); i++) { Local current_key(Nan::To(keys->Get(i)).ToLocalChecked()); Local values = Local::Cast( Nan::Get(metadata, current_key).ToLocalChecked()); grpc_slice key_slice = CreateSliceFromString(current_key); grpc_slice key_intern_slice = grpc_slice_intern(key_slice); grpc_slice_unref(key_slice); for (unsigned int j = 0; j < values->Length(); j++) { Local value = Nan::Get(values, j).ToLocalChecked(); grpc_metadata *current = &array->metadata[array->count]; current->key = key_intern_slice; // Only allow binary headers for "-bin" keys if (grpc_is_binary_header(key_intern_slice)) { if (::node::Buffer::HasInstance(value)) { current->value = CreateSliceFromBuffer(value); } else { return false; } } else { if (value->IsString()) { Local string_value = Nan::To(value).ToLocalChecked(); current->value = CreateSliceFromString(string_value); } else { return false; } } array->count += 1; } } return true; } void DestroyMetadataArray(grpc_metadata_array *array) { for (size_t i = 0; i < array->count; i++) { // Don't unref keys because they are interned grpc_slice_unref(array->metadata[i].value); } grpc_metadata_array_destroy(array); } Local ParseMetadata(const grpc_metadata_array *metadata_array) { EscapableHandleScope scope; grpc_metadata *metadata_elements = metadata_array->metadata; size_t length = metadata_array->count; Local metadata_object = Nan::New(); for (unsigned int i = 0; i < length; i++) { grpc_metadata* elem = &metadata_elements[i]; // TODO(murgatroid99): Use zero-copy string construction instead Local key_string = CopyStringFromSlice(elem->key); Local array; MaybeLocal maybe_array = Nan::Get(metadata_object, key_string); if (maybe_array.IsEmpty() || !maybe_array.ToLocalChecked()->IsArray()) { array = Nan::New(0); Nan::Set(metadata_object, key_string, array); } else { array = Local::Cast(maybe_array.ToLocalChecked()); } if (grpc_is_binary_header(elem->key)) { Nan::Set(array, array->Length(), CreateBufferFromSlice(elem->value)); } else { // TODO(murgatroid99): Use zero-copy string construction instead Nan::Set(array, array->Length(), CopyStringFromSlice(elem->value)); } } return scope.Escape(metadata_object); } Local Op::GetOpType() const { EscapableHandleScope scope; return scope.Escape(Nan::New(GetTypeString()).ToLocalChecked()); } Op::~Op() { } class SendMetadataOp : public Op { public: SendMetadataOp() { grpc_metadata_array_init(&send_metadata); } ~SendMetadataOp() { DestroyMetadataArray(&send_metadata); } Local GetNodeValue() const { EscapableHandleScope scope; return scope.Escape(Nan::True()); } bool ParseOp(Local value, grpc_op *out) { if (!value->IsObject()) { return false; } MaybeLocal maybe_metadata = Nan::To(value); if (maybe_metadata.IsEmpty()) { return false; } if (!CreateMetadataArray(maybe_metadata.ToLocalChecked(), &send_metadata)) { return false; } out->data.send_initial_metadata.count = send_metadata.count; out->data.send_initial_metadata.metadata = send_metadata.metadata; return true; } bool IsFinalOp() { return false; } void OnComplete(bool success) { } protected: std::string GetTypeString() const { return "send_metadata"; } private: grpc_metadata_array send_metadata; }; class SendMessageOp : public Op { public: SendMessageOp() { send_message = NULL; } ~SendMessageOp() { if (send_message != NULL) { grpc_byte_buffer_destroy(send_message); } } Local GetNodeValue() const { EscapableHandleScope scope; return scope.Escape(Nan::True()); } bool ParseOp(Local value, grpc_op *out) { if (!::node::Buffer::HasInstance(value)) { return false; } Local object_value = Nan::To(value).ToLocalChecked(); MaybeLocal maybe_flag_value = Nan::Get( object_value, Nan::New("grpcWriteFlags").ToLocalChecked()); if (!maybe_flag_value.IsEmpty()) { Local flag_value = maybe_flag_value.ToLocalChecked(); if (flag_value->IsUint32()) { Maybe maybe_flag = Nan::To(flag_value); out->flags = maybe_flag.FromMaybe(0) & GRPC_WRITE_USED_MASK; } } send_message = BufferToByteBuffer(value); out->data.send_message.send_message = send_message; return true; } bool IsFinalOp() { return false; } void OnComplete(bool success) { } protected: std::string GetTypeString() const { return "send_message"; } private: grpc_byte_buffer *send_message; }; class SendClientCloseOp : public Op { public: Local GetNodeValue() const { EscapableHandleScope scope; return scope.Escape(Nan::True()); } bool ParseOp(Local value, grpc_op *out) { return true; } bool IsFinalOp() { return false; } void OnComplete(bool success) { } protected: std::string GetTypeString() const { return "client_close"; } }; class SendServerStatusOp : public Op { public: SendServerStatusOp() { grpc_metadata_array_init(&status_metadata); } ~SendServerStatusOp() { grpc_slice_unref(details); DestroyMetadataArray(&status_metadata); } Local GetNodeValue() const { EscapableHandleScope scope; return scope.Escape(Nan::True()); } bool ParseOp(Local value, grpc_op *out) { if (!value->IsObject()) { return false; } Local server_status = Nan::To(value).ToLocalChecked(); MaybeLocal maybe_metadata = Nan::Get( server_status, Nan::New("metadata").ToLocalChecked()); if (maybe_metadata.IsEmpty()) { return false; } if (!maybe_metadata.ToLocalChecked()->IsObject()) { return false; } Local metadata = Nan::To( maybe_metadata.ToLocalChecked()).ToLocalChecked(); MaybeLocal maybe_code = Nan::Get(server_status, Nan::New("code").ToLocalChecked()); if (maybe_code.IsEmpty()) { return false; } if (!maybe_code.ToLocalChecked()->IsUint32()) { return false; } uint32_t code = Nan::To(maybe_code.ToLocalChecked()).FromJust(); MaybeLocal maybe_details = Nan::Get( server_status, Nan::New("details").ToLocalChecked()); if (maybe_details.IsEmpty()) { return false; } if (!maybe_details.ToLocalChecked()->IsString()) { return false; } Local details = Nan::To( maybe_details.ToLocalChecked()).ToLocalChecked(); if (!CreateMetadataArray(metadata, &status_metadata)) { return false; } out->data.send_status_from_server.trailing_metadata_count = status_metadata.count; out->data.send_status_from_server.trailing_metadata = status_metadata.metadata; out->data.send_status_from_server.status = static_cast(code); this->details = CreateSliceFromString(details); out->data.send_status_from_server.status_details = &this->details; return true; } bool IsFinalOp() { return true; } void OnComplete(bool success) { } protected: std::string GetTypeString() const { return "send_status"; } private: grpc_slice details; grpc_metadata_array status_metadata; }; class GetMetadataOp : public Op { public: GetMetadataOp() { grpc_metadata_array_init(&recv_metadata); } ~GetMetadataOp() { grpc_metadata_array_destroy(&recv_metadata); } Local GetNodeValue() const { EscapableHandleScope scope; return scope.Escape(ParseMetadata(&recv_metadata)); } bool ParseOp(Local value, grpc_op *out) { out->data.recv_initial_metadata.recv_initial_metadata = &recv_metadata; return true; } bool IsFinalOp() { return false; } void OnComplete(bool success) { } protected: std::string GetTypeString() const { return "metadata"; } private: grpc_metadata_array recv_metadata; }; class ReadMessageOp : public Op { public: ReadMessageOp() { recv_message = NULL; } ~ReadMessageOp() { if (recv_message != NULL) { grpc_byte_buffer_destroy(recv_message); } } Local GetNodeValue() const { EscapableHandleScope scope; return scope.Escape(ByteBufferToBuffer(recv_message)); } bool ParseOp(Local value, grpc_op *out) { out->data.recv_message.recv_message = &recv_message; return true; } bool IsFinalOp() { return false; } void OnComplete(bool success) { } protected: std::string GetTypeString() const { return "read"; } private: grpc_byte_buffer *recv_message; }; class ClientStatusOp : public Op { public: ClientStatusOp() { grpc_metadata_array_init(&metadata_array); } ~ClientStatusOp() { grpc_metadata_array_destroy(&metadata_array); } bool ParseOp(Local value, grpc_op *out) { out->data.recv_status_on_client.trailing_metadata = &metadata_array; out->data.recv_status_on_client.status = &status; out->data.recv_status_on_client.status_details = &status_details; return true; } Local GetNodeValue() const { EscapableHandleScope scope; Local status_obj = Nan::New(); Nan::Set(status_obj, Nan::New("code").ToLocalChecked(), Nan::New(status)); Nan::Set(status_obj, Nan::New("details").ToLocalChecked(), CopyStringFromSlice(status_details)); Nan::Set(status_obj, Nan::New("metadata").ToLocalChecked(), ParseMetadata(&metadata_array)); return scope.Escape(status_obj); } bool IsFinalOp() { return true; } void OnComplete(bool success) { } protected: std::string GetTypeString() const { return "status"; } private: grpc_metadata_array metadata_array; grpc_status_code status; grpc_slice status_details; }; class ServerCloseResponseOp : public Op { public: Local GetNodeValue() const { EscapableHandleScope scope; return scope.Escape(Nan::New(cancelled)); } bool ParseOp(Local value, grpc_op *out) { out->data.recv_close_on_server.cancelled = &cancelled; return true; } bool IsFinalOp() { return false; } void OnComplete(bool success) { } protected: std::string GetTypeString() const { return "cancelled"; } private: int cancelled; }; tag::tag(Callback *callback, OpVec *ops, Call *call, Local call_value) : callback(callback), ops(ops), call(call){ HandleScope scope; call_persist.Reset(call_value); } tag::~tag() { delete callback; delete ops; } void CompleteTag(void *tag, const char *error_message) { HandleScope scope; struct tag *tag_struct = reinterpret_cast(tag); Callback *callback = tag_struct->callback; if (error_message == NULL) { Local tag_obj = Nan::New(); for (vector >::iterator it = tag_struct->ops->begin(); it != tag_struct->ops->end(); ++it) { Op *op_ptr = it->get(); Nan::Set(tag_obj, op_ptr->GetOpType(), op_ptr->GetNodeValue()); } Local argv[] = {Nan::Null(), tag_obj}; callback->Call(2, argv); } else { Local argv[] = {Nan::Error(error_message)}; callback->Call(1, argv); } bool success = (error_message == NULL); bool is_final_op = false; for (vector >::iterator it = tag_struct->ops->begin(); it != tag_struct->ops->end(); ++it) { Op *op_ptr = it->get(); op_ptr->OnComplete(success); if (op_ptr->IsFinalOp()) { is_final_op = true; } } if (tag_struct->call == NULL) { return; } tag_struct->call->CompleteBatch(is_final_op); } void DestroyTag(void *tag) { struct tag *tag_struct = reinterpret_cast(tag); delete tag_struct; } void Call::DestroyCall() { if (this->wrapped_call != NULL) { grpc_call_destroy(this->wrapped_call); this->wrapped_call = NULL; } } Call::Call(grpc_call *call) : wrapped_call(call), pending_batches(0), has_final_op_completed(false) { } Call::~Call() { DestroyCall(); } void Call::Init(Local exports) { HandleScope scope; Local tpl = Nan::New(New); tpl->SetClassName(Nan::New("Call").ToLocalChecked()); tpl->InstanceTemplate()->SetInternalFieldCount(1); Nan::SetPrototypeMethod(tpl, "startBatch", StartBatch); Nan::SetPrototypeMethod(tpl, "cancel", Cancel); Nan::SetPrototypeMethod(tpl, "cancelWithStatus", CancelWithStatus); Nan::SetPrototypeMethod(tpl, "getPeer", GetPeer); Nan::SetPrototypeMethod(tpl, "setCredentials", SetCredentials); fun_tpl.Reset(tpl); Local ctr = Nan::GetFunction(tpl).ToLocalChecked(); Nan::Set(exports, Nan::New("Call").ToLocalChecked(), ctr); constructor = new Callback(ctr); } bool Call::HasInstance(Local val) { HandleScope scope; return Nan::New(fun_tpl)->HasInstance(val); } Local Call::WrapStruct(grpc_call *call) { EscapableHandleScope scope; if (call == NULL) { return scope.Escape(Nan::Null()); } const int argc = 1; Local argv[argc] = {Nan::New( reinterpret_cast(call))}; MaybeLocal maybe_instance = Nan::NewInstance( constructor->GetFunction(), argc, argv); if (maybe_instance.IsEmpty()) { return scope.Escape(Nan::Null()); } else { return scope.Escape(maybe_instance.ToLocalChecked()); } } void Call::CompleteBatch(bool is_final_op) { if (is_final_op) { this->has_final_op_completed = true; } this->pending_batches--; if (this->has_final_op_completed && this->pending_batches == 0) { this->DestroyCall(); } } NAN_METHOD(Call::New) { /* Arguments: * 0: Channel to make the call on * 1: Method * 2: Deadline * 3: host * 4: parent Call * 5: propagation flags */ if (info.IsConstructCall()) { Call *call; if (info[0]->IsExternal()) { Local ext = info[0].As(); // This option is used for wrapping an existing call grpc_call *call_value = reinterpret_cast(ext->Value()); call = new Call(call_value); } else { if (!Channel::HasInstance(info[0])) { return Nan::ThrowTypeError("Call's first argument must be a Channel"); } if (!info[1]->IsString()) { return Nan::ThrowTypeError("Call's second argument must be a string"); } if (!(info[2]->IsNumber() || info[2]->IsDate())) { return Nan::ThrowTypeError( "Call's third argument must be a date or a number"); } // These arguments are at the end because they are optional grpc_call *parent_call = NULL; if (Call::HasInstance(info[4])) { Call *parent_obj = ObjectWrap::Unwrap( Nan::To(info[4]).ToLocalChecked()); parent_call = parent_obj->wrapped_call; } else if (!(info[4]->IsUndefined() || info[4]->IsNull())) { return Nan::ThrowTypeError( "Call's fifth argument must be another call, if provided"); } uint32_t propagate_flags = GRPC_PROPAGATE_DEFAULTS; if (info[5]->IsUint32()) { propagate_flags = Nan::To(info[5]).FromJust(); } else if (!(info[5]->IsUndefined() || info[5]->IsNull())) { return Nan::ThrowTypeError( "Call's sixth argument must be propagate flags, if provided"); } Local channel_object = Nan::To(info[0]).ToLocalChecked(); Channel *channel = ObjectWrap::Unwrap(channel_object); if (channel->GetWrappedChannel() == NULL) { return Nan::ThrowError("Call cannot be created from a closed channel"); } double deadline = Nan::To(info[2]).FromJust(); grpc_channel *wrapped_channel = channel->GetWrappedChannel(); grpc_call *wrapped_call; grpc_slice method = CreateSliceFromString( Nan::To(info[1]).ToLocalChecked()); if (info[3]->IsString()) { grpc_slice *host = new grpc_slice; *host = CreateSliceFromString( Nan::To(info[3]).ToLocalChecked()); wrapped_call = grpc_channel_create_call( wrapped_channel, parent_call, propagate_flags, GetCompletionQueue(), method, host, MillisecondsToTimespec(deadline), NULL); delete host; } else if (info[3]->IsUndefined() || info[3]->IsNull()) { wrapped_call = grpc_channel_create_call( wrapped_channel, parent_call, propagate_flags, GetCompletionQueue(), method, NULL, MillisecondsToTimespec(deadline), NULL); } else { return Nan::ThrowTypeError("Call's fourth argument must be a string"); } grpc_slice_unref(method); call = new Call(wrapped_call); Nan::Set(info.This(), Nan::New("channel_").ToLocalChecked(), channel_object); } call->Wrap(info.This()); info.GetReturnValue().Set(info.This()); } else { const int argc = 4; Local argv[argc] = {info[0], info[1], info[2], info[3]}; MaybeLocal maybe_instance = Nan::NewInstance( constructor->GetFunction(), argc, argv); if (maybe_instance.IsEmpty()) { // There's probably a pending exception return; } else { info.GetReturnValue().Set(maybe_instance.ToLocalChecked()); } } } NAN_METHOD(Call::StartBatch) { if (!Call::HasInstance(info.This())) { return Nan::ThrowTypeError("startBatch can only be called on Call objects"); } if (!info[0]->IsObject()) { return Nan::ThrowError("startBatch's first argument must be an object"); } if (!info[1]->IsFunction()) { return Nan::ThrowError("startBatch's second argument must be a callback"); } Local callback_func = info[1].As(); Call *call = ObjectWrap::Unwrap(info.This()); Local obj = Nan::To(info[0]).ToLocalChecked(); Local keys = Nan::GetOwnPropertyNames(obj).ToLocalChecked(); size_t nops = keys->Length(); vector ops(nops); unique_ptr op_vector(new OpVec()); for (unsigned int i = 0; i < nops; i++) { unique_ptr op; MaybeLocal maybe_key = Nan::Get(keys, i); if (maybe_key.IsEmpty() || (!maybe_key.ToLocalChecked()->IsUint32())) { return Nan::ThrowError( "startBatch's first argument's keys must be integers"); } uint32_t type = Nan::To(maybe_key.ToLocalChecked()).FromJust(); ops[i].op = static_cast(type); ops[i].flags = 0; ops[i].reserved = NULL; switch (type) { case GRPC_OP_SEND_INITIAL_METADATA: op.reset(new SendMetadataOp()); break; case GRPC_OP_SEND_MESSAGE: op.reset(new SendMessageOp()); break; case GRPC_OP_SEND_CLOSE_FROM_CLIENT: op.reset(new SendClientCloseOp()); break; case GRPC_OP_SEND_STATUS_FROM_SERVER: op.reset(new SendServerStatusOp()); break; case GRPC_OP_RECV_INITIAL_METADATA: op.reset(new GetMetadataOp()); break; case GRPC_OP_RECV_MESSAGE: op.reset(new ReadMessageOp()); break; case GRPC_OP_RECV_STATUS_ON_CLIENT: op.reset(new ClientStatusOp()); break; case GRPC_OP_RECV_CLOSE_ON_SERVER: op.reset(new ServerCloseResponseOp()); break; default: return Nan::ThrowError("Argument object had an unrecognized key"); } if (!op->ParseOp(obj->Get(type), &ops[i])) { return Nan::ThrowTypeError("Incorrectly typed arguments to startBatch"); } op_vector->push_back(std::move(op)); } Callback *callback = new Callback(callback_func); grpc_call_error error = grpc_call_start_batch( call->wrapped_call, &ops[0], nops, new struct tag( callback, op_vector.release(), call, info.This()), NULL); if (error != GRPC_CALL_OK) { return Nan::ThrowError(nanErrorWithCode("startBatch failed", error)); } call->pending_batches++; CompletionQueueNext(); } NAN_METHOD(Call::Cancel) { if (!Call::HasInstance(info.This())) { return Nan::ThrowTypeError("cancel can only be called on Call objects"); } Call *call = ObjectWrap::Unwrap(info.This()); grpc_call_error error = grpc_call_cancel(call->wrapped_call, NULL); if (error != GRPC_CALL_OK) { return Nan::ThrowError(nanErrorWithCode("cancel failed", error)); } } NAN_METHOD(Call::CancelWithStatus) { Nan::HandleScope scope; if (!HasInstance(info.This())) { return Nan::ThrowTypeError("cancel can only be called on Call objects"); } if (!info[0]->IsUint32()) { return Nan::ThrowTypeError( "cancelWithStatus's first argument must be a status code"); } if (!info[1]->IsString()) { return Nan::ThrowTypeError( "cancelWithStatus's second argument must be a string"); } Call *call = ObjectWrap::Unwrap(info.This()); grpc_status_code code = static_cast( Nan::To(info[0]).FromJust()); if (code == GRPC_STATUS_OK) { return Nan::ThrowRangeError( "cancelWithStatus cannot be called with OK status"); } Utf8String details(info[1]); grpc_call_cancel_with_status(call->wrapped_call, code, *details, NULL); } NAN_METHOD(Call::GetPeer) { Nan::HandleScope scope; if (!HasInstance(info.This())) { return Nan::ThrowTypeError("getPeer can only be called on Call objects"); } Call *call = ObjectWrap::Unwrap(info.This()); char *peer = grpc_call_get_peer(call->wrapped_call); Local peer_value = Nan::New(peer).ToLocalChecked(); gpr_free(peer); info.GetReturnValue().Set(peer_value); } NAN_METHOD(Call::SetCredentials) { Nan::HandleScope scope; if (!HasInstance(info.This())) { return Nan::ThrowTypeError( "setCredentials can only be called on Call objects"); } if (!CallCredentials::HasInstance(info[0])) { return Nan::ThrowTypeError( "setCredentials' first argument must be a CallCredentials"); } Call *call = ObjectWrap::Unwrap(info.This()); CallCredentials *creds_object = ObjectWrap::Unwrap( Nan::To(info[0]).ToLocalChecked()); grpc_call_credentials *creds = creds_object->GetWrappedCredentials(); grpc_call_error error = GRPC_CALL_ERROR; if (creds) { error = grpc_call_set_credentials(call->wrapped_call, creds); } info.GetReturnValue().Set(Nan::New(error)); } } // namespace node } // namespace grpc grpc-1.3.2/src/node/ext/call.h000066400000000000000000000101741310511640000160420ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef NET_GRPC_NODE_CALL_H_ #define NET_GRPC_NODE_CALL_H_ #include #include #include #include #include "grpc/grpc.h" #include "grpc/support/log.h" #include "channel.h" namespace grpc { namespace node { using std::unique_ptr; using std::shared_ptr; v8::Local nanErrorWithCode(const char *msg, grpc_call_error code); v8::Local ParseMetadata(const grpc_metadata_array *metadata_array); bool CreateMetadataArray(v8::Local metadata, grpc_metadata_array *array); void DestroyMetadataArray(grpc_metadata_array *array); /* Wrapper class for grpc_call structs. */ class Call : public Nan::ObjectWrap { public: static void Init(v8::Local exports); static bool HasInstance(v8::Local val); /* Wrap a grpc_call struct in a javascript object */ static v8::Local WrapStruct(grpc_call *call); void CompleteBatch(bool is_final_op); private: explicit Call(grpc_call *call); ~Call(); // Prevent copying Call(const Call &); Call &operator=(const Call &); void DestroyCall(); static NAN_METHOD(New); static NAN_METHOD(StartBatch); static NAN_METHOD(Cancel); static NAN_METHOD(CancelWithStatus); static NAN_METHOD(GetPeer); static NAN_METHOD(SetCredentials); static Nan::Callback *constructor; // Used for typechecking instances of this javascript class static Nan::Persistent fun_tpl; grpc_call *wrapped_call; // The number of ops that were started but not completed on this call int pending_batches; /* Indicates whether the "final" op on a call has completed. For a client call, this is GRPC_OP_RECV_STATUS_ON_CLIENT and for a server call, this is GRPC_OP_SEND_STATUS_FROM_SERVER */ bool has_final_op_completed; }; class Op { public: virtual v8::Local GetNodeValue() const = 0; virtual bool ParseOp(v8::Local value, grpc_op *out) = 0; virtual ~Op(); v8::Local GetOpType() const; virtual bool IsFinalOp() = 0; virtual void OnComplete(bool success) = 0; protected: virtual std::string GetTypeString() const = 0; }; typedef std::vector> OpVec; struct tag { tag(Nan::Callback *callback, OpVec *ops, Call *call, v8::Local call_value); ~tag(); Nan::Callback *callback; OpVec *ops; Call *call; Nan::Persistent> call_persist; }; void DestroyTag(void *tag); void CompleteTag(void *tag, const char *error_message); } // namespace node } // namespace grpc #endif // NET_GRPC_NODE_CALL_H_ grpc-1.3.2/src/node/ext/call_credentials.cc000066400000000000000000000240071310511640000205550ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include "grpc/grpc.h" #include "grpc/grpc_security.h" #include "grpc/support/log.h" #include "call_credentials.h" #include "call.h" namespace grpc { namespace node { using Nan::Callback; using Nan::EscapableHandleScope; using Nan::HandleScope; using Nan::Maybe; using Nan::MaybeLocal; using Nan::ObjectWrap; using Nan::Persistent; using Nan::Utf8String; using v8::Exception; using v8::External; using v8::Function; using v8::FunctionTemplate; using v8::Integer; using v8::Local; using v8::Object; using v8::ObjectTemplate; using v8::Value; Nan::Callback *CallCredentials::constructor; Persistent CallCredentials::fun_tpl; static Callback *plugin_callback; CallCredentials::CallCredentials(grpc_call_credentials *credentials) : wrapped_credentials(credentials) {} CallCredentials::~CallCredentials() { grpc_call_credentials_release(wrapped_credentials); } void CallCredentials::Init(Local exports) { HandleScope scope; Local tpl = Nan::New(New); tpl->SetClassName(Nan::New("CallCredentials").ToLocalChecked()); tpl->InstanceTemplate()->SetInternalFieldCount(1); Nan::SetPrototypeMethod(tpl, "compose", Compose); fun_tpl.Reset(tpl); Local ctr = Nan::GetFunction(tpl).ToLocalChecked(); Nan::Set(ctr, Nan::New("createFromPlugin").ToLocalChecked(), Nan::GetFunction( Nan::New(CreateFromPlugin)).ToLocalChecked()); Nan::Set(exports, Nan::New("CallCredentials").ToLocalChecked(), ctr); constructor = new Nan::Callback(ctr); Local callback_tpl = Nan::New(PluginCallback); plugin_callback = new Callback( Nan::GetFunction(callback_tpl).ToLocalChecked()); } bool CallCredentials::HasInstance(Local val) { HandleScope scope; return Nan::New(fun_tpl)->HasInstance(val); } Local CallCredentials::WrapStruct(grpc_call_credentials *credentials) { EscapableHandleScope scope; const int argc = 1; if (credentials == NULL) { return scope.Escape(Nan::Null()); } Local argv[argc] = { Nan::New(reinterpret_cast(credentials))}; MaybeLocal maybe_instance = Nan::NewInstance( constructor->GetFunction(), argc, argv); if (maybe_instance.IsEmpty()) { return scope.Escape(Nan::Null()); } else { return scope.Escape(maybe_instance.ToLocalChecked()); } } grpc_call_credentials *CallCredentials::GetWrappedCredentials() { return wrapped_credentials; } NAN_METHOD(CallCredentials::New) { if (info.IsConstructCall()) { if (!info[0]->IsExternal()) { return Nan::ThrowTypeError( "CallCredentials can only be created with the provided functions"); } Local ext = info[0].As(); grpc_call_credentials *creds_value = reinterpret_cast(ext->Value()); CallCredentials *credentials = new CallCredentials(creds_value); credentials->Wrap(info.This()); info.GetReturnValue().Set(info.This()); return; } else { // This should never be called directly return Nan::ThrowTypeError( "CallCredentials can only be created with the provided functions"); } } NAN_METHOD(CallCredentials::Compose) { if (!CallCredentials::HasInstance(info.This())) { return Nan::ThrowTypeError( "compose can only be called on CallCredentials objects"); } if (!CallCredentials::HasInstance(info[0])) { return Nan::ThrowTypeError( "compose's first argument must be a CallCredentials object"); } CallCredentials *self = ObjectWrap::Unwrap(info.This()); CallCredentials *other = ObjectWrap::Unwrap( Nan::To(info[0]).ToLocalChecked()); grpc_call_credentials *creds = grpc_composite_call_credentials_create( self->wrapped_credentials, other->wrapped_credentials, NULL); info.GetReturnValue().Set(WrapStruct(creds)); } NAN_METHOD(CallCredentials::CreateFromPlugin) { if (!info[0]->IsFunction()) { return Nan::ThrowTypeError( "createFromPlugin's argument must be a function"); } grpc_metadata_credentials_plugin plugin; plugin_state *state = new plugin_state; state->callback = new Nan::Callback(info[0].As()); state->pending_callbacks = new std::queue(); uv_mutex_init(&state->plugin_mutex); uv_async_init(uv_default_loop(), &state->plugin_async, SendPluginCallback); uv_unref((uv_handle_t*)&state->plugin_async); state->plugin_async.data = state; plugin.get_metadata = plugin_get_metadata; plugin.destroy = plugin_destroy_state; plugin.state = reinterpret_cast(state); plugin.type = ""; grpc_call_credentials *creds = grpc_metadata_credentials_create_from_plugin( plugin, NULL); info.GetReturnValue().Set(WrapStruct(creds)); } NAN_METHOD(PluginCallback) { // Arguments: status code, error details, metadata if (!info[0]->IsUint32()) { return Nan::ThrowTypeError( "The callback's first argument must be a status code"); } if (!info[1]->IsString()) { return Nan::ThrowTypeError( "The callback's second argument must be a string"); } if (!info[2]->IsObject()) { return Nan::ThrowTypeError( "The callback's third argument must be an object"); } if (!info[3]->IsObject()) { return Nan::ThrowTypeError( "The callback's fourth argument must be an object"); } grpc_status_code code = static_cast( Nan::To(info[0]).FromJust()); Utf8String details_utf8_str(info[1]); char *details = *details_utf8_str; grpc_metadata_array array; grpc_metadata_array_init(&array); Local callback_data = Nan::To(info[3]).ToLocalChecked(); if (!CreateMetadataArray(Nan::To(info[2]).ToLocalChecked(), &array)){ return Nan::ThrowError("Failed to parse metadata"); } grpc_credentials_plugin_metadata_cb cb = reinterpret_cast( Nan::Get(callback_data, Nan::New("cb").ToLocalChecked() ).ToLocalChecked().As()->Value()); void *user_data = Nan::Get(callback_data, Nan::New("user_data").ToLocalChecked() ).ToLocalChecked().As()->Value(); cb(user_data, array.metadata, array.count, code, details); DestroyMetadataArray(&array); } NAUV_WORK_CB(SendPluginCallback) { Nan::HandleScope scope; plugin_state *state = reinterpret_cast(async->data); std::queue callbacks; uv_mutex_lock(&state->plugin_mutex); state->pending_callbacks->swap(callbacks); uv_mutex_unlock(&state->plugin_mutex); while (!callbacks.empty()) { plugin_callback_data *data = callbacks.front(); callbacks.pop(); Local callback_data = Nan::New(); Nan::Set(callback_data, Nan::New("cb").ToLocalChecked(), Nan::New(reinterpret_cast(data->cb))); Nan::Set(callback_data, Nan::New("user_data").ToLocalChecked(), Nan::New(data->user_data)); const int argc = 3; v8::Local argv[argc] = { Nan::New(data->service_url).ToLocalChecked(), callback_data, // Get Local from Nan::Callback* **plugin_callback }; Nan::Callback *callback = state->callback; callback->Call(argc, argv); delete data; } } void plugin_get_metadata(void *state, grpc_auth_metadata_context context, grpc_credentials_plugin_metadata_cb cb, void *user_data) { plugin_state *p_state = reinterpret_cast(state); plugin_callback_data *data = new plugin_callback_data; data->service_url = context.service_url; data->cb = cb; data->user_data = user_data; uv_mutex_lock(&p_state->plugin_mutex); p_state->pending_callbacks->push(data); uv_mutex_unlock(&p_state->plugin_mutex); uv_async_send(&p_state->plugin_async); } void plugin_uv_close_cb(uv_handle_t *handle) { uv_async_t *async = reinterpret_cast(handle); plugin_state *state = reinterpret_cast(async->data); uv_mutex_destroy(&state->plugin_mutex); delete state->pending_callbacks; delete state->callback; delete state; } void plugin_destroy_state(void *ptr) { plugin_state *state = reinterpret_cast(ptr); uv_close((uv_handle_t*)&state->plugin_async, plugin_uv_close_cb); } } // namespace node } // namespace grpc grpc-1.3.2/src/node/ext/call_credentials.h000066400000000000000000000067241310511640000204250ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_NODE_CALL_CREDENTIALS_H_ #define GRPC_NODE_CALL_CREDENTIALS_H_ #include #include #include #include #include "grpc/grpc_security.h" namespace grpc { namespace node { class CallCredentials : public Nan::ObjectWrap { public: static void Init(v8::Local exports); static bool HasInstance(v8::Local val); /* Wrap a grpc_call_credentials struct in a javascript object */ static v8::Local WrapStruct(grpc_call_credentials *credentials); /* Returns the grpc_call_credentials struct that this object wraps */ grpc_call_credentials *GetWrappedCredentials(); private: explicit CallCredentials(grpc_call_credentials *credentials); ~CallCredentials(); // Prevent copying CallCredentials(const CallCredentials &); CallCredentials &operator=(const CallCredentials &); static NAN_METHOD(New); static NAN_METHOD(CreateSsl); static NAN_METHOD(CreateFromPlugin); static NAN_METHOD(Compose); static Nan::Callback *constructor; // Used for typechecking instances of this javascript class static Nan::Persistent fun_tpl; grpc_call_credentials *wrapped_credentials; }; /* Auth metadata plugin functionality */ typedef struct plugin_callback_data { const char *service_url; grpc_credentials_plugin_metadata_cb cb; void *user_data; } plugin_callback_data; typedef struct plugin_state { Nan::Callback *callback; std::queue *pending_callbacks; uv_mutex_t plugin_mutex; // async.data == this uv_async_t plugin_async; } plugin_state; void plugin_get_metadata(void *state, grpc_auth_metadata_context context, grpc_credentials_plugin_metadata_cb cb, void *user_data); void plugin_destroy_state(void *state); NAN_METHOD(PluginCallback); NAUV_WORK_CB(SendPluginCallback); } // namespace node } // namepsace grpc #endif // GRPC_NODE_CALL_CREDENTIALS_H_ grpc-1.3.2/src/node/ext/channel.cc000066400000000000000000000237541310511640000167050ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "grpc/support/log.h" #include #include #include "grpc/grpc.h" #include "grpc/grpc_security.h" #include "call.h" #include "channel.h" #include "completion_queue.h" #include "channel_credentials.h" #include "timeval.h" namespace grpc { namespace node { using Nan::Callback; using Nan::EscapableHandleScope; using Nan::HandleScope; using Nan::Maybe; using Nan::MaybeLocal; using Nan::ObjectWrap; using Nan::Persistent; using Nan::Utf8String; using v8::Array; using v8::Exception; using v8::Function; using v8::FunctionTemplate; using v8::Integer; using v8::Local; using v8::Number; using v8::Object; using v8::String; using v8::Value; Callback *Channel::constructor; Persistent Channel::fun_tpl; bool ParseChannelArgs(Local args_val, grpc_channel_args **channel_args_ptr) { if (args_val->IsUndefined() || args_val->IsNull()) { *channel_args_ptr = NULL; return true; } if (!args_val->IsObject()) { *channel_args_ptr = NULL; return false; } grpc_channel_args *channel_args = reinterpret_cast( malloc(sizeof(grpc_channel_args))); *channel_args_ptr = channel_args; Local args_hash = Nan::To(args_val).ToLocalChecked(); Local keys = Nan::GetOwnPropertyNames(args_hash).ToLocalChecked(); channel_args->num_args = keys->Length(); channel_args->args = reinterpret_cast( calloc(channel_args->num_args, sizeof(grpc_arg))); for (unsigned int i = 0; i < channel_args->num_args; i++) { Local key = Nan::Get(keys, i).ToLocalChecked(); Utf8String key_str(key); if (*key_str == NULL) { // Key string onversion failed return false; } Local value = Nan::Get(args_hash, key).ToLocalChecked(); if (value->IsInt32()) { channel_args->args[i].type = GRPC_ARG_INTEGER; channel_args->args[i].value.integer = Nan::To(value).FromJust(); } else if (value->IsString()) { Utf8String val_str(value); channel_args->args[i].type = GRPC_ARG_STRING; channel_args->args[i].value.string = reinterpret_cast( calloc(val_str.length() + 1,sizeof(char))); memcpy(channel_args->args[i].value.string, *val_str, val_str.length() + 1); } else { // The value does not match either of the accepted types return false; } channel_args->args[i].key = reinterpret_cast( calloc(key_str.length() + 1, sizeof(char))); memcpy(channel_args->args[i].key, *key_str, key_str.length() + 1); } return true; } void DeallocateChannelArgs(grpc_channel_args *channel_args) { if (channel_args == NULL) { return; } for (size_t i = 0; i < channel_args->num_args; i++) { if (channel_args->args[i].key == NULL) { /* NULL key implies that this argument and all subsequent arguments failed * to parse */ break; } free(channel_args->args[i].key); if (channel_args->args[i].type == GRPC_ARG_STRING) { free(channel_args->args[i].value.string); } } free(channel_args->args); free(channel_args); } Channel::Channel(grpc_channel *channel) : wrapped_channel(channel) {} Channel::~Channel() { gpr_log(GPR_DEBUG, "Destroying channel"); if (wrapped_channel != NULL) { grpc_channel_destroy(wrapped_channel); } } void Channel::Init(Local exports) { Nan::HandleScope scope; Local tpl = Nan::New(New); tpl->SetClassName(Nan::New("Channel").ToLocalChecked()); tpl->InstanceTemplate()->SetInternalFieldCount(1); Nan::SetPrototypeMethod(tpl, "close", Close); Nan::SetPrototypeMethod(tpl, "getTarget", GetTarget); Nan::SetPrototypeMethod(tpl, "getConnectivityState", GetConnectivityState); Nan::SetPrototypeMethod(tpl, "watchConnectivityState", WatchConnectivityState); fun_tpl.Reset(tpl); Local ctr = Nan::GetFunction(tpl).ToLocalChecked(); Nan::Set(exports, Nan::New("Channel").ToLocalChecked(), ctr); constructor = new Callback(ctr); } bool Channel::HasInstance(Local val) { HandleScope scope; return Nan::New(fun_tpl)->HasInstance(val); } grpc_channel *Channel::GetWrappedChannel() { return this->wrapped_channel; } NAN_METHOD(Channel::New) { if (info.IsConstructCall()) { if (!info[0]->IsString()) { return Nan::ThrowTypeError( "Channel expects a string, a credential and an object"); } grpc_channel *wrapped_channel; // Owned by the Channel object Utf8String host(info[0]); grpc_channel_credentials *creds; if (!ChannelCredentials::HasInstance(info[1])) { return Nan::ThrowTypeError( "Channel's second argument must be a ChannelCredentials"); } ChannelCredentials *creds_object = ObjectWrap::Unwrap( Nan::To(info[1]).ToLocalChecked()); creds = creds_object->GetWrappedCredentials(); grpc_channel_args *channel_args_ptr = NULL; if (!ParseChannelArgs(info[2], &channel_args_ptr)) { DeallocateChannelArgs(channel_args_ptr); return Nan::ThrowTypeError("Channel options must be an object with " "string keys and integer or string values"); } if (creds == NULL) { wrapped_channel = grpc_insecure_channel_create(*host, channel_args_ptr, NULL); } else { wrapped_channel = grpc_secure_channel_create(creds, *host, channel_args_ptr, NULL); } DeallocateChannelArgs(channel_args_ptr); Channel *channel = new Channel(wrapped_channel); channel->Wrap(info.This()); info.GetReturnValue().Set(info.This()); return; } else { const int argc = 3; Local argv[argc] = {info[0], info[1], info[2]}; MaybeLocal maybe_instance = Nan::NewInstance( constructor->GetFunction(), argc, argv); if (maybe_instance.IsEmpty()) { // There's probably a pending exception return; } else { info.GetReturnValue().Set(maybe_instance.ToLocalChecked()); } } } NAN_METHOD(Channel::Close) { if (!HasInstance(info.This())) { return Nan::ThrowTypeError("close can only be called on Channel objects"); } Channel *channel = ObjectWrap::Unwrap(info.This()); if (channel->wrapped_channel != NULL) { grpc_channel_destroy(channel->wrapped_channel); channel->wrapped_channel = NULL; } } NAN_METHOD(Channel::GetTarget) { if (!HasInstance(info.This())) { return Nan::ThrowTypeError("getTarget can only be called on Channel objects"); } Channel *channel = ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New( grpc_channel_get_target(channel->wrapped_channel)).ToLocalChecked()); } NAN_METHOD(Channel::GetConnectivityState) { if (!HasInstance(info.This())) { return Nan::ThrowTypeError( "getConnectivityState can only be called on Channel objects"); } Channel *channel = ObjectWrap::Unwrap(info.This()); int try_to_connect = (int)info[0]->Equals(Nan::True()); info.GetReturnValue().Set( grpc_channel_check_connectivity_state(channel->wrapped_channel, try_to_connect)); } NAN_METHOD(Channel::WatchConnectivityState) { if (!HasInstance(info.This())) { return Nan::ThrowTypeError( "watchConnectivityState can only be called on Channel objects"); } if (!info[0]->IsUint32()) { return Nan::ThrowTypeError( "watchConnectivityState's first argument must be a channel state"); } if (!(info[1]->IsNumber() || info[1]->IsDate())) { return Nan::ThrowTypeError( "watchConnectivityState's second argument must be a date or a number"); } if (!info[2]->IsFunction()) { return Nan::ThrowTypeError( "watchConnectivityState's third argument must be a callback"); } grpc_connectivity_state last_state = static_cast( Nan::To(info[0]).FromJust()); double deadline = Nan::To(info[1]).FromJust(); Local callback_func = info[2].As(); Nan::Callback *callback = new Callback(callback_func); Channel *channel = ObjectWrap::Unwrap(info.This()); unique_ptr ops(new OpVec()); grpc_channel_watch_connectivity_state( channel->wrapped_channel, last_state, MillisecondsToTimespec(deadline), GetCompletionQueue(), new struct tag(callback, ops.release(), NULL, Nan::Null())); CompletionQueueNext(); } } // namespace node } // namespace grpc grpc-1.3.2/src/node/ext/channel.h000066400000000000000000000055121310511640000165370ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef NET_GRPC_NODE_CHANNEL_H_ #define NET_GRPC_NODE_CHANNEL_H_ #include #include #include "grpc/grpc.h" namespace grpc { namespace node { bool ParseChannelArgs(v8::Local args_val, grpc_channel_args **channel_args_ptr); void DeallocateChannelArgs(grpc_channel_args *channel_args); /* Wrapper class for grpc_channel structs */ class Channel : public Nan::ObjectWrap { public: static void Init(v8::Local exports); static bool HasInstance(v8::Local val); /* This is used to typecheck javascript objects before converting them to this type */ static v8::Persistent prototype; /* Returns the grpc_channel struct that this object wraps */ grpc_channel *GetWrappedChannel(); private: explicit Channel(grpc_channel *channel); ~Channel(); // Prevent copying Channel(const Channel &); Channel &operator=(const Channel &); static NAN_METHOD(New); static NAN_METHOD(Close); static NAN_METHOD(GetTarget); static NAN_METHOD(GetConnectivityState); static NAN_METHOD(WatchConnectivityState); static Nan::Callback *constructor; static Nan::Persistent fun_tpl; grpc_channel *wrapped_channel; }; } // namespace node } // namespace grpc #endif // NET_GRPC_NODE_CHANNEL_H_ grpc-1.3.2/src/node/ext/channel_credentials.cc000066400000000000000000000162311310511640000212520ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "grpc/grpc.h" #include "grpc/grpc_security.h" #include "grpc/support/log.h" #include "channel_credentials.h" #include "call_credentials.h" #include "call.h" namespace grpc { namespace node { using Nan::Callback; using Nan::EscapableHandleScope; using Nan::HandleScope; using Nan::Maybe; using Nan::MaybeLocal; using Nan::ObjectWrap; using Nan::Persistent; using Nan::Utf8String; using v8::Exception; using v8::External; using v8::Function; using v8::FunctionTemplate; using v8::Integer; using v8::Local; using v8::Object; using v8::ObjectTemplate; using v8::Value; Nan::Callback *ChannelCredentials::constructor; Persistent ChannelCredentials::fun_tpl; ChannelCredentials::ChannelCredentials(grpc_channel_credentials *credentials) : wrapped_credentials(credentials) {} ChannelCredentials::~ChannelCredentials() { grpc_channel_credentials_release(wrapped_credentials); } void ChannelCredentials::Init(Local exports) { HandleScope scope; Local tpl = Nan::New(New); tpl->SetClassName(Nan::New("ChannelCredentials").ToLocalChecked()); tpl->InstanceTemplate()->SetInternalFieldCount(1); Nan::SetPrototypeMethod(tpl, "compose", Compose); fun_tpl.Reset(tpl); Local ctr = Nan::GetFunction(tpl).ToLocalChecked(); Nan::Set(ctr, Nan::New("createSsl").ToLocalChecked(), Nan::GetFunction( Nan::New(CreateSsl)).ToLocalChecked()); Nan::Set(ctr, Nan::New("createInsecure").ToLocalChecked(), Nan::GetFunction( Nan::New(CreateInsecure)).ToLocalChecked()); Nan::Set(exports, Nan::New("ChannelCredentials").ToLocalChecked(), ctr); constructor = new Nan::Callback(ctr); } bool ChannelCredentials::HasInstance(Local val) { HandleScope scope; return Nan::New(fun_tpl)->HasInstance(val); } Local ChannelCredentials::WrapStruct( grpc_channel_credentials *credentials) { EscapableHandleScope scope; const int argc = 1; Local argv[argc] = { Nan::New(reinterpret_cast(credentials))}; MaybeLocal maybe_instance = Nan::NewInstance( constructor->GetFunction(), argc, argv); if (maybe_instance.IsEmpty()) { return scope.Escape(Nan::Null()); } else { return scope.Escape(maybe_instance.ToLocalChecked()); } } grpc_channel_credentials *ChannelCredentials::GetWrappedCredentials() { return wrapped_credentials; } NAN_METHOD(ChannelCredentials::New) { if (info.IsConstructCall()) { if (!info[0]->IsExternal()) { return Nan::ThrowTypeError( "ChannelCredentials can only be created with the provided functions"); } Local ext = info[0].As(); grpc_channel_credentials *creds_value = reinterpret_cast(ext->Value()); ChannelCredentials *credentials = new ChannelCredentials(creds_value); credentials->Wrap(info.This()); info.GetReturnValue().Set(info.This()); return; } else { // This should never be called directly return Nan::ThrowTypeError( "ChannelCredentials can only be created with the provided functions"); } } NAN_METHOD(ChannelCredentials::CreateSsl) { char *root_certs = NULL; grpc_ssl_pem_key_cert_pair key_cert_pair = {NULL, NULL}; if (::node::Buffer::HasInstance(info[0])) { root_certs = ::node::Buffer::Data(info[0]); } else if (!(info[0]->IsNull() || info[0]->IsUndefined())) { return Nan::ThrowTypeError("createSsl's first argument must be a Buffer"); } if (::node::Buffer::HasInstance(info[1])) { key_cert_pair.private_key = ::node::Buffer::Data(info[1]); } else if (!(info[1]->IsNull() || info[1]->IsUndefined())) { return Nan::ThrowTypeError( "createSSl's second argument must be a Buffer if provided"); } if (::node::Buffer::HasInstance(info[2])) { key_cert_pair.cert_chain = ::node::Buffer::Data(info[2]); } else if (!(info[2]->IsNull() || info[2]->IsUndefined())) { return Nan::ThrowTypeError( "createSSl's third argument must be a Buffer if provided"); } if ((key_cert_pair.private_key == NULL) != (key_cert_pair.cert_chain == NULL)) { return Nan::ThrowError( "createSsl's second and third arguments must be" " provided or omitted together"); } grpc_channel_credentials *creds = grpc_ssl_credentials_create( root_certs, key_cert_pair.private_key == NULL ? NULL : &key_cert_pair, NULL); if (creds == NULL) { info.GetReturnValue().SetNull(); } else { info.GetReturnValue().Set(WrapStruct(creds)); } } NAN_METHOD(ChannelCredentials::Compose) { if (!ChannelCredentials::HasInstance(info.This())) { return Nan::ThrowTypeError( "compose can only be called on ChannelCredentials objects"); } if (!CallCredentials::HasInstance(info[0])) { return Nan::ThrowTypeError( "compose's first argument must be a CallCredentials object"); } ChannelCredentials *self = ObjectWrap::Unwrap( info.This()); if (self->wrapped_credentials == NULL) { return Nan::ThrowTypeError( "Cannot compose insecure credential"); } CallCredentials *other = ObjectWrap::Unwrap( Nan::To(info[0]).ToLocalChecked()); grpc_channel_credentials *creds = grpc_composite_channel_credentials_create( self->wrapped_credentials, other->GetWrappedCredentials(), NULL); if (creds == NULL) { info.GetReturnValue().SetNull(); } else { info.GetReturnValue().Set(WrapStruct(creds)); } } NAN_METHOD(ChannelCredentials::CreateInsecure) { info.GetReturnValue().Set(WrapStruct(NULL)); } } // namespace node } // namespace grpc grpc-1.3.2/src/node/ext/channel_credentials.h000066400000000000000000000056131310511640000211160ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef NET_GRPC_NODE_CHANNEL_CREDENTIALS_H_ #define NET_GRPC_NODE_CHANNEL_CREDENTIALS_H_ #include #include #include "grpc/grpc.h" #include "grpc/grpc_security.h" namespace grpc { namespace node { /* Wrapper class for grpc_channel_credentials structs */ class ChannelCredentials : public Nan::ObjectWrap { public: static void Init(v8::Local exports); static bool HasInstance(v8::Local val); /* Wrap a grpc_channel_credentials struct in a javascript object */ static v8::Local WrapStruct(grpc_channel_credentials *credentials); /* Returns the grpc_channel_credentials struct that this object wraps */ grpc_channel_credentials *GetWrappedCredentials(); private: explicit ChannelCredentials(grpc_channel_credentials *credentials); ~ChannelCredentials(); // Prevent copying ChannelCredentials(const ChannelCredentials &); ChannelCredentials &operator=(const ChannelCredentials &); static NAN_METHOD(New); static NAN_METHOD(CreateSsl); static NAN_METHOD(CreateInsecure); static NAN_METHOD(Compose); static Nan::Callback *constructor; // Used for typechecking instances of this javascript class static Nan::Persistent fun_tpl; grpc_channel_credentials *wrapped_credentials; }; } // namespace node } // namespace grpc #endif // NET_GRPC_NODE_CHANNEL_CREDENTIALS_H_ grpc-1.3.2/src/node/ext/completion_queue.cc000066400000000000000000000057071310511640000206500ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include "call.h" #include "completion_queue.h" namespace grpc { namespace node { using v8::Local; using v8::Object; using v8::Value; grpc_completion_queue *queue; uv_prepare_t prepare; int pending_batches; void drain_completion_queue(uv_prepare_t *handle) { Nan::HandleScope scope; grpc_event event; (void)handle; do { event = grpc_completion_queue_next( queue, gpr_inf_past(GPR_CLOCK_MONOTONIC), NULL); if (event.type == GRPC_OP_COMPLETE) { const char *error_message; if (event.success) { error_message = NULL; } else { error_message = "The async function encountered an error"; } CompleteTag(event.tag, error_message); grpc::node::DestroyTag(event.tag); pending_batches--; if (pending_batches == 0) { uv_prepare_stop(&prepare); } } } while (event.type != GRPC_QUEUE_TIMEOUT); } grpc_completion_queue *GetCompletionQueue() { return queue; } void CompletionQueueNext() { if (pending_batches == 0) { GPR_ASSERT(!uv_is_active((uv_handle_t *)&prepare)); uv_prepare_start(&prepare, drain_completion_queue); } pending_batches++; } void CompletionQueueInit(Local exports) { queue = grpc_completion_queue_create(NULL); uv_prepare_init(uv_default_loop(), &prepare); pending_batches = 0; } } // namespace node } // namespace grpc grpc-1.3.2/src/node/ext/completion_queue.h000066400000000000000000000034341310511640000205050ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include namespace grpc { namespace node { grpc_completion_queue *GetCompletionQueue(); void CompletionQueueNext(); void CompletionQueueInit(v8::Local exports); } // namespace node } // namespace grpc grpc-1.3.2/src/node/ext/node_grpc.cc000066400000000000000000000466371310511640000172420ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include "grpc/grpc.h" #include "grpc/grpc_security.h" #include "grpc/support/alloc.h" #include "grpc/support/log.h" #include "grpc/support/time.h" // TODO(murgatroid99): Remove this when the endpoint API becomes public extern "C" { #include "src/core/lib/iomgr/pollset_uv.h" } #include "call.h" #include "call_credentials.h" #include "channel.h" #include "channel_credentials.h" #include "server.h" #include "server_credentials.h" #include "slice.h" #include "timeval.h" #include "completion_queue.h" using grpc::node::CreateSliceFromString; using v8::FunctionTemplate; using v8::Local; using v8::Value; using v8::Number; using v8::Object; using v8::Uint32; using v8::String; typedef struct log_args { gpr_log_func_args core_args; gpr_timespec timestamp; } log_args; typedef struct logger_state { Nan::Callback *callback; std::queue *pending_args; uv_mutex_t mutex; uv_async_t async; // Indicates that a logger has been set bool logger_set; } logger_state; logger_state grpc_logger_state; static char *pem_root_certs = NULL; void InitStatusConstants(Local exports) { Nan::HandleScope scope; Local status = Nan::New(); Nan::Set(exports, Nan::New("status").ToLocalChecked(), status); Local OK(Nan::New(GRPC_STATUS_OK)); Nan::Set(status, Nan::New("OK").ToLocalChecked(), OK); Local CANCELLED(Nan::New(GRPC_STATUS_CANCELLED)); Nan::Set(status, Nan::New("CANCELLED").ToLocalChecked(), CANCELLED); Local UNKNOWN(Nan::New(GRPC_STATUS_UNKNOWN)); Nan::Set(status, Nan::New("UNKNOWN").ToLocalChecked(), UNKNOWN); Local INVALID_ARGUMENT( Nan::New(GRPC_STATUS_INVALID_ARGUMENT)); Nan::Set(status, Nan::New("INVALID_ARGUMENT").ToLocalChecked(), INVALID_ARGUMENT); Local DEADLINE_EXCEEDED( Nan::New(GRPC_STATUS_DEADLINE_EXCEEDED)); Nan::Set(status, Nan::New("DEADLINE_EXCEEDED").ToLocalChecked(), DEADLINE_EXCEEDED); Local NOT_FOUND(Nan::New(GRPC_STATUS_NOT_FOUND)); Nan::Set(status, Nan::New("NOT_FOUND").ToLocalChecked(), NOT_FOUND); Local ALREADY_EXISTS( Nan::New(GRPC_STATUS_ALREADY_EXISTS)); Nan::Set(status, Nan::New("ALREADY_EXISTS").ToLocalChecked(), ALREADY_EXISTS); Local PERMISSION_DENIED( Nan::New(GRPC_STATUS_PERMISSION_DENIED)); Nan::Set(status, Nan::New("PERMISSION_DENIED").ToLocalChecked(), PERMISSION_DENIED); Local UNAUTHENTICATED( Nan::New(GRPC_STATUS_UNAUTHENTICATED)); Nan::Set(status, Nan::New("UNAUTHENTICATED").ToLocalChecked(), UNAUTHENTICATED); Local RESOURCE_EXHAUSTED( Nan::New(GRPC_STATUS_RESOURCE_EXHAUSTED)); Nan::Set(status, Nan::New("RESOURCE_EXHAUSTED").ToLocalChecked(), RESOURCE_EXHAUSTED); Local FAILED_PRECONDITION( Nan::New(GRPC_STATUS_FAILED_PRECONDITION)); Nan::Set(status, Nan::New("FAILED_PRECONDITION").ToLocalChecked(), FAILED_PRECONDITION); Local ABORTED(Nan::New(GRPC_STATUS_ABORTED)); Nan::Set(status, Nan::New("ABORTED").ToLocalChecked(), ABORTED); Local OUT_OF_RANGE( Nan::New(GRPC_STATUS_OUT_OF_RANGE)); Nan::Set(status, Nan::New("OUT_OF_RANGE").ToLocalChecked(), OUT_OF_RANGE); Local UNIMPLEMENTED( Nan::New(GRPC_STATUS_UNIMPLEMENTED)); Nan::Set(status, Nan::New("UNIMPLEMENTED").ToLocalChecked(), UNIMPLEMENTED); Local INTERNAL(Nan::New(GRPC_STATUS_INTERNAL)); Nan::Set(status, Nan::New("INTERNAL").ToLocalChecked(), INTERNAL); Local UNAVAILABLE(Nan::New(GRPC_STATUS_UNAVAILABLE)); Nan::Set(status, Nan::New("UNAVAILABLE").ToLocalChecked(), UNAVAILABLE); Local DATA_LOSS(Nan::New(GRPC_STATUS_DATA_LOSS)); Nan::Set(status, Nan::New("DATA_LOSS").ToLocalChecked(), DATA_LOSS); } void InitCallErrorConstants(Local exports) { Nan::HandleScope scope; Local call_error = Nan::New(); Nan::Set(exports, Nan::New("callError").ToLocalChecked(), call_error); Local OK(Nan::New(GRPC_CALL_OK)); Nan::Set(call_error, Nan::New("OK").ToLocalChecked(), OK); Local CALL_ERROR(Nan::New(GRPC_CALL_ERROR)); Nan::Set(call_error, Nan::New("ERROR").ToLocalChecked(), CALL_ERROR); Local NOT_ON_SERVER( Nan::New(GRPC_CALL_ERROR_NOT_ON_SERVER)); Nan::Set(call_error, Nan::New("NOT_ON_SERVER").ToLocalChecked(), NOT_ON_SERVER); Local NOT_ON_CLIENT( Nan::New(GRPC_CALL_ERROR_NOT_ON_CLIENT)); Nan::Set(call_error, Nan::New("NOT_ON_CLIENT").ToLocalChecked(), NOT_ON_CLIENT); Local ALREADY_INVOKED( Nan::New(GRPC_CALL_ERROR_ALREADY_INVOKED)); Nan::Set(call_error, Nan::New("ALREADY_INVOKED").ToLocalChecked(), ALREADY_INVOKED); Local NOT_INVOKED( Nan::New(GRPC_CALL_ERROR_NOT_INVOKED)); Nan::Set(call_error, Nan::New("NOT_INVOKED").ToLocalChecked(), NOT_INVOKED); Local ALREADY_FINISHED( Nan::New(GRPC_CALL_ERROR_ALREADY_FINISHED)); Nan::Set(call_error, Nan::New("ALREADY_FINISHED").ToLocalChecked(), ALREADY_FINISHED); Local TOO_MANY_OPERATIONS( Nan::New(GRPC_CALL_ERROR_TOO_MANY_OPERATIONS)); Nan::Set(call_error, Nan::New("TOO_MANY_OPERATIONS").ToLocalChecked(), TOO_MANY_OPERATIONS); Local INVALID_FLAGS( Nan::New(GRPC_CALL_ERROR_INVALID_FLAGS)); Nan::Set(call_error, Nan::New("INVALID_FLAGS").ToLocalChecked(), INVALID_FLAGS); } void InitOpTypeConstants(Local exports) { Nan::HandleScope scope; Local op_type = Nan::New(); Nan::Set(exports, Nan::New("opType").ToLocalChecked(), op_type); Local SEND_INITIAL_METADATA( Nan::New(GRPC_OP_SEND_INITIAL_METADATA)); Nan::Set(op_type, Nan::New("SEND_INITIAL_METADATA").ToLocalChecked(), SEND_INITIAL_METADATA); Local SEND_MESSAGE( Nan::New(GRPC_OP_SEND_MESSAGE)); Nan::Set(op_type, Nan::New("SEND_MESSAGE").ToLocalChecked(), SEND_MESSAGE); Local SEND_CLOSE_FROM_CLIENT( Nan::New(GRPC_OP_SEND_CLOSE_FROM_CLIENT)); Nan::Set(op_type, Nan::New("SEND_CLOSE_FROM_CLIENT").ToLocalChecked(), SEND_CLOSE_FROM_CLIENT); Local SEND_STATUS_FROM_SERVER( Nan::New(GRPC_OP_SEND_STATUS_FROM_SERVER)); Nan::Set(op_type, Nan::New("SEND_STATUS_FROM_SERVER").ToLocalChecked(), SEND_STATUS_FROM_SERVER); Local RECV_INITIAL_METADATA( Nan::New(GRPC_OP_RECV_INITIAL_METADATA)); Nan::Set(op_type, Nan::New("RECV_INITIAL_METADATA").ToLocalChecked(), RECV_INITIAL_METADATA); Local RECV_MESSAGE( Nan::New(GRPC_OP_RECV_MESSAGE)); Nan::Set(op_type, Nan::New("RECV_MESSAGE").ToLocalChecked(), RECV_MESSAGE); Local RECV_STATUS_ON_CLIENT( Nan::New(GRPC_OP_RECV_STATUS_ON_CLIENT)); Nan::Set(op_type, Nan::New("RECV_STATUS_ON_CLIENT").ToLocalChecked(), RECV_STATUS_ON_CLIENT); Local RECV_CLOSE_ON_SERVER( Nan::New(GRPC_OP_RECV_CLOSE_ON_SERVER)); Nan::Set(op_type, Nan::New("RECV_CLOSE_ON_SERVER").ToLocalChecked(), RECV_CLOSE_ON_SERVER); } void InitPropagateConstants(Local exports) { Nan::HandleScope scope; Local propagate = Nan::New(); Nan::Set(exports, Nan::New("propagate").ToLocalChecked(), propagate); Local DEADLINE(Nan::New(GRPC_PROPAGATE_DEADLINE)); Nan::Set(propagate, Nan::New("DEADLINE").ToLocalChecked(), DEADLINE); Local CENSUS_STATS_CONTEXT( Nan::New(GRPC_PROPAGATE_CENSUS_STATS_CONTEXT)); Nan::Set(propagate, Nan::New("CENSUS_STATS_CONTEXT").ToLocalChecked(), CENSUS_STATS_CONTEXT); Local CENSUS_TRACING_CONTEXT( Nan::New(GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT)); Nan::Set(propagate, Nan::New("CENSUS_TRACING_CONTEXT").ToLocalChecked(), CENSUS_TRACING_CONTEXT); Local CANCELLATION( Nan::New(GRPC_PROPAGATE_CANCELLATION)); Nan::Set(propagate, Nan::New("CANCELLATION").ToLocalChecked(), CANCELLATION); Local DEFAULTS(Nan::New(GRPC_PROPAGATE_DEFAULTS)); Nan::Set(propagate, Nan::New("DEFAULTS").ToLocalChecked(), DEFAULTS); } void InitConnectivityStateConstants(Local exports) { Nan::HandleScope scope; Local channel_state = Nan::New(); Nan::Set(exports, Nan::New("connectivityState").ToLocalChecked(), channel_state); Local IDLE(Nan::New(GRPC_CHANNEL_IDLE)); Nan::Set(channel_state, Nan::New("IDLE").ToLocalChecked(), IDLE); Local CONNECTING(Nan::New(GRPC_CHANNEL_CONNECTING)); Nan::Set(channel_state, Nan::New("CONNECTING").ToLocalChecked(), CONNECTING); Local READY(Nan::New(GRPC_CHANNEL_READY)); Nan::Set(channel_state, Nan::New("READY").ToLocalChecked(), READY); Local TRANSIENT_FAILURE( Nan::New(GRPC_CHANNEL_TRANSIENT_FAILURE)); Nan::Set(channel_state, Nan::New("TRANSIENT_FAILURE").ToLocalChecked(), TRANSIENT_FAILURE); Local FATAL_FAILURE( Nan::New(GRPC_CHANNEL_SHUTDOWN)); Nan::Set(channel_state, Nan::New("FATAL_FAILURE").ToLocalChecked(), FATAL_FAILURE); } void InitWriteFlags(Local exports) { Nan::HandleScope scope; Local write_flags = Nan::New(); Nan::Set(exports, Nan::New("writeFlags").ToLocalChecked(), write_flags); Local BUFFER_HINT(Nan::New(GRPC_WRITE_BUFFER_HINT)); Nan::Set(write_flags, Nan::New("BUFFER_HINT").ToLocalChecked(), BUFFER_HINT); Local NO_COMPRESS(Nan::New(GRPC_WRITE_NO_COMPRESS)); Nan::Set(write_flags, Nan::New("NO_COMPRESS").ToLocalChecked(), NO_COMPRESS); } void InitLogConstants(Local exports) { Nan::HandleScope scope; Local log_verbosity = Nan::New(); Nan::Set(exports, Nan::New("logVerbosity").ToLocalChecked(), log_verbosity); Local LOG_DEBUG(Nan::New(GPR_LOG_SEVERITY_DEBUG)); Nan::Set(log_verbosity, Nan::New("DEBUG").ToLocalChecked(), LOG_DEBUG); Local LOG_INFO(Nan::New(GPR_LOG_SEVERITY_INFO)); Nan::Set(log_verbosity, Nan::New("INFO").ToLocalChecked(), LOG_INFO); Local LOG_ERROR(Nan::New(GPR_LOG_SEVERITY_ERROR)); Nan::Set(log_verbosity, Nan::New("ERROR").ToLocalChecked(), LOG_ERROR); } NAN_METHOD(MetadataKeyIsLegal) { if (!info[0]->IsString()) { return Nan::ThrowTypeError( "headerKeyIsLegal's argument must be a string"); } Local key = Nan::To(info[0]).ToLocalChecked(); grpc_slice slice = CreateSliceFromString(key); info.GetReturnValue().Set(static_cast( grpc_header_key_is_legal(slice))); grpc_slice_unref(slice); } NAN_METHOD(MetadataNonbinValueIsLegal) { if (!info[0]->IsString()) { return Nan::ThrowTypeError( "metadataNonbinValueIsLegal's argument must be a string"); } Local value = Nan::To(info[0]).ToLocalChecked(); grpc_slice slice = CreateSliceFromString(value); info.GetReturnValue().Set(static_cast( grpc_header_nonbin_value_is_legal(slice))); grpc_slice_unref(slice); } NAN_METHOD(MetadataKeyIsBinary) { if (!info[0]->IsString()) { return Nan::ThrowTypeError( "metadataKeyIsLegal's argument must be a string"); } Local key = Nan::To(info[0]).ToLocalChecked(); grpc_slice slice = CreateSliceFromString(key); info.GetReturnValue().Set(static_cast( grpc_is_binary_header(slice))); grpc_slice_unref(slice); } static grpc_ssl_roots_override_result get_ssl_roots_override( char **pem_root_certs_ptr) { *pem_root_certs_ptr = pem_root_certs; if (pem_root_certs == NULL) { return GRPC_SSL_ROOTS_OVERRIDE_FAIL; } else { return GRPC_SSL_ROOTS_OVERRIDE_OK; } } /* This should only be called once, and only before creating any *ServerCredentials */ NAN_METHOD(SetDefaultRootsPem) { if (!info[0]->IsString()) { return Nan::ThrowTypeError( "setDefaultRootsPem's argument must be a string"); } Nan::Utf8String utf8_roots(info[0]); size_t length = static_cast(utf8_roots.length()); if (length > 0) { const char *data = *utf8_roots; pem_root_certs = (char *)gpr_malloc((length + 1) * sizeof(char)); memcpy(pem_root_certs, data, length + 1); } } NAUV_WORK_CB(LogMessagesCallback) { Nan::HandleScope scope; std::queue args; uv_mutex_lock(&grpc_logger_state.mutex); grpc_logger_state.pending_args->swap(args); uv_mutex_unlock(&grpc_logger_state.mutex); /* Call the callback with each log message */ while (!args.empty()) { log_args *arg = args.front(); args.pop(); Local file = Nan::New(arg->core_args.file).ToLocalChecked(); Local line = Nan::New(arg->core_args.line); Local severity = Nan::New( gpr_log_severity_string(arg->core_args.severity)).ToLocalChecked(); Local message = Nan::New(arg->core_args.message).ToLocalChecked(); Local timestamp = Nan::New( grpc::node::TimespecToMilliseconds(arg->timestamp)).ToLocalChecked(); const int argc = 5; Local argv[argc] = {file, line, severity, message, timestamp}; grpc_logger_state.callback->Call(argc, argv); delete[] arg->core_args.message; delete arg; } } void node_log_func(gpr_log_func_args *args) { // TODO(mlumish): Use the core's log formatter when it becomes available log_args *args_copy = new log_args; size_t message_len = strlen(args->message) + 1; char *message = new char[message_len]; memcpy(message, args->message, message_len); memcpy(&args_copy->core_args, args, sizeof(gpr_log_func_args)); args_copy->core_args.message = message; args_copy->timestamp = gpr_now(GPR_CLOCK_REALTIME); uv_mutex_lock(&grpc_logger_state.mutex); grpc_logger_state.pending_args->push(args_copy); uv_mutex_unlock(&grpc_logger_state.mutex); uv_async_send(&grpc_logger_state.async); } void init_logger() { memset(&grpc_logger_state, 0, sizeof(logger_state)); grpc_logger_state.pending_args = new std::queue(); uv_mutex_init(&grpc_logger_state.mutex); uv_async_init(uv_default_loop(), &grpc_logger_state.async, LogMessagesCallback); uv_unref((uv_handle_t*)&grpc_logger_state.async); grpc_logger_state.logger_set = false; gpr_log_verbosity_init(); } /* This registers a JavaScript logger for messages from the gRPC core. Because that handler has to be run in the context of the JavaScript event loop, it will be run asynchronously. To minimize the problems that could cause for debugging, we leave core to do its default synchronous logging until a JavaScript logger is set */ NAN_METHOD(SetDefaultLoggerCallback) { if (!info[0]->IsFunction()) { return Nan::ThrowTypeError( "setDefaultLoggerCallback's argument must be a function"); } if (!grpc_logger_state.logger_set) { gpr_set_log_function(node_log_func); grpc_logger_state.logger_set = true; } grpc_logger_state.callback = new Nan::Callback(info[0].As()); } NAN_METHOD(SetLogVerbosity) { if (!info[0]->IsUint32()) { return Nan::ThrowTypeError( "setLogVerbosity's argument must be a number"); } gpr_log_severity severity = static_cast( Nan::To(info[0]).FromJust()); gpr_set_log_verbosity(severity); } void init(Local exports) { Nan::HandleScope scope; grpc_init(); grpc_set_ssl_roots_override_callback(get_ssl_roots_override); init_logger(); InitStatusConstants(exports); InitCallErrorConstants(exports); InitOpTypeConstants(exports); InitPropagateConstants(exports); InitConnectivityStateConstants(exports); InitWriteFlags(exports); InitLogConstants(exports); grpc_pollset_work_run_loop = 0; grpc::node::Call::Init(exports); grpc::node::CallCredentials::Init(exports); grpc::node::Channel::Init(exports); grpc::node::ChannelCredentials::Init(exports); grpc::node::Server::Init(exports); grpc::node::ServerCredentials::Init(exports); grpc::node::CompletionQueueInit(exports); // Attach a few utility functions directly to the module Nan::Set(exports, Nan::New("metadataKeyIsLegal").ToLocalChecked(), Nan::GetFunction( Nan::New(MetadataKeyIsLegal)).ToLocalChecked()); Nan::Set(exports, Nan::New("metadataNonbinValueIsLegal").ToLocalChecked(), Nan::GetFunction( Nan::New(MetadataNonbinValueIsLegal) ).ToLocalChecked()); Nan::Set(exports, Nan::New("metadataKeyIsBinary").ToLocalChecked(), Nan::GetFunction( Nan::New(MetadataKeyIsBinary) ).ToLocalChecked()); Nan::Set(exports, Nan::New("setDefaultRootsPem").ToLocalChecked(), Nan::GetFunction( Nan::New(SetDefaultRootsPem) ).ToLocalChecked()); Nan::Set(exports, Nan::New("setDefaultLoggerCallback").ToLocalChecked(), Nan::GetFunction( Nan::New(SetDefaultLoggerCallback) ).ToLocalChecked()); Nan::Set(exports, Nan::New("setLogVerbosity").ToLocalChecked(), Nan::GetFunction( Nan::New(SetLogVerbosity) ).ToLocalChecked()); } NODE_MODULE(grpc_node, init) grpc-1.3.2/src/node/ext/server.cc000066400000000000000000000266431310511640000166030ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "server.h" #include #include #include #include "call.h" #include "completion_queue.h" #include "grpc/grpc.h" #include "grpc/grpc_security.h" #include "grpc/support/log.h" #include "server_credentials.h" #include "slice.h" #include "timeval.h" namespace grpc { namespace node { using Nan::Callback; using Nan::EscapableHandleScope; using Nan::HandleScope; using Nan::Maybe; using Nan::MaybeLocal; using Nan::ObjectWrap; using Nan::Persistent; using Nan::Utf8String; using std::unique_ptr; using v8::Array; using v8::Boolean; using v8::Date; using v8::Exception; using v8::External; using v8::Function; using v8::FunctionTemplate; using v8::Local; using v8::Number; using v8::Object; using v8::String; using v8::Value; Nan::Callback *Server::constructor; Persistent Server::fun_tpl; static Callback *shutdown_callback = NULL; class ServerShutdownOp : public Op { public: ServerShutdownOp(grpc_server *server) : server(server) {} ~ServerShutdownOp() {} Local GetNodeValue() const { return Nan::Null(); } bool ParseOp(Local value, grpc_op *out) { return true; } bool IsFinalOp() { return false; } void OnComplete(bool success) { /* Because cancel_all_calls was called, we assume that shutdown_and_notify completes successfully */ grpc_server_destroy(server); } grpc_server *server; protected: std::string GetTypeString() const { return "shutdown"; } }; class NewCallOp : public Op { public: NewCallOp() { call = NULL; grpc_call_details_init(&details); grpc_metadata_array_init(&request_metadata); } ~NewCallOp() { grpc_call_details_destroy(&details); grpc_metadata_array_destroy(&request_metadata); } Local GetNodeValue() const { Nan::EscapableHandleScope scope; if (call == NULL) { return scope.Escape(Nan::Null()); } Local obj = Nan::New(); Nan::Set(obj, Nan::New("call").ToLocalChecked(), Call::WrapStruct(call)); // TODO(murgatroid99): Use zero-copy string construction instead Nan::Set(obj, Nan::New("method").ToLocalChecked(), CopyStringFromSlice(details.method)); Nan::Set(obj, Nan::New("host").ToLocalChecked(), CopyStringFromSlice(details.host)); Nan::Set(obj, Nan::New("deadline").ToLocalChecked(), Nan::New(TimespecToMilliseconds(details.deadline)) .ToLocalChecked()); Nan::Set(obj, Nan::New("metadata").ToLocalChecked(), ParseMetadata(&request_metadata)); return scope.Escape(obj); } bool ParseOp(Local value, grpc_op *out) { return true; } bool IsFinalOp() { return false; } void OnComplete(bool success) { } grpc_call *call; grpc_call_details details; grpc_metadata_array request_metadata; protected: std::string GetTypeString() const { return "new_call"; } }; class TryShutdownOp: public Op { public: TryShutdownOp(Server *server, Local server_value) : server(server) { server_persist.Reset(server_value); } Local GetNodeValue() const { EscapableHandleScope scope; return scope.Escape(Nan::New(server_persist)); } bool ParseOp(Local value, grpc_op *out) { return true; } bool IsFinalOp() { return false; } void OnComplete(bool success) { if (success) { server->DestroyWrappedServer(); } } protected: std::string GetTypeString() const { return "try_shutdown"; } private: Server *server; Nan::Persistent> server_persist; }; Server::Server(grpc_server *server) : wrapped_server(server) {} Server::~Server() { this->ShutdownServer(); } void Server::Init(Local exports) { HandleScope scope; Local tpl = Nan::New(New); tpl->SetClassName(Nan::New("Server").ToLocalChecked()); tpl->InstanceTemplate()->SetInternalFieldCount(1); Nan::SetPrototypeMethod(tpl, "requestCall", RequestCall); Nan::SetPrototypeMethod(tpl, "addHttp2Port", AddHttp2Port); Nan::SetPrototypeMethod(tpl, "start", Start); Nan::SetPrototypeMethod(tpl, "tryShutdown", TryShutdown); Nan::SetPrototypeMethod(tpl, "forceShutdown", ForceShutdown); fun_tpl.Reset(tpl); Local ctr = Nan::GetFunction(tpl).ToLocalChecked(); Nan::Set(exports, Nan::New("Server").ToLocalChecked(), ctr); constructor = new Callback(ctr); } bool Server::HasInstance(Local val) { HandleScope scope; return Nan::New(fun_tpl)->HasInstance(val); } void Server::DestroyWrappedServer() { if (this->wrapped_server != NULL) { grpc_server_destroy(this->wrapped_server); this->wrapped_server = NULL; } } NAN_METHOD(ServerShutdownCallback) { if (!info[0]->IsNull()) { return Nan::ThrowError("forceShutdown failed somehow"); } } void Server::ShutdownServer() { Nan::HandleScope scope; if (this->wrapped_server != NULL) { if (shutdown_callback == NULL) { Local callback_tpl = Nan::New(ServerShutdownCallback); shutdown_callback = new Callback(Nan::GetFunction(callback_tpl).ToLocalChecked()); } ServerShutdownOp *op = new ServerShutdownOp(this->wrapped_server); unique_ptr ops(new OpVec()); ops->push_back(unique_ptr(op)); grpc_server_shutdown_and_notify( this->wrapped_server, GetCompletionQueue(), new struct tag(new Callback(**shutdown_callback), ops.release(), NULL, Nan::Null())); grpc_server_cancel_all_calls(this->wrapped_server); CompletionQueueNext(); this->wrapped_server = NULL; } } NAN_METHOD(Server::New) { /* If this is not a constructor call, make a constructor call and return the result */ if (!info.IsConstructCall()) { const int argc = 1; Local argv[argc] = {info[0]}; MaybeLocal maybe_instance = Nan::NewInstance(constructor->GetFunction(), argc, argv); if (maybe_instance.IsEmpty()) { // There's probably a pending exception return; } else { info.GetReturnValue().Set(maybe_instance.ToLocalChecked()); return; } } grpc_server *wrapped_server; grpc_completion_queue *queue = GetCompletionQueue(); grpc_channel_args *channel_args; if (!ParseChannelArgs(info[0], &channel_args)) { DeallocateChannelArgs(channel_args); return Nan::ThrowTypeError( "Server options must be an object with " "string keys and integer or string values"); } wrapped_server = grpc_server_create(channel_args, NULL); DeallocateChannelArgs(channel_args); grpc_server_register_completion_queue(wrapped_server, queue, NULL); Server *server = new Server(wrapped_server); server->Wrap(info.This()); info.GetReturnValue().Set(info.This()); } NAN_METHOD(Server::RequestCall) { if (!HasInstance(info.This())) { return Nan::ThrowTypeError("requestCall can only be called on a Server"); } Server *server = ObjectWrap::Unwrap(info.This()); NewCallOp *op = new NewCallOp(); unique_ptr ops(new OpVec()); ops->push_back(unique_ptr(op)); grpc_call_error error = grpc_server_request_call( server->wrapped_server, &op->call, &op->details, &op->request_metadata, GetCompletionQueue(), GetCompletionQueue(), new struct tag(new Callback(info[0].As()), ops.release(), NULL, Nan::Null())); if (error != GRPC_CALL_OK) { return Nan::ThrowError(nanErrorWithCode("requestCall failed", error)); } CompletionQueueNext(); } NAN_METHOD(Server::AddHttp2Port) { if (!HasInstance(info.This())) { return Nan::ThrowTypeError("addHttp2Port can only be called on a Server"); } if (!info[0]->IsString()) { return Nan::ThrowTypeError( "addHttp2Port's first argument must be a String"); } if (!ServerCredentials::HasInstance(info[1])) { return Nan::ThrowTypeError( "addHttp2Port's second argument must be ServerCredentials"); } Server *server = ObjectWrap::Unwrap(info.This()); ServerCredentials *creds_object = ObjectWrap::Unwrap( Nan::To(info[1]).ToLocalChecked()); grpc_server_credentials *creds = creds_object->GetWrappedServerCredentials(); int port; if (creds == NULL) { port = grpc_server_add_insecure_http2_port(server->wrapped_server, *Utf8String(info[0])); } else { port = grpc_server_add_secure_http2_port(server->wrapped_server, *Utf8String(info[0]), creds); } info.GetReturnValue().Set(Nan::New(port)); } NAN_METHOD(Server::Start) { Nan::HandleScope scope; if (!HasInstance(info.This())) { return Nan::ThrowTypeError("start can only be called on a Server"); } Server *server = ObjectWrap::Unwrap(info.This()); grpc_server_start(server->wrapped_server); } NAN_METHOD(Server::TryShutdown) { Nan::HandleScope scope; if (!HasInstance(info.This())) { return Nan::ThrowTypeError("tryShutdown can only be called on a Server"); } Server *server = ObjectWrap::Unwrap(info.This()); if (server->wrapped_server == NULL) { // Server is already shut down. Call callback immediately. Nan::Callback callback(info[0].As()); callback.Call(0, {}); return; } TryShutdownOp *op = new TryShutdownOp(server, info.This()); unique_ptr ops(new OpVec()); ops->push_back(unique_ptr(op)); grpc_server_shutdown_and_notify( server->wrapped_server, GetCompletionQueue(), new struct tag(new Nan::Callback(info[0].As()), ops.release(), NULL, Nan::Null())); CompletionQueueNext(); } NAN_METHOD(Server::ForceShutdown) { Nan::HandleScope scope; if (!HasInstance(info.This())) { return Nan::ThrowTypeError("forceShutdown can only be called on a Server"); } Server *server = ObjectWrap::Unwrap(info.This()); server->ShutdownServer(); } } // namespace node } // namespace grpc grpc-1.3.2/src/node/ext/server.h000066400000000000000000000055631310511640000164430ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef NET_GRPC_NODE_SERVER_H_ #define NET_GRPC_NODE_SERVER_H_ #include #include #include "grpc/grpc.h" namespace grpc { namespace node { /* Wraps grpc_server as a JavaScript object. Provides a constructor and wrapper methods for grpc_server_create, grpc_server_request_call, grpc_server_add_http2_port, and grpc_server_start. */ class Server : public Nan::ObjectWrap { public: /* Initializes the Server class and exposes the constructor and wrapper methods to JavaScript */ static void Init(v8::Local exports); /* Tests whether the given value was constructed by this class's JavaScript constructor */ static bool HasInstance(v8::Local val); void DestroyWrappedServer(); private: explicit Server(grpc_server *server); ~Server(); // Prevent copying Server(const Server &); Server &operator=(const Server &); void ShutdownServer(); static NAN_METHOD(New); static NAN_METHOD(RequestCall); static NAN_METHOD(AddHttp2Port); static NAN_METHOD(Start); static NAN_METHOD(TryShutdown); static NAN_METHOD(ForceShutdown); static Nan::Callback *constructor; static Nan::Persistent fun_tpl; grpc_server *wrapped_server; grpc_completion_queue *shutdown_queue; }; } // namespace node } // namespace grpc #endif // NET_GRPC_NODE_SERVER_H_ grpc-1.3.2/src/node/ext/server_credentials.cc000066400000000000000000000165301310511640000211520ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "grpc/grpc.h" #include "grpc/grpc_security.h" #include "grpc/support/log.h" #include "server_credentials.h" namespace grpc { namespace node { using Nan::Callback; using Nan::EscapableHandleScope; using Nan::HandleScope; using Nan::Maybe; using Nan::MaybeLocal; using Nan::ObjectWrap; using Nan::Persistent; using Nan::Utf8String; using v8::Array; using v8::Exception; using v8::External; using v8::Function; using v8::FunctionTemplate; using v8::Integer; using v8::Local; using v8::Object; using v8::ObjectTemplate; using v8::String; using v8::Value; Nan::Callback *ServerCredentials::constructor; Persistent ServerCredentials::fun_tpl; ServerCredentials::ServerCredentials(grpc_server_credentials *credentials) : wrapped_credentials(credentials) {} ServerCredentials::~ServerCredentials() { grpc_server_credentials_release(wrapped_credentials); } void ServerCredentials::Init(Local exports) { Nan::HandleScope scope; Local tpl = Nan::New(New); tpl->SetClassName(Nan::New("ServerCredentials").ToLocalChecked()); tpl->InstanceTemplate()->SetInternalFieldCount(1); Local ctr = tpl->GetFunction(); Nan::Set(ctr, Nan::New("createSsl").ToLocalChecked(), Nan::GetFunction( Nan::New(CreateSsl)).ToLocalChecked()); Nan::Set(ctr, Nan::New("createInsecure").ToLocalChecked(), Nan::GetFunction( Nan::New(CreateInsecure)).ToLocalChecked()); fun_tpl.Reset(tpl); constructor = new Nan::Callback(ctr); Nan::Set(exports, Nan::New("ServerCredentials").ToLocalChecked(), ctr); } bool ServerCredentials::HasInstance(Local val) { Nan::HandleScope scope; return Nan::New(fun_tpl)->HasInstance(val); } Local ServerCredentials::WrapStruct( grpc_server_credentials *credentials) { Nan::EscapableHandleScope scope; const int argc = 1; Local argv[argc] = { Nan::New(reinterpret_cast(credentials))}; MaybeLocal maybe_instance = Nan::NewInstance( constructor->GetFunction(), argc, argv); if (maybe_instance.IsEmpty()) { return scope.Escape(Nan::Null()); } else { return scope.Escape(maybe_instance.ToLocalChecked()); } } grpc_server_credentials *ServerCredentials::GetWrappedServerCredentials() { return wrapped_credentials; } NAN_METHOD(ServerCredentials::New) { if (info.IsConstructCall()) { if (!info[0]->IsExternal()) { return Nan::ThrowTypeError( "ServerCredentials can only be created with the provided functions"); } Local ext = info[0].As(); grpc_server_credentials *creds_value = reinterpret_cast(ext->Value()); ServerCredentials *credentials = new ServerCredentials(creds_value); credentials->Wrap(info.This()); info.GetReturnValue().Set(info.This()); } else { // This should never be called directly return Nan::ThrowTypeError( "ServerCredentials can only be created with the provided functions"); } } NAN_METHOD(ServerCredentials::CreateSsl) { Nan::HandleScope scope; char *root_certs = NULL; if (::node::Buffer::HasInstance(info[0])) { root_certs = ::node::Buffer::Data(info[0]); } else if (!(info[0]->IsNull() || info[0]->IsUndefined())) { return Nan::ThrowTypeError( "createSSl's first argument must be a Buffer if provided"); } if (!info[1]->IsArray()) { return Nan::ThrowTypeError( "createSsl's second argument must be a list of objects"); } // Default to not requesting the client certificate grpc_ssl_client_certificate_request_type client_certificate_request = GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE; if (info[2]->IsBoolean()) { client_certificate_request = Nan::To(info[2]).FromJust() ? GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY : GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE; } else if (!(info[2]->IsUndefined() || info[2]->IsNull())) { return Nan::ThrowTypeError( "createSsl's third argument must be a boolean if provided"); } Local pair_list = Local::Cast(info[1]); uint32_t key_cert_pair_count = pair_list->Length(); grpc_ssl_pem_key_cert_pair *key_cert_pairs = new grpc_ssl_pem_key_cert_pair[ key_cert_pair_count]; Local key_key = Nan::New("private_key").ToLocalChecked(); Local cert_key = Nan::New("cert_chain").ToLocalChecked(); for(uint32_t i = 0; i < key_cert_pair_count; i++) { Local pair_val = Nan::Get(pair_list, i).ToLocalChecked(); if (!pair_val->IsObject()) { delete[] key_cert_pairs; return Nan::ThrowTypeError("Key/cert pairs must be objects"); } Local pair_obj = Nan::To(pair_val).ToLocalChecked(); Local maybe_key = Nan::Get(pair_obj, key_key).ToLocalChecked(); Local maybe_cert = Nan::Get(pair_obj, cert_key).ToLocalChecked(); if (!::node::Buffer::HasInstance(maybe_key)) { delete[] key_cert_pairs; return Nan::ThrowTypeError("private_key must be a Buffer"); } if (!::node::Buffer::HasInstance(maybe_cert)) { delete[] key_cert_pairs; return Nan::ThrowTypeError("cert_chain must be a Buffer"); } key_cert_pairs[i].private_key = ::node::Buffer::Data(maybe_key); key_cert_pairs[i].cert_chain = ::node::Buffer::Data(maybe_cert); } grpc_server_credentials *creds = grpc_ssl_server_credentials_create_ex( root_certs, key_cert_pairs, key_cert_pair_count, client_certificate_request, NULL); delete[] key_cert_pairs; if (creds == NULL) { info.GetReturnValue().SetNull(); } else { info.GetReturnValue().Set(WrapStruct(creds)); } } NAN_METHOD(ServerCredentials::CreateInsecure) { info.GetReturnValue().Set(WrapStruct(NULL)); } } // namespace node } // namespace grpc grpc-1.3.2/src/node/ext/server_credentials.h000066400000000000000000000055411310511640000210140ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef NET_GRPC_NODE_SERVER_CREDENTIALS_H_ #define NET_GRPC_NODE_SERVER_CREDENTIALS_H_ #include #include #include "grpc/grpc.h" #include "grpc/grpc_security.h" namespace grpc { namespace node { /* Wrapper class for grpc_server_credentials structs */ class ServerCredentials : public Nan::ObjectWrap { public: static void Init(v8::Local exports); static bool HasInstance(v8::Local val); /* Wrap a grpc_server_credentials struct in a javascript object */ static v8::Local WrapStruct(grpc_server_credentials *credentials); /* Returns the grpc_server_credentials struct that this object wraps */ grpc_server_credentials *GetWrappedServerCredentials(); private: explicit ServerCredentials(grpc_server_credentials *credentials); ~ServerCredentials(); // Prevent copying ServerCredentials(const ServerCredentials &); ServerCredentials &operator=(const ServerCredentials &); static NAN_METHOD(New); static NAN_METHOD(CreateSsl); static NAN_METHOD(CreateInsecure); static Nan::Callback *constructor; // Used for typechecking instances of this javascript class static Nan::Persistent fun_tpl; grpc_server_credentials *wrapped_credentials; }; } // namespace node } // namespace grpc #endif // NET_GRPC_NODE_SERVER_CREDENTIALS_H_ grpc-1.3.2/src/node/ext/slice.cc000066400000000000000000000071561310511640000163720ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include "slice.h" namespace grpc { namespace node { using Nan::Persistent; using v8::Local; using v8::String; using v8::Value; namespace { void SliceFreeCallback(char *data, void *hint) { grpc_slice *slice = reinterpret_cast(hint); grpc_slice_unref(*slice); delete slice; } void string_destroy_func(void *user_data) { delete reinterpret_cast(user_data); } void buffer_destroy_func(void *user_data) { delete reinterpret_cast(user_data); } } // namespace grpc_slice CreateSliceFromString(const Local source) { Nan::HandleScope scope; Nan::Utf8String *utf8_value = new Nan::Utf8String(source); return grpc_slice_new_with_user_data(**utf8_value, source->Length(), string_destroy_func, utf8_value); } grpc_slice CreateSliceFromBuffer(const Local source) { // Prerequisite: ::node::Buffer::HasInstance(source) Nan::HandleScope scope; return grpc_slice_new_with_user_data(::node::Buffer::Data(source), ::node::Buffer::Length(source), buffer_destroy_func, new PersistentValue(source)); } Local CopyStringFromSlice(const grpc_slice slice) { Nan::EscapableHandleScope scope; if (GRPC_SLICE_LENGTH(slice) == 0) { return scope.Escape(Nan::EmptyString()); } return scope.Escape(Nan::New( const_cast(reinterpret_cast(GRPC_SLICE_START_PTR(slice))), GRPC_SLICE_LENGTH(slice)).ToLocalChecked()); } Local CreateBufferFromSlice(const grpc_slice slice) { Nan::EscapableHandleScope scope; grpc_slice *slice_ptr = new grpc_slice; *slice_ptr = grpc_slice_ref(slice); return scope.Escape(Nan::NewBuffer( const_cast(reinterpret_cast(GRPC_SLICE_START_PTR(*slice_ptr))), GRPC_SLICE_LENGTH(*slice_ptr), SliceFreeCallback, slice_ptr).ToLocalChecked()); } } // namespace node } // namespace grpc grpc-1.3.2/src/node/ext/slice.h000066400000000000000000000040401310511640000162210ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include namespace grpc { namespace node { typedef Nan::Persistent> PersistentValue; grpc_slice CreateSliceFromString(const v8::Local source); grpc_slice CreateSliceFromBuffer(const v8::Local source); v8::Local CopyStringFromSlice(const grpc_slice slice); v8::Local CreateBufferFromSlice(const grpc_slice slice); } // namespace node } // namespace grpc grpc-1.3.2/src/node/ext/timeval.cc000066400000000000000000000052001310511640000167200ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include "grpc/grpc.h" #include "grpc/support/time.h" #include "timeval.h" namespace grpc { namespace node { gpr_timespec MillisecondsToTimespec(double millis) { if (millis == std::numeric_limits::infinity()) { return gpr_inf_future(GPR_CLOCK_REALTIME); } else if (millis == -std::numeric_limits::infinity()) { return gpr_inf_past(GPR_CLOCK_REALTIME); } else { return gpr_time_from_micros(static_cast(millis * 1000), GPR_CLOCK_REALTIME); } } double TimespecToMilliseconds(gpr_timespec timespec) { timespec = gpr_convert_clock_type(timespec, GPR_CLOCK_REALTIME); if (gpr_time_cmp(timespec, gpr_inf_future(GPR_CLOCK_REALTIME)) == 0) { return std::numeric_limits::infinity(); } else if (gpr_time_cmp(timespec, gpr_inf_past(GPR_CLOCK_REALTIME)) == 0) { return -std::numeric_limits::infinity(); } else { return (static_cast(timespec.tv_sec) * 1000 + static_cast(timespec.tv_nsec) / 1000000); } } } // namespace node } // namespace grpc grpc-1.3.2/src/node/ext/timeval.h000066400000000000000000000035361310511640000165740ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef NET_GRPC_NODE_TIMEVAL_H_ #define NET_GRPC_NODE_TIMEVAL_H_ #include "grpc/support/time.h" namespace grpc { namespace node { double TimespecToMilliseconds(gpr_timespec time); gpr_timespec MillisecondsToTimespec(double millis); } // namespace node } // namespace grpc #endif // NET_GRPC_NODE_TIMEVAL_H_ grpc-1.3.2/src/node/health_check/000077500000000000000000000000001310511640000165555ustar00rootroot00000000000000grpc-1.3.2/src/node/health_check/LICENSE000066400000000000000000000027031310511640000175640ustar00rootroot00000000000000Copyright 2015, Google Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/node/health_check/health.js000066400000000000000000000046271310511640000203710ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var grpc = require('grpc'); var _ = require('lodash'); var health_messages = require('./v1/health_pb'); var health_service = require('./v1/health_grpc_pb'); function HealthImplementation(statusMap) { this.statusMap = _.clone(statusMap); } HealthImplementation.prototype.setStatus = function(service, status) { this.statusMap[service] = status; }; HealthImplementation.prototype.check = function(call, callback){ var service = call.request.getService(); var status = _.get(this.statusMap, service, null); if (status === null) { callback({code:grpc.status.NOT_FOUND}); } else { var response = new health_messages.HealthCheckResponse(); response.setStatus(status); callback(null, response); } }; module.exports = { Client: health_service.HealthClient, service: health_service.HealthService, Implementation: HealthImplementation }; grpc-1.3.2/src/node/health_check/node_modules/000077500000000000000000000000001310511640000212325ustar00rootroot00000000000000grpc-1.3.2/src/node/health_check/node_modules/grpc.js000066400000000000000000000032661310511640000225320ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* This exists solely to allow the generated code to import the grpc module * without using a relative path */ module.exports = require('../..'); grpc-1.3.2/src/node/health_check/package.json000066400000000000000000000011361310511640000210440ustar00rootroot00000000000000{ "name": "grpc-health-check", "version": "1.3.2", "author": "Google Inc.", "description": "Health check service for use with gRPC", "repository": { "type": "git", "url": "https://github.com/grpc/grpc.git" }, "bugs": "https://github.com/grpc/grpc/issues", "contributors": [ { "name": "Michael Lumish", "email": "mlumish@google.com" } ], "dependencies": { "grpc": "^1.3.2", "lodash": "^3.9.3", "google-protobuf": "^3.0.0" }, "files": [ "LICENSE", "health.js", "v1" ], "main": "src/node/index.js", "license": "BSD-3-Clause" } grpc-1.3.2/src/node/health_check/v1/000077500000000000000000000000001310511640000171035ustar00rootroot00000000000000grpc-1.3.2/src/node/health_check/v1/health_grpc_pb.js000066400000000000000000000057061310511640000224120ustar00rootroot00000000000000// GENERATED CODE -- DO NOT EDIT! // Original file comments: // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // 'use strict'; var grpc = require('grpc'); var v1_health_pb = require('../v1/health_pb.js'); function serialize_HealthCheckRequest(arg) { if (!(arg instanceof v1_health_pb.HealthCheckRequest)) { throw new Error('Expected argument of type HealthCheckRequest'); } return new Buffer(arg.serializeBinary()); } function deserialize_HealthCheckRequest(buffer_arg) { return v1_health_pb.HealthCheckRequest.deserializeBinary(new Uint8Array(buffer_arg)); } function serialize_HealthCheckResponse(arg) { if (!(arg instanceof v1_health_pb.HealthCheckResponse)) { throw new Error('Expected argument of type HealthCheckResponse'); } return new Buffer(arg.serializeBinary()); } function deserialize_HealthCheckResponse(buffer_arg) { return v1_health_pb.HealthCheckResponse.deserializeBinary(new Uint8Array(buffer_arg)); } var HealthService = exports.HealthService = { check: { path: '/grpc.health.v1.Health/Check', requestStream: false, responseStream: false, requestType: v1_health_pb.HealthCheckRequest, responseType: v1_health_pb.HealthCheckResponse, requestSerialize: serialize_HealthCheckRequest, requestDeserialize: deserialize_HealthCheckRequest, responseSerialize: serialize_HealthCheckResponse, responseDeserialize: deserialize_HealthCheckResponse, }, }; exports.HealthClient = grpc.makeGenericClientConstructor(HealthService); grpc-1.3.2/src/node/health_check/v1/health_pb.js000066400000000000000000000251451310511640000213760ustar00rootroot00000000000000/** * @fileoverview * @enhanceable * @public */ // GENERATED CODE -- DO NOT EDIT! var jspb = require('google-protobuf'); var goog = jspb; var global = Function('return this')(); goog.exportSymbol('proto.grpc.health.v1.HealthCheckRequest', null, global); goog.exportSymbol('proto.grpc.health.v1.HealthCheckResponse', null, global); goog.exportSymbol('proto.grpc.health.v1.HealthCheckResponse.ServingStatus', null, global); /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a * server response, or constructed directly in Javascript. The array is used * in place and becomes part of the constructed object. It is not cloned. * If no data is provided, the constructed object will be empty, but still * valid. * @extends {jspb.Message} * @constructor */ proto.grpc.health.v1.HealthCheckRequest = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; goog.inherits(proto.grpc.health.v1.HealthCheckRequest, jspb.Message); if (goog.DEBUG && !COMPILED) { proto.grpc.health.v1.HealthCheckRequest.displayName = 'proto.grpc.health.v1.HealthCheckRequest'; } if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto suitable for use in Soy templates. * Field names that are reserved in JavaScript and will be renamed to pb_name. * To access a reserved field use, foo.pb_, eg, foo.pb_default. * For the list of reserved names please see: * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration * @return {!Object} */ proto.grpc.health.v1.HealthCheckRequest.prototype.toObject = function(opt_includeInstance) { return proto.grpc.health.v1.HealthCheckRequest.toObject(opt_includeInstance, this); }; /** * Static version of the {@see toObject} method. * @param {boolean|undefined} includeInstance Whether to include the JSPB * instance for transitional soy proto support: * http://goto/soy-param-migration * @param {!proto.grpc.health.v1.HealthCheckRequest} msg The msg instance to transform. * @return {!Object} */ proto.grpc.health.v1.HealthCheckRequest.toObject = function(includeInstance, msg) { var f, obj = { service: msg.getService() }; if (includeInstance) { obj.$jspbMessageInstance = msg; } return obj; }; } /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. * @return {!proto.grpc.health.v1.HealthCheckRequest} */ proto.grpc.health.v1.HealthCheckRequest.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); var msg = new proto.grpc.health.v1.HealthCheckRequest; return proto.grpc.health.v1.HealthCheckRequest.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. * @param {!proto.grpc.health.v1.HealthCheckRequest} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. * @return {!proto.grpc.health.v1.HealthCheckRequest} */ proto.grpc.health.v1.HealthCheckRequest.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); switch (field) { case 1: var value = /** @type {string} */ (reader.readString()); msg.setService(value); break; default: reader.skipField(); break; } } return msg; }; /** * Class method variant: serializes the given message to binary data * (in protobuf wire format), writing to the given BinaryWriter. * @param {!proto.grpc.health.v1.HealthCheckRequest} message * @param {!jspb.BinaryWriter} writer */ proto.grpc.health.v1.HealthCheckRequest.serializeBinaryToWriter = function(message, writer) { message.serializeBinaryToWriter(writer); }; /** * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ proto.grpc.health.v1.HealthCheckRequest.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); this.serializeBinaryToWriter(writer); return writer.getResultBuffer(); }; /** * Serializes the message to binary data (in protobuf wire format), * writing to the given BinaryWriter. * @param {!jspb.BinaryWriter} writer */ proto.grpc.health.v1.HealthCheckRequest.prototype.serializeBinaryToWriter = function (writer) { var f = undefined; f = this.getService(); if (f.length > 0) { writer.writeString( 1, f ); } }; /** * Creates a deep clone of this proto. No data is shared with the original. * @return {!proto.grpc.health.v1.HealthCheckRequest} The clone. */ proto.grpc.health.v1.HealthCheckRequest.prototype.cloneMessage = function() { return /** @type {!proto.grpc.health.v1.HealthCheckRequest} */ (jspb.Message.cloneMessage(this)); }; /** * optional string service = 1; * @return {string} */ proto.grpc.health.v1.HealthCheckRequest.prototype.getService = function() { return /** @type {string} */ (jspb.Message.getFieldProto3(this, 1, "")); }; /** @param {string} value */ proto.grpc.health.v1.HealthCheckRequest.prototype.setService = function(value) { jspb.Message.setField(this, 1, value); }; /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a * server response, or constructed directly in Javascript. The array is used * in place and becomes part of the constructed object. It is not cloned. * If no data is provided, the constructed object will be empty, but still * valid. * @extends {jspb.Message} * @constructor */ proto.grpc.health.v1.HealthCheckResponse = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; goog.inherits(proto.grpc.health.v1.HealthCheckResponse, jspb.Message); if (goog.DEBUG && !COMPILED) { proto.grpc.health.v1.HealthCheckResponse.displayName = 'proto.grpc.health.v1.HealthCheckResponse'; } if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto suitable for use in Soy templates. * Field names that are reserved in JavaScript and will be renamed to pb_name. * To access a reserved field use, foo.pb_, eg, foo.pb_default. * For the list of reserved names please see: * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration * @return {!Object} */ proto.grpc.health.v1.HealthCheckResponse.prototype.toObject = function(opt_includeInstance) { return proto.grpc.health.v1.HealthCheckResponse.toObject(opt_includeInstance, this); }; /** * Static version of the {@see toObject} method. * @param {boolean|undefined} includeInstance Whether to include the JSPB * instance for transitional soy proto support: * http://goto/soy-param-migration * @param {!proto.grpc.health.v1.HealthCheckResponse} msg The msg instance to transform. * @return {!Object} */ proto.grpc.health.v1.HealthCheckResponse.toObject = function(includeInstance, msg) { var f, obj = { status: msg.getStatus() }; if (includeInstance) { obj.$jspbMessageInstance = msg; } return obj; }; } /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. * @return {!proto.grpc.health.v1.HealthCheckResponse} */ proto.grpc.health.v1.HealthCheckResponse.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); var msg = new proto.grpc.health.v1.HealthCheckResponse; return proto.grpc.health.v1.HealthCheckResponse.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. * @param {!proto.grpc.health.v1.HealthCheckResponse} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. * @return {!proto.grpc.health.v1.HealthCheckResponse} */ proto.grpc.health.v1.HealthCheckResponse.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); switch (field) { case 1: var value = /** @type {!proto.grpc.health.v1.HealthCheckResponse.ServingStatus} */ (reader.readEnum()); msg.setStatus(value); break; default: reader.skipField(); break; } } return msg; }; /** * Class method variant: serializes the given message to binary data * (in protobuf wire format), writing to the given BinaryWriter. * @param {!proto.grpc.health.v1.HealthCheckResponse} message * @param {!jspb.BinaryWriter} writer */ proto.grpc.health.v1.HealthCheckResponse.serializeBinaryToWriter = function(message, writer) { message.serializeBinaryToWriter(writer); }; /** * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ proto.grpc.health.v1.HealthCheckResponse.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); this.serializeBinaryToWriter(writer); return writer.getResultBuffer(); }; /** * Serializes the message to binary data (in protobuf wire format), * writing to the given BinaryWriter. * @param {!jspb.BinaryWriter} writer */ proto.grpc.health.v1.HealthCheckResponse.prototype.serializeBinaryToWriter = function (writer) { var f = undefined; f = this.getStatus(); if (f !== 0.0) { writer.writeEnum( 1, f ); } }; /** * Creates a deep clone of this proto. No data is shared with the original. * @return {!proto.grpc.health.v1.HealthCheckResponse} The clone. */ proto.grpc.health.v1.HealthCheckResponse.prototype.cloneMessage = function() { return /** @type {!proto.grpc.health.v1.HealthCheckResponse} */ (jspb.Message.cloneMessage(this)); }; /** * optional ServingStatus status = 1; * @return {!proto.grpc.health.v1.HealthCheckResponse.ServingStatus} */ proto.grpc.health.v1.HealthCheckResponse.prototype.getStatus = function() { return /** @type {!proto.grpc.health.v1.HealthCheckResponse.ServingStatus} */ (jspb.Message.getFieldProto3(this, 1, 0)); }; /** @param {!proto.grpc.health.v1.HealthCheckResponse.ServingStatus} value */ proto.grpc.health.v1.HealthCheckResponse.prototype.setStatus = function(value) { jspb.Message.setField(this, 1, value); }; /** * @enum {number} */ proto.grpc.health.v1.HealthCheckResponse.ServingStatus = { UNKNOWN: 0, SERVING: 1, NOT_SERVING: 2 }; goog.object.extend(exports, proto.grpc.health.v1); grpc-1.3.2/src/node/index.js000066400000000000000000000207141310511640000156240ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var path = require('path'); var fs = require('fs'); var SSL_ROOTS_PATH = path.resolve(__dirname, '..', '..', 'etc', 'roots.pem'); var _ = require('lodash'); var ProtoBuf = require('protobufjs'); var client = require('./src/client.js'); var server = require('./src/server.js'); var common = require('./src/common.js'); var Metadata = require('./src/metadata.js'); var grpc = require('./src/grpc_extension'); var protobuf_js_5_common = require('./src/protobuf_js_5_common'); var protobuf_js_6_common = require('./src/protobuf_js_6_common'); grpc.setDefaultRootsPem(fs.readFileSync(SSL_ROOTS_PATH, 'ascii')); /** * Load a ProtoBuf.js object as a gRPC object. The options object can provide * 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. * 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. * - 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=} options Options to apply to the loaded file * @return {Object} The resulting gRPC object */ exports.loadObject = function loadObject(value, options) { options = _.defaults(options, common.defaultGrpcOptions); options = _.defaults(options, {'protobufjsVersion': 'detect'}); var protobufjsVersion; if (options.protobufjsVersion === 'detect') { if (protobuf_js_6_common.isProbablyProtobufJs6(value)) { protobufjsVersion = 6; } else if (protobuf_js_5_common.isProbablyProtobufJs5(value)) { protobufjsVersion = 5; } else { var error_message = 'Could not detect ProtoBuf.js version. Please ' + 'specify the version number with the "protobufjs_version" option'; throw new Error(error_message); } } else { protobufjsVersion = options.protobufjsVersion; } switch (protobufjsVersion) { case 6: return protobuf_js_6_common.loadObject(value, options); case 5: return protobuf_js_5_common.loadObject(value, options); default: throw new Error('Unrecognized protobufjsVersion', protobufjsVersion); } }; var loadObject = exports.loadObject; /** * Load a gRPC object from a .proto file. The options object can provide the * following options: * - convertFieldsToCamelCase: Load this file with field names in camel case * 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=} format The file format to expect. Must be either 'proto' or * 'json'. Defaults to 'proto' * @param {Object=} options Options to apply to the loaded file * @return {Object} The resulting gRPC object */ exports.load = function load(filename, format, options) { options = _.defaults(options, common.defaultGrpcOptions); options.protobufjsVersion = 5; if (!format) { format = 'proto'; } var convertFieldsToCamelCaseOriginal = ProtoBuf.convertFieldsToCamelCase; if(options && options.hasOwnProperty('convertFieldsToCamelCase')) { ProtoBuf.convertFieldsToCamelCase = options.convertFieldsToCamelCase; } var builder; try { switch(format) { case 'proto': builder = ProtoBuf.loadProtoFile(filename); break; case 'json': builder = ProtoBuf.loadJsonFile(filename); break; default: throw new Error('Unrecognized format "' + format + '"'); } } finally { ProtoBuf.convertFieldsToCamelCase = convertFieldsToCamelCaseOriginal; } return loadObject(builder.ns, options); }; var log_template = _.template( '{severity} {timestamp}\t{file}:{line}]\t{message}', {interpolate: /{([\s\S]+?)}/g}); /** * Sets the logger function for the gRPC module. For debugging purposes, the C * core will log synchronously directly to stdout unless this function is * called. Note: the output format here is intended to be informational, and * is not guaranteed to stay the same in the future. * Logs will be directed to logger.error. * @param {Console} logger A Console-like object. */ exports.setLogger = function setLogger(logger) { common.logger = logger; grpc.setDefaultLoggerCallback(function(file, line, severity, message, timestamp) { logger.error(log_template({ file: path.basename(file), line: line, severity: severity, message: message, timestamp: timestamp.toISOString() })); }); }; /** * Sets the logger verbosity for gRPC module logging. The options are members * of the grpc.logVerbosity map. * @param {Number} verbosity The minimum severity to log */ exports.setLogVerbosity = function setLogVerbosity(verbosity) { common.logVerbosity = verbosity; grpc.setLogVerbosity(verbosity); }; /** * @see module:src/server.Server */ exports.Server = server.Server; /** * @see module:src/metadata */ exports.Metadata = Metadata; /** * Status name to code number mapping */ exports.status = grpc.status; /** * Propagate flag name to number mapping */ exports.propagate = grpc.propagate; /** * Call error name to code number mapping */ exports.callError = grpc.callError; /** * Write flag name to code number mapping */ exports.writeFlags = grpc.writeFlags; /** * Log verbosity setting name to code number mapping */ exports.logVerbosity = grpc.logVerbosity; /** * Credentials factories */ exports.credentials = require('./src/credentials.js'); /** * ServerCredentials factories */ exports.ServerCredentials = grpc.ServerCredentials; /** * @see module:src/client.makeClientConstructor */ exports.makeGenericClientConstructor = client.makeClientConstructor; /** * @see module:src/client.getClientChannel */ exports.getClientChannel = client.getClientChannel; /** * @see module:src/client.waitForClientReady */ exports.waitForClientReady = client.waitForClientReady; exports.closeClient = function closeClient(client_obj) { client.getClientChannel(client_obj).close(); }; grpc-1.3.2/src/node/interop/000077500000000000000000000000001310511640000156335ustar00rootroot00000000000000grpc-1.3.2/src/node/interop/async_delay_queue.js000066400000000000000000000052741310511640000217000ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var _ = require('lodash'); /** * This class represents a queue of callbacks that must happen sequentially, * each with a specific delay after the previous event. */ function AsyncDelayQueue() { this.queue = []; this.callback_pending = false; } /** * Run the next callback after its corresponding delay, if there are any * remaining. */ AsyncDelayQueue.prototype.runNext = function() { var next = this.queue.shift(); var continueCallback = _.bind(this.runNext, this); if (next) { this.callback_pending = true; setTimeout(function() { next.callback(continueCallback); }, next.delay); } else { this.callback_pending = false; } }; /** * Add a callback to be called with a specific delay after now or after the * current last item in the queue or current pending callback, whichever is * latest. * @param {function(function())} callback The callback * @param {Number} The delay to apply, in milliseconds */ AsyncDelayQueue.prototype.add = function(callback, delay) { this.queue.push({callback: callback, delay: delay}); if (!this.callback_pending) { this.runNext(); } }; module.exports = AsyncDelayQueue; grpc-1.3.2/src/node/interop/interop_client.js000066400000000000000000000461721310511640000212210ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var fs = require('fs'); var path = require('path'); var grpc = require('..'); var testProto = grpc.load({ root: __dirname + '/../../..', file: 'src/proto/grpc/testing/test.proto'}).grpc.testing; var GoogleAuth = require('google-auth-library'); var assert = require('assert'); var SERVICE_ACCOUNT_EMAIL; try { SERVICE_ACCOUNT_EMAIL = require( process.env.GOOGLE_APPLICATION_CREDENTIALS).client_email; } catch (e) { // This will cause the tests to fail if they need that string SERVICE_ACCOUNT_EMAIL = null; } var ECHO_INITIAL_KEY = 'x-grpc-test-echo-initial'; var ECHO_TRAILING_KEY = 'x-grpc-test-echo-trailing-bin'; /** * Create a buffer filled with size zeroes * @param {number} size The length of the buffer * @return {Buffer} The new buffer */ function zeroBuffer(size) { var zeros = new Buffer(size); zeros.fill(0); return zeros; } /** * This is used for testing functions with multiple asynchronous calls that * can happen in different orders. This should be passed the number of async * function invocations that can occur last, and each of those should call this * function's return value * @param {function()} done The function that should be called when a test is * complete. * @param {number} count The number of calls to the resulting function if the * test passes. * @return {function()} The function that should be called at the end of each * sequence of asynchronous functions. */ function multiDone(done, count) { return function() { count -= 1; if (count <= 0) { done(); } }; } /** * Run the empty_unary test * @param {Client} client The client to test against * @param {function} done Callback to call when the test is completed. Included * primarily for use with mocha */ function emptyUnary(client, done) { client.emptyCall({}, function(err, resp) { assert.ifError(err); if (done) { done(); } }); } /** * Run the large_unary test * @param {Client} client The client to test against * @param {function} done Callback to call when the test is completed. Included * primarily for use with mocha */ function largeUnary(client, done) { var arg = { response_type: 'COMPRESSABLE', response_size: 314159, payload: { body: zeroBuffer(271828) } }; client.unaryCall(arg, function(err, resp) { assert.ifError(err); assert.strictEqual(resp.payload.type, 'COMPRESSABLE'); assert.strictEqual(resp.payload.body.length, 314159); if (done) { done(); } }); } /** * Run the client_streaming test * @param {Client} client The client to test against * @param {function} done Callback to call when the test is completed. Included * primarily for use with mocha */ function clientStreaming(client, done) { var call = client.streamingInputCall(function(err, resp) { assert.ifError(err); assert.strictEqual(resp.aggregated_payload_size, 74922); if (done) { done(); } }); var payload_sizes = [27182, 8, 1828, 45904]; for (var i = 0; i < payload_sizes.length; i++) { call.write({payload: {body: zeroBuffer(payload_sizes[i])}}); } call.end(); } /** * Run the server_streaming test * @param {Client} client The client to test against * @param {function} done Callback to call when the test is completed. Included * primarily for use with mocha */ function serverStreaming(client, done) { var arg = { response_type: 'COMPRESSABLE', response_parameters: [ {size: 31415}, {size: 9}, {size: 2653}, {size: 58979} ] }; var call = client.streamingOutputCall(arg); var resp_index = 0; call.on('data', function(value) { assert(resp_index < 4); assert.strictEqual(value.payload.type, 'COMPRESSABLE'); assert.strictEqual(value.payload.body.length, arg.response_parameters[resp_index].size); resp_index += 1; }); call.on('end', function() { assert.strictEqual(resp_index, 4); if (done) { done(); } }); call.on('status', function(status) { assert.strictEqual(status.code, grpc.status.OK); }); } /** * Run the ping_pong test * @param {Client} client The client to test against * @param {function} done Callback to call when the test is completed. Included * primarily for use with mocha */ function pingPong(client, done) { var payload_sizes = [27182, 8, 1828, 45904]; var response_sizes = [31415, 9, 2653, 58979]; var call = client.fullDuplexCall(); call.on('status', function(status) { assert.strictEqual(status.code, grpc.status.OK); if (done) { done(); } }); var index = 0; call.write({ response_type: 'COMPRESSABLE', response_parameters: [ {size: response_sizes[index]} ], payload: {body: zeroBuffer(payload_sizes[index])} }); call.on('data', function(response) { assert.strictEqual(response.payload.type, 'COMPRESSABLE'); assert.equal(response.payload.body.length, response_sizes[index]); index += 1; if (index === 4) { call.end(); } else { call.write({ response_type: 'COMPRESSABLE', response_parameters: [ {size: response_sizes[index]} ], payload: {body: zeroBuffer(payload_sizes[index])} }); } }); } /** * Run the empty_stream test. * @param {Client} client The client to test against * @param {function} done Callback to call when the test is completed. Included * primarily for use with mocha */ function emptyStream(client, done) { var call = client.fullDuplexCall(); call.on('status', function(status) { assert.strictEqual(status.code, grpc.status.OK); if (done) { done(); } }); call.on('data', function(value) { assert.fail(value, null, 'No data should have been received', '!=='); }); call.end(); } /** * Run the cancel_after_begin test. * @param {Client} client The client to test against * @param {function} done Callback to call when the test is completed. Included * primarily for use with mocha */ function cancelAfterBegin(client, done) { var call = client.streamingInputCall(function(err, resp) { assert.strictEqual(err.code, grpc.status.CANCELLED); done(); }); call.cancel(); } /** * Run the cancel_after_first_response test. * @param {Client} client The client to test against * @param {function} done Callback to call when the test is completed. Included * primarily for use with mocha */ function cancelAfterFirstResponse(client, done) { var call = client.fullDuplexCall(); call.write({ response_type: 'COMPRESSABLE', response_parameters: [ {size: 31415} ], payload: {body: zeroBuffer(27182)} }); call.on('data', function(data) { call.cancel(); }); call.on('error', function(error) { assert.strictEqual(error.code, grpc.status.CANCELLED); done(); }); } function timeoutOnSleepingServer(client, done) { var deadline = new Date(); deadline.setMilliseconds(deadline.getMilliseconds() + 1); var call = client.fullDuplexCall({deadline: deadline}); call.write({ payload: {body: zeroBuffer(27182)} }); call.on('data', function() {}); call.on('error', function(error) { assert(error.code === grpc.status.DEADLINE_EXCEEDED || error.code === grpc.status.INTERNAL); done(); }); } function customMetadata(client, done) { done = multiDone(done, 5); var metadata = new grpc.Metadata(); metadata.set(ECHO_INITIAL_KEY, 'test_initial_metadata_value'); metadata.set(ECHO_TRAILING_KEY, new Buffer('ababab', 'hex')); var arg = { response_type: 'COMPRESSABLE', response_size: 314159, payload: { body: zeroBuffer(271828) } }; var streaming_arg = { response_parameters: [ {size: 314159} ], payload: { body: zeroBuffer(271828) } }; var unary = client.unaryCall(arg, metadata, function(err, resp) { assert.ifError(err); done(); }); unary.on('metadata', function(metadata) { assert.deepEqual(metadata.get(ECHO_INITIAL_KEY), ['test_initial_metadata_value']); done(); }); unary.on('status', function(status) { var echo_trailer = status.metadata.get(ECHO_TRAILING_KEY); assert(echo_trailer.length > 0); assert.strictEqual(echo_trailer[0].toString('hex'), 'ababab'); done(); }); var stream = client.fullDuplexCall(metadata); stream.on('metadata', function(metadata) { assert.deepEqual(metadata.get(ECHO_INITIAL_KEY), ['test_initial_metadata_value']); done(); }); stream.on('data', function() {}); stream.on('status', function(status) { var echo_trailer = status.metadata.get(ECHO_TRAILING_KEY); assert(echo_trailer.length > 0); assert.strictEqual(echo_trailer[0].toString('hex'), 'ababab'); done(); }); stream.write(streaming_arg); stream.end(); } function statusCodeAndMessage(client, done) { done = multiDone(done, 2); var arg = { response_status: { code: 2, message: 'test status message' } }; client.unaryCall(arg, function(err, resp) { assert(err); assert.strictEqual(err.code, 2); assert.strictEqual(err.message, 'test status message'); done(); }); var duplex = client.fullDuplexCall(); duplex.on('data', function() {}); duplex.on('status', function(status) { assert(status); assert.strictEqual(status.code, 2); assert.strictEqual(status.details, 'test status message'); done(); }); duplex.on('error', function(){}); duplex.write(arg); duplex.end(); } // NOTE: the client param to this function is from UnimplementedService function unimplementedService(client, done) { client.unimplementedCall({}, function(err, resp) { assert(err); assert.strictEqual(err.code, grpc.status.UNIMPLEMENTED); done(); }); } // NOTE: the client param to this function is from TestService function unimplementedMethod(client, done) { client.unimplementedCall({}, function(err, resp) { assert(err); assert.strictEqual(err.code, grpc.status.UNIMPLEMENTED); done(); }); } /** * Run one of the authentication tests. * @param {string} expected_user The expected username in the response * @param {Client} client The client to test against * @param {?string} scope The scope to apply to the credentials * @param {function} done Callback to call when the test is completed. Included * primarily for use with mocha */ function authTest(expected_user, scope, client, done) { var arg = { response_type: 'COMPRESSABLE', response_size: 314159, payload: { body: zeroBuffer(271828) }, fill_username: true, fill_oauth_scope: true }; client.unaryCall(arg, function(err, resp) { assert.ifError(err); assert.strictEqual(resp.payload.type, 'COMPRESSABLE'); assert.strictEqual(resp.payload.body.length, 314159); assert.strictEqual(resp.username, expected_user); if (scope) { assert(scope.indexOf(resp.oauth_scope) > -1); } if (done) { done(); } }); } function computeEngineCreds(client, done, extra) { authTest(extra.service_account, null, client, done); } function serviceAccountCreds(client, done, extra) { authTest(SERVICE_ACCOUNT_EMAIL, extra.oauth_scope, client, done); } function jwtTokenCreds(client, done, extra) { authTest(SERVICE_ACCOUNT_EMAIL, null, client, done); } function oauth2Test(client, done, extra) { var arg = { fill_username: true, fill_oauth_scope: true }; client.unaryCall(arg, function(err, resp) { assert.ifError(err); assert.strictEqual(resp.username, SERVICE_ACCOUNT_EMAIL); assert(extra.oauth_scope.indexOf(resp.oauth_scope) > -1); if (done) { done(); } }); } function perRpcAuthTest(client, done, extra) { (new GoogleAuth()).getApplicationDefault(function(err, credential) { assert.ifError(err); var arg = { fill_username: true, fill_oauth_scope: true }; var scope = extra.oauth_scope; if (credential.createScopedRequired() && scope) { credential = credential.createScoped(scope); } var creds = grpc.credentials.createFromGoogleCredential(credential); client.unaryCall(arg, {credentials: creds}, function(err, resp) { assert.ifError(err); assert.strictEqual(resp.username, SERVICE_ACCOUNT_EMAIL); assert(extra.oauth_scope.indexOf(resp.oauth_scope) > -1); if (done) { done(); } }); }); } function getApplicationCreds(scope, callback) { (new GoogleAuth()).getApplicationDefault(function(err, credential) { if (err) { callback(err); return; } if (credential.createScopedRequired() && scope) { credential = credential.createScoped(scope); } callback(null, grpc.credentials.createFromGoogleCredential(credential)); }); } function getOauth2Creds(scope, callback) { (new GoogleAuth()).getApplicationDefault(function(err, credential) { if (err) { callback(err); return; } credential = credential.createScoped(scope); credential.getAccessToken(function(err, token) { if (err) { callback(err); return; } var updateMd = function(service_url, callback) { var metadata = new grpc.Metadata(); metadata.add('authorization', 'Bearer ' + token); callback(null, metadata); }; callback(null, grpc.credentials.createFromMetadataGenerator(updateMd)); }); }); } /** * Map from test case names to test functions */ var test_cases = { empty_unary: {run: emptyUnary, Client: testProto.TestService}, large_unary: {run: largeUnary, Client: testProto.TestService}, client_streaming: {run: clientStreaming, Client: testProto.TestService}, server_streaming: {run: serverStreaming, Client: testProto.TestService}, ping_pong: {run: pingPong, Client: testProto.TestService}, empty_stream: {run: emptyStream, Client: testProto.TestService}, cancel_after_begin: {run: cancelAfterBegin, Client: testProto.TestService}, cancel_after_first_response: {run: cancelAfterFirstResponse, Client: testProto.TestService}, timeout_on_sleeping_server: {run: timeoutOnSleepingServer, Client: testProto.TestService}, custom_metadata: {run: customMetadata, Client: testProto.TestService}, status_code_and_message: {run: statusCodeAndMessage, Client: testProto.TestService}, unimplemented_service: {run: unimplementedService, Client: testProto.UnimplementedService}, unimplemented_method: {run: unimplementedMethod, Client: testProto.TestService}, compute_engine_creds: {run: computeEngineCreds, Client: testProto.TestService, getCreds: getApplicationCreds}, service_account_creds: {run: serviceAccountCreds, Client: testProto.TestService, getCreds: getApplicationCreds}, jwt_token_creds: {run: jwtTokenCreds, Client: testProto.TestService, getCreds: getApplicationCreds}, oauth2_auth_token: {run: oauth2Test, Client: testProto.TestService, getCreds: getOauth2Creds}, per_rpc_creds: {run: perRpcAuthTest, Client: testProto.TestService} }; exports.test_cases = test_cases; /** * Execute a single test case. * @param {string} address The address of the server to connect to, in the * format 'hostname:port' * @param {string} host_overrirde The hostname of the server to use as an SSL * override * @param {string} test_case The name of the test case to run * @param {bool} tls Indicates that a secure channel should be used * @param {function} done Callback to call when the test is completed. Included * primarily for use with mocha * @param {object=} extra Extra options for some tests */ function runTest(address, host_override, test_case, tls, test_ca, done, extra) { // TODO(mlumish): enable TLS functionality var options = {}; var creds; if (tls) { var ca_path; if (test_ca) { ca_path = path.join(__dirname, '../test/data/ca.pem'); var ca_data = fs.readFileSync(ca_path); creds = grpc.credentials.createSsl(ca_data); } else { creds = grpc.credentials.createSsl(); } if (host_override) { options['grpc.ssl_target_name_override'] = host_override; options['grpc.default_authority'] = host_override; } } else { creds = grpc.credentials.createInsecure(); } var test = test_cases[test_case]; var execute = function(err, creds) { assert.ifError(err); var client = new test.Client(address, creds, options); test.run(client, done, extra); }; if (test.getCreds) { test.getCreds(extra.oauth_scope, function(err, new_creds) { assert.ifError(err); execute(err, grpc.credentials.combineChannelCredentials( creds, new_creds)); }); } else { execute(null, creds); } } if (require.main === module) { var parseArgs = require('minimist'); var argv = parseArgs(process.argv, { string: ['server_host', 'server_host_override', 'server_port', 'test_case', 'use_tls', 'use_test_ca', 'default_service_account', 'oauth_scope', 'service_account_key_file'] }); var extra_args = { service_account: argv.default_service_account, oauth_scope: argv.oauth_scope }; runTest(argv.server_host + ':' + argv.server_port, argv.server_host_override, argv.test_case, argv.use_tls === 'true', argv.use_test_ca === 'true', function () { console.log('OK:', argv.test_case); }, extra_args); } /** * See docs for runTest */ exports.runTest = runTest; grpc-1.3.2/src/node/interop/interop_server.js000066400000000000000000000200541310511640000212400ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var fs = require('fs'); var path = require('path'); var _ = require('lodash'); var AsyncDelayQueue = require('./async_delay_queue'); var grpc = require('..'); var testProto = grpc.load({ root: __dirname + '/../../..', file: 'src/proto/grpc/testing/test.proto'}).grpc.testing; var ECHO_INITIAL_KEY = 'x-grpc-test-echo-initial'; var ECHO_TRAILING_KEY = 'x-grpc-test-echo-trailing-bin'; /** * Create a buffer filled with size zeroes * @param {number} size The length of the buffer * @return {Buffer} The new buffer */ function zeroBuffer(size) { var zeros = new Buffer(size); zeros.fill(0); return zeros; } /** * Echos a header metadata item as specified in the interop spec. * @param {Call} call The call to echo metadata on */ function echoHeader(call) { var echo_initial = call.metadata.get(ECHO_INITIAL_KEY); if (echo_initial.length > 0) { var response_metadata = new grpc.Metadata(); response_metadata.set(ECHO_INITIAL_KEY, echo_initial[0]); call.sendMetadata(response_metadata); } } /** * Gets the trailer metadata that should be echoed when the call is done, * as specified in the interop spec. * @param {Call} call The call to get metadata from * @return {grpc.Metadata} The metadata to send as a trailer */ function getEchoTrailer(call) { var echo_trailer = call.metadata.get(ECHO_TRAILING_KEY); var response_trailer = new grpc.Metadata(); if (echo_trailer.length > 0) { response_trailer.set(ECHO_TRAILING_KEY, echo_trailer[0]); } return response_trailer; } function getPayload(payload_type, size) { var body = zeroBuffer(size); return {type: payload_type, body: body}; } /** * Respond to an empty parameter with an empty response. * NOTE: this currently does not work due to issue #137 * @param {Call} call Call to handle * @param {function(Error, Object)} callback Callback to call with result * or error */ function handleEmpty(call, callback) { echoHeader(call); callback(null, {}, getEchoTrailer(call)); } /** * Handle a unary request by sending the requested payload * @param {Call} call Call to handle * @param {function(Error, Object)} callback Callback to call with result or * error */ function handleUnary(call, callback) { echoHeader(call); var req = call.request; if (req.response_status) { var status = req.response_status; status.metadata = getEchoTrailer(call); callback(status); return; } var payload = getPayload(req.response_type, req.response_size); callback(null, {payload: payload}, getEchoTrailer(call)); } /** * Respond to a streaming call with the total size of all payloads * @param {Call} call Call to handle * @param {function(Error, Object)} callback Callback to call with result or * error */ function handleStreamingInput(call, callback) { echoHeader(call); var aggregate_size = 0; call.on('data', function(value) { aggregate_size += value.payload.body.length; }); call.on('end', function() { callback(null, {aggregated_payload_size: aggregate_size}, getEchoTrailer(call)); }); } /** * Respond to a payload request with a stream of the requested payloads * @param {Call} call Call to handle */ function handleStreamingOutput(call) { echoHeader(call); var delay_queue = new AsyncDelayQueue(); var req = call.request; if (req.response_status) { var status = req.response_status; status.metadata = getEchoTrailer(call); call.emit('error', status); return; } _.each(req.response_parameters, function(resp_param) { delay_queue.add(function(next) { call.write({payload: getPayload(req.response_type, resp_param.size)}); next(); }, resp_param.interval_us); }); delay_queue.add(function(next) { call.end(getEchoTrailer(call)); next(); }); } /** * Respond to a stream of payload requests with a stream of payload responses as * they arrive. * @param {Call} call Call to handle */ function handleFullDuplex(call) { echoHeader(call); var delay_queue = new AsyncDelayQueue(); call.on('data', function(value) { if (value.response_status) { var status = value.response_status; status.metadata = getEchoTrailer(call); call.emit('error', status); return; } _.each(value.response_parameters, function(resp_param) { delay_queue.add(function(next) { call.write({payload: getPayload(value.response_type, resp_param.size)}); next(); }, resp_param.interval_us); }); }); call.on('end', function() { delay_queue.add(function(next) { call.end(getEchoTrailer(call)); next(); }); }); } /** * Respond to a stream of payload requests with a stream of payload responses * after all requests have arrived * @param {Call} call Call to handle */ function handleHalfDuplex(call) { call.emit('error', Error('HalfDuplexCall not yet implemented')); } /** * Get a server object bound to the given port * @param {string} port Port to which to bind * @param {boolean} tls Indicates that the bound port should use TLS * @return {{server: Server, port: number}} Server object bound to the support, * and port number that the server is bound to */ function getServer(port, tls) { // TODO(mlumish): enable TLS functionality var options = {}; var server_creds; if (tls) { var key_path = path.join(__dirname, '../test/data/server1.key'); var pem_path = path.join(__dirname, '../test/data/server1.pem'); var key_data = fs.readFileSync(key_path); var pem_data = fs.readFileSync(pem_path); server_creds = grpc.ServerCredentials.createSsl(null, [{private_key: key_data, cert_chain: pem_data}]); } else { server_creds = grpc.ServerCredentials.createInsecure(); } var server = new grpc.Server(options); server.addService(testProto.TestService.service, { emptyCall: handleEmpty, unaryCall: handleUnary, streamingOutputCall: handleStreamingOutput, streamingInputCall: handleStreamingInput, fullDuplexCall: handleFullDuplex, halfDuplexCall: handleHalfDuplex }); var port_num = server.bind('0.0.0.0:' + port, server_creds); return {server: server, port: port_num}; } if (require.main === module) { var parseArgs = require('minimist'); var argv = parseArgs(process.argv, { string: ['port', 'use_tls'] }); var server_obj = getServer(argv.port, argv.use_tls === 'true'); console.log('Server attaching to port ' + argv.port); server_obj.server.start(); } /** * See docs for getServer */ exports.getServer = getServer; grpc-1.3.2/src/node/jsdoc_conf.json000066400000000000000000000006731310511640000171630ustar00rootroot00000000000000{ "tags": { "allowUnknownTags": true }, "source": { "include": [ "src/node/index.js", "src/node/src" ], "includePattern": "src/node/.+\\.js(doc)?$", "excludePattern": "(^|\\/|\\\\)_" }, "opts": { "package": "package.json", "readme": "src/node/README.md" }, "plugins": [], "templates": { "cleverLinks": false, "monospaceLinks": false, "default": { "outputSourceFiles": true } } } grpc-1.3.2/src/node/performance/000077500000000000000000000000001310511640000164545ustar00rootroot00000000000000grpc-1.3.2/src/node/performance/benchmark_client.js000066400000000000000000000306621310511640000223110ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** * Benchmark client module * @module */ 'use strict'; var fs = require('fs'); var path = require('path'); var util = require('util'); var EventEmitter = require('events'); var async = require('async'); var _ = require('lodash'); var PoissonProcess = require('poisson-process'); var Histogram = require('./histogram'); var genericService = require('./generic_service'); var grpc = require('../../../'); var serviceProto = grpc.load({ root: __dirname + '/../../..', file: 'src/proto/grpc/testing/services.proto'}).grpc.testing; /** * Create a buffer filled with size zeroes * @param {number} size The length of the buffer * @return {Buffer} The new buffer */ function zeroBuffer(size) { var zeros = new Buffer(size); zeros.fill(0); return zeros; } /** * Convert a time difference, as returned by process.hrtime, to a number of * nanoseconds. * @param {Array.} time_diff The time diff, represented as * [seconds, nanoseconds] * @return {number} The total number of nanoseconds */ function timeDiffToNanos(time_diff) { return time_diff[0] * 1e9 + time_diff[1]; } /** * The BenchmarkClient class. Opens channels to servers and makes RPCs based on * parameters from the driver, and records statistics about those RPCs. * @param {Array.} server_targets List of servers to connect to * @param {number} channels The total number of channels to open * @param {Object} histogram_params Options for setting up the histogram * @param {Object=} security_params Options for TLS setup. If absent, don't use * TLS */ function BenchmarkClient(server_targets, channels, histogram_params, security_params) { var options = { "grpc.max_receive_message_length": -1, "grpc.max_send_message_length": -1 }; var creds; if (security_params) { var ca_path; if (security_params.use_test_ca) { ca_path = path.join(__dirname, '../test/data/ca.pem'); var ca_data = fs.readFileSync(ca_path); creds = grpc.credentials.createSsl(ca_data); } else { creds = grpc.credentials.createSsl(); } if (security_params.server_host_override) { var host_override = security_params.server_host_override; options['grpc.ssl_target_name_override'] = host_override; options['grpc.default_authority'] = host_override; } } else { creds = grpc.credentials.createInsecure(); } this.clients = []; var GenericClient = grpc.makeGenericClientConstructor(genericService); this.genericClients = []; for (var i = 0; i < channels; i++) { this.clients[i] = new serviceProto.BenchmarkService( server_targets[i % server_targets.length], creds, options); this.genericClients[i] = new GenericClient( server_targets[i % server_targets.length], creds, options); } this.histogram = new Histogram(histogram_params.resolution, histogram_params.max_possible); this.running = false; this.pending_calls = 0; }; util.inherits(BenchmarkClient, EventEmitter); /** * Start every client in the list of clients by waiting for each to be ready, * then starting outstanding_rpcs_per_channel calls on each of them * @param {Array} client_list The list of clients * @param {Number} outstanding_rpcs_per_channel The number of calls to start * on each client * @param {function(grpc.Client)} makeCall Function to make a single call on * a single client * @param {EventEmitter} emitter The event emitter to send errors on, if * necessary */ function startAllClients(client_list, outstanding_rpcs_per_channel, makeCall, emitter) { var ready_wait_funcs = _.map(client_list, function(client) { return _.partial(grpc.waitForClientReady, client, Infinity); }); async.parallel(ready_wait_funcs, function(err) { if (err) { emitter.emit('error', err); return; } _.each(client_list, function(client) { _.times(outstanding_rpcs_per_channel, function() { makeCall(client); }); }); }); } /** * Start a closed-loop test. For each channel, start * outstanding_rpcs_per_channel RPCs. Then, whenever an RPC finishes, start * another one. * @param {number} outstanding_rpcs_per_channel Number of RPCs to start per * channel * @param {string} rpc_type Which method to call. Should be 'UNARY' or * 'STREAMING' * @param {number} req_size The size of the payload to send with each request * @param {number} resp_size The size of payload to request be sent in responses * @param {boolean} generic Indicates that the generic (non-proto) clients * should be used */ BenchmarkClient.prototype.startClosedLoop = function( outstanding_rpcs_per_channel, rpc_type, req_size, resp_size, generic) { var self = this; self.running = true; self.last_wall_time = process.hrtime(); self.last_usage = process.cpuUsage(); var makeCall; var argument; var client_list; if (generic) { argument = zeroBuffer(req_size); client_list = self.genericClients; } else { argument = { response_size: resp_size, payload: { body: zeroBuffer(req_size) } }; client_list = self.clients; } if (rpc_type == 'UNARY') { makeCall = function(client) { if (self.running) { self.pending_calls++; var start_time = process.hrtime(); client.unaryCall(argument, function(error, response) { if (error) { self.emit('error', new Error('Client error: ' + error.message)); self.running = false; return; } var time_diff = process.hrtime(start_time); self.histogram.add(timeDiffToNanos(time_diff)); makeCall(client); self.pending_calls--; if ((!self.running) && self.pending_calls == 0) { self.emit('finished'); } }); } }; } else { makeCall = function(client) { if (self.running) { self.pending_calls++; var start_time = process.hrtime(); var call = client.streamingCall(); call.write(argument); call.on('data', function() { }); call.on('end', function() { var time_diff = process.hrtime(start_time); self.histogram.add(timeDiffToNanos(time_diff)); makeCall(client); self.pending_calls--; if ((!self.running) && self.pending_calls == 0) { self.emit('finished'); } }); call.on('error', function(error) { self.emit('error', new Error('Client error: ' + error.message)); self.running = false; }); } }; } startAllClients(client_list, outstanding_rpcs_per_channel, makeCall, self); }; /** * Start a poisson test. For each channel, this initiates a number of Poisson * processes equal to outstanding_rpcs_per_channel, where each Poisson process * has the load parameter offered_load. * @param {number} outstanding_rpcs_per_channel Number of RPCs to start per * channel * @param {string} rpc_type Which method to call. Should be 'UNARY' or * 'STREAMING' * @param {number} req_size The size of the payload to send with each request * @param {number} resp_size The size of payload to request be sent in responses * @param {number} offered_load The load parameter for the Poisson process * @param {boolean} generic Indicates that the generic (non-proto) clients * should be used */ BenchmarkClient.prototype.startPoisson = function( outstanding_rpcs_per_channel, rpc_type, req_size, resp_size, offered_load, generic) { var self = this; self.running = true; self.last_wall_time = process.hrtime(); self.last_usage = process.cpuUsage(); var makeCall; var argument; var client_list; if (generic) { argument = zeroBuffer(req_size); client_list = self.genericClients; } else { argument = { response_size: resp_size, payload: { body: zeroBuffer(req_size) } }; client_list = self.clients; } if (rpc_type == 'UNARY') { makeCall = function(client, poisson) { if (self.running) { self.pending_calls++; var start_time = process.hrtime(); client.unaryCall(argument, function(error, response) { if (error) { self.emit('error', new Error('Client error: ' + error.message)); self.running = false; return; } var time_diff = process.hrtime(start_time); self.histogram.add(timeDiffToNanos(time_diff)); self.pending_calls--; if ((!self.running) && self.pending_calls == 0) { self.emit('finished'); } }); } else { poisson.stop(); } }; } else { makeCall = function(client, poisson) { if (self.running) { self.pending_calls++; var start_time = process.hrtime(); var call = client.streamingCall(); call.write(argument); call.on('data', function() { }); call.on('end', function() { var time_diff = process.hrtime(start_time); self.histogram.add(timeDiffToNanos(time_diff)); self.pending_calls--; if ((!self.running) && self.pending_calls == 0) { self.emit('finished'); } }); call.on('error', function(error) { self.emit('error', new Error('Client error: ' + error.message)); self.running = false; }); } else { poisson.stop(); } }; } var averageIntervalMs = (1 / offered_load) * 1000; startAllClients(client_list, outstanding_rpcs_per_channel, function(client){ var p = PoissonProcess.create(averageIntervalMs, function() { makeCall(client, p); }); p.start(); }, self); }; /** * Return curent statistics for the client. If reset is set, restart * statistic collection. * @param {boolean} reset Indicates that statistics should be reset * @return {object} Client statistics */ BenchmarkClient.prototype.mark = function(reset) { var wall_time_diff = process.hrtime(this.last_wall_time); var usage_diff = process.cpuUsage(this.last_usage); var histogram = this.histogram; if (reset) { this.last_wall_time = process.hrtime(); this.last_usage = process.cpuUsage(); this.histogram = new Histogram(histogram.resolution, histogram.max_possible); } return { latencies: { bucket: histogram.getContents(), min_seen: histogram.minimum(), max_seen: histogram.maximum(), sum: histogram.getSum(), sum_of_squares: histogram.sumOfSquares(), count: histogram.getCount() }, time_elapsed: wall_time_diff[0] + wall_time_diff[1] / 1e9, time_user: usage_diff.user / 1000000, time_system: usage_diff.system / 1000000 }; }; /** * Stop the clients. * @param {function} callback Called when the clients have finished shutting * down */ BenchmarkClient.prototype.stop = function(callback) { this.running = false; this.on('finished', callback); }; module.exports = BenchmarkClient; grpc-1.3.2/src/node/performance/benchmark_client_express.js000066400000000000000000000216031310511640000240550ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** * Benchmark client module * @module */ 'use strict'; var fs = require('fs'); var path = require('path'); var util = require('util'); var EventEmitter = require('events'); var http = require('http'); var https = require('https'); var async = require('async'); var _ = require('lodash'); var PoissonProcess = require('poisson-process'); var Histogram = require('./histogram'); /** * Convert a time difference, as returned by process.hrtime, to a number of * nanoseconds. * @param {Array.} time_diff The time diff, represented as * [seconds, nanoseconds] * @return {number} The total number of nanoseconds */ function timeDiffToNanos(time_diff) { return time_diff[0] * 1e9 + time_diff[1]; } function BenchmarkClient(server_targets, channels, histogram_params, security_params) { var options = { method: 'PUT', headers: { 'Content-Type': 'application/json' } }; var protocol; if (security_params) { var ca_path; protocol = https; this.request = _.bind(https.request, https); if (security_params.use_test_ca) { ca_path = path.join(__dirname, '../test/data/ca.pem'); var ca_data = fs.readFileSync(ca_path); options.ca = ca_data; } if (security_params.server_host_override) { var host_override = security_params.server_host_override; options.servername = host_override; } } else { protocol = http; } this.request = _.bind(protocol.request, protocol); this.client_options = []; for (var i = 0; i < channels; i++) { var host_port; host_port = server_targets[i % server_targets.length].split(':'); var new_options = _.assign({hostname: host_port[0], port: +host_port[1]}, options); this.client_options[i] = new_options; } this.histogram = new Histogram(histogram_params.resolution, histogram_params.max_possible); this.running = false; this.pending_calls = 0; } util.inherits(BenchmarkClient, EventEmitter); function startAllClients(client_options_list, outstanding_rpcs_per_channel, makeCall, emitter) { _.each(client_options_list, function(client_options) { _.times(outstanding_rpcs_per_channel, function() { makeCall(client_options); }); }); } BenchmarkClient.prototype.startClosedLoop = function( outstanding_rpcs_per_channel, rpc_type, req_size, resp_size, generic) { var self = this; var options = {}; self.running = true; if (rpc_type == 'UNARY') { options.path = '/serviceProto.BenchmarkService.service/unaryCall'; } else { self.emit('error', new Error('Unsupported rpc_type: ' + rpc_type)); } if (generic) { self.emit('error', new Error('Generic client not supported')); } self.last_wall_time = process.hrtime(); self.last_usage = process.cpuUsage(); var argument = { response_size: resp_size, payload: { body: '0'.repeat(req_size) } }; function makeCall(client_options) { if (self.running) { self.pending_calls++; var start_time = process.hrtime(); function finishCall(success) { if (success) { var time_diff = process.hrtime(start_time); self.histogram.add(timeDiffToNanos(time_diff)); } makeCall(client_options); self.pending_calls--; if ((!self.running) && self.pending_calls == 0) { self.emit('finished'); } } var req = self.request(client_options, function(res) { var res_data = ''; res.on('data', function(data) { res_data += data; }); res.on('end', function() { JSON.parse(res_data); finishCall(true); }); }); req.write(JSON.stringify(argument)); req.end(); req.on('error', function(error) { if (error.code === 'ECONNRESET' || error.code === 'ETIMEDOUT') { finishCall(false); return; } self.emit('error', new Error('Client error: ' + error.message)); self.running = false; }); } } startAllClients(_.map(self.client_options, _.partial(_.assign, options)), outstanding_rpcs_per_channel, makeCall, self); }; BenchmarkClient.prototype.startPoisson = function( outstanding_rpcs_per_channel, rpc_type, req_size, resp_size, offered_load, generic) { var self = this; var options = {}; self.running = true; if (rpc_type == 'UNARY') { options.path = '/serviceProto.BenchmarkService.service/unaryCall'; } else { self.emit('error', new Error('Unsupported rpc_type: ' + rpc_type)); } if (generic) { self.emit('error', new Error('Generic client not supported')); } self.last_wall_time = process.hrtime(); self.last_usage = process.cpuUsage(); var argument = { response_size: resp_size, payload: { body: '0'.repeat(req_size) } }; function makeCall(client_options, poisson) { if (self.running) { self.pending_calls++; var start_time = process.hrtime(); var req = self.request(client_options, function(res) { var res_data = ''; res.on('data', function(data) { res_data += data; }); res.on('end', function() { JSON.parse(res_data); var time_diff = process.hrtime(start_time); self.histogram.add(timeDiffToNanos(time_diff)); self.pending_calls--; if ((!self.running) && self.pending_calls == 0) { self.emit('finished'); } }); }); req.write(JSON.stringify(argument)); req.end(); req.on('error', function(error) { self.emit('error', new Error('Client error: ' + error.message)); self.running = false; }); } else { poisson.stop(); } } var averageIntervalMs = (1 / offered_load) * 1000; startAllClients(_.map(self.client_options, _.partial(_.assign, options)), outstanding_rpcs_per_channel, function(opts){ var p = PoissonProcess.create(averageIntervalMs, function() { makeCall(opts, p); }); p.start(); }, self); }; /** * Return curent statistics for the client. If reset is set, restart * statistic collection. * @param {boolean} reset Indicates that statistics should be reset * @return {object} Client statistics */ BenchmarkClient.prototype.mark = function(reset) { var wall_time_diff = process.hrtime(this.last_wall_time); var usage_diff = process.cpuUsage(this.last_usage); var histogram = this.histogram; if (reset) { this.last_wall_time = process.hrtime(); this.last_usage = process.cpuUsage(); this.histogram = new Histogram(histogram.resolution, histogram.max_possible); } return { latencies: { bucket: histogram.getContents(), min_seen: histogram.minimum(), max_seen: histogram.maximum(), sum: histogram.getSum(), sum_of_squares: histogram.sumOfSquares(), count: histogram.getCount() }, time_elapsed: wall_time_diff[0] + wall_time_diff[1] / 1e9, time_user: usage_diff.user / 1000000, time_system: usage_diff.system / 1000000 }; }; /** * Stop the clients. * @param {function} callback Called when the clients have finished shutting * down */ BenchmarkClient.prototype.stop = function(callback) { this.running = false; this.on('finished', callback); }; module.exports = BenchmarkClient; grpc-1.3.2/src/node/performance/benchmark_server.js000066400000000000000000000144461310511640000223430ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** * Benchmark server module * @module */ 'use strict'; var fs = require('fs'); var path = require('path'); var EventEmitter = require('events'); var util = require('util'); var genericService = require('./generic_service'); var grpc = require('../../../'); var serviceProto = grpc.load({ root: __dirname + '/../../..', file: 'src/proto/grpc/testing/services.proto'}).grpc.testing; /** * Create a buffer filled with size zeroes * @param {number} size The length of the buffer * @return {Buffer} The new buffer */ function zeroBuffer(size) { var zeros = new Buffer(size); zeros.fill(0); return zeros; } /** * Handler for the unary benchmark method. Simply responds with a payload * containing the requested number of zero bytes. * @param {Call} call The call object to be handled * @param {function} callback The callback to call with the response */ function unaryCall(call, callback) { var req = call.request; var payload = {body: zeroBuffer(req.response_size)}; callback(null, {payload: payload}); } /** * Handler for the streaming benchmark method. Simply responds to each request * with a payload containing the requested number of zero bytes. * @param {Call} call The call object to be handled */ function streamingCall(call) { call.on('data', function(value) { var payload = {body: zeroBuffer(value.response_size)}; call.write({payload: payload}); }); call.on('end', function() { call.end(); }); } function makeUnaryGenericCall(response_size) { var response = zeroBuffer(response_size); return function unaryGenericCall(call, callback) { callback(null, response); }; } function makeStreamingGenericCall(response_size) { var response = zeroBuffer(response_size); return function streamingGenericCall(call) { call.on('data', function(value) { call.write(response); }); call.on('end', function() { call.end(); }); }; } /** * BenchmarkServer class. Constructed based on parameters from the driver and * stores statistics. * @param {string} host The host to serve on * @param {number} port The port to listen to * @param {boolean} tls Indicates whether TLS should be used * @param {boolean} generic Indicates whether to use the generic service * @param {number=} response_size The response size for the generic service */ function BenchmarkServer(host, port, tls, generic, response_size) { var server_creds; var host_override; if (tls) { var key_path = path.join(__dirname, '../test/data/server1.key'); var pem_path = path.join(__dirname, '../test/data/server1.pem'); var key_data = fs.readFileSync(key_path); var pem_data = fs.readFileSync(pem_path); server_creds = grpc.ServerCredentials.createSsl(null, [{private_key: key_data, cert_chain: pem_data}]); } else { server_creds = grpc.ServerCredentials.createInsecure(); } var options = { "grpc.max_receive_message_length": -1, "grpc.max_send_message_length": -1 }; var server = new grpc.Server(options); this.port = server.bind(host + ':' + port, server_creds); if (generic) { server.addService(genericService, { unaryCall: makeUnaryGenericCall(response_size), streamingCall: makeStreamingGenericCall(response_size) }); } else { server.addService(serviceProto.BenchmarkService.service, { unaryCall: unaryCall, streamingCall: streamingCall }); } this.server = server; } util.inherits(BenchmarkServer, EventEmitter); /** * Start the benchmark server. */ BenchmarkServer.prototype.start = function() { this.server.start(); this.last_wall_time = process.hrtime(); this.last_usage = process.cpuUsage(); this.emit('started'); }; /** * Return the port number that the server is bound to. * @return {Number} The port number */ BenchmarkServer.prototype.getPort = function() { return this.port; }; /** * Return current statistics for the server. If reset is set, restart * statistic collection. * @param {boolean} reset Indicates that statistics should be reset * @return {object} Server statistics */ BenchmarkServer.prototype.mark = function(reset) { var wall_time_diff = process.hrtime(this.last_wall_time); var usage_diff = process.cpuUsage(this.last_usage); if (reset) { this.last_wall_time = process.hrtime(); this.last_usage = process.cpuUsage(); } return { time_elapsed: wall_time_diff[0] + wall_time_diff[1] / 1e9, time_user: usage_diff.user / 1000000, time_system: usage_diff.system / 1000000 }; }; /** * Stop the server. * @param {function} callback Called when the server has finished shutting down */ BenchmarkServer.prototype.stop = function(callback) { this.server.tryShutdown(callback); }; module.exports = BenchmarkServer; grpc-1.3.2/src/node/performance/benchmark_server_express.js000066400000000000000000000071471310511640000241140ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** * Benchmark server module * @module */ 'use strict'; var fs = require('fs'); var path = require('path'); var http = require('http'); var https = require('https'); var EventEmitter = require('events'); var util = require('util'); var express = require('express'); var bodyParser = require('body-parser'); function unaryCall(req, res) { var reqObj = req.body; var payload = {body: '0'.repeat(reqObj.response_size)}; res.json(payload); } function BenchmarkServer(host, port, tls, generic, response_size) { var app = express(); app.use(bodyParser.json()); app.put('/serviceProto.BenchmarkService.service/unaryCall', unaryCall); this.input_host = host; this.input_port = port; if (tls) { var credentials = {}; var key_path = path.join(__dirname, '../test/data/server1.key'); var pem_path = path.join(__dirname, '../test/data/server1.pem'); var key_data = fs.readFileSync(key_path); var pem_data = fs.readFileSync(pem_path); credentials['key'] = key_data; credentials['cert'] = pem_data; this.server = https.createServer(credentials, app); } else { this.server = http.createServer(app); } } util.inherits(BenchmarkServer, EventEmitter); BenchmarkServer.prototype.start = function() { var self = this; this.server.listen(this.input_port, this.input_hostname, function() { self.last_wall_time = process.hrtime(); self.last_usage = process.cpuUsage(); self.emit('started'); }); }; BenchmarkServer.prototype.getPort = function() { return this.server.address().port; }; BenchmarkServer.prototype.mark = function(reset) { var wall_time_diff = process.hrtime(this.last_wall_time); var usage_diff = process.cpuUsage(this.last_usage); if (reset) { this.last_wall_time = process.hrtime(); this.last_usage = process.cpuUsage(); } return { time_elapsed: wall_time_diff[0] + wall_time_diff[1] / 1e9, time_user: usage_diff.user / 1000000, time_system: usage_diff.system / 1000000 }; }; BenchmarkServer.prototype.stop = function(callback) { this.server.close(callback); }; module.exports = BenchmarkServer; grpc-1.3.2/src/node/performance/generic_service.js000066400000000000000000000041671310511640000221560ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ var _ = require('lodash'); module.exports = { 'unaryCall' : { path: '/grpc.testing.BenchmarkService/UnaryCall', requestStream: false, responseStream: false, requestSerialize: _.identity, requestDeserialize: _.identity, responseSerialize: _.identity, responseDeserialize: _.identity }, 'streamingCall' : { path: '/grpc.testing.BenchmarkService/StreamingCall', requestStream: true, responseStream: true, requestSerialize: _.identity, requestDeserialize: _.identity, responseSerialize: _.identity, responseDeserialize: _.identity } }; grpc-1.3.2/src/node/performance/histogram.js000066400000000000000000000120171310511640000210100ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** * Histogram module. Exports the Histogram class * @module */ 'use strict'; /** * Histogram class. Collects data and exposes a histogram and other statistics. * This data structure is taken directly from src/core/support/histogram.c, but * pared down to the statistics needed for client stats in * test/proto/benchmarks/stats.proto. * @constructor * @param {number} resolution The histogram's bucket resolution. Must be positive * @param {number} max_possible The maximum allowed value. Must be greater than 1 */ function Histogram(resolution, max_possible) { this.resolution = resolution; this.max_possible = max_possible; this.sum = 0; this.sum_of_squares = 0; this.multiplier = 1 + resolution; this.count = 0; this.min_seen = max_possible; this.max_seen = 0; this.buckets = []; for (var i = 0; i < this.bucketFor(max_possible) + 1; i++) { this.buckets[i] = 0; } } /** * Get the bucket index for a given value. * @param {number} value The value to check * @return {number} The bucket index */ Histogram.prototype.bucketFor = function(value) { return Math.floor(Math.log(value) / Math.log(this.multiplier)); }; /** * Get the minimum value for a given bucket index * @param {number} The bucket index to check * @return {number} The minimum value for that bucket */ Histogram.prototype.bucketStart = function(index) { return Math.pow(this.multiplier, index); }; /** * Add a value to the histogram. This updates all statistics with the new * value. Those statistics should not be modified except with this function * @param {number} value The value to add */ Histogram.prototype.add = function(value) { // Ensure value is a number value = +value; this.sum += value; this.sum_of_squares += value * value; this.count++; if (value < this.min_seen) { this.min_seen = value; } if (value > this.max_seen) { this.max_seen = value; } this.buckets[this.bucketFor(value)]++; }; /** * Get the mean of all added values * @return {number} The mean */ Histogram.prototype.mean = function() { return this.sum / this.count; }; /** * Get the variance of all added values. Used to calulate the standard deviation * @return {number} The variance */ Histogram.prototype.variance = function() { if (this.count == 0) { return 0; } return (this.sum_of_squares * this.count - this.sum * this.sum) / (this.count * this.count); }; /** * Get the standard deviation of all added values * @return {number} The standard deviation */ Histogram.prototype.stddev = function() { return Math.sqrt(this.variance); }; /** * Get the maximum among all added values * @return {number} The maximum */ Histogram.prototype.maximum = function() { return this.max_seen; }; /** * Get the minimum among all added values * @return {number} The minimum */ Histogram.prototype.minimum = function() { return this.min_seen; }; /** * Get the number of all added values * @return {number} The count */ Histogram.prototype.getCount = function() { return this.count; }; /** * Get the sum of all added values * @return {number} The sum */ Histogram.prototype.getSum = function() { return this.sum; }; /** * Get the sum of squares of all added values * @return {number} The sum of squares */ Histogram.prototype.sumOfSquares = function() { return this.sum_of_squares; }; /** * Get the raw histogram as a list of bucket sizes * @return {Array.} The buckets */ Histogram.prototype.getContents = function() { return this.buckets; }; module.exports = Histogram; grpc-1.3.2/src/node/performance/worker.js000066400000000000000000000047651310511640000203370ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var console = require('console'); var WorkerServiceImpl = require('./worker_service_impl'); var grpc = require('../../../'); var serviceProto = grpc.load({ root: __dirname + '/../../..', file: 'src/proto/grpc/testing/services.proto'}).grpc.testing; function runServer(port, benchmark_impl) { var server_creds = grpc.ServerCredentials.createInsecure(); var server = new grpc.Server(); server.addService(serviceProto.WorkerService.service, new WorkerServiceImpl(benchmark_impl, server)); var address = '0.0.0.0:' + port; server.bind(address, server_creds); server.start(); console.log('running QPS worker on %s', address); return server; } if (require.main === module) { Error.stackTraceLimit = Infinity; var parseArgs = require('minimist'); var argv = parseArgs(process.argv, { string: ['driver_port', 'benchmark_impl'] }); runServer(argv.driver_port, argv.benchmark_impl); } exports.runServer = runServer; grpc-1.3.2/src/node/performance/worker_service_impl.js000066400000000000000000000152751310511640000230760ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var os = require('os'); var console = require('console'); var BenchmarkClient = require('./benchmark_client'); var BenchmarkServer = require('./benchmark_server'); module.exports = function WorkerServiceImpl(benchmark_impl, server) { var BenchmarkClient; var BenchmarkServer; switch (benchmark_impl) { case 'grpc': BenchmarkClient = require('./benchmark_client'); BenchmarkServer = require('./benchmark_server'); break; case 'express': BenchmarkClient = require('./benchmark_client_express'); BenchmarkServer = require('./benchmark_server_express'); break; default: throw new Error('Unrecognized benchmark impl: ' + benchmark_impl); } this.quitWorker = function quitWorker(call, callback) { callback(null, {}); server.tryShutdown(function() {}); }; this.runClient = function runClient(call) { var client; call.on('data', function(request) { var stats; switch (request.argtype) { case 'setup': var setup = request.setup; console.log('ClientConfig %j', setup); client = new BenchmarkClient(setup.server_targets, setup.client_channels, setup.histogram_params, setup.security_params); client.on('error', function(error) { call.emit('error', error); }); var req_size, resp_size, generic; switch (setup.payload_config.payload) { case 'bytebuf_params': req_size = setup.payload_config.bytebuf_params.req_size; resp_size = setup.payload_config.bytebuf_params.resp_size; generic = true; break; case 'simple_params': req_size = setup.payload_config.simple_params.req_size; resp_size = setup.payload_config.simple_params.resp_size; generic = false; break; default: call.emit('error', new Error('Unsupported PayloadConfig type' + setup.payload_config.payload)); return; } switch (setup.load_params.load) { case 'closed_loop': client.startClosedLoop(setup.outstanding_rpcs_per_channel, setup.rpc_type, req_size, resp_size, generic); break; case 'poisson': client.startPoisson(setup.outstanding_rpcs_per_channel, setup.rpc_type, req_size, resp_size, setup.load_params.poisson.offered_load, generic); break; default: call.emit('error', new Error('Unsupported LoadParams type' + setup.load_params.load)); return; } stats = client.mark(); call.write({ stats: stats }); break; case 'mark': if (client) { stats = client.mark(request.mark.reset); call.write({ stats: stats }); } else { call.emit('error', new Error('Got Mark before ClientConfig')); } break; default: throw new Error('Nonexistent client argtype option: ' + request.argtype); } }); call.on('end', function() { client.stop(function() { call.end(); }); }); }; this.runServer = function runServer(call) { var server; call.on('data', function(request) { var stats; switch (request.argtype) { case 'setup': console.log('ServerConfig %j', request.setup); var setup = request.setup; var resp_size, generic; if (setup.payload_config) { switch (setup.payload_config.payload) { case 'bytebuf_params': resp_size = setup.payload_config.bytebuf_params.resp_size; generic = true; break; case 'simple_params': resp_size = setup.payload_config.simple_params.resp_size; generic = false; break; default: call.emit('error', new Error('Unsupported PayloadConfig type' + setup.payload_config.payload)); return; } } server = new BenchmarkServer('[::]', request.setup.port, request.setup.security_params, generic, resp_size); server.on('started', function() { stats = server.mark(); call.write({ stats: stats, port: server.getPort() }); }); server.start(); break; case 'mark': if (server) { stats = server.mark(request.mark.reset); call.write({ stats: stats, port: server.getPort(), cores: 1 }); } else { call.emit('error', new Error('Got Mark before ServerConfig')); } break; default: throw new Error('Nonexistent server argtype option'); } }); call.on('end', function() { server.stop(function() { call.end(); }); }); }; this.coreCount = function coreCount(call, callback) { callback(null, {cores: os.cpus().length}); }; }; grpc-1.3.2/src/node/src/000077500000000000000000000000001310511640000147425ustar00rootroot00000000000000grpc-1.3.2/src/node/src/client.js000066400000000000000000000720041310511640000165610ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** * Client module * * This module contains the factory method for creating Client classes, and the * method calling code for all types of methods. * * For example, to create a client and call a method on it: * * var proto_obj = grpc.load(proto_file_path); * var Client = proto_obj.package.subpackage.ServiceName; * var client = new Client(server_address, client_credentials); * var call = client.unaryMethod(arguments, callback); * * @module */ 'use strict'; var _ = require('lodash'); var arguejs = require('arguejs'); var grpc = require('./grpc_extension'); var common = require('./common'); var Metadata = require('./metadata'); var EventEmitter = require('events').EventEmitter; var stream = require('stream'); var Readable = stream.Readable; var Writable = stream.Writable; var Duplex = stream.Duplex; var util = require('util'); var version = require('../../../package.json').version; util.inherits(ClientWritableStream, Writable); /** * A stream that the client can write to. Used for calls that are streaming from * the client side. * @constructor * @param {grpc.Call} call The call object to send data with * @param {function(*):Buffer=} serialize Serialization function for writes. */ function ClientWritableStream(call, serialize) { Writable.call(this, {objectMode: true}); this.call = call; this.serialize = common.wrapIgnoreNull(serialize); this.on('finish', function() { var batch = {}; batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; call.startBatch(batch, function() {}); }); } /** * Attempt to write the given chunk. Calls the callback when done. This is an * implementation of a method needed for implementing stream.Writable. * @access private * @param {Buffer} chunk The chunk to write * @param {string} encoding Used to pass write flags * @param {function(Error=)} callback Called when the write is complete */ function _write(chunk, encoding, callback) { /* jshint validthis: true */ var batch = {}; var message; try { message = this.serialize(chunk); } catch (e) { /* Sending this error to the server and emitting it immediately on the client may put the call in a slightly weird state on the client side, but passing an object that causes a serialization failure is a misuse of the API anyway, so that's OK. The primary purpose here is to give the programmer a useful error and to stop the stream properly */ this.call.cancelWithStatus(grpc.status.INTERNAL, 'Serialization failure'); callback(e); } if (_.isFinite(encoding)) { /* Attach the encoding if it is a finite number. This is the closest we * can get to checking that it is valid flags */ message.grpcWriteFlags = encoding; } batch[grpc.opType.SEND_MESSAGE] = message; this.call.startBatch(batch, function(err, event) { if (err) { // Something has gone wrong. Stop writing by failing to call callback return; } callback(); }); } ClientWritableStream.prototype._write = _write; util.inherits(ClientReadableStream, Readable); /** * A stream that the client can read from. Used for calls that are streaming * from the server side. * @constructor * @param {grpc.Call} call The call object to read data with * @param {function(Buffer):*=} deserialize Deserialization function for reads */ function ClientReadableStream(call, deserialize) { Readable.call(this, {objectMode: true}); this.call = call; this.finished = false; this.reading = false; this.deserialize = common.wrapIgnoreNull(deserialize); /* Status generated from reading messages from the server. Overrides the * status from the server if not OK */ this.read_status = null; /* Status received from the server. */ this.received_status = null; } /** * Called when all messages from the server have been processed. The status * parameter indicates that the call should end with that status. status * defaults to OK if not provided. * @param {Object!} status The status that the call should end with */ function _readsDone(status) { /* jshint validthis: true */ if (!status) { status = {code: grpc.status.OK, details: 'OK'}; } if (status.code !== grpc.status.OK) { this.call.cancelWithStatus(status.code, status.details); } this.finished = true; this.read_status = status; this._emitStatusIfDone(); } ClientReadableStream.prototype._readsDone = _readsDone; /** * Called to indicate that we have received a status from the server. */ function _receiveStatus(status) { /* jshint validthis: true */ this.received_status = status; this._emitStatusIfDone(); } ClientReadableStream.prototype._receiveStatus = _receiveStatus; /** * If we have both processed all incoming messages and received the status from * the server, emit the status. Otherwise, do nothing. */ function _emitStatusIfDone() { /* jshint validthis: true */ var status; if (this.read_status && this.received_status) { if (this.read_status.code !== grpc.status.OK) { status = this.read_status; } else { status = this.received_status; } if (status.code === grpc.status.OK) { this.push(null); } else { var error = new Error(status.details); error.code = status.code; error.metadata = status.metadata; this.emit('error', error); } this.emit('status', status); } } ClientReadableStream.prototype._emitStatusIfDone = _emitStatusIfDone; /** * Read the next object from the stream. * @access private * @param {*} size Ignored because we use objectMode=true */ function _read(size) { /* jshint validthis: true */ var self = this; /** * Callback to be called when a READ event is received. Pushes the data onto * the read queue and starts reading again if applicable * @param {grpc.Event} event READ event object */ function readCallback(err, event) { if (err) { // Something has gone wrong. Stop reading and wait for status self.finished = true; self._readsDone(); return; } var data = event.read; var deserialized; try { deserialized = self.deserialize(data); } catch (e) { self._readsDone({code: grpc.status.INTERNAL, details: 'Failed to parse server response'}); return; } if (data === null) { self._readsDone(); return; } if (self.push(deserialized) && data !== null) { var read_batch = {}; read_batch[grpc.opType.RECV_MESSAGE] = true; self.call.startBatch(read_batch, readCallback); } else { self.reading = false; } } if (self.finished) { self.push(null); } else { if (!self.reading) { self.reading = true; var read_batch = {}; read_batch[grpc.opType.RECV_MESSAGE] = true; self.call.startBatch(read_batch, readCallback); } } } ClientReadableStream.prototype._read = _read; util.inherits(ClientDuplexStream, Duplex); /** * A stream that the client can read from or write to. Used for calls with * duplex streaming. * @constructor * @param {grpc.Call} call Call object to proxy * @param {function(*):Buffer=} serialize Serialization function for requests * @param {function(Buffer):*=} deserialize Deserialization function for * responses */ function ClientDuplexStream(call, serialize, deserialize) { Duplex.call(this, {objectMode: true}); this.serialize = common.wrapIgnoreNull(serialize); this.deserialize = common.wrapIgnoreNull(deserialize); this.call = call; /* Status generated from reading messages from the server. Overrides the * status from the server if not OK */ this.read_status = null; /* Status received from the server. */ this.received_status = null; this.on('finish', function() { var batch = {}; batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; call.startBatch(batch, function() {}); }); } ClientDuplexStream.prototype._readsDone = _readsDone; ClientDuplexStream.prototype._receiveStatus = _receiveStatus; ClientDuplexStream.prototype._emitStatusIfDone = _emitStatusIfDone; ClientDuplexStream.prototype._read = _read; ClientDuplexStream.prototype._write = _write; /** * Cancel the ongoing call */ function cancel() { /* jshint validthis: true */ this.call.cancel(); } ClientReadableStream.prototype.cancel = cancel; ClientWritableStream.prototype.cancel = cancel; ClientDuplexStream.prototype.cancel = cancel; /** * Get the endpoint this call/stream is connected to. * @return {string} The URI of the endpoint */ function getPeer() { /* jshint validthis: true */ return this.call.getPeer(); } ClientReadableStream.prototype.getPeer = getPeer; ClientWritableStream.prototype.getPeer = getPeer; ClientDuplexStream.prototype.getPeer = getPeer; /** * Get a call object built with the provided options. Keys for options are * 'deadline', which takes a date or number, and 'host', which takes a string * and overrides the hostname to connect to. * @param {Object} options Options map. */ function getCall(channel, method, options) { var deadline; var host; var parent; var propagate_flags; var credentials; if (options) { deadline = options.deadline; host = options.host; parent = _.get(options, 'parent.call'); propagate_flags = options.propagate_flags; credentials = options.credentials; } if (deadline === undefined) { deadline = Infinity; } var call = new grpc.Call(channel, method, deadline, host, parent, propagate_flags); if (credentials) { call.setCredentials(credentials); } return call; } /** * Get a function that can make unary requests to the specified method. * @param {string} method The name of the method to request * @param {function(*):Buffer} serialize The serialization function for inputs * @param {function(Buffer)} deserialize The deserialization function for * outputs * @return {Function} makeUnaryRequest */ function makeUnaryRequestFunction(method, serialize, deserialize) { /** * Make a unary request with this method on the given channel with the given * argument, callback, etc. * @this {Client} Client object. Must have a channel member. * @param {*} argument The argument to the call. Should be serializable with * serialize * @param {Metadata=} metadata Metadata to add to the call * @param {Object=} options Options map * @param {function(?Error, value=)} callback The callback to for when the * response is received * @return {EventEmitter} An event emitter for stream related events */ function makeUnaryRequest(argument, metadata, options, callback) { /* jshint validthis: true */ /* While the arguments are listed in the function signature, those variables * are not used directly. Instead, ArgueJS processes the arguments * object. This allows for simple handling of optional arguments in the * middle of the argument list, and also provides type checking. */ var args = arguejs({argument: null, metadata: [Metadata, new Metadata()], options: [Object], callback: Function}, arguments); var emitter = new EventEmitter(); var call = getCall(this.$channel, method, args.options); metadata = args.metadata.clone(); emitter.cancel = function cancel() { call.cancel(); }; emitter.getPeer = function getPeer() { return call.getPeer(); }; var client_batch = {}; var message = serialize(args.argument); if (args.options) { message.grpcWriteFlags = args.options.flags; } client_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata._getCoreRepresentation(); client_batch[grpc.opType.SEND_MESSAGE] = message; client_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; client_batch[grpc.opType.RECV_INITIAL_METADATA] = true; client_batch[grpc.opType.RECV_MESSAGE] = true; client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; call.startBatch(client_batch, function(err, response) { response.status.metadata = Metadata._fromCoreRepresentation( response.status.metadata); var status = response.status; var error; var deserialized; emitter.emit('metadata', Metadata._fromCoreRepresentation( response.metadata)); if (status.code === grpc.status.OK) { if (err) { // Got a batch error, but OK status. Something went wrong args.callback(err); return; } else { try { deserialized = deserialize(response.read); } catch (e) { /* Change status to indicate bad server response. This will result * in passing an error to the callback */ status = { code: grpc.status.INTERNAL, details: 'Failed to parse server response' }; } } } if (status.code !== grpc.status.OK) { error = new Error(status.details); error.code = status.code; error.metadata = status.metadata; args.callback(error); } else { args.callback(null, deserialized); } emitter.emit('status', status); }); return emitter; } return makeUnaryRequest; } /** * Get a function that can make client stream requests to the specified method. * @param {string} method The name of the method to request * @param {function(*):Buffer} serialize The serialization function for inputs * @param {function(Buffer)} deserialize The deserialization function for * outputs * @return {Function} makeClientStreamRequest */ function makeClientStreamRequestFunction(method, serialize, deserialize) { /** * Make a client stream request with this method on the given channel with the * given callback, etc. * @this {Client} Client object. Must have a channel member. * @param {Metadata=} metadata Array of metadata key/value pairs to add to the * call * @param {Object=} options Options map * @param {function(?Error, value=)} callback The callback to for when the * response is received * @return {EventEmitter} An event emitter for stream related events */ function makeClientStreamRequest(metadata, options, callback) { /* jshint validthis: true */ /* While the arguments are listed in the function signature, those variables * are not used directly. Instead, ArgueJS processes the arguments * object. This allows for simple handling of optional arguments in the * middle of the argument list, and also provides type checking. */ var args = arguejs({metadata: [Metadata, new Metadata()], options: [Object], callback: Function}, arguments); var call = getCall(this.$channel, method, args.options); metadata = args.metadata.clone(); var stream = new ClientWritableStream(call, serialize); var metadata_batch = {}; metadata_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata._getCoreRepresentation(); metadata_batch[grpc.opType.RECV_INITIAL_METADATA] = true; call.startBatch(metadata_batch, function(err, response) { if (err) { // The call has stopped for some reason. A non-OK status will arrive // in the other batch. return; } stream.emit('metadata', Metadata._fromCoreRepresentation( response.metadata)); }); var client_batch = {}; client_batch[grpc.opType.RECV_MESSAGE] = true; client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; call.startBatch(client_batch, function(err, response) { response.status.metadata = Metadata._fromCoreRepresentation( response.status.metadata); var status = response.status; var error; var deserialized; if (status.code === grpc.status.OK) { if (err) { // Got a batch error, but OK status. Something went wrong args.callback(err); return; } else { try { deserialized = deserialize(response.read); } catch (e) { /* Change status to indicate bad server response. This will result * in passing an error to the callback */ status = { code: grpc.status.INTERNAL, details: 'Failed to parse server response' }; } } } if (status.code !== grpc.status.OK) { error = new Error(response.status.details); error.code = status.code; error.metadata = status.metadata; args.callback(error); } else { args.callback(null, deserialized); } stream.emit('status', status); }); return stream; } return makeClientStreamRequest; } /** * Get a function that can make server stream requests to the specified method. * @param {string} method The name of the method to request * @param {function(*):Buffer} serialize The serialization function for inputs * @param {function(Buffer)} deserialize The deserialization function for * outputs * @return {Function} makeServerStreamRequest */ function makeServerStreamRequestFunction(method, serialize, deserialize) { /** * Make a server stream request with this method on the given channel with the * given argument, etc. * @this {SurfaceClient} Client object. Must have a channel member. * @param {*} argument The argument to the call. Should be serializable with * serialize * @param {Metadata=} metadata Array of metadata key/value pairs to add to the * call * @param {Object} options Options map * @return {EventEmitter} An event emitter for stream related events */ function makeServerStreamRequest(argument, metadata, options) { /* jshint validthis: true */ /* While the arguments are listed in the function signature, those variables * are not used directly. Instead, ArgueJS processes the arguments * object. */ var args = arguejs({argument: null, metadata: [Metadata, new Metadata()], options: [Object]}, arguments); var call = getCall(this.$channel, method, args.options); metadata = args.metadata.clone(); var stream = new ClientReadableStream(call, deserialize); var start_batch = {}; var message = serialize(args.argument); if (args.options) { message.grpcWriteFlags = args.options.flags; } start_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata._getCoreRepresentation(); start_batch[grpc.opType.RECV_INITIAL_METADATA] = true; start_batch[grpc.opType.SEND_MESSAGE] = message; start_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; call.startBatch(start_batch, function(err, response) { if (err) { // The call has stopped for some reason. A non-OK status will arrive // in the other batch. return; } stream.emit('metadata', Metadata._fromCoreRepresentation( response.metadata)); }); var status_batch = {}; status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; call.startBatch(status_batch, function(err, response) { if (err) { stream.emit('error', err); return; } response.status.metadata = Metadata._fromCoreRepresentation( response.status.metadata); stream._receiveStatus(response.status); }); return stream; } return makeServerStreamRequest; } /** * Get a function that can make bidirectional stream requests to the specified * method. * @param {string} method The name of the method to request * @param {function(*):Buffer} serialize The serialization function for inputs * @param {function(Buffer)} deserialize The deserialization function for * outputs * @return {Function} makeBidiStreamRequest */ function makeBidiStreamRequestFunction(method, serialize, deserialize) { /** * Make a bidirectional stream request with this method on the given channel. * @this {SurfaceClient} Client object. Must have a channel member. * @param {Metadata=} metadata Array of metadata key/value pairs to add to the * call * @param {Options} options Options map * @return {EventEmitter} An event emitter for stream related events */ function makeBidiStreamRequest(metadata, options) { /* jshint validthis: true */ /* While the arguments are listed in the function signature, those variables * are not used directly. Instead, ArgueJS processes the arguments * object. */ var args = arguejs({metadata: [Metadata, new Metadata()], options: [Object]}, arguments); var call = getCall(this.$channel, method, args.options); metadata = args.metadata.clone(); var stream = new ClientDuplexStream(call, serialize, deserialize); var start_batch = {}; start_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata._getCoreRepresentation(); start_batch[grpc.opType.RECV_INITIAL_METADATA] = true; call.startBatch(start_batch, function(err, response) { if (err) { // The call has stopped for some reason. A non-OK status will arrive // in the other batch. return; } stream.emit('metadata', Metadata._fromCoreRepresentation( response.metadata)); }); var status_batch = {}; status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; call.startBatch(status_batch, function(err, response) { if (err) { stream.emit('error', err); return; } response.status.metadata = Metadata._fromCoreRepresentation( response.status.metadata); stream._receiveStatus(response.status); }); return stream; } return makeBidiStreamRequest; } /** * Map with short names for each of the requester maker functions. Used in * makeClientConstructor */ var requester_makers = { unary: makeUnaryRequestFunction, server_stream: makeServerStreamRequestFunction, client_stream: makeClientStreamRequestFunction, bidi: makeBidiStreamRequestFunction }; function getDefaultValues(metadata, options) { var res = {}; res.metadata = metadata || new Metadata(); res.options = options || {}; return res; } /** * Map with wrappers for each type of requester function to make it use the old * argument order with optional arguments after the callback. */ var deprecated_request_wrap = { unary: function(makeUnaryRequest) { return function makeWrappedUnaryRequest(argument, callback, metadata, options) { /* jshint validthis: true */ var opt_args = getDefaultValues(metadata, metadata); return makeUnaryRequest.call(this, argument, opt_args.metadata, opt_args.options, callback); }; }, client_stream: function(makeServerStreamRequest) { return function makeWrappedClientStreamRequest(callback, metadata, options) { /* jshint validthis: true */ var opt_args = getDefaultValues(metadata, options); return makeServerStreamRequest.call(this, opt_args.metadata, opt_args.options, callback); }; }, server_stream: _.identity, bidi: _.identity }; /** * Creates a constructor for a client with the given methods. The methods object * maps method name to an object with the following keys: * path: The path on the server for accessing the method. For example, for * protocol buffers, we use "/service_name/method_name" * requestStream: bool indicating whether the client sends a stream * resonseStream: bool indicating whether the server sends a stream * requestSerialize: function to serialize request objects * responseDeserialize: function to deserialize response objects * @param {Object} methods An object mapping method names to method attributes * @param {string} serviceName The fully qualified name of the service * @param {Object} class_options An options object. Currently only uses the key * deprecatedArgumentOrder, a boolean that Indicates that the old argument * order should be used for methods, with optional arguments at the end * instead of the callback at the end. 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. * @return {function(string, Object)} New client constructor */ exports.makeClientConstructor = function(methods, serviceName, class_options) { if (!class_options) { class_options = {}; } /** * Create a client with the given methods * @constructor * @param {string} address The address of the server to connect to * @param {grpc.Credentials} credentials Credentials to use to connect * to the server * @param {Object} options Options to pass to the underlying channel */ function Client(address, credentials, options) { if (!options) { options = {}; } /* Append the grpc-node user agent string after the application user agent * string, and put the combination at the beginning of the user agent string */ if (options['grpc.primary_user_agent']) { options['grpc.primary_user_agent'] += ' '; } else { options['grpc.primary_user_agent'] = ''; } options['grpc.primary_user_agent'] += 'grpc-node/' + version; /* Private fields use $ as a prefix instead of _ because it is an invalid * prefix of a method name */ this.$channel = new grpc.Channel(address, credentials, options); } _.each(methods, function(attrs, name) { var method_type; if (_.startsWith(name, '$')) { throw new Error('Method names cannot start with $'); } if (attrs.requestStream) { if (attrs.responseStream) { method_type = 'bidi'; } else { method_type = 'client_stream'; } } else { if (attrs.responseStream) { method_type = 'server_stream'; } else { method_type = 'unary'; } } var serialize = attrs.requestSerialize; var deserialize = attrs.responseDeserialize; var method_func = requester_makers[method_type]( attrs.path, serialize, deserialize); if (class_options.deprecatedArgumentOrder) { Client.prototype[name] = deprecated_request_wrap(method_func); } else { Client.prototype[name] = method_func; } // Associate all provided attributes with the method _.assign(Client.prototype[name], attrs); }); Client.service = methods; return Client; }; /** * Return the underlying channel object for the specified client * @param {Client} client * @return {Channel} The channel */ exports.getClientChannel = function(client) { return client.$channel; }; /** * Wait for the client to be ready. The callback will be called when the * client has successfully connected to the server, and it will be called * 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 * start connecting if it has not already done so. * @param {Client} client The client to wait on * @param {(Date|Number)} deadline When to stop waiting for a connection. Pass * Infinity to wait forever. * @param {function(Error)} callback The callback to call when done attempting * to connect. */ exports.waitForClientReady = function(client, deadline, callback) { var checkState = function(err) { if (err) { callback(new Error('Failed to connect before the deadline')); return; } var new_state = client.$channel.getConnectivityState(true); if (new_state === grpc.connectivityState.READY) { callback(); } else if (new_state === grpc.connectivityState.FATAL_FAILURE) { callback(new Error('Failed to connect to server')); } else { client.$channel.watchConnectivityState(new_state, deadline, checkState); } }; checkState(); }; /** * Map of status code names to status codes */ exports.status = grpc.status; /** * See docs for client.callError */ exports.callError = grpc.callError; grpc-1.3.2/src/node/src/common.js000066400000000000000000000056461310511640000166030ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** * 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'; var _ = require('lodash'); /** * Wrap a function to pass null-like values through without calling it. If no * function is given, just uses the identity; * @param {?function} func The function to wrap * @return {function} The wrapped function */ exports.wrapIgnoreNull = function wrapIgnoreNull(func) { if (!func) { return _.identity; } return function(arg) { if (arg === null || arg === undefined) { return null; } return func(arg); }; }; /** * The logger object for the gRPC module. Defaults to console. */ exports.logger = console; /** * The current logging verbosity. 0 corresponds to logging everything */ exports.logVerbosity = 0; /** * Log a message if the severity is at least as high as the current verbosity * @param {Number} severity A value of the grpc.logVerbosity map * @param {String} message The message to log */ exports.log = function log(severity, message) { if (severity >= exports.logVerbosity) { exports.logger.error(message); } }; /** * Default options for loading proto files into gRPC */ exports.defaultGrpcOptions = { convertFieldsToCamelCase: false, binaryAsBase64: false, longsAsStrings: true, enumsAsStrings: true, deprecatedArgumentOrder: false }; grpc-1.3.2/src/node/src/credentials.js000066400000000000000000000151341310511640000176010ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** * Credentials module * * This module contains factory methods for two different credential types: * CallCredentials and ChannelCredentials. ChannelCredentials are things like * SSL credentials that can be used to secure a connection, and are used to * construct a Client object. CallCredentials genrally modify metadata, so they * can be attached to an individual method call. * * CallCredentials can be composed with other CallCredentials to create * CallCredentials. ChannelCredentials can be composed with CallCredentials * to create ChannelCredentials. No combined credential can have more than * one ChannelCredentials. * * For example, to create a client secured with SSL that uses Google * default application credentials to authenticate: * * var channel_creds = credentials.createSsl(root_certs); * (new GoogleAuth()).getApplicationDefault(function(err, credential) { * var call_creds = credentials.createFromGoogleCredential(credential); * var combined_creds = credentials.combineChannelCredentials( * channel_creds, call_creds); * var client = new Client(address, combined_creds); * }); * * @module */ 'use strict'; var grpc = require('./grpc_extension'); var CallCredentials = grpc.CallCredentials; var ChannelCredentials = grpc.ChannelCredentials; var Metadata = require('./metadata.js'); var common = require('./common.js'); var _ = require('lodash'); /** * Create an SSL Credentials object. If using a client-side certificate, both * the second and third arguments must be passed. * @param {Buffer} root_certs The root certificate data * @param {Buffer=} private_key The client certificate private key, if * applicable * @param {Buffer=} cert_chain The client certificate cert chain, if applicable * @return {ChannelCredentials} The SSL Credentials object */ exports.createSsl = ChannelCredentials.createSsl; /** * Create a gRPC credentials object from a metadata generation function. This * 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, * which corresponds to a status code that this library uses. * @param {function(String, function(Error, Metadata))} metadata_generator The * function that generates metadata * @return {CallCredentials} The credentials object */ exports.createFromMetadataGenerator = function(metadata_generator) { return CallCredentials.createFromPlugin(function(service_url, cb_data, callback) { metadata_generator({service_url: service_url}, function(error, metadata) { var code = grpc.status.OK; var message = ''; if (error) { message = error.message; if (error.hasOwnProperty('code') && _.isFinite(error.code)) { code = error.code; } else { code = grpc.status.UNAUTHENTICATED; } if (!metadata) { metadata = new Metadata(); } } callback(code, message, metadata._getCoreRepresentation(), cb_data); }); }); }; /** * Create a gRPC credential from a Google credential object. * @param {Object} google_credential The Google credential object to use * @return {CallCredentials} The resulting credentials object */ exports.createFromGoogleCredential = function(google_credential) { return exports.createFromMetadataGenerator(function(auth_context, callback) { var service_url = auth_context.service_url; google_credential.getRequestMetadata(service_url, function(err, header) { if (err) { common.log(grpc.logVerbosity.INFO, 'Auth error:' + err); callback(err); return; } var metadata = new Metadata(); metadata.add('authorization', header.Authorization); callback(null, metadata); }); }); }; /** * Combine a ChannelCredentials with any number of CallCredentials into a single * ChannelCredentials object. * @param {ChannelCredentials} channel_credential The ChannelCredentials to * start with * @param {...CallCredentials} credentials The CallCredentials to compose * @return ChannelCredentials A credentials object that combines all of the * input credentials */ exports.combineChannelCredentials = function(channel_credential) { var current = channel_credential; for (var i = 1; i < arguments.length; i++) { current = current.compose(arguments[i]); } return current; }; /** * Combine any number of CallCredentials into a single CallCredentials object * @param {...CallCredentials} credentials the CallCredentials to compose * @return CallCredentials A credentials object that combines all of the input * credentials */ exports.combineCallCredentials = function() { var current = arguments[0]; for (var i = 1; i < arguments.length; i++) { current = current.compose(arguments[i]); } return current; }; /** * Create an insecure credentials object. This is used to create a channel that * does not use SSL. This cannot be composed with anything. * @return {ChannelCredentials} The insecure credentials object */ exports.createInsecure = ChannelCredentials.createInsecure; grpc-1.3.2/src/node/src/grpc_extension.js000066400000000000000000000034251310511640000203330ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ var binary = require('node-pre-gyp/lib/pre-binding'); var path = require('path'); var binding_path = binary.find(path.resolve(path.join(__dirname, '../../../package.json'))); var binding = require(binding_path); module.exports = binding; grpc-1.3.2/src/node/src/metadata.js000066400000000000000000000136271310511640000170710ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** * Metadata module * * This module defines the Metadata class, which represents header and trailer * metadata for gRPC calls. Here is an example of how to use it: * * var metadata = new metadata_module.Metadata(); * metadata.set('key1', 'value1'); * metadata.add('key1', 'value2'); * metadata.get('key1') // returns ['value1', 'value2'] * * @module */ 'use strict'; var _ = require('lodash'); var grpc = require('./grpc_extension'); /** * Class for storing metadata. Keys are normalized to lowercase ASCII. * @constructor */ function Metadata() { this._internal_repr = {}; } function normalizeKey(key) { key = key.toLowerCase(); if (grpc.metadataKeyIsLegal(key)) { return key; } else { throw new Error('Metadata key"' + key + '" contains illegal characters'); } } function validate(key, value) { if (grpc.metadataKeyIsBinary(key)) { if (!(value instanceof Buffer)) { throw new Error('keys that end with \'-bin\' must have Buffer values'); } } else { if (!_.isString(value)) { throw new Error( 'keys that don\'t end with \'-bin\' must have String values'); } if (!grpc.metadataNonbinValueIsLegal(value)) { throw new Error('Metadata string value "' + value + '" contains illegal characters'); } } } /** * Sets the given value for the given key, replacing any other values associated * with that key. Normalizes the key. * @param {String} key The key to set * @param {String|Buffer} value The value to set. Must be a buffer if and only * if the normalized key ends with '-bin' */ Metadata.prototype.set = function(key, value) { key = normalizeKey(key); validate(key, value); this._internal_repr[key] = [value]; }; /** * Adds the given value for the given key. Normalizes the key. * @param {String} key The key to add to. * @param {String|Buffer} value The value to add. Must be a buffer if and only * if the normalized key ends with '-bin' */ Metadata.prototype.add = function(key, value) { key = normalizeKey(key); validate(key, value); if (!this._internal_repr[key]) { this._internal_repr[key] = []; } this._internal_repr[key].push(value); }; /** * Remove the given key and any associated values. Normalizes the key. * @param {String} key The key to remove */ Metadata.prototype.remove = function(key) { key = normalizeKey(key); if (Object.prototype.hasOwnProperty.call(this._internal_repr, key)) { delete this._internal_repr[key]; } }; /** * Gets a list of all values associated with the key. Normalizes the key. * @param {String} key The key to get * @return {Array.} The values associated with that key */ Metadata.prototype.get = function(key) { key = normalizeKey(key); if (Object.prototype.hasOwnProperty.call(this._internal_repr, key)) { return this._internal_repr[key]; } else { return []; } }; /** * Get a map of each key to a single associated value. This reflects the most * common way that people will want to see metadata. * @return {Object.} A key/value mapping of the metadata */ Metadata.prototype.getMap = function() { var result = {}; _.forOwn(this._internal_repr, function(values, key) { if(values.length > 0) { result[key] = values[0]; } }); return result; }; /** * Clone the metadata object. * @return {Metadata} The new cloned object */ Metadata.prototype.clone = function() { var copy = new Metadata(); _.forOwn(this._internal_repr, function(value, key) { copy._internal_repr[key] = _.clone(value); }); return copy; }; /** * Gets the metadata in the format used by interal code. Intended for internal * use only. API stability is not guaranteed. * @private * @return {Object.>} The metadata */ Metadata.prototype._getCoreRepresentation = function() { return this._internal_repr; }; /** * Creates a Metadata object from a metadata map in the internal format. * Intended for internal use only. API stability is not guaranteed. * @private * @param {Object.>} The metadata * @return {Metadata} The new Metadata object */ Metadata._fromCoreRepresentation = function(metadata) { var newMetadata = new Metadata(); if (metadata) { _.forOwn(metadata, function(value, key) { newMetadata._internal_repr[key] = _.clone(value); }); } return newMetadata; }; module.exports = Metadata; grpc-1.3.2/src/node/src/protobuf_js_5_common.js000066400000000000000000000155421310511640000214370ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var _ = require('lodash'); var client = require('./client'); /** * Get a function that deserializes a specific type of protobuf. * @param {function()} cls The constructor of the message type to deserialize * @param {bool=} binaryAsBase64 Deserialize bytes fields as base64 strings * instead of Buffers. Defaults to false * @param {bool=} longsAsStrings Deserialize long values as strings instead of * objects. Defaults to true * @return {function(Buffer):cls} The deserialization function */ exports.deserializeCls = function deserializeCls(cls, options) { /** * Deserialize a buffer to a message object * @param {Buffer} arg_buf The buffer to deserialize * @return {cls} The resulting object */ return function deserialize(arg_buf) { // Convert to a native object with binary fields as Buffers (first argument) // and longs as strings (second argument) return cls.decode(arg_buf).toRaw(options.binaryAsBase64, options.longsAsStrings); }; }; var deserializeCls = exports.deserializeCls; /** * Get a function that serializes objects to a buffer by protobuf class. * @param {function()} Cls The constructor of the message type to serialize * @return {function(Cls):Buffer} The serialization function */ exports.serializeCls = function serializeCls(Cls) { /** * Serialize an object to a Buffer * @param {Object} arg The object to serialize * @return {Buffer} The serialized object */ return function serialize(arg) { return new Buffer(new Cls(arg).encode().toBuffer()); }; }; var serializeCls = exports.serializeCls; /** * Get the fully qualified (dotted) name of a ProtoBuf.Reflect value. * @param {ProtoBuf.Reflect.Namespace} value The value to get the name of * @return {string} The fully qualified name of the value */ exports.fullyQualifiedName = function fullyQualifiedName(value) { if (value === null || value === undefined) { return ''; } var name = value.name; var parent_name = fullyQualifiedName(value.parent); if (parent_name !== '') { name = parent_name + '.' + name; } return name; }; var fullyQualifiedName = exports.fullyQualifiedName; /** * Return a map from method names to method attributes for the service. * @param {ProtoBuf.Reflect.Service} service The service to get attributes for * @param {Object=} options Options to apply to these attributes * @return {Object} The attributes map */ exports.getProtobufServiceAttrs = function getProtobufServiceAttrs(service, options) { var prefix = '/' + fullyQualifiedName(service) + '/'; var binaryAsBase64, longsAsStrings; if (options) { binaryAsBase64 = options.binaryAsBase64; longsAsStrings = options.longsAsStrings; } /* This slightly awkward construction is used to make sure we only use lodash@3.10.1-compatible functions. A previous version used _.fromPairs, which would be cleaner, but was introduced in lodash version 4 */ return _.zipObject(_.map(service.children, function(method) { return _.camelCase(method.name); }), _.map(service.children, function(method) { return { originalName: method.name, path: prefix + method.name, requestStream: method.requestStream, responseStream: method.responseStream, requestType: method.resolvedRequestType, responseType: method.resolvedResponseType, requestSerialize: serializeCls(method.resolvedRequestType.build()), requestDeserialize: deserializeCls(method.resolvedRequestType.build(), options), responseSerialize: serializeCls(method.resolvedResponseType.build()), responseDeserialize: deserializeCls(method.resolvedResponseType.build(), options) }; })); }; var getProtobufServiceAttrs = exports.getProtobufServiceAttrs; /** * Load a gRPC object from an existing ProtoBuf.Reflect object. * @param {ProtoBuf.Reflect.Namespace} value The ProtoBuf object to load. * @param {Object=} options Options to apply to the loaded object * @return {Object} The resulting gRPC object */ exports.loadObject = function loadObject(value, options) { var result = {}; if (!value) { return value; } if (value.hasOwnProperty('ns')) { return loadObject(value.ns, options); } if (value.className === 'Namespace') { _.each(value.children, function(child) { result[child.name] = loadObject(child, options); }); return result; } else if (value.className === 'Service') { return client.makeClientConstructor(getProtobufServiceAttrs(value, options), options); } else if (value.className === 'Message' || value.className === 'Enum') { return value.build(); } else { return value; } }; /** * The primary purpose of this method is to distinguish between reflection * objects from different versions of ProtoBuf.js. This is just a heuristic, * checking for properties that are (currently) specific to this version of * ProtoBuf.js * @param {Object} obj The object to check * @return {boolean} Whether the object appears to be a Protobuf.js 5 * ReflectionObject */ exports.isProbablyProtobufJs5 = function isProbablyProtobufJs5(obj) { return _.isArray(obj.children) && (typeof obj.build === 'function'); }; grpc-1.3.2/src/node/src/protobuf_js_6_common.js000066400000000000000000000141471310511640000214400ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var _ = require('lodash'); var client = require('./client'); /** * Get a function that deserializes a specific type of protobuf. * @param {function()} cls The constructor of the message type to deserialize * @param {bool=} binaryAsBase64 Deserialize bytes fields as base64 strings * instead of Buffers. Defaults to false * @param {bool=} longsAsStrings Deserialize long values as strings instead of * objects. Defaults to true * @return {function(Buffer):cls} The deserialization function */ exports.deserializeCls = function deserializeCls(cls, options) { var conversion_options = { defaults: true, bytes: options.binaryAsBase64 ? String : Buffer, longs: options.longsAsStrings ? String : null, enums: options.enumsAsStrings ? String : null, oneofs: true }; /** * Deserialize a buffer to a message object * @param {Buffer} arg_buf The buffer to deserialize * @return {cls} The resulting object */ return function deserialize(arg_buf) { return cls.decode(arg_buf).toObject(conversion_options); }; }; var deserializeCls = exports.deserializeCls; /** * Get a function that serializes objects to a buffer by protobuf class. * @param {function()} Cls The constructor of the message type to serialize * @return {function(Cls):Buffer} The serialization function */ exports.serializeCls = function serializeCls(cls) { /** * Serialize an object to a Buffer * @param {Object} arg The object to serialize * @return {Buffer} The serialized object */ return function serialize(arg) { var message = cls.fromObject(arg); return cls.encode(message).finish(); }; }; var serializeCls = exports.serializeCls; /** * Get the fully qualified (dotted) name of a ProtoBuf.Reflect value. * @param {ProtoBuf.ReflectionObject} value The value to get the name of * @return {string} The fully qualified name of the value */ exports.fullyQualifiedName = function fullyQualifiedName(value) { if (value === null || value === undefined) { return ''; } var name = value.name; var parent_fqn = fullyQualifiedName(value.parent); if (parent_fqn !== '') { name = parent_fqn + '.' + name; } return name; }; var fullyQualifiedName = exports.fullyQualifiedName; /** * Return a map from method names to method attributes for the service. * @param {ProtoBuf.Service} service The service to get attributes for * @param {Object=} options Options to apply to these attributes * @return {Object} The attributes map */ exports.getProtobufServiceAttrs = function getProtobufServiceAttrs(service, options) { var prefix = '/' + fullyQualifiedName(service) + '/'; service.resolveAll(); return _.zipObject(_.map(service.methods, function(method) { return _.camelCase(method.name); }), _.map(service.methods, function(method) { return { originalName: method.name, path: prefix + method.name, requestStream: !!method.requestStream, responseStream: !!method.responseStream, requestType: method.resolvedRequestType, responseType: method.resolvedResponseType, requestSerialize: serializeCls(method.resolvedRequestType), requestDeserialize: deserializeCls(method.resolvedRequestType, options), responseSerialize: serializeCls(method.resolvedResponseType), responseDeserialize: deserializeCls(method.resolvedResponseType, options) }; })); }; var getProtobufServiceAttrs = exports.getProtobufServiceAttrs; exports.loadObject = function loadObject(value, options) { var result = {}; if (!value) { return value; } if (value.hasOwnProperty('methods')) { // It's a service object var service_attrs = getProtobufServiceAttrs(value, options); return client.makeClientConstructor(service_attrs); } if (value.hasOwnProperty('nested')) { // It's a namespace or root object _.each(value.nested, function(nested, name) { result[name] = loadObject(nested, options); }); return result; } // Otherwise, it's not something we need to change return value; }; /** * The primary purpose of this method is to distinguish between reflection * objects from different versions of ProtoBuf.js. This is just a heuristic, * checking for properties that are (currently) specific to this version of * ProtoBuf.js * @param {Object} obj The object to check * @return {boolean} Whether the object appears to be a Protobuf.js 6 * ReflectionObject */ exports.isProbablyProtobufJs6 = function isProbablyProtobufJs6(obj) { return (typeof obj.root === 'object') && (typeof obj.resolve === 'function'); }; grpc-1.3.2/src/node/src/server.js000066400000000000000000000623671310511640000166240ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** * 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'; var _ = require('lodash'); var grpc = require('./grpc_extension'); var common = require('./common'); var Metadata = require('./metadata'); var stream = require('stream'); var Readable = stream.Readable; var Writable = stream.Writable; var Duplex = stream.Duplex; var util = require('util'); var EventEmitter = require('events').EventEmitter; /** * Handle an error on a call by sending it as a status * @access private * @param {grpc.Call} call The call to send the error on * @param {Object} error The error object */ function handleError(call, error) { var statusMetadata = new Metadata(); var status = { code: grpc.status.UNKNOWN, details: 'Unknown Error' }; if (error.hasOwnProperty('message')) { status.details = error.message; } if (error.hasOwnProperty('code')) { status.code = error.code; if (error.hasOwnProperty('details')) { status.details = error.details; } } if (error.hasOwnProperty('metadata')) { statusMetadata = error.metadata; } status.metadata = statusMetadata._getCoreRepresentation(); var error_batch = {}; if (!call.metadataSent) { error_batch[grpc.opType.SEND_INITIAL_METADATA] = (new Metadata())._getCoreRepresentation(); } error_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = status; call.startBatch(error_batch, function(){}); } /** * Send a response to a unary or client streaming call. * @access private * @param {grpc.Call} call The call to respond on * @param {*} value The value to respond with * @param {function(*):Buffer=} serialize Serialization function for the * response * @param {Metadata=} metadata Optional trailing metadata to send with status * @param {number=} flags Flags for modifying how the message is sent. * Defaults to 0. */ function sendUnaryResponse(call, value, serialize, metadata, flags) { var end_batch = {}; var statusMetadata = new Metadata(); var status = { code: grpc.status.OK, details: 'OK' }; if (metadata) { statusMetadata = metadata; } var message; try { message = serialize(value); } catch (e) { e.code = grpc.status.INTERNAL; handleError(call, e); return; } status.metadata = statusMetadata._getCoreRepresentation(); if (!call.metadataSent) { end_batch[grpc.opType.SEND_INITIAL_METADATA] = (new Metadata())._getCoreRepresentation(); call.metadataSent = true; } message.grpcWriteFlags = flags; end_batch[grpc.opType.SEND_MESSAGE] = message; end_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = status; call.startBatch(end_batch, function (){}); } /** * Initialize a writable stream. This is used for both the writable and duplex * stream constructors. * @access private * @param {Writable} stream The stream to set up * @param {function(*):Buffer=} Serialization function for responses */ function setUpWritable(stream, serialize) { stream.finished = false; stream.status = { code : grpc.status.OK, details : 'OK', metadata : new Metadata() }; stream.serialize = common.wrapIgnoreNull(serialize); function sendStatus() { var batch = {}; if (!stream.call.metadataSent) { stream.call.metadataSent = true; batch[grpc.opType.SEND_INITIAL_METADATA] = (new Metadata())._getCoreRepresentation(); } if (stream.status.metadata) { stream.status.metadata = stream.status.metadata._getCoreRepresentation(); } batch[grpc.opType.SEND_STATUS_FROM_SERVER] = stream.status; stream.call.startBatch(batch, function(){}); } stream.on('finish', sendStatus); /** * Set the pending status to a given error status. If the error does not have * code or details properties, the code will be set to grpc.status.UNKNOWN * and the details will be set to 'Unknown Error'. * @param {Error} err The error object */ function setStatus(err) { var code = grpc.status.UNKNOWN; var details = 'Unknown Error'; var metadata = new Metadata(); if (err.hasOwnProperty('message')) { details = err.message; } if (err.hasOwnProperty('code')) { code = err.code; if (err.hasOwnProperty('details')) { details = err.details; } } if (err.hasOwnProperty('metadata')) { metadata = err.metadata; } stream.status = {code: code, details: details, metadata: metadata}; } /** * Terminate the call. This includes indicating that reads are done, draining * all pending writes, and sending the given error as a status * @param {Error} err The error object * @this GrpcServerStream */ function terminateCall(err) { // Drain readable data setStatus(err); stream.end(); } stream.on('error', terminateCall); /** * Override of Writable#end method that allows for sending metadata with a * success status. * @param {Metadata=} metadata Metadata to send with the status */ stream.end = function(metadata) { if (metadata) { stream.status.metadata = metadata; } Writable.prototype.end.call(this); }; } /** * Initialize a readable stream. This is used for both the readable and duplex * stream constructors. * @access private * @param {Readable} stream The stream to initialize * @param {function(Buffer):*=} deserialize Deserialization function for * incoming data. */ function setUpReadable(stream, deserialize) { stream.deserialize = common.wrapIgnoreNull(deserialize); stream.finished = false; stream.reading = false; stream.terminate = function() { stream.finished = true; stream.on('data', function() {}); }; stream.on('cancelled', function() { stream.terminate(); }); } util.inherits(ServerUnaryCall, EventEmitter); function ServerUnaryCall(call) { EventEmitter.call(this); this.call = call; } util.inherits(ServerWritableStream, Writable); /** * A stream that the server can write to. Used for calls that are streaming from * the server side. * @constructor * @param {grpc.Call} call The call object to send data with * @param {function(*):Buffer=} serialize Serialization function for writes */ function ServerWritableStream(call, serialize) { Writable.call(this, {objectMode: true}); this.call = call; this.finished = false; setUpWritable(this, serialize); } /** * Start writing a chunk of data. This is an implementation of a method required * for implementing stream.Writable. * @access private * @param {Buffer} chunk The chunk of data to write * @param {string} encoding Used to pass write flags * @param {function(Error=)} callback Callback to indicate that the write is * complete */ function _write(chunk, encoding, callback) { /* jshint validthis: true */ var batch = {}; var self = this; var message; try { message = this.serialize(chunk); } catch (e) { e.code = grpc.status.INTERNAL; callback(e); return; } if (!this.call.metadataSent) { batch[grpc.opType.SEND_INITIAL_METADATA] = (new Metadata())._getCoreRepresentation(); this.call.metadataSent = true; } if (_.isFinite(encoding)) { /* Attach the encoding if it is a finite number. This is the closest we * can get to checking that it is valid flags */ message.grpcWriteFlags = encoding; } batch[grpc.opType.SEND_MESSAGE] = message; this.call.startBatch(batch, function(err, value) { if (err) { self.emit('error', err); return; } callback(); }); } ServerWritableStream.prototype._write = _write; util.inherits(ServerReadableStream, Readable); /** * A stream that the server can read from. Used for calls that are streaming * from the client side. * @constructor * @param {grpc.Call} call The call object to read data with * @param {function(Buffer):*=} deserialize Deserialization function for reads */ function ServerReadableStream(call, deserialize) { Readable.call(this, {objectMode: true}); this.call = call; setUpReadable(this, deserialize); } /** * Start reading from the gRPC data source. This is an implementation of a * method required for implementing stream.Readable * @access private * @param {number} size Ignored */ function _read(size) { /* jshint validthis: true */ var self = this; /** * Callback to be called when a READ event is received. Pushes the data onto * the read queue and starts reading again if applicable * @param {grpc.Event} event READ event object */ function readCallback(err, event) { if (err) { self.terminate(); return; } if (self.finished) { self.push(null); return; } var data = event.read; var deserialized; try { deserialized = self.deserialize(data); } catch (e) { e.code = grpc.status.INTERNAL; self.emit('error', e); return; } if (self.push(deserialized) && data !== null) { var read_batch = {}; read_batch[grpc.opType.RECV_MESSAGE] = true; self.call.startBatch(read_batch, readCallback); } else { self.reading = false; } } if (self.finished) { self.push(null); } else { if (!self.reading) { self.reading = true; var batch = {}; batch[grpc.opType.RECV_MESSAGE] = true; self.call.startBatch(batch, readCallback); } } } ServerReadableStream.prototype._read = _read; util.inherits(ServerDuplexStream, Duplex); /** * A stream that the server can read from or write to. Used for calls with * duplex streaming. * @constructor * @param {grpc.Call} call Call object to proxy * @param {function(*):Buffer=} serialize Serialization function for requests * @param {function(Buffer):*=} deserialize Deserialization function for * responses */ function ServerDuplexStream(call, serialize, deserialize) { Duplex.call(this, {objectMode: true}); this.call = call; setUpWritable(this, serialize); setUpReadable(this, deserialize); } ServerDuplexStream.prototype._read = _read; ServerDuplexStream.prototype._write = _write; /** * Send the initial metadata for a writable stream. * @param {Metadata} responseMetadata Metadata to send */ function sendMetadata(responseMetadata) { /* jshint validthis: true */ var self = this; if (!this.call.metadataSent) { this.call.metadataSent = true; var batch = {}; batch[grpc.opType.SEND_INITIAL_METADATA] = responseMetadata._getCoreRepresentation(); this.call.startBatch(batch, function(err) { if (err) { self.emit('error', err); return; } }); } } ServerUnaryCall.prototype.sendMetadata = sendMetadata; ServerWritableStream.prototype.sendMetadata = sendMetadata; ServerReadableStream.prototype.sendMetadata = sendMetadata; ServerDuplexStream.prototype.sendMetadata = sendMetadata; /** * Get the endpoint this call/stream is connected to. * @return {string} The URI of the endpoint */ function getPeer() { /* jshint validthis: true */ return this.call.getPeer(); } ServerUnaryCall.prototype.getPeer = getPeer; ServerReadableStream.prototype.getPeer = getPeer; ServerWritableStream.prototype.getPeer = getPeer; ServerDuplexStream.prototype.getPeer = getPeer; /** * Wait for the client to close, then emit a cancelled event if the client * cancelled. */ function waitForCancel() { /* jshint validthis: true */ var self = this; var cancel_batch = {}; cancel_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true; self.call.startBatch(cancel_batch, function(err, result) { if (err) { self.emit('error', err); } if (result.cancelled) { self.cancelled = true; self.emit('cancelled'); } }); } ServerUnaryCall.prototype.waitForCancel = waitForCancel; ServerReadableStream.prototype.waitForCancel = waitForCancel; ServerWritableStream.prototype.waitForCancel = waitForCancel; ServerDuplexStream.prototype.waitForCancel = waitForCancel; /** * Fully handle a unary call * @access private * @param {grpc.Call} call The call to handle * @param {Object} handler Request handler object for the method that was called * @param {Metadata} metadata Metadata from the client */ function handleUnary(call, handler, metadata) { var emitter = new ServerUnaryCall(call); emitter.on('error', function(error) { handleError(call, error); }); emitter.metadata = metadata; emitter.waitForCancel(); var batch = {}; batch[grpc.opType.RECV_MESSAGE] = true; call.startBatch(batch, function(err, result) { if (err) { handleError(call, err); return; } try { emitter.request = handler.deserialize(result.read); } catch (e) { e.code = grpc.status.INTERNAL; handleError(call, e); return; } if (emitter.cancelled) { return; } handler.func(emitter, function sendUnaryData(err, value, trailer, flags) { if (err) { if (trailer) { err.metadata = trailer; } handleError(call, err); } else { sendUnaryResponse(call, value, handler.serialize, trailer, flags); } }); }); } /** * Fully handle a server streaming call * @access private * @param {grpc.Call} call The call to handle * @param {Object} handler Request handler object for the method that was called * @param {Metadata} metadata Metadata from the client */ function handleServerStreaming(call, handler, metadata) { var stream = new ServerWritableStream(call, handler.serialize); stream.waitForCancel(); stream.metadata = metadata; var batch = {}; batch[grpc.opType.RECV_MESSAGE] = true; call.startBatch(batch, function(err, result) { if (err) { stream.emit('error', err); return; } try { stream.request = handler.deserialize(result.read); } catch (e) { e.code = grpc.status.INTERNAL; stream.emit('error', e); return; } handler.func(stream); }); } /** * Fully handle a client streaming call * @access private * @param {grpc.Call} call The call to handle * @param {Object} handler Request handler object for the method that was called * @param {Metadata} metadata Metadata from the client */ function handleClientStreaming(call, handler, metadata) { var stream = new ServerReadableStream(call, handler.deserialize); stream.on('error', function(error) { handleError(call, error); }); stream.waitForCancel(); stream.metadata = metadata; handler.func(stream, function(err, value, trailer, flags) { stream.terminate(); if (err) { if (trailer) { err.metadata = trailer; } handleError(call, err); } else { sendUnaryResponse(call, value, handler.serialize, trailer, flags); } }); } /** * Fully handle a bidirectional streaming call * @access private * @param {grpc.Call} call The call to handle * @param {Object} handler Request handler object for the method that was called * @param {Metadata} metadata Metadata from the client */ function handleBidiStreaming(call, handler, metadata) { var stream = new ServerDuplexStream(call, handler.serialize, handler.deserialize); stream.waitForCancel(); stream.metadata = metadata; handler.func(stream); } var streamHandlers = { unary: handleUnary, server_stream: handleServerStreaming, client_stream: handleClientStreaming, bidi: handleBidiStreaming }; /** * Constructs a server object that stores request handlers and delegates * incoming requests to those handlers * @constructor * @param {Object=} options Options that should be passed to the internal server * implementation */ function Server(options) { this.handlers = {}; var handlers = this.handlers; var server = new grpc.Server(options); this._server = server; this.started = false; /** * Start the server and begin handling requests * @this Server */ this.start = function() { if (this.started) { throw new Error('Server is already running'); } this.started = true; server.start(); /** * Handles the SERVER_RPC_NEW event. If there is a handler associated with * the requested method, use that handler to respond to the request. Then * wait for the next request * @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: grpc.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); }; /** * 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 */ this.tryShutdown = function(callback) { 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. */ this.forceShutdown = function() { server.forceShutdown(); }; } /** * Registers a handler to handle the named method. Fails if there already is * a handler for the given method. Returns true on success * @param {string} name The name of the method that the provided function should * handle/respond to. * @param {function} handler Function that takes a stream of request values and * returns a stream of response values * @param {function(*):Buffer} serialize Serialization function for responses * @param {function(Buffer):*} deserialize Deserialization function for requests * @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 * set for that name. */ Server.prototype.register = function(name, handler, serialize, deserialize, type) { if (this.handlers.hasOwnProperty(name)) { return false; } this.handlers[name] = { func: handler, serialize: serialize, deserialize: deserialize, type: type }; return true; }; var unimplementedStatusResponse = { code: grpc.status.UNIMPLEMENTED, details: 'The server does not implement this method' }; var defaultHandler = { unary: function(call, callback) { callback(unimplementedStatusResponse); }, client_stream: function(call, callback) { callback(unimplementedStatusResponse); }, server_stream: function(call) { call.emit('error', unimplementedStatusResponse); }, bidi: function(call) { call.emit('error', unimplementedStatusResponse); } }; /** * Add a service to the server, with a corresponding implementation. If you are * generating this from a proto file, you should instead use * addProtoService. * @param {Object} service The service descriptor, as * {@link module:src/common.getProtobufServiceAttrs} returns * @param {Object} implementation Map of method names to * method implementation for the provided service. */ Server.prototype.addService = function(service, implementation) { if (!_.isObject(service) || !_.isObject(implementation)) { throw new Error('addService requires two objects as arguments'); } if (_.keys(service).length === 0) { throw new Error('Cannot add an empty service to a server'); } if (this.started) { throw new Error('Can\'t add a service to a started server.'); } var self = this; _.forOwn(service, function(attrs, name) { var method_type; if (attrs.requestStream) { if (attrs.responseStream) { method_type = 'bidi'; } else { method_type = 'client_stream'; } } else { if (attrs.responseStream) { method_type = 'server_stream'; } else { method_type = 'unary'; } } var impl; if (implementation[name] === undefined) { /* Handle the case where the method is passed with the name exactly as written in the proto file, instead of using JavaScript function naming style */ if (implementation[attrs.originalName] === undefined) { common.log(grpc.logVerbosity.ERROR, 'Method handler ' + name + ' for ' + attrs.path + ' expected but not provided'); impl = defaultHandler[method_type]; } else { impl = _.bind(implementation[attrs.originalName], implementation); } } else { impl = _.bind(implementation[name], implementation); } var serialize = attrs.responseSerialize; var deserialize = attrs.requestDeserialize; var register_success = self.register(attrs.path, impl, serialize, deserialize, method_type); if (!register_success) { throw new Error('Method handler for ' + attrs.path + ' already provided.'); } }); }; var logAddProtoServiceDeprecationOnce = _.once(function() { common.log(grpc.logVerbosity.INFO, 'Server#addProtoService is deprecated. Use addService instead'); }); /** * Add a proto service to the server, with a corresponding implementation * @deprecated Use grpc.load and Server#addService instead * @param {Protobuf.Reflect.Service} service The proto service descriptor * @param {Object} implementation Map of method names to * method implementation for the provided service. */ Server.prototype.addProtoService = function(service, implementation) { var options; var protobuf_js_5_common = require('./protobuf_js_5_common'); var protobuf_js_6_common = require('./protobuf_js_6_common'); logAddProtoServiceDeprecationOnce(); if (protobuf_js_5_common.isProbablyProtobufJs5(service)) { options = _.defaults(service.grpc_options, common.defaultGrpcOptions); this.addService( protobuf_js_5_common.getProtobufServiceAttrs(service, options), implementation); } else if (protobuf_js_6_common.isProbablyProtobufJs6(service)) { options = _.defaults(service.grpc_options, common.defaultGrpcOptions); this.addService( protobuf_js_6_common.getProtobufServiceAttrs(service, options), implementation); } else { // We assume that this is a service attributes object this.addService(service, implementation); } }; /** * Binds the server to the given port, with SSL enabled if creds is given * @param {string} port The port that the server should bind on, in the format * "address:port" * @param {ServerCredentials=} creds Server credential object to be used for * SSL. Pass an insecure credentials object for an insecure port. */ Server.prototype.bind = function(port, creds) { if (this.started) { throw new Error('Can\'t bind an already running server to an address'); } return this._server.addHttp2Port(port, creds); }; /** * @see module:src/server~Server */ exports.Server = Server; grpc-1.3.2/src/node/stress/000077500000000000000000000000001310511640000154765ustar00rootroot00000000000000grpc-1.3.2/src/node/stress/metrics_client.js000066400000000000000000000044611310511640000210450ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var grpc = require('../../..'); var proto = grpc.load(__dirname + '/../../proto/grpc/testing/metrics.proto'); var metrics = proto.grpc.testing; function main() { var parseArgs = require('minimist'); var argv = parseArgs(process.argv, { string: 'metrics_server_address', boolean: 'total_only' }); var client = new metrics.MetricsService(argv.metrics_server_address, grpc.credentials.createInsecure()); if (argv.total_only) { client.getGauge({name: 'qps'}, function(err, data) { console.log(data.name + ':', data.long_value); }); } else { var call = client.getAllGauges({}); call.on('data', function(data) { console.log(data.name + ':', data.long_value); }); } } main(); grpc-1.3.2/src/node/stress/metrics_server.js000066400000000000000000000056311310511640000210750ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var _ = require('lodash'); var grpc = require('../../..'); var proto = grpc.load(__dirname + '/../../proto/grpc/testing/metrics.proto'); var metrics = proto.grpc.testing; function getGauge(call, callback) { /* jshint validthis: true */ // Should be bound to a MetricsServer object var name = call.request.name; if (this.gauges.hasOwnProperty(name)) { callback(null, _.assign({name: name}, this.gauges[name]())); } else { callback({code: grpc.status.NOT_FOUND, details: 'No such gauge: ' + name}); } } function getAllGauges(call) { /* jshint validthis: true */ // Should be bound to a MetricsServer object _.each(this.gauges, function(getter, name) { call.write(_.assign({name: name}, getter())); }); call.end(); } function MetricsServer(port) { var server = new grpc.Server(); server.addService(metrics.MetricsService.service, { getGauge: _.bind(getGauge, this), getAllGauges: _.bind(getAllGauges, this) }); server.bind('localhost:' + port, grpc.ServerCredentials.createInsecure()); this.server = server; this.gauges = {}; } MetricsServer.prototype.start = function() { this.server.start(); } MetricsServer.prototype.registerGauge = function(name, getter) { this.gauges[name] = getter; }; MetricsServer.prototype.shutdown = function() { this.server.forceShutdown(); }; module.exports = MetricsServer; grpc-1.3.2/src/node/stress/stress_client.js000066400000000000000000000107301310511640000207160ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var _ = require('lodash'); var grpc = require('../../..'); var interop_client = require('../interop/interop_client'); var MetricsServer = require('./metrics_server'); var running; var metrics_server; var start_time; var query_count; function makeCall(client, test_cases) { if (!running) { return; } var test_case = test_cases[_.random(test_cases.length - 1)]; interop_client.test_cases[test_case].run(client, function() { query_count += 1; makeCall(client, test_cases); }); } function makeCalls(client, test_cases, parallel_calls_per_channel) { _.times(parallel_calls_per_channel, function() { makeCall(client, test_cases); }); } function getQps() { var diff = process.hrtime(start_time); var seconds = diff[0] + diff[1] / 1e9; return {long_value: query_count / seconds}; } function start(server_addresses, test_cases, channels_per_server, parallel_calls_per_channel, metrics_port) { running = true; /* Assuming that we are not calling unimplemented_method. The client class * used by empty_unary is (currently) the client class used by every interop * test except unimplemented_method */ var Client = interop_client.test_cases.empty_unary.Client; /* Make channels_per_server clients connecting to each server address */ var channels = _.flatten(_.times( channels_per_server, _.partial(_.map, server_addresses, function(address) { return new Client(address, grpc.credentials.createInsecure()); }))); metrics_server = new MetricsServer(metrics_port); metrics_server.registerGauge('qps', getQps); start_time = process.hrtime(); query_count = 0; _.each(channels, _.partial(makeCalls, _, test_cases, parallel_calls_per_channel)); metrics_server.start(); } function stop() { running = false; metrics_server.shutdown(); console.log('QPS: ' + getQps().long_value); } function main() { var parseArgs = require('minimist'); var argv = parseArgs(process.argv, { string: ['server_addresses', 'test_cases', 'metrics_port'], default: {'server_addresses': 'localhost:8080', 'test_duration_secs': -1, 'num_channels_per_server': 1, 'num_stubs_per_channel': 1, 'metrics_port': '8081'} }); var server_addresses = argv.server_addresses.split(','); /* Generate an array of test cases, where the number of instances of each name * corresponds to the number given in the argument. * e.g. 'empty_unary:1,large_unary:2' => * ['empty_unary', 'large_unary', 'large_unary'] */ var test_cases = _.flatten(_.map(argv.test_cases.split(','), function(value) { var split = value.split(':'); return _.times(split[1], _.constant(split[0])); })); start(server_addresses, test_cases, argv.num_channels_per_server, argv.num_stubs_per_channel, argv.metrics_port); if (argv.test_duration_secs > -1) { setTimeout(stop, argv.test_duration_secs * 1000); } } main(); grpc-1.3.2/src/node/test/000077500000000000000000000000001310511640000151325ustar00rootroot00000000000000grpc-1.3.2/src/node/test/async_test.js000066400000000000000000000061501310511640000176460ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var assert = require('assert'); var grpc = require('..'); var math = grpc.load(__dirname + '/../../proto/math/math.proto').math; /** * Client to use to make requests to a running server. */ var math_client; /** * Server to test against */ var getServer = require('./math/math_server.js'); var server = getServer(); describe('Async functionality', function() { before(function(done) { var port_num = server.bind('0.0.0.0:0', grpc.ServerCredentials.createInsecure()); server.start(); math_client = new math.Math('localhost:' + port_num, grpc.credentials.createInsecure()); done(); }); after(function() { grpc.closeClient(math_client); server.forceShutdown(); }); it('should not hang', function(done) { var chunkCount=0; var call = math_client.sum(function handleSumResult(err, value) { assert.ifError(err); assert.equal(value.num, chunkCount); }); var path = require('path'); var fs = require('fs'); var fileToRead = path.join(__dirname, 'numbers.txt'); var readStream = fs.createReadStream(fileToRead); readStream.once('readable', function () { readStream.on('data', function (chunk) { call.write({'num': 1}); chunkCount += 1; }); readStream.on('end', function () { call.end(); }); readStream.on('error', function (error) { }); }); call.on('status', function checkStatus(status) { assert.strictEqual(status.code, grpc.status.OK); done(); }); }); }); grpc-1.3.2/src/node/test/call_test.js000066400000000000000000000220511310511640000174420ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var assert = require('assert'); var grpc = require('../src/grpc_extension'); /** * Helper function to return an absolute deadline given a relative timeout in * seconds. * @param {number} timeout_secs The number of seconds to wait before timing out * @return {Date} A date timeout_secs in the future */ function getDeadline(timeout_secs) { var deadline = new Date(); deadline.setSeconds(deadline.getSeconds() + timeout_secs); return deadline; } var insecureCreds = grpc.ChannelCredentials.createInsecure(); describe('call', function() { var channel; var server; before(function() { server = new grpc.Server(); var port = server.addHttp2Port('localhost:0', grpc.ServerCredentials.createInsecure()); server.start(); channel = new grpc.Channel('localhost:' + port, insecureCreds); }); after(function() { server.forceShutdown(); }); describe('constructor', function() { it('should reject anything less than 3 arguments', function() { assert.throws(function() { new grpc.Call(); }, TypeError); assert.throws(function() { new grpc.Call(channel); }, TypeError); assert.throws(function() { new grpc.Call(channel, 'method'); }, TypeError); }); it('should succeed with a Channel, a string, and a date or number', function() { assert.doesNotThrow(function() { new grpc.Call(channel, 'method', new Date()); }); assert.doesNotThrow(function() { new grpc.Call(channel, 'method', 0); }); }); it('should accept an optional fourth string parameter', function() { assert.doesNotThrow(function() { new grpc.Call(channel, 'method', new Date(), 'host_override'); }); }); it('should fail with a closed channel', function() { var local_channel = new grpc.Channel('hostname', insecureCreds); local_channel.close(); assert.throws(function() { new grpc.Call(channel, 'method'); }); }); it('should fail with other types', function() { assert.throws(function() { new grpc.Call({}, 'method', 0); }, TypeError); assert.throws(function() { new grpc.Call(channel, null, 0); }, TypeError); assert.throws(function() { new grpc.Call(channel, 'method', 'now'); }, TypeError); }); it('should succeed without the new keyword', function() { assert.doesNotThrow(function() { var call = grpc.Call(channel, 'method', new Date()); assert(call instanceof grpc.Call); }); }); }); describe('deadline', function() { it('should time out immediately with negative deadline', function(done) { var call = new grpc.Call(channel, 'method', -Infinity); var batch = {}; batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; call.startBatch(batch, function(err, response) { assert.strictEqual(response.status.code, grpc.status.DEADLINE_EXCEEDED); done(); }); }); }); describe('startBatch', function() { it('should fail without an object and a function', function() { var call = new grpc.Call(channel, 'method', getDeadline(1)); assert.throws(function() { call.startBatch(); }); assert.throws(function() { call.startBatch({}); }); assert.throws(function() { call.startBatch(null, function(){}); }); }); it('should succeed with an empty object', function(done) { var call = new grpc.Call(channel, 'method', getDeadline(1)); assert.doesNotThrow(function() { call.startBatch({}, function(err) { assert.ifError(err); done(); }); }); }); }); describe('startBatch with metadata', function() { it('should succeed with a map of strings to string arrays', function(done) { var call = new grpc.Call(channel, 'method', getDeadline(1)); assert.doesNotThrow(function() { var batch = {}; batch[grpc.opType.SEND_INITIAL_METADATA] = {'key1': ['value1'], 'key2': ['value2']}; call.startBatch(batch, function(err, resp) { assert.ifError(err); assert.deepEqual(resp, {'send_metadata': true}); done(); }); }); }); it('should succeed with a map of strings to buffer arrays', function(done) { var call = new grpc.Call(channel, 'method', getDeadline(1)); assert.doesNotThrow(function() { var batch = {}; batch[grpc.opType.SEND_INITIAL_METADATA] = { 'key1-bin': [new Buffer('value1')], 'key2-bin': [new Buffer('value2')] }; call.startBatch(batch, function(err, resp) { assert.ifError(err); assert.deepEqual(resp, {'send_metadata': true}); done(); }); }); }); it('should fail with other parameter types', function() { var call = new grpc.Call(channel, 'method', getDeadline(1)); assert.throws(function() { var batch = {}; batch[grpc.opType.SEND_INITIAL_METADATA] = undefined; call.startBatch(batch, function(){}); }); assert.throws(function() { var batch = {}; batch[grpc.opType.SEND_INITIAL_METADATA] = null; call.startBatch(batch, function(){}); }, TypeError); assert.throws(function() { var batch = {}; batch[grpc.opType.SEND_INITIAL_METADATA] = 'value'; call.startBatch(batch, function(){}); }, TypeError); assert.throws(function() { var batch = {}; batch[grpc.opType.SEND_INITIAL_METADATA] = 5; call.startBatch(batch, function(){}); }, TypeError); }); }); describe('cancel', function() { it('should succeed', function() { var call = new grpc.Call(channel, 'method', getDeadline(1)); assert.doesNotThrow(function() { call.cancel(); }); }); }); describe('cancelWithStatus', function() { it('should reject anything other than an integer and a string', function() { assert.doesNotThrow(function() { var call = new grpc.Call(channel, 'method', getDeadline(1)); call.cancelWithStatus(1, 'details'); }); assert.throws(function() { var call = new grpc.Call(channel, 'method', getDeadline(1)); call.cancelWithStatus(); }); assert.throws(function() { var call = new grpc.Call(channel, 'method', getDeadline(1)); call.cancelWithStatus(''); }); assert.throws(function() { var call = new grpc.Call(channel, 'method', getDeadline(1)); call.cancelWithStatus(5, {}); }); }); it('should reject the OK status code', function() { assert.throws(function() { var call = new grpc.Call(channel, 'method', getDeadline(1)); call.cancelWithStatus(0, 'details'); }); }); it('should result in the call ending with a status', function(done) { var call = new grpc.Call(channel, 'method', getDeadline(1)); var batch = {}; batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; call.startBatch(batch, function(err, response) { assert.strictEqual(response.status.code, 5); assert.strictEqual(response.status.details, 'details'); done(); }); call.cancelWithStatus(5, 'details'); }); }); describe('getPeer', function() { it('should return a string', function() { var call = new grpc.Call(channel, 'method', getDeadline(1)); assert.strictEqual(typeof call.getPeer(), 'string'); }); }); }); grpc-1.3.2/src/node/test/channel_test.js000066400000000000000000000155571310511640000201540ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var assert = require('assert'); var grpc = require('../src/grpc_extension'); /** * This is used for testing functions with multiple asynchronous calls that * can happen in different orders. This should be passed the number of async * function invocations that can occur last, and each of those should call this * function's return value * @param {function()} done The function that should be called when a test is * complete. * @param {number} count The number of calls to the resulting function if the * test passes. * @return {function()} The function that should be called at the end of each * sequence of asynchronous functions. */ function multiDone(done, count) { return function() { count -= 1; if (count <= 0) { done(); } }; } var insecureCreds = grpc.ChannelCredentials.createInsecure(); describe('channel', function() { describe('constructor', function() { it('should require a string for the first argument', function() { assert.doesNotThrow(function() { new grpc.Channel('hostname', insecureCreds); }); assert.throws(function() { new grpc.Channel(); }, TypeError); assert.throws(function() { new grpc.Channel(5); }); }); it('should require a credential for the second argument', function() { assert.doesNotThrow(function() { new grpc.Channel('hostname', insecureCreds); }); assert.throws(function() { new grpc.Channel('hostname', 5); }); assert.throws(function() { new grpc.Channel('hostname'); }); }); it('should accept an object for the third argument', function() { assert.doesNotThrow(function() { new grpc.Channel('hostname', insecureCreds, {}); }); assert.throws(function() { new grpc.Channel('hostname', insecureCreds, 'abc'); }); }); it('should only accept objects with string or int values', function() { assert.doesNotThrow(function() { new grpc.Channel('hostname', insecureCreds,{'key' : 'value'}); }); assert.doesNotThrow(function() { new grpc.Channel('hostname', insecureCreds, {'key' : 5}); }); assert.throws(function() { new grpc.Channel('hostname', insecureCreds, {'key' : null}); }); assert.throws(function() { new grpc.Channel('hostname', insecureCreds, {'key' : new Date()}); }); }); it('should succeed without the new keyword', function() { assert.doesNotThrow(function() { var channel = grpc.Channel('hostname', insecureCreds); assert(channel instanceof grpc.Channel); }); }); }); describe('close', function() { var channel; beforeEach(function() { channel = new grpc.Channel('hostname', insecureCreds, {}); }); it('should succeed silently', function() { assert.doesNotThrow(function() { channel.close(); }); }); it('should be idempotent', function() { assert.doesNotThrow(function() { channel.close(); channel.close(); }); }); }); describe('getTarget', function() { var channel; beforeEach(function() { channel = new grpc.Channel('hostname', insecureCreds, {}); }); it('should return a string', function() { assert.strictEqual(typeof channel.getTarget(), 'string'); }); }); describe('getConnectivityState', function() { var channel; beforeEach(function() { channel = new grpc.Channel('hostname', insecureCreds, {}); }); it('should return IDLE for a new channel', function() { assert.strictEqual(channel.getConnectivityState(), grpc.connectivityState.IDLE); }); }); describe('watchConnectivityState', function() { var channel; beforeEach(function() { channel = new grpc.Channel('localhost', insecureCreds, {}); }); afterEach(function() { channel.close(); }); it('should time out if called alone', function(done) { var old_state = channel.getConnectivityState(); var deadline = new Date(); deadline.setSeconds(deadline.getSeconds() + 1); channel.watchConnectivityState(old_state, deadline, function(err, value) { assert(err); done(); }); }); it('should complete if a connection attempt is forced', function(done) { var old_state = channel.getConnectivityState(); var deadline = new Date(); deadline.setSeconds(deadline.getSeconds() + 1); channel.watchConnectivityState(old_state, deadline, function(err, value) { assert.ifError(err); assert.notEqual(value.new_state, old_state); done(); }); channel.getConnectivityState(true); }); it('should complete twice if called twice', function(done) { done = multiDone(done, 2); var old_state = channel.getConnectivityState(); var deadline = new Date(); deadline.setSeconds(deadline.getSeconds() + 1); channel.watchConnectivityState(old_state, deadline, function(err, value) { assert.ifError(err); assert.notEqual(value.new_state, old_state); done(); }); channel.watchConnectivityState(old_state, deadline, function(err, value) { assert.ifError(err); assert.notEqual(value.new_state, old_state); done(); }); channel.getConnectivityState(true); }); }); }); grpc-1.3.2/src/node/test/common_test.js000066400000000000000000000227341310511640000200270ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var assert = require('assert'); var _ = require('lodash'); var common = require('../src/common'); var protobuf_js_5_common = require('../src/protobuf_js_5_common'); var serializeCls = protobuf_js_5_common.serializeCls; var deserializeCls = protobuf_js_5_common.deserializeCls; var ProtoBuf = require('protobufjs'); var messages_proto = ProtoBuf.loadProtoFile( __dirname + '/test_messages.proto').build(); var default_options = common.defaultGrpcOptions; describe('Proto message long int serialize and deserialize', function() { var longSerialize = serializeCls(messages_proto.LongValues); var longDeserialize = deserializeCls(messages_proto.LongValues, default_options); var pos_value = '314159265358979'; var neg_value = '-27182818284590'; it('should preserve positive int64 values', function() { var serialized = longSerialize({int_64: pos_value}); assert.strictEqual(longDeserialize(serialized).int_64.toString(), pos_value); }); it('should preserve negative int64 values', function() { var serialized = longSerialize({int_64: neg_value}); assert.strictEqual(longDeserialize(serialized).int_64.toString(), neg_value); }); it('should preserve uint64 values', function() { var serialized = longSerialize({uint_64: pos_value}); assert.strictEqual(longDeserialize(serialized).uint_64.toString(), pos_value); }); it('should preserve positive sint64 values', function() { var serialized = longSerialize({sint_64: pos_value}); assert.strictEqual(longDeserialize(serialized).sint_64.toString(), pos_value); }); it('should preserve negative sint64 values', function() { var serialized = longSerialize({sint_64: neg_value}); assert.strictEqual(longDeserialize(serialized).sint_64.toString(), neg_value); }); it('should preserve fixed64 values', function() { var serialized = longSerialize({fixed_64: pos_value}); assert.strictEqual(longDeserialize(serialized).fixed_64.toString(), pos_value); }); it('should preserve positive sfixed64 values', function() { var serialized = longSerialize({sfixed_64: pos_value}); assert.strictEqual(longDeserialize(serialized).sfixed_64.toString(), pos_value); }); it('should preserve negative sfixed64 values', function() { var serialized = longSerialize({sfixed_64: neg_value}); assert.strictEqual(longDeserialize(serialized).sfixed_64.toString(), neg_value); }); it('should deserialize as a number with the right option set', function() { var num_options = _.defaults({longsAsStrings: false}, default_options); var longNumDeserialize = deserializeCls(messages_proto.LongValues, num_options); var serialized = longSerialize({int_64: pos_value}); console.log(longDeserialize(serialized)); assert.strictEqual(typeof longDeserialize(serialized).int_64, 'string'); /* With the longsAsStrings option disabled, long values are represented as * objects with 3 keys: low, high, and unsigned */ assert.strictEqual(typeof longNumDeserialize(serialized).int_64, 'object'); }); }); describe('Proto message bytes serialize and deserialize', function() { var sequenceSerialize = serializeCls(messages_proto.SequenceValues); var sequenceDeserialize = deserializeCls( messages_proto.SequenceValues, default_options); var b64_options = _.defaults({binaryAsBase64: true}, default_options); var sequenceBase64Deserialize = deserializeCls( messages_proto.SequenceValues, b64_options); var buffer_val = new Buffer([0x69, 0xb7]); var base64_val = 'abc='; it('should preserve a buffer', function() { var serialized = sequenceSerialize({bytes_field: buffer_val}); var deserialized = sequenceDeserialize(serialized); assert.strictEqual(deserialized.bytes_field.compare(buffer_val), 0); }); it('should accept base64 encoded strings', function() { var serialized = sequenceSerialize({bytes_field: base64_val}); var deserialized = sequenceDeserialize(serialized); assert.strictEqual(deserialized.bytes_field.compare(buffer_val), 0); }); it('should output base64 encoded strings with an option set', function() { var serialized = sequenceSerialize({bytes_field: base64_val}); var deserialized = sequenceBase64Deserialize(serialized); assert.strictEqual(deserialized.bytes_field, base64_val); }); it('should serialize a repeated field as packed by default', function() { var expected_serialize = new Buffer([0x12, 0x01, 0x0a]); var serialized = sequenceSerialize({repeated_field: [10]}); assert.strictEqual(expected_serialize.compare(serialized), 0); }); // This tests a bug that was fixed in Protobuf.js 6 it.skip('should deserialize packed or unpacked repeated', function() { var expectedDeserialize = { bytes_field: new Buffer(''), repeated_field: [10] }; var packedSerialized = new Buffer([0x12, 0x01, 0x0a]); var unpackedSerialized = new Buffer([0x10, 0x0a]); var packedDeserialized; var unpackedDeserialized; assert.doesNotThrow(function() { packedDeserialized = sequenceDeserialize(packedSerialized); }); assert.doesNotThrow(function() { unpackedDeserialized = sequenceDeserialize(unpackedSerialized); }); assert.deepEqual(packedDeserialized, expectedDeserialize); assert.deepEqual(unpackedDeserialized, expectedDeserialize); }); }); // This tests a bug that was fixed in Protobuf.js 6 describe.skip('Proto message oneof serialize and deserialize', function() { var oneofSerialize = serializeCls(messages_proto.OneOfValues); var oneofDeserialize = deserializeCls( messages_proto.OneOfValues, default_options); it('Should have idempotent round trips', function() { var test_message = {oneof_choice: 'int_choice', int_choice: 5}; var serialized1 = oneofSerialize(test_message); var deserialized1 = oneofDeserialize(serialized1); assert.equal(deserialized1.int_choice, 5); var serialized2 = oneofSerialize(deserialized1); var deserialized2 = oneofDeserialize(serialized2); assert.deepEqual(deserialized1, deserialized2); }); it('Should emit a property indicating which field was chosen', function() { var test_message1 = {oneof_choice: 'int_choice', int_choice: 5}; var serialized1 = oneofSerialize(test_message1); var deserialized1 = oneofDeserialize(serialized1); assert.equal(deserialized1.oneof_choice, 'int_choice'); var test_message2 = {oneof_choice: 'string_choice', string_choice: 'abc'}; var serialized2 = oneofSerialize(test_message2); var deserialized2 = oneofDeserialize(serialized2); assert.equal(deserialized2.oneof_choice, 'string_choice'); }); }); describe('Proto message enum serialize and deserialize', function() { var enumSerialize = serializeCls(messages_proto.EnumValues); var enumDeserialize = deserializeCls( messages_proto.EnumValues, default_options); var enumIntOptions = _.defaults({enumsAsStrings: false}, default_options); var enumIntDeserialize = deserializeCls( messages_proto.EnumValues, enumIntOptions); it('Should accept both names and numbers', function() { var nameSerialized = enumSerialize({enum_value: 'ONE'}); var numberSerialized = enumSerialize({enum_value: 1}); assert.strictEqual(messages_proto.TestEnum.ONE, 1); assert.deepEqual(enumDeserialize(nameSerialized), enumDeserialize(numberSerialized)); }); // This tests a bug that was fixed in Protobuf.js 6 it.skip('Should correctly handle the enumsAsStrings option', function() { var serialized = enumSerialize({enum_value: 'TWO'}); var nameDeserialized = enumDeserialize(serialized); var numberDeserialized = enumIntDeserialize(serialized); assert.deepEqual(nameDeserialized, {enum_value: 'TWO'}); assert.deepEqual(numberDeserialized, {enum_value: 2}); }); }); grpc-1.3.2/src/node/test/constant_test.js000066400000000000000000000073241310511640000203660ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var assert = require('assert'); var grpc = require('../src/grpc_extension'); /** * List of all status names * @const * @type {Array.} */ var statusNames = [ 'OK', 'CANCELLED', 'UNKNOWN', 'INVALID_ARGUMENT', 'DEADLINE_EXCEEDED', 'NOT_FOUND', 'ALREADY_EXISTS', 'PERMISSION_DENIED', 'UNAUTHENTICATED', 'RESOURCE_EXHAUSTED', 'FAILED_PRECONDITION', 'ABORTED', 'OUT_OF_RANGE', 'UNIMPLEMENTED', 'INTERNAL', 'UNAVAILABLE', 'DATA_LOSS' ]; /** * List of all call error names * @const * @type {Array.} */ var callErrorNames = [ 'OK', 'ERROR', 'NOT_ON_SERVER', 'NOT_ON_CLIENT', 'ALREADY_INVOKED', 'NOT_INVOKED', 'ALREADY_FINISHED', 'TOO_MANY_OPERATIONS', 'INVALID_FLAGS' ]; /** * List of all propagate flag names * @const * @type {Array.} */ var propagateFlagNames = [ 'DEADLINE', 'CENSUS_STATS_CONTEXT', 'CENSUS_TRACING_CONTEXT', 'CANCELLATION', 'DEFAULTS' ]; /* * List of all connectivity state names * @const * @type {Array.} */ var connectivityStateNames = [ 'IDLE', 'CONNECTING', 'READY', 'TRANSIENT_FAILURE', 'FATAL_FAILURE' ]; describe('constants', function() { it('should have all of the status constants', function() { for (var i = 0; i < statusNames.length; i++) { assert(grpc.status.hasOwnProperty(statusNames[i]), 'status missing: ' + statusNames[i]); } }); it('should have all of the call errors', function() { for (var i = 0; i < callErrorNames.length; i++) { assert(grpc.callError.hasOwnProperty(callErrorNames[i]), 'call error missing: ' + callErrorNames[i]); } }); it('should have all of the propagate flags', function() { for (var i = 0; i < propagateFlagNames.length; i++) { assert(grpc.propagate.hasOwnProperty(propagateFlagNames[i]), 'call error missing: ' + propagateFlagNames[i]); } }); it('should have all of the connectivity states', function() { for (var i = 0; i < connectivityStateNames.length; i++) { assert(grpc.connectivityState.hasOwnProperty(connectivityStateNames[i]), 'connectivity status missing: ' + connectivityStateNames[i]); } }); }); grpc-1.3.2/src/node/test/credentials_test.js000066400000000000000000000421661310511640000210350ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var assert = require('assert'); var fs = require('fs'); var path = require('path'); var grpc = require('..'); /** * This is used for testing functions with multiple asynchronous calls that * can happen in different orders. This should be passed the number of async * function invocations that can occur last, and each of those should call this * function's return value * @param {function()} done The function that should be called when a test is * complete. * @param {number} count The number of calls to the resulting function if the * test passes. * @return {function()} The function that should be called at the end of each * sequence of asynchronous functions. */ function multiDone(done, count) { return function() { count -= 1; if (count <= 0) { done(); } }; } var fakeSuccessfulGoogleCredentials = { getRequestMetadata: function(service_url, callback) { setTimeout(function() { callback(null, {Authorization: 'success'}); }, 0); } }; var fakeFailingGoogleCredentials = { getRequestMetadata: function(service_url, callback) { setTimeout(function() { // Google credentials currently adds string error codes to auth errors var error = new Error('Authentication failure'); error.code = 'ENOENT'; callback(error); }, 0); } }; var key_data, pem_data, ca_data; before(function() { var key_path = path.join(__dirname, './data/server1.key'); var pem_path = path.join(__dirname, './data/server1.pem'); var ca_path = path.join(__dirname, '../test/data/ca.pem'); key_data = fs.readFileSync(key_path); pem_data = fs.readFileSync(pem_path); ca_data = fs.readFileSync(ca_path); }); describe('channel credentials', function() { describe('#createSsl', function() { it('works with no arguments', function() { var creds; assert.doesNotThrow(function() { creds = grpc.credentials.createSsl(); }); assert.notEqual(creds, null); }); it('works with just one Buffer argument', function() { var creds; assert.doesNotThrow(function() { creds = grpc.credentials.createSsl(ca_data); }); assert.notEqual(creds, null); }); it('works with 3 Buffer arguments', function() { var creds; assert.doesNotThrow(function() { creds = grpc.credentials.createSsl(ca_data, key_data, pem_data); }); assert.notEqual(creds, null); }); it('works if the first argument is null', function() { var creds; assert.doesNotThrow(function() { creds = grpc.credentials.createSsl(null, key_data, pem_data); }); assert.notEqual(creds, null); }); it('fails if the first argument is a non-Buffer value', function() { assert.throws(function() { grpc.credentials.createSsl('test'); }, TypeError); }); it('fails if the second argument is a non-Buffer value', function() { assert.throws(function() { grpc.credentials.createSsl(null, 'test', pem_data); }, TypeError); }); it('fails if the third argument is a non-Buffer value', function() { assert.throws(function() { grpc.credentials.createSsl(null, key_data, 'test'); }, TypeError); }); it('fails if only 1 of the last 2 arguments is provided', function() { assert.throws(function() { grpc.credentials.createSsl(null, key_data); }); assert.throws(function() { grpc.credentials.createSsl(null, null, pem_data); }); }); }); }); describe('server credentials', function() { describe('#createSsl', function() { it('accepts a buffer and array as the first 2 arguments', function() { var creds; assert.doesNotThrow(function() { creds = grpc.ServerCredentials.createSsl(ca_data, []); }); assert.notEqual(creds, null); }); it('accepts a boolean as the third argument', function() { var creds; assert.doesNotThrow(function() { creds = grpc.ServerCredentials.createSsl(ca_data, [], true); }); assert.notEqual(creds, null); }); it('accepts an object with two buffers in the second argument', function() { var creds; assert.doesNotThrow(function() { creds = grpc.ServerCredentials.createSsl(null, [{private_key: key_data, cert_chain: pem_data}]); }); assert.notEqual(creds, null); }); it('accepts multiple objects in the second argument', function() { var creds; assert.doesNotThrow(function() { creds = grpc.ServerCredentials.createSsl(null, [{private_key: key_data, cert_chain: pem_data}, {private_key: key_data, cert_chain: pem_data}]); }); assert.notEqual(creds, null); }); it('fails if the second argument is not an Array', function() { assert.throws(function() { grpc.ServerCredentials.createSsl(ca_data, 'test'); }, TypeError); }); it('fails if the first argument is a non-Buffer value', function() { assert.throws(function() { grpc.ServerCredentials.createSsl('test', []); }, TypeError); }); it('fails if the third argument is a non-boolean value', function() { assert.throws(function() { grpc.ServerCredentials.createSsl(ca_data, [], 'test'); }, TypeError); }); it('fails if the array elements are not objects', function() { assert.throws(function() { grpc.ServerCredentials.createSsl(ca_data, 'test'); }, TypeError); }); it('fails if the object does not have a Buffer private_key', function() { assert.throws(function() { grpc.ServerCredentials.createSsl(null, [{private_key: 'test', cert_chain: pem_data}]); }, TypeError); }); it('fails if the object does not have a Buffer cert_chain', function() { assert.throws(function() { grpc.ServerCredentials.createSsl(null, [{private_key: key_data, cert_chain: 'test'}]); }, TypeError); }); }); }); describe('client credentials', function() { var Client; var server; var port; var client_ssl_creds; var client_options = {}; before(function() { var proto = grpc.load(__dirname + '/test_service.proto'); server = new grpc.Server(); server.addService(proto.TestService.service, { unary: function(call, cb) { call.sendMetadata(call.metadata); cb(null, {}); }, clientStream: function(stream, cb){ stream.on('data', function(data) {}); stream.on('end', function() { stream.sendMetadata(stream.metadata); cb(null, {}); }); }, serverStream: function(stream) { stream.sendMetadata(stream.metadata); stream.end(); }, bidiStream: function(stream) { stream.on('data', function(data) {}); stream.on('end', function() { stream.sendMetadata(stream.metadata); stream.end(); }); } }); var creds = grpc.ServerCredentials.createSsl(null, [{private_key: key_data, cert_chain: pem_data}]); port = server.bind('localhost:0', creds); server.start(); Client = proto.TestService; client_ssl_creds = grpc.credentials.createSsl(ca_data); var host_override = 'foo.test.google.fr'; client_options['grpc.ssl_target_name_override'] = host_override; client_options['grpc.default_authority'] = host_override; }); after(function() { server.forceShutdown(); }); it('Should accept SSL creds for a client', function(done) { var client = new Client('localhost:' + port, client_ssl_creds, client_options); client.unary({}, function(err, data) { assert.ifError(err); done(); }); }); it('Should update metadata with SSL creds', function(done) { var metadataUpdater = function(service_url, callback) { var metadata = new grpc.Metadata(); metadata.set('plugin_key', 'plugin_value'); callback(null, metadata); }; var creds = grpc.credentials.createFromMetadataGenerator(metadataUpdater); var combined_creds = grpc.credentials.combineChannelCredentials( client_ssl_creds, creds); var client = new Client('localhost:' + port, combined_creds, client_options); var call = client.unary({}, function(err, data) { assert.ifError(err); }); call.on('metadata', function(metadata) { assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']); done(); }); }); it('Should update metadata for two simultaneous calls', function(done) { done = multiDone(done, 2); var metadataUpdater = function(service_url, callback) { var metadata = new grpc.Metadata(); metadata.set('plugin_key', 'plugin_value'); callback(null, metadata); }; var creds = grpc.credentials.createFromMetadataGenerator(metadataUpdater); var combined_creds = grpc.credentials.combineChannelCredentials( client_ssl_creds, creds); var client = new Client('localhost:' + port, combined_creds, client_options); var call = client.unary({}, function(err, data) { assert.ifError(err); }); call.on('metadata', function(metadata) { assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']); done(); }); var call2 = client.unary({}, function(err, data) { assert.ifError(err); }); call2.on('metadata', function(metadata) { assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']); done(); }); }); it('should propagate errors that the updater emits', function(done) { var metadataUpdater = function(service_url, callback) { var error = new Error('Authentication error'); error.code = grpc.status.UNAUTHENTICATED; callback(error); }; var creds = grpc.credentials.createFromMetadataGenerator(metadataUpdater); var combined_creds = grpc.credentials.combineChannelCredentials( client_ssl_creds, creds); var client = new Client('localhost:' + port, combined_creds, client_options); client.unary({}, function(err, data) { assert(err); assert.strictEqual(err.message, 'Authentication error'); assert.strictEqual(err.code, grpc.status.UNAUTHENTICATED); done(); }); }); it('should successfully wrap a Google credential', function(done) { var creds = grpc.credentials.createFromGoogleCredential( fakeSuccessfulGoogleCredentials); var combined_creds = grpc.credentials.combineChannelCredentials( client_ssl_creds, creds); var client = new Client('localhost:' + port, combined_creds, client_options); var call = client.unary({}, function(err, data) { assert.ifError(err); }); call.on('metadata', function(metadata) { assert.deepEqual(metadata.get('authorization'), ['success']); done(); }); }); it('Should not add metadata with just SSL credentials', function(done) { // Tests idempotency of credentials composition var metadataUpdater = function(service_url, callback) { var metadata = new grpc.Metadata(); metadata.set('plugin_key', 'plugin_value'); callback(null, metadata); }; var creds = grpc.credentials.createFromMetadataGenerator(metadataUpdater); grpc.credentials.combineChannelCredentials(client_ssl_creds, creds); var client = new Client('localhost:' + port, client_ssl_creds, client_options); var call = client.unary({}, function(err, data) { assert.ifError(err); }); call.on('metadata', function(metadata) { assert.deepEqual(metadata.get('plugin_key'), []); done(); }); }); it('should get an error from a Google credential', function(done) { var creds = grpc.credentials.createFromGoogleCredential( fakeFailingGoogleCredentials); var combined_creds = grpc.credentials.combineChannelCredentials( client_ssl_creds, creds); var client = new Client('localhost:' + port, combined_creds, client_options); client.unary({}, function(err, data) { assert(err); assert.strictEqual(err.message, 'Authentication failure'); done(); }); }); describe('Per-rpc creds', function() { var client; var updater_creds; before(function() { client = new Client('localhost:' + port, client_ssl_creds, client_options); var metadataUpdater = function(service_url, callback) { var metadata = new grpc.Metadata(); metadata.set('plugin_key', 'plugin_value'); callback(null, metadata); }; updater_creds = grpc.credentials.createFromMetadataGenerator( metadataUpdater); }); it('Should update metadata on a unary call', function(done) { var call = client.unary({}, {credentials: updater_creds}, function(err, data) { assert.ifError(err); }); call.on('metadata', function(metadata) { assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']); done(); }); }); it('should update metadata on a client streaming call', function(done) { var call = client.clientStream({credentials: updater_creds}, function(err, data) { assert.ifError(err); }); call.on('metadata', function(metadata) { assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']); done(); }); call.end(); }); it('should update metadata on a server streaming call', function(done) { var call = client.serverStream({}, {credentials: updater_creds}); call.on('data', function() {}); call.on('metadata', function(metadata) { assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']); done(); }); }); it('should update metadata on a bidi streaming call', function(done) { var call = client.bidiStream({credentials: updater_creds}); call.on('data', function() {}); call.on('metadata', function(metadata) { assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']); done(); }); call.end(); }); it('should be able to use multiple plugin credentials', function(done) { var altMetadataUpdater = function(service_url, callback) { var metadata = new grpc.Metadata(); metadata.set('other_plugin_key', 'other_plugin_value'); callback(null, metadata); }; var alt_updater_creds = grpc.credentials.createFromMetadataGenerator( altMetadataUpdater); var combined_updater = grpc.credentials.combineCallCredentials( updater_creds, alt_updater_creds); var call = client.unary({}, {credentials: combined_updater}, function(err, data) { assert.ifError(err); }); call.on('metadata', function(metadata) { assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']); assert.deepEqual(metadata.get('other_plugin_key'), ['other_plugin_value']); done(); }); }); }); }); grpc-1.3.2/src/node/test/data/000077500000000000000000000000001310511640000160435ustar00rootroot00000000000000grpc-1.3.2/src/node/test/data/README000066400000000000000000000000211310511640000167140ustar00rootroot00000000000000CONFIRMEDTESTKEY grpc-1.3.2/src/node/test/data/ca.pem000066400000000000000000000015271310511640000171360ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIICSjCCAbOgAwIBAgIJAJHGGR4dGioHMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnRlc3RjYTAeFw0xNDExMTEyMjMxMjla Fw0yNDExMDgyMjMxMjlaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0 YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDzANBgNVBAMT BnRlc3RjYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwEDfBV5MYdlHVHJ7 +L4nxrZy7mBfAVXpOc5vMYztssUI7mL2/iYujiIXM+weZYNTEpLdjyJdu7R5gGUu g1jSVK/EPHfc74O7AyZU34PNIP4Sh33N+/A5YexrNgJlPY+E3GdVYi4ldWJjgkAd Qah2PH5ACLrIIC6tRka9hcaBlIECAwEAAaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNV HQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADgYEAHzC7jdYlzAVmddi/gdAeKPau sPBG/C2HCWqHzpCUHcKuvMzDVkY/MP2o6JIW2DBbY64bO/FceExhjcykgaYtCH/m oIU63+CFOTtR7otyQAWHqXa7q4SbCDlG7DyRFxqG0txPtGvy12lgldA2+RgcigQG Dfcog5wrJytaQ6UA0wE= -----END CERTIFICATE----- grpc-1.3.2/src/node/test/data/server1.key000066400000000000000000000016201310511640000201430ustar00rootroot00000000000000-----BEGIN PRIVATE KEY----- MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOHDFScoLCVJpYDD M4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1BgzkWF+slf 3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd9N8YwbBY AckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAECgYAn7qGnM2vbjJNBm0VZCkOkTIWm V10okw7EPJrdL2mkre9NasghNXbE1y5zDshx5Nt3KsazKOxTT8d0Jwh/3KbaN+YY tTCbKGW0pXDRBhwUHRcuRzScjli8Rih5UOCiZkhefUTcRb6xIhZJuQy71tjaSy0p dHZRmYyBYO2YEQ8xoQJBAPrJPhMBkzmEYFtyIEqAxQ/o/A6E+E4w8i+KM7nQCK7q K4JXzyXVAjLfyBZWHGM2uro/fjqPggGD6QH1qXCkI4MCQQDmdKeb2TrKRh5BY1LR 81aJGKcJ2XbcDu6wMZK4oqWbTX2KiYn9GB0woM6nSr/Y6iy1u145YzYxEV/iMwff DJULAkB8B2MnyzOg0pNFJqBJuH29bKCcHa8gHJzqXhNO5lAlEbMK95p/P2Wi+4Hd aiEIAF1BF326QJcvYKmwSmrORp85AkAlSNxRJ50OWrfMZnBgzVjDx3xG6KsFQVk2 ol6VhqL6dFgKUORFUWBvnKSyhjJxurlPEahV6oo6+A+mPhFY8eUvAkAZQyTdupP3 XEFQKctGz+9+gKkemDp7LBBMEMBXrGTLPhpEfcjv/7KPdnFHYmhYeBTBnuVmTVWe F98XJ7tIFfJq -----END PRIVATE KEY----- grpc-1.3.2/src/node/test/data/server1.pem000066400000000000000000000017041310511640000201370ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50 ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd 9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6 hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8 -----END CERTIFICATE----- grpc-1.3.2/src/node/test/echo_service.proto000066400000000000000000000032621310511640000206600ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; message EchoMessage { string value = 1; int32 value2 = 2; } service EchoService { rpc Echo (EchoMessage) returns (EchoMessage); } grpc-1.3.2/src/node/test/end_to_end_test.js000066400000000000000000000261121310511640000206270ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var assert = require('assert'); var grpc = require('../src/grpc_extension'); /** * This is used for testing functions with multiple asynchronous calls that * can happen in different orders. This should be passed the number of async * function invocations that can occur last, and each of those should call this * function's return value * @param {function()} done The function that should be called when a test is * complete. * @param {number} count The number of calls to the resulting function if the * test passes. * @return {function()} The function that should be called at the end of each * sequence of asynchronous functions. */ function multiDone(done, count) { return function() { count -= 1; if (count <= 0) { done(); } }; } var insecureCreds = grpc.ChannelCredentials.createInsecure(); describe('end-to-end', function() { var server; var channel; before(function() { server = new grpc.Server(); var port_num = server.addHttp2Port('0.0.0.0:0', grpc.ServerCredentials.createInsecure()); server.start(); channel = new grpc.Channel('localhost:' + port_num, insecureCreds); }); after(function() { server.forceShutdown(); }); it('should start and end a request without error', function(complete) { var done = multiDone(complete, 2); var status_text = 'xyz'; var call = new grpc.Call(channel, 'dummy_method', Infinity); var client_batch = {}; client_batch[grpc.opType.SEND_INITIAL_METADATA] = {}; client_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; client_batch[grpc.opType.RECV_INITIAL_METADATA] = true; client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; call.startBatch(client_batch, function(err, response) { assert.ifError(err); assert.deepEqual(response, { send_metadata: true, client_close: true, metadata: {}, status: { code: grpc.status.OK, details: status_text, metadata: {} } }); done(); }); server.requestCall(function(err, call_details) { var new_call = call_details.new_call; assert.notEqual(new_call, null); var server_call = new_call.call; assert.notEqual(server_call, null); var server_batch = {}; server_batch[grpc.opType.SEND_INITIAL_METADATA] = {}; server_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = { metadata: {}, code: grpc.status.OK, details: status_text }; server_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true; server_call.startBatch(server_batch, function(err, response) { assert.ifError(err); assert.deepEqual(response, { send_metadata: true, send_status: true, cancelled: false }); done(); }); }); }); it('should successfully send and receive metadata', function(complete) { var done = multiDone(complete, 2); var status_text = 'xyz'; var call = new grpc.Call(channel, 'dummy_method', Infinity); var client_batch = {}; client_batch[grpc.opType.SEND_INITIAL_METADATA] = { client_key: ['client_value'] }; client_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; client_batch[grpc.opType.RECV_INITIAL_METADATA] = true; client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; call.startBatch(client_batch, function(err, response) { assert.ifError(err); assert.deepEqual(response,{ send_metadata: true, client_close: true, metadata: {server_key: ['server_value']}, status: {code: grpc.status.OK, details: status_text, metadata: {}} }); done(); }); server.requestCall(function(err, call_details) { var new_call = call_details.new_call; assert.notEqual(new_call, null); assert.strictEqual(new_call.metadata.client_key[0], 'client_value'); var server_call = new_call.call; assert.notEqual(server_call, null); var server_batch = {}; server_batch[grpc.opType.SEND_INITIAL_METADATA] = { server_key: ['server_value'] }; server_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = { metadata: {}, code: grpc.status.OK, details: status_text }; server_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true; server_call.startBatch(server_batch, function(err, response) { assert.ifError(err); assert.deepEqual(response, { send_metadata: true, send_status: true, cancelled: false }); done(); }); }); }); it('should send and receive data without error', function(complete) { var req_text = 'client_request'; var reply_text = 'server_response'; var done = multiDone(complete, 2); var status_text = 'success'; var call = new grpc.Call(channel, 'dummy_method', Infinity); var client_batch = {}; client_batch[grpc.opType.SEND_INITIAL_METADATA] = {}; client_batch[grpc.opType.SEND_MESSAGE] = new Buffer(req_text); client_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; client_batch[grpc.opType.RECV_INITIAL_METADATA] = true; client_batch[grpc.opType.RECV_MESSAGE] = true; client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; call.startBatch(client_batch, function(err, response) { assert.ifError(err); assert(response.send_metadata); assert(response.client_close); assert.deepEqual(response.metadata, {}); assert(response.send_message); assert.strictEqual(response.read.toString(), reply_text); assert.deepEqual(response.status, {code: grpc.status.OK, details: status_text, metadata: {}}); done(); }); server.requestCall(function(err, call_details) { var new_call = call_details.new_call; assert.notEqual(new_call, null); var server_call = new_call.call; assert.notEqual(server_call, null); var server_batch = {}; server_batch[grpc.opType.SEND_INITIAL_METADATA] = {}; server_batch[grpc.opType.RECV_MESSAGE] = true; server_call.startBatch(server_batch, function(err, response) { assert.ifError(err); assert(response.send_metadata); assert.strictEqual(response.read.toString(), req_text); var response_batch = {}; response_batch[grpc.opType.SEND_MESSAGE] = new Buffer(reply_text); response_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = { metadata: {}, code: grpc.status.OK, details: status_text }; response_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true; server_call.startBatch(response_batch, function(err, response) { assert(response.send_status); assert(!response.cancelled); done(); }); }); }); }); it('should send multiple messages', function(complete) { var done = multiDone(complete, 2); var requests = ['req1', 'req2']; var status_text = 'xyz'; var call = new grpc.Call(channel, 'dummy_method', Infinity); var client_batch = {}; client_batch[grpc.opType.SEND_INITIAL_METADATA] = {}; client_batch[grpc.opType.SEND_MESSAGE] = new Buffer(requests[0]); client_batch[grpc.opType.RECV_INITIAL_METADATA] = true; call.startBatch(client_batch, function(err, response) { assert.ifError(err); assert.deepEqual(response, { send_metadata: true, send_message: true, metadata: {} }); var req2_batch = {}; req2_batch[grpc.opType.SEND_MESSAGE] = new Buffer(requests[1]); req2_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; req2_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; call.startBatch(req2_batch, function(err, resp) { assert.ifError(err); assert.deepEqual(resp, { send_message: true, client_close: true, status: { code: grpc.status.OK, details: status_text, metadata: {} } }); done(); }); }); server.requestCall(function(err, call_details) { var new_call = call_details.new_call; assert.notEqual(new_call, null); var server_call = new_call.call; assert.notEqual(server_call, null); var server_batch = {}; server_batch[grpc.opType.SEND_INITIAL_METADATA] = {}; server_batch[grpc.opType.RECV_MESSAGE] = true; server_call.startBatch(server_batch, function(err, response) { assert.ifError(err); assert(response.send_metadata); assert.strictEqual(response.read.toString(), requests[0]); var snd_batch = {}; snd_batch[grpc.opType.RECV_MESSAGE] = true; server_call.startBatch(snd_batch, function(err, response) { assert.ifError(err); assert.strictEqual(response.read.toString(), requests[1]); var end_batch = {}; end_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true; end_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = { metadata: {}, code: grpc.status.OK, details: status_text }; server_call.startBatch(end_batch, function(err, response) { assert.ifError(err); assert(response.send_status); assert(!response.cancelled); done(); }); }); }); }); }); }); grpc-1.3.2/src/node/test/health_test.js000066400000000000000000000110611310511640000177730ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var assert = require('assert'); var health = require('../health_check/health'); var health_messages = require('../health_check/v1/health_pb'); var ServingStatus = health_messages.HealthCheckResponse.ServingStatus; var grpc = require('../'); describe('Health Checking', function() { var statusMap = { '': ServingStatus.SERVING, 'grpc.test.TestServiceNotServing': ServingStatus.NOT_SERVING, 'grpc.test.TestServiceServing': ServingStatus.SERVING }; var healthServer; var healthImpl; var healthClient; before(function() { healthServer = new grpc.Server(); healthImpl = new health.Implementation(statusMap); healthServer.addService(health.service, healthImpl); var port_num = healthServer.bind('0.0.0.0:0', grpc.ServerCredentials.createInsecure()); healthServer.start(); healthClient = new health.Client('localhost:' + port_num, grpc.credentials.createInsecure()); }); after(function() { healthServer.forceShutdown(); }); it('should say an enabled service is SERVING', function(done) { var request = new health_messages.HealthCheckRequest(); request.setService(''); healthClient.check(request, function(err, response) { assert.ifError(err); assert.strictEqual(response.getStatus(), ServingStatus.SERVING); done(); }); }); it('should say that a disabled service is NOT_SERVING', function(done) { var request = new health_messages.HealthCheckRequest(); request.setService('grpc.test.TestServiceNotServing'); healthClient.check(request, function(err, response) { assert.ifError(err); assert.strictEqual(response.getStatus(), ServingStatus.NOT_SERVING); done(); }); }); it('should say that an enabled service is SERVING', function(done) { var request = new health_messages.HealthCheckRequest(); request.setService('grpc.test.TestServiceServing'); healthClient.check(request, function(err, response) { assert.ifError(err); assert.strictEqual(response.getStatus(), ServingStatus.SERVING); done(); }); }); it('should get NOT_FOUND if the service is not registered', function(done) { var request = new health_messages.HealthCheckRequest(); request.setService('not_registered'); healthClient.check(request, function(err, response) { assert(err); assert.strictEqual(err.code, grpc.status.NOT_FOUND); done(); }); }); it('should get a different response if the status changes', function(done) { var request = new health_messages.HealthCheckRequest(); request.setService('transient'); healthClient.check(request, function(err, response) { assert(err); assert.strictEqual(err.code, grpc.status.NOT_FOUND); healthImpl.setStatus('transient', ServingStatus.SERVING); healthClient.check(request, function(err, response) { assert.ifError(err); assert.strictEqual(response.getStatus(), ServingStatus.SERVING); done(); }); }); }); }); grpc-1.3.2/src/node/test/interop_sanity_test.js000066400000000000000000000105101310511640000215730ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var interop_server = require('../interop/interop_server.js'); var interop_client = require('../interop/interop_client.js'); var server; var port; var name_override = 'foo.test.google.fr'; describe('Interop tests', function() { before(function(done) { var server_obj = interop_server.getServer(0, true); server = server_obj.server; server.start(); port = 'localhost:' + server_obj.port; done(); }); after(function() { server.forceShutdown(); }); // This depends on not using a binary stream it('should pass empty_unary', function(done) { interop_client.runTest(port, name_override, 'empty_unary', true, true, done); }); // This fails due to an unknown bug it('should pass large_unary', function(done) { interop_client.runTest(port, name_override, 'large_unary', true, true, done); }); it('should pass client_streaming', function(done) { interop_client.runTest(port, name_override, 'client_streaming', true, true, done); }); it('should pass server_streaming', function(done) { interop_client.runTest(port, name_override, 'server_streaming', true, true, done); }); it('should pass ping_pong', function(done) { interop_client.runTest(port, name_override, 'ping_pong', true, true, done); }); it('should pass empty_stream', function(done) { interop_client.runTest(port, name_override, 'empty_stream', true, true, done); }); it('should pass cancel_after_begin', function(done) { interop_client.runTest(port, name_override, 'cancel_after_begin', true, true, done); }); it('should pass cancel_after_first_response', function(done) { interop_client.runTest(port, name_override, 'cancel_after_first_response', true, true, done); }); it('should pass timeout_on_sleeping_server', function(done) { interop_client.runTest(port, name_override, 'timeout_on_sleeping_server', true, true, done); }); it('should pass custom_metadata', function(done) { interop_client.runTest(port, name_override, 'custom_metadata', true, true, done); }); it('should pass status_code_and_message', function(done) { interop_client.runTest(port, name_override, 'status_code_and_message', true, true, done); }); it('should pass unimplemented_service', function(done) { interop_client.runTest(port, name_override, 'unimplemented_service', true, true, done); }); it('should pass unimplemented_method', function(done) { interop_client.runTest(port, name_override, 'unimplemented_method', true, true, done); }); }); grpc-1.3.2/src/node/test/math/000077500000000000000000000000001310511640000160635ustar00rootroot00000000000000grpc-1.3.2/src/node/test/math/math_grpc_pb.js000066400000000000000000000120311310511640000210430ustar00rootroot00000000000000// GENERATED CODE -- DO NOT EDIT! // Original file comments: // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // 'use strict'; var grpc = require('grpc'); var math_math_pb = require('../math/math_pb.js'); function serialize_DivArgs(arg) { if (!(arg instanceof math_math_pb.DivArgs)) { throw new Error('Expected argument of type DivArgs'); } return new Buffer(arg.serializeBinary()); } function deserialize_DivArgs(buffer_arg) { return math_math_pb.DivArgs.deserializeBinary(new Uint8Array(buffer_arg)); } function serialize_DivReply(arg) { if (!(arg instanceof math_math_pb.DivReply)) { throw new Error('Expected argument of type DivReply'); } return new Buffer(arg.serializeBinary()); } function deserialize_DivReply(buffer_arg) { return math_math_pb.DivReply.deserializeBinary(new Uint8Array(buffer_arg)); } function serialize_FibArgs(arg) { if (!(arg instanceof math_math_pb.FibArgs)) { throw new Error('Expected argument of type FibArgs'); } return new Buffer(arg.serializeBinary()); } function deserialize_FibArgs(buffer_arg) { return math_math_pb.FibArgs.deserializeBinary(new Uint8Array(buffer_arg)); } function serialize_Num(arg) { if (!(arg instanceof math_math_pb.Num)) { throw new Error('Expected argument of type Num'); } return new Buffer(arg.serializeBinary()); } function deserialize_Num(buffer_arg) { return math_math_pb.Num.deserializeBinary(new Uint8Array(buffer_arg)); } var MathService = exports.MathService = { // Div divides args.dividend by args.divisor and returns the quotient and // remainder. div: { path: '/math.Math/Div', requestStream: false, responseStream: false, requestType: math_math_pb.DivArgs, responseType: math_math_pb.DivReply, requestSerialize: serialize_DivArgs, requestDeserialize: deserialize_DivArgs, responseSerialize: serialize_DivReply, responseDeserialize: deserialize_DivReply, }, // DivMany accepts an arbitrary number of division args from the client stream // and sends back the results in the reply stream. The stream continues until // the client closes its end; the server does the same after sending all the // replies. The stream ends immediately if either end aborts. divMany: { path: '/math.Math/DivMany', requestStream: true, responseStream: true, requestType: math_math_pb.DivArgs, responseType: math_math_pb.DivReply, requestSerialize: serialize_DivArgs, requestDeserialize: deserialize_DivArgs, responseSerialize: serialize_DivReply, responseDeserialize: deserialize_DivReply, }, // Fib generates numbers in the Fibonacci sequence. If args.limit > 0, Fib // generates up to limit numbers; otherwise it continues until the call is // canceled. Unlike Fib above, Fib has no final FibReply. fib: { path: '/math.Math/Fib', requestStream: false, responseStream: true, requestType: math_math_pb.FibArgs, responseType: math_math_pb.Num, requestSerialize: serialize_FibArgs, requestDeserialize: deserialize_FibArgs, responseSerialize: serialize_Num, responseDeserialize: deserialize_Num, }, // Sum sums a stream of numbers, returning the final result once the stream // is closed. sum: { path: '/math.Math/Sum', requestStream: true, responseStream: false, requestType: math_math_pb.Num, responseType: math_math_pb.Num, requestSerialize: serialize_Num, requestDeserialize: deserialize_Num, responseSerialize: serialize_Num, responseDeserialize: deserialize_Num, }, }; exports.MathClient = grpc.makeGenericClientConstructor(MathService); grpc-1.3.2/src/node/test/math/math_pb.js000066400000000000000000000570031310511640000200400ustar00rootroot00000000000000/** * @fileoverview * @enhanceable * @public */ // GENERATED CODE -- DO NOT EDIT! var jspb = require('google-protobuf'); var goog = jspb; var global = Function('return this')(); goog.exportSymbol('proto.math.DivArgs', null, global); goog.exportSymbol('proto.math.DivReply', null, global); goog.exportSymbol('proto.math.FibArgs', null, global); goog.exportSymbol('proto.math.FibReply', null, global); goog.exportSymbol('proto.math.Num', null, global); /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a * server response, or constructed directly in Javascript. The array is used * in place and becomes part of the constructed object. It is not cloned. * If no data is provided, the constructed object will be empty, but still * valid. * @extends {jspb.Message} * @constructor */ proto.math.DivArgs = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; goog.inherits(proto.math.DivArgs, jspb.Message); if (goog.DEBUG && !COMPILED) { proto.math.DivArgs.displayName = 'proto.math.DivArgs'; } if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto suitable for use in Soy templates. * Field names that are reserved in JavaScript and will be renamed to pb_name. * To access a reserved field use, foo.pb_, eg, foo.pb_default. * For the list of reserved names please see: * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration * @return {!Object} */ proto.math.DivArgs.prototype.toObject = function(opt_includeInstance) { return proto.math.DivArgs.toObject(opt_includeInstance, this); }; /** * Static version of the {@see toObject} method. * @param {boolean|undefined} includeInstance Whether to include the JSPB * instance for transitional soy proto support: * http://goto/soy-param-migration * @param {!proto.math.DivArgs} msg The msg instance to transform. * @return {!Object} */ proto.math.DivArgs.toObject = function(includeInstance, msg) { var f, obj = { dividend: msg.getDividend(), divisor: msg.getDivisor() }; if (includeInstance) { obj.$jspbMessageInstance = msg; } return obj; }; } /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. * @return {!proto.math.DivArgs} */ proto.math.DivArgs.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); var msg = new proto.math.DivArgs; return proto.math.DivArgs.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. * @param {!proto.math.DivArgs} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. * @return {!proto.math.DivArgs} */ proto.math.DivArgs.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); switch (field) { case 1: var value = /** @type {number} */ (reader.readInt64()); msg.setDividend(value); break; case 2: var value = /** @type {number} */ (reader.readInt64()); msg.setDivisor(value); break; default: reader.skipField(); break; } } return msg; }; /** * Class method variant: serializes the given message to binary data * (in protobuf wire format), writing to the given BinaryWriter. * @param {!proto.math.DivArgs} message * @param {!jspb.BinaryWriter} writer */ proto.math.DivArgs.serializeBinaryToWriter = function(message, writer) { message.serializeBinaryToWriter(writer); }; /** * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ proto.math.DivArgs.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); this.serializeBinaryToWriter(writer); return writer.getResultBuffer(); }; /** * Serializes the message to binary data (in protobuf wire format), * writing to the given BinaryWriter. * @param {!jspb.BinaryWriter} writer */ proto.math.DivArgs.prototype.serializeBinaryToWriter = function (writer) { var f = undefined; f = this.getDividend(); if (f !== 0) { writer.writeInt64( 1, f ); } f = this.getDivisor(); if (f !== 0) { writer.writeInt64( 2, f ); } }; /** * Creates a deep clone of this proto. No data is shared with the original. * @return {!proto.math.DivArgs} The clone. */ proto.math.DivArgs.prototype.cloneMessage = function() { return /** @type {!proto.math.DivArgs} */ (jspb.Message.cloneMessage(this)); }; /** * optional int64 dividend = 1; * @return {number} */ proto.math.DivArgs.prototype.getDividend = function() { return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0)); }; /** @param {number} value */ proto.math.DivArgs.prototype.setDividend = function(value) { jspb.Message.setField(this, 1, value); }; /** * optional int64 divisor = 2; * @return {number} */ proto.math.DivArgs.prototype.getDivisor = function() { return /** @type {number} */ (jspb.Message.getFieldProto3(this, 2, 0)); }; /** @param {number} value */ proto.math.DivArgs.prototype.setDivisor = function(value) { jspb.Message.setField(this, 2, value); }; /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a * server response, or constructed directly in Javascript. The array is used * in place and becomes part of the constructed object. It is not cloned. * If no data is provided, the constructed object will be empty, but still * valid. * @extends {jspb.Message} * @constructor */ proto.math.DivReply = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; goog.inherits(proto.math.DivReply, jspb.Message); if (goog.DEBUG && !COMPILED) { proto.math.DivReply.displayName = 'proto.math.DivReply'; } if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto suitable for use in Soy templates. * Field names that are reserved in JavaScript and will be renamed to pb_name. * To access a reserved field use, foo.pb_, eg, foo.pb_default. * For the list of reserved names please see: * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration * @return {!Object} */ proto.math.DivReply.prototype.toObject = function(opt_includeInstance) { return proto.math.DivReply.toObject(opt_includeInstance, this); }; /** * Static version of the {@see toObject} method. * @param {boolean|undefined} includeInstance Whether to include the JSPB * instance for transitional soy proto support: * http://goto/soy-param-migration * @param {!proto.math.DivReply} msg The msg instance to transform. * @return {!Object} */ proto.math.DivReply.toObject = function(includeInstance, msg) { var f, obj = { quotient: msg.getQuotient(), remainder: msg.getRemainder() }; if (includeInstance) { obj.$jspbMessageInstance = msg; } return obj; }; } /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. * @return {!proto.math.DivReply} */ proto.math.DivReply.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); var msg = new proto.math.DivReply; return proto.math.DivReply.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. * @param {!proto.math.DivReply} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. * @return {!proto.math.DivReply} */ proto.math.DivReply.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); switch (field) { case 1: var value = /** @type {number} */ (reader.readInt64()); msg.setQuotient(value); break; case 2: var value = /** @type {number} */ (reader.readInt64()); msg.setRemainder(value); break; default: reader.skipField(); break; } } return msg; }; /** * Class method variant: serializes the given message to binary data * (in protobuf wire format), writing to the given BinaryWriter. * @param {!proto.math.DivReply} message * @param {!jspb.BinaryWriter} writer */ proto.math.DivReply.serializeBinaryToWriter = function(message, writer) { message.serializeBinaryToWriter(writer); }; /** * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ proto.math.DivReply.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); this.serializeBinaryToWriter(writer); return writer.getResultBuffer(); }; /** * Serializes the message to binary data (in protobuf wire format), * writing to the given BinaryWriter. * @param {!jspb.BinaryWriter} writer */ proto.math.DivReply.prototype.serializeBinaryToWriter = function (writer) { var f = undefined; f = this.getQuotient(); if (f !== 0) { writer.writeInt64( 1, f ); } f = this.getRemainder(); if (f !== 0) { writer.writeInt64( 2, f ); } }; /** * Creates a deep clone of this proto. No data is shared with the original. * @return {!proto.math.DivReply} The clone. */ proto.math.DivReply.prototype.cloneMessage = function() { return /** @type {!proto.math.DivReply} */ (jspb.Message.cloneMessage(this)); }; /** * optional int64 quotient = 1; * @return {number} */ proto.math.DivReply.prototype.getQuotient = function() { return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0)); }; /** @param {number} value */ proto.math.DivReply.prototype.setQuotient = function(value) { jspb.Message.setField(this, 1, value); }; /** * optional int64 remainder = 2; * @return {number} */ proto.math.DivReply.prototype.getRemainder = function() { return /** @type {number} */ (jspb.Message.getFieldProto3(this, 2, 0)); }; /** @param {number} value */ proto.math.DivReply.prototype.setRemainder = function(value) { jspb.Message.setField(this, 2, value); }; /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a * server response, or constructed directly in Javascript. The array is used * in place and becomes part of the constructed object. It is not cloned. * If no data is provided, the constructed object will be empty, but still * valid. * @extends {jspb.Message} * @constructor */ proto.math.FibArgs = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; goog.inherits(proto.math.FibArgs, jspb.Message); if (goog.DEBUG && !COMPILED) { proto.math.FibArgs.displayName = 'proto.math.FibArgs'; } if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto suitable for use in Soy templates. * Field names that are reserved in JavaScript and will be renamed to pb_name. * To access a reserved field use, foo.pb_, eg, foo.pb_default. * For the list of reserved names please see: * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration * @return {!Object} */ proto.math.FibArgs.prototype.toObject = function(opt_includeInstance) { return proto.math.FibArgs.toObject(opt_includeInstance, this); }; /** * Static version of the {@see toObject} method. * @param {boolean|undefined} includeInstance Whether to include the JSPB * instance for transitional soy proto support: * http://goto/soy-param-migration * @param {!proto.math.FibArgs} msg The msg instance to transform. * @return {!Object} */ proto.math.FibArgs.toObject = function(includeInstance, msg) { var f, obj = { limit: msg.getLimit() }; if (includeInstance) { obj.$jspbMessageInstance = msg; } return obj; }; } /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. * @return {!proto.math.FibArgs} */ proto.math.FibArgs.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); var msg = new proto.math.FibArgs; return proto.math.FibArgs.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. * @param {!proto.math.FibArgs} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. * @return {!proto.math.FibArgs} */ proto.math.FibArgs.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); switch (field) { case 1: var value = /** @type {number} */ (reader.readInt64()); msg.setLimit(value); break; default: reader.skipField(); break; } } return msg; }; /** * Class method variant: serializes the given message to binary data * (in protobuf wire format), writing to the given BinaryWriter. * @param {!proto.math.FibArgs} message * @param {!jspb.BinaryWriter} writer */ proto.math.FibArgs.serializeBinaryToWriter = function(message, writer) { message.serializeBinaryToWriter(writer); }; /** * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ proto.math.FibArgs.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); this.serializeBinaryToWriter(writer); return writer.getResultBuffer(); }; /** * Serializes the message to binary data (in protobuf wire format), * writing to the given BinaryWriter. * @param {!jspb.BinaryWriter} writer */ proto.math.FibArgs.prototype.serializeBinaryToWriter = function (writer) { var f = undefined; f = this.getLimit(); if (f !== 0) { writer.writeInt64( 1, f ); } }; /** * Creates a deep clone of this proto. No data is shared with the original. * @return {!proto.math.FibArgs} The clone. */ proto.math.FibArgs.prototype.cloneMessage = function() { return /** @type {!proto.math.FibArgs} */ (jspb.Message.cloneMessage(this)); }; /** * optional int64 limit = 1; * @return {number} */ proto.math.FibArgs.prototype.getLimit = function() { return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0)); }; /** @param {number} value */ proto.math.FibArgs.prototype.setLimit = function(value) { jspb.Message.setField(this, 1, value); }; /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a * server response, or constructed directly in Javascript. The array is used * in place and becomes part of the constructed object. It is not cloned. * If no data is provided, the constructed object will be empty, but still * valid. * @extends {jspb.Message} * @constructor */ proto.math.Num = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; goog.inherits(proto.math.Num, jspb.Message); if (goog.DEBUG && !COMPILED) { proto.math.Num.displayName = 'proto.math.Num'; } if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto suitable for use in Soy templates. * Field names that are reserved in JavaScript and will be renamed to pb_name. * To access a reserved field use, foo.pb_, eg, foo.pb_default. * For the list of reserved names please see: * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration * @return {!Object} */ proto.math.Num.prototype.toObject = function(opt_includeInstance) { return proto.math.Num.toObject(opt_includeInstance, this); }; /** * Static version of the {@see toObject} method. * @param {boolean|undefined} includeInstance Whether to include the JSPB * instance for transitional soy proto support: * http://goto/soy-param-migration * @param {!proto.math.Num} msg The msg instance to transform. * @return {!Object} */ proto.math.Num.toObject = function(includeInstance, msg) { var f, obj = { num: msg.getNum() }; if (includeInstance) { obj.$jspbMessageInstance = msg; } return obj; }; } /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. * @return {!proto.math.Num} */ proto.math.Num.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); var msg = new proto.math.Num; return proto.math.Num.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. * @param {!proto.math.Num} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. * @return {!proto.math.Num} */ proto.math.Num.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); switch (field) { case 1: var value = /** @type {number} */ (reader.readInt64()); msg.setNum(value); break; default: reader.skipField(); break; } } return msg; }; /** * Class method variant: serializes the given message to binary data * (in protobuf wire format), writing to the given BinaryWriter. * @param {!proto.math.Num} message * @param {!jspb.BinaryWriter} writer */ proto.math.Num.serializeBinaryToWriter = function(message, writer) { message.serializeBinaryToWriter(writer); }; /** * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ proto.math.Num.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); this.serializeBinaryToWriter(writer); return writer.getResultBuffer(); }; /** * Serializes the message to binary data (in protobuf wire format), * writing to the given BinaryWriter. * @param {!jspb.BinaryWriter} writer */ proto.math.Num.prototype.serializeBinaryToWriter = function (writer) { var f = undefined; f = this.getNum(); if (f !== 0) { writer.writeInt64( 1, f ); } }; /** * Creates a deep clone of this proto. No data is shared with the original. * @return {!proto.math.Num} The clone. */ proto.math.Num.prototype.cloneMessage = function() { return /** @type {!proto.math.Num} */ (jspb.Message.cloneMessage(this)); }; /** * optional int64 num = 1; * @return {number} */ proto.math.Num.prototype.getNum = function() { return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0)); }; /** @param {number} value */ proto.math.Num.prototype.setNum = function(value) { jspb.Message.setField(this, 1, value); }; /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a * server response, or constructed directly in Javascript. The array is used * in place and becomes part of the constructed object. It is not cloned. * If no data is provided, the constructed object will be empty, but still * valid. * @extends {jspb.Message} * @constructor */ proto.math.FibReply = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; goog.inherits(proto.math.FibReply, jspb.Message); if (goog.DEBUG && !COMPILED) { proto.math.FibReply.displayName = 'proto.math.FibReply'; } if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto suitable for use in Soy templates. * Field names that are reserved in JavaScript and will be renamed to pb_name. * To access a reserved field use, foo.pb_, eg, foo.pb_default. * For the list of reserved names please see: * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration * @return {!Object} */ proto.math.FibReply.prototype.toObject = function(opt_includeInstance) { return proto.math.FibReply.toObject(opt_includeInstance, this); }; /** * Static version of the {@see toObject} method. * @param {boolean|undefined} includeInstance Whether to include the JSPB * instance for transitional soy proto support: * http://goto/soy-param-migration * @param {!proto.math.FibReply} msg The msg instance to transform. * @return {!Object} */ proto.math.FibReply.toObject = function(includeInstance, msg) { var f, obj = { count: msg.getCount() }; if (includeInstance) { obj.$jspbMessageInstance = msg; } return obj; }; } /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. * @return {!proto.math.FibReply} */ proto.math.FibReply.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); var msg = new proto.math.FibReply; return proto.math.FibReply.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. * @param {!proto.math.FibReply} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. * @return {!proto.math.FibReply} */ proto.math.FibReply.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); switch (field) { case 1: var value = /** @type {number} */ (reader.readInt64()); msg.setCount(value); break; default: reader.skipField(); break; } } return msg; }; /** * Class method variant: serializes the given message to binary data * (in protobuf wire format), writing to the given BinaryWriter. * @param {!proto.math.FibReply} message * @param {!jspb.BinaryWriter} writer */ proto.math.FibReply.serializeBinaryToWriter = function(message, writer) { message.serializeBinaryToWriter(writer); }; /** * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ proto.math.FibReply.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); this.serializeBinaryToWriter(writer); return writer.getResultBuffer(); }; /** * Serializes the message to binary data (in protobuf wire format), * writing to the given BinaryWriter. * @param {!jspb.BinaryWriter} writer */ proto.math.FibReply.prototype.serializeBinaryToWriter = function (writer) { var f = undefined; f = this.getCount(); if (f !== 0) { writer.writeInt64( 1, f ); } }; /** * Creates a deep clone of this proto. No data is shared with the original. * @return {!proto.math.FibReply} The clone. */ proto.math.FibReply.prototype.cloneMessage = function() { return /** @type {!proto.math.FibReply} */ (jspb.Message.cloneMessage(this)); }; /** * optional int64 count = 1; * @return {number} */ proto.math.FibReply.prototype.getCount = function() { return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0)); }; /** @param {number} value */ proto.math.FibReply.prototype.setCount = function(value) { jspb.Message.setField(this, 1, value); }; goog.object.extend(exports, proto.math); grpc-1.3.2/src/node/test/math/math_server.js000066400000000000000000000107741310511640000207510ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var grpc = require('../..'); var grpcMath = require('./math_grpc_pb'); var math = require('./math_pb'); /** * Server function for division. Provides the /Math/DivMany and /Math/Div * functions (Div is just DivMany with only one stream element). For each * DivArgs parameter, responds with a DivReply with the results of the division * @param {Object} call The object containing request and cancellation info * @param {function(Error, *)} cb Response callback */ function mathDiv(call, cb) { var req = call.request; var divisor = req.getDivisor(); var dividend = req.getDividend(); // Unary + is explicit coersion to integer if (req.getDivisor() === 0) { cb(new Error('cannot divide by zero')); } else { var response = new math.DivReply(); response.setQuotient(Math.floor(dividend / divisor)); response.setRemainder(dividend % divisor); cb(null, response); } } /** * Server function for Fibonacci numbers. Provides the /Math/Fib function. Reads * a single parameter that indicates the number of responses, and then responds * with a stream of that many Fibonacci numbers. * @param {stream} stream The stream for sending responses. */ function mathFib(stream) { // Here, call is a standard writable Node object Stream var previous = 0, current = 1; for (var i = 0; i < stream.request.getLimit(); i++) { var response = new math.Num(); response.setNum(current); stream.write(response); var temp = current; current += previous; previous = temp; } stream.end(); } /** * Server function for summation. Provides the /Math/Sum function. Reads a * stream of number parameters, then responds with their sum. * @param {stream} call The stream of arguments. * @param {function(Error, *)} cb Response callback */ function mathSum(call, cb) { // Here, call is a standard readable Node object Stream var sum = 0; call.on('data', function(data) { sum += data.getNum(); }); call.on('end', function() { var response = new math.Num(); response.setNum(sum); cb(null, response); }); } function mathDivMany(stream) { stream.on('data', function(div_args) { var divisor = div_args.getDivisor(); var dividend = div_args.getDividend(); if (divisor === 0) { stream.emit('error', new Error('cannot divide by zero')); } else { var response = new math.DivReply(); response.setQuotient(Math.floor(dividend / divisor)); response.setRemainder(dividend % divisor); stream.write(response); } }); stream.on('end', function() { stream.end(); }); } function getMathServer() { var server = new grpc.Server(); server.addService(grpcMath.MathService, { div: mathDiv, fib: mathFib, sum: mathSum, divMany: mathDivMany }); return server; } if (require.main === module) { var server = getMathServer(); server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure()); server.start(); } /** * See docs for server */ module.exports = getMathServer; grpc-1.3.2/src/node/test/math/node_modules/000077500000000000000000000000001310511640000205405ustar00rootroot00000000000000grpc-1.3.2/src/node/test/math/node_modules/grpc.js000066400000000000000000000032711310511640000220340ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* This exists solely to allow the generated code to import the grpc module * without using a relative path */ module.exports = require('../../..'); grpc-1.3.2/src/node/test/math_client_test.js000066400000000000000000000117731310511640000210270ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var assert = require('assert'); var grpc = require('..'); var math = require('./math/math_pb'); var MathClient = require('./math/math_grpc_pb').MathClient; /** * Client to use to make requests to a running server. */ var math_client; /** * Server to test against */ var getServer = require('./math/math_server.js'); var server = getServer(); describe('Math client', function() { before(function(done) { var port_num = server.bind('0.0.0.0:0', grpc.ServerCredentials.createInsecure()); server.start(); math_client = new MathClient('localhost:' + port_num, grpc.credentials.createInsecure()); done(); }); after(function() { server.forceShutdown(); }); it('should handle a single request', function(done) { var arg = new math.DivArgs(); arg.setDividend(7); arg.setDivisor(4); math_client.div(arg, function handleDivResult(err, value) { assert.ifError(err); assert.equal(value.getQuotient(), 1); assert.equal(value.getRemainder(), 3); done(); }); }); it('should handle an error from a unary request', function(done) { var arg = new math.DivArgs(); arg.setDividend(7); arg.setDivisor(0); math_client.div(arg, function handleDivResult(err, value) { assert(err); done(); }); }); it('should handle a server streaming request', function(done) { var arg = new math.FibArgs(); arg.setLimit(7); var call = math_client.fib(arg); var expected_results = [1, 1, 2, 3, 5, 8, 13]; var next_expected = 0; call.on('data', function checkResponse(value) { assert.equal(value.getNum(), expected_results[next_expected]); next_expected += 1; }); call.on('status', function checkStatus(status) { assert.strictEqual(status.code, grpc.status.OK); done(); }); }); it('should handle a client streaming request', function(done) { var call = math_client.sum(function handleSumResult(err, value) { assert.ifError(err); assert.equal(value.getNum(), 21); }); for (var i = 0; i < 7; i++) { var arg = new math.Num(); arg.setNum(i); call.write(arg); } call.end(); call.on('status', function checkStatus(status) { assert.strictEqual(status.code, grpc.status.OK); done(); }); }); it('should handle a bidirectional streaming request', function(done) { function checkResponse(index, value) { assert.equal(value.getQuotient(), index); assert.equal(value.getRemainder(), 1); } var call = math_client.divMany(); var response_index = 0; call.on('data', function(value) { checkResponse(response_index, value); response_index += 1; }); for (var i = 0; i < 7; i++) { var arg = new math.DivArgs(); arg.setDividend(2 * i + 1); arg.setDivisor(2); call.write(arg); } call.end(); call.on('status', function checkStatus(status) { assert.strictEqual(status.code, grpc.status.OK); done(); }); }); it('should handle an error from a bidi request', function(done) { var call = math_client.divMany(); call.on('data', function(value) { assert.fail(value, undefined, 'Unexpected data response on failing call', '!='); }); var arg = new math.DivArgs(); arg.setDividend(7); arg.setDivisor(0); call.write(arg); call.end(); call.on('error', function checkStatus(status) { done(); }); }); }); grpc-1.3.2/src/node/test/metadata_test.js000066400000000000000000000152351310511640000203150ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var Metadata = require('../src/metadata.js'); var assert = require('assert'); describe('Metadata', function() { var metadata; beforeEach(function() { metadata = new Metadata(); }); describe('#set', function() { it('Only accepts string values for non "-bin" keys', function() { assert.throws(function() { metadata.set('key', new Buffer('value')); }); assert.doesNotThrow(function() { metadata.set('key', 'value'); }); }); it('Only accepts Buffer values for "-bin" keys', function() { assert.throws(function() { metadata.set('key-bin', 'value'); }); assert.doesNotThrow(function() { metadata.set('key-bin', new Buffer('value')); }); }); it('Rejects invalid keys', function() { assert.throws(function() { metadata.set('key$', 'value'); }); assert.throws(function() { metadata.set('', 'value'); }); }); it('Rejects values with non-ASCII characters', function() { assert.throws(function() { metadata.set('key', 'résumé'); }); }); it('Saves values that can be retrieved', function() { metadata.set('key', 'value'); assert.deepEqual(metadata.get('key'), ['value']); }); it('Overwrites previous values', function() { metadata.set('key', 'value1'); metadata.set('key', 'value2'); assert.deepEqual(metadata.get('key'), ['value2']); }); it('Normalizes keys', function() { metadata.set('Key', 'value1'); assert.deepEqual(metadata.get('key'), ['value1']); metadata.set('KEY', 'value2'); assert.deepEqual(metadata.get('key'), ['value2']); }); }); describe('#add', function() { it('Only accepts string values for non "-bin" keys', function() { assert.throws(function() { metadata.add('key', new Buffer('value')); }); assert.doesNotThrow(function() { metadata.add('key', 'value'); }); }); it('Only accepts Buffer values for "-bin" keys', function() { assert.throws(function() { metadata.add('key-bin', 'value'); }); assert.doesNotThrow(function() { metadata.add('key-bin', new Buffer('value')); }); }); it('Rejects invalid keys', function() { assert.throws(function() { metadata.add('key$', 'value'); }); assert.throws(function() { metadata.add('', 'value'); }); }); it('Saves values that can be retrieved', function() { metadata.add('key', 'value'); assert.deepEqual(metadata.get('key'), ['value']); }); it('Combines with previous values', function() { metadata.add('key', 'value1'); metadata.add('key', 'value2'); assert.deepEqual(metadata.get('key'), ['value1', 'value2']); }); it('Normalizes keys', function() { metadata.add('Key', 'value1'); assert.deepEqual(metadata.get('key'), ['value1']); metadata.add('KEY', 'value2'); assert.deepEqual(metadata.get('key'), ['value1', 'value2']); }); }); describe('#remove', function() { it('clears values from a key', function() { metadata.add('key', 'value'); metadata.remove('key'); assert.deepEqual(metadata.get('key'), []); }); it('Normalizes keys', function() { metadata.add('key', 'value'); metadata.remove('KEY'); assert.deepEqual(metadata.get('key'), []); }); }); describe('#get', function() { beforeEach(function() { metadata.add('key', 'value1'); metadata.add('key', 'value2'); metadata.add('key-bin', new Buffer('value')); }); it('gets all values associated with a key', function() { assert.deepEqual(metadata.get('key'), ['value1', 'value2']); }); it('Normalizes keys', function() { assert.deepEqual(metadata.get('KEY'), ['value1', 'value2']); }); it('returns an empty list for non-existent keys', function() { assert.deepEqual(metadata.get('non-existent-key'), []); }); it('returns Buffers for "-bin" keys', function() { assert(metadata.get('key-bin')[0] instanceof Buffer); }); }); describe('#getMap', function() { it('gets a map of keys to values', function() { metadata.add('key1', 'value1'); metadata.add('Key2', 'value2'); metadata.add('KEY3', 'value3'); assert.deepEqual(metadata.getMap(), {key1: 'value1', key2: 'value2', key3: 'value3'}); }); }); describe('#clone', function() { it('retains values from the original', function() { metadata.add('key', 'value'); var copy = metadata.clone(); assert.deepEqual(copy.get('key'), ['value']); }); it('Does not see newly added values', function() { metadata.add('key', 'value1'); var copy = metadata.clone(); metadata.add('key', 'value2'); assert.deepEqual(copy.get('key'), ['value1']); }); it('Does not add new values to the original', function() { metadata.add('key', 'value1'); var copy = metadata.clone(); copy.add('key', 'value2'); assert.deepEqual(metadata.get('key'), ['value1']); }); }); }); grpc-1.3.2/src/node/test/numbers.txt000066400000000000000000031343601310511640000173600ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 grpc-1.3.2/src/node/test/server_test.js000066400000000000000000000122051310511640000200350ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var assert = require('assert'); var fs = require('fs'); var path = require('path'); var grpc = require('../src/grpc_extension'); describe('server', function() { describe('constructor', function() { it('should work with no arguments', function() { assert.doesNotThrow(function() { new grpc.Server(); }); }); it('should work with an empty object argument', function() { assert.doesNotThrow(function() { new grpc.Server({}); }); }); it('should work without the new keyword', function() { var server; assert.doesNotThrow(function() { server = grpc.Server(); }); assert(server instanceof grpc.Server); }); it('should only accept objects with string or int values', function() { assert.doesNotThrow(function() { new grpc.Server({'key' : 'value'}); }); assert.doesNotThrow(function() { new grpc.Server({'key' : 5}); }); assert.throws(function() { new grpc.Server({'key' : null}); }); assert.throws(function() { new grpc.Server({'key' : new Date()}); }); }); }); describe('addHttp2Port', function() { var server; before(function() { server = new grpc.Server(); }); it('should bind to an unused port', function() { var port; assert.doesNotThrow(function() { port = server.addHttp2Port('0.0.0.0:0', grpc.ServerCredentials.createInsecure()); }); assert(port > 0); }); it('should bind to an unused port with ssl credentials', function() { var port; var key_path = path.join(__dirname, '../test/data/server1.key'); var pem_path = path.join(__dirname, '../test/data/server1.pem'); var key_data = fs.readFileSync(key_path); var pem_data = fs.readFileSync(pem_path); var creds = grpc.ServerCredentials.createSsl(null, [{private_key: key_data, cert_chain: pem_data}]); assert.doesNotThrow(function() { port = server.addHttp2Port('0.0.0.0:0', creds); }); assert(port > 0); }); }); describe('addSecureHttp2Port', function() { var server; before(function() { server = new grpc.Server(); }); }); describe('start', function() { var server; before(function() { server = new grpc.Server(); server.addHttp2Port('0.0.0.0:0', grpc.ServerCredentials.createInsecure()); }); after(function() { server.forceShutdown(); }); it('should start without error', function() { assert.doesNotThrow(function() { server.start(); }); }); }); describe('shutdown', function() { var server; beforeEach(function() { server = new grpc.Server(); server.addHttp2Port('0.0.0.0:0', grpc.ServerCredentials.createInsecure()); server.start(); }); afterEach(function() { server.forceShutdown(); }); it('tryShutdown should shutdown successfully', function(done) { server.tryShutdown(done); }); it('forceShutdown should shutdown successfully', function() { server.forceShutdown(); }); it('tryShutdown should be idempotent', function(done) { server.tryShutdown(done); server.tryShutdown(function() {}); }); it('forceShutdown should be idempotent', function() { server.forceShutdown(); server.forceShutdown(); }); it('forceShutdown should trigger tryShutdown', function(done) { server.tryShutdown(done); server.forceShutdown(); }); }); }); grpc-1.3.2/src/node/test/surface_test.js000066400000000000000000001267301310511640000201700ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; var assert = require('assert'); var _ = require('lodash'); var surface_client = require('../src/client.js'); var common = require('../src/common'); var ProtoBuf = require('protobufjs'); var grpc = require('..'); var math_proto = ProtoBuf.loadProtoFile(__dirname + '/../../proto/math/math.proto'); var mathService = math_proto.lookup('math.Math'); var mathServiceAttrs = grpc.loadObject( mathService, common.defaultGrpcOptions).service; /** * This is used for testing functions with multiple asynchronous calls that * can happen in different orders. This should be passed the number of async * function invocations that can occur last, and each of those should call this * function's return value * @param {function()} done The function that should be called when a test is * complete. * @param {number} count The number of calls to the resulting function if the * test passes. * @return {function()} The function that should be called at the end of each * sequence of asynchronous functions. */ function multiDone(done, count) { return function() { count -= 1; if (count <= 0) { done(); } }; } var server_insecure_creds = grpc.ServerCredentials.createInsecure(); describe('File loader', function() { it('Should load a proto file by default', function() { assert.doesNotThrow(function() { grpc.load(__dirname + '/test_service.proto'); }); }); it('Should load a proto file with the proto format', function() { assert.doesNotThrow(function() { grpc.load(__dirname + '/test_service.proto', 'proto'); }); }); it('Should load a json file with the json format', function() { assert.doesNotThrow(function() { grpc.load(__dirname + '/test_service.json', 'json'); }); }); }); describe('surface Server', function() { var server; beforeEach(function() { server = new grpc.Server(); }); afterEach(function() { server.forceShutdown(); }); it('should error if started twice', function() { server.start(); assert.throws(function() { server.start(); }); }); it('should error if a port is bound after the server starts', function() { server.start(); assert.throws(function() { server.bind('localhost:0', grpc.ServerCredentials.createInsecure()); }); }); it('should successfully shutdown if tryShutdown is called', function(done) { server.start(); server.tryShutdown(done); }); }); describe('Server.prototype.addProtoService', function() { var server; var dummyImpls = { 'div': function() {}, 'divMany': function() {}, 'fib': function() {}, 'sum': function() {} }; beforeEach(function() { server = new grpc.Server(); }); afterEach(function() { server.forceShutdown(); }); it('Should succeed with a single proto service', function() { assert.doesNotThrow(function() { server.addProtoService(mathService, dummyImpls); }); }); it('Should succeed with a single service attributes object', function() { assert.doesNotThrow(function() { server.addProtoService(mathServiceAttrs, dummyImpls); }); }); }); describe('Server.prototype.addService', function() { var server; var dummyImpls = { 'div': function() {}, 'divMany': function() {}, 'fib': function() {}, 'sum': function() {} }; beforeEach(function() { server = new grpc.Server(); }); afterEach(function() { server.forceShutdown(); }); it('Should succeed with a single service', function() { assert.doesNotThrow(function() { server.addService(mathServiceAttrs, dummyImpls); }); }); it('Should fail with conflicting method names', function() { server.addService(mathServiceAttrs, dummyImpls); assert.throws(function() { server.addService(mathServiceAttrs, dummyImpls); }); }); it('Should allow method names as originally written', function() { var altDummyImpls = { 'Div': function() {}, 'DivMany': function() {}, 'Fib': function() {}, 'Sum': function() {} }; assert.doesNotThrow(function() { server.addProtoService(mathService, altDummyImpls); }); }); it('Should have a conflict between name variations', function() { /* This is really testing that both name variations are actually used, by checking that the method actually gets registered, for the corresponding function, in both cases */ var altDummyImpls = { 'Div': function() {}, 'DivMany': function() {}, 'Fib': function() {}, 'Sum': function() {} }; server.addProtoService(mathService, altDummyImpls); assert.throws(function() { server.addProtoService(mathService, dummyImpls); }); }); it('Should fail if the server has been started', function() { server.start(); assert.throws(function() { server.addService(mathServiceAttrs, dummyImpls); }); }); describe('Default handlers', function() { var client; beforeEach(function() { server.addService(mathServiceAttrs, {}); var port = server.bind('localhost:0', server_insecure_creds); var Client = grpc.loadObject(mathService); client = new Client('localhost:' + port, grpc.credentials.createInsecure()); server.start(); }); it('should respond to a unary call with UNIMPLEMENTED', function(done) { client.div({divisor: 4, dividend: 3}, function(error, response) { assert(error); assert.strictEqual(error.code, grpc.status.UNIMPLEMENTED); done(); }); }); it('should respond to a client stream with UNIMPLEMENTED', function(done) { var call = client.sum(function(error, respones) { assert(error); assert.strictEqual(error.code, grpc.status.UNIMPLEMENTED); done(); }); call.end(); }); it('should respond to a server stream with UNIMPLEMENTED', function(done) { var call = client.fib({limit: 5}); call.on('data', function(value) { assert.fail('No messages expected'); }); call.on('error', function(err) { assert.strictEqual(err.code, grpc.status.UNIMPLEMENTED); done(); }); call.on('error', function(status) { /* Do nothing */ }); }); it('should respond to a bidi call with UNIMPLEMENTED', function(done) { var call = client.divMany(); call.on('data', function(value) { assert.fail('No messages expected'); }); call.on('error', function(err) { assert.strictEqual(err.code, grpc.status.UNIMPLEMENTED); done(); }); call.on('error', function(status) { /* Do nothing */ }); call.end(); }); }); }); describe('Client constructor building', function() { var illegal_service_attrs = { $method : { path: '/illegal/$method', requestStream: false, responseStream: false, requestSerialize: _.identity, requestDeserialize: _.identity, responseSerialize: _.identity, responseDeserialize: _.identity } }; it('Should reject method names starting with $', function() { assert.throws(function() { grpc.makeGenericClientConstructor(illegal_service_attrs); }, /\$/); }); }); describe('waitForClientReady', function() { var server; var port; var Client; var client; before(function() { server = new grpc.Server(); port = server.bind('localhost:0', grpc.ServerCredentials.createInsecure()); server.start(); Client = grpc.loadObject(mathService); }); beforeEach(function() { client = new Client('localhost:' + port, grpc.credentials.createInsecure()); }); after(function() { server.forceShutdown(); }); it('should complete when called alone', function(done) { grpc.waitForClientReady(client, Infinity, function(error) { assert.ifError(error); done(); }); }); it('should complete when a call is initiated', function(done) { grpc.waitForClientReady(client, Infinity, function(error) { assert.ifError(error); done(); }); var call = client.div({}, function(err, response) {}); call.cancel(); }); it('should complete if called more than once', function(done) { done = multiDone(done, 2); grpc.waitForClientReady(client, Infinity, function(error) { assert.ifError(error); done(); }); grpc.waitForClientReady(client, Infinity, function(error) { assert.ifError(error); done(); }); }); it('should complete if called when already ready', function(done) { grpc.waitForClientReady(client, Infinity, function(error) { assert.ifError(error); grpc.waitForClientReady(client, Infinity, function(error) { assert.ifError(error); done(); }); }); }); it('should time out if the server does not exist', function(done) { var bad_client = new Client('nonexistent_hostname', grpc.credentials.createInsecure()); var deadline = new Date(); deadline.setSeconds(deadline.getSeconds() + 1); grpc.waitForClientReady(bad_client, deadline, function(error) { assert(error); done(); }); }); }); describe('Echo service', function() { var server; var client; before(function() { var test_proto = ProtoBuf.loadProtoFile(__dirname + '/echo_service.proto'); var echo_service = test_proto.lookup('EchoService'); var Client = grpc.loadObject(echo_service); server = new grpc.Server(); server.addService(Client.service, { echo: function(call, callback) { callback(null, call.request); } }); var port = server.bind('localhost:0', server_insecure_creds); client = new Client('localhost:' + port, grpc.credentials.createInsecure()); server.start(); }); after(function() { server.forceShutdown(); }); it('should echo the recieved message directly', function(done) { client.echo({value: 'test value', value2: 3}, function(error, response) { assert.ifError(error); assert.deepEqual(response, {value: 'test value', value2: 3}); done(); }); }); it('Should convert an undefined argument to default values', function(done) { client.echo(undefined, function(error, response) { assert.ifError(error); assert.deepEqual(response, {value: '', value2: 0}); done(); }); }); }); describe('Generic client and server', function() { function toString(val) { return val.toString(); } function toBuffer(str) { return new Buffer(str); } var string_service_attrs = { 'capitalize' : { path: '/string/capitalize', requestStream: false, responseStream: false, requestSerialize: toBuffer, requestDeserialize: toString, responseSerialize: toBuffer, responseDeserialize: toString } }; describe('String client and server', function() { var client; var server; before(function() { server = new grpc.Server(); server.addService(string_service_attrs, { capitalize: function(call, callback) { callback(null, _.capitalize(call.request)); } }); var port = server.bind('localhost:0', server_insecure_creds); server.start(); var Client = grpc.makeGenericClientConstructor(string_service_attrs); client = new Client('localhost:' + port, grpc.credentials.createInsecure()); }); after(function() { server.forceShutdown(); }); it('Should respond with a capitalized string', function(done) { client.capitalize('abc', function(err, response) { assert.ifError(err); assert.strictEqual(response, 'Abc'); done(); }); }); }); }); describe('Server-side getPeer', function() { function toString(val) { return val.toString(); } function toBuffer(str) { return new Buffer(str); } var string_service_attrs = { 'getPeer' : { path: '/string/getPeer', requestStream: false, responseStream: false, requestSerialize: toBuffer, requestDeserialize: toString, responseSerialize: toBuffer, responseDeserialize: toString } }; var client; var server; before(function() { server = new grpc.Server(); server.addService(string_service_attrs, { getPeer: function(call, callback) { try { callback(null, call.getPeer()); } catch (e) { call.emit('error', e); } } }); var port = server.bind('localhost:0', server_insecure_creds); server.start(); var Client = grpc.makeGenericClientConstructor(string_service_attrs); client = new Client('localhost:' + port, grpc.credentials.createInsecure()); }); after(function() { server.forceShutdown(); }); it('should respond with a string representing the client', function(done) { client.getPeer('', function(err, response) { assert.ifError(err); // We don't expect a specific value, just that it worked without error done(); }); }); }); describe('Echo metadata', function() { var client; var server; var metadata; before(function() { var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto'); var test_service = test_proto.lookup('TestService'); var Client = grpc.loadObject(test_service); server = new grpc.Server(); server.addService(Client.service, { unary: function(call, cb) { call.sendMetadata(call.metadata); cb(null, {}); }, clientStream: function(stream, cb){ stream.on('data', function(data) {}); stream.on('end', function() { stream.sendMetadata(stream.metadata); cb(null, {}); }); }, serverStream: function(stream) { stream.sendMetadata(stream.metadata); stream.end(); }, bidiStream: function(stream) { stream.on('data', function(data) {}); stream.on('end', function() { stream.sendMetadata(stream.metadata); stream.end(); }); } }); var port = server.bind('localhost:0', server_insecure_creds); client = new Client('localhost:' + port, grpc.credentials.createInsecure()); server.start(); metadata = new grpc.Metadata(); metadata.set('key', 'value'); }); after(function() { server.forceShutdown(); }); it('with unary call', function(done) { var call = client.unary({}, metadata, function(err, data) { assert.ifError(err); }); call.on('metadata', function(metadata) { assert.deepEqual(metadata.get('key'), ['value']); done(); }); }); it('with client stream call', function(done) { var call = client.clientStream(metadata, function(err, data) { assert.ifError(err); }); call.on('metadata', function(metadata) { assert.deepEqual(metadata.get('key'), ['value']); done(); }); call.end(); }); it('with server stream call', function(done) { var call = client.serverStream({}, metadata); call.on('data', function() {}); call.on('metadata', function(metadata) { assert.deepEqual(metadata.get('key'), ['value']); done(); }); }); it('with bidi stream call', function(done) { var call = client.bidiStream(metadata); call.on('data', function() {}); call.on('metadata', function(metadata) { assert.deepEqual(metadata.get('key'), ['value']); done(); }); call.end(); }); it('shows the correct user-agent string', function(done) { var version = require('../../../package.json').version; var call = client.unary({}, metadata, function(err, data) { assert.ifError(err); }); call.on('metadata', function(metadata) { assert(_.startsWith(metadata.get('user-agent')[0], 'grpc-node/' + version)); done(); }); }); it('properly handles duplicate values', function(done) { var dup_metadata = metadata.clone(); dup_metadata.add('key', 'value2'); var call = client.unary({}, dup_metadata, function(err, data) {assert.ifError(err); }); call.on('metadata', function(resp_metadata) { // Two arrays are equal iff their symmetric difference is empty assert.deepEqual(_.xor(dup_metadata.get('key'), resp_metadata.get('key')), []); done(); }); }); }); describe('Client malformed response handling', function() { var server; var client; var badArg = new Buffer([0xFF]); before(function() { var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto'); var test_service = test_proto.lookup('TestService'); var malformed_test_service = { unary: { path: '/TestService/Unary', requestStream: false, responseStream: false, requestDeserialize: _.identity, responseSerialize: _.identity }, clientStream: { path: '/TestService/ClientStream', requestStream: true, responseStream: false, requestDeserialize: _.identity, responseSerialize: _.identity }, serverStream: { path: '/TestService/ServerStream', requestStream: false, responseStream: true, requestDeserialize: _.identity, responseSerialize: _.identity }, bidiStream: { path: '/TestService/BidiStream', requestStream: true, responseStream: true, requestDeserialize: _.identity, responseSerialize: _.identity } }; server = new grpc.Server(); server.addService(malformed_test_service, { unary: function(call, cb) { cb(null, badArg); }, clientStream: function(stream, cb) { stream.on('data', function() {/* Ignore requests */}); stream.on('end', function() { cb(null, badArg); }); }, serverStream: function(stream) { stream.write(badArg); stream.end(); }, bidiStream: function(stream) { stream.on('data', function() { // Ignore requests stream.write(badArg); }); stream.on('end', function() { stream.end(); }); } }); var port = server.bind('localhost:0', server_insecure_creds); var Client = grpc.loadObject(test_service); client = new Client('localhost:' + port, grpc.credentials.createInsecure()); server.start(); }); after(function() { server.forceShutdown(); }); it('should get an INTERNAL status with a unary call', function(done) { client.unary({}, function(err, data) { assert(err); assert.strictEqual(err.code, grpc.status.INTERNAL); done(); }); }); it('should get an INTERNAL status with a client stream call', function(done) { var call = client.clientStream(function(err, data) { assert(err); assert.strictEqual(err.code, grpc.status.INTERNAL); done(); }); call.write({}); call.end(); }); it('should get an INTERNAL status with a server stream call', function(done) { var call = client.serverStream({}); call.on('data', function(){}); call.on('error', function(err) { assert.strictEqual(err.code, grpc.status.INTERNAL); done(); }); }); it('should get an INTERNAL status with a bidi stream call', function(done) { var call = client.bidiStream(); call.on('data', function(){}); call.on('error', function(err) { assert.strictEqual(err.code, grpc.status.INTERNAL); done(); }); call.write({}); call.end(); }); }); describe('Server serialization failure handling', function() { function serializeFail(obj) { throw new Error('Serialization failed'); } var client; var server; before(function() { var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto'); var test_service = test_proto.lookup('TestService'); var malformed_test_service = { unary: { path: '/TestService/Unary', requestStream: false, responseStream: false, requestDeserialize: _.identity, responseSerialize: serializeFail }, clientStream: { path: '/TestService/ClientStream', requestStream: true, responseStream: false, requestDeserialize: _.identity, responseSerialize: serializeFail }, serverStream: { path: '/TestService/ServerStream', requestStream: false, responseStream: true, requestDeserialize: _.identity, responseSerialize: serializeFail }, bidiStream: { path: '/TestService/BidiStream', requestStream: true, responseStream: true, requestDeserialize: _.identity, responseSerialize: serializeFail } }; server = new grpc.Server(); server.addService(malformed_test_service, { unary: function(call, cb) { cb(null, {}); }, clientStream: function(stream, cb) { stream.on('data', function() {/* Ignore requests */}); stream.on('end', function() { cb(null, {}); }); }, serverStream: function(stream) { stream.write({}); stream.end(); }, bidiStream: function(stream) { stream.on('data', function() { // Ignore requests stream.write({}); }); stream.on('end', function() { stream.end(); }); } }); var port = server.bind('localhost:0', server_insecure_creds); var Client = grpc.loadObject(test_service); client = new Client('localhost:' + port, grpc.credentials.createInsecure()); server.start(); }); after(function() { server.forceShutdown(); }); it('should get an INTERNAL status with a unary call', function(done) { client.unary({}, function(err, data) { assert(err); assert.strictEqual(err.code, grpc.status.INTERNAL); done(); }); }); it('should get an INTERNAL status with a client stream call', function(done) { var call = client.clientStream(function(err, data) { assert(err); assert.strictEqual(err.code, grpc.status.INTERNAL); done(); }); call.write({}); call.end(); }); it('should get an INTERNAL status with a server stream call', function(done) { var call = client.serverStream({}); call.on('data', function(){}); call.on('error', function(err) { assert.strictEqual(err.code, grpc.status.INTERNAL); done(); }); }); it('should get an INTERNAL status with a bidi stream call', function(done) { var call = client.bidiStream(); call.on('data', function(){}); call.on('error', function(err) { assert.strictEqual(err.code, grpc.status.INTERNAL); done(); }); call.write({}); call.end(); }); }); describe('Other conditions', function() { var Client; var client; var server; var port; before(function() { var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto'); var test_service = test_proto.lookup('TestService'); Client = grpc.loadObject(test_service); server = new grpc.Server(); var trailer_metadata = new grpc.Metadata(); trailer_metadata.add('trailer-present', 'yes'); server.addService(Client.service, { unary: function(call, cb) { var req = call.request; if (req.error) { cb({code: grpc.status.UNKNOWN, details: 'Requested error'}, null, trailer_metadata); } else { cb(null, {count: 1}, trailer_metadata); } }, clientStream: function(stream, cb){ var count = 0; var errored; stream.on('data', function(data) { if (data.error) { errored = true; cb(new Error('Requested error'), null, trailer_metadata); } else { count += 1; } }); stream.on('end', function() { if (!errored) { cb(null, {count: count}, trailer_metadata); } }); }, serverStream: function(stream) { var req = stream.request; if (req.error) { var err = {code: grpc.status.UNKNOWN, details: 'Requested error'}; err.metadata = trailer_metadata; stream.emit('error', err); } else { for (var i = 0; i < 5; i++) { stream.write({count: i}); } stream.end(trailer_metadata); } }, bidiStream: function(stream) { var count = 0; stream.on('data', function(data) { if (data.error) { var err = new Error('Requested error'); err.metadata = trailer_metadata.clone(); err.metadata.add('count', '' + count); stream.emit('error', err); } else { stream.write({count: count}); count += 1; } }); stream.on('end', function() { stream.end(trailer_metadata); }); } }); port = server.bind('localhost:0', server_insecure_creds); client = new Client('localhost:' + port, grpc.credentials.createInsecure()); server.start(); }); after(function() { server.forceShutdown(); }); it('channel.getTarget should be available', function() { assert.strictEqual(typeof grpc.getClientChannel(client).getTarget(), 'string'); }); it('client should be able to pause and resume a stream', function(done) { var call = client.bidiStream(); call.on('data', function(data) { assert(data.count < 3); call.pause(); setTimeout(function() { call.resume(); }, 10); }); call.on('end', function() { done(); }); call.write({}); call.write({}); call.write({}); call.end(); }); describe('Server recieving bad input', function() { var misbehavingClient; var badArg = new Buffer([0xFF]); before(function() { var test_service_attrs = { unary: { path: '/TestService/Unary', requestStream: false, responseStream: false, requestSerialize: _.identity, responseDeserialize: _.identity }, clientStream: { path: '/TestService/ClientStream', requestStream: true, responseStream: false, requestSerialize: _.identity, responseDeserialize: _.identity }, serverStream: { path: '/TestService/ServerStream', requestStream: false, responseStream: true, requestSerialize: _.identity, responseDeserialize: _.identity }, bidiStream: { path: '/TestService/BidiStream', requestStream: true, responseStream: true, requestSerialize: _.identity, responseDeserialize: _.identity } }; var Client = surface_client.makeClientConstructor(test_service_attrs, 'TestService'); misbehavingClient = new Client('localhost:' + port, grpc.credentials.createInsecure()); }); it('should respond correctly to a unary call', function(done) { misbehavingClient.unary(badArg, function(err, data) { assert(err); assert.strictEqual(err.code, grpc.status.INTERNAL); done(); }); }); it('should respond correctly to a client stream', function(done) { var call = misbehavingClient.clientStream(function(err, data) { assert(err); assert.strictEqual(err.code, grpc.status.INTERNAL); done(); }); call.write(badArg); // TODO(mlumish): Remove call.end() call.end(); }); it('should respond correctly to a server stream', function(done) { var call = misbehavingClient.serverStream(badArg); call.on('data', function(data) { assert.fail(data, null, 'Unexpected data', '==='); }); call.on('error', function(err) { assert.strictEqual(err.code, grpc.status.INTERNAL); done(); }); }); it('should respond correctly to a bidi stream', function(done) { var call = misbehavingClient.bidiStream(); call.on('data', function(data) { assert.fail(data, null, 'Unexpected data', '==='); }); call.on('error', function(err) { assert.strictEqual(err.code, grpc.status.INTERNAL); done(); }); call.write(badArg); // TODO(mlumish): Remove call.end() call.end(); }); }); describe('Trailing metadata', function() { it('should be present when a unary call succeeds', function(done) { var call = client.unary({error: false}, function(err, data) { assert.ifError(err); }); call.on('status', function(status) { assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); it('should be present when a unary call fails', function(done) { var call = client.unary({error: true}, function(err, data) { assert(err); }); call.on('status', function(status) { assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); it('should be present when a client stream call succeeds', function(done) { var call = client.clientStream(function(err, data) { assert.ifError(err); }); call.write({error: false}); call.write({error: false}); call.end(); call.on('status', function(status) { assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); it('should be present when a client stream call fails', function(done) { var call = client.clientStream(function(err, data) { assert(err); }); call.write({error: false}); call.write({error: true}); call.end(); call.on('status', function(status) { assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); it('should be present when a server stream call succeeds', function(done) { var call = client.serverStream({error: false}); call.on('data', function(){}); call.on('status', function(status) { assert.strictEqual(status.code, grpc.status.OK); assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); it('should be present when a server stream call fails', function(done) { var call = client.serverStream({error: true}); call.on('data', function(){}); call.on('error', function(error) { assert.deepEqual(error.metadata.get('trailer-present'), ['yes']); done(); }); }); it('should be present when a bidi stream succeeds', function(done) { var call = client.bidiStream(); call.write({error: false}); call.write({error: false}); call.end(); call.on('data', function(){}); call.on('status', function(status) { assert.strictEqual(status.code, grpc.status.OK); assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); it('should be present when a bidi stream fails', function(done) { var call = client.bidiStream(); call.write({error: false}); call.write({error: true}); call.end(); call.on('data', function(){}); call.on('error', function(error) { assert.deepEqual(error.metadata.get('trailer-present'), ['yes']); done(); }); }); }); describe('Error object should contain the status', function() { it('for a unary call', function(done) { client.unary({error: true}, function(err, data) { assert(err); assert.strictEqual(err.code, grpc.status.UNKNOWN); assert.strictEqual(err.message, 'Requested error'); done(); }); }); it('for a client stream call', function(done) { var call = client.clientStream(function(err, data) { assert(err); assert.strictEqual(err.code, grpc.status.UNKNOWN); assert.strictEqual(err.message, 'Requested error'); done(); }); call.write({error: false}); call.write({error: true}); call.end(); }); it('for a server stream call', function(done) { var call = client.serverStream({error: true}); call.on('data', function(){}); call.on('error', function(error) { assert.strictEqual(error.code, grpc.status.UNKNOWN); assert.strictEqual(error.message, 'Requested error'); done(); }); }); it('for a bidi stream call', function(done) { var call = client.bidiStream(); call.write({error: false}); call.write({error: true}); call.end(); call.on('data', function(){}); call.on('error', function(error) { assert.strictEqual(error.code, grpc.status.UNKNOWN); assert.strictEqual(error.message, 'Requested error'); done(); }); }); }); describe('call.getPeer should return the peer', function() { it('for a unary call', function(done) { var call = client.unary({error: false}, function(err, data) { assert.ifError(err); done(); }); assert.strictEqual(typeof call.getPeer(), 'string'); }); it('for a client stream call', function(done) { var call = client.clientStream(function(err, data) { assert.ifError(err); done(); }); assert.strictEqual(typeof call.getPeer(), 'string'); call.write({error: false}); call.end(); }); it('for a server stream call', function(done) { var call = client.serverStream({error: false}); assert.strictEqual(typeof call.getPeer(), 'string'); call.on('data', function(){}); call.on('status', function(status) { assert.strictEqual(status.code, grpc.status.OK); done(); }); }); it('for a bidi stream call', function(done) { var call = client.bidiStream(); assert.strictEqual(typeof call.getPeer(), 'string'); call.write({error: false}); call.end(); call.on('data', function(){}); call.on('status', function(status) { done(); }); }); }); }); describe('Call propagation', function() { var proxy; var proxy_impl; var Client; var client; var server; before(function() { var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto'); var test_service = test_proto.lookup('TestService'); server = new grpc.Server(); Client = grpc.loadObject(test_service); server.addService(Client.service, { unary: function(call) {}, clientStream: function(stream) {}, serverStream: function(stream) {}, bidiStream: function(stream) {} }); var port = server.bind('localhost:0', server_insecure_creds); client = new Client('localhost:' + port, grpc.credentials.createInsecure()); server.start(); }); after(function() { server.forceShutdown(); }); beforeEach(function() { proxy = new grpc.Server(); proxy_impl = { unary: function(call) {}, clientStream: function(stream) {}, serverStream: function(stream) {}, bidiStream: function(stream) {} }; }); afterEach(function() { proxy.forceShutdown(); }); describe('Cancellation', function() { it('With a unary call', function(done) { done = multiDone(done, 2); var call; proxy_impl.unary = function(parent, callback) { client.unary(parent.request, {parent: parent}, function(err, value) { try { assert(err); assert.strictEqual(err.code, grpc.status.CANCELLED); } finally { callback(err, value); done(); } }); call.cancel(); }; proxy.addService(Client.service, proxy_impl); var proxy_port = proxy.bind('localhost:0', server_insecure_creds); proxy.start(); var proxy_client = new Client('localhost:' + proxy_port, grpc.credentials.createInsecure()); call = proxy_client.unary({}, function(err, value) { done(); }); }); it('With a client stream call', function(done) { done = multiDone(done, 2); var call; proxy_impl.clientStream = function(parent, callback) { client.clientStream({parent: parent}, function(err, value) { try { assert(err); assert.strictEqual(err.code, grpc.status.CANCELLED); } finally { callback(err, value); done(); } }); call.cancel(); }; proxy.addService(Client.service, proxy_impl); var proxy_port = proxy.bind('localhost:0', server_insecure_creds); proxy.start(); var proxy_client = new Client('localhost:' + proxy_port, grpc.credentials.createInsecure()); call = proxy_client.clientStream(function(err, value) { done(); }); }); it('With a server stream call', function(done) { done = multiDone(done, 2); var call; proxy_impl.serverStream = function(parent) { var child = client.serverStream(parent.request, {parent: parent}); child.on('data', function() {}); child.on('error', function(err) { assert(err); assert.strictEqual(err.code, grpc.status.CANCELLED); done(); }); call.cancel(); }; proxy.addService(Client.service, proxy_impl); var proxy_port = proxy.bind('localhost:0', server_insecure_creds); proxy.start(); var proxy_client = new Client('localhost:' + proxy_port, grpc.credentials.createInsecure()); call = proxy_client.serverStream({}); call.on('data', function() {}); call.on('error', function(err) { done(); }); }); it('With a bidi stream call', function(done) { done = multiDone(done, 2); var call; proxy_impl.bidiStream = function(parent) { var child = client.bidiStream({parent: parent}); child.on('data', function() {}); child.on('error', function(err) { assert(err); assert.strictEqual(err.code, grpc.status.CANCELLED); done(); }); call.cancel(); }; proxy.addService(Client.service, proxy_impl); var proxy_port = proxy.bind('localhost:0', server_insecure_creds); proxy.start(); var proxy_client = new Client('localhost:' + proxy_port, grpc.credentials.createInsecure()); call = proxy_client.bidiStream(); call.on('data', function() {}); call.on('error', function(err) { done(); }); }); }); describe('Deadline', function() { /* jshint bitwise:false */ var deadline_flags = (grpc.propagate.DEFAULTS & ~grpc.propagate.CANCELLATION); it('With a client stream call', function(done) { done = multiDone(done, 2); proxy_impl.clientStream = function(parent, callback) { var options = {parent: parent, propagate_flags: deadline_flags}; client.clientStream(options, function(err, value) { try { assert(err); assert(err.code === grpc.status.DEADLINE_EXCEEDED || err.code === grpc.status.INTERNAL); } finally { callback(err, value); done(); } }); }; proxy.addService(Client.service, proxy_impl); var proxy_port = proxy.bind('localhost:0', server_insecure_creds); proxy.start(); var proxy_client = new Client('localhost:' + proxy_port, grpc.credentials.createInsecure()); var deadline = new Date(); deadline.setSeconds(deadline.getSeconds() + 1); proxy_client.clientStream({deadline: deadline}, function(err, value) { done(); }); }); it('With a bidi stream call', function(done) { done = multiDone(done, 2); proxy_impl.bidiStream = function(parent) { var child = client.bidiStream( {parent: parent, propagate_flags: deadline_flags}); child.on('data', function() {}); child.on('error', function(err) { assert(err); assert(err.code === grpc.status.DEADLINE_EXCEEDED || err.code === grpc.status.INTERNAL); done(); }); }; proxy.addService(Client.service, proxy_impl); var proxy_port = proxy.bind('localhost:0', server_insecure_creds); proxy.start(); var proxy_client = new Client('localhost:' + proxy_port, grpc.credentials.createInsecure()); var deadline = new Date(); deadline.setSeconds(deadline.getSeconds() + 1); var call = proxy_client.bidiStream({deadline: deadline}); call.on('data', function() {}); call.on('error', function(err) { done(); }); }); }); }); describe('Cancelling surface client', function() { var client; var server; before(function() { server = new grpc.Server(); server.addService(mathServiceAttrs, { 'div': function(stream) {}, 'divMany': function(stream) {}, 'fib': function(stream) {}, 'sum': function(stream) {} }); var port = server.bind('localhost:0', server_insecure_creds); var Client = surface_client.makeClientConstructor(mathServiceAttrs); client = new Client('localhost:' + port, grpc.credentials.createInsecure()); server.start(); }); after(function() { server.forceShutdown(); }); it('Should correctly cancel a unary call', function(done) { var call = client.div({'divisor': 0, 'dividend': 0}, function(err, resp) { assert.strictEqual(err.code, surface_client.status.CANCELLED); done(); }); call.cancel(); }); it('Should correctly cancel a client stream call', function(done) { var call = client.sum(function(err, resp) { assert.strictEqual(err.code, surface_client.status.CANCELLED); done(); }); call.cancel(); }); it('Should correctly cancel a server stream call', function(done) { var call = client.fib({'limit': 5}); call.on('data', function() {}); call.on('error', function(error) { assert.strictEqual(error.code, surface_client.status.CANCELLED); done(); }); call.cancel(); }); it('Should correctly cancel a bidi stream call', function(done) { var call = client.divMany(); call.on('data', function() {}); call.on('error', function(error) { assert.strictEqual(error.code, surface_client.status.CANCELLED); done(); }); call.cancel(); }); }); grpc-1.3.2/src/node/test/test_messages.proto000066400000000000000000000037401310511640000210710ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; message LongValues { int64 int_64 = 1; uint64 uint_64 = 2; sint64 sint_64 = 3; fixed64 fixed_64 = 4; sfixed64 sfixed_64 = 5; } message SequenceValues { bytes bytes_field = 1; repeated int32 repeated_field = 2; } message OneOfValues { oneof oneof_choice { int32 int_choice = 1; string string_choice = 2; } } enum TestEnum { ZERO = 0; ONE = 1; TWO = 2; } message EnumValues { TestEnum enum_value = 1; } grpc-1.3.2/src/node/test/test_service.json000066400000000000000000000025771310511640000205370ustar00rootroot00000000000000{ "package": null, "messages": [ { "name": "Request", "fields": [ { "rule": "optional", "type": "bool", "name": "error", "id": 1 } ] }, { "name": "Response", "fields": [ { "rule": "optional", "type": "int32", "name": "count", "id": 1 } ] } ], "services": [ { "name": "TestService", "options": {}, "rpc": { "Unary": { "request": "Request", "response": "Response", "options": {} }, "ClientStream": { "request": "Request", "response": "Response", "options": {} }, "ServerStream": { "request": "Request", "response": "Response", "options": {} }, "BidiStream": { "request": "Request", "response": "Response", "options": {} } } } ] }grpc-1.3.2/src/node/test/test_service.proto000066400000000000000000000035771310511640000207320ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; message Request { bool error = 1; } message Response { int32 count = 1; } service TestService { rpc Unary (Request) returns (Response) { } rpc ClientStream (stream Request) returns (Response) { } rpc ServerStream (Request) returns (stream Response) { } rpc BidiStream (stream Request) returns (stream Response) { } } grpc-1.3.2/src/node/tools/000077500000000000000000000000001310511640000153135ustar00rootroot00000000000000grpc-1.3.2/src/node/tools/bin/000077500000000000000000000000001310511640000160635ustar00rootroot00000000000000grpc-1.3.2/src/node/tools/bin/protoc.js000077500000000000000000000044441310511640000177400ustar00rootroot00000000000000#!/usr/bin/env node /* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** * This file is required because package.json cannot reference a file that * is not distributed with the package, and we use node-pre-gyp to distribute * the protoc binary */ 'use strict'; var path = require('path'); var execFile = require('child_process').execFile; var exe_ext = process.platform === 'win32' ? '.exe' : ''; var protoc = path.resolve(__dirname, 'protoc' + exe_ext); var plugin = path.resolve(__dirname, 'grpc_node_plugin' + exe_ext); var args = ['--plugin=protoc-gen-grpc=' + plugin].concat(process.argv.slice(2)); var child_process = execFile(protoc, args, function(error, stdout, stderr) { if (error) { throw error; } }); child_process.stdout.pipe(process.stdout); child_process.stderr.pipe(process.stderr); grpc-1.3.2/src/node/tools/bin/protoc_plugin.js000077500000000000000000000043471310511640000213200ustar00rootroot00000000000000#!/usr/bin/env node /* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** * This file is required because package.json cannot reference a file that * is not distributed with the package, and we use node-pre-gyp to distribute * the plugin binary */ 'use strict'; var path = require('path'); var execFile = require('child_process').execFile; var exe_ext = process.platform === 'win32' ? '.exe' : ''; var plugin = path.resolve(__dirname, 'grpc_node_plugin' + exe_ext); var child_process = execFile(plugin, process.argv.slice(2), {encoding: 'buffer'}, function(error, stdout, stderr) { if (error) { throw error; } }); process.stdin.pipe(child_process.stdin); child_process.stdout.pipe(process.stdout); child_process.stderr.pipe(process.stderr); grpc-1.3.2/src/node/tools/index.js000066400000000000000000000033201310511640000167560ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ 'use strict'; /** * package.json requires this file to be present. In the future, this can * export useful information about the included tools. */ module.exports = {}; grpc-1.3.2/src/node/tools/package.json000066400000000000000000000020361310511640000176020ustar00rootroot00000000000000{ "name": "grpc-tools", "version": "1.3.2", "author": "Google Inc.", "description": "Tools for developing with gRPC on Node.js", "homepage": "http://www.grpc.io/", "repository": { "type": "git", "url": "https://github.com/grpc/grpc.git" }, "bugs": "https://github.com/grpc/grpc/issues", "contributors": [ { "name": "Michael Lumish", "email": "mlumish@google.com" } ], "bin": { "grpc_tools_node_protoc": "./bin/protoc.js", "grpc_tools_node_protoc_plugin": "./bin/protoc_plugin.js" }, "scripts": { "install": "./node_modules/.bin/node-pre-gyp install" }, "bundledDependencies": ["node-pre-gyp"], "binary": { "module_name": "grpc_tools", "host": "https://storage.googleapis.com/", "remote_path": "grpc-precompiled-binaries/node/{name}/v{version}", "package_name": "{platform}-{arch}.tar.gz", "module_path": "bin" }, "files": [ "index.js", "bin/protoc.js", "bin/protoc_plugin.js", "bin/google/protobuf", "LICENSE" ], "main": "index.js" } grpc-1.3.2/src/objective-c/000077500000000000000000000000001310511640000154205ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec000066400000000000000000000137231310511640000236140ustar00rootroot00000000000000# This file has been automatically generated from a template file. # Please make modifications to # `templates/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec.template` # instead. This file can be regenerated from the template by running # `tools/buildgen/generate_projects.sh`. # CocoaPods podspec for the gRPC Proto Compiler Plugin # # Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Pod::Spec.new do |s| # This pod is only a utility that will be used by other pods _at install time_ (not at compile # time). Other pods can access it in their `prepare_command` script, under /. # Because CocoaPods installs pods in alphabetical order, beginning this pod's name with an # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed # before them. s.name = '!ProtoCompiler-gRPCPlugin' v = '1.3.2' s.version = v s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.' s.description = <<-DESC This podspec only downloads the gRPC protoc plugin so that local pods generating protos can use it in their invocation of protoc, as part of their prepare_command. The generated code will have a dependency on the gRPC Objective-C Proto runtime of the same version. The runtime can be obtained as the "gRPC-ProtoRPC" pod. DESC s.homepage = 'http://www.grpc.io' s.license = { :type => 'New BSD', :text => <<-LICENSE Copyright 2015, Google Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. LICENSE } s.authors = { 'The gRPC contributors' => 'grpc-packages@google.com' } repo = 'grpc/grpc' file = "grpc_objective_c_plugin-#{v}-macos-x86_64.zip" s.source = { :http => "https://github.com/#{repo}/releases/download/v#{v}/#{file}", # TODO(jcanizales): Add sha1 or sha256 # :sha1 => '??', } repo_root = '../..' plugin = 'grpc_objective_c_plugin' s.preserve_paths = plugin # Restrict the protoc version to the one supported by this plugin. s.dependency '!ProtoCompiler', '3.2.0' # For the Protobuf dependency not to complain: s.ios.deployment_target = '7.0' s.osx.deployment_target = '10.9' # Restrict the gRPC runtime version to the one supported by this plugin. s.dependency 'gRPC-ProtoRPC', v # This is only for local development of the plugin: If the Podfile brings this pod from a local # directory using `:path`, CocoaPods won't download the zip file and so the plugin won't be # present in this pod's directory. We use that knowledge to check for the existence of the file # and, if absent, compile the plugin from the local sources. s.prepare_command = <<-CMD if [ ! -f #{plugin} ]; then cd #{repo_root} # This will build the plugin and put it in #{repo_root}/bins/opt. # # TODO(jcanizales): I reckon make will try to use locally-installed libprotoc (headers and # library binary) if found, which _we do not want_. Find a way for this to always use the # sources in the repo. make #{plugin} cd - fi CMD end grpc-1.3.2/src/objective-c/!ProtoCompiler.podspec000066400000000000000000000146601310511640000216450ustar00rootroot00000000000000# Proto Compiler CocoaPods podspec # Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Pod::Spec.new do |s| # This pod is only a utility that will be used by other pods _at install time_ (not at compile # time). Other pods can access it in their `prepare_command` script, under /. # Because CocoaPods installs pods in alphabetical order, beginning this pod's name with an # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed # before them. s.name = '!ProtoCompiler' v = '3.2.0' s.version = v s.summary = 'The Protobuf Compiler (protoc) generates Objective-C files from .proto files' s.description = <<-DESC This podspec only downloads protoc so that local pods generating protos can execute it as part of their prepare_command. The generated code will have a dependency on the Protobuf Objective-C runtime of the same version. The runtime can be obtained as the "Protobuf" pod. DESC s.homepage = 'https://github.com/google/protobuf' s.license = { :type => 'New BSD', :text => <<-LICENSE This license applies to all parts of Protocol Buffers except the following: - Atomicops support for generic gcc, located in src/google/protobuf/stubs/atomicops_internals_generic_gcc.h. This file is copyrighted by Red Hat Inc. - Atomicops support for AIX/POWER, located in src/google/protobuf/stubs/atomicops_internals_power.h. This file is copyrighted by Bloomberg Finance LP. Copyright 2014, Google Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Code generated by the Protocol Buffer compiler is owned by the owner of the input file used when generating it. This code is not standalone and requires a support library to be linked with it. This support library is itself covered by the above license. LICENSE } # "The name and email addresses of the library maintainers, not the Podspec maintainer." s.authors = { 'The Protocol Buffers contributors' => 'protobuf@googlegroups.com' } repo = 'google/protobuf' file = "protoc-#{v}-osx-x86_64.zip" s.source = { :http => "https://github.com/#{repo}/releases/download/v#{v}/#{file}", # TODO(jcanizales): Add sha1 or sha256 # :sha1 => '??', } s.preserve_paths = 'protoc', 'google/**/*.proto' # Well-known protobuf types # Restrict the protobuf runtime version to the one supported by this version of protoc. s.dependency 'Protobuf', '~> 3.0' # For the Protobuf dependency not to complain: s.ios.deployment_target = '7.0' s.osx.deployment_target = '10.9' # This is only for local development of protoc: If the Podfile brings this pod from a local # directory using `:path`, CocoaPods won't download the zip file and so the compiler won't be # present in this pod's directory. We use that knowledge to check for the existence of the file # and, if absent, build it from the local sources. repo_root = '../..' plugin = 'grpc_objective_c_plugin' s.prepare_command = <<-CMD if [ ! -f bin/protoc ]; then cd #{repo_root} # This will build protoc from the Protobuf submodule of gRPC, and put it in # #{repo_root}/bins/opt/protobuf. # # TODO(jcanizales): Make won't build protoc from sources if one's locally installed, which # _we do not want_. Find a way for this to always build from source. make #{plugin} cd - else mv bin/protoc . mv include/google . fi CMD end grpc-1.3.2/src/objective-c/BoringSSL.podspec000066400000000000000000001367051310511640000206150ustar00rootroot00000000000000# BoringSSL CocoaPods podspec # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Pod::Spec.new do |s| s.name = 'BoringSSL' version = '8.0' s.version = version s.summary = 'BoringSSL is a fork of OpenSSL that is designed to meet Google’s needs.' # Adapted from the homepage: s.description = <<-DESC BoringSSL is a fork of OpenSSL that is designed to meet Google’s needs. Although BoringSSL is an open source project, it is not intended for general use, as OpenSSL is. We don’t recommend that third parties depend upon it. Doing so is likely to be frustrating because there are no guarantees of API stability. Only the latest version of this pod is supported, and every new version is a new major version. We update Google libraries and programs that use BoringSSL as needed when deciding to make API changes. This allows us to mostly avoid compromises in the name of compatibility. It works for us, but it may not work for you. As a Cocoapods pod, it has the advantage over OpenSSL's pods that the library doesn't need to be precompiled. This eliminates the 10 - 20 minutes of wait the first time a user does "pod install", lets it be used as a dynamic framework (pending solution of Cocoapods' issue #4605), and works with bitcode automatically. It's also thought to be smaller than OpenSSL (which takes 1MB - 2MB per ARM architecture), but we don't have specific numbers yet. BoringSSL arose because Google used OpenSSL for many years in various ways and, over time, built up a large number of patches that were maintained while tracking upstream OpenSSL. As Google’s product portfolio became more complex, more copies of OpenSSL sprung up and the effort involved in maintaining all these patches in multiple places was growing steadily. Currently BoringSSL is the SSL library in Chrome/Chromium, Android (but it’s not part of the NDK) and a number of other apps/programs. DESC s.homepage = 'https://boringssl.googlesource.com/boringssl/' s.documentation_url = 'https://commondatastorage.googleapis.com/chromium-boringssl-docs/headers.html' s.license = { :type => 'Mixed', :file => 'LICENSE' } # "The name and email addresses of the library maintainers, not the Podspec maintainer." s.authors = 'Adam Langley', 'David Benjamin', 'Matt Braithwaite' s.source = { :git => 'https://boringssl.googlesource.com/boringssl', :tag => "version_for_cocoapods_#{version}", # :commit => '4fec04b48406111cb88fdd8d196253adc54f7a31', } name = 'openssl' # When creating a dynamic framework, name it openssl.framework instead of BoringSSL.framework. # This lets users write their includes like `#include ` as opposed to `#include # `. s.module_name = name # When creating a dynamic framework, copy the headers under `include/openssl/` into the root of # the `Headers/` directory of the framework (i.e., not under `Headers/include/openssl`). # # TODO(jcanizales): Debug why this doesn't work on macOS. s.header_mappings_dir = 'include/openssl' # The above has an undesired effect when creating a static library: It forces users to write # includes like `#include `. `s.header_dir` adds a path prefix to that, and # because Cocoapods lets omit the pod name when including headers of static libraries, the # following lets users write `#include `. s.header_dir = name # The module map and umbrella header created automatically by Cocoapods don't work for C libraries # like this one. The following file, and a correct umbrella header, are created on the fly by the # `prepare_command` of this pod. s.module_map = 'include/openssl/module.modulemap' # We don't need to inhibit all warnings; only -Wno-shorten-64-to-32. But Cocoapods' linter doesn't # want that for some reason. s.compiler_flags = '-DOPENSSL_NO_ASM', '-GCC_WARN_INHIBIT_ALL_WARNINGS', '-w' s.requires_arc = false # Like many other C libraries, BoringSSL has its public headers under `include//` and its # sources and private headers in other directories outside `include/`. Cocoapods' linter doesn't # allow any header to be listed outside the `header_mappings_dir` (even though doing so works in # practice). Because we need our `header_mappings_dir` to be `include/openssl/` for the reason # mentioned above, we work around the linter limitation by dividing the pod into two subspecs, one # for public headers and the other for implementation. Each gets its own `header_mappings_dir`, # making the linter happy. s.subspec 'Interface' do |ss| ss.header_mappings_dir = 'include/openssl' ss.source_files = 'include/openssl/*.h' end s.subspec 'Implementation' do |ss| ss.header_mappings_dir = '.' ss.source_files = 'ssl/*.{h,c}', 'ssl/**/*.{h,c}', '*.{h,c}', 'crypto/*.{h,c}', 'crypto/**/*.{h,c}' ss.private_header_files = 'ssl/*.h', 'ssl/**/*.h', '*.h', 'crypto/*.h', 'crypto/**/*.h' ss.exclude_files = '**/*_test.*', '**/test_*.*', '**/test/*.*' ss.dependency "#{s.name}/Interface", version end s.prepare_command = <<-END_OF_COMMAND # Replace "const BIGNUM *I" in rsa.h with a lowercase i, as the former fails when including # OpenSSL in a Swift bridging header (complex.h defines "I", and it's as if the compiler # included it in every bridged header). sed -E -i '.back' 's/\\*I,/*i,/g' include/openssl/rsa.h # Replace `#include "../crypto/internal.h"` in e_tls.c with `#include "../internal.h"`. The # former assumes crypto/ is in the headers search path, which is hard to enforce when using # dynamic frameworks. The latters always works, being relative to the current file. sed -E -i '.back' 's/crypto\\///g' crypto/cipher/e_tls.c # Add a module map and an umbrella header cat > include/openssl/umbrella.h < include/openssl/module.modulemap < fails to compile when building a dynamic framework. libgit2 in # https://github.com/libgit2/libgit2/commit/1ddada422caf8e72ba97dca2568d2bf879fed5f2 and libvpx # in https://chromium.googlesource.com/webm/libvpx/+/1bec0c5a7e885ec792f6bb658eb3f34ad8f37b15 # work around it by removing the include. We need four of its macros, so we expand them here. sed -E -i '.back' '//d' include/openssl/bn.h sed -E -i '.back' 's/PRIu32/"u"/g' include/openssl/bn.h sed -E -i '.back' 's/PRIx32/"x"/g' include/openssl/bn.h sed -E -i '.back' 's/PRIu64/"llu"/g' include/openssl/bn.h sed -E -i '.back' 's/PRIx64/"llx"/g' include/openssl/bn.h # This is a bit ridiculous, but requiring people to install Go in order to build is slightly # more ridiculous IMO. To save you from scrolling, this is the last part of the podspec. # TODO(jcanizales): Translate err_data_generate.go into a Bash or Ruby script. cat > err_data.c < #include #include OPENSSL_COMPILE_ASSERT(ERR_LIB_NONE == 1, library_values_changed_1); OPENSSL_COMPILE_ASSERT(ERR_LIB_SYS == 2, library_values_changed_2); OPENSSL_COMPILE_ASSERT(ERR_LIB_BN == 3, library_values_changed_3); OPENSSL_COMPILE_ASSERT(ERR_LIB_RSA == 4, library_values_changed_4); OPENSSL_COMPILE_ASSERT(ERR_LIB_DH == 5, library_values_changed_5); OPENSSL_COMPILE_ASSERT(ERR_LIB_EVP == 6, library_values_changed_6); OPENSSL_COMPILE_ASSERT(ERR_LIB_BUF == 7, library_values_changed_7); OPENSSL_COMPILE_ASSERT(ERR_LIB_OBJ == 8, library_values_changed_8); OPENSSL_COMPILE_ASSERT(ERR_LIB_PEM == 9, library_values_changed_9); OPENSSL_COMPILE_ASSERT(ERR_LIB_DSA == 10, library_values_changed_10); OPENSSL_COMPILE_ASSERT(ERR_LIB_X509 == 11, library_values_changed_11); OPENSSL_COMPILE_ASSERT(ERR_LIB_ASN1 == 12, library_values_changed_12); OPENSSL_COMPILE_ASSERT(ERR_LIB_CONF == 13, library_values_changed_13); OPENSSL_COMPILE_ASSERT(ERR_LIB_CRYPTO == 14, library_values_changed_14); OPENSSL_COMPILE_ASSERT(ERR_LIB_EC == 15, library_values_changed_15); OPENSSL_COMPILE_ASSERT(ERR_LIB_SSL == 16, library_values_changed_16); OPENSSL_COMPILE_ASSERT(ERR_LIB_BIO == 17, library_values_changed_17); OPENSSL_COMPILE_ASSERT(ERR_LIB_PKCS7 == 18, library_values_changed_18); OPENSSL_COMPILE_ASSERT(ERR_LIB_PKCS8 == 19, library_values_changed_19); OPENSSL_COMPILE_ASSERT(ERR_LIB_X509V3 == 20, library_values_changed_20); OPENSSL_COMPILE_ASSERT(ERR_LIB_RAND == 21, library_values_changed_21); OPENSSL_COMPILE_ASSERT(ERR_LIB_ENGINE == 22, library_values_changed_22); OPENSSL_COMPILE_ASSERT(ERR_LIB_OCSP == 23, library_values_changed_23); OPENSSL_COMPILE_ASSERT(ERR_LIB_UI == 24, library_values_changed_24); OPENSSL_COMPILE_ASSERT(ERR_LIB_COMP == 25, library_values_changed_25); OPENSSL_COMPILE_ASSERT(ERR_LIB_ECDSA == 26, library_values_changed_26); OPENSSL_COMPILE_ASSERT(ERR_LIB_ECDH == 27, library_values_changed_27); OPENSSL_COMPILE_ASSERT(ERR_LIB_HMAC == 28, library_values_changed_28); OPENSSL_COMPILE_ASSERT(ERR_LIB_DIGEST == 29, library_values_changed_29); OPENSSL_COMPILE_ASSERT(ERR_LIB_CIPHER == 30, library_values_changed_30); OPENSSL_COMPILE_ASSERT(ERR_LIB_HKDF == 31, library_values_changed_31); OPENSSL_COMPILE_ASSERT(ERR_LIB_USER == 32, library_values_changed_32); OPENSSL_COMPILE_ASSERT(ERR_NUM_LIBS == 33, library_values_changed_num); const uint32_t kOpenSSLReasonValues[] = { 0xc320838, 0xc328852, 0xc330861, 0xc338871, 0xc340880, 0xc348899, 0xc3508a5, 0xc3588c2, 0xc3608d4, 0xc3688e2, 0xc3708f2, 0xc3788ff, 0xc38090f, 0xc38891a, 0xc390930, 0xc39893f, 0xc3a0953, 0xc3a8845, 0xc3b00ea, 0x10320845, 0x103293ab, 0x103313b7, 0x103393d0, 0x103413e3, 0x10348e8b, 0x10350c19, 0x103593f6, 0x1036140b, 0x1036941e, 0x1037143d, 0x10379456, 0x1038146b, 0x10389489, 0x10391498, 0x103994b4, 0x103a14cf, 0x103a94de, 0x103b14fa, 0x103b9515, 0x103c152c, 0x103c80ea, 0x103d153d, 0x103d9551, 0x103e1570, 0x103e957f, 0x103f1596, 0x103f95a9, 0x10400bea, 0x104095bc, 0x104115da, 0x104195ed, 0x10421607, 0x10429617, 0x1043162b, 0x10439641, 0x10441659, 0x1044966e, 0x10451682, 0x10459694, 0x104605fb, 0x1046893f, 0x104716a9, 0x104796c0, 0x104816d5, 0x104896e3, 0x14320bcd, 0x14328bdb, 0x14330bea, 0x14338bfc, 0x143400ac, 0x143480ea, 0x18320083, 0x18328ee1, 0x183300ac, 0x18338ef7, 0x18340f0b, 0x183480ea, 0x18350f20, 0x18358f38, 0x18360f4d, 0x18368f61, 0x18370f85, 0x18378f9b, 0x18380faf, 0x18388fbf, 0x18390a57, 0x18398fcf, 0x183a0fe4, 0x183a8ff8, 0x183b0c25, 0x183b9005, 0x183c1017, 0x183c9022, 0x183d1032, 0x183d9043, 0x183e1054, 0x183e9066, 0x183f108f, 0x183f90a8, 0x184010c0, 0x184086d3, 0x203210e7, 0x243210f3, 0x24328985, 0x24331105, 0x24339112, 0x2434111f, 0x24349131, 0x24351140, 0x2435915d, 0x2436116a, 0x24369178, 0x24371186, 0x24379194, 0x2438119d, 0x243891aa, 0x243911bd, 0x28320c0d, 0x28328c25, 0x28330bea, 0x28338c38, 0x28340c19, 0x283480ac, 0x283500ea, 0x2c3228ca, 0x2c32a8d8, 0x2c3328ea, 0x2c33a8fc, 0x2c342910, 0x2c34a922, 0x2c35293d, 0x2c35a94f, 0x2c362962, 0x2c36832d, 0x2c37296f, 0x2c37a981, 0x2c382994, 0x2c38a9ab, 0x2c3929b9, 0x2c39a9c9, 0x2c3a29db, 0x2c3aa9ef, 0x2c3b2a00, 0x2c3baa1f, 0x2c3c2a33, 0x2c3caa49, 0x2c3d2a62, 0x2c3daa7f, 0x2c3e2a90, 0x2c3eaa9e, 0x2c3f2ab6, 0x2c3faace, 0x2c402adb, 0x2c4090e7, 0x2c412aec, 0x2c41aaff, 0x2c4210c0, 0x2c42ab10, 0x2c430720, 0x2c43aa11, 0x30320000, 0x30328015, 0x3033001f, 0x30338038, 0x3034004a, 0x30348064, 0x3035006b, 0x30358083, 0x30360094, 0x303680ac, 0x303700b9, 0x303780c8, 0x303800ea, 0x303880f7, 0x3039010a, 0x30398125, 0x303a013a, 0x303a814e, 0x303b0162, 0x303b8173, 0x303c018c, 0x303c81a9, 0x303d01b7, 0x303d81cb, 0x303e01db, 0x303e81f4, 0x303f0204, 0x303f8217, 0x30400226, 0x30408232, 0x30410247, 0x30418257, 0x3042026e, 0x3042827b, 0x3043028e, 0x3043829d, 0x304402b2, 0x304482d3, 0x304502e6, 0x304582f9, 0x30460312, 0x3046832d, 0x3047034a, 0x30478363, 0x30480371, 0x30488382, 0x30490391, 0x304983a9, 0x304a03bb, 0x304a83cf, 0x304b03ee, 0x304b8401, 0x304c040c, 0x304c841d, 0x304d0429, 0x304d843f, 0x304e044d, 0x304e8463, 0x304f0475, 0x304f8487, 0x3050049a, 0x305084ad, 0x305104be, 0x305184ce, 0x305204e6, 0x305284fb, 0x30530513, 0x30538527, 0x3054053f, 0x30548558, 0x30550571, 0x3055858e, 0x30560599, 0x305685b1, 0x305705c1, 0x305785d2, 0x305805e5, 0x305885fb, 0x30590604, 0x30598619, 0x305a062c, 0x305a863b, 0x305b065b, 0x305b866a, 0x305c068b, 0x305c86a7, 0x305d06b3, 0x305d86d3, 0x305e06ef, 0x305e8700, 0x305f0716, 0x305f8720, 0x34320b47, 0x34328b5b, 0x34330b78, 0x34338b8b, 0x34340b9a, 0x34348bb7, 0x3c320083, 0x3c328c62, 0x3c330c7b, 0x3c338c96, 0x3c340cb3, 0x3c348cdd, 0x3c350cf8, 0x3c358d1e, 0x3c360d37, 0x3c368d4f, 0x3c370d60, 0x3c378d6e, 0x3c380d7b, 0x3c388d8f, 0x3c390c25, 0x3c398da3, 0x3c3a0db7, 0x3c3a88ff, 0x3c3b0dc7, 0x3c3b8de2, 0x3c3c0df4, 0x3c3c8e0a, 0x3c3d0e14, 0x3c3d8e28, 0x3c3e0e36, 0x3c3e8e5b, 0x3c3f0c4e, 0x3c3f8e44, 0x3c4000ac, 0x3c4080ea, 0x3c410cce, 0x3c418d0d, 0x403216fa, 0x40329710, 0x4033173e, 0x40339748, 0x4034175f, 0x4034977d, 0x4035178d, 0x4035979f, 0x403617ac, 0x403697b8, 0x403717cd, 0x403797df, 0x403817ea, 0x403897fc, 0x40390e8b, 0x4039980c, 0x403a181f, 0x403a9840, 0x403b1851, 0x403b9861, 0x403c0064, 0x403c8083, 0x403d18aa, 0x403d98c0, 0x403e18cf, 0x403e98e2, 0x403f18fc, 0x403f990a, 0x4040191f, 0x40409933, 0x40411950, 0x4041996b, 0x40421984, 0x40429997, 0x404319ab, 0x404399c3, 0x404419da, 0x404480ac, 0x404519ef, 0x40459a01, 0x40461a25, 0x40469a45, 0x40471a53, 0x40479a7a, 0x40481ab7, 0x40489ad0, 0x40491ae7, 0x40499b01, 0x404a1b18, 0x404a9b36, 0x404b1b4e, 0x404b9b65, 0x404c1b7b, 0x404c9b8d, 0x404d1bae, 0x404d9bd0, 0x404e1be4, 0x404e9bf1, 0x404f1c1e, 0x404f9c47, 0x40501c71, 0x40509c85, 0x40511ca0, 0x40519cb0, 0x40521cc7, 0x40529ceb, 0x40531d03, 0x40539d16, 0x40541d2b, 0x40549d4e, 0x40551d5c, 0x40559d79, 0x40561d86, 0x40569d9f, 0x40571db7, 0x40579dca, 0x40581ddf, 0x40589e06, 0x40591e35, 0x40599e62, 0x405a1e76, 0x405a9e86, 0x405b1e9e, 0x405b9eaf, 0x405c1ec2, 0x405c9ed3, 0x405d1ee0, 0x405d9ef7, 0x405e1f17, 0x405e8a95, 0x405f1f38, 0x405f9f45, 0x40601f53, 0x40609f75, 0x40611f9d, 0x40619fb2, 0x40621fc9, 0x40629fda, 0x40631feb, 0x4063a000, 0x40642017, 0x4064a043, 0x4065205e, 0x4065a075, 0x4066208d, 0x4066a0b7, 0x406720e2, 0x4067a103, 0x40682116, 0x4068a137, 0x40692169, 0x4069a197, 0x406a21b8, 0x406aa1d8, 0x406b2360, 0x406ba383, 0x406c2399, 0x406ca5c5, 0x406d25f4, 0x406da61c, 0x406e264a, 0x406ea662, 0x406f2681, 0x406fa696, 0x407026a9, 0x4070a6c6, 0x40710800, 0x4071a6d8, 0x407226eb, 0x4072a704, 0x4073271c, 0x4073936d, 0x40742730, 0x4074a74a, 0x4075275b, 0x4075a76f, 0x4076277d, 0x407691aa, 0x407727a2, 0x4077a7c4, 0x407827df, 0x4078a818, 0x4079282f, 0x4079a845, 0x407a2851, 0x407aa864, 0x407b2879, 0x407ba88b, 0x407c28a0, 0x407ca8a9, 0x407d2152, 0x407d9c57, 0x407e27f4, 0x407e9e16, 0x407f1a67, 0x407f9887, 0x40801c2e, 0x40809a8f, 0x40811cd9, 0x40819c08, 0x40822635, 0x4082986d, 0x40831df1, 0x4083a028, 0x40841aa3, 0x40849e4e, 0x41f4228b, 0x41f9231d, 0x41fe2210, 0x41fea3ec, 0x41ff24dd, 0x420322a4, 0x420822c6, 0x4208a302, 0x420921f4, 0x4209a33c, 0x420a224b, 0x420aa22b, 0x420b226b, 0x420ba2e4, 0x420c24f9, 0x420ca3b9, 0x420d23d3, 0x420da40a, 0x42122424, 0x421724c0, 0x4217a466, 0x421c2488, 0x421f2443, 0x42212510, 0x422624a3, 0x422b25a9, 0x422ba572, 0x422c2591, 0x422ca54c, 0x422d252b, 0x4432072b, 0x4432873a, 0x44330746, 0x44338754, 0x44340767, 0x44348778, 0x4435077f, 0x44358789, 0x4436079c, 0x443687b2, 0x443707c4, 0x443787d1, 0x443807e0, 0x443887e8, 0x44390800, 0x4439880e, 0x443a0821, 0x4c3211d4, 0x4c3291e4, 0x4c3311f7, 0x4c339217, 0x4c3400ac, 0x4c3480ea, 0x4c351223, 0x4c359231, 0x4c36124d, 0x4c369260, 0x4c37126f, 0x4c37927d, 0x4c381292, 0x4c38929e, 0x4c3912be, 0x4c3992e8, 0x4c3a1301, 0x4c3a931a, 0x4c3b05fb, 0x4c3b9333, 0x4c3c1345, 0x4c3c9354, 0x4c3d136d, 0x4c3d937c, 0x4c3e1389, 0x50322b22, 0x5032ab31, 0x50332b3c, 0x5033ab4c, 0x50342b65, 0x5034ab7f, 0x50352b8d, 0x5035aba3, 0x50362bb5, 0x5036abcb, 0x50372be4, 0x5037abf7, 0x50382c0f, 0x5038ac20, 0x50392c35, 0x5039ac49, 0x503a2c69, 0x503aac7f, 0x503b2c97, 0x503baca9, 0x503c2cc5, 0x503cacdc, 0x503d2cf5, 0x503dad0b, 0x503e2d18, 0x503ead2e, 0x503f2d40, 0x503f8382, 0x50402d53, 0x5040ad63, 0x50412d7d, 0x5041ad8c, 0x50422da6, 0x5042adc3, 0x50432dd3, 0x5043ade3, 0x50442df2, 0x5044843f, 0x50452e06, 0x5045ae24, 0x50462e37, 0x5046ae4d, 0x50472e5f, 0x5047ae74, 0x50482e9a, 0x5048aea8, 0x50492ebb, 0x5049aed0, 0x504a2ee6, 0x504aaef6, 0x504b2f16, 0x504baf29, 0x504c2f4c, 0x504caf7a, 0x504d2f8c, 0x504dafa9, 0x504e2fc4, 0x504eafe0, 0x504f2ff2, 0x504fb009, 0x50503018, 0x505086ef, 0x5051302b, 0x58320ec9, 0x68320e8b, 0x68328c25, 0x68330c38, 0x68338e99, 0x68340ea9, 0x683480ea, 0x6c320e67, 0x6c328bfc, 0x6c330e72, 0x74320a0b, 0x78320970, 0x78328985, 0x78330991, 0x78338083, 0x783409a0, 0x783489b5, 0x783509d4, 0x783589f6, 0x78360a0b, 0x78368a21, 0x78370a31, 0x78378a44, 0x78380a57, 0x78388a69, 0x78390a76, 0x78398a95, 0x783a0aaa, 0x783a8ab8, 0x783b0ac2, 0x783b8ad6, 0x783c0aed, 0x783c8b02, 0x783d0b19, 0x783d8b2e, 0x783e0a84, 0x7c3210d6, }; const size_t kOpenSSLReasonValuesLen = sizeof(kOpenSSLReasonValues) / sizeof(kOpenSSLReasonValues[0]); const char kOpenSSLReasonStringData[] = "ASN1_LENGTH_MISMATCH\\0" "AUX_ERROR\\0" "BAD_GET_ASN1_OBJECT_CALL\\0" "BAD_OBJECT_HEADER\\0" "BMPSTRING_IS_WRONG_LENGTH\\0" "BN_LIB\\0" "BOOLEAN_IS_WRONG_LENGTH\\0" "BUFFER_TOO_SMALL\\0" "CONTEXT_NOT_INITIALISED\\0" "DECODE_ERROR\\0" "DEPTH_EXCEEDED\\0" "DIGEST_AND_KEY_TYPE_NOT_SUPPORTED\\0" "ENCODE_ERROR\\0" "ERROR_GETTING_TIME\\0" "EXPECTING_AN_ASN1_SEQUENCE\\0" "EXPECTING_AN_INTEGER\\0" "EXPECTING_AN_OBJECT\\0" "EXPECTING_A_BOOLEAN\\0" "EXPECTING_A_TIME\\0" "EXPLICIT_LENGTH_MISMATCH\\0" "EXPLICIT_TAG_NOT_CONSTRUCTED\\0" "FIELD_MISSING\\0" "FIRST_NUM_TOO_LARGE\\0" "HEADER_TOO_LONG\\0" "ILLEGAL_BITSTRING_FORMAT\\0" "ILLEGAL_BOOLEAN\\0" "ILLEGAL_CHARACTERS\\0" "ILLEGAL_FORMAT\\0" "ILLEGAL_HEX\\0" "ILLEGAL_IMPLICIT_TAG\\0" "ILLEGAL_INTEGER\\0" "ILLEGAL_NESTED_TAGGING\\0" "ILLEGAL_NULL\\0" "ILLEGAL_NULL_VALUE\\0" "ILLEGAL_OBJECT\\0" "ILLEGAL_OPTIONAL_ANY\\0" "ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE\\0" "ILLEGAL_TAGGED_ANY\\0" "ILLEGAL_TIME_VALUE\\0" "INTEGER_NOT_ASCII_FORMAT\\0" "INTEGER_TOO_LARGE_FOR_LONG\\0" "INVALID_BIT_STRING_BITS_LEFT\\0" "INVALID_BMPSTRING_LENGTH\\0" "INVALID_DIGIT\\0" "INVALID_MODIFIER\\0" "INVALID_NUMBER\\0" "INVALID_OBJECT_ENCODING\\0" "INVALID_SEPARATOR\\0" "INVALID_TIME_FORMAT\\0" "INVALID_UNIVERSALSTRING_LENGTH\\0" "INVALID_UTF8STRING\\0" "LIST_ERROR\\0" "MISSING_ASN1_EOS\\0" "MISSING_EOC\\0" "MISSING_SECOND_NUMBER\\0" "MISSING_VALUE\\0" "MSTRING_NOT_UNIVERSAL\\0" "MSTRING_WRONG_TAG\\0" "NESTED_ASN1_ERROR\\0" "NESTED_ASN1_STRING\\0" "NON_HEX_CHARACTERS\\0" "NOT_ASCII_FORMAT\\0" "NOT_ENOUGH_DATA\\0" "NO_MATCHING_CHOICE_TYPE\\0" "NULL_IS_WRONG_LENGTH\\0" "OBJECT_NOT_ASCII_FORMAT\\0" "ODD_NUMBER_OF_CHARS\\0" "SECOND_NUMBER_TOO_LARGE\\0" "SEQUENCE_LENGTH_MISMATCH\\0" "SEQUENCE_NOT_CONSTRUCTED\\0" "SEQUENCE_OR_SET_NEEDS_CONFIG\\0" "SHORT_LINE\\0" "STREAMING_NOT_SUPPORTED\\0" "STRING_TOO_LONG\\0" "STRING_TOO_SHORT\\0" "TAG_VALUE_TOO_HIGH\\0" "TIME_NOT_ASCII_FORMAT\\0" "TOO_LONG\\0" "TYPE_NOT_CONSTRUCTED\\0" "TYPE_NOT_PRIMITIVE\\0" "UNEXPECTED_EOC\\0" "UNIVERSALSTRING_IS_WRONG_LENGTH\\0" "UNKNOWN_FORMAT\\0" "UNKNOWN_MESSAGE_DIGEST_ALGORITHM\\0" "UNKNOWN_SIGNATURE_ALGORITHM\\0" "UNKNOWN_TAG\\0" "UNSUPPORTED_ANY_DEFINED_BY_TYPE\\0" "UNSUPPORTED_PUBLIC_KEY_TYPE\\0" "UNSUPPORTED_TYPE\\0" "WRONG_PUBLIC_KEY_TYPE\\0" "WRONG_TAG\\0" "WRONG_TYPE\\0" "BAD_FOPEN_MODE\\0" "BROKEN_PIPE\\0" "CONNECT_ERROR\\0" "ERROR_SETTING_NBIO\\0" "INVALID_ARGUMENT\\0" "IN_USE\\0" "KEEPALIVE\\0" "NBIO_CONNECT_ERROR\\0" "NO_HOSTNAME_SPECIFIED\\0" "NO_PORT_SPECIFIED\\0" "NO_SUCH_FILE\\0" "NULL_PARAMETER\\0" "SYS_LIB\\0" "UNABLE_TO_CREATE_SOCKET\\0" "UNINITIALIZED\\0" "UNSUPPORTED_METHOD\\0" "WRITE_TO_READ_ONLY_BIO\\0" "ARG2_LT_ARG3\\0" "BAD_ENCODING\\0" "BAD_RECIPROCAL\\0" "BIGNUM_TOO_LONG\\0" "BITS_TOO_SMALL\\0" "CALLED_WITH_EVEN_MODULUS\\0" "DIV_BY_ZERO\\0" "EXPAND_ON_STATIC_BIGNUM_DATA\\0" "INPUT_NOT_REDUCED\\0" "INVALID_RANGE\\0" "NEGATIVE_NUMBER\\0" "NOT_A_SQUARE\\0" "NOT_INITIALIZED\\0" "NO_INVERSE\\0" "PRIVATE_KEY_TOO_LARGE\\0" "P_IS_NOT_PRIME\\0" "TOO_MANY_ITERATIONS\\0" "TOO_MANY_TEMPORARY_VARIABLES\\0" "AES_KEY_SETUP_FAILED\\0" "BAD_DECRYPT\\0" "BAD_KEY_LENGTH\\0" "CTRL_NOT_IMPLEMENTED\\0" "CTRL_OPERATION_NOT_IMPLEMENTED\\0" "DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH\\0" "INITIALIZATION_ERROR\\0" "INPUT_NOT_INITIALIZED\\0" "INVALID_AD_SIZE\\0" "INVALID_KEY_LENGTH\\0" "INVALID_NONCE_SIZE\\0" "INVALID_OPERATION\\0" "IV_TOO_LARGE\\0" "NO_CIPHER_SET\\0" "NO_DIRECTION_SET\\0" "OUTPUT_ALIASES_INPUT\\0" "TAG_TOO_LARGE\\0" "TOO_LARGE\\0" "UNSUPPORTED_AD_SIZE\\0" "UNSUPPORTED_INPUT_SIZE\\0" "UNSUPPORTED_KEY_SIZE\\0" "UNSUPPORTED_NONCE_SIZE\\0" "UNSUPPORTED_TAG_SIZE\\0" "WRONG_FINAL_BLOCK_LENGTH\\0" "LIST_CANNOT_BE_NULL\\0" "MISSING_CLOSE_SQUARE_BRACKET\\0" "MISSING_EQUAL_SIGN\\0" "NO_CLOSE_BRACE\\0" "UNABLE_TO_CREATE_NEW_SECTION\\0" "VARIABLE_HAS_NO_VALUE\\0" "BAD_GENERATOR\\0" "INVALID_PUBKEY\\0" "MODULUS_TOO_LARGE\\0" "NO_PRIVATE_VALUE\\0" "BAD_Q_VALUE\\0" "BAD_VERSION\\0" "MISSING_PARAMETERS\\0" "NEED_NEW_SETUP_VALUES\\0" "BIGNUM_OUT_OF_RANGE\\0" "COORDINATES_OUT_OF_RANGE\\0" "D2I_ECPKPARAMETERS_FAILURE\\0" "EC_GROUP_NEW_BY_NAME_FAILURE\\0" "GROUP2PKPARAMETERS_FAILURE\\0" "GROUP_MISMATCH\\0" "I2D_ECPKPARAMETERS_FAILURE\\0" "INCOMPATIBLE_OBJECTS\\0" "INVALID_COFACTOR\\0" "INVALID_COMPRESSED_POINT\\0" "INVALID_COMPRESSION_BIT\\0" "INVALID_ENCODING\\0" "INVALID_FIELD\\0" "INVALID_FORM\\0" "INVALID_GROUP_ORDER\\0" "INVALID_PRIVATE_KEY\\0" "MISSING_PRIVATE_KEY\\0" "NON_NAMED_CURVE\\0" "PKPARAMETERS2GROUP_FAILURE\\0" "POINT_AT_INFINITY\\0" "POINT_IS_NOT_ON_CURVE\\0" "SLOT_FULL\\0" "UNDEFINED_GENERATOR\\0" "UNKNOWN_GROUP\\0" "UNKNOWN_ORDER\\0" "WRONG_CURVE_PARAMETERS\\0" "WRONG_ORDER\\0" "KDF_FAILED\\0" "POINT_ARITHMETIC_FAILURE\\0" "BAD_SIGNATURE\\0" "NOT_IMPLEMENTED\\0" "RANDOM_NUMBER_GENERATION_FAILED\\0" "OPERATION_NOT_SUPPORTED\\0" "COMMAND_NOT_SUPPORTED\\0" "DIFFERENT_KEY_TYPES\\0" "DIFFERENT_PARAMETERS\\0" "EXPECTING_AN_EC_KEY_KEY\\0" "EXPECTING_AN_RSA_KEY\\0" "EXPECTING_A_DSA_KEY\\0" "ILLEGAL_OR_UNSUPPORTED_PADDING_MODE\\0" "INVALID_DIGEST_LENGTH\\0" "INVALID_DIGEST_TYPE\\0" "INVALID_KEYBITS\\0" "INVALID_MGF1_MD\\0" "INVALID_PADDING_MODE\\0" "INVALID_PSS_SALTLEN\\0" "KEYS_NOT_SET\\0" "NO_DEFAULT_DIGEST\\0" "NO_KEY_SET\\0" "NO_MDC2_SUPPORT\\0" "NO_NID_FOR_CURVE\\0" "NO_OPERATION_SET\\0" "NO_PARAMETERS_SET\\0" "OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE\\0" "OPERATON_NOT_INITIALIZED\\0" "UNKNOWN_PUBLIC_KEY_TYPE\\0" "UNSUPPORTED_ALGORITHM\\0" "OUTPUT_TOO_LARGE\\0" "UNKNOWN_NID\\0" "BAD_BASE64_DECODE\\0" "BAD_END_LINE\\0" "BAD_IV_CHARS\\0" "BAD_PASSWORD_READ\\0" "CIPHER_IS_NULL\\0" "ERROR_CONVERTING_PRIVATE_KEY\\0" "NOT_DEK_INFO\\0" "NOT_ENCRYPTED\\0" "NOT_PROC_TYPE\\0" "NO_START_LINE\\0" "READ_KEY\\0" "SHORT_HEADER\\0" "UNSUPPORTED_CIPHER\\0" "UNSUPPORTED_ENCRYPTION\\0" "BAD_PKCS12_DATA\\0" "BAD_PKCS12_VERSION\\0" "CIPHER_HAS_NO_OBJECT_IDENTIFIER\\0" "CRYPT_ERROR\\0" "ENCRYPT_ERROR\\0" "ERROR_SETTING_CIPHER_PARAMS\\0" "INCORRECT_PASSWORD\\0" "KEYGEN_FAILURE\\0" "KEY_GEN_ERROR\\0" "METHOD_NOT_SUPPORTED\\0" "MISSING_MAC\\0" "MULTIPLE_PRIVATE_KEYS_IN_PKCS12\\0" "PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED\\0" "PKCS12_TOO_DEEPLY_NESTED\\0" "PRIVATE_KEY_DECODE_ERROR\\0" "PRIVATE_KEY_ENCODE_ERROR\\0" "UNKNOWN_ALGORITHM\\0" "UNKNOWN_CIPHER\\0" "UNKNOWN_CIPHER_ALGORITHM\\0" "UNKNOWN_DIGEST\\0" "UNKNOWN_HASH\\0" "UNSUPPORTED_PRIVATE_KEY_ALGORITHM\\0" "BAD_E_VALUE\\0" "BAD_FIXED_HEADER_DECRYPT\\0" "BAD_PAD_BYTE_COUNT\\0" "BAD_RSA_PARAMETERS\\0" "BLOCK_TYPE_IS_NOT_01\\0" "BN_NOT_INITIALIZED\\0" "CANNOT_RECOVER_MULTI_PRIME_KEY\\0" "CRT_PARAMS_ALREADY_GIVEN\\0" "CRT_VALUES_INCORRECT\\0" "DATA_LEN_NOT_EQUAL_TO_MOD_LEN\\0" "DATA_TOO_LARGE\\0" "DATA_TOO_LARGE_FOR_KEY_SIZE\\0" "DATA_TOO_LARGE_FOR_MODULUS\\0" "DATA_TOO_SMALL\\0" "DATA_TOO_SMALL_FOR_KEY_SIZE\\0" "DIGEST_TOO_BIG_FOR_RSA_KEY\\0" "D_E_NOT_CONGRUENT_TO_1\\0" "EMPTY_PUBLIC_KEY\\0" "FIRST_OCTET_INVALID\\0" "INCONSISTENT_SET_OF_CRT_VALUES\\0" "INTERNAL_ERROR\\0" "INVALID_MESSAGE_LENGTH\\0" "KEY_SIZE_TOO_SMALL\\0" "LAST_OCTET_INVALID\\0" "MUST_HAVE_AT_LEAST_TWO_PRIMES\\0" "NO_PUBLIC_EXPONENT\\0" "NULL_BEFORE_BLOCK_MISSING\\0" "N_NOT_EQUAL_P_Q\\0" "OAEP_DECODING_ERROR\\0" "ONLY_ONE_OF_P_Q_GIVEN\\0" "OUTPUT_BUFFER_TOO_SMALL\\0" "PADDING_CHECK_FAILED\\0" "PKCS_DECODING_ERROR\\0" "SLEN_CHECK_FAILED\\0" "SLEN_RECOVERY_FAILED\\0" "UNKNOWN_ALGORITHM_TYPE\\0" "UNKNOWN_PADDING_TYPE\\0" "VALUE_MISSING\\0" "WRONG_SIGNATURE_LENGTH\\0" "APP_DATA_IN_HANDSHAKE\\0" "ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT\\0" "BAD_ALERT\\0" "BAD_CHANGE_CIPHER_SPEC\\0" "BAD_DATA_RETURNED_BY_CALLBACK\\0" "BAD_DH_P_LENGTH\\0" "BAD_DIGEST_LENGTH\\0" "BAD_ECC_CERT\\0" "BAD_ECPOINT\\0" "BAD_HANDSHAKE_RECORD\\0" "BAD_HELLO_REQUEST\\0" "BAD_LENGTH\\0" "BAD_PACKET_LENGTH\\0" "BAD_RSA_ENCRYPT\\0" "BAD_SRTP_MKI_VALUE\\0" "BAD_SRTP_PROTECTION_PROFILE_LIST\\0" "BAD_SSL_FILETYPE\\0" "BAD_WRITE_RETRY\\0" "BIO_NOT_SET\\0" "BLOCK_CIPHER_PAD_IS_WRONG\\0" "BUFFERED_MESSAGES_ON_CIPHER_CHANGE\\0" "CA_DN_LENGTH_MISMATCH\\0" "CA_DN_TOO_LONG\\0" "CCS_RECEIVED_EARLY\\0" "CERTIFICATE_VERIFY_FAILED\\0" "CERT_CB_ERROR\\0" "CERT_LENGTH_MISMATCH\\0" "CHANNEL_ID_NOT_P256\\0" "CHANNEL_ID_SIGNATURE_INVALID\\0" "CIPHER_OR_HASH_UNAVAILABLE\\0" "CLIENTHELLO_PARSE_FAILED\\0" "CLIENTHELLO_TLSEXT\\0" "CONNECTION_REJECTED\\0" "CONNECTION_TYPE_NOT_SET\\0" "CUSTOM_EXTENSION_ERROR\\0" "DATA_LENGTH_TOO_LONG\\0" "DECRYPTION_FAILED\\0" "DECRYPTION_FAILED_OR_BAD_RECORD_MAC\\0" "DH_PUBLIC_VALUE_LENGTH_IS_WRONG\\0" "DH_P_TOO_LONG\\0" "DIGEST_CHECK_FAILED\\0" "DOWNGRADE_DETECTED\\0" "DTLS_MESSAGE_TOO_BIG\\0" "DUPLICATE_EXTENSION\\0" "DUPLICATE_KEY_SHARE\\0" "ECC_CERT_NOT_FOR_SIGNING\\0" "EMS_STATE_INCONSISTENT\\0" "ENCRYPTED_LENGTH_TOO_LONG\\0" "ERROR_ADDING_EXTENSION\\0" "ERROR_IN_RECEIVED_CIPHER_LIST\\0" "ERROR_PARSING_EXTENSION\\0" "EXCESSIVE_MESSAGE_SIZE\\0" "EXTRA_DATA_IN_MESSAGE\\0" "FRAGMENT_MISMATCH\\0" "GOT_NEXT_PROTO_WITHOUT_EXTENSION\\0" "HANDSHAKE_FAILURE_ON_CLIENT_HELLO\\0" "HTTPS_PROXY_REQUEST\\0" "HTTP_REQUEST\\0" "INAPPROPRIATE_FALLBACK\\0" "INVALID_ALPN_PROTOCOL\\0" "INVALID_COMMAND\\0" "INVALID_COMPRESSION_LIST\\0" "INVALID_MESSAGE\\0" "INVALID_OUTER_RECORD_TYPE\\0" "INVALID_SSL_SESSION\\0" "INVALID_TICKET_KEYS_LENGTH\\0" "LENGTH_MISMATCH\\0" "LIBRARY_HAS_NO_CIPHERS\\0" "MISSING_EXTENSION\\0" "MISSING_KEY_SHARE\\0" "MISSING_RSA_CERTIFICATE\\0" "MISSING_TMP_DH_KEY\\0" "MISSING_TMP_ECDH_KEY\\0" "MIXED_SPECIAL_OPERATOR_WITH_GROUPS\\0" "MTU_TOO_SMALL\\0" "NEGOTIATED_BOTH_NPN_AND_ALPN\\0" "NESTED_GROUP\\0" "NO_CERTIFICATES_RETURNED\\0" "NO_CERTIFICATE_ASSIGNED\\0" "NO_CERTIFICATE_SET\\0" "NO_CIPHERS_AVAILABLE\\0" "NO_CIPHERS_PASSED\\0" "NO_CIPHERS_SPECIFIED\\0" "NO_CIPHER_MATCH\\0" "NO_COMMON_SIGNATURE_ALGORITHMS\\0" "NO_COMPRESSION_SPECIFIED\\0" "NO_GROUPS_SPECIFIED\\0" "NO_METHOD_SPECIFIED\\0" "NO_P256_SUPPORT\\0" "NO_PRIVATE_KEY_ASSIGNED\\0" "NO_RENEGOTIATION\\0" "NO_REQUIRED_DIGEST\\0" "NO_SHARED_CIPHER\\0" "NULL_SSL_CTX\\0" "NULL_SSL_METHOD_PASSED\\0" "OLD_SESSION_CIPHER_NOT_RETURNED\\0" "OLD_SESSION_VERSION_NOT_RETURNED\\0" "PARSE_TLSEXT\\0" "PATH_TOO_LONG\\0" "PEER_DID_NOT_RETURN_A_CERTIFICATE\\0" "PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE\\0" "PROTOCOL_IS_SHUTDOWN\\0" "PSK_IDENTITY_NOT_FOUND\\0" "PSK_NO_CLIENT_CB\\0" "PSK_NO_SERVER_CB\\0" "READ_TIMEOUT_EXPIRED\\0" "RECORD_LENGTH_MISMATCH\\0" "RECORD_TOO_LARGE\\0" "RENEGOTIATION_EMS_MISMATCH\\0" "RENEGOTIATION_ENCODING_ERR\\0" "RENEGOTIATION_MISMATCH\\0" "REQUIRED_CIPHER_MISSING\\0" "RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION\\0" "RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION\\0" "SCSV_RECEIVED_WHEN_RENEGOTIATING\\0" "SERVERHELLO_TLSEXT\\0" "SESSION_ID_CONTEXT_UNINITIALIZED\\0" "SESSION_MAY_NOT_BE_CREATED\\0" "SHUTDOWN_WHILE_IN_INIT\\0" "SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER\\0" "SRTP_COULD_NOT_ALLOCATE_PROFILES\\0" "SRTP_UNKNOWN_PROTECTION_PROFILE\\0" "SSL3_EXT_INVALID_SERVERNAME\\0" "SSLV3_ALERT_BAD_CERTIFICATE\\0" "SSLV3_ALERT_BAD_RECORD_MAC\\0" "SSLV3_ALERT_CERTIFICATE_EXPIRED\\0" "SSLV3_ALERT_CERTIFICATE_REVOKED\\0" "SSLV3_ALERT_CERTIFICATE_UNKNOWN\\0" "SSLV3_ALERT_CLOSE_NOTIFY\\0" "SSLV3_ALERT_DECOMPRESSION_FAILURE\\0" "SSLV3_ALERT_HANDSHAKE_FAILURE\\0" "SSLV3_ALERT_ILLEGAL_PARAMETER\\0" "SSLV3_ALERT_NO_CERTIFICATE\\0" "SSLV3_ALERT_UNEXPECTED_MESSAGE\\0" "SSLV3_ALERT_UNSUPPORTED_CERTIFICATE\\0" "SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION\\0" "SSL_HANDSHAKE_FAILURE\\0" "SSL_SESSION_ID_CONTEXT_TOO_LONG\\0" "TLSV1_ALERT_ACCESS_DENIED\\0" "TLSV1_ALERT_DECODE_ERROR\\0" "TLSV1_ALERT_DECRYPTION_FAILED\\0" "TLSV1_ALERT_DECRYPT_ERROR\\0" "TLSV1_ALERT_EXPORT_RESTRICTION\\0" "TLSV1_ALERT_INAPPROPRIATE_FALLBACK\\0" "TLSV1_ALERT_INSUFFICIENT_SECURITY\\0" "TLSV1_ALERT_INTERNAL_ERROR\\0" "TLSV1_ALERT_NO_RENEGOTIATION\\0" "TLSV1_ALERT_PROTOCOL_VERSION\\0" "TLSV1_ALERT_RECORD_OVERFLOW\\0" "TLSV1_ALERT_UNKNOWN_CA\\0" "TLSV1_ALERT_USER_CANCELLED\\0" "TLSV1_BAD_CERTIFICATE_HASH_VALUE\\0" "TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE\\0" "TLSV1_CERTIFICATE_UNOBTAINABLE\\0" "TLSV1_UNRECOGNIZED_NAME\\0" "TLSV1_UNSUPPORTED_EXTENSION\\0" "TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST\\0" "TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG\\0" "TOO_MANY_EMPTY_FRAGMENTS\\0" "TOO_MANY_KEY_UPDATES\\0" "TOO_MANY_WARNING_ALERTS\\0" "UNABLE_TO_FIND_ECDH_PARAMETERS\\0" "UNEXPECTED_EXTENSION\\0" "UNEXPECTED_MESSAGE\\0" "UNEXPECTED_OPERATOR_IN_GROUP\\0" "UNEXPECTED_RECORD\\0" "UNKNOWN_ALERT_TYPE\\0" "UNKNOWN_CERTIFICATE_TYPE\\0" "UNKNOWN_CIPHER_RETURNED\\0" "UNKNOWN_CIPHER_TYPE\\0" "UNKNOWN_KEY_EXCHANGE_TYPE\\0" "UNKNOWN_PROTOCOL\\0" "UNKNOWN_SSL_VERSION\\0" "UNKNOWN_STATE\\0" "UNSAFE_LEGACY_RENEGOTIATION_DISABLED\\0" "UNSUPPORTED_COMPRESSION_ALGORITHM\\0" "UNSUPPORTED_ELLIPTIC_CURVE\\0" "UNSUPPORTED_PROTOCOL\\0" "UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY\\0" "WRONG_CERTIFICATE_TYPE\\0" "WRONG_CIPHER_RETURNED\\0" "WRONG_CURVE\\0" "WRONG_MESSAGE_TYPE\\0" "WRONG_SIGNATURE_TYPE\\0" "WRONG_SSL_VERSION\\0" "WRONG_VERSION_NUMBER\\0" "X509_LIB\\0" "X509_VERIFICATION_SETUP_PROBLEMS\\0" "AKID_MISMATCH\\0" "BAD_PKCS7_VERSION\\0" "BAD_X509_FILETYPE\\0" "BASE64_DECODE_ERROR\\0" "CANT_CHECK_DH_KEY\\0" "CERT_ALREADY_IN_HASH_TABLE\\0" "CRL_ALREADY_DELTA\\0" "CRL_VERIFY_FAILURE\\0" "IDP_MISMATCH\\0" "INVALID_DIRECTORY\\0" "INVALID_FIELD_NAME\\0" "INVALID_PSS_PARAMETERS\\0" "INVALID_TRUST\\0" "ISSUER_MISMATCH\\0" "KEY_TYPE_MISMATCH\\0" "KEY_VALUES_MISMATCH\\0" "LOADING_CERT_DIR\\0" "LOADING_DEFAULTS\\0" "NAME_TOO_LONG\\0" "NEWER_CRL_NOT_NEWER\\0" "NOT_PKCS7_SIGNED_DATA\\0" "NO_CERTIFICATES_INCLUDED\\0" "NO_CERT_SET_FOR_US_TO_VERIFY\\0" "NO_CRLS_INCLUDED\\0" "NO_CRL_NUMBER\\0" "PUBLIC_KEY_DECODE_ERROR\\0" "PUBLIC_KEY_ENCODE_ERROR\\0" "SHOULD_RETRY\\0" "UNKNOWN_KEY_TYPE\\0" "UNKNOWN_PURPOSE_ID\\0" "UNKNOWN_TRUST_ID\\0" "WRONG_LOOKUP_TYPE\\0" "BAD_IP_ADDRESS\\0" "BAD_OBJECT\\0" "BN_DEC2BN_ERROR\\0" "BN_TO_ASN1_INTEGER_ERROR\\0" "CANNOT_FIND_FREE_FUNCTION\\0" "DIRNAME_ERROR\\0" "DISTPOINT_ALREADY_SET\\0" "DUPLICATE_ZONE_ID\\0" "ERROR_CONVERTING_ZONE\\0" "ERROR_CREATING_EXTENSION\\0" "ERROR_IN_EXTENSION\\0" "EXPECTED_A_SECTION_NAME\\0" "EXTENSION_EXISTS\\0" "EXTENSION_NAME_ERROR\\0" "EXTENSION_NOT_FOUND\\0" "EXTENSION_SETTING_NOT_SUPPORTED\\0" "EXTENSION_VALUE_ERROR\\0" "ILLEGAL_EMPTY_EXTENSION\\0" "ILLEGAL_HEX_DIGIT\\0" "INCORRECT_POLICY_SYNTAX_TAG\\0" "INVALID_BOOLEAN_STRING\\0" "INVALID_EXTENSION_STRING\\0" "INVALID_MULTIPLE_RDNS\\0" "INVALID_NAME\\0" "INVALID_NULL_ARGUMENT\\0" "INVALID_NULL_NAME\\0" "INVALID_NULL_VALUE\\0" "INVALID_NUMBERS\\0" "INVALID_OBJECT_IDENTIFIER\\0" "INVALID_OPTION\\0" "INVALID_POLICY_IDENTIFIER\\0" "INVALID_PROXY_POLICY_SETTING\\0" "INVALID_PURPOSE\\0" "INVALID_SECTION\\0" "INVALID_SYNTAX\\0" "ISSUER_DECODE_ERROR\\0" "NEED_ORGANIZATION_AND_NUMBERS\\0" "NO_CONFIG_DATABASE\\0" "NO_ISSUER_CERTIFICATE\\0" "NO_ISSUER_DETAILS\\0" "NO_POLICY_IDENTIFIER\\0" "NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED\\0" "NO_PUBLIC_KEY\\0" "NO_SUBJECT_DETAILS\\0" "ODD_NUMBER_OF_DIGITS\\0" "OPERATION_NOT_DEFINED\\0" "OTHERNAME_ERROR\\0" "POLICY_LANGUAGE_ALREADY_DEFINED\\0" "POLICY_PATH_LENGTH\\0" "POLICY_PATH_LENGTH_ALREADY_DEFINED\\0" "POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY\\0" "SECTION_NOT_FOUND\\0" "UNABLE_TO_GET_ISSUER_DETAILS\\0" "UNABLE_TO_GET_ISSUER_KEYID\\0" "UNKNOWN_BIT_STRING_ARGUMENT\\0" "UNKNOWN_EXTENSION\\0" "UNKNOWN_EXTENSION_NAME\\0" "UNKNOWN_OPTION\\0" "UNSUPPORTED_OPTION\\0" "USER_TOO_LONG\\0" ""; EOF END_OF_COMMAND end grpc-1.3.2/src/objective-c/CronetFramework.podspec000066400000000000000000000074071310511640000221170ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Pod::Spec.new do |s| s.name = "CronetFramework" v = '0.0.4' s.version = v s.summary = "Cronet, precompiled and used as a framework." s.homepage = "http://chromium.org" s.license = { :type => 'BSD', :text => <<-LICENSE Copyright 2015, Google Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. LICENSE } s.vendored_framework = "Cronet.framework" s.author = "The Chromium Authors" s.ios.deployment_target = "8.0" s.source = { :http => "https://storage.googleapis.com/grpc-precompiled-binaries/cronet/Cronet.framework-v#{v}.zip"} s.preserve_paths = "Cronet.framework" s.public_header_files = "Cronet.framework/Headers/**/*{.h}" s.source_files = "Cronet.framework/Headers/**/*{.h}" end grpc-1.3.2/src/objective-c/GRPCClient/000077500000000000000000000000001310511640000173125ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h000066400000000000000000000045101310511640000230100ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRPCCall.h" #include /** * Methods to configure GRPC channel options. */ @interface GRPCCall (ChannelArg) /** * Use the provided @c userAgentPrefix at the beginning of the HTTP User Agent string for all calls * to the specified @c host. */ + (void)setUserAgentPrefix:(nonnull NSString *)userAgentPrefix forHost:(nonnull NSString *)host; /** The default response size limit is 4MB. Set this to override that default. */ + (void)setResponseSizeLimit:(NSUInteger)limit forHost:(nonnull NSString *)host; + (void)closeOpenConnections DEPRECATED_MSG_ATTRIBUTE("The API for this feature is experimental, " "and might be removed or modified at any " "time."); @end grpc-1.3.2/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m000066400000000000000000000041401310511640000230140ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRPCCall+ChannelArg.h" #import "private/GRPCHost.h" @implementation GRPCCall (ChannelArg) + (void)setUserAgentPrefix:(nonnull NSString *)userAgentPrefix forHost:(nonnull NSString *)host { GRPCHost *hostConfig = [GRPCHost hostWithAddress:host]; hostConfig.userAgentPrefix = userAgentPrefix; } + (void)setResponseSizeLimit:(NSUInteger)limit forHost:(nonnull NSString *)host { GRPCHost *hostConfig = [GRPCHost hostWithAddress:host]; hostConfig.responseSizeLimitOverride = @(limit); } + (void)closeOpenConnections { [GRPCHost flushChannelCache]; } @end grpc-1.3.2/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.h000066400000000000000000000047361310511640000245460ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRPCCall.h" /** Helpers for setting TLS Trusted Roots, Client Certificates, and Private Key */ @interface GRPCCall (ChannelCredentials) /** * Use the provided @c pemRootCert as the set of trusted root Certificate Authorities for @c host. */ + (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCert forHost:(nonnull NSString *)host error:(NSError * _Nullable * _Nullable)errorPtr; /** * Configures @c host with TLS/SSL Client Credentials and optionally trusted root Certificate * Authorities. If @c pemRootCerts is nil, the default CA Certificates bundled with gRPC will be * used. */ + (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCerts withPrivateKey:(nullable NSString *)pemPrivateKey withCertChain:(nullable NSString *)pemCertChain forHost:(nonnull NSString *)host error:(NSError * _Nullable * _Nullable)errorPtr; @end grpc-1.3.2/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.m000066400000000000000000000052221310511640000245420ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRPCCall+ChannelCredentials.h" #import "private/GRPCHost.h" @implementation GRPCCall (ChannelCredentials) + (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCerts withPrivateKey:(nullable NSString *)pemPrivateKey withCertChain:(nullable NSString *)pemCertChain forHost:(nonnull NSString *)host error:(NSError **)errorPtr { if (!host) { [NSException raise:NSInvalidArgumentException format:@"host must be provided."]; } GRPCHost *hostConfig = [GRPCHost hostWithAddress:host]; return [hostConfig setTLSPEMRootCerts:pemRootCerts withPrivateKey:pemPrivateKey withCertChain:pemCertChain error:errorPtr]; } + (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCerts forHost:(nonnull NSString *)host error:(NSError **)errorPtr { return [GRPCCall setTLSPEMRootCerts:pemRootCerts withPrivateKey:nil withCertChain:nil forHost:host error:errorPtr]; } @end grpc-1.3.2/src/objective-c/GRPCClient/GRPCCall+Cronet.h000066400000000000000000000041711310511640000222430ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifdef GRPC_COMPILE_WITH_CRONET #import #import "GRPCCall.h" /** * Methods for using cronet transport. */ @interface GRPCCall (Cronet) /** * This method should be called before issuing the first RPC. It should be * called only once. Create an instance of Cronet engine in your app elsewhere * and pass the instance pointer in the stream_engine parameter. Once set, * all subsequent RPCs will use Cronet transport. The method is not thread * safe. */ +(void)useCronetWithEngine:(stream_engine *)engine; +(stream_engine *)cronetEngine; +(BOOL)isUsingCronet; @end #endif grpc-1.3.2/src/objective-c/GRPCClient/GRPCCall+Cronet.m000066400000000000000000000036611310511640000222530ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRPCCall+Cronet.h" #ifdef GRPC_COMPILE_WITH_CRONET static BOOL useCronet = NO; static stream_engine *globalCronetEngine; @implementation GRPCCall (Cronet) + (void)useCronetWithEngine:(stream_engine *)engine { useCronet = YES; globalCronetEngine = engine; } + (stream_engine *)cronetEngine { return globalCronetEngine; } + (BOOL)isUsingCronet { return useCronet; } @end #endif grpc-1.3.2/src/objective-c/GRPCClient/GRPCCall+OAuth2.h000066400000000000000000000044271310511640000221170ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRPCCall.h" /** Helpers for setting and reading headers compatible with OAuth2. */ @interface GRPCCall (OAuth2) /** * Setting this property is equivalent to setting "Bearer " as the value of the * request header with key "authorization" (the authorization header). Setting it to nil removes the * authorization header from the request. * The value obtained by getting the property is the OAuth2 bearer token if the authorization header * of the request has the form "Bearer ", or nil otherwise. */ @property(atomic, copy) NSString *oauth2AccessToken; /** Returns the value (if any) of the "www-authenticate" response header (the challenge header). */ @property(atomic, readonly) NSString *oauth2ChallengeHeader; @end grpc-1.3.2/src/objective-c/GRPCClient/GRPCCall+OAuth2.m000066400000000000000000000045451310511640000221250ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRPCCall+OAuth2.h" static NSString * const kAuthorizationHeader = @"authorization"; static NSString * const kBearerPrefix = @"Bearer "; static NSString * const kChallengeHeader = @"www-authenticate"; @implementation GRPCCall (OAuth2) - (NSString *)oauth2AccessToken { NSString *headerValue = self.requestHeaders[kAuthorizationHeader]; if ([headerValue hasPrefix:kBearerPrefix]) { return [headerValue substringFromIndex:kBearerPrefix.length]; } else { return nil; } } - (void)setOauth2AccessToken:(NSString *)token { if (token) { self.requestHeaders[kAuthorizationHeader] = [kBearerPrefix stringByAppendingString:token]; } else { [self.requestHeaders removeObjectForKey:kAuthorizationHeader]; } } - (NSString *)oauth2ChallengeHeader { return self.responseHeaders[kChallengeHeader]; } @end grpc-1.3.2/src/objective-c/GRPCClient/GRPCCall+Tests.h000066400000000000000000000052161310511640000221140ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRPCCall.h" /** * Methods to let tune down the security of gRPC connections for specific hosts. These shouldn't be * used in releases, but are sometimes needed for testing. */ @interface GRPCCall (Tests) /** * Establish all SSL connections to the provided host using the passed SSL target name and the root * certificates found in the file at |certsPath|. * * Must be called before any gRPC call to that host is made. It's illegal to pass the same host to * more than one invocation of the methods of this category. */ + (void)useTestCertsPath:(NSString *)certsPath testName:(NSString *)testName forHost:(NSString *)host; /** * Establish all connections to the provided host using cleartext instead of SSL. * * Must be called before any gRPC call to that host is made. It's illegal to pass the same host to * more than one invocation of the methods of this category. */ + (void)useInsecureConnectionsForHost:(NSString *)host; /** * Resets all host configurations to their default values, and flushes all connections from the * cache. */ + (void)resetHostSettings; @end grpc-1.3.2/src/objective-c/GRPCClient/GRPCCall+Tests.m000066400000000000000000000052271310511640000221230ustar00rootroot00000000000000/* * * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRPCCall+Tests.h" #import "private/GRPCHost.h" @implementation GRPCCall (Tests) + (void)useTestCertsPath:(NSString *)certsPath testName:(NSString *)testName forHost:(NSString *)host { if (!host || !certsPath || !testName) { [NSException raise:NSInvalidArgumentException format:@"host, path and name must be provided."]; } NSError *error = nil; NSString *certs = [NSString stringWithContentsOfFile:certsPath encoding:NSUTF8StringEncoding error:&error]; if (error != nil) { [NSException raise:[error localizedDescription] format:@"failed to load certs"]; } GRPCHost *hostConfig = [GRPCHost hostWithAddress:host]; [hostConfig setTLSPEMRootCerts:certs withPrivateKey:nil withCertChain:nil error:nil]; hostConfig.hostNameOverride = testName; } + (void)useInsecureConnectionsForHost:(NSString *)host { GRPCHost *hostConfig = [GRPCHost hostWithAddress:host]; hostConfig.secure = NO; } + (void)resetHostSettings { [GRPCHost resetAllHostSettings]; } @end grpc-1.3.2/src/objective-c/GRPCClient/GRPCCall.h000066400000000000000000000263261310511640000210230ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** * The gRPC protocol is an RPC protocol on top of HTTP2. * * While the most common type of RPC receives only one request message and returns only one response * message, the protocol also supports RPCs that return multiple individual messages in a streaming * fashion, RPCs that accept a stream of request messages, or RPCs with both streaming requests and * responses. * * Conceptually, each gRPC call consists of a bidirectional stream of binary messages, with RPCs of * the "non-streaming type" sending only one message in the corresponding direction (the protocol * doesn't make any distinction). * * Each RPC uses a different HTTP2 stream, and thus multiple simultaneous RPCs can be multiplexed * transparently on the same TCP connection. */ #import #import #include #pragma mark gRPC errors /** Domain of NSError objects produced by gRPC. */ extern NSString *const kGRPCErrorDomain; /** * gRPC error codes. * Note that a few of these are never produced by the gRPC libraries, but are of general utility for * server applications to produce. */ typedef NS_ENUM(NSUInteger, GRPCErrorCode) { /** The operation was cancelled (typically by the caller). */ GRPCErrorCodeCancelled = 1, /** * Unknown error. Errors raised by APIs that do not return enough error information may be * converted to this error. */ GRPCErrorCodeUnknown = 2, /** * The client specified an invalid argument. Note that this differs from FAILED_PRECONDITION. * INVALID_ARGUMENT indicates arguments that are problematic regardless of the state of the * server (e.g., a malformed file name). */ GRPCErrorCodeInvalidArgument = 3, /** * Deadline expired before operation could complete. For operations that change the state of the * server, this error may be returned even if the operation has completed successfully. For * example, a successful response from the server could have been delayed long enough for the * deadline to expire. */ GRPCErrorCodeDeadlineExceeded = 4, /** Some requested entity (e.g., file or directory) was not found. */ GRPCErrorCodeNotFound = 5, /** Some entity that we attempted to create (e.g., file or directory) already exists. */ GRPCErrorCodeAlreadyExists = 6, /** * The caller does not have permission to execute the specified operation. PERMISSION_DENIED isn't * used for rejections caused by exhausting some resource (RESOURCE_EXHAUSTED is used instead for * those errors). PERMISSION_DENIED doesn't indicate a failure to identify the caller * (UNAUTHENTICATED is used instead for those errors). */ GRPCErrorCodePermissionDenied = 7, /** * The request does not have valid authentication credentials for the operation (e.g. the caller's * identity can't be verified). */ GRPCErrorCodeUnauthenticated = 16, /** Some resource has been exhausted, perhaps a per-user quota. */ GRPCErrorCodeResourceExhausted = 8, /** * The RPC was rejected because the server is not in a state required for the procedure's * execution. For example, a directory to be deleted may be non-empty, etc. * The client should not retry until the server state has been explicitly fixed (e.g. by * performing another RPC). The details depend on the service being called, and should be found in * the NSError's userInfo. */ GRPCErrorCodeFailedPrecondition = 9, /** * The RPC was aborted, typically due to a concurrency issue like sequencer check failures, * transaction aborts, etc. The client should retry at a higher-level (e.g., restarting a read- * modify-write sequence). */ GRPCErrorCodeAborted = 10, /** * The RPC was attempted past the valid range. E.g., enumerating past the end of a list. * Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed if the system state * changes. For example, an RPC to get elements of a list will generate INVALID_ARGUMENT if asked * to return the element at a negative index, but it will generate OUT_OF_RANGE if asked to return * the element at an index past the current size of the list. */ GRPCErrorCodeOutOfRange = 11, /** The procedure is not implemented or not supported/enabled in this server. */ GRPCErrorCodeUnimplemented = 12, /** * Internal error. Means some invariant expected by the server application or the gRPC library has * been broken. */ GRPCErrorCodeInternal = 13, /** * The server is currently unavailable. This is most likely a transient condition and may be * corrected by retrying with a backoff. */ GRPCErrorCodeUnavailable = 14, /** Unrecoverable data loss or corruption. */ GRPCErrorCodeDataLoss = 15, }; /** * Safety remark of a gRPC method as defined in RFC 2616 Section 9.1 */ typedef NS_ENUM(NSUInteger, GRPCCallSafety) { /** Signal that there is no guarantees on how the call affects the server state. */ GRPCCallSafetyDefault = 0, /** Signal that the call is idempotent. gRPC is free to use PUT verb. */ GRPCCallSafetyIdempotentRequest = 1, /** Signal that the call is cacheable and will not affect server state. gRPC is free to use GET verb. */ GRPCCallSafetyCacheableRequest = 2, }; /** * Keys used in |NSError|'s |userInfo| dictionary to store the response headers and trailers sent by * the server. */ extern id const kGRPCHeadersKey; extern id const kGRPCTrailersKey; #pragma mark GRPCCall /** Represents a single gRPC remote call. */ @interface GRPCCall : GRXWriter /** * The container of the request headers of an RPC conforms to this protocol, which is a subset of * NSMutableDictionary's interface. It will become a NSMutableDictionary later on. * The keys of this container are the header names, which per the HTTP standard are case- * insensitive. They are stored in lowercase (which is how HTTP/2 mandates them on the wire), and * can only consist of ASCII characters. * A header value is a NSString object (with only ASCII characters), unless the header name has the * suffix "-bin", in which case the value has to be a NSData object. */ /** * These HTTP headers will be passed to the server as part of this call. Each HTTP header is a * name-value pair with string names and either string or binary values. * * The passed dictionary has to use NSString keys, corresponding to the header names. The value * associated to each can be a NSString object or a NSData object. E.g.: * * call.requestHeaders = @{@"authorization": @"Bearer ..."}; * * call.requestHeaders[@"my-header-bin"] = someData; * * After the call is started, trying to modify this property is an error. * * The property is initialized to an empty NSMutableDictionary. */ @property(atomic, readonly) NSMutableDictionary *requestHeaders; /** * This dictionary is populated with the HTTP headers received from the server. This happens before * any response message is received from the server. It has the same structure as the request * headers dictionary: Keys are NSString header names; names ending with the suffix "-bin" have a * NSData value; the others have a NSString value. * * The value of this property is nil until all response headers are received, and will change before * any of -writeValue: or -writesFinishedWithError: are sent to the writeable. */ @property(atomic, readonly) NSDictionary *responseHeaders; /** * Same as responseHeaders, but populated with the HTTP trailers received from the server before the * call finishes. * * The value of this property is nil until all response trailers are received, and will change * before -writesFinishedWithError: is sent to the writeable. */ @property(atomic, readonly) NSDictionary *responseTrailers; /** * The request writer has to write NSData objects into the provided Writeable. The server will * receive each of those separately and in order as distinct messages. * A gRPC call might not complete until the request writer finishes. On the other hand, the request * finishing doesn't necessarily make the call to finish, as the server might continue sending * messages to the response side of the call indefinitely (depending on the semantics of the * specific remote method called). * To finish a call right away, invoke cancel. * host parameter should not contain the scheme (http:// or https://), only the name or IP addr * and the port number, for example @"localhost:5050". */ - (instancetype)initWithHost:(NSString *)host path:(NSString *)path requestsWriter:(GRXWriter *)requestsWriter NS_DESIGNATED_INITIALIZER; /** * Finishes the request side of this call, notifies the server that the RPC should be cancelled, and * finishes the response side of the call with an error of code CANCELED. */ - (void)cancel; /** * Set the call flag for a specific host path. * * Host parameter should not contain the scheme (http:// or https://), only the name or IP addr * and the port number, for example @"localhost:5050". */ + (void)setCallSafety:(GRPCCallSafety)callSafety host:(NSString *)host path:(NSString *)path; // TODO(jcanizales): Let specify a deadline. As a category of GRXWriter? @end #pragma mark Backwards compatibiity /** This protocol is kept for backwards compatibility with existing code. */ DEPRECATED_MSG_ATTRIBUTE("Use NSDictionary or NSMutableDictionary instead.") @protocol GRPCRequestHeaders @property(nonatomic, readonly) NSUInteger count; - (id)objectForKeyedSubscript:(id)key; - (void)setObject:(id)obj forKeyedSubscript:(id)key; - (void)removeAllObjects; - (void)removeObjectForKey:(id)key; @end #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated" /** This is only needed for backwards-compatibility. */ @interface NSMutableDictionary (GRPCRequestHeaders) @end #pragma clang diagnostic pop grpc-1.3.2/src/objective-c/GRPCClient/GRPCCall.m000066400000000000000000000443061310511640000210260ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRPCCall.h" #include #include #import #import #import "private/GRPCConnectivityMonitor.h" #import "private/GRPCHost.h" #import "private/GRPCRequestHeaders.h" #import "private/GRPCWrappedCall.h" #import "private/NSData+GRPC.h" #import "private/NSDictionary+GRPC.h" #import "private/NSError+GRPC.h" // At most 6 ops can be in an op batch for a client: SEND_INITIAL_METADATA, // SEND_MESSAGE, SEND_CLOSE_FROM_CLIENT, RECV_INITIAL_METADATA, RECV_MESSAGE, // and RECV_STATUS_ON_CLIENT. NSInteger kMaxClientBatch = 6; NSString * const kGRPCHeadersKey = @"io.grpc.HeadersKey"; NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; static NSMutableDictionary *callFlags; @interface GRPCCall () // Make them read-write. @property(atomic, strong) NSDictionary *responseHeaders; @property(atomic, strong) NSDictionary *responseTrailers; @end // The following methods of a C gRPC call object aren't reentrant, and thus // calls to them must be serialized: // - start_batch // - destroy // // start_batch with a SEND_MESSAGE argument can only be called after the // OP_COMPLETE event for any previous write is received. This is achieved by // pausing the requests writer immediately every time it writes a value, and // resuming it again when OP_COMPLETE is received. // // Similarly, start_batch with a RECV_MESSAGE argument can only be called after // the OP_COMPLETE event for any previous read is received.This is easier to // enforce, as we're writing the received messages into the writeable: // start_batch is enqueued once upon receiving the OP_COMPLETE event for the // RECV_METADATA batch, and then once after receiving each OP_COMPLETE event for // each RECV_MESSAGE batch. @implementation GRPCCall { dispatch_queue_t _callQueue; NSString *_host; NSString *_path; GRPCWrappedCall *_wrappedCall; GRPCConnectivityMonitor *_connectivityMonitor; // The C gRPC library has less guarantees on the ordering of events than we // do. Particularly, in the face of errors, there's no ordering guarantee at // all. This wrapper over our actual writeable ensures thread-safety and // correct ordering. GRXConcurrentWriteable *_responseWriteable; // The network thread wants the requestWriter to resume (when the server is ready for more input), // or to stop (on errors), concurrently with user threads that want to start it, pause it or stop // it. Because a writer isn't thread-safe, we'll synchronize those operations on it. // We don't use a dispatch queue for that purpose, because the writer can call writeValue: or // writesFinishedWithError: on this GRPCCall as part of those operations. We want to be able to // pause the writer immediately on writeValue:, so we need our locking to be recursive. GRXWriter *_requestWriter; // To create a retain cycle when a call is started, up until it finishes. See // |startWithWriteable:| and |finishWithError:|. This saves users from having to retain a // reference to the call object if all they're interested in is the handler being executed when // the response arrives. GRPCCall *_retainSelf; GRPCRequestHeaders *_requestHeaders; // In the case that the call is a unary call (i.e. the writer to GRPCCall is of type // GRXImmediateSingleWriter), GRPCCall will delay sending ops (not send them to C core // immediately) and buffer them into a batch _unaryOpBatch. The batch is sent to C core when // the SendClose op is added. BOOL _unaryCall; NSMutableArray *_unaryOpBatch; } @synthesize state = _state; // TODO(jcanizales): If grpc_init is idempotent, this should be changed from load to initialize. + (void)load { grpc_init(); callFlags = [NSMutableDictionary dictionary]; } + (void)setCallSafety:(GRPCCallSafety)callSafety host:(NSString *)host path:(NSString *)path { NSString *hostAndPath = [NSString stringWithFormat:@"%@/%@", host, path]; switch (callSafety) { case GRPCCallSafetyDefault: callFlags[hostAndPath] = @0; break; case GRPCCallSafetyIdempotentRequest: callFlags[hostAndPath] = @GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; break; case GRPCCallSafetyCacheableRequest: callFlags[hostAndPath] = @GRPC_INITIAL_METADATA_CACHEABLE_REQUEST; break; default: break; } } + (uint32_t)callFlagsForHost:(NSString *)host path:(NSString *)path { NSString *hostAndPath = [NSString stringWithFormat:@"%@/%@", host, path]; return [callFlags[hostAndPath] intValue]; } - (instancetype)init { return [self initWithHost:nil path:nil requestsWriter:nil]; } // Designated initializer - (instancetype)initWithHost:(NSString *)host path:(NSString *)path requestsWriter:(GRXWriter *)requestWriter { if (!host || !path) { [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; } if (requestWriter.state != GRXWriterStateNotStarted) { [NSException raise:NSInvalidArgumentException format:@"The requests writer can't be already started."]; } if ((self = [super init])) { _host = [host copy]; _path = [path copy]; // Serial queue to invoke the non-reentrant methods of the grpc_call object. _callQueue = dispatch_queue_create("io.grpc.call", NULL); _requestWriter = requestWriter; _requestHeaders = [[GRPCRequestHeaders alloc] initWithCall:self]; if ([requestWriter isKindOfClass:[GRXImmediateSingleWriter class]]) { _unaryCall = YES; _unaryOpBatch = [NSMutableArray arrayWithCapacity:kMaxClientBatch]; } } return self; } #pragma mark Finish - (void)finishWithError:(NSError *)errorOrNil { @synchronized(self) { if (_state == GRXWriterStateFinished) { return; } _state = GRXWriterStateFinished; } // If the call isn't retained anywhere else, it can be deallocated now. _retainSelf = nil; // If there were still request messages coming, stop them. @synchronized(_requestWriter) { _requestWriter.state = GRXWriterStateFinished; } if (errorOrNil) { [_responseWriteable cancelWithError:errorOrNil]; } else { [_responseWriteable enqueueSuccessfulCompletion]; } } - (void)cancelCall { // Can be called from any thread, any number of times. [_wrappedCall cancel]; } - (void)cancel { [self finishWithError:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeCancelled userInfo:@{NSLocalizedDescriptionKey: @"Canceled by app"}]]; [self cancelCall]; } - (void)dealloc { __block GRPCWrappedCall *wrappedCall = _wrappedCall; dispatch_async(_callQueue, ^{ wrappedCall = nil; }); } #pragma mark Read messages // Only called from the call queue. // The handler will be called from the network queue. - (void)startReadWithHandler:(void(^)(grpc_byte_buffer *))handler { // TODO(jcanizales): Add error handlers for async failures [_wrappedCall startBatchWithOperations:@[[[GRPCOpRecvMessage alloc] initWithHandler:handler]]]; } // Called initially from the network queue once response headers are received, // then "recursively" from the responseWriteable queue after each response from the // server has been written. // If the call is currently paused, this is a noop. Restarting the call will invoke this // method. // TODO(jcanizales): Rename to readResponseIfNotPaused. - (void)startNextRead { if (self.state == GRXWriterStatePaused) { return; } __weak GRPCCall *weakSelf = self; __weak GRXConcurrentWriteable *weakWriteable = _responseWriteable; dispatch_async(_callQueue, ^{ [weakSelf startReadWithHandler:^(grpc_byte_buffer *message) { if (message == NULL) { // No more messages from the server return; } NSData *data = [NSData grpc_dataWithByteBuffer:message]; grpc_byte_buffer_destroy(message); if (!data) { // The app doesn't have enough memory to hold the server response. We // don't want to throw, because the app shouldn't crash for a behavior // that's on the hands of any server to have. Instead we finish and ask // the server to cancel. [weakSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeResourceExhausted userInfo:@{NSLocalizedDescriptionKey: @"Client does not have enough memory to hold the server response."}]]; [weakSelf cancelCall]; return; } [weakWriteable enqueueValue:data completionHandler:^{ [weakSelf startNextRead]; }]; }]; }); } #pragma mark Send headers - (void)sendHeaders:(NSDictionary *)headers { // TODO(jcanizales): Add error handlers for async failures GRPCOpSendMetadata *op = [[GRPCOpSendMetadata alloc] initWithMetadata:headers flags:[GRPCCall callFlagsForHost:_host path:_path] handler:nil]; // No clean-up needed after SEND_INITIAL_METADATA if (!_unaryCall) { [_wrappedCall startBatchWithOperations:@[op]]; } else { [_unaryOpBatch addObject:op]; } } #pragma mark GRXWriteable implementation // Only called from the call queue. The error handler will be called from the // network queue if the write didn't succeed. // If the call is a unary call, parameter \a errorHandler will be ignored and // the error handler of GRPCOpSendClose will be executed in case of error. - (void)writeMessage:(NSData *)message withErrorHandler:(void (^)())errorHandler { __weak GRPCCall *weakSelf = self; void(^resumingHandler)(void) = ^{ // Resume the request writer. GRPCCall *strongSelf = weakSelf; if (strongSelf) { @synchronized(strongSelf->_requestWriter) { strongSelf->_requestWriter.state = GRXWriterStateStarted; } } }; GRPCOpSendMessage *op = [[GRPCOpSendMessage alloc] initWithMessage:message handler:resumingHandler]; if (!_unaryCall) { [_wrappedCall startBatchWithOperations:@[op] errorHandler:errorHandler]; } else { // Ignored errorHandler since it is the same as the one for GRPCOpSendClose. // TODO (mxyan): unify the error handlers of all Ops into a single closure. [_unaryOpBatch addObject:op]; } } - (void)writeValue:(id)value { // TODO(jcanizales): Throw/assert if value isn't NSData. // Pause the input and only resume it when the C layer notifies us that writes // can proceed. @synchronized(_requestWriter) { _requestWriter.state = GRXWriterStatePaused; } __weak GRPCCall *weakSelf = self; dispatch_async(_callQueue, ^{ [weakSelf writeMessage:value withErrorHandler:^{ [weakSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeInternal userInfo:nil]]; }]; }); } // Only called from the call queue. The error handler will be called from the // network queue if the requests stream couldn't be closed successfully. - (void)finishRequestWithErrorHandler:(void (^)())errorHandler { if (!_unaryCall) { [_wrappedCall startBatchWithOperations:@[[[GRPCOpSendClose alloc] init]] errorHandler:errorHandler]; } else { [_unaryOpBatch addObject:[[GRPCOpSendClose alloc] init]]; [_wrappedCall startBatchWithOperations:_unaryOpBatch errorHandler:errorHandler]; } } - (void)writesFinishedWithError:(NSError *)errorOrNil { if (errorOrNil) { [self cancel]; } else { __weak GRPCCall *weakSelf = self; dispatch_async(_callQueue, ^{ [weakSelf finishRequestWithErrorHandler:^{ [weakSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeInternal userInfo:nil]]; }]; }); } } #pragma mark Invoke // Both handlers will eventually be called, from the network queue. Writes can start immediately // after this. // The first one (headersHandler), when the response headers are received. // The second one (completionHandler), whenever the RPC finishes for any reason. - (void)invokeCallWithHeadersHandler:(void(^)(NSDictionary *))headersHandler completionHandler:(void(^)(NSError *, NSDictionary *))completionHandler { // TODO(jcanizales): Add error handlers for async failures [_wrappedCall startBatchWithOperations:@[[[GRPCOpRecvMetadata alloc] initWithHandler:headersHandler]]]; [_wrappedCall startBatchWithOperations:@[[[GRPCOpRecvStatus alloc] initWithHandler:completionHandler]]]; } - (void)invokeCall { [self invokeCallWithHeadersHandler:^(NSDictionary *headers) { // Response headers received. self.responseHeaders = headers; [self startNextRead]; } completionHandler:^(NSError *error, NSDictionary *trailers) { self.responseTrailers = trailers; if (error) { NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; if (error.userInfo) { [userInfo addEntriesFromDictionary:error.userInfo]; } userInfo[kGRPCTrailersKey] = self.responseTrailers; // TODO(jcanizales): The C gRPC library doesn't guarantee that the headers block will be // called before this one, so an error might end up with trailers but no headers. We // shouldn't call finishWithError until ater both blocks are called. It is also when this is // done that we can provide a merged view of response headers and trailers in a thread-safe // way. if (self.responseHeaders) { userInfo[kGRPCHeadersKey] = self.responseHeaders; } error = [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo]; } [self finishWithError:error]; }]; // Now that the RPC has been initiated, request writes can start. @synchronized(_requestWriter) { [_requestWriter startWithWriteable:self]; } } #pragma mark GRXWriter implementation - (void)startWithWriteable:(id)writeable { @synchronized(self) { _state = GRXWriterStateStarted; } // Create a retain cycle so that this instance lives until the RPC finishes (or is cancelled). // This makes RPCs in which the call isn't externally retained possible (as long as it is started // before being autoreleased). // Care is taken not to retain self strongly in any of the blocks used in this implementation, so // that the life of the instance is determined by this retain cycle. _retainSelf = self; _responseWriteable = [[GRXConcurrentWriteable alloc] initWithWriteable:writeable]; _wrappedCall = [[GRPCWrappedCall alloc] initWithHost:_host path:_path]; NSAssert(_wrappedCall, @"Error allocating RPC objects. Low memory?"); [self sendHeaders:_requestHeaders]; [self invokeCall]; // TODO(jcanizales): Extract this logic somewhere common. NSString *host = [NSURL URLWithString:[@"https://" stringByAppendingString:_host]].host; if (!host) { // TODO(jcanizales): Check this on init. [NSException raise:NSInvalidArgumentException format:@"host of %@ is nil", _host]; } __weak typeof(self) weakSelf = self; _connectivityMonitor = [GRPCConnectivityMonitor monitorWithHost:host]; void (^handler)() = ^{ typeof(self) strongSelf = weakSelf; if (strongSelf) { [strongSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeUnavailable userInfo:@{ NSLocalizedDescriptionKey : @"Connectivity lost." }]]; } }; [_connectivityMonitor handleLossWithHandler:handler wifiStatusChangeHandler:nil]; } - (void)setState:(GRXWriterState)newState { @synchronized(self) { // Manual transitions are only allowed from the started or paused states. if (_state == GRXWriterStateNotStarted || _state == GRXWriterStateFinished) { return; } switch (newState) { case GRXWriterStateFinished: _state = newState; // Per GRXWriter's contract, setting the state to Finished manually // means one doesn't wish the writeable to be messaged anymore. [_responseWriteable cancelSilently]; _responseWriteable = nil; return; case GRXWriterStatePaused: _state = newState; return; case GRXWriterStateStarted: if (_state == GRXWriterStatePaused) { _state = newState; [self startNextRead]; } return; case GRXWriterStateNotStarted: return; } } } @end grpc-1.3.2/src/objective-c/GRPCClient/README.md000066400000000000000000000002301310511640000205640ustar00rootroot00000000000000This is a generic gRPC client for Objective-C on iOS. If you're trying to get started with the library or with gRPC, you should first read GRPCCall.h. grpc-1.3.2/src/objective-c/GRPCClient/internal_testing/000077500000000000000000000000001310511640000226635ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/GRPCClient/internal_testing/GRPCCall+InternalTests.h000066400000000000000000000044611310511640000271630ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifdef GRPC_TEST_OBJC #import "../GRPCCall.h" /** * Methods used for gRPC internal tests. DO NOT USE. */ @interface GRPCCall (InternalTests) /** * Enables logging of op batches. Memory consumption increases as more ops are logged. * * This function is for internal testing of gRPC only. It is not part of gRPC's public interface. * Do not use in production. To enable, set the preprocessor flag GRPC_TEST_OBJC. */ + (void)enableOpBatchLog:(BOOL)enabled; /** * Obtain the logged op batches. Invoking this method will clean the log. * * This function is for internal testing of gRPC only. It is not part of gRPC's public interface. * Do not use in production. To enable, set the preprocessor flag GRPC_TEST_OBJC. */ + (NSArray *)obtainAndCleanOpBatchLog; @end #endif grpc-1.3.2/src/objective-c/GRPCClient/internal_testing/GRPCCall+InternalTests.m000066400000000000000000000035631310511640000271720ustar00rootroot00000000000000/* * * Copyright 2017, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifdef GRPC_TEST_OBJC #import "GRPCCall+InternalTests.h" #import "../private/GRPCOpBatchLog.h" @implementation GRPCCall (InternalTests) + (void)enableOpBatchLog:(BOOL)enabled { [GRPCOpBatchLog enableOpBatchLog:enabled]; } + (NSArray *)obtainAndCleanOpBatchLog { return [GRPCOpBatchLog obtainAndCleanOpBatchLog]; } @end #endif grpc-1.3.2/src/objective-c/GRPCClient/private/000077500000000000000000000000001310511640000207645ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/GRPCClient/private/GRPCChannel.h000066400000000000000000000064501310511640000231660ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #include @class GRPCCompletionQueue; struct grpc_channel_credentials; /** * Each separate instance of this class represents at least one TCP connection to the provided host. */ @interface GRPCChannel : NSObject @property(nonatomic, readonly, nonnull) struct grpc_channel *unmanagedChannel; - (nullable instancetype)init NS_UNAVAILABLE; /** * Creates a secure channel to the specified @c host using default credentials and channel * arguments. If certificates could not be found to create a secure channel, then @c nil is * returned. */ + (nullable GRPCChannel *)secureChannelWithHost:(nonnull NSString *)host; /** * Creates a secure channel to the specified @c host using Cronet as a transport mechanism. */ #ifdef GRPC_COMPILE_WITH_CRONET + (nullable GRPCChannel *)secureCronetChannelWithHost:(nonnull NSString *)host channelArgs:(nonnull NSDictionary *)channelArgs; #endif /** * Creates a secure channel to the specified @c host using the specified @c credentials and * @c channelArgs. Only in tests should @c GRPC_SSL_TARGET_NAME_OVERRIDE_ARG channel arg be set. */ + (nonnull GRPCChannel *)secureChannelWithHost:(nonnull NSString *)host credentials:(nonnull struct grpc_channel_credentials *)credentials channelArgs:(nullable NSDictionary *)channelArgs; /** * Creates an insecure channel to the specified @c host using the specified @c channelArgs. */ + (nonnull GRPCChannel *)insecureChannelWithHost:(nonnull NSString *)host channelArgs:(nullable NSDictionary *)channelArgs; - (nullable grpc_call *)unmanagedCallWithPath:(nonnull NSString *)path completionQueue:(nonnull GRPCCompletionQueue *)queue; @end grpc-1.3.2/src/objective-c/GRPCClient/private/GRPCChannel.m000066400000000000000000000170301310511640000231670ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRPCChannel.h" #include #ifdef GRPC_COMPILE_WITH_CRONET #include #endif #include #include #include #ifdef GRPC_COMPILE_WITH_CRONET #import #import #endif #import "GRPCCompletionQueue.h" static void FreeChannelArgs(grpc_channel_args *channel_args) { for (size_t i = 0; i < channel_args->num_args; ++i) { grpc_arg *arg = &channel_args->args[i]; gpr_free(arg->key); if (arg->type == GRPC_ARG_STRING) { gpr_free(arg->value.string); } } gpr_free(channel_args); } /** * Allocates a @c grpc_channel_args and populates it with the options specified in the * @c dictionary. Keys must be @c NSString. If the value responds to @c @selector(UTF8String) then * it will be mapped to @c GRPC_ARG_STRING. If not, it will be mapped to @c GRPC_ARG_INTEGER if the * value responds to @c @selector(intValue). Otherwise, an exception will be raised. The caller of * this function is responsible for calling @c freeChannelArgs on a non-NULL returned value. */ static grpc_channel_args *BuildChannelArgs(NSDictionary *dictionary) { if (!dictionary) { return NULL; } NSArray *keys = [dictionary allKeys]; NSUInteger argCount = [keys count]; grpc_channel_args *channelArgs = gpr_malloc(sizeof(grpc_channel_args)); channelArgs->num_args = argCount; channelArgs->args = gpr_malloc(argCount * sizeof(grpc_arg)); // TODO(kriswuollett) Check that keys adhere to GRPC core library requirements for (NSUInteger i = 0; i < argCount; ++i) { grpc_arg *arg = &channelArgs->args[i]; arg->key = gpr_strdup([keys[i] UTF8String]); id value = dictionary[keys[i]]; if ([value respondsToSelector:@selector(UTF8String)]) { arg->type = GRPC_ARG_STRING; arg->value.string = gpr_strdup([value UTF8String]); } else if ([value respondsToSelector:@selector(intValue)]) { arg->type = GRPC_ARG_INTEGER; arg->value.integer = [value intValue]; } else { [NSException raise:NSInvalidArgumentException format:@"Invalid value type: %@", [value class]]; } } return channelArgs; } @implementation GRPCChannel { // Retain arguments to channel_create because they may not be used on the thread that invoked // the channel_create function. NSString *_host; grpc_channel_args *_channelArgs; } #ifdef GRPC_COMPILE_WITH_CRONET - (instancetype)initWithHost:(NSString *)host cronetEngine:(stream_engine *)cronetEngine channelArgs:(NSDictionary *)channelArgs { if (!host) { [NSException raise:NSInvalidArgumentException format:@"host argument missing"]; } if (self = [super init]) { _channelArgs = BuildChannelArgs(channelArgs); _host = [host copy]; _unmanagedChannel = grpc_cronet_secure_channel_create(cronetEngine, _host.UTF8String, _channelArgs, NULL); } return self; } #endif - (instancetype)initWithHost:(NSString *)host secure:(BOOL)secure credentials:(struct grpc_channel_credentials *)credentials channelArgs:(NSDictionary *)channelArgs { if (!host) { [NSException raise:NSInvalidArgumentException format:@"host argument missing"]; } if (secure && !credentials) { return nil; } if (self = [super init]) { _channelArgs = BuildChannelArgs(channelArgs); _host = [host copy]; if (secure) { _unmanagedChannel = grpc_secure_channel_create(credentials, _host.UTF8String, _channelArgs, NULL); } else { _unmanagedChannel = grpc_insecure_channel_create(_host.UTF8String, _channelArgs, NULL); } } return self; } - (void)dealloc { // TODO(jcanizales): Be sure to add a test with a server that closes the connection prematurely, // as in the past that made this call to crash. grpc_channel_destroy(_unmanagedChannel); FreeChannelArgs(_channelArgs); } #ifdef GRPC_COMPILE_WITH_CRONET + (GRPCChannel *)secureCronetChannelWithHost:(NSString *)host channelArgs:(NSDictionary *)channelArgs { stream_engine *engine = [GRPCCall cronetEngine]; if (!engine) { [NSException raise:NSInvalidArgumentException format:@"cronet_engine is NULL. Set it first."]; return nil; } return [[GRPCChannel alloc] initWithHost:host cronetEngine:engine channelArgs:channelArgs]; } #endif + (GRPCChannel *)secureChannelWithHost:(NSString *)host { return [[GRPCChannel alloc] initWithHost:host secure:YES credentials:NULL channelArgs:NULL]; } + (GRPCChannel *)secureChannelWithHost:(NSString *)host credentials:(struct grpc_channel_credentials *)credentials channelArgs:(NSDictionary *)channelArgs { return [[GRPCChannel alloc] initWithHost:host secure:YES credentials:credentials channelArgs:channelArgs]; } + (GRPCChannel *)insecureChannelWithHost:(NSString *)host channelArgs:(NSDictionary *)channelArgs { return [[GRPCChannel alloc] initWithHost:host secure:NO credentials:NULL channelArgs:channelArgs]; } - (grpc_call *)unmanagedCallWithPath:(NSString *)path completionQueue:(GRPCCompletionQueue *)queue { return grpc_channel_create_call(_unmanagedChannel, NULL, GRPC_PROPAGATE_DEFAULTS, queue.unmanagedQueue, grpc_slice_from_copied_string(path.UTF8String), NULL, // Passing NULL for host gpr_inf_future(GPR_CLOCK_REALTIME), NULL); } @end grpc-1.3.2/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h000066400000000000000000000047241310511640000247360ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #include typedef void(^GRPCQueueCompletionHandler)(bool success); /** * This class lets one more easily use |grpc_completion_queue|. To use it, pass the value of the * |unmanagedQueue| property of an instance of this class to |grpc_channel_create_call|. Then for * every |grpc_call_*| method that accepts a tag, you can pass a block of type * |GRPCQueueCompletionHandler| (remembering to cast it using |__bridge_retained|). The block is * guaranteed to eventually be called, by a concurrent queue, and then released. Each such block is * passed a |bool| that tells if the operation was successful. * * Release the GRPCCompletionQueue object only after you are not going to pass any more blocks to * the |grpc_call| that's using it. */ @interface GRPCCompletionQueue : NSObject @property(nonatomic, readonly) grpc_completion_queue *unmanagedQueue; + (instancetype)completionQueue; @end grpc-1.3.2/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m000066400000000000000000000076641310511640000247510ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRPCCompletionQueue.h" #import @implementation GRPCCompletionQueue + (instancetype)completionQueue { static GRPCCompletionQueue *singleton = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ singleton = [[self alloc] init]; }); return singleton; } - (instancetype)init { if ((self = [super init])) { _unmanagedQueue = grpc_completion_queue_create(NULL); // This is for the following block to capture the pointer by value (instead // of retaining self and doing self->_unmanagedQueue). This is essential // because the block doesn't end until after grpc_completion_queue_shutdown // is called, and we only want that to happen after nobody's using the queue // anymore (i.e. on self dealloc). So the block would never end if it // retained self. grpc_completion_queue *unmanagedQueue = _unmanagedQueue; // Start a loop on a concurrent queue to read events from the completion // queue and dispatch each. static dispatch_once_t initialization; static dispatch_queue_t gDefaultConcurrentQueue; dispatch_once(&initialization, ^{ gDefaultConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); }); dispatch_async(gDefaultConcurrentQueue, ^{ while (YES) { // The following call blocks until an event is available. grpc_event event = grpc_completion_queue_next(unmanagedQueue, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); GRPCQueueCompletionHandler handler; switch (event.type) { case GRPC_OP_COMPLETE: handler = (__bridge_transfer GRPCQueueCompletionHandler)event.tag; handler(event.success); break; case GRPC_QUEUE_SHUTDOWN: grpc_completion_queue_destroy(unmanagedQueue); return; default: [NSException raise:@"Unrecognized completion type" format:@""]; } }; }); } return self; } - (void)dealloc { // This makes the completion queue produce a GRPC_QUEUE_SHUTDOWN event *after* // all other pending events are flushed. What this means is all the blocks // passed to the gRPC C library as void* are eventually called, even if some // are called after self is dealloc'd. grpc_completion_queue_shutdown(_unmanagedQueue); } @end grpc-1.3.2/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.h000066400000000000000000000060001310511640000256330ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import @interface GRPCReachabilityFlags : NSObject + (nonnull instancetype)flagsWithFlags:(SCNetworkReachabilityFlags)flags; /** * One accessor method to query each of the different flags. Example: @property(nonatomic, readonly) BOOL isCell; */ #define GRPC_XMACRO_ITEM(methodName, FlagName) \ @property(nonatomic, readonly) BOOL methodName; #include "GRPCReachabilityFlagNames.xmacro.h" #undef GRPC_XMACRO_ITEM @property(nonatomic, readonly) BOOL isHostReachable; @end @interface GRPCConnectivityMonitor : NSObject + (nullable instancetype)monitorWithHost:(nonnull NSString *)hostName; - (nonnull instancetype)init NS_UNAVAILABLE; /** * Queue on which callbacks will be dispatched. Default is the main queue. Set it before calling * handleLossWithHandler:. */ // TODO(jcanizales): Default to a serial background queue instead. @property(nonatomic, strong, null_resettable) dispatch_queue_t queue; /** * Calls handler every time the connectivity to this instance's host is lost. If this instance is * released before that happens, the handler won't be called. * Only one handler is active at a time, so if this method is called again before the previous * handler has been called, it might never be called at all (or yes, if it has already been queued). */ - (void)handleLossWithHandler:(nullable void (^)())lossHandler wifiStatusChangeHandler:(nullable void (^)())wifiStatusChangeHandler; @end grpc-1.3.2/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.m000066400000000000000000000154171310511640000256540ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRPCConnectivityMonitor.h" #pragma mark Flags @implementation GRPCReachabilityFlags { SCNetworkReachabilityFlags _flags; } + (instancetype)flagsWithFlags:(SCNetworkReachabilityFlags)flags { return [[self alloc] initWithFlags:flags]; } - (instancetype)initWithFlags:(SCNetworkReachabilityFlags)flags { if ((self = [super init])) { _flags = flags; } return self; } /* * One accessor method implementation per flag. Example: - (BOOL)isCell { \ return !!(_flags & kSCNetworkReachabilityFlagsIsWWAN); \ } */ #define GRPC_XMACRO_ITEM(methodName, FlagName) \ - (BOOL)methodName { \ return !!(_flags & kSCNetworkReachabilityFlags ## FlagName); \ } #include "GRPCReachabilityFlagNames.xmacro.h" #undef GRPC_XMACRO_ITEM - (BOOL)isHostReachable { // Note: connectionOnDemand means it'll be reachable only if using the CFSocketStream API or APIs // on top of it. // connectionRequired means we can't tell until a connection is attempted (e.g. for VPN on // demand). return self.reachable && !self.interventionRequired && !self.connectionOnDemand; } - (NSString *)description { NSMutableArray *activeOptions = [NSMutableArray arrayWithCapacity:9]; /* * For each flag, add its name to the array if it's ON. Example: if (self.isCell) { [activeOptions addObject:@"isCell"]; } */ #define GRPC_XMACRO_ITEM(methodName, FlagName) \ if (self.methodName) { \ [activeOptions addObject:@ #methodName]; \ } #include "GRPCReachabilityFlagNames.xmacro.h" #undef GRPC_XMACRO_ITEM return activeOptions.count == 0 ? @"(none)" : [activeOptions componentsJoinedByString:@", "]; } - (BOOL)isEqual:(id)object { return [object isKindOfClass:[GRPCReachabilityFlags class]] && _flags == ((GRPCReachabilityFlags *)object)->_flags; } - (NSUInteger)hash { return _flags; } @end #pragma mark Connectivity Monitor // Assumes the third argument is a block that accepts a GRPCReachabilityFlags object, and passes the // received ones to it. static void PassFlagsToContextInfoBlock(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info) { #pragma unused (target) // This can be called many times with the same info. The info is retained by SCNetworkReachability // while this function is being executed. void (^handler)(GRPCReachabilityFlags *) = (__bridge void (^)(GRPCReachabilityFlags *))info; handler([[GRPCReachabilityFlags alloc] initWithFlags:flags]); } @implementation GRPCConnectivityMonitor { SCNetworkReachabilityRef _reachabilityRef; GRPCReachabilityFlags *_previousReachabilityFlags; } - (nullable instancetype)initWithReachability:(nullable SCNetworkReachabilityRef)reachability { if (!reachability) { return nil; } if ((self = [super init])) { _reachabilityRef = CFRetain(reachability); _queue = dispatch_get_main_queue(); _previousReachabilityFlags = nil; } return self; } + (nullable instancetype)monitorWithHost:(nonnull NSString *)host { const char *hostName = host.UTF8String; if (!hostName) { [NSException raise:NSInvalidArgumentException format:@"host.UTF8String returns NULL for %@", host]; } SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, hostName); GRPCConnectivityMonitor *returnValue = [[self alloc] initWithReachability:reachability]; if (reachability) { CFRelease(reachability); } return returnValue; } - (void)handleLossWithHandler:(nullable void (^)())lossHandler wifiStatusChangeHandler:(nullable void (^)())wifiStatusChangeHandler { __weak typeof(self) weakSelf = self; [self startListeningWithHandler:^(GRPCReachabilityFlags *flags) { typeof(self) strongSelf = weakSelf; if (strongSelf) { if (lossHandler && !flags.reachable) { lossHandler(); #if TARGET_OS_IPHONE } else if (wifiStatusChangeHandler && strongSelf->_previousReachabilityFlags && (flags.isWWAN ^ strongSelf->_previousReachabilityFlags.isWWAN)) { wifiStatusChangeHandler(); #endif } strongSelf->_previousReachabilityFlags = flags; } }]; } - (void)startListeningWithHandler:(void (^)(GRPCReachabilityFlags *))handler { // Copy to ensure the handler block is in the heap (and so can't be deallocated when this method // returns). void (^copiedHandler)(GRPCReachabilityFlags *) = [handler copy]; SCNetworkReachabilityContext context = { .version = 0, .info = (__bridge void *)copiedHandler, .retain = CFRetain, .release = CFRelease, }; // The following will retain context.info, and release it when the callback is set to NULL. SCNetworkReachabilitySetCallback(_reachabilityRef, PassFlagsToContextInfoBlock, &context); SCNetworkReachabilitySetDispatchQueue(_reachabilityRef, _queue); } - (void)stopListening { // This releases the block on context.info. SCNetworkReachabilitySetCallback(_reachabilityRef, NULL, NULL); SCNetworkReachabilitySetDispatchQueue(_reachabilityRef, NULL); } - (void)setQueue:(dispatch_queue_t)queue { _queue = queue ?: dispatch_get_main_queue(); } - (void)dealloc { if (_reachabilityRef) { [self stopListening]; CFRelease(_reachabilityRef); } } @end grpc-1.3.2/src/objective-c/GRPCClient/private/GRPCHost.h000066400000000000000000000070551310511640000225350ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import NS_ASSUME_NONNULL_BEGIN @class GRPCCompletionQueue; struct grpc_call; struct grpc_channel_credentials; @interface GRPCHost : NSObject + (void)flushChannelCache; + (void)resetAllHostSettings; @property(nonatomic, readonly) NSString *address; @property(nonatomic, copy, nullable) NSString *userAgentPrefix; @property(nonatomic, nullable) struct grpc_channel_credentials *channelCreds; /** The following properties should only be modified for testing: */ @property(nonatomic, getter=isSecure) BOOL secure; @property(nonatomic, copy, nullable) NSString *hostNameOverride; /** The default response size limit is 4MB. Set this to override that default. */ @property(nonatomic, strong, nullable) NSNumber *responseSizeLimitOverride; - (nullable instancetype)init NS_UNAVAILABLE; /** Host objects initialized with the same address are the same. */ + (nullable instancetype)hostWithAddress:(NSString *)address; - (nullable instancetype)initWithAddress:(NSString *)address NS_DESIGNATED_INITIALIZER; - (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCerts withPrivateKey:(nullable NSString *)pemPrivateKey withCertChain:(nullable NSString *)pemCertChain error:(NSError **)errorPtr; /** Create a grpc_call object to the provided path on this host. */ - (nullable struct grpc_call *)unmanagedCallWithPath:(NSString *)path completionQueue:(GRPCCompletionQueue *)queue; // TODO: There's a race when a new RPC is coming through just as an existing one is getting // notified that there's no connectivity. If connectivity comes back at that moment, the new RPC // will have its channel destroyed by the other RPC, and will never get notified of a problem, so // it'll hang (the C layer logs a timeout, with exponential back off). One solution could be to pass // the GRPCChannel to the GRPCCall, renaming this as "disconnectChannel:channel", which would only // act on that specific channel. - (void)disconnect; @end NS_ASSUME_NONNULL_END grpc-1.3.2/src/objective-c/GRPCClient/private/GRPCHost.m000066400000000000000000000237011310511640000225360ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRPCHost.h" #include #include #import #ifdef GRPC_COMPILE_WITH_CRONET #import #import #endif #import "GRPCChannel.h" #import "GRPCCompletionQueue.h" #import "GRPCConnectivityMonitor.h" #import "NSDictionary+GRPC.h" #import "version.h" NS_ASSUME_NONNULL_BEGIN static NSMutableDictionary *kHostCache; // This connectivity monitor flushes the host cache when connectivity status // changes or when connection switch between Wifi and Cellular data, so that a // new call will use a new channel. Otherwise, a new call will still use the // cached channel which is no longer available and will cause gRPC to hang. static GRPCConnectivityMonitor *connectivityMonitor = nil; @implementation GRPCHost { // TODO(mlumish): Investigate whether caching channels with strong links is a good idea. GRPCChannel *_channel; } + (nullable instancetype)hostWithAddress:(NSString *)address { return [[self alloc] initWithAddress:address]; } - (void)dealloc { if (_channelCreds != nil) { grpc_channel_credentials_release(_channelCreds); } } // Default initializer. - (nullable instancetype)initWithAddress:(NSString *)address { if (!address) { return nil; } // To provide a default port, we try to interpret the address. If it's just a host name without // scheme and without port, we'll use port 443. If it has a scheme, we pass it untouched to the C // gRPC library. // TODO(jcanizales): Add unit tests for the types of addresses we want to let pass untouched. NSURL *hostURL = [NSURL URLWithString:[@"https://" stringByAppendingString:address]]; if (hostURL.host && !hostURL.port) { address = [hostURL.host stringByAppendingString:@":443"]; } // Look up the GRPCHost in the cache. static dispatch_once_t cacheInitialization; dispatch_once(&cacheInitialization, ^{ kHostCache = [NSMutableDictionary dictionary]; }); @synchronized(kHostCache) { GRPCHost *cachedHost = kHostCache[address]; if (cachedHost) { return cachedHost; } if ((self = [super init])) { _address = address; _secure = YES; kHostCache[address] = self; } // Keep a single monitor to flush the cache if the connectivity status changes // Thread safety guarded by @synchronized(kHostCache) if (!connectivityMonitor) { connectivityMonitor = [GRPCConnectivityMonitor monitorWithHost:hostURL.host]; void (^handler)() = ^{ [GRPCHost flushChannelCache]; }; [connectivityMonitor handleLossWithHandler:handler wifiStatusChangeHandler:handler]; } } return self; } + (void)flushChannelCache { @synchronized(kHostCache) { [kHostCache enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, GRPCHost * _Nonnull host, BOOL * _Nonnull stop) { [host disconnect]; }]; } } + (void)resetAllHostSettings { @synchronized (kHostCache) { kHostCache = [NSMutableDictionary dictionary]; } } - (nullable grpc_call *)unmanagedCallWithPath:(NSString *)path completionQueue:(GRPCCompletionQueue *)queue { GRPCChannel *channel; // This is racing -[GRPCHost disconnect]. @synchronized(self) { if (!_channel) { _channel = [self newChannel]; } channel = _channel; } return [channel unmanagedCallWithPath:path completionQueue:queue]; } - (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCerts withPrivateKey:(nullable NSString *)pemPrivateKey withCertChain:(nullable NSString *)pemCertChain error:(NSError **)errorPtr { static NSData *kDefaultRootsASCII; static NSError *kDefaultRootsError; static dispatch_once_t loading; dispatch_once(&loading, ^{ NSString *defaultPath = @"gRPCCertificates.bundle/roots"; // .pem // Do not use NSBundle.mainBundle, as it's nil for tests of library projects. NSBundle *bundle = [NSBundle bundleForClass:self.class]; NSString *path = [bundle pathForResource:defaultPath ofType:@"pem"]; NSError *error; // Files in PEM format can have non-ASCII characters in their comments (e.g. for the name of the // issuer). Load them as UTF8 and produce an ASCII equivalent. NSString *contentInUTF8 = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error]; if (contentInUTF8 == nil) { kDefaultRootsError = error; return; } kDefaultRootsASCII = [contentInUTF8 dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; }); NSData *rootsASCII; if (pemRootCerts != nil) { rootsASCII = [pemRootCerts dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; } else { if (kDefaultRootsASCII == nil) { if (errorPtr) { *errorPtr = kDefaultRootsError; } NSAssert(kDefaultRootsASCII, @"Could not read gRPCCertificates.bundle/roots.pem. This file, " "with the root certificates, is needed to establish secure (TLS) connections. " "Because the file is distributed with the gRPC library, this error is usually a sign " "that the library wasn't configured correctly for your project. Error: %@", kDefaultRootsError); return NO; } rootsASCII = kDefaultRootsASCII; } grpc_channel_credentials *creds; if (pemPrivateKey == nil && pemCertChain == nil) { creds = grpc_ssl_credentials_create(rootsASCII.bytes, NULL, NULL); } else { grpc_ssl_pem_key_cert_pair key_cert_pair; NSData *privateKeyASCII = [pemPrivateKey dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; NSData *certChainASCII = [pemCertChain dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; key_cert_pair.private_key = privateKeyASCII.bytes; key_cert_pair.cert_chain = certChainASCII.bytes; creds = grpc_ssl_credentials_create(rootsASCII.bytes, &key_cert_pair, NULL); } @synchronized(self) { if (_channelCreds != nil) { grpc_channel_credentials_release(_channelCreds); } _channelCreds = creds; } return YES; } - (NSDictionary *)channelArgs { NSMutableDictionary *args = [NSMutableDictionary dictionary]; // TODO(jcanizales): Add OS and device information (see // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#user-agents ). NSString *userAgent = @"grpc-objc/" GRPC_OBJC_VERSION_STRING; if (_userAgentPrefix) { userAgent = [_userAgentPrefix stringByAppendingFormat:@" %@", userAgent]; } args[@GRPC_ARG_PRIMARY_USER_AGENT_STRING] = userAgent; if (_secure && _hostNameOverride) { args[@GRPC_SSL_TARGET_NAME_OVERRIDE_ARG] = _hostNameOverride; } if (_responseSizeLimitOverride) { args[@GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH] = _responseSizeLimitOverride; } // Use 10000ms initial backoff time for correct behavior on bad/slow networks args[@GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS] = @10000; return args; } - (GRPCChannel *)newChannel { NSDictionary *args = [self channelArgs]; #ifdef GRPC_COMPILE_WITH_CRONET BOOL useCronet = [GRPCCall isUsingCronet]; #endif if (_secure) { GRPCChannel *channel; @synchronized(self) { if (_channelCreds == nil) { [self setTLSPEMRootCerts:nil withPrivateKey:nil withCertChain:nil error:nil]; } #ifdef GRPC_COMPILE_WITH_CRONET if (useCronet) { channel = [GRPCChannel secureCronetChannelWithHost:_address channelArgs:args]; } else #endif { channel = [GRPCChannel secureChannelWithHost:_address credentials:_channelCreds channelArgs:args]; } } return channel; } else { return [GRPCChannel insecureChannelWithHost:_address channelArgs:args]; } } - (NSString *)hostName { // TODO(jcanizales): Default to nil instead of _address when Issue #2635 is clarified. return _hostNameOverride ?: _address; } - (void)disconnect { // This is racing -[GRPCHost unmanagedCallWithPath:completionQueue:]. @synchronized(self) { _channel = nil; } } @end NS_ASSUME_NONNULL_END grpc-1.3.2/src/objective-c/GRPCClient/private/GRPCOpBatchLog.h000066400000000000000000000037731310511640000236050ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifdef GRPC_TEST_OBJC /** * Logs the op batches of a client. Used for testing. */ @interface GRPCOpBatchLog : NSObject /** * Enables logging of op batches. Memory consumption increases as more ops are logged. */ + (void)enableOpBatchLog:(BOOL)enabled; /** * Add an op batch to log. */ + (void)addOpBatchToLog:(NSArray *)batch; /** * Obtain the logged op batches. Invoking this method will clean the log. */ + (NSArray *)obtainAndCleanOpBatchLog; @end #endif grpc-1.3.2/src/objective-c/GRPCClient/private/GRPCOpBatchLog.m000066400000000000000000000043021310511640000235770ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifdef GRPC_TEST_OBJC #import "GRPCOpBatchLog.h" static NSMutableArray *opBatchLog = nil; @implementation GRPCOpBatchLog + (void)enableOpBatchLog:(BOOL)enabled { @synchronized (opBatchLog) { if (enabled) { if (!opBatchLog) { opBatchLog = [NSMutableArray array]; } } else { if (opBatchLog) { opBatchLog = nil; } } } } + (void)addOpBatchToLog:(NSArray *)batch { @synchronized (opBatchLog) { [opBatchLog addObject:batch]; } } + (NSArray *)obtainAndCleanOpBatchLog { @synchronized (opBatchLog) { NSArray *out = opBatchLog; opBatchLog = [NSMutableArray array]; return out; } } @end #endif grpc-1.3.2/src/objective-c/GRPCClient/private/GRPCReachabilityFlagNames.xmacro.h000066400000000000000000000054101310511640000272570ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** * "X-macro" file that lists the flags names of Apple's Network Reachability API, along with a nice * Objective-C method name used to query each of them. * * Example usage: To generate a dictionary from flag value to name, one can do: NSDictionary *flagNames = @{ #define GRPC_XMACRO_ITEM(methodName, FlagName) \ @(kSCNetworkReachabilityFlags ## FlagName): @#methodName, #include "GRXReachabilityFlagNames.xmacro.h" #undef GRPC_XMACRO_ITEM }; XCTAssertEqualObjects(flagNames[@(kSCNetworkReachabilityFlagsIsWWAN)], @"isCell"); */ #ifndef GRPC_XMACRO_ITEM #error This file is to be used with the "X-macro" pattern: Please #define \ GRPC_XMACRO_ITEM(methodName, FlagName), then #include this file, and then #undef \ GRPC_XMACRO_ITEM. #endif #if TARGET_OS_IPHONE GRPC_XMACRO_ITEM(isWWAN, IsWWAN) #endif GRPC_XMACRO_ITEM(reachable, Reachable) GRPC_XMACRO_ITEM(transientConnection, TransientConnection) GRPC_XMACRO_ITEM(connectionRequired, ConnectionRequired) GRPC_XMACRO_ITEM(connectionOnTraffic, ConnectionOnTraffic) GRPC_XMACRO_ITEM(interventionRequired, InterventionRequired) GRPC_XMACRO_ITEM(connectionOnDemand, ConnectionOnDemand) GRPC_XMACRO_ITEM(isLocalAddress, IsLocalAddress) GRPC_XMACRO_ITEM(isDirect, IsDirect) grpc-1.3.2/src/objective-c/GRPCClient/private/GRPCRequestHeaders.h000066400000000000000000000035161310511640000245420ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import "../GRPCCall.h" @interface GRPCRequestHeaders : NSMutableDictionary - (instancetype)initWithCall:(GRPCCall *)call; - (instancetype)initWithCall:(GRPCCall *)call storage:(NSMutableDictionary *)storage NS_DESIGNATED_INITIALIZER; @end grpc-1.3.2/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m000066400000000000000000000112621310511640000245440ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRPCRequestHeaders.h" #import #import "NSDictionary+GRPC.h" // Used by the setter. static void CheckIsNonNilASCII(NSString *name, NSString* value) { if (!value) { [NSException raise:NSInvalidArgumentException format:@"%@ cannot be nil", name]; } if (![value canBeConvertedToEncoding:NSASCIIStringEncoding]) { [NSException raise:NSInvalidArgumentException format:@"%@ %@ contains non-ASCII characters", name, value]; } } // Precondition: key isn't nil. static void CheckKeyValuePairIsValid(NSString *key, id value) { if ([key hasSuffix:@"-bin"]) { if (![value isKindOfClass:NSData.class]) { [NSException raise:NSInvalidArgumentException format:@"Expected NSData value for header %@ ending in \"-bin\", " @"instead got %@", key, value]; } } else { if (![value isKindOfClass:NSString.class]) { [NSException raise:NSInvalidArgumentException format:@"Expected NSString value for header %@ not ending in \"-bin\", " @"instead got %@", key, value]; } CheckIsNonNilASCII(@"Text header value", (NSString *)value); } } @implementation GRPCRequestHeaders { __weak GRPCCall *_call; // The NSMutableDictionary superclass doesn't hold any storage (so that people can implement their // own in subclasses). As that's not the reason we're subclassing, we just delegate storage to the // default NSMutableDictionary subclass returned by the cluster (e.g. __NSDictionaryM on iOS 9). NSMutableDictionary *_delegate; } - (instancetype)init { return [self initWithCall:nil]; } - (instancetype)initWithCapacity:(NSUInteger)numItems { return [self init]; } - (instancetype)initWithCoder:(NSCoder *)aDecoder { return [self init]; } - (instancetype)initWithCall:(GRPCCall *)call { return [self initWithCall:call storage:[NSMutableDictionary dictionary]]; } // Designated initializer - (instancetype)initWithCall:(GRPCCall *)call storage:(NSMutableDictionary *)storage { // TODO(jcanizales): Throw if call or storage are nil. if ((self = [super init])) { _call = call; _delegate = storage; } return self; } - (instancetype)initWithObjects:(const id _Nonnull __unsafe_unretained *)objects forKeys:(const id _Nonnull __unsafe_unretained *)keys count:(NSUInteger)cnt { return [self init]; } - (void)checkCallIsNotStarted { if (_call.state != GRXWriterStateNotStarted) { [NSException raise:@"Invalid modification" format:@"Cannot modify request headers after call is started"]; } } - (id)objectForKey:(NSString *)key { return _delegate[key.lowercaseString]; } - (void)setObject:(id)obj forKey:(NSString *)key { [self checkCallIsNotStarted]; CheckIsNonNilASCII(@"Header name", key); key = key.lowercaseString; CheckKeyValuePairIsValid(key, obj); _delegate[key] = obj; } - (void)removeObjectForKey:(NSString *)key { [self checkCallIsNotStarted]; [_delegate removeObjectForKey:key.lowercaseString]; } - (NSUInteger)count { return _delegate.count; } - (NSEnumerator * _Nonnull)keyEnumerator { return [_delegate keyEnumerator]; } @end grpc-1.3.2/src/objective-c/GRPCClient/private/GRPCWrappedCall.h000066400000000000000000000063311310511640000240120ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #include #import "GRPCRequestHeaders.h" @interface GRPCOperation : NSObject @property(nonatomic, readonly) grpc_op op; /** Guaranteed to be called when the operation has finished. */ - (void)finish; @end @interface GRPCOpSendMetadata : GRPCOperation - (instancetype)initWithMetadata:(NSDictionary *)metadata handler:(void(^)())handler; - (instancetype)initWithMetadata:(NSDictionary *)metadata flags:(uint32_t)flags handler:(void(^)())handler NS_DESIGNATED_INITIALIZER; @end @interface GRPCOpSendMessage : GRPCOperation - (instancetype)initWithMessage:(NSData *)message handler:(void(^)())handler NS_DESIGNATED_INITIALIZER; @end @interface GRPCOpSendClose : GRPCOperation - (instancetype)initWithHandler:(void(^)())handler NS_DESIGNATED_INITIALIZER; @end @interface GRPCOpRecvMetadata : GRPCOperation - (instancetype)initWithHandler:(void(^)(NSDictionary *))handler NS_DESIGNATED_INITIALIZER; @end @interface GRPCOpRecvMessage : GRPCOperation - (instancetype)initWithHandler:(void(^)(grpc_byte_buffer *))handler NS_DESIGNATED_INITIALIZER; @end @interface GRPCOpRecvStatus : GRPCOperation - (instancetype)initWithHandler:(void(^)(NSError *, NSDictionary *))handler NS_DESIGNATED_INITIALIZER; @end #pragma mark GRPCWrappedCall @interface GRPCWrappedCall : NSObject - (instancetype)initWithHost:(NSString *)host path:(NSString *)path NS_DESIGNATED_INITIALIZER; - (void)startBatchWithOperations:(NSArray *)ops errorHandler:(void(^)())errorHandler; - (void)startBatchWithOperations:(NSArray *)ops; - (void)cancel; @end grpc-1.3.2/src/objective-c/GRPCClient/private/GRPCWrappedCall.m000066400000000000000000000215631310511640000240230ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRPCWrappedCall.h" #import #include #include #include #import "GRPCCompletionQueue.h" #import "GRPCHost.h" #import "NSDictionary+GRPC.h" #import "NSData+GRPC.h" #import "NSError+GRPC.h" #import "GRPCOpBatchLog.h" @implementation GRPCOperation { @protected // Most operation subclasses don't set any flags in the grpc_op, and rely on the flag member being // initialized to zero. grpc_op _op; void(^_handler)(); } - (void)finish { if (_handler) { void(^handler)() = _handler; _handler = nil; handler(); } } @end @implementation GRPCOpSendMetadata - (instancetype)init { return [self initWithMetadata:nil flags:0 handler:nil]; } - (instancetype)initWithMetadata:(NSDictionary *)metadata handler:(void (^)())handler { return [self initWithMetadata:metadata flags:0 handler:handler]; } - (instancetype)initWithMetadata:(NSDictionary *)metadata flags:(uint32_t)flags handler:(void (^)())handler { if (self = [super init]) { _op.op = GRPC_OP_SEND_INITIAL_METADATA; _op.data.send_initial_metadata.count = metadata.count; _op.data.send_initial_metadata.metadata = metadata.grpc_metadataArray; _op.data.send_initial_metadata.maybe_compression_level.is_set = false; _op.data.send_initial_metadata.maybe_compression_level.level = 0; _op.flags = flags; _handler = handler; } return self; } - (void)dealloc { gpr_free(_op.data.send_initial_metadata.metadata); } @end @implementation GRPCOpSendMessage - (instancetype)init { return [self initWithMessage:nil handler:nil]; } - (instancetype)initWithMessage:(NSData *)message handler:(void (^)())handler { if (!message) { [NSException raise:NSInvalidArgumentException format:@"message cannot be nil"]; } if (self = [super init]) { _op.op = GRPC_OP_SEND_MESSAGE; _op.data.send_message.send_message = message.grpc_byteBuffer; _handler = handler; } return self; } - (void)dealloc { grpc_byte_buffer_destroy(_op.data.send_message.send_message); } @end @implementation GRPCOpSendClose - (instancetype)init { return [self initWithHandler:nil]; } - (instancetype)initWithHandler:(void (^)())handler { if (self = [super init]) { _op.op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; _handler = handler; } return self; } @end @implementation GRPCOpRecvMetadata { grpc_metadata_array _headers; } - (instancetype) init { return [self initWithHandler:nil]; } - (instancetype) initWithHandler:(void (^)(NSDictionary *))handler { if (self = [super init]) { _op.op = GRPC_OP_RECV_INITIAL_METADATA; grpc_metadata_array_init(&_headers); _op.data.recv_initial_metadata.recv_initial_metadata = &_headers; if (handler) { // Prevent reference cycle with _handler __weak typeof(self) weakSelf = self; _handler = ^{ __strong typeof(self) strongSelf = weakSelf; NSDictionary *metadata = [NSDictionary grpc_dictionaryFromMetadataArray:strongSelf->_headers]; handler(metadata); }; } } return self; } - (void)dealloc { grpc_metadata_array_destroy(&_headers); } @end @implementation GRPCOpRecvMessage{ grpc_byte_buffer *_receivedMessage; } - (instancetype)init { return [self initWithHandler:nil]; } - (instancetype)initWithHandler:(void (^)(grpc_byte_buffer *))handler { if (self = [super init]) { _op.op = GRPC_OP_RECV_MESSAGE; _op.data.recv_message.recv_message = &_receivedMessage; if (handler) { // Prevent reference cycle with _handler __weak typeof(self) weakSelf = self; _handler = ^{ __strong typeof(self) strongSelf = weakSelf; handler(strongSelf->_receivedMessage); }; } } return self; } @end @implementation GRPCOpRecvStatus{ grpc_status_code _statusCode; grpc_slice _details; size_t _detailsCapacity; grpc_metadata_array _trailers; } - (instancetype) init { return [self initWithHandler:nil]; } - (instancetype) initWithHandler:(void (^)(NSError *, NSDictionary *))handler { if (self = [super init]) { _op.op = GRPC_OP_RECV_STATUS_ON_CLIENT; _op.data.recv_status_on_client.status = &_statusCode; _op.data.recv_status_on_client.status_details = &_details; grpc_metadata_array_init(&_trailers); _op.data.recv_status_on_client.trailing_metadata = &_trailers; if (handler) { // Prevent reference cycle with _handler __weak typeof(self) weakSelf = self; _handler = ^{ __strong typeof(self) strongSelf = weakSelf; if (strongSelf) { char *details = grpc_slice_to_c_string(strongSelf->_details); NSError *error = [NSError grpc_errorFromStatusCode:strongSelf->_statusCode details:details]; NSDictionary *trailers = [NSDictionary grpc_dictionaryFromMetadataArray:strongSelf->_trailers]; handler(error, trailers); gpr_free(details); } }; } } return self; } - (void)dealloc { grpc_metadata_array_destroy(&_trailers); grpc_slice_unref(_details); } @end #pragma mark GRPCWrappedCall @implementation GRPCWrappedCall { GRPCCompletionQueue *_queue; grpc_call *_call; } - (instancetype)init { return [self initWithHost:nil path:nil]; } - (instancetype)initWithHost:(NSString *)host path:(NSString *)path { if (!path || !host) { [NSException raise:NSInvalidArgumentException format:@"path and host cannot be nil."]; } if (self = [super init]) { // Each completion queue consumes one thread. There's a trade to be made between creating and // consuming too many threads and having contention of multiple calls in a single completion // queue. Currently we use a singleton queue. _queue = [GRPCCompletionQueue completionQueue]; _call = [[GRPCHost hostWithAddress:host] unmanagedCallWithPath:path completionQueue:_queue]; if (_call == NULL) { return nil; } } return self; } - (void)startBatchWithOperations:(NSArray *)operations { [self startBatchWithOperations:operations errorHandler:nil]; } - (void)startBatchWithOperations:(NSArray *)operations errorHandler:(void (^)())errorHandler { // Keep logs of op batches when we are running tests. Disabled when in production for improved // performance. #ifdef GRPC_TEST_OBJC [GRPCOpBatchLog addOpBatchToLog:operations]; #endif size_t nops = operations.count; grpc_op *ops_array = gpr_malloc(nops * sizeof(grpc_op)); size_t i = 0; for (GRPCOperation *operation in operations) { ops_array[i++] = operation.op; } grpc_call_error error = grpc_call_start_batch(_call, ops_array, nops, (__bridge_retained void *)(^(bool success){ if (!success) { if (errorHandler) { errorHandler(); } else { return; } } for (GRPCOperation *operation in operations) { [operation finish]; } }), NULL); gpr_free(ops_array); if (error != GRPC_CALL_OK) { [NSException raise:NSInternalInconsistencyException format:@"A precondition for calling grpc_call_start_batch wasn't met. Error %i", error]; } } - (void)cancel { grpc_call_cancel(_call, NULL); } - (void)dealloc { grpc_call_destroy(_call); } @end grpc-1.3.2/src/objective-c/GRPCClient/private/NSData+GRPC.h000066400000000000000000000033661310511640000230060ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import struct grpc_byte_buffer; @interface NSData (GRPC) + (instancetype)grpc_dataWithByteBuffer:(struct grpc_byte_buffer *)buffer; - (struct grpc_byte_buffer *)grpc_byteBuffer; @end grpc-1.3.2/src/objective-c/GRPCClient/private/NSData+GRPC.m000066400000000000000000000107571310511640000230150ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "NSData+GRPC.h" #include #include #include // TODO(jcanizales): Move these two incantations to the C library. static void MallocAndCopyByteBufferToCharArray(grpc_byte_buffer *buffer, size_t *length, char **array) { grpc_byte_buffer_reader reader; if (!grpc_byte_buffer_reader_init(&reader, buffer)) { // grpc_byte_buffer_reader_init can fail if the data sent by the server // could not be decompressed for any reason. This is an issue with the data // coming from the server and thus we want the RPC to fail with error code // INTERNAL. *array = NULL; *length = 0; return; } // The slice contains uncompressed data even if compressed data was received // because the reader takes care of automatically decompressing it grpc_slice slice = grpc_byte_buffer_reader_readall(&reader); size_t uncompressed_length = GRPC_SLICE_LENGTH(slice); char *result = malloc(uncompressed_length); if (result) { memcpy(result, GRPC_SLICE_START_PTR(slice), uncompressed_length); } grpc_slice_unref(slice); *array = result; *length = uncompressed_length; } static grpc_byte_buffer *CopyCharArrayToNewByteBuffer(const char *array, size_t length) { grpc_slice slice = grpc_slice_from_copied_buffer(array, length); grpc_byte_buffer *buffer = grpc_raw_byte_buffer_create(&slice, 1); grpc_slice_unref(slice); return buffer; } @implementation NSData (GRPC) + (instancetype)grpc_dataWithByteBuffer:(grpc_byte_buffer *)buffer { if (buffer == NULL) { return nil; } char *array; size_t length; MallocAndCopyByteBufferToCharArray(buffer, &length, &array); if (!array) { // TODO(jcanizales): grpc_byte_buffer is reference-counted, so we can // prevent this memory problem by implementing a subclass of NSData // that wraps the grpc_byte_buffer. Then enumerateByteRangesUsingBlock: // can be implemented using a grpc_byte_buffer_reader. return nil; } // Not depending upon size assumption of NSUInteger NSUInteger length_max = MIN(length, UINT_MAX); return [self dataWithBytesNoCopy:array length:length_max freeWhenDone:YES]; } - (grpc_byte_buffer *)grpc_byteBuffer { // Some implementations of NSData, as well as grpc_byte_buffer, support O(1) // appending of byte arrays by not using internally a single contiguous memory // block for representation. // The following implementation is thus not optimal, sometimes requiring two // copies (one by self.bytes and another by grpc_slice_from_copied_buffer). // If it turns out to be an issue, we can use enumerateByteRangesUsingblock: // to create an array of grpc_slice objects to pass to // grpc_raw_byte_buffer_create. // That would make it do exactly one copy, always. return CopyCharArrayToNewByteBuffer((const char *)self.bytes, (size_t)self.length); } @end grpc-1.3.2/src/objective-c/GRPCClient/private/NSDictionary+GRPC.h000066400000000000000000000035161310511640000242370ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #include @interface NSDictionary (GRPC) + (instancetype)grpc_dictionaryFromMetadataArray:(grpc_metadata_array)array; + (instancetype)grpc_dictionaryFromMetadata:(grpc_metadata *)entries count:(size_t)count; - (grpc_metadata *)grpc_metadataArray; @end grpc-1.3.2/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m000066400000000000000000000114111310511640000242350ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "NSDictionary+GRPC.h" #include #pragma mark Category for binary metadata elements @interface NSData (GRPCMetadata) + (instancetype)grpc_dataFromMetadataValue:(grpc_metadata *)metadata; // Fill a metadata object with the binary value in this NSData. - (void)grpc_initMetadata:(grpc_metadata *)metadata; @end @implementation NSData (GRPCMetadata) + (instancetype)grpc_dataFromMetadataValue:(grpc_metadata *)metadata { // TODO(jcanizales): Should we use a non-copy constructor? return [self dataWithBytes:GRPC_SLICE_START_PTR(metadata->value) length:GRPC_SLICE_LENGTH(metadata->value)]; } - (void)grpc_initMetadata:(grpc_metadata *)metadata { metadata->value = grpc_slice_from_copied_buffer(self.bytes, self.length); } @end #pragma mark Category for textual metadata elements @interface NSString (GRPCMetadata) + (instancetype)grpc_stringFromMetadataValue:(grpc_metadata *)metadata; // Fill a metadata object with the textual value in this NSString. - (void)grpc_initMetadata:(grpc_metadata *)metadata; @end @implementation NSString (GRPCMetadata) + (instancetype)grpc_stringFromMetadataValue:(grpc_metadata *)metadata { return [[self alloc] initWithBytes:GRPC_SLICE_START_PTR(metadata->value) length:GRPC_SLICE_LENGTH(metadata->value) encoding:NSASCIIStringEncoding]; } // Precondition: This object contains only ASCII characters. - (void)grpc_initMetadata:(grpc_metadata *)metadata { metadata->value = grpc_slice_from_copied_string(self.UTF8String); } @end #pragma mark Category for metadata arrays @implementation NSDictionary (GRPC) + (instancetype)grpc_dictionaryFromMetadataArray:(grpc_metadata_array)array { return [self grpc_dictionaryFromMetadata:array.metadata count:array.count]; } + (instancetype)grpc_dictionaryFromMetadata:(grpc_metadata *)entries count:(size_t)count { NSMutableDictionary *metadata = [NSMutableDictionary dictionaryWithCapacity:count]; for (grpc_metadata *entry = entries; entry < entries + count; entry++) { char *key = grpc_slice_to_c_string(entry->key); NSString *name = [NSString stringWithCString:key encoding:NSASCIIStringEncoding]; gpr_free(key); if (!name || metadata[name]) { // Log if name is nil? continue; } id value; if ([name hasSuffix:@"-bin"]) { value = [NSData grpc_dataFromMetadataValue:entry]; } else { value = [NSString grpc_stringFromMetadataValue:entry]; } metadata[name] = value; } return metadata; } // Preconditions: All keys are ASCII strings. Keys ending in -bin have NSData values; the others // have NSString values. - (grpc_metadata *)grpc_metadataArray { grpc_metadata *metadata = gpr_malloc([self count] * sizeof(grpc_metadata)); grpc_metadata *current = metadata; for (NSString* key in self) { id value = self[key]; current->key = grpc_slice_from_copied_string(key.UTF8String); if ([value respondsToSelector:@selector(grpc_initMetadata:)]) { [value grpc_initMetadata:current]; } else { [NSException raise:NSInvalidArgumentException format:@"Metadata values must be NSString or NSData."]; } ++current; } return metadata; } @end grpc-1.3.2/src/objective-c/GRPCClient/private/NSError+GRPC.h000066400000000000000000000035601310511640000232220ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #include @interface NSError (GRPC) /** * Returns nil if the status code is OK. Otherwise, a NSError whose code is one of |GRPCErrorCode| * and whose domain is |kGRPCErrorDomain|. */ + (instancetype)grpc_errorFromStatusCode:(grpc_status_code)statusCode details:(char *)details; @end grpc-1.3.2/src/objective-c/GRPCClient/private/NSError+GRPC.m000066400000000000000000000041121310511640000232210ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "NSError+GRPC.h" #include NSString * const kGRPCErrorDomain = @"io.grpc"; @implementation NSError (GRPC) + (instancetype)grpc_errorFromStatusCode:(grpc_status_code)statusCode details:(char *)details { if (statusCode == GRPC_STATUS_OK) { return nil; } NSString *message = [NSString stringWithCString:details encoding:NSASCIIStringEncoding]; return [NSError errorWithDomain:kGRPCErrorDomain code:statusCode userInfo:@{NSLocalizedDescriptionKey: message}]; } @end grpc-1.3.2/src/objective-c/GRPCClient/private/version.h000066400000000000000000000035271310511640000226310ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ // This file is autogenerated from a template file. Please make // modifications to // `templates/src/objective-c/GRPCClient/private/version.h.template` // instead. This file can be regenerated from the template by running // `tools/buildgen/generate_projects.sh`. #define GRPC_OBJC_VERSION_STRING @"1.3.2" grpc-1.3.2/src/objective-c/ProtoRPC/000077500000000000000000000000001310511640000170705ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/ProtoRPC/ProtoMethod.h000066400000000000000000000046751310511640000215210ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import /** * A fully-qualified proto service method name. Full qualification is needed because a gRPC endpoint * can implement multiple services. */ __attribute__((deprecated("Please use GRPCProtoMethod."))) @interface ProtoMethod : NSObject @property(nonatomic, readonly) NSString *package; @property(nonatomic, readonly) NSString *service; @property(nonatomic, readonly) NSString *method; @property(nonatomic, readonly) NSString *HTTPPath; - (instancetype)initWithPackage:(NSString *)package service:(NSString *)service method:(NSString *)method; @end /** * This subclass is empty now. Eventually we'll remove ProtoMethod class * to avoid potential naming conflict */ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" @interface GRPCProtoMethod : ProtoMethod #pragma clang diagnostic pop @end grpc-1.3.2/src/objective-c/ProtoRPC/ProtoMethod.m000066400000000000000000000042321310511640000215130ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "ProtoMethod.h" @implementation ProtoMethod - (instancetype)initWithPackage:(NSString *)package service:(NSString *)service method:(NSString *)method { if ((self = [super init])) { _package = [package copy]; _service = [service copy]; _method = [method copy]; } return self; } - (NSString *)HTTPPath { if (_package && _package.length > 0) { return [NSString stringWithFormat:@"/%@.%@/%@", _package, _service, _method]; } else { return [NSString stringWithFormat:@"/%@/%@", _service, _method]; } } @end @implementation GRPCProtoMethod @end grpc-1.3.2/src/objective-c/ProtoRPC/ProtoRPC.h000066400000000000000000000047171310511640000207220ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import #import "ProtoMethod.h" __attribute__((deprecated("Please use GRPCProtoCall."))) @interface ProtoRPC : GRPCCall /** * host parameter should not contain the scheme (http:// or https://), only the name or IP addr * and the port number, for example @"localhost:5050". */ - (instancetype)initWithHost:(NSString *)host method:(GRPCProtoMethod *)method requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass responsesWriteable:(id)responsesWriteable NS_DESIGNATED_INITIALIZER; - (void)start; @end /** * This subclass is empty now. Eventually we'll remove ProtoRPC class * to avoid potential naming conflict */ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" @interface GRPCProtoCall : ProtoRPC #pragma clang diagnostic pop @end grpc-1.3.2/src/objective-c/ProtoRPC/ProtoRPC.m000066400000000000000000000120541310511640000207200ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "ProtoRPC.h" #if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS #import #else #import #endif #import #import static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsingError) { NSDictionary *info = @{ NSLocalizedDescriptionKey: @"Unable to parse response from the server", NSLocalizedRecoverySuggestionErrorKey: @"If this RPC is idempotent, retry " @"with exponential backoff. Otherwise, query the server status before " @"retrying.", NSUnderlyingErrorKey: parsingError, @"Expected class": expectedClass, @"Received value": proto, }; // TODO(jcanizales): Use kGRPCErrorDomain and GRPCErrorCodeInternal when they're public. return [NSError errorWithDomain:@"io.grpc" code:13 userInfo:info]; } @implementation ProtoRPC { id _responseWriteable; } #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wobjc-designated-initializers" - (instancetype)initWithHost:(NSString *)host path:(NSString *)path requestsWriter:(GRXWriter *)requestsWriter { [NSException raise:NSInvalidArgumentException format:@"Please use ProtoRPC's designated initializer instead."]; return nil; } #pragma clang diagnostic pop // Designated initializer - (instancetype)initWithHost:(NSString *)host method:(GRPCProtoMethod *)method requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass responsesWriteable:(id)responsesWriteable { // Because we can't tell the type system to constrain the class, we need to check at runtime: if (![responseClass respondsToSelector:@selector(parseFromData:error:)]) { [NSException raise:NSInvalidArgumentException format:@"A protobuf class to parse the responses must be provided."]; } // A writer that serializes the proto messages to send. GRXWriter *bytesWriter = [requestsWriter map:^id(GPBMessage *proto) { if (![proto isKindOfClass:GPBMessage.class]) { [NSException raise:NSInvalidArgumentException format:@"Request must be a proto message: %@", proto]; } return [proto data]; }]; if ((self = [super initWithHost:host path:method.HTTPPath requestsWriter:bytesWriter])) { __weak ProtoRPC *weakSelf = self; // A writeable that parses the proto messages received. _responseWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { // TODO(jcanizales): This is done in the main thread, and needs to happen in another thread. NSError *error = nil; id parsed = [responseClass parseFromData:value error:&error]; if (parsed) { [responsesWriteable writeValue:parsed]; } else { [weakSelf finishWithError:ErrorForBadProto(value, responseClass, error)]; } } completionHandler:^(NSError *errorOrNil) { [responsesWriteable writesFinishedWithError:errorOrNil]; }]; } return self; } - (void)start { [self startWithWriteable:_responseWriteable]; } - (void)startWithWriteable:(id)writeable { [super startWithWriteable:writeable]; // Break retain cycles. _responseWriteable = nil; } @end @implementation GRPCProtoCall @end grpc-1.3.2/src/objective-c/ProtoRPC/ProtoService.h000066400000000000000000000046271310511640000216760ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import @class GRPCProtoCall; @protocol GRXWriteable; @class GRXWriter; __attribute__((deprecated("Please use GRPCProtoService."))) @interface ProtoService : NSObject - (instancetype)initWithHost:(NSString *)host packageName:(NSString *)packageName serviceName:(NSString *)serviceName NS_DESIGNATED_INITIALIZER; - (GRPCProtoCall *)RPCToMethod:(NSString *)method requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass responsesWriteable:(id)responsesWriteable; @end /** * This subclass is empty now. Eventually we'll remove ProtoService class * to avoid potential naming conflict */ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" @interface GRPCProtoService : ProtoService #pragma clang diagnostic pop @end grpc-1.3.2/src/objective-c/ProtoRPC/ProtoService.m000066400000000000000000000062251310511640000216770ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "ProtoService.h" #import #import #import "ProtoMethod.h" #import "ProtoRPC.h" @implementation ProtoService { NSString *_host; NSString *_packageName; NSString *_serviceName; } - (instancetype)init { return [self initWithHost:nil packageName:nil serviceName:nil]; } // Designated initializer - (instancetype)initWithHost:(NSString *)host packageName:(NSString *)packageName serviceName:(NSString *)serviceName { if (!host || !serviceName) { [NSException raise:NSInvalidArgumentException format:@"Neither host nor serviceName can be nil."]; } if ((self = [super init])) { _host = [host copy]; _packageName = [packageName copy]; _serviceName = [serviceName copy]; } return self; } - (GRPCProtoCall *)RPCToMethod:(NSString *)method requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass responsesWriteable:(id)responsesWriteable { GRPCProtoMethod *methodName = [[GRPCProtoMethod alloc] initWithPackage:_packageName service:_serviceName method:method]; return [[GRPCProtoCall alloc] initWithHost:_host method:methodName requestsWriter:requestsWriter responseClass:responseClass responsesWriteable:responsesWriteable]; } @end @implementation GRPCProtoService @end grpc-1.3.2/src/objective-c/README.md000066400000000000000000000205671310511640000167110ustar00rootroot00000000000000[![Cocoapods](https://img.shields.io/cocoapods/v/gRPC.svg)](https://cocoapods.org/pods/gRPC) # gRPC for Objective-C - [Write your API declaration in proto format](#write-protos) - [Integrate a proto library in your project](#cocoapods) - [Use the generated library in your code](#use) - [Use gRPC without Protobuf](#no-proto) - [Alternatives to the steps above](#alternatives) - [Install protoc with the gRPC plugin](#install) - [Install protoc and the gRPC plugin without using Homebrew](#no-homebrew) - [Integrate the generated gRPC library without using Cocoapods](#no-cocoapods) While gRPC doesn't require the use of an IDL to describe the API of services, using one simplifies usage and adds some interoperability guarantees. Here we use [Protocol Buffers][], and provide a plugin for the Protobuf Compiler (_protoc_) to generate client libraries to communicate with gRPC services. ## Write your API declaration in proto format For this you can consult the [Protocol Buffers][]' official documentation, or learn from a quick example [here](https://github.com/grpc/grpc/tree/master/examples#defining-a-service). ## Integrate a proto library in your project Install [Cocoapods](https://cocoapods.org/#install). You need to create a Podspec file for your proto library. You may simply copy the following example to the directory where your `.proto` files are located, updating the name, version and license as necessary. You also need to set the `pods_root` variable to the correct value, depending on where you place this podspec relative to your Podfile. ```ruby Pod::Spec.new do |s| s.name = '' s.version = '0.0.1' s.license = '...' s.authors = { '' => '' } s.homepage = '...' s.summary = '...' s.source = { :git => 'https://github.com/...' } s.ios.deployment_target = '7.1' s.osx.deployment_target = '10.9' # Base directory where the .proto files are. src = '.' # We'll use protoc with the gRPC plugin. s.dependency '!ProtoCompiler-gRPCPlugin', '~> 1.0' # Pods directory corresponding to this app's Podfile, relative to the location of this podspec. pods_root = '/Pods' # Path where Cocoapods downloads protoc and the gRPC plugin. protoc_dir = "#{pods_root}/!ProtoCompiler" protoc = "#{protoc_dir}/protoc" plugin = "#{pods_root}/!ProtoCompiler-gRPCPlugin/grpc_objective_c_plugin" # Directory where you want the generated files to be placed. This is an example. dir = "#{pods_root}/#{s.name}" # Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients. # You can run this command manually if you later change your protos and need to regenerate. # Alternatively, you can advance the version of this podspec and run `pod update`. s.prepare_command = <<-CMD mkdir -p #{dir} #{protoc} \ --plugin=protoc-gen-grpc=#{plugin} \ --objc_out=#{dir} \ --grpc_out=#{dir} \ -I #{src} \ -I #{protoc_dir} \ #{src}/*.proto CMD # The --objc_out plugin generates a pair of .pbobjc.h/.pbobjc.m files for each .proto file. s.subspec 'Messages' do |ms| ms.source_files = "#{dir}/*.pbobjc.{h,m}" ms.header_mappings_dir = dir ms.requires_arc = false # The generated files depend on the protobuf runtime. ms.dependency 'Protobuf' end # The --objcgrpc_out plugin generates a pair of .pbrpc.h/.pbrpc.m files for each .proto file with # a service defined. s.subspec 'Services' do |ss| ss.source_files = "#{dir}/*.pbrpc.{h,m}" ss.header_mappings_dir = dir ss.requires_arc = true # The generated files depend on the gRPC runtime, and on the files generated by `--objc_out`. ss.dependency 'gRPC-ProtoRPC' ss.dependency "#{s.name}/Messages" end s.pod_target_xcconfig = { # This is needed by all pods that depend on Protobuf: 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1', # This is needed by all pods that depend on gRPC-RxLibrary: 'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES', } end ``` The file should be named `.podspec`. Note: If your proto files are in a directory hierarchy, you might want to adjust the _globs_ used in the sample Podspec above. For example, you could use: ```ruby s.prepare_command = <<-CMD ... #{src}/*.proto #{src}/**/*.proto CMD ... ms.source_files = "#{dir}/*.pbobjc.{h,m}", "#{dir}/**/*.pbobjc.{h,m}" ... ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}" ``` Once your library has a Podspec, Cocoapods can install it into any XCode project. For that, go into your project's directory and create a Podfile by running: ```sh pod init ``` Next add a line to your Podfile to refer to your library's Podspec. Use `:path` as described [here](https://guides.cocoapods.org/using/the-podfile.html#using-the-files-from-a-folder-local-to-the-machine): ```ruby pod '', :path => 'path/to/the/directory/of/your/podspec' ``` You can look at this [example Podfile][]. Finally, in your project's directory, run: ```sh pod install ``` ## Use the generated library in your code Please check the [example apps][] for examples of how to use a generated gRPC library. ## Use gRPC without Protobuf This [tests file](https://github.com/grpc/grpc/tree/master/src/objective-c/tests/GRPCClientTests.m) shows how to use the generic gRPC Objective-C client without generated protobuf files. ## Alternatives to the steps above ### Install _protoc_ with the gRPC plugin Although it's not recommended (because it can lead to hard-to-solve version conflicts), it is sometimes more convenient to install _protoc_ and the gRPC plugin in your development machine, instead of letting Cocoapods download the appropriate versions for you. To do so, on Mac OS X or later, install [homebrew][]. The run the following command to install _protoc_ and the gRPC _protoc_ plugin: ```sh $ curl -fsSL https://goo.gl/getgrpc | bash - ``` This will download and run the [gRPC install script][]. ### Install _protoc_ and the gRPC plugin without using Homebrew First install v3 of the Protocol Buffers compiler (_protoc_), by cloning [its Git repository](https://github.com/google/protobuf) and following these [installation instructions](https://github.com/google/protobuf#c-installation---unix) (the ones titled C++; don't miss the note for Mac users). Then clone this repository and execute the following commands from the root directory where it was cloned. Compile the gRPC plugins for _protoc_: ```sh make grpc_objective_c_plugin ``` Create a symbolic link to the compiled plugin binary somewhere in your `$PATH`: ```sh ln -s `pwd`/bins/opt/grpc_objective_c_plugin /usr/local/bin/protoc-gen-objcgrpc ``` (Notice that the name of the created link must begin with "`protoc-gen-`" for _protoc_ to recognize it as a plugin). If you don't want to create the symbolic link, you can alternatively copy the binary (with the appropriate name). Or you might prefer instead to specify the plugin's path as a flag when invoking _protoc_, in which case no system modification nor renaming is necessary. ### Integrate the generated gRPC library without using Cocoapods You need to compile the generated `.pbobjc.*` files (the enums and messages) without ARC support, and the generated `.pbrpc.*` files (the services) with ARC support. The generated code depends on v0.12+ of the Objective-C gRPC runtime library and v3.0.0-alpha-4+ of the Objective-C Protobuf runtime library. These libraries need to be integrated into your project as described in their respective Podspec files: * [Podspec](https://github.com/grpc/grpc/blob/master/gRPC.podspec) for the Objective-C gRPC runtime library. This can be tedious to configure manually. * [Podspec](https://github.com/google/protobuf/blob/master/Protobuf.podspec) for the Objective-C Protobuf runtime library. [Protocol Buffers]:https://developers.google.com/protocol-buffers/ [homebrew]:http://brew.sh [gRPC install script]:https://raw.githubusercontent.com/grpc/homebrew-grpc/master/scripts/install [example Podfile]:https://github.com/grpc/grpc/blob/master/examples/objective-c/helloworld/Podfile [example apps]: https://github.com/grpc/grpc/tree/master/examples/objective-c grpc-1.3.2/src/objective-c/RxLibrary/000077500000000000000000000000001310511640000173365ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/RxLibrary/GRXBufferedPipe.h000066400000000000000000000055041310511640000224340ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import "GRXWriteable.h" #import "GRXWriter.h" /** * A buffered pipe is a Writer that also acts as a Writeable. * Once it is started, whatever values are written into it (via -writeValue:) will be propagated * immediately, unless flow control prevents it. * If it is throttled and keeps receiving values, as well as if it receives values before being * started, it will buffer them and propagate them in order as soon as its state becomes Started. * If it receives an error (via -writesFinishedWithError:), it will drop any buffered values and * propagate the error immediately. * * Beware that a pipe of this type can't prevent receiving more values when it is paused (for * example if used to write data to a congested network connection). Because in such situations the * pipe will keep buffering all data written to it, your application could run out of memory and * crash. If you want to react to flow control signals to prevent that, instead of using this class * you can implement an object that conforms to GRXWriter. * * Thread-safety: * The methods of an object of this class should not be called concurrently from different threads. */ @interface GRXBufferedPipe : GRXWriter /** Convenience constructor. */ + (instancetype)pipe; @end grpc-1.3.2/src/objective-c/RxLibrary/GRXBufferedPipe.m000066400000000000000000000106701310511640000224410ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRXBufferedPipe.h" @implementation GRXBufferedPipe { id _writeable; NSMutableArray *_queue; BOOL _inputIsFinished; NSError *_errorOrNil; } @synthesize state = _state; + (instancetype)pipe { return [[self alloc] init]; } - (instancetype)init { if (self = [super init]) { _queue = [NSMutableArray array]; _state = GRXWriterStateNotStarted; } return self; } - (id)popValue { id value = _queue[0]; [_queue removeObjectAtIndex:0]; return value; } - (void)writeBufferUntilPausedOrStopped { while (_state == GRXWriterStateStarted && _queue.count > 0) { [_writeable writeValue:[self popValue]]; } if (_inputIsFinished && _queue.count == 0) { // Our writer finished normally while we were paused or not-started-yet. [self finishWithError:_errorOrNil]; } } #pragma mark GRXWriteable implementation // Returns whether events can be simply propagated to the other end of the pipe. - (BOOL)shouldFastForward { return _state == GRXWriterStateStarted && _queue.count == 0; } - (void)writeValue:(id)value { if (self.shouldFastForward) { // Skip the queue. [_writeable writeValue:value]; } else { // Even if we're paused and with enqueued values, we can't excert back-pressure to our writer. // So just buffer the new value. // We need a copy, so that it doesn't mutate before it's written at the other end of the pipe. if ([value respondsToSelector:@selector(copy)]) { value = [value copy]; } [_queue addObject:value]; } } - (void)writesFinishedWithError:(NSError *)errorOrNil { _inputIsFinished = YES; _errorOrNil = errorOrNil; if (errorOrNil || self.shouldFastForward) { // No need to write pending values. [self finishWithError:_errorOrNil]; } } #pragma mark GRXWriter implementation - (void)setState:(GRXWriterState)newState { // Manual transitions are only allowed from the started or paused states. if (_state == GRXWriterStateNotStarted || _state == GRXWriterStateFinished) { return; } switch (newState) { case GRXWriterStateFinished: _state = newState; _queue = nil; // Per GRXWriter's contract, setting the state to Finished manually means one doesn't wish the // writeable to be messaged anymore. _writeable = nil; return; case GRXWriterStatePaused: _state = newState; return; case GRXWriterStateStarted: if (_state == GRXWriterStatePaused) { _state = newState; [self writeBufferUntilPausedOrStopped]; } return; case GRXWriterStateNotStarted: return; } } - (void)startWithWriteable:(id)writeable { _state = GRXWriterStateStarted; _writeable = writeable; [self writeBufferUntilPausedOrStopped]; } - (void)finishWithError:(NSError *)errorOrNil { id writeable = _writeable; self.state = GRXWriterStateFinished; [writeable writesFinishedWithError:errorOrNil]; } @end grpc-1.3.2/src/objective-c/RxLibrary/GRXConcurrentWriteable.h000066400000000000000000000070301310511640000240510ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import "GRXWriter.h" #import "GRXWriteable.h" /** * This is a thread-safe wrapper over a GRXWriteable instance. It lets one enqueue calls to a * GRXWriteable instance for the main thread, guaranteeing that writesFinishedWithError: is the last * message sent to it (no matter what messages are sent to the wrapper, in what order, nor from * which thread). It also guarantees that, if cancelWithError: is called from the main thread (e.g. * by the app cancelling the writes), no further messages are sent to the writeable except * writesFinishedWithError:. * * TODO(jcanizales): Let the user specify another queue for the writeable callbacks. */ @interface GRXConcurrentWriteable : NSObject /** * The GRXWriteable passed is the wrapped writeable. * The GRXWriteable instance is retained until writesFinishedWithError: is sent to it, and released * after that. */ - (instancetype)initWithWriteable:(id)writeable NS_DESIGNATED_INITIALIZER; /** * Enqueues writeValue: to be sent to the writeable in the main thread. * The passed handler is invoked from the main thread after writeValue: returns. */ - (void)enqueueValue:(id)value completionHandler:(void (^)())handler; /** * Enqueues writesFinishedWithError:nil to be sent to the writeable in the main thread. After that * message is sent to the writeable, all other methods of this object are effectively noops. */ - (void)enqueueSuccessfulCompletion; /** * If the writeable has not yet received a writesFinishedWithError: message, this will enqueue one * to be sent to it in the main thread, and cancel all other pending messages to the writeable * enqueued by this object (both past and future). * The error argument cannot be nil. */ - (void)cancelWithError:(NSError *)error; /** * Cancels all pending messages to the writeable enqueued by this object (both past and future). * Because the writeable won't receive writesFinishedWithError:, this also releases the writeable. */ - (void)cancelSilently; @end grpc-1.3.2/src/objective-c/RxLibrary/GRXConcurrentWriteable.m000066400000000000000000000100421310511640000240530ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRXConcurrentWriteable.h" #import @interface GRXConcurrentWriteable () // This is atomic so that cancellation can nillify it from any thread. @property(atomic, strong) id writeable; @end @implementation GRXConcurrentWriteable { dispatch_queue_t _writeableQueue; // This ensures that writesFinishedWithError: is only sent once to the writeable. dispatch_once_t _alreadyFinished; } - (instancetype)init { return [self initWithWriteable:nil]; } // Designated initializer - (instancetype)initWithWriteable:(id)writeable { if (self = [super init]) { _writeableQueue = dispatch_get_main_queue(); _writeable = writeable; } return self; } - (void)enqueueValue:(id)value completionHandler:(void (^)())handler { dispatch_async(_writeableQueue, ^{ // We're racing a possible cancellation performed by another thread. To turn all already- // enqueued messages into noops, cancellation nillifies the writeable property. If we get it // before it's nil, we won the race. id writeable = self.writeable; if (writeable) { [writeable writeValue:value]; handler(); } }); } - (void)enqueueSuccessfulCompletion { dispatch_async(_writeableQueue, ^{ dispatch_once(&_alreadyFinished, ^{ // Cancellation is now impossible. None of the other three blocks can run concurrently with // this one. [self.writeable writesFinishedWithError:nil]; // Skip any possible message to the wrapped writeable enqueued after this one. self.writeable = nil; }); }); } - (void)cancelWithError:(NSError *)error { NSAssert(error, @"For a successful completion, use enqueueSuccessfulCompletion."); dispatch_once(&_alreadyFinished, ^{ // Skip any of the still-enqueued messages to the wrapped writeable. We use the atomic setter to // nillify writeable because we might be running concurrently with the blocks in // _writeableQueue, and assignment with ARC isn't atomic. id writeable = self.writeable; self.writeable = nil; dispatch_async(_writeableQueue, ^{ [writeable writesFinishedWithError:error]; }); }); } - (void)cancelSilently { dispatch_once(&_alreadyFinished, ^{ // Skip any of the still-enqueued messages to the wrapped writeable. We use the atomic setter to // nillify writeable because we might be running concurrently with the blocks in // _writeableQueue, and assignment with ARC isn't atomic. self.writeable = nil; }); } @end grpc-1.3.2/src/objective-c/RxLibrary/GRXForwardingWriter.h000066400000000000000000000045461310511640000234000ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRXWriter.h" /** * A "proxy" class that simply forwards values, completion, and errors from its input writer to its * writeable. * It is useful as a superclass for pipes that act as a transformation of their * input writer, and for classes that represent objects with input and * output sequences of values, like an RPC. * * Thread-safety: * All messages sent to this object need to be serialized. When it is started, the writer it wraps * is started in the same thread. Manual state changes are propagated to the wrapped writer in the * same thread too. Importantly, all messages the wrapped writer sends to its writeable need to be * serialized with any message sent to this object. */ @interface GRXForwardingWriter : GRXWriter - (instancetype)initWithWriter:(GRXWriter *)writer NS_DESIGNATED_INITIALIZER; @end grpc-1.3.2/src/objective-c/RxLibrary/GRXForwardingWriter.m000066400000000000000000000066751310511640000234120ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRXForwardingWriter.h" @interface GRXForwardingWriter () @end @implementation GRXForwardingWriter { GRXWriter *_writer; id _writeable; } - (instancetype)init { return [self initWithWriter:nil]; } // Designated initializer - (instancetype)initWithWriter:(GRXWriter *)writer { if (!writer) { return nil; } if (writer.state != GRXWriterStateNotStarted) { [NSException raise:NSInvalidArgumentException format:@"The writer argument must not have already started."]; } if ((self = [super init])) { _writer = writer; } return self; } // This is used to send a completion or an error to the writeable. It nillifies // our reference to it in order to guarantee no more messages are sent to it, // and to release it. - (void)finishOutputWithError:(NSError *)errorOrNil { id writeable = _writeable; _writeable = nil; [writeable writesFinishedWithError:errorOrNil]; } // This is used to stop the input writer. It nillifies our reference to it // to release it. - (void)finishInput { GRXWriter *writer = _writer; _writer = nil; writer.state = GRXWriterStateFinished; } #pragma mark GRXWriteable implementation - (void)writeValue:(id)value { [_writeable writeValue:value]; } - (void)writesFinishedWithError:(NSError *)errorOrNil { _writer = nil; [self finishOutputWithError:errorOrNil]; } #pragma mark GRXWriter implementation - (GRXWriterState)state { return _writer ? _writer.state : GRXWriterStateFinished; } - (void)setState:(GRXWriterState)state { if (state == GRXWriterStateFinished) { _writeable = nil; [self finishInput]; } else { _writer.state = state; } } - (void)startWithWriteable:(id)writeable { _writeable = writeable; [_writer startWithWriteable:self]; } - (void)finishWithError:(NSError *)errorOrNil { [self finishOutputWithError:errorOrNil]; [self finishInput]; } @end grpc-1.3.2/src/objective-c/RxLibrary/GRXImmediateSingleWriter.h000066400000000000000000000036651310511640000243370ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import "GRXImmediateWriter.h" /** * Utility to construct GRXWriter instances from values that are immediately available when * required. */ @interface GRXImmediateSingleWriter : GRXImmediateWriter /** * Returns a writer that sends the passed value to its writeable and then finishes (releasing the * value). */ + (GRXWriter *)writerWithValue:(id)value; @end grpc-1.3.2/src/objective-c/RxLibrary/GRXImmediateSingleWriter.m000066400000000000000000000056611310511640000243420ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRXImmediateSingleWriter.h" @implementation GRXImmediateSingleWriter { id _value; id _writeable; } @synthesize state = _state; - (instancetype)initWithValue:(id)value { if (self = [super init]) { _value = value; _state = GRXWriterStateNotStarted; } return self; } + (GRXWriter *)writerWithValue:(id)value { return [[self alloc] initWithValue:value]; } - (void)startWithWriteable:(id)writeable { _state = GRXWriterStateStarted; _writeable = writeable; [writeable writeValue:_value]; [self finish]; } - (void)finish { _state = GRXWriterStateFinished; _value = nil; id writeable = _writeable; _writeable = nil; [writeable writesFinishedWithError:nil]; } // Overwrite the setter to disallow manual state transition. The getter // of _state is synthesized. - (void)setState:(GRXWriterState)newState { // Manual state transition is not allowed return; } // Overrides [requestWriter(Transformations):map:] for Protocol Buffers // encoding. // We need the return value of this map to be a GRXImmediateSingleWriter but // the original \a map function returns a new Writer of another type. So we // need to override this function here. - (GRXWriter *)map:(id (^)(id))map { // Since _value is available when creating the object, we can simply // apply the map and store the output. _value = map(_value); return self; } @end grpc-1.3.2/src/objective-c/RxLibrary/GRXImmediateWriter.h000066400000000000000000000073041310511640000231670ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import "GRXWriter.h" /** * Utility to construct GRXWriter instances from values that are immediately available when * required. * * Thread-safety: * * An object of this class shouldn't be messaged concurrently by more than one thread. It will start * messaging the writeable before |startWithWriteable:| returns, in the same thread. That is the * only place where the writer can be paused or stopped prematurely. * * If a paused writer of this class is resumed, it will start messaging the writeable, in the same * thread, before |setState:| returns. Because the object can't be legally accessed concurrently, * that's the only place where it can be paused again (or stopped). */ @interface GRXImmediateWriter : GRXWriter /** * Returns a writer that pulls values from the passed NSEnumerator instance and pushes them to * its writeable. The NSEnumerator is released when it finishes. */ + (GRXWriter *)writerWithEnumerator:(NSEnumerator *)enumerator; /** * Returns a writer that pushes to its writeable the successive values returned by the passed * block. When the block first returns nil, it is released. */ + (GRXWriter *)writerWithValueSupplier:(id (^)())block; /** * Returns a writer that iterates over the values of the passed container and pushes them to * its writeable. The container is released when the iteration is over. * * Note that the usual speed gain of NSFastEnumeration over NSEnumerator results from not having to * call one method per element. Because GRXWriteable instances accept values one by one, that speed * gain doesn't happen here. */ + (GRXWriter *)writerWithContainer:(id)container; /** * Returns a writer that sends the passed value to its writeable and then finishes (releasing the * value). */ + (GRXWriter *)writerWithValue:(id)value; /** * Returns a writer that, as part of its start method, sends the passed error to the writeable * (then releasing the error). */ + (GRXWriter *)writerWithError:(NSError *)error; /** * Returns a writer that, as part of its start method, finishes immediately without sending any * values to its writeable. */ + (GRXWriter *)emptyWriter; @end grpc-1.3.2/src/objective-c/RxLibrary/GRXImmediateWriter.m000066400000000000000000000117011310511640000231700ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRXImmediateWriter.h" #import "NSEnumerator+GRXUtil.h" @implementation GRXImmediateWriter { NSEnumerator *_enumerator; NSError *_errorOrNil; id _writeable; } @synthesize state = _state; - (instancetype) init { return [self initWithEnumerator:nil error:nil]; // results in an empty writer. } // Designated initializer - (instancetype)initWithEnumerator:(NSEnumerator *)enumerator error:(NSError *)errorOrNil { if (((self = [super init]))) { _enumerator = enumerator; _errorOrNil = errorOrNil; _state = GRXWriterStateNotStarted; } return self; } #pragma mark Convenience constructors + (instancetype)writerWithEnumerator:(NSEnumerator *)enumerator error:(NSError *)errorOrNil { return [[self alloc] initWithEnumerator:enumerator error:errorOrNil]; } + (GRXWriter *)writerWithEnumerator:(NSEnumerator *)enumerator { return [self writerWithEnumerator:enumerator error:nil]; } + (GRXWriter *)writerWithValueSupplier:(id (^)())block { return [self writerWithEnumerator:[NSEnumerator grx_enumeratorWithValueSupplier:block]]; } + (GRXWriter *)writerWithContainer:(id)container { return [self writerWithEnumerator:[NSEnumerator grx_enumeratorWithContainer:container]];; } + (GRXWriter *)writerWithValue:(id)value { return [self writerWithEnumerator:[NSEnumerator grx_enumeratorWithSingleValue:value]]; } + (GRXWriter *)writerWithError:(NSError *)error { return [self writerWithEnumerator:nil error:error]; } + (GRXWriter *)emptyWriter { return [self writerWithEnumerator:nil error:nil]; } #pragma mark Conformance with GRXWriter // Most of the complexity in this implementation is the result of supporting pause and resumption of // the GRXWriter. It's an important feature for instances of GRXWriter that are backed by a // container (which may be huge), or by a NSEnumerator (which may even be infinite). - (void)writeUntilPausedOrStopped { id value; while (value = [_enumerator nextObject]) { [_writeable writeValue:value]; // If the writeable has a reference to us, it might change our state to paused or finished. if (_state == GRXWriterStatePaused || _state == GRXWriterStateFinished) { return; } } [self finishWithError:_errorOrNil]; } - (void)startWithWriteable:(id)writeable { _state = GRXWriterStateStarted; _writeable = writeable; [self writeUntilPausedOrStopped]; } - (void)finishWithError:(NSError *)errorOrNil { _state = GRXWriterStateFinished; _enumerator = nil; _errorOrNil = nil; id writeable = _writeable; _writeable = nil; [writeable writesFinishedWithError:errorOrNil]; } - (void)setState:(GRXWriterState)newState { // Manual transitions are only allowed from the started or paused states. if (_state == GRXWriterStateNotStarted || _state == GRXWriterStateFinished) { return; } switch (newState) { case GRXWriterStateFinished: _state = newState; _enumerator = nil; _errorOrNil = nil; // Per GRXWriter's contract, setting the state to Finished manually // means one doesn't wish the writeable to be messaged anymore. _writeable = nil; return; case GRXWriterStatePaused: _state = newState; return; case GRXWriterStateStarted: if (_state == GRXWriterStatePaused) { _state = newState; [self writeUntilPausedOrStopped]; } return; case GRXWriterStateNotStarted: return; } } @end grpc-1.3.2/src/objective-c/RxLibrary/GRXWriteable.h000066400000000000000000000054541310511640000220160ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import /** * A GRXWriteable is an object to which a sequence of values can be sent. The * sequence finishes with an optional error. */ @protocol GRXWriteable /** Push the next value of the sequence to the receiving object. */ - (void)writeValue:(id)value; /** * Signal that the sequence is completed, or that an error ocurred. After this * message is sent to the instance, neither it nor writeValue: may be * called again. */ - (void)writesFinishedWithError:(NSError *)errorOrNil; @end typedef void (^GRXValueHandler)(id value); typedef void (^GRXCompletionHandler)(NSError *errorOrNil); typedef void (^GRXSingleHandler)(id value, NSError *errorOrNil); typedef void (^GRXEventHandler)(BOOL done, id value, NSError *error); /** * Utility to create objects that conform to the GRXWriteable protocol, from * blocks that handle each of the two methods of the protocol. */ @interface GRXWriteable : NSObject + (instancetype)writeableWithSingleHandler:(GRXSingleHandler)handler; + (instancetype)writeableWithEventHandler:(GRXEventHandler)handler; - (instancetype)initWithValueHandler:(GRXValueHandler)valueHandler completionHandler:(GRXCompletionHandler)completionHandler NS_DESIGNATED_INITIALIZER; @end grpc-1.3.2/src/objective-c/RxLibrary/GRXWriteable.m000066400000000000000000000112151310511640000220130ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRXWriteable.h" @implementation GRXWriteable { GRXValueHandler _valueHandler; GRXCompletionHandler _completionHandler; } + (instancetype)writeableWithSingleHandler:(GRXSingleHandler)handler { if (!handler) { return [[self alloc] init]; } // We nilify this variable when the block is invoked, so that handler is only invoked once even if // the writer tries to write multiple values. __block GRXEventHandler eventHandler = ^(BOOL done, id value, NSError *error) { // Nillify eventHandler before invoking handler, in case the latter causes the former to be // executed recursively. Because blocks can be deallocated even during execution, we have to // first retain handler locally to guarantee it's valid. // TODO(jcanizales): Just turn this craziness into a simple subclass of GRXWriteable. GRXSingleHandler singleHandler = handler; eventHandler = nil; if (value) { singleHandler(value, nil); } else if (error) { singleHandler(nil, error); } else { NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: @"The writer finished without producing any value." }; // Even though RxLibrary is independent of gRPC, the domain and code here are, for the moment, // set to the values of kGRPCErrorDomain and GRPCErrorCodeInternal. This way, the error formed // is the one user of gRPC would expect if the server failed to produce a response. // // TODO(jcanizales): Figure out a way to keep errors of RxLibrary generic without making users // of gRPC take care of two different error domains and error code enums. A possibility is to // add error handling to GRXWriters or GRXWriteables, and use them to translate errors between // the two domains. static NSString *kGRPCErrorDomain = @"io.grpc"; static NSUInteger kGRPCErrorCodeInternal = 13; singleHandler(nil, [NSError errorWithDomain:kGRPCErrorDomain code:kGRPCErrorCodeInternal userInfo:userInfo]); } }; return [self writeableWithEventHandler:^(BOOL done, id value, NSError *error) { if (eventHandler) { eventHandler(done, value, error); } }]; } + (instancetype)writeableWithEventHandler:(GRXEventHandler)handler { if (!handler) { return [[self alloc] init]; } return [[self alloc] initWithValueHandler:^(id value) { handler(NO, value, nil); } completionHandler:^(NSError *errorOrNil) { handler(YES, nil, errorOrNil); }]; } - (instancetype)init { return [self initWithValueHandler:nil completionHandler:nil]; } // Designated initializer - (instancetype)initWithValueHandler:(GRXValueHandler)valueHandler completionHandler:(GRXCompletionHandler)completionHandler { if ((self = [super init])) { _valueHandler = valueHandler; _completionHandler = completionHandler; } return self; } - (void)writeValue:(id)value { if (_valueHandler) { _valueHandler(value); } } - (void)writesFinishedWithError:(NSError *)errorOrNil { if (_completionHandler) { _completionHandler(errorOrNil); } } @end grpc-1.3.2/src/objective-c/RxLibrary/GRXWriter+Immediate.h000066400000000000000000000057761310511640000232550ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRXWriter.h" @interface GRXWriter (Immediate) /** * Returns a writer that pulls values from the passed NSEnumerator instance and pushes them to * its writeable. The NSEnumerator is released when it finishes. */ + (instancetype)writerWithEnumerator:(NSEnumerator *)enumerator; /** * Returns a writer that pushes to its writeable the successive values returned by the passed * block. When the block first returns nil, it is released. */ + (instancetype)writerWithValueSupplier:(id (^)())block; /** * Returns a writer that iterates over the values of the passed container and pushes them to * its writeable. The container is released when the iteration is over. * * Note that the usual speed gain of NSFastEnumeration over NSEnumerator results from not having to * call one method per element. Because GRXWriteable instances accept values one by one, that speed * gain doesn't happen here. */ + (instancetype)writerWithContainer:(id)container; /** * Returns a writer that sends the passed value to its writeable and then finishes (releasing the * value). */ + (instancetype)writerWithValue:(id)value; /** * Returns a writer that, as part of its start method, sends the passed error to the writeable * (then releasing the error). */ + (instancetype)writerWithError:(NSError *)error; /** * Returns a writer that, as part of its start method, finishes immediately without sending any * values to its writeable. */ + (instancetype)emptyWriter; @end grpc-1.3.2/src/objective-c/RxLibrary/GRXWriter+Immediate.m000066400000000000000000000045321310511640000232470ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRXWriter+Immediate.h" #import "GRXImmediateWriter.h" #import "GRXImmediateSingleWriter.h" @implementation GRXWriter (Immediate) + (instancetype)writerWithEnumerator:(NSEnumerator *)enumerator { return [GRXImmediateWriter writerWithEnumerator:enumerator]; } + (instancetype)writerWithValueSupplier:(id (^)())block { return [GRXImmediateWriter writerWithValueSupplier:block]; } + (instancetype)writerWithContainer:(id)container { return [GRXImmediateWriter writerWithContainer:container]; } + (instancetype)writerWithValue:(id)value { return [GRXImmediateSingleWriter writerWithValue:value]; } + (instancetype)writerWithError:(NSError *)error { return [GRXImmediateWriter writerWithError:error]; } + (instancetype)emptyWriter { return [GRXImmediateWriter emptyWriter]; } @end grpc-1.3.2/src/objective-c/RxLibrary/GRXWriter+Transformations.h000066400000000000000000000034471310511640000245410ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRXWriter.h" @interface GRXWriter (Transformations) /** * Returns a writer that wraps the receiver, and has all the values the receiver would write * transformed by the provided mapping function. */ - (GRXWriter *)map:(id (^)(id value))map; @end grpc-1.3.2/src/objective-c/RxLibrary/GRXWriter+Transformations.m000066400000000000000000000034651310511640000245460ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRXWriter+Transformations.h" #import "transformations/GRXMappingWriter.h" @implementation GRXWriter (Transformations) - (GRXWriter *)map:(id (^)(id))map { if (!map) { return self; } return [[GRXMappingWriter alloc] initWithWriter:self map:map]; } @end grpc-1.3.2/src/objective-c/RxLibrary/GRXWriter.h000066400000000000000000000125401310511640000213460ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import "GRXWriteable.h" /** States of a writer. */ typedef NS_ENUM(NSInteger, GRXWriterState) { /** * The writer has not yet been given a writeable to which it can push its values. To have a writer * transition to the Started state, send it a startWithWriteable: message. * * A writer's state cannot be manually set to this value. */ GRXWriterStateNotStarted, /** The writer might push values to the writeable at any moment. */ GRXWriterStateStarted, /** * The writer is temporarily paused, and won't send any more values to the writeable unless its * state is set back to Started. The writer might still transition to the Finished state at any * moment, and is allowed to send writesFinishedWithError: to its writeable. */ GRXWriterStatePaused, /** * The writer has released its writeable and won't interact with it anymore. * * One seldomly wants to set a writer's state to this value, as its writeable isn't notified with * a writesFinishedWithError: message. Instead, sending finishWithError: to the writer will make * it notify the writeable and then transition to this state. */ GRXWriterStateFinished }; /** * An GRXWriter object can produce, on demand, a sequence of values. The sequence may be produced * asynchronously, and it may consist of any number of elements, including none or an infinite * number. * * GRXWriter is the active dual of NSEnumerator. The difference between them is thus whether the * object plays an active or passive role during usage: A user of NSEnumerator pulls values off it, * and passes the values to a writeable. A user of GRXWriter, though, just gives it a writeable, and * the GRXWriter instance pushes values to the writeable. This makes this protocol suitable to * represent a sequence of future values, as well as collections with internal iteration. * * An instance of GRXWriter can start producing values after a writeable is passed to it. It can * also be commanded to finish the sequence immediately (with an optional error). Finally, it can be * asked to pause, and resumed later. All GRXWriter objects support pausing and early termination. * * Thread-safety: * * State transitions take immediate effect if the object is used from a single thread. Subclasses * might offer stronger guarantees. * * Unless otherwise indicated by a conforming subclass, no messages should be sent concurrently to a * GRXWriter. I.e., conforming classes aren't required to be thread-safe. */ @interface GRXWriter : NSObject /** * This property can be used to query the current state of the writer, which determines how it might * currently use its writeable. Some state transitions can be triggered by setting this property to * the corresponding value, and that's useful for advanced use cases like pausing an writer. For * more details, see the documentation of the enum further down. */ @property(nonatomic) GRXWriterState state; /** * Transition to the Started state, and start sending messages to the writeable (a reference to it * is retained). Messages to the writeable may be sent before the method returns, or they may be * sent later in the future. See GRXWriteable.h for the different messages a writeable can receive. * * If this writer draws its values from an external source (e.g. from the filesystem or from a * server), calling this method will commonly trigger side effects (like network connections). * * This method might only be called on writers in the NotStarted state. */ - (void)startWithWriteable:(id)writeable; /** * Send writesFinishedWithError:errorOrNil to the writeable. Then release the reference to it and * transition to the Finished state. * * This method might only be called on writers in the Started or Paused state. */ - (void)finishWithError:(NSError *)errorOrNil; @end grpc-1.3.2/src/objective-c/RxLibrary/GRXWriter.m000066400000000000000000000036761310511640000213650ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRXWriter.h" @implementation GRXWriter - (void)startWithWriteable:(id)writeable { NSAssert(NO, @"Missing base implementation for %@", NSStringFromSelector(_cmd)); [self doesNotRecognizeSelector:_cmd]; } - (void)finishWithError:(NSError *)errorOrNil { NSAssert(NO, @"Missing base implementation for %@", NSStringFromSelector(_cmd)); [self doesNotRecognizeSelector:_cmd]; } @end grpc-1.3.2/src/objective-c/RxLibrary/NSEnumerator+GRXUtil.h000066400000000000000000000047201310511640000233660ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import @interface NSEnumerator (GRXUtil) /** * Returns a NSEnumerator instance that iterates through the elements of the passed container that * supports fast enumeration. Note that this negates the speed benefits of fast enumeration over * NSEnumerator. It's only intended for the rare cases when one needs the latter and only has the * former, e.g. for iteration that needs to be paused and resumed later. */ + (NSEnumerator *)grx_enumeratorWithContainer:(id)container; /** * Returns a NSEnumerator instance that provides a single object before finishing. The value is then * released. */ + (NSEnumerator *)grx_enumeratorWithSingleValue:(id)value; /** * Returns a NSEnumerator instance that delegates the invocations of nextObject to the passed block. * When the block first returns nil, it is released. */ + (NSEnumerator *)grx_enumeratorWithValueSupplier:(id (^)())block; @end grpc-1.3.2/src/objective-c/RxLibrary/NSEnumerator+GRXUtil.m000066400000000000000000000043611310511640000233740ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "NSEnumerator+GRXUtil.h" #import "private/GRXNSBlockEnumerator.h" #import "private/GRXNSFastEnumerator.h" #import "private/GRXNSScalarEnumerator.h" @implementation NSEnumerator (GRXUtil) + (NSEnumerator *)grx_enumeratorWithContainer:(id)container { // TODO(jcanizales): Consider checking if container responds to objectEnumerator and return that? return [[GRXNSFastEnumerator alloc] initWithContainer:container]; } + (NSEnumerator *)grx_enumeratorWithSingleValue:(id)value { return [[GRXNSScalarEnumerator alloc] initWithValue:value]; } + (NSEnumerator *)grx_enumeratorWithValueSupplier:(id (^)())block { return [[GRXNSBlockEnumerator alloc] initWithValueSupplier:block]; } @end grpc-1.3.2/src/objective-c/RxLibrary/README.md000066400000000000000000000005501310511640000206150ustar00rootroot00000000000000This is a generic Reactive Extensions library for Objective-C, created to ease the implementation of the gRPC Objective-C runtime. It has no dependencies on gRPC nor other libraries, and should eventually be moved under its own GitHub project. If you're trying to get started on the library, you might want to first read GRXWriter.h and then GRXWriteable.h. grpc-1.3.2/src/objective-c/RxLibrary/private/000077500000000000000000000000001310511640000210105ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/RxLibrary/private/GRXNSBlockEnumerator.h000066400000000000000000000036461310511640000251100ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import /** * Concrete subclass of NSEnumerator that delegates the invocations of nextObject to a block passed * on initialization. */ @interface GRXNSBlockEnumerator : NSEnumerator /** * The first time the passed block returns nil, the enumeration will end and the block will be * released. */ - (instancetype)initWithValueSupplier:(id (^)())block; @end grpc-1.3.2/src/objective-c/RxLibrary/private/GRXNSBlockEnumerator.m000066400000000000000000000037221310511640000251100ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRXNSBlockEnumerator.h" @implementation GRXNSBlockEnumerator { id (^_block)(); } - (instancetype)init { return [self initWithValueSupplier:nil]; } - (instancetype)initWithValueSupplier:(id (^)())block { if ((self = [super init])) { _block = block; } return self; } - (id)nextObject { if (!_block) { return nil; } id value = _block(); if (!value) { _block = nil; } return value; } @end grpc-1.3.2/src/objective-c/RxLibrary/private/GRXNSFastEnumerator.h000066400000000000000000000042321310511640000247430ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import /** * This is a bridge to interact through NSEnumerator's interface with objects that only conform to * NSFastEnumeration. (There's nothing specifically fast about it - you certainly don't win any * speed by using this instead of a NSEnumerator provided by your container). */ @interface GRXNSFastEnumerator : NSEnumerator /** * After the iteration of the container (via the NSFastEnumeration protocol) is over, the container * is released. If the container is modified during enumeration, an exception is thrown. */ - (instancetype)initWithContainer:(id)container; @end grpc-1.3.2/src/objective-c/RxLibrary/private/GRXNSFastEnumerator.m000066400000000000000000000065141310511640000247550ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRXNSFastEnumerator.h" @implementation GRXNSFastEnumerator { id _container; NSFastEnumerationState _state; // Number of elements of the container currently in the _state.itemsPtr array. NSUInteger _count; // The index of the next object to return from the _state.itemsPtr array. NSUInteger _index; // A "buffer of one element," for the containers that enumerate their elements one by one. Those // will set _state.itemsPtr to point to this. // The NSFastEnumeration protocol requires it to be __unsafe_unretained, but that's alright // because the only use we'd make of its value is to return it immediately as the result of // nextObject. __unsafe_unretained id _bufferValue; // Neither NSEnumerator nor NSFastEnumeration instances are required to work correctly when the // underlying container is mutated during iteration. The expectation is that an exception is // thrown when that happens. So we check for mutations. unsigned long _mutationFlag; BOOL _mutationFlagIsSet; } - (instancetype)init { return [self initWithContainer:nil]; } // Designated initializer. - (instancetype)initWithContainer:(id)container { if ((self = [super init])) { _container = container; } return self; } - (id)nextObject { if (_index == _count) { _index = 0; _count = [_container countByEnumeratingWithState:&_state objects:&_bufferValue count:1]; if (_count == 0) { // Enumeration is over. _container = nil; return nil; } if (_mutationFlagIsSet) { NSAssert(_mutationFlag == *(_state.mutationsPtr), @"container was mutated while being enumerated"); } else { _mutationFlag = *(_state.mutationsPtr); _mutationFlagIsSet = YES; } } return _state.itemsPtr[_index++]; } @end grpc-1.3.2/src/objective-c/RxLibrary/private/GRXNSScalarEnumerator.h000066400000000000000000000036171310511640000252610ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import /** Concrete subclass of NSEnumerator whose instances return a single object before finishing. */ @interface GRXNSScalarEnumerator : NSEnumerator /** * Param value: the single object this instance will produce. After the first invocation of * nextObject, the value is released. */ - (instancetype)initWithValue:(id)value; @end grpc-1.3.2/src/objective-c/RxLibrary/private/GRXNSScalarEnumerator.m000066400000000000000000000036271310511640000252670ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRXNSScalarEnumerator.h" @implementation GRXNSScalarEnumerator { id _value; } - (instancetype)init { return [self initWithValue:nil]; } // Designated initializer. - (instancetype)initWithValue:(id)value { if ((self = [super init])) { _value = value; } return self; } - (id)nextObject { id value = _value; _value = nil; return value; } @end grpc-1.3.2/src/objective-c/RxLibrary/transformations/000077500000000000000000000000001310511640000225675ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/RxLibrary/transformations/GRXMappingWriter.h000066400000000000000000000035301310511640000261120ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "RxLibrary/GRXForwardingWriter.h" /** A "proxy" writer that transforms all the values of its input writer by using a mapping function. */ @interface GRXMappingWriter : GRXForwardingWriter - (instancetype)initWithWriter:(GRXWriter *)writer map:(id (^)(id value))map NS_DESIGNATED_INITIALIZER; @end grpc-1.3.2/src/objective-c/RxLibrary/transformations/GRXMappingWriter.m000066400000000000000000000041341310511640000261200ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "GRXMappingWriter.h" @interface GRXForwardingWriter () @end @implementation GRXMappingWriter { id (^_map)(id value); } - (instancetype)initWithWriter:(GRXWriter *)writer { return [self initWithWriter:writer map:nil]; } // Designated initializer - (instancetype)initWithWriter:(GRXWriter *)writer map:(id (^)(id value))map { if ((self = [super initWithWriter:writer])) { _map = map ?: ^id(id value) { return value; }; } return self; } // Override - (void)writeValue:(id)value { [super writeValue:_map(value)]; } @end grpc-1.3.2/src/objective-c/change-comments.py000077500000000000000000000070451310511640000210530ustar00rootroot00000000000000#!/usr/bin/env python2.7 # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Change comments style of source files from // to /** */""" import re import sys if len(sys.argv) < 2: print("Please provide at least one source file name as argument.") sys.exit() for file_name in sys.argv[1:]: print("Modifying format of {file} comments in place...".format( file=file_name, )) # Input with open(file_name, "r") as input_file: lines = input_file.readlines() def peek(): return lines[0] def read_line(): return lines.pop(0) def more_input_available(): return lines # Output output_lines = [] def write(line): output_lines.append(line) def flush_output(): with open(file_name, "w") as output_file: for line in output_lines: output_file.write(line) # Pattern matching comment_regex = r'^(\s*)//\s(.*)$' def is_comment(line): return re.search(comment_regex, line) def isnt_comment(line): return not is_comment(line) def next_line(predicate): return more_input_available() and predicate(peek()) # Transformation def indentation_of(line): match = re.search(comment_regex, line) return match.group(1) def content(line): match = re.search(comment_regex, line) return match.group(2) def format_as_block(comment_block): if len(comment_block) == 0: return [] indent = indentation_of(comment_block[0]) if len(comment_block) == 1: return [indent + "/** " + content(comment_block[0]) + " */\n"] block = ["/**"] + [" * " + content(line) for line in comment_block] + [" */"] return [indent + line.rstrip() + "\n" for line in block] # Main algorithm while more_input_available(): while next_line(isnt_comment): write(read_line()) comment_block = [] # Get all lines in the same comment block. We could restrict the indentation # to be the same as the first line of the block, but it's probably ok. while (next_line(is_comment)): comment_block.append(read_line()) for line in format_as_block(comment_block): write(line) flush_output() grpc-1.3.2/src/objective-c/examples/000077500000000000000000000000001310511640000172365ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/examples/RemoteTestClient/000077500000000000000000000000001310511640000224705ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec000066400000000000000000000031531310511640000261440ustar00rootroot00000000000000Pod::Spec.new do |s| s.name = 'RemoteTest' s.version = '0.0.1' s.license = 'New BSD' s.authors = { 'gRPC contributors' => 'grpc-io@googlegroups.com' } s.homepage = 'http://www.grpc.io/' s.summary = 'RemoteTest example' s.source = { :git => 'https://github.com/grpc/grpc.git' } s.ios.deployment_target = '7.1' s.osx.deployment_target = '10.9' # Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients. s.dependency "!ProtoCompiler-gRPCPlugin" repo_root = '../../../..' bin_dir = "#{repo_root}/bins/$CONFIG" protoc = "#{bin_dir}/protobuf/protoc" well_known_types_dir = "#{repo_root}/third_party/protobuf/src" plugin = "#{bin_dir}/grpc_objective_c_plugin" s.prepare_command = <<-CMD #{protoc} \ --plugin=protoc-gen-grpc=#{plugin} \ --objc_out=. \ --grpc_out=. \ -I . \ -I #{well_known_types_dir} \ *.proto CMD s.subspec 'Messages' do |ms| ms.source_files = '*.pbobjc.{h,m}' ms.header_mappings_dir = '.' ms.requires_arc = false ms.dependency 'Protobuf' end s.subspec 'Services' do |ss| ss.source_files = '*.pbrpc.{h,m}' ss.header_mappings_dir = '.' ss.requires_arc = true ss.dependency 'gRPC-ProtoRPC' ss.dependency "#{s.name}/Messages" end s.pod_target_xcconfig = { # This is needed by all pods that depend on Protobuf: 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1', # This is needed by all pods that depend on gRPC-RxLibrary: 'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES', } end grpc-1.3.2/src/objective-c/examples/RemoteTestClient/messages.proto000066400000000000000000000106631310511640000253720ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Message definitions to be used by integration test service definitions. syntax = "proto3"; package grpc.testing; option objc_class_prefix = "RMT"; // The type of payload that should be returned. enum PayloadType { // Compressable text format. COMPRESSABLE = 0; // Uncompressable binary format. UNCOMPRESSABLE = 1; // Randomly chosen from all other formats defined in this enum. RANDOM = 2; } // A block of data, to simply increase gRPC message size. message Payload { // The type of data in body. PayloadType type = 1; // Primary contents of payload. bytes body = 2; } // Unary request. message SimpleRequest { // Desired payload type in the response from the server. // If response_type is RANDOM, server randomly chooses one from other formats. PayloadType response_type = 1; // Desired payload size in the response from the server. // If response_type is COMPRESSABLE, this denotes the size before compression. int32 response_size = 2; // Optional input payload sent along with the request. Payload payload = 3; // Whether SimpleResponse should include username. bool fill_username = 4; // Whether SimpleResponse should include OAuth scope. bool fill_oauth_scope = 5; } // Unary response, as configured by the request. message SimpleResponse { // Payload to increase message size. Payload payload = 1; // The user the request came from, for verifying authentication was // successful when the client expected it. string username = 2; // OAuth scope. string oauth_scope = 3; } // Client-streaming request. message StreamingInputCallRequest { // Optional input payload sent along with the request. Payload payload = 1; // Not expecting any payload from the response. } // Client-streaming response. message StreamingInputCallResponse { // Aggregated size of payloads received from the client. int32 aggregated_payload_size = 1; } // Configuration for a particular response. message ResponseParameters { // Desired payload sizes in responses from the server. // If response_type is COMPRESSABLE, this denotes the size before compression. int32 size = 1; // Desired interval between consecutive responses in the response stream in // microseconds. int32 interval_us = 2; } // Server-streaming request. message StreamingOutputCallRequest { // Desired payload type in the response from the server. // If response_type is RANDOM, the payload from each response in the stream // might be of different types. This is to simulate a mixed type of payload // stream. PayloadType response_type = 1; // Configuration for each expected response message. repeated ResponseParameters response_parameters = 2; // Optional input payload sent along with the request. Payload payload = 3; } // Server-streaming response, as configured by the request and parameters. message StreamingOutputCallResponse { // Payload to increase response size. Payload payload = 1; } grpc-1.3.2/src/objective-c/examples/RemoteTestClient/test.proto000066400000000000000000000064371310511640000245460ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // An integration test service that covers all the method signature permutations // of unary/streaming requests/responses. syntax = "proto3"; import "google/protobuf/empty.proto"; import "messages.proto"; package grpc.testing; option objc_class_prefix = "RMT"; // A simple service to test the various types of RPCs and experiment with // performance with various types of payload. service TestService { // One empty request followed by one empty response. rpc EmptyCall(google.protobuf.Empty) returns (google.protobuf.Empty); // One request followed by one response. rpc UnaryCall(SimpleRequest) returns (SimpleResponse); // One request followed by a sequence of responses (streamed download). // The server returns the payload with client desired type and sizes. rpc StreamingOutputCall(StreamingOutputCallRequest) returns (stream StreamingOutputCallResponse); // A sequence of requests followed by one response (streamed upload). // The server returns the aggregated size of client payload as the result. rpc StreamingInputCall(stream StreamingInputCallRequest) returns (StreamingInputCallResponse); // A sequence of requests with each request served by the server immediately. // As one request could lead to multiple responses, this interface // demonstrates the idea of full duplexing. rpc FullDuplexCall(stream StreamingOutputCallRequest) returns (stream StreamingOutputCallResponse); // A sequence of requests followed by a sequence of responses. // The server buffers all the client requests and then serves them in order. A // stream of responses are returned to the client when the server starts with // first request. rpc HalfDuplexCall(stream StreamingOutputCallRequest) returns (stream StreamingOutputCallResponse); } grpc-1.3.2/src/objective-c/examples/Sample/000077500000000000000000000000001310511640000204575ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/examples/Sample/Podfile000066400000000000000000000035201310511640000217640ustar00rootroot00000000000000source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' install! 'cocoapods', :deterministic_uuids => false use_frameworks! if ENV['FRAMEWORKS'] == 'YES' # Location of gRPC's repo root relative to this file. GRPC_LOCAL_SRC = '../../../..' target 'Sample' do # Depend on the generated RemoteTestClient library pod 'RemoteTest', :path => "../RemoteTestClient" # Use the local versions of Protobuf, BoringSSL, and gRPC. You don't need any of the following # lines in your application. pod '!ProtoCompiler', :path => "#{GRPC_LOCAL_SRC}/src/objective-c" pod '!ProtoCompiler-gRPCPlugin', :path => "#{GRPC_LOCAL_SRC}/src/objective-c" pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf" pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c" pod 'gRPC', :path => GRPC_LOCAL_SRC pod 'gRPC-Core', :path => GRPC_LOCAL_SRC pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC pod 'gRPC-ProtoRPC', :path => GRPC_LOCAL_SRC end # This pre_install hook is only needed to use the local version of gRPC-Core. You don't need it in # your application. pre_install do |installer| # This is the gRPC-Core podspec object, as initialized by its podspec file. grpc_core_spec = installer.pod_targets.find{|t| t.name == 'gRPC-Core'}.root_spec # Copied from gRPC-Core.podspec, except for the adjusted src_root: src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}" grpc_core_spec.pod_target_xcconfig = { 'GRPC_SRC_ROOT' => src_root, 'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"', 'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"', # If we don't set these two settings, `include/grpc/support/time.h` and # `src/core/lib/support/string.h` shadow the system `` and ``, breaking the # build. 'USE_HEADERMAP' => 'NO', 'ALWAYS_SEARCH_USER_PATHS' => 'NO', } end grpc-1.3.2/src/objective-c/examples/Sample/README.md000066400000000000000000000003011310511640000217300ustar00rootroot00000000000000This sample app requires the use of Cocoapods. After installing Cocoapods, run `pod install` in this directory to recreate its dependencies. (This will compile OpenSSL, which takes some time). grpc-1.3.2/src/objective-c/examples/Sample/Sample.xcodeproj/000077500000000000000000000000001310511640000236745ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj000066400000000000000000000337541310511640000267640ustar00rootroot00000000000000// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 3F035697392F601049D3DDE1 /* Pods_Sample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC1B27EA0C428429B07BC34B /* Pods_Sample.framework */; }; 6369A2701A9322E20015FC5C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A26F1A9322E20015FC5C /* main.m */; }; 6369A2731A9322E20015FC5C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2721A9322E20015FC5C /* AppDelegate.m */; }; 6369A2761A9322E20015FC5C /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2751A9322E20015FC5C /* ViewController.m */; }; 6369A2791A9322E20015FC5C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6369A2771A9322E20015FC5C /* Main.storyboard */; }; 6369A27B1A9322E20015FC5C /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6369A27A1A9322E20015FC5C /* Images.xcassets */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 5A8C9F4B28733B249DE4AB6D /* Pods-Sample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sample.release.xcconfig"; path = "Pods/Target Support Files/Pods-Sample/Pods-Sample.release.xcconfig"; sourceTree = ""; }; 6369A26A1A9322E20015FC5C /* Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6369A26E1A9322E20015FC5C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 6369A26F1A9322E20015FC5C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 6369A2711A9322E20015FC5C /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 6369A2721A9322E20015FC5C /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 6369A2741A9322E20015FC5C /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 6369A2751A9322E20015FC5C /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 6369A2781A9322E20015FC5C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 6369A27A1A9322E20015FC5C /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; CC1B27EA0C428429B07BC34B /* Pods_Sample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Sample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E3C01DF315C4E7433BCEC6E6 /* Pods-Sample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Sample/Pods-Sample.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 6369A2671A9322E20015FC5C /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 3F035697392F601049D3DDE1 /* Pods_Sample.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 6369A2611A9322E20015FC5C = { isa = PBXGroup; children = ( 6369A26C1A9322E20015FC5C /* Sample */, 6369A26B1A9322E20015FC5C /* Products */, AB3331C9AE6488E61B2B094E /* Pods */, C4C2C5219053E079C9EFB930 /* Frameworks */, ); sourceTree = ""; }; 6369A26B1A9322E20015FC5C /* Products */ = { isa = PBXGroup; children = ( 6369A26A1A9322E20015FC5C /* Sample.app */, ); name = Products; sourceTree = ""; }; 6369A26C1A9322E20015FC5C /* Sample */ = { isa = PBXGroup; children = ( 6369A2711A9322E20015FC5C /* AppDelegate.h */, 6369A2721A9322E20015FC5C /* AppDelegate.m */, 6369A2741A9322E20015FC5C /* ViewController.h */, 6369A2751A9322E20015FC5C /* ViewController.m */, 6369A2771A9322E20015FC5C /* Main.storyboard */, 6369A27A1A9322E20015FC5C /* Images.xcassets */, 6369A26D1A9322E20015FC5C /* Supporting Files */, ); path = Sample; sourceTree = ""; }; 6369A26D1A9322E20015FC5C /* Supporting Files */ = { isa = PBXGroup; children = ( 6369A26E1A9322E20015FC5C /* Info.plist */, 6369A26F1A9322E20015FC5C /* main.m */, ); name = "Supporting Files"; sourceTree = ""; }; AB3331C9AE6488E61B2B094E /* Pods */ = { isa = PBXGroup; children = ( E3C01DF315C4E7433BCEC6E6 /* Pods-Sample.debug.xcconfig */, 5A8C9F4B28733B249DE4AB6D /* Pods-Sample.release.xcconfig */, ); name = Pods; sourceTree = ""; }; C4C2C5219053E079C9EFB930 /* Frameworks */ = { isa = PBXGroup; children = ( CC1B27EA0C428429B07BC34B /* Pods_Sample.framework */, ); name = Frameworks; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 6369A2691A9322E20015FC5C /* Sample */ = { isa = PBXNativeTarget; buildConfigurationList = 6369A28D1A9322E20015FC5C /* Build configuration list for PBXNativeTarget "Sample" */; buildPhases = ( 41F7486D8F66994B0BFB84AF /* [CP] Check Pods Manifest.lock */, 6369A2661A9322E20015FC5C /* Sources */, 6369A2671A9322E20015FC5C /* Frameworks */, 6369A2681A9322E20015FC5C /* Resources */, 04554623324BE4A838846086 /* [CP] Copy Pods Resources */, C7FAD018D05AB5F0B0FE81E2 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); dependencies = ( ); name = Sample; productName = Sample; productReference = 6369A26A1A9322E20015FC5C /* Sample.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 6369A2621A9322E20015FC5C /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0730; ORGANIZATIONNAME = gRPC; TargetAttributes = { 6369A2691A9322E20015FC5C = { CreatedOnToolsVersion = 6.1.1; }; }; }; buildConfigurationList = 6369A2651A9322E20015FC5C /* Build configuration list for PBXProject "Sample" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 6369A2611A9322E20015FC5C; productRefGroup = 6369A26B1A9322E20015FC5C /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 6369A2691A9322E20015FC5C /* Sample */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 6369A2681A9322E20015FC5C /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 6369A2791A9322E20015FC5C /* Main.storyboard in Resources */, 6369A27B1A9322E20015FC5C /* Images.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 04554623324BE4A838846086 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Sample/Pods-Sample-resources.sh\"\n"; showEnvVarsInLog = 0; }; 41F7486D8F66994B0BFB84AF /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; C7FAD018D05AB5F0B0FE81E2 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Sample/Pods-Sample-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 6369A2661A9322E20015FC5C /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 6369A2761A9322E20015FC5C /* ViewController.m in Sources */, 6369A2731A9322E20015FC5C /* AppDelegate.m in Sources */, 6369A2701A9322E20015FC5C /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 6369A2771A9322E20015FC5C /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 6369A2781A9322E20015FC5C /* Base */, ); name = Main.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 6369A28B1A9322E20015FC5C /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.1; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 6369A28C1A9322E20015FC5C /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.1; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; 6369A28E1A9322E20015FC5C /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = E3C01DF315C4E7433BCEC6E6 /* Pods-Sample.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Sample/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "org.grpc.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 6369A28F1A9322E20015FC5C /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 5A8C9F4B28733B249DE4AB6D /* Pods-Sample.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Sample/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "org.grpc.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 6369A2651A9322E20015FC5C /* Build configuration list for PBXProject "Sample" */ = { isa = XCConfigurationList; buildConfigurations = ( 6369A28B1A9322E20015FC5C /* Debug */, 6369A28C1A9322E20015FC5C /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 6369A28D1A9322E20015FC5C /* Build configuration list for PBXNativeTarget "Sample" */ = { isa = XCConfigurationList; buildConfigurations = ( 6369A28E1A9322E20015FC5C /* Debug */, 6369A28F1A9322E20015FC5C /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 6369A2621A9322E20015FC5C /* Project object */; } grpc-1.3.2/src/objective-c/examples/Sample/Sample.xcodeproj/project.xcworkspace/000077500000000000000000000000001310511640000276725ustar00rootroot00000000000000contents.xcworkspacedata000066400000000000000000000002271310511640000345560ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/examples/Sample/Sample.xcodeproj/project.xcworkspace grpc-1.3.2/src/objective-c/examples/Sample/Sample.xcodeproj/xcshareddata/000077500000000000000000000000001310511640000263275ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/examples/Sample/Sample.xcodeproj/xcshareddata/xcschemes/000077500000000000000000000000001310511640000303115ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/examples/Sample/Sample.xcodeproj/xcshareddata/xcschemes/Sample.xcscheme000066400000000000000000000063331310511640000332600ustar00rootroot00000000000000 grpc-1.3.2/src/objective-c/examples/Sample/Sample/000077500000000000000000000000001310511640000217005ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/examples/Sample/Sample/AppDelegate.h000066400000000000000000000032551310511640000242310ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @end grpc-1.3.2/src/objective-c/examples/Sample/Sample/AppDelegate.m000066400000000000000000000031341310511640000242320ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "AppDelegate.h" @implementation AppDelegate @end grpc-1.3.2/src/objective-c/examples/Sample/Sample/Base.lproj/000077500000000000000000000000001310511640000236775ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/examples/Sample/Sample/Base.lproj/Main.storyboard000066400000000000000000000102161310511640000266750ustar00rootroot00000000000000 grpc-1.3.2/src/objective-c/examples/Sample/Sample/Images.xcassets/000077500000000000000000000000001310511640000247415ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/examples/Sample/Sample/Images.xcassets/AppIcon.appiconset/000077500000000000000000000000001310511640000304365ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/examples/Sample/Sample/Images.xcassets/AppIcon.appiconset/Contents.json000066400000000000000000000020651310511640000331310ustar00rootroot00000000000000{ "images" : [ { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } }grpc-1.3.2/src/objective-c/examples/Sample/Sample/Info.plist000066400000000000000000000027171310511640000236570ustar00rootroot00000000000000 CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName Main UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight grpc-1.3.2/src/objective-c/examples/Sample/Sample/ViewController.h000066400000000000000000000031551310511640000250330ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import @interface ViewController : UIViewController @end grpc-1.3.2/src/objective-c/examples/Sample/Sample/ViewController.m000066400000000000000000000070201310511640000250330ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "ViewController.h" #import #import #import #import #import #import @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; NSString * const kRemoteHost = @"grpc-test.sandbox.googleapis.com"; RMTSimpleRequest *request = [[RMTSimpleRequest alloc] init]; request.responseSize = 10; request.fillUsername = YES; request.fillOauthScope = YES; // Example gRPC call using a generated proto client library: RMTTestService *service = [[RMTTestService alloc] initWithHost:kRemoteHost]; [service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) { if (response) { NSLog(@"Finished successfully with response:\n%@", response); } else if (error) { NSLog(@"Finished with error: %@", error); } }]; // Same example call using the generic gRPC client library: GRPCProtoMethod *method = [[GRPCProtoMethod alloc] initWithPackage:@"grpc.testing" service:@"TestService" method:@"UnaryCall"]; GRXWriter *requestsWriter = [GRXWriter writerWithValue:[request data]]; GRPCCall *call = [[GRPCCall alloc] initWithHost:kRemoteHost path:method.HTTPPath requestsWriter:requestsWriter]; id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { RMTSimpleResponse *response = [RMTSimpleResponse parseFromData:value error:NULL]; NSLog(@"Received response:\n%@", response); } completionHandler:^(NSError *errorOrNil) { if (errorOrNil) { NSLog(@"Finished with error: %@", errorOrNil); } else { NSLog(@"Finished successfully."); } }]; [call startWithWriteable:responsesWriteable]; } @end grpc-1.3.2/src/objective-c/examples/Sample/Sample/main.m000066400000000000000000000033531310511640000230060ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import "AppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } grpc-1.3.2/src/objective-c/examples/SwiftSample/000077500000000000000000000000001310511640000214745ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/examples/SwiftSample/AppDelegate.swift000066400000000000000000000032251310511640000247270ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? } grpc-1.3.2/src/objective-c/examples/SwiftSample/Base.lproj/000077500000000000000000000000001310511640000234735ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/examples/SwiftSample/Base.lproj/Main.storyboard000066400000000000000000000030551310511640000264740ustar00rootroot00000000000000 grpc-1.3.2/src/objective-c/examples/SwiftSample/Images.xcassets/000077500000000000000000000000001310511640000245355ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/examples/SwiftSample/Images.xcassets/AppIcon.appiconset/000077500000000000000000000000001310511640000302325ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/examples/SwiftSample/Images.xcassets/AppIcon.appiconset/Contents.json000066400000000000000000000020651310511640000327250ustar00rootroot00000000000000{ "images" : [ { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } }grpc-1.3.2/src/objective-c/examples/SwiftSample/Info.plist000066400000000000000000000027171310511640000234530ustar00rootroot00000000000000 CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName Main UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight grpc-1.3.2/src/objective-c/examples/SwiftSample/Podfile000066400000000000000000000034671310511640000230130ustar00rootroot00000000000000source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' install! 'cocoapods', :deterministic_uuids => false use_frameworks! # Location of gRPC's repo root relative to this file. GRPC_LOCAL_SRC = '../../../..' target 'SwiftSample' do # Depend on the generated RemoteTestClient library pod 'RemoteTest', :path => "../RemoteTestClient" # Use the local versions of Protobuf, BoringSSL, and gRPC. You don't need any of the following # lines in your application. pod '!ProtoCompiler', :path => "#{GRPC_LOCAL_SRC}/src/objective-c" pod '!ProtoCompiler-gRPCPlugin', :path => "#{GRPC_LOCAL_SRC}/src/objective-c" pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf" pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c" pod 'gRPC', :path => GRPC_LOCAL_SRC pod 'gRPC-Core', :path => GRPC_LOCAL_SRC pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC pod 'gRPC-ProtoRPC', :path => GRPC_LOCAL_SRC end # This pre_install hook is only needed to use the local version of gRPC-Core. You don't need it in # your application. pre_install do |installer| # This is the gRPC-Core podspec object, as initialized by its podspec file. grpc_core_spec = installer.pod_targets.find{|t| t.name == 'gRPC-Core'}.root_spec # Copied from gRPC-Core.podspec, except for the adjusted src_root: src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}" grpc_core_spec.pod_target_xcconfig = { 'GRPC_SRC_ROOT' => src_root, 'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"', 'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"', # If we don't set these two settings, `include/grpc/support/time.h` and # `src/core/lib/support/string.h` shadow the system `` and ``, breaking the # build. 'USE_HEADERMAP' => 'NO', 'ALWAYS_SEARCH_USER_PATHS' => 'NO', } end grpc-1.3.2/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/000077500000000000000000000000001310511640000257265ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj000066400000000000000000000334421310511640000310100ustar00rootroot00000000000000// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 2C0B024CB798839E17F76126 /* Pods_SwiftSample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B394F343BDE186C5436DBDB9 /* Pods_SwiftSample.framework */; }; 633BFFC81B950B210007E424 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 633BFFC71B950B210007E424 /* AppDelegate.swift */; }; 633BFFCA1B950B210007E424 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 633BFFC91B950B210007E424 /* ViewController.swift */; }; 633BFFCD1B950B210007E424 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 633BFFCB1B950B210007E424 /* Main.storyboard */; }; 633BFFCF1B950B210007E424 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 633BFFCE1B950B210007E424 /* Images.xcassets */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 633BFFC21B950B210007E424 /* SwiftSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 633BFFC61B950B210007E424 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 633BFFC71B950B210007E424 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 633BFFC91B950B210007E424 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 633BFFCC1B950B210007E424 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 633BFFCE1B950B210007E424 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; A7E614A494D89D01BB395761 /* Pods-SwiftSample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftSample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftSample/Pods-SwiftSample.debug.xcconfig"; sourceTree = ""; }; B394F343BDE186C5436DBDB9 /* Pods_SwiftSample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SwiftSample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C314E3E246AF23AC29B38FCF /* Pods-SwiftSample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftSample.release.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftSample/Pods-SwiftSample.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 633BFFBF1B950B210007E424 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 2C0B024CB798839E17F76126 /* Pods_SwiftSample.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 31F283C976AE97586C17CCD9 /* Pods */ = { isa = PBXGroup; children = ( A7E614A494D89D01BB395761 /* Pods-SwiftSample.debug.xcconfig */, C314E3E246AF23AC29B38FCF /* Pods-SwiftSample.release.xcconfig */, ); name = Pods; sourceTree = ""; }; 633BFFB91B950B210007E424 = { isa = PBXGroup; children = ( 633BFFC41B950B210007E424 /* SwiftSample */, 633BFFC31B950B210007E424 /* Products */, 31F283C976AE97586C17CCD9 /* Pods */, 9D63A7F6423989BA306810CA /* Frameworks */, ); sourceTree = ""; }; 633BFFC31B950B210007E424 /* Products */ = { isa = PBXGroup; children = ( 633BFFC21B950B210007E424 /* SwiftSample.app */, ); name = Products; sourceTree = ""; }; 633BFFC41B950B210007E424 /* SwiftSample */ = { isa = PBXGroup; children = ( 633BFFC71B950B210007E424 /* AppDelegate.swift */, 633BFFC91B950B210007E424 /* ViewController.swift */, 633BFFCB1B950B210007E424 /* Main.storyboard */, 633BFFCE1B950B210007E424 /* Images.xcassets */, 633BFFC51B950B210007E424 /* Supporting Files */, ); name = SwiftSample; sourceTree = SOURCE_ROOT; }; 633BFFC51B950B210007E424 /* Supporting Files */ = { isa = PBXGroup; children = ( 633BFFC61B950B210007E424 /* Info.plist */, ); name = "Supporting Files"; sourceTree = ""; }; 9D63A7F6423989BA306810CA /* Frameworks */ = { isa = PBXGroup; children = ( B394F343BDE186C5436DBDB9 /* Pods_SwiftSample.framework */, ); name = Frameworks; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 633BFFC11B950B210007E424 /* SwiftSample */ = { isa = PBXNativeTarget; buildConfigurationList = 633BFFE11B950B210007E424 /* Build configuration list for PBXNativeTarget "SwiftSample" */; buildPhases = ( 6BEEB33CA2705D7D2F2210E6 /* [CP] Check Pods Manifest.lock */, 633BFFBE1B950B210007E424 /* Sources */, 633BFFBF1B950B210007E424 /* Frameworks */, 633BFFC01B950B210007E424 /* Resources */, AC2F6F9AB1C090BB0BEE6E4D /* [CP] Copy Pods Resources */, A1738A987353B0BF2C64F0F7 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); dependencies = ( ); name = SwiftSample; productName = SwiftSample; productReference = 633BFFC21B950B210007E424 /* SwiftSample.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 633BFFBA1B950B210007E424 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0710; LastUpgradeCheck = 0730; ORGANIZATIONNAME = gRPC; TargetAttributes = { 633BFFC11B950B210007E424 = { CreatedOnToolsVersion = 6.4; }; }; }; buildConfigurationList = 633BFFBD1B950B210007E424 /* Build configuration list for PBXProject "SwiftSample" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 633BFFB91B950B210007E424; productRefGroup = 633BFFC31B950B210007E424 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 633BFFC11B950B210007E424 /* SwiftSample */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 633BFFC01B950B210007E424 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 633BFFCD1B950B210007E424 /* Main.storyboard in Resources */, 633BFFCF1B950B210007E424 /* Images.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 6BEEB33CA2705D7D2F2210E6 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; A1738A987353B0BF2C64F0F7 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SwiftSample/Pods-SwiftSample-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; AC2F6F9AB1C090BB0BEE6E4D /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SwiftSample/Pods-SwiftSample-resources.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 633BFFBE1B950B210007E424 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 633BFFCA1B950B210007E424 /* ViewController.swift in Sources */, 633BFFC81B950B210007E424 /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 633BFFCB1B950B210007E424 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 633BFFCC1B950B210007E424 /* Base */, ); name = Main.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 633BFFDF1B950B210007E424 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.4; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 633BFFE01B950B210007E424 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.4; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; 633BFFE21B950B210007E424 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = A7E614A494D89D01BB395761 /* Pods-SwiftSample.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "io.grpc.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = ""; USER_HEADER_SEARCH_PATHS = ""; }; name = Debug; }; 633BFFE31B950B210007E424 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = C314E3E246AF23AC29B38FCF /* Pods-SwiftSample.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "io.grpc.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = ""; USER_HEADER_SEARCH_PATHS = ""; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 633BFFBD1B950B210007E424 /* Build configuration list for PBXProject "SwiftSample" */ = { isa = XCConfigurationList; buildConfigurations = ( 633BFFDF1B950B210007E424 /* Debug */, 633BFFE01B950B210007E424 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 633BFFE11B950B210007E424 /* Build configuration list for PBXNativeTarget "SwiftSample" */ = { isa = XCConfigurationList; buildConfigurations = ( 633BFFE21B950B210007E424 /* Debug */, 633BFFE31B950B210007E424 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 633BFFBA1B950B210007E424 /* Project object */; } grpc-1.3.2/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.xcworkspace/000077500000000000000000000000001310511640000317245ustar00rootroot00000000000000contents.xcworkspacedata000066400000000000000000000002341310511640000366060ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.xcworkspace grpc-1.3.2/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/xcshareddata/000077500000000000000000000000001310511640000303615ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/xcshareddata/xcschemes/000077500000000000000000000000001310511640000323435ustar00rootroot00000000000000SwiftSample.xcscheme000066400000000000000000000064271310511640000362540ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/xcshareddata/xcschemes grpc-1.3.2/src/objective-c/examples/SwiftSample/ViewController.swift000066400000000000000000000072251310511640000255360ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ import UIKit import RemoteTest class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let RemoteHost = "grpc-test.sandbox.googleapis.com" let request = RMTSimpleRequest() request.responseSize = 10 request.fillUsername = true request.fillOauthScope = true // Example gRPC call using a generated proto client library: let service = RMTTestService(host: RemoteHost) service.unaryCallWithRequest(request) { response, error in if let response = response { NSLog("1. Finished successfully with response:\n\(response)") } else { NSLog("1. Finished with error: \(error!)") } } // Same but manipulating headers: var RPC : GRPCProtoCall! // Needed to convince Swift to capture by reference (__block) RPC = service.RPCToUnaryCallWithRequest(request) { response, error in if let response = response { NSLog("2. Finished successfully with response:\n\(response)") } else { NSLog("2. Finished with error: \(error!)") } NSLog("2. Response headers: \(RPC.responseHeaders)") NSLog("2. Response trailers: \(RPC.responseTrailers)") } // TODO(jcanizales): Revert to using subscript syntax once XCode 8 is released. RPC.requestHeaders.setObject("My value", forKey: "My-Header") RPC.start() // Same example call using the generic gRPC client library: let method = GRPCProtoMethod(package: "grpc.testing", service: "TestService", method: "UnaryCall") let requestsWriter = GRXWriter(value: request.data()) let call = GRPCCall(host: RemoteHost, path: method.HTTPPath, requestsWriter: requestsWriter) call.requestHeaders.setObject("My value", forKey: "My-Header") call.startWithWriteable(GRXWriteable { response, error in if let response = response as? NSData { NSLog("3. Received response:\n\(try! RMTSimpleResponse(data: response))") } else { NSLog("3. Finished with error: \(error!)") } NSLog("3. Response headers: \(call.responseHeaders)") NSLog("3. Response trailers: \(call.responseTrailers)") }) } } grpc-1.3.2/src/objective-c/format-all-comments.sh000066400000000000000000000032351310511640000216400ustar00rootroot00000000000000#!/bin/bash # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. find . -type f -name "*.h" ! -path "*/Pods/*" ! -path "./generated_libraries/*" ! -path "./examples/*" ! -path "./tests/*" | xargs ./change-comments.py grpc-1.3.2/src/objective-c/tests/000077500000000000000000000000001310511640000165625ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/tests/Connectivity/000077500000000000000000000000001310511640000212405ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/tests/Connectivity/Base.lproj/000077500000000000000000000000001310511640000232375ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/tests/Connectivity/Base.lproj/Main.storyboard000066400000000000000000000016271310511640000262430ustar00rootroot00000000000000 grpc-1.3.2/src/objective-c/tests/Connectivity/ConnectivityTestingApp.xcodeproj/000077500000000000000000000000001310511640000277115ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/tests/Connectivity/ConnectivityTestingApp.xcodeproj/project.pbxproj000066400000000000000000000323711310511640000327730ustar00rootroot00000000000000// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 500A4E0AC9D489EB214D1ED4 /* libPods-ConnectivityTestingApp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C2AF815D8242A2172891621D /* libPods-ConnectivityTestingApp.a */; }; 63BFB9CC1D2478DD00E17927 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 63BFB9CB1D2478DD00E17927 /* main.m */; }; 63BFB9D21D2478DD00E17927 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 63BFB9D11D2478DD00E17927 /* ViewController.m */; }; 63BFB9D51D2478DD00E17927 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 63BFB9D31D2478DD00E17927 /* Main.storyboard */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 63BFB9C71D2478DD00E17927 /* ConnectivityTestingApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ConnectivityTestingApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 63BFB9CB1D2478DD00E17927 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = SOURCE_ROOT; }; 63BFB9D11D2478DD00E17927 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = SOURCE_ROOT; }; 63BFB9D41D2478DD00E17927 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 63BFB9DB1D2478DD00E17927 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; BA96CBC1612BD2F70E66246C /* Pods-ConnectivityTestingApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ConnectivityTestingApp.release.xcconfig"; path = "Pods/Target Support Files/Pods-ConnectivityTestingApp/Pods-ConnectivityTestingApp.release.xcconfig"; sourceTree = ""; }; C2AF815D8242A2172891621D /* libPods-ConnectivityTestingApp.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ConnectivityTestingApp.a"; sourceTree = BUILT_PRODUCTS_DIR; }; FC9BD3AE427396EDB4CD13E3 /* Pods-ConnectivityTestingApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ConnectivityTestingApp.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ConnectivityTestingApp/Pods-ConnectivityTestingApp.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 63BFB9C41D2478DD00E17927 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 500A4E0AC9D489EB214D1ED4 /* libPods-ConnectivityTestingApp.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 16E6C67F2E48B42376DFFD2A /* Pods */ = { isa = PBXGroup; children = ( FC9BD3AE427396EDB4CD13E3 /* Pods-ConnectivityTestingApp.debug.xcconfig */, BA96CBC1612BD2F70E66246C /* Pods-ConnectivityTestingApp.release.xcconfig */, ); name = Pods; sourceTree = ""; }; 48F8EC18C66D3416A41F76F5 /* Frameworks */ = { isa = PBXGroup; children = ( C2AF815D8242A2172891621D /* libPods-ConnectivityTestingApp.a */, ); name = Frameworks; sourceTree = ""; }; 63BFB9BE1D2478DD00E17927 = { isa = PBXGroup; children = ( 63BFB9D11D2478DD00E17927 /* ViewController.m */, 63BFB9D31D2478DD00E17927 /* Main.storyboard */, 63BFB9DB1D2478DD00E17927 /* Info.plist */, 63BFB9CB1D2478DD00E17927 /* main.m */, 63BFB9C81D2478DD00E17927 /* Products */, 16E6C67F2E48B42376DFFD2A /* Pods */, 48F8EC18C66D3416A41F76F5 /* Frameworks */, ); sourceTree = ""; }; 63BFB9C81D2478DD00E17927 /* Products */ = { isa = PBXGroup; children = ( 63BFB9C71D2478DD00E17927 /* ConnectivityTestingApp.app */, ); name = Products; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 63BFB9C61D2478DD00E17927 /* ConnectivityTestingApp */ = { isa = PBXNativeTarget; buildConfigurationList = 63BFB9DE1D2478DD00E17927 /* Build configuration list for PBXNativeTarget "ConnectivityTestingApp" */; buildPhases = ( 4DCA2703A0AA5DC1BD2751B8 /* [CP] Check Pods Manifest.lock */, 63BFB9C31D2478DD00E17927 /* Sources */, 63BFB9C41D2478DD00E17927 /* Frameworks */, 63BFB9C51D2478DD00E17927 /* Resources */, 8593A2388A8F7BF5A7E98D26 /* [CP] Embed Pods Frameworks */, 5347BF6C41E7888C1C05CD88 /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( ); name = ConnectivityTestingApp; productName = ConnectivityTestingApp; productReference = 63BFB9C71D2478DD00E17927 /* ConnectivityTestingApp.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 63BFB9BF1D2478DD00E17927 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0800; ORGANIZATIONNAME = gRPC; TargetAttributes = { 63BFB9C61D2478DD00E17927 = { CreatedOnToolsVersion = 8.0; DevelopmentTeam = EQHXZ8M8AV; DevelopmentTeamName = "Google, Inc."; ProvisioningStyle = Automatic; }; }; }; buildConfigurationList = 63BFB9C21D2478DD00E17927 /* Build configuration list for PBXProject "ConnectivityTestingApp" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 63BFB9BE1D2478DD00E17927; productRefGroup = 63BFB9C81D2478DD00E17927 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 63BFB9C61D2478DD00E17927 /* ConnectivityTestingApp */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 63BFB9C51D2478DD00E17927 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 63BFB9D51D2478DD00E17927 /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 4DCA2703A0AA5DC1BD2751B8 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; 5347BF6C41E7888C1C05CD88 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ConnectivityTestingApp/Pods-ConnectivityTestingApp-resources.sh\"\n"; showEnvVarsInLog = 0; }; 8593A2388A8F7BF5A7E98D26 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ConnectivityTestingApp/Pods-ConnectivityTestingApp-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 63BFB9C31D2478DD00E17927 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 63BFB9D21D2478DD00E17927 /* ViewController.m in Sources */, 63BFB9CC1D2478DD00E17927 /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 63BFB9D31D2478DD00E17927 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 63BFB9D41D2478DD00E17927 /* Base */, ); name = Main.storyboard; path = .; sourceTree = SOURCE_ROOT; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 63BFB9DC1D2478DD00E17927 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; }; name = Debug; }; 63BFB9DD1D2478DD00E17927 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; }; name = Release; }; 63BFB9DF1D2478DD00E17927 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = FC9BD3AE427396EDB4CD13E3 /* Pods-ConnectivityTestingApp.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.ConnectivityTestingApp; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 63BFB9E01D2478DD00E17927 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = BA96CBC1612BD2F70E66246C /* Pods-ConnectivityTestingApp.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.ConnectivityTestingApp; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 63BFB9C21D2478DD00E17927 /* Build configuration list for PBXProject "ConnectivityTestingApp" */ = { isa = XCConfigurationList; buildConfigurations = ( 63BFB9DC1D2478DD00E17927 /* Debug */, 63BFB9DD1D2478DD00E17927 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 63BFB9DE1D2478DD00E17927 /* Build configuration list for PBXNativeTarget "ConnectivityTestingApp" */ = { isa = XCConfigurationList; buildConfigurations = ( 63BFB9DF1D2478DD00E17927 /* Debug */, 63BFB9E01D2478DD00E17927 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 63BFB9BF1D2478DD00E17927 /* Project object */; } grpc-1.3.2/src/objective-c/tests/Connectivity/ConnectivityTestingApp.xcodeproj/project.xcworkspace/000077500000000000000000000000001310511640000337075ustar00rootroot00000000000000contents.xcworkspacedata000066400000000000000000000002471310511640000405750ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/tests/Connectivity/ConnectivityTestingApp.xcodeproj/project.xcworkspace grpc-1.3.2/src/objective-c/tests/Connectivity/Info.plist000066400000000000000000000022551310511640000232140ustar00rootroot00000000000000 CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName Main UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight grpc-1.3.2/src/objective-c/tests/Connectivity/Podfile000066400000000000000000000024061310511640000225470ustar00rootroot00000000000000install! 'cocoapods', :deterministic_uuids => false platform :ios, '8.0' # Location of gRPC's repo root relative to this file. GRPC_LOCAL_SRC = '../../../..' target 'ConnectivityTestingApp' do pod 'gRPC', :path => GRPC_LOCAL_SRC pod 'gRPC-Core', :path => GRPC_LOCAL_SRC pod 'gRPC-ProtoRPC', :path => GRPC_LOCAL_SRC pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf" pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c" end pre_install do |installer| # This is the gRPC-Core podspec object, as initialized by its podspec file. grpc_core_spec = installer.pod_targets.find{|t| t.name == 'gRPC-Core'}.root_spec # Copied from gRPC-Core.podspec, except for the adjusted src_root: src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}" grpc_core_spec.pod_target_xcconfig = { 'GRPC_SRC_ROOT' => src_root, 'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"', 'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"', # If we don't set these two settings, `include/grpc/support/time.h` and # `src/core/lib/support/string.h` shadow the system `` and ``, breaking the # build. 'USE_HEADERMAP' => 'NO', 'ALWAYS_SEARCH_USER_PATHS' => 'NO', } end grpc-1.3.2/src/objective-c/tests/Connectivity/README.md000066400000000000000000000014631310511640000225230ustar00rootroot00000000000000This app can be used to manually test gRPC under changing network conditions. It makes RPCs in a loop, logging when the request is sent and the response is received. To test on the simulator, run `pod install`, open the workspace created by Cocoapods, and run the app. Once running, disable WiFi (or ethernet) _in your computer_, then enable it again after a while. Don't bother with the simulator's WiFi or cell settings, as they have no effect: Simulator apps are just Mac apps running within the simulator UI. The expected result is to never see a "hanged" RPC: success or failure should happen almost immediately after sending the request. Symptom of a hanged RPC is a log like the following being the last in your console: ``` 2016-06-29 16:51:29.443 ConnectivityTestingApp[73129:3567949] Sending request. ``` grpc-1.3.2/src/objective-c/tests/Connectivity/ViewController.m000066400000000000000000000061331310511640000243770ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import #import #import #import @interface ViewController : UIViewController @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; NSString *host = @"grpc-test.sandbox.googleapis.com"; GRPCProtoMethod *method = [[GRPCProtoMethod alloc] initWithPackage:@"grpc.testing" service:@"TestService" method:@"StreamingOutputCall"]; __block void (^startCall)() = ^{ GRXWriter *loggingRequestWriter = [[GRXWriter writerWithValue:[NSData data]] map:^id(id value) { NSLog(@"Sending request."); return value; }]; GRPCCall *call = [[GRPCCall alloc] initWithHost:host path:method.HTTPPath requestsWriter:loggingRequestWriter]; [call startWithWriteable:[GRXWriteable writeableWithEventHandler:^(BOOL done, id value, NSError *error) { if (!done) { return; } if (error) { NSLog(@"Finished with error %@", error); } else { NSLog(@"Finished successfully."); } dispatch_time_t oneSecond = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)); dispatch_after(oneSecond, dispatch_get_main_queue(), startCall); }]]; }; startCall(); } @end grpc-1.3.2/src/objective-c/tests/Connectivity/main.m000066400000000000000000000035451310511640000223510ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @end @implementation AppDelegate @end int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass(AppDelegate.class)); } } grpc-1.3.2/src/objective-c/tests/CoreCronetEnd2EndTests/000077500000000000000000000000001310511640000230105ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m000066400000000000000000000273121310511640000274210ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* * This test file is derived from fixture h2_ssl.c in core end2end test * (test/core/end2end/fixture/h2_ssl.c). The structure of the fixture is * preserved as much as possible * * This fixture creates a server full stack using chttp2 and a client * full stack using Cronet. End-to-end tests are run against this * configuration * */ #import #include "test/core/end2end/end2end_tests.h" #include #include #include #include #include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" #include "src/core/lib/support/tmpfile.h" #include "test/core/end2end/data/ssl_test_data.h" #include "test/core/util/port.h" #include "test/core/util/test_config.h" #import #include typedef struct fullstack_secure_fixture_data { char *localaddr; } fullstack_secure_fixture_data; static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack( grpc_channel_args *client_args, grpc_channel_args *server_args) { grpc_end2end_test_fixture f; int port = grpc_pick_unused_port_or_die(); fullstack_secure_fixture_data *ffd = gpr_malloc(sizeof(fullstack_secure_fixture_data)); memset(&f, 0, sizeof(f)); gpr_join_host_port(&ffd->localaddr, "127.0.0.1", port); f.fixture_data = ffd; f.cq = grpc_completion_queue_create(NULL); return f; } static void process_auth_failure(void *state, grpc_auth_context *ctx, const grpc_metadata *md, size_t md_count, grpc_process_auth_metadata_done_cb cb, void *user_data) { GPR_ASSERT(state == NULL); cb(user_data, NULL, 0, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL); } static void cronet_init_client_secure_fullstack(grpc_end2end_test_fixture *f, grpc_channel_args *client_args, stream_engine *cronetEngine) { fullstack_secure_fixture_data *ffd = f->fixture_data; f->client = grpc_cronet_secure_channel_create(cronetEngine, ffd->localaddr, client_args, NULL); GPR_ASSERT(f->client != NULL); } static void chttp2_init_server_secure_fullstack( grpc_end2end_test_fixture *f, grpc_channel_args *server_args, grpc_server_credentials *server_creds) { fullstack_secure_fixture_data *ffd = f->fixture_data; if (f->server) { grpc_server_destroy(f->server); } f->server = grpc_server_create(server_args, NULL); grpc_server_register_completion_queue(f->server, f->cq, NULL); GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr, server_creds)); grpc_server_credentials_release(server_creds); grpc_server_start(f->server); } static void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) { fullstack_secure_fixture_data *ffd = f->fixture_data; gpr_free(ffd->localaddr); gpr_free(ffd); } static void cronet_init_client_simple_ssl_secure_fullstack( grpc_end2end_test_fixture *f, grpc_channel_args *client_args) { grpc_exec_ctx ctx = GRPC_EXEC_CTX_INIT; stream_engine *cronetEngine = [Cronet getGlobalEngine]; grpc_channel_args *new_client_args = grpc_channel_args_copy(client_args); cronet_init_client_secure_fullstack(f, new_client_args, cronetEngine); grpc_channel_args_destroy(&ctx, new_client_args); grpc_exec_ctx_finish(&ctx); } static int fail_server_auth_check(grpc_channel_args *server_args) { size_t i; if (server_args == NULL) return 0; for (i = 0; i < server_args->num_args; i++) { if (strcmp(server_args->args[i].key, FAIL_AUTH_CHECK_SERVER_ARG_NAME) == 0) { return 1; } } return 0; } static void chttp2_init_server_simple_ssl_secure_fullstack( grpc_end2end_test_fixture *f, grpc_channel_args *server_args) { grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key, test_server1_cert}; grpc_server_credentials *ssl_creds = grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL); if (fail_server_auth_check(server_args)) { grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL}; grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor); } chttp2_init_server_secure_fullstack(f, server_args, ssl_creds); } /* All test configurations */ static grpc_end2end_test_config configs[] = { {"chttp2/simple_ssl_fullstack", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS, chttp2_create_fixture_secure_fullstack, cronet_init_client_simple_ssl_secure_fullstack, chttp2_init_server_simple_ssl_secure_fullstack, chttp2_tear_down_secure_fullstack}, }; static char *roots_filename; @interface CoreCronetEnd2EndTests : XCTestCase @end @implementation CoreCronetEnd2EndTests // The setUp() function is run before the test cases run and only run once + (void)setUp { [super setUp]; FILE *roots_file; size_t roots_size = strlen(test_root_cert); char *argv[] = {"CoreCronetEnd2EndTests"}; grpc_test_init(1, argv); grpc_end2end_tests_pre_init(); /* Set the SSL roots env var. */ roots_file = gpr_tmpfile("chttp2_simple_ssl_fullstack_test", &roots_filename); GPR_ASSERT(roots_filename != NULL); GPR_ASSERT(roots_file != NULL); GPR_ASSERT(fwrite(test_root_cert, 1, roots_size, roots_file) == roots_size); fclose(roots_file); gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_filename); grpc_init(); [Cronet setHttp2Enabled:YES]; [Cronet enableTestCertVerifierForTesting]; NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; NSLog(@"Documents directory: %@", url); [Cronet start]; [Cronet startNetLogToFile:@"cronet_netlog.json" logBytes:YES]; } // The tearDown() function is run after all test cases finish running + (void)tearDown { grpc_shutdown(); /* Cleanup. */ remove(roots_filename); gpr_free(roots_filename); [super tearDown]; } - (void)testIndividualCase:(char *)test_case { char *argv[] = {"h2_ssl", test_case}; for (int i = 0; i < sizeof(configs) / sizeof(*configs); i++) { grpc_end2end_tests(sizeof(argv) / sizeof(argv[0]), argv, configs[i]); } } // TODO(mxyan): Use NSStringFromSelector(_cmd) to acquire test name from the // test case method name, so that bodies of test cases can stay identical - (void)testAuthorityNotSupported { [self testIndividualCase:"authority_not_supported"]; } - (void)testBadHostname { [self testIndividualCase:"bad_hostname"]; } - (void)testBinaryMetadata { // NOT SUPPORTED //[self testIndividualCase:"binary_metadata"]; } - (void)testCallCreds { // NOT SUPPORTED // [self testIndividualCase:"call_creds"]; } - (void)testCancelAfterAccept { [self testIndividualCase:"cancel_after_accept"]; } - (void)testCancelAfterClientDone { [self testIndividualCase:"cancel_after_client_done"]; } - (void)testCancelAfterInvoke { [self testIndividualCase:"cancel_after_invoke"]; } - (void)testCancelBeforeInvoke { [self testIndividualCase:"cancel_before_invoke"]; } - (void)testCancelInAVacuum { [self testIndividualCase:"cancel_in_a_vacuum"]; } - (void)testCancelWithStatus { [self testIndividualCase:"cancel_with_status"]; } - (void)testCompressedPayload { [self testIndividualCase:"compressed_payload"]; } - (void)testConnectivity { // NOT SUPPORTED // [self testIndividualCase:"connectivity"]; } - (void)testDefaultHost { [self testIndividualCase:"default_host"]; } - (void)testDisappearingServer { [self testIndividualCase:"disappearing_server"]; } - (void)testEmptyBatch { [self testIndividualCase:"empty_batch"]; } - (void)testFilterCausesClose { // NOT SUPPORTED // [self testIndividualCase:"filter_causes_close"]; } - (void)testGracefulServerShutdown { [self testIndividualCase:"graceful_server_shutdown"]; } - (void)testHighInitialSeqno { [self testIndividualCase:"high_initial_seqno"]; } - (void)testHpackSize { // NOT SUPPORTED // [self testIndividualCase:"hpack_size"]; } - (void)testIdempotentRequest { // NOT SUPPORTED // [self testIndividualCase:"idempotent_request"]; } - (void)testInvokeLargeRequest { // NOT SUPPORTED (frame size) // [self testIndividualCase:"invoke_large_request"]; } - (void)testLargeMetadata { // NOT SUPPORTED // [self testIndividualCase:"large_metadata"]; } - (void)testMaxConcurrentStreams { [self testIndividualCase:"max_concurrent_streams"]; } - (void)testMaxMessageLength { // NOT SUPPORTED (close_error) // [self testIndividualCase:"max_message_length"]; } - (void)testNegativeDeadline { [self testIndividualCase:"negative_deadline"]; } - (void)testNetworkStatusChange { [self testIndividualCase:"network_status_change"]; } - (void)testNoOp { [self testIndividualCase:"no_op"]; } - (void)testPayload { [self testIndividualCase:"payload"]; } - (void)testPing { // NOT SUPPORTED // [self testIndividualCase:"ping"]; } - (void)testPingPongStreaming { [self testIndividualCase:"ping_pong_streaming"]; } - (void)testRegisteredCall { [self testIndividualCase:"registered_call"]; } - (void)testRequestWithFlags { // NOT SUPPORTED // [self testIndividualCase:"request_with_flags"]; } - (void)testRequestWithPayload { [self testIndividualCase:"request_with_payload"]; } - (void)testServerFinishesRequest { [self testIndividualCase:"server_finishes_request"]; } - (void)testShutdownFinishesCalls { [self testIndividualCase:"shutdown_finishes_calls"]; } - (void)testShutdownFinishesTags { [self testIndividualCase:"shutdown_finishes_tags"]; } - (void)testSimpleDelayedRequest { [self testIndividualCase:"simple_delayed_request"]; } - (void)testSimpleMetadata { [self testIndividualCase:"simple_metadata"]; } - (void)testSimpleRequest { [self testIndividualCase:"simple_request"]; } - (void)testStreamingErrorResponse { [self testIndividualCase:"streaming_error_response"]; } - (void)testTrailingMetadata { [self testIndividualCase:"trailing_metadata"]; } @end grpc-1.3.2/src/objective-c/tests/CoreCronetEnd2EndTests/Info.plist000066400000000000000000000013471310511640000247650ustar00rootroot00000000000000 CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier gRPC.$(PRODUCT_NAME:rfc1034identifier) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 grpc-1.3.2/src/objective-c/tests/CronetUnitTests/000077500000000000000000000000001310511640000216775ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m000066400000000000000000000354401310511640000252000ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import #import #import #import #import #import #import "test/core/end2end/cq_verifier.h" #import "test/core/util/port.h" #import #import #import "src/core/lib/channel/channel_args.h" #import "src/core/lib/support/env.h" #import "src/core/lib/support/string.h" #import "src/core/lib/support/tmpfile.h" #import "test/core/end2end/data/ssl_test_data.h" #import "test/core/util/test_config.h" #import static void drain_cq(grpc_completion_queue *cq) { grpc_event ev; do { ev = grpc_completion_queue_next(cq, grpc_timeout_seconds_to_deadline(5), NULL); } while (ev.type != GRPC_QUEUE_SHUTDOWN); } @interface CronetUnitTests : XCTestCase @end @implementation CronetUnitTests + (void)setUp { [super setUp]; char *argv[] = {"CoreCronetEnd2EndTests"}; grpc_test_init(1, argv); grpc_init(); [Cronet setHttp2Enabled:YES]; [Cronet setSslKeyLogFileName:@"Documents/key"]; [Cronet enableTestCertVerifierForTesting]; NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; NSLog(@"Documents directory: %@", url); [Cronet start]; [Cronet startNetLogToFile:@"Documents/cronet_netlog.json" logBytes:YES]; init_ssl(); } + (void)tearDown { grpc_shutdown(); cleanup_ssl(); [super tearDown]; } void init_ssl(void) { SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); } void cleanup_ssl(void) { EVP_cleanup(); } int alpn_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { // Always select "h2" as the ALPN protocol to be used *out = (const unsigned char *)"h2"; *outlen = 2; return SSL_TLSEXT_ERR_OK; } void init_ctx(SSL_CTX *ctx) { // Install server certificate BIO *pem = BIO_new_mem_buf((void *)test_server1_cert, (int)strlen(test_server1_cert)); X509 *cert = PEM_read_bio_X509_AUX(pem, NULL, NULL, ""); SSL_CTX_use_certificate(ctx, cert); X509_free(cert); BIO_free(pem); // Install server private key pem = BIO_new_mem_buf((void *)test_server1_key, (int)strlen(test_server1_key)); EVP_PKEY *key = PEM_read_bio_PrivateKey(pem, NULL, NULL, ""); SSL_CTX_use_PrivateKey(ctx, key); EVP_PKEY_free(key); BIO_free(pem); // Select cipher suite SSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES128-GCM-SHA256"); // Select ALPN protocol SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, NULL); } unsigned int parse_h2_length(const char *field) { return ((unsigned int)(unsigned char)(field[0])) * 65536 + ((unsigned int)(unsigned char)(field[1])) * 256 + ((unsigned int)(unsigned char)(field[2])); } - (void)testInternalError { grpc_call *c; grpc_slice request_payload_slice = grpc_slice_from_copied_string("hello world"); grpc_byte_buffer *request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"), grpc_slice_from_static_string("val1"), 0, {{NULL, NULL, NULL, NULL}}}, {grpc_slice_from_static_string("key2"), grpc_slice_from_static_string("val2"), 0, {{NULL, NULL, NULL, NULL}}}}; int port = grpc_pick_unused_port_or_die(); char *addr; gpr_join_host_port(&addr, "127.0.0.1", port); grpc_completion_queue *cq = grpc_completion_queue_create(NULL); stream_engine *cronetEngine = [Cronet getGlobalEngine]; grpc_channel *client = grpc_cronet_secure_channel_create(cronetEngine, addr, NULL, NULL); cq_verifier *cqv = cq_verifier_create(cq); grpc_op ops[6]; grpc_op *op; grpc_metadata_array initial_metadata_recv; grpc_metadata_array trailing_metadata_recv; grpc_metadata_array request_metadata_recv; grpc_byte_buffer *response_payload_recv = NULL; grpc_call_details call_details; grpc_status_code status; grpc_call_error error; grpc_slice details; c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, cq, grpc_slice_from_static_string("/foo"), NULL, deadline, NULL); GPR_ASSERT(c); grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&trailing_metadata_recv); grpc_metadata_array_init(&request_metadata_recv); grpc_call_details_init(&call_details); int sl = socket(AF_INET, SOCK_STREAM, 0); GPR_ASSERT(sl >= 0); // Make an TCP endpoint to accept the connection struct sockaddr_in s_addr; memset(&s_addr, 0, sizeof(s_addr)); s_addr.sin_family = AF_INET; s_addr.sin_addr.s_addr = htonl(INADDR_ANY); s_addr.sin_port = htons(port); GPR_ASSERT(0 == bind(sl, (struct sockaddr *)&s_addr, sizeof(s_addr))); GPR_ASSERT(0 == listen(sl, 5)); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 2; op->data.send_initial_metadata.metadata = meta_c; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message.send_message = request_payload; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_INITIAL_METADATA; op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_MESSAGE; op->data.recv_message.recv_message = &response_payload_recv; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; op->data.recv_status_on_client.status = &status; op->data.recv_status_on_client.status_details = &details; op->flags = 0; op->reserved = NULL; op++; error = grpc_call_start_batch(c, ops, (size_t)(op - ops), (void *)1, NULL); GPR_ASSERT(GRPC_CALL_OK == error); dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ int s = accept(sl, NULL, NULL); GPR_ASSERT(s >= 0); // Close the connection after 1 second to trigger Cronet's on_failed() sleep(1); close(s); close(sl); }); CQ_EXPECT_COMPLETION(cqv, (void *)1, 1); cq_verify(cqv); GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); grpc_slice_unref(details); grpc_metadata_array_destroy(&initial_metadata_recv); grpc_metadata_array_destroy(&trailing_metadata_recv); grpc_metadata_array_destroy(&request_metadata_recv); grpc_call_details_destroy(&call_details); grpc_call_destroy(c); cq_verifier_destroy(cqv); grpc_byte_buffer_destroy(request_payload); grpc_byte_buffer_destroy(response_payload_recv); grpc_channel_destroy(client); grpc_completion_queue_shutdown(cq); drain_cq(cq); grpc_completion_queue_destroy(cq); } - (void)packetCoalescing:(BOOL)useCoalescing { grpc_arg arg; arg.key = GRPC_ARG_USE_CRONET_PACKET_COALESCING; arg.type = GRPC_ARG_INTEGER; arg.value.integer = useCoalescing ? 1 : 0; grpc_channel_args *args = grpc_channel_args_copy_and_add(NULL, &arg, 1); grpc_call *c; grpc_slice request_payload_slice = grpc_slice_from_copied_string("hello world"); grpc_byte_buffer *request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"), grpc_slice_from_static_string("val1"), 0, {{NULL, NULL, NULL, NULL}}}, {grpc_slice_from_static_string("key2"), grpc_slice_from_static_string("val2"), 0, {{NULL, NULL, NULL, NULL}}}}; int port = grpc_pick_unused_port_or_die(); char *addr; gpr_join_host_port(&addr, "127.0.0.1", port); grpc_completion_queue *cq = grpc_completion_queue_create(NULL); stream_engine *cronetEngine = [Cronet getGlobalEngine]; grpc_channel *client = grpc_cronet_secure_channel_create(cronetEngine, addr, args, NULL); cq_verifier *cqv = cq_verifier_create(cq); grpc_op ops[6]; grpc_op *op; grpc_metadata_array initial_metadata_recv; grpc_metadata_array trailing_metadata_recv; grpc_metadata_array request_metadata_recv; grpc_byte_buffer *response_payload_recv = NULL; grpc_call_details call_details; grpc_status_code status; grpc_call_error error; grpc_slice details; c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, cq, grpc_slice_from_static_string("/foo"), NULL, deadline, NULL); GPR_ASSERT(c); grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&trailing_metadata_recv); grpc_metadata_array_init(&request_metadata_recv); grpc_call_details_init(&call_details); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Coalescing"]; int sl = socket(AF_INET, SOCK_STREAM, 0); GPR_ASSERT(sl >= 0); struct sockaddr_in s_addr; memset(&s_addr, 0, sizeof(s_addr)); s_addr.sin_family = AF_INET; s_addr.sin_addr.s_addr = htonl(INADDR_ANY); s_addr.sin_port = htons(port); GPR_ASSERT(0 == bind(sl, (struct sockaddr *)&s_addr, sizeof(s_addr))); GPR_ASSERT(0 == listen(sl, 5)); dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ int s = accept(sl, NULL, NULL); GPR_ASSERT(s >= 0); struct timeval tv; tv.tv_sec = 2; tv.tv_usec = 0; setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); // Make an TLS endpoint to receive Cronet's transmission SSL_CTX *ctx = SSL_CTX_new(TLSv1_2_server_method()); init_ctx(ctx); SSL *ssl = SSL_new(ctx); SSL_set_fd(ssl, s); SSL_accept(ssl); const char magic[] = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"; char buf[4096]; long len; BOOL coalesced = NO; while ((len = SSL_read(ssl, buf, sizeof(buf))) > 0) { gpr_log(GPR_DEBUG, "Read len: %ld", len); // Analyze the HTTP/2 frames in the same TLS PDU to identify if // coalescing is successful unsigned int p = 0; while (p < len) { if (len - p >= 24 && 0 == memcmp(&buf[p], magic, 24)) { p += 24; continue; } if (buf[p + 3] == 0 && // Type is DATA parse_h2_length(&buf[p]) == 0x10 && // Length is correct (buf[p + 4] & 1) != 0 && // EOS bit is set 0 == memcmp("hello world", &buf[p + 14], 11)) { // Message is correct coalesced = YES; break; } p += (parse_h2_length(&buf[p]) + 9); } if (coalesced) { break; } } XCTAssert(coalesced == useCoalescing); SSL_free(ssl); SSL_CTX_free(ctx); close(s); close(sl); [expectation fulfill]; }); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 2; op->data.send_initial_metadata.metadata = meta_c; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message.send_message = request_payload; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_INITIAL_METADATA; op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_MESSAGE; op->data.recv_message.recv_message = &response_payload_recv; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; op->data.recv_status_on_client.status = &status; op->data.recv_status_on_client.status_details = &details; op->flags = 0; op->reserved = NULL; op++; error = grpc_call_start_batch(c, ops, (size_t)(op - ops), (void *)1, NULL); GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, (void *)1, 1); cq_verify(cqv); grpc_slice_unref(details); grpc_metadata_array_destroy(&initial_metadata_recv); grpc_metadata_array_destroy(&trailing_metadata_recv); grpc_metadata_array_destroy(&request_metadata_recv); grpc_call_details_destroy(&call_details); grpc_call_destroy(c); cq_verifier_destroy(cqv); grpc_byte_buffer_destroy(request_payload); grpc_byte_buffer_destroy(response_payload_recv); grpc_channel_destroy(client); grpc_completion_queue_shutdown(cq); drain_cq(cq); grpc_completion_queue_destroy(cq); [self waitForExpectationsWithTimeout:4 handler:nil]; } - (void)testPacketCoalescing { [self packetCoalescing:YES]; [self packetCoalescing:NO]; } @end grpc-1.3.2/src/objective-c/tests/CronetUnitTests/Info.plist000066400000000000000000000013351310511640000236510ustar00rootroot00000000000000 CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 grpc-1.3.2/src/objective-c/tests/GRPCClientTests.m000066400000000000000000000361311310511640000216610ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import #import #import #import #import #import #import #import #import #import #define TEST_TIMEOUT 16 static NSString * const kHostAddress = @"localhost:5050"; static NSString * const kPackage = @"grpc.testing"; static NSString * const kService = @"TestService"; static NSString * const kRemoteSSLHost = @"grpc-test.sandbox.googleapis.com"; static GRPCProtoMethod *kInexistentMethod; static GRPCProtoMethod *kEmptyCallMethod; static GRPCProtoMethod *kUnaryCallMethod; /** Observer class for testing that responseMetadata is KVO-compliant */ @interface PassthroughObserver : NSObject - (instancetype) initWithCallback:(void (^)(NSString*, id, NSDictionary*))callback NS_DESIGNATED_INITIALIZER; - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context; @end @implementation PassthroughObserver { void (^_callback)(NSString*, id, NSDictionary*); } - (instancetype)init { return [self initWithCallback:nil]; } - (instancetype)initWithCallback:(void (^)(NSString *, id, NSDictionary *))callback { if (!callback) { return nil; } if ((self = [super init])) { _callback = callback; } return self; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { _callback(keyPath, object, change); [object removeObserver:self forKeyPath:keyPath]; } @end # pragma mark Tests /** * A few tests similar to InteropTests, but which use the generic gRPC client (GRPCCall) rather than * a generated proto library on top of it. Its RPCs are sent to a local cleartext server. * * TODO(jcanizales): Run them also against a local SSL server and against a remote server. */ @interface GRPCClientTests : XCTestCase @end @implementation GRPCClientTests - (void)setUp { // Add a custom user agent prefix that will be used in test [GRPCCall setUserAgentPrefix:@"Foo" forHost:kHostAddress]; // Register test server as non-SSL. [GRPCCall useInsecureConnectionsForHost:kHostAddress]; // This method isn't implemented by the remote server. kInexistentMethod = [[GRPCProtoMethod alloc] initWithPackage:kPackage service:kService method:@"Inexistent"]; kEmptyCallMethod = [[GRPCProtoMethod alloc] initWithPackage:kPackage service:kService method:@"EmptyCall"]; kUnaryCallMethod = [[GRPCProtoMethod alloc] initWithPackage:kPackage service:kService method:@"UnaryCall"]; } - (void)testConnectionToRemoteServer { __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Server reachable."]; GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress path:kInexistentMethod.HTTPPath requestsWriter:[GRXWriter writerWithValue:[NSData data]]]; id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { XCTFail(@"Received unexpected response: %@", value); } completionHandler:^(NSError *errorOrNil) { XCTAssertNotNil(errorOrNil, @"Finished without error!"); XCTAssertEqual(errorOrNil.code, 12, @"Finished with unexpected error: %@", errorOrNil); [expectation fulfill]; }]; [call startWithWriteable:responsesWriteable]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testEmptyRPC { __weak XCTestExpectation *response = [self expectationWithDescription:@"Empty response received."]; __weak XCTestExpectation *completion = [self expectationWithDescription:@"Empty RPC completed."]; GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress path:kEmptyCallMethod.HTTPPath requestsWriter:[GRXWriter writerWithValue:[NSData data]]]; id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { XCTAssertNotNil(value, @"nil value received as response."); XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value); [response fulfill]; } completionHandler:^(NSError *errorOrNil) { XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil); [completion fulfill]; }]; [call startWithWriteable:responsesWriteable]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testSimpleProtoRPC { __weak XCTestExpectation *response = [self expectationWithDescription:@"Expected response."]; __weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."]; RMTSimpleRequest *request = [RMTSimpleRequest message]; request.responseSize = 100; request.fillUsername = YES; request.fillOauthScope = YES; GRXWriter *requestsWriter = [GRXWriter writerWithValue:[request data]]; GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress path:kUnaryCallMethod.HTTPPath requestsWriter:requestsWriter]; id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { XCTAssertNotNil(value, @"nil value received as response."); XCTAssertGreaterThan(value.length, 0, @"Empty response received."); RMTSimpleResponse *responseProto = [RMTSimpleResponse parseFromData:value error:NULL]; // We expect empty strings, not nil: XCTAssertNotNil(responseProto.username, @"Response's username is nil."); XCTAssertNotNil(responseProto.oauthScope, @"Response's OAuth scope is nil."); [response fulfill]; } completionHandler:^(NSError *errorOrNil) { XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil); [completion fulfill]; }]; [call startWithWriteable:responsesWriteable]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testMetadata { __weak XCTestExpectation *expectation = [self expectationWithDescription:@"RPC unauthorized."]; RMTSimpleRequest *request = [RMTSimpleRequest message]; request.fillUsername = YES; request.fillOauthScope = YES; GRXWriter *requestsWriter = [GRXWriter writerWithValue:[request data]]; GRPCCall *call = [[GRPCCall alloc] initWithHost:kRemoteSSLHost path:kUnaryCallMethod.HTTPPath requestsWriter:requestsWriter]; call.oauth2AccessToken = @"bogusToken"; id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { XCTFail(@"Received unexpected response: %@", value); } completionHandler:^(NSError *errorOrNil) { XCTAssertNotNil(errorOrNil, @"Finished without error!"); XCTAssertEqual(errorOrNil.code, 16, @"Finished with unexpected error: %@", errorOrNil); XCTAssertEqualObjects(call.responseHeaders, errorOrNil.userInfo[kGRPCHeadersKey], @"Headers in the NSError object and call object differ."); XCTAssertEqualObjects(call.responseTrailers, errorOrNil.userInfo[kGRPCTrailersKey], @"Trailers in the NSError object and call object differ."); NSString *challengeHeader = call.oauth2ChallengeHeader; XCTAssertGreaterThan(challengeHeader.length, 0, @"No challenge in response headers %@", call.responseHeaders); [expectation fulfill]; }]; [call startWithWriteable:responsesWriteable]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testResponseMetadataKVO { __weak XCTestExpectation *response = [self expectationWithDescription:@"Empty response received."]; __weak XCTestExpectation *completion = [self expectationWithDescription:@"Empty RPC completed."]; __weak XCTestExpectation *metadata = [self expectationWithDescription:@"Metadata changed."]; GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress path:kEmptyCallMethod.HTTPPath requestsWriter:[GRXWriter writerWithValue:[NSData data]]]; PassthroughObserver *observer = [[PassthroughObserver alloc] initWithCallback:^(NSString *keypath, id object, NSDictionary * change) { if ([keypath isEqual: @"responseHeaders"]) { [metadata fulfill]; } }]; [call addObserver:observer forKeyPath:@"responseHeaders" options:0 context:NULL]; id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { XCTAssertNotNil(value, @"nil value received as response."); XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value); [response fulfill]; } completionHandler:^(NSError *errorOrNil) { XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil); [completion fulfill]; }]; [call startWithWriteable:responsesWriteable]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testUserAgentPrefix { __weak XCTestExpectation *response = [self expectationWithDescription:@"Empty response received."]; __weak XCTestExpectation *completion = [self expectationWithDescription:@"Empty RPC completed."]; GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress path:kEmptyCallMethod.HTTPPath requestsWriter:[GRXWriter writerWithValue:[NSData data]]]; // Setting this special key in the header will cause the interop server to echo back the // user-agent value, which we confirm. call.requestHeaders[@"x-grpc-test-echo-useragent"] = @""; id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { XCTAssertNotNil(value, @"nil value received as response."); XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value); /* This test needs to be more clever in regards to changing the version of the core. XCTAssertEqualObjects(call.responseHeaders[@"x-grpc-test-echo-useragent"], @"Foo grpc-objc/0.13.0 grpc-c/0.14.0-dev (ios)", @"Did not receive expected user agent %@", call.responseHeaders[@"x-grpc-test-echo-useragent"]); */ [response fulfill]; } completionHandler:^(NSError *errorOrNil) { XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil); [completion fulfill]; }]; [call startWithWriteable:responsesWriteable]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } // TODO(makarandd): Move to a different file that contains only unit tests - (void)testExceptions { // Try to set parameters to nil for GRPCCall. This should cause an exception @try { (void)[[GRPCCall alloc] initWithHost:nil path:nil requestsWriter:nil]; XCTFail(@"Did not receive an exception when parameters are nil"); } @catch(NSException *theException) { NSLog(@"Received exception as expected: %@", theException.name); } // Set state to Finished by force GRXWriter *requestsWriter = [GRXWriter emptyWriter]; [requestsWriter finishWithError:nil]; @try { (void)[[GRPCCall alloc] initWithHost:kHostAddress path:kUnaryCallMethod.HTTPPath requestsWriter:requestsWriter]; XCTFail(@"Did not receive an exception when GRXWriter has incorrect state."); } @catch(NSException *theException) { NSLog(@"Received exception as expected: %@", theException.name); } } - (void)testIdempotentProtoRPC { __weak XCTestExpectation *response = [self expectationWithDescription:@"Expected response."]; __weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."]; RMTSimpleRequest *request = [RMTSimpleRequest message]; request.responseSize = 100; request.fillUsername = YES; request.fillOauthScope = YES; GRXWriter *requestsWriter = [GRXWriter writerWithValue:[request data]]; GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress path:kUnaryCallMethod.HTTPPath requestsWriter:requestsWriter]; [GRPCCall setCallSafety:GRPCCallSafetyIdempotentRequest host:kHostAddress path:kUnaryCallMethod.HTTPPath]; id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { XCTAssertNotNil(value, @"nil value received as response."); XCTAssertGreaterThan(value.length, 0, @"Empty response received."); RMTSimpleResponse *responseProto = [RMTSimpleResponse parseFromData:value error:NULL]; // We expect empty strings, not nil: XCTAssertNotNil(responseProto.username, @"Response's username is nil."); XCTAssertNotNil(responseProto.oauthScope, @"Response's OAuth scope is nil."); [response fulfill]; } completionHandler:^(NSError *errorOrNil) { XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil); [completion fulfill]; }]; [call startWithWriteable:responsesWriteable]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } @end grpc-1.3.2/src/objective-c/tests/Info.plist000066400000000000000000000013471310511640000205370ustar00rootroot00000000000000 CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier gRPC.$(PRODUCT_NAME:rfc1034identifier) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 grpc-1.3.2/src/objective-c/tests/InteropTests.h000066400000000000000000000045141310511640000214020ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import /** * Implements tests as described here: * https://github.com/grpc/grpc/blob/master/doc/interop-test-descriptions.md * * This is an abstract class that needs to be subclassed. See |+host|. */ @interface InteropTests : XCTestCase /** * Host to send the RPCs to. The base implementation returns nil, which would make all tests to * fail. * Override in a subclass to perform these tests against a specific address. */ + (NSString *)host; /** * Bytes of overhead of test proto responses due to encoding. This is used to excercise the behavior * when responses are just above or below the max response size. For some reason, the local and * remote servers enconde responses with different overhead (?), so this is defined per-subclass. */ - (int32_t)encodingOverhead; @end grpc-1.3.2/src/objective-c/tests/InteropTests.m000066400000000000000000000436301310511640000214110ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import "InteropTests.h" #include #import #import #import #import #import #import #import #import #import #import #import #import #import #define TEST_TIMEOUT 32 // Convenience constructors for the generated proto messages: @interface RMTStreamingOutputCallRequest (Constructors) + (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize requestedResponseSize:(NSNumber *)responseSize; @end @implementation RMTStreamingOutputCallRequest (Constructors) + (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize requestedResponseSize:(NSNumber *)responseSize { RMTStreamingOutputCallRequest *request = [self message]; RMTResponseParameters *parameters = [RMTResponseParameters message]; parameters.size = responseSize.intValue; [request.responseParametersArray addObject:parameters]; request.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedIntegerValue]; return request; } @end @interface RMTStreamingOutputCallResponse (Constructors) + (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize; @end @implementation RMTStreamingOutputCallResponse (Constructors) + (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize { RMTStreamingOutputCallResponse * response = [self message]; response.payload.type = RMTPayloadType_Compressable; response.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedIntegerValue]; return response; } @end #pragma mark Tests @implementation InteropTests { RMTTestService *_service; } + (NSString *)host { return nil; } // This number indicates how many bytes of overhead does Protocol Buffers encoding add onto the // message. The number varies as different message.proto is used on different servers. The actual // number for each interop server is overridden in corresponding derived test classes. - (int32_t)encodingOverhead { return 0; } + (void)setUp { #ifdef GRPC_COMPILE_WITH_CRONET // Cronet setup [Cronet setHttp2Enabled:YES]; [Cronet start]; [GRPCCall useCronetWithEngine:[Cronet getGlobalEngine]]; #endif } - (void)setUp { self.continueAfterFailure = NO; [GRPCCall resetHostSettings]; _service = self.class.host ? [RMTTestService serviceWithHost:self.class.host] : nil; } - (void)testEmptyUnaryRPC { XCTAssertNotNil(self.class.host); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyUnary"]; GPBEmpty *request = [GPBEmpty message]; [_service emptyCallWithRequest:request handler:^(GPBEmpty *response, NSError *error) { XCTAssertNil(error, @"Finished with unexpected error: %@", error); id expectedResponse = [GPBEmpty message]; XCTAssertEqualObjects(response, expectedResponse); [expectation fulfill]; }]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testLargeUnaryRPC { XCTAssertNotNil(self.class.host); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"LargeUnary"]; RMTSimpleRequest *request = [RMTSimpleRequest message]; request.responseType = RMTPayloadType_Compressable; request.responseSize = 314159; request.payload.body = [NSMutableData dataWithLength:271828]; [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) { XCTAssertNil(error, @"Finished with unexpected error: %@", error); RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message]; expectedResponse.payload.type = RMTPayloadType_Compressable; expectedResponse.payload.body = [NSMutableData dataWithLength:314159]; XCTAssertEqualObjects(response, expectedResponse); [expectation fulfill]; }]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testPacketCoalescing { XCTAssertNotNil(self.class.host); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"LargeUnary"]; RMTSimpleRequest *request = [RMTSimpleRequest message]; request.responseType = RMTPayloadType_Compressable; request.responseSize = 10; request.payload.body = [NSMutableData dataWithLength:10]; [GRPCCall enableOpBatchLog:YES]; [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) { XCTAssertNil(error, @"Finished with unexpected error: %@", error); RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message]; expectedResponse.payload.type = RMTPayloadType_Compressable; expectedResponse.payload.body = [NSMutableData dataWithLength:10]; XCTAssertEqualObjects(response, expectedResponse); // The test is a success if there is a batch of exactly 3 ops (SEND_INITIAL_METADATA, // SEND_MESSAGE, SEND_CLOSE_FROM_CLIENT). Without packet coalescing each batch of ops contains // only one op. NSArray *opBatches = [GRPCCall obtainAndCleanOpBatchLog]; const NSInteger kExpectedOpBatchSize = 3; for (NSObject *o in opBatches) { if ([o isKindOfClass:[NSArray class]]) { NSArray *batch = (NSArray *)o; if ([batch count] == kExpectedOpBatchSize) { [expectation fulfill]; break; } } } }]; [self waitForExpectationsWithTimeout:16 handler:nil]; [GRPCCall enableOpBatchLog:NO]; } - (void)test4MBResponsesAreAccepted { XCTAssertNotNil(self.class.host); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"MaxResponseSize"]; RMTSimpleRequest *request = [RMTSimpleRequest message]; const int32_t kPayloadSize = 4 * 1024 * 1024 - self.encodingOverhead; // 4MB - encoding overhead request.responseSize = kPayloadSize; [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) { XCTAssertNil(error, @"Finished with unexpected error: %@", error); XCTAssertEqual(response.payload.body.length, kPayloadSize); [expectation fulfill]; }]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testResponsesOverMaxSizeFailWithActionableMessage { XCTAssertNotNil(self.class.host); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ResponseOverMaxSize"]; RMTSimpleRequest *request = [RMTSimpleRequest message]; const int32_t kPayloadSize = 4 * 1024 * 1024 - self.encodingOverhead + 1; // 1B over max size request.responseSize = kPayloadSize; [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) { // TODO(jcanizales): Catch the error and rethrow it with an actionable message: // - Use +[GRPCCall setResponseSizeLimit:forHost:] to set a higher limit. // - If you're developing the server, consider using response streaming, or let clients filter // responses by setting a google.protobuf.FieldMask in the request: // https://github.com/google/protobuf/blob/master/src/google/protobuf/field_mask.proto XCTAssertEqualObjects(error.localizedDescription, @"Received message larger than max (4194305 vs. 4194304)"); [expectation fulfill]; }]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testResponsesOver4MBAreAcceptedIfOptedIn { XCTAssertNotNil(self.class.host); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"HigherResponseSizeLimit"]; RMTSimpleRequest *request = [RMTSimpleRequest message]; const size_t kPayloadSize = 5 * 1024 * 1024; // 5MB request.responseSize = kPayloadSize; [GRPCCall setResponseSizeLimit:6 * 1024 * 1024 forHost:self.class.host]; [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) { XCTAssertNil(error, @"Finished with unexpected error: %@", error); XCTAssertEqual(response.payload.body.length, kPayloadSize); [expectation fulfill]; }]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testClientStreamingRPC { XCTAssertNotNil(self.class.host); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ClientStreaming"]; RMTStreamingInputCallRequest *request1 = [RMTStreamingInputCallRequest message]; request1.payload.body = [NSMutableData dataWithLength:27182]; RMTStreamingInputCallRequest *request2 = [RMTStreamingInputCallRequest message]; request2.payload.body = [NSMutableData dataWithLength:8]; RMTStreamingInputCallRequest *request3 = [RMTStreamingInputCallRequest message]; request3.payload.body = [NSMutableData dataWithLength:1828]; RMTStreamingInputCallRequest *request4 = [RMTStreamingInputCallRequest message]; request4.payload.body = [NSMutableData dataWithLength:45904]; GRXWriter *writer = [GRXWriter writerWithContainer:@[request1, request2, request3, request4]]; [_service streamingInputCallWithRequestsWriter:writer handler:^(RMTStreamingInputCallResponse *response, NSError *error) { XCTAssertNil(error, @"Finished with unexpected error: %@", error); RMTStreamingInputCallResponse *expectedResponse = [RMTStreamingInputCallResponse message]; expectedResponse.aggregatedPayloadSize = 74922; XCTAssertEqualObjects(response, expectedResponse); [expectation fulfill]; }]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testServerStreamingRPC { XCTAssertNotNil(self.class.host); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ServerStreaming"]; NSArray *expectedSizes = @[@31415, @9, @2653, @58979]; RMTStreamingOutputCallRequest *request = [RMTStreamingOutputCallRequest message]; for (NSNumber *size in expectedSizes) { RMTResponseParameters *parameters = [RMTResponseParameters message]; parameters.size = [size intValue]; [request.responseParametersArray addObject:parameters]; } __block int index = 0; [_service streamingOutputCallWithRequest:request eventHandler:^(BOOL done, RMTStreamingOutputCallResponse *response, NSError *error){ XCTAssertNil(error, @"Finished with unexpected error: %@", error); XCTAssertTrue(done || response, @"Event handler called without an event."); if (response) { XCTAssertLessThan(index, 4, @"More than 4 responses received."); id expected = [RMTStreamingOutputCallResponse messageWithPayloadSize:expectedSizes[index]]; XCTAssertEqualObjects(response, expected); index += 1; } if (done) { XCTAssertEqual(index, 4, @"Received %i responses instead of 4.", index); [expectation fulfill]; } }]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testPingPongRPC { XCTAssertNotNil(self.class.host); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"PingPong"]; NSArray *requests = @[@27182, @8, @1828, @45904]; NSArray *responses = @[@31415, @9, @2653, @58979]; GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init]; __block int index = 0; id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] requestedResponseSize:responses[index]]; [requestsBuffer writeValue:request]; [_service fullDuplexCallWithRequestsWriter:requestsBuffer eventHandler:^(BOOL done, RMTStreamingOutputCallResponse *response, NSError *error) { XCTAssertNil(error, @"Finished with unexpected error: %@", error); XCTAssertTrue(done || response, @"Event handler called without an event."); if (response) { XCTAssertLessThan(index, 4, @"More than 4 responses received."); id expected = [RMTStreamingOutputCallResponse messageWithPayloadSize:responses[index]]; XCTAssertEqualObjects(response, expected); index += 1; if (index < 4) { id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] requestedResponseSize:responses[index]]; [requestsBuffer writeValue:request]; } else { [requestsBuffer writesFinishedWithError:nil]; } } if (done) { XCTAssertEqual(index, 4, @"Received %i responses instead of 4.", index); [expectation fulfill]; } }]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testEmptyStreamRPC { XCTAssertNotNil(self.class.host); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyStream"]; [_service fullDuplexCallWithRequestsWriter:[GRXWriter emptyWriter] eventHandler:^(BOOL done, RMTStreamingOutputCallResponse *response, NSError *error) { XCTAssertNil(error, @"Finished with unexpected error: %@", error); XCTAssert(done, @"Unexpected response: %@", response); [expectation fulfill]; }]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testCancelAfterBeginRPC { XCTAssertNotNil(self.class.host); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterBegin"]; // A buffered pipe to which we never write any value acts as a writer that just hangs. GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init]; GRPCProtoCall *call = [_service RPCToStreamingInputCallWithRequestsWriter:requestsBuffer handler:^(RMTStreamingInputCallResponse *response, NSError *error) { XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED); [expectation fulfill]; }]; XCTAssertEqual(call.state, GRXWriterStateNotStarted); [call start]; XCTAssertEqual(call.state, GRXWriterStateStarted); [call cancel]; XCTAssertEqual(call.state, GRXWriterStateFinished); [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testCancelAfterFirstResponseRPC { XCTAssertNotNil(self.class.host); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterFirstResponse"]; // A buffered pipe to which we write a single value but never close GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init]; __block BOOL receivedResponse = NO; id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:@21782 requestedResponseSize:@31415]; [requestsBuffer writeValue:request]; __block GRPCProtoCall *call = [_service RPCToFullDuplexCallWithRequestsWriter:requestsBuffer eventHandler:^(BOOL done, RMTStreamingOutputCallResponse *response, NSError *error) { if (receivedResponse) { XCTAssert(done, @"Unexpected extra response %@", response); XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED); [expectation fulfill]; } else { XCTAssertNil(error, @"Finished with unexpected error: %@", error); XCTAssertFalse(done, @"Finished without response"); XCTAssertNotNil(response); receivedResponse = YES; [call cancel]; } }]; [call start]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testRPCAfterClosingOpenConnections { XCTAssertNotNil(self.class.host); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"RPC after closing connection"]; GPBEmpty *request = [GPBEmpty message]; [_service emptyCallWithRequest:request handler:^(GPBEmpty *response, NSError *error) { XCTAssertNil(error, @"First RPC finished with unexpected error: %@", error); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" [GRPCCall closeOpenConnections]; #pragma clang diagnostic pop [_service emptyCallWithRequest:request handler:^(GPBEmpty *response, NSError *error) { XCTAssertNil(error, @"Second RPC finished with unexpected error: %@", error); [expectation fulfill]; }]; }]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } @end grpc-1.3.2/src/objective-c/tests/InteropTestsLocalCleartext.m000066400000000000000000000045551310511640000242430ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import #import "InteropTests.h" static NSString * const kLocalCleartextHost = @"localhost:5050"; // The Protocol Buffers encoding overhead of local interop server. Acquired // by experiment. Adjust this when server's proto file changes. static int32_t kLocalInteropServerOverhead = 10; /** Tests in InteropTests.m, sending the RPCs to a local cleartext server. */ @interface InteropTestsLocalCleartext : InteropTests @end @implementation InteropTestsLocalCleartext + (NSString *)host { return kLocalCleartextHost; } - (int32_t)encodingOverhead { return kLocalInteropServerOverhead; // bytes } - (void)setUp { [super setUp]; // Register test server as non-SSL. [GRPCCall useInsecureConnectionsForHost:kLocalCleartextHost]; } @end grpc-1.3.2/src/objective-c/tests/InteropTestsLocalSSL.m000066400000000000000000000056761310511640000227560ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import #import "InteropTests.h" static NSString * const kLocalSSLHost = @"localhost:5051"; // The Protocol Buffers encoding overhead of local interop server. Acquired // by experiment. Adjust this when server's proto file changes. static int32_t kLocalInteropServerOverhead = 10; /** Tests in InteropTests.m, sending the RPCs to a local SSL server. */ @interface InteropTestsLocalSSL : InteropTests @end @implementation InteropTestsLocalSSL + (NSString *)host { return kLocalSSLHost; } - (int32_t)encodingOverhead { return kLocalInteropServerOverhead; // bytes } - (void)setUp { [super setUp]; // Register test server certificates and name. NSBundle *bundle = [NSBundle bundleForClass:self.class]; NSString *certsPath = [bundle pathForResource:@"TestCertificates.bundle/test-certificates" ofType:@"pem"]; [GRPCCall useTestCertsPath:certsPath testName:@"foo.test.google.fr" forHost:kLocalSSLHost]; } - (void)testExceptions { // Try to set userAgentPrefix for host that is nil. This should cause // an exception. @try { [GRPCCall useTestCertsPath:nil testName:nil forHost:nil]; XCTFail(@"Did not receive an exception when parameters are nil"); } @catch(NSException *theException) { NSLog(@"Received exception as expected: %@", theException.name); } } @end grpc-1.3.2/src/objective-c/tests/InteropTestsRemote.m000066400000000000000000000043301310511640000225570ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import #import "InteropTests.h" static NSString * const kRemoteSSLHost = @"grpc-test.sandbox.googleapis.com"; // The Protocol Buffers encoding overhead of remote interop server. Acquired // by experiment. Adjust this when server's proto file changes. static int32_t kRemoteInteropServerOverhead = 12; /** Tests in InteropTests.m, sending the RPCs to a remote SSL server. */ @interface InteropTestsRemote : InteropTests @end @implementation InteropTestsRemote + (NSString *)host { return kRemoteSSLHost; } - (int32_t)encodingOverhead { return kRemoteInteropServerOverhead; // bytes } @end grpc-1.3.2/src/objective-c/tests/InteropTestsRemoteWithCronet/000077500000000000000000000000001310511640000244105ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/tests/InteropTestsRemoteWithCronet/Info.plist000066400000000000000000000013351310511640000263620ustar00rootroot00000000000000 CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 grpc-1.3.2/src/objective-c/tests/InteropTestsRemoteWithCronet/InteropTestsRemoteWithCronet.m000066400000000000000000000044561310511640000324250ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import #import #import #import "InteropTests.h" static NSString * const kRemoteSSLHost = @"grpc-test.sandbox.googleapis.com"; // The Protocol Buffers encoding overhead of remote interop server. Acquired // by experiment. Adjust this when server's proto file changes. static int32_t kRemoteInteropServerOverhead = 12; /** Tests in InteropTests.m, sending the RPCs to a remote SSL server. */ @interface InteropTestsRemoteWithCronet : InteropTests @end @implementation InteropTestsRemoteWithCronet + (NSString *)host { return kRemoteSSLHost; } - (int32_t)encodingOverhead { return kRemoteInteropServerOverhead; // bytes } @end grpc-1.3.2/src/objective-c/tests/Podfile000066400000000000000000000121431310511640000200700ustar00rootroot00000000000000source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' install! 'cocoapods', :deterministic_uuids => false # Location of gRPC's repo root relative to this file. GRPC_LOCAL_SRC = '../../..' # Install the dependencies in the main target plus all test targets. %w( Tests AllTests RxLibraryUnitTests InteropTestsRemote InteropTestsLocalSSL InteropTestsLocalCleartext InteropTestsRemoteWithCronet ).each do |target_name| target target_name do pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf", :inhibit_warnings => true pod '!ProtoCompiler', :path => "#{GRPC_LOCAL_SRC}/src/objective-c" pod '!ProtoCompiler-gRPCPlugin', :path => "#{GRPC_LOCAL_SRC}/src/objective-c" pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true pod 'gRPC', :path => GRPC_LOCAL_SRC pod 'gRPC-Core', :path => GRPC_LOCAL_SRC pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC pod 'gRPC-ProtoRPC', :path => GRPC_LOCAL_SRC pod 'RemoteTest', :path => "RemoteTestClient" if target_name == 'InteropTestsRemoteWithCronet' pod 'gRPC-Core/Cronet-Implementation', :path => GRPC_LOCAL_SRC pod 'CronetFramework', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c" end end end %w( CoreCronetEnd2EndTests CronetUnitTests ).each do |target_name| target target_name do pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true pod 'CronetFramework', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c" pod 'gRPC-Core', :path => GRPC_LOCAL_SRC pod 'gRPC-Core/Cronet-Interface', :path => GRPC_LOCAL_SRC pod 'gRPC-Core/Cronet-Implementation', :path => GRPC_LOCAL_SRC pod 'gRPC-Core/Tests', :path => GRPC_LOCAL_SRC end end # gRPC-Core.podspec needs to be modified to be successfully used for local development. A Podfile's # pre_install hook lets us do that. The block passed to it runs after the podspecs are downloaded # and before they are installed in the user project. # # This podspec searches for the gRPC core library headers under "$(PODS_ROOT)/gRPC-Core", where # Cocoapods normally places the downloaded sources. When doing local development of the libraries, # though, Cocoapods just takes the sources from whatever directory was specified using `:path`, and # doesn't copy them under $(PODS_ROOT). When using static libraries, one can sometimes rely on the # symbolic links to the pods headers that Cocoapods creates under "$(PODS_ROOT)/Headers". But those # aren't created when using dynamic frameworks. So our solution is to modify the podspec on the fly # to point at the local directory where the sources are. # # TODO(jcanizales): Send a PR to Cocoapods to get rid of this need. pre_install do |installer| # This is the gRPC-Core podspec object, as initialized by its podspec file. grpc_core_spec = installer.pod_targets.find{|t| t.name == 'gRPC-Core'}.root_spec # Copied from gRPC-Core.podspec, except for the adjusted src_root: src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}" grpc_core_spec.pod_target_xcconfig = { 'GRPC_SRC_ROOT' => src_root, 'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"', 'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"', # If we don't set these two settings, `include/grpc/support/time.h` and # `src/core/lib/support/string.h` shadow the system `` and ``, breaking the # build. 'USE_HEADERMAP' => 'NO', 'ALWAYS_SEARCH_USER_PATHS' => 'NO', } end post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['GCC_TREAT_WARNINGS_AS_ERRORS'] = 'YES' end # CocoaPods creates duplicated library targets of gRPC-Core when the test targets include # non-default subspecs of gRPC-Core. All of these library targets start with prefix 'gRPC-Core' # and require the same error suppresion. if target.name.start_with?('gRPC-Core') target.build_configurations.each do |config| # TODO(zyc): Remove this setting after the issue is resolved # GPR_UNREACHABLE_CODE causes "Control may reach end of non-void # function" warning config.build_settings['GCC_WARN_ABOUT_RETURN_TYPE'] = 'NO' config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_CRONET_WITH_PACKET_COALESCING=1' end end # Activate Cronet for the dedicated build configuration 'Cronet', which will be used solely by # the test target 'InteropTestsRemoteWithCronet' # Activate GRPCCall+InternalTests functions for the dedicated build configuration 'Test', which will # be used by all test targets using it. if target.name == 'gRPC' target.build_configurations.each do |config| if config.name == 'Cronet' config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_COMPILE_WITH_CRONET=1 GRPC_TEST_OBJC=1' elsif config.name == 'Test' config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_TEST_OBJC=1' end end end end end grpc-1.3.2/src/objective-c/tests/RemoteTestClient/000077500000000000000000000000001310511640000220145ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec000066400000000000000000000031531310511640000254700ustar00rootroot00000000000000Pod::Spec.new do |s| s.name = "RemoteTest" s.version = "0.0.1" s.license = "New BSD" s.authors = { 'gRPC contributors' => 'grpc-io@googlegroups.com' } s.homepage = "http://www.grpc.io/" s.summary = "RemoteTest example" s.source = { :git => 'https://github.com/grpc/grpc.git' } s.ios.deployment_target = '7.1' s.osx.deployment_target = '10.9' # Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients. s.dependency "!ProtoCompiler-gRPCPlugin" repo_root = '../../../..' bin_dir = "#{repo_root}/bins/$CONFIG" protoc = "#{bin_dir}/protobuf/protoc" well_known_types_dir = "#{repo_root}/third_party/protobuf/src" plugin = "#{bin_dir}/grpc_objective_c_plugin" s.prepare_command = <<-CMD #{protoc} \ --plugin=protoc-gen-grpc=#{plugin} \ --objc_out=. \ --grpc_out=. \ -I . \ -I #{well_known_types_dir} \ *.proto CMD s.subspec "Messages" do |ms| ms.source_files = "*.pbobjc.{h,m}" ms.header_mappings_dir = "." ms.requires_arc = false ms.dependency "Protobuf" end s.subspec "Services" do |ss| ss.source_files = "*.pbrpc.{h,m}" ss.header_mappings_dir = "." ss.requires_arc = true ss.dependency "gRPC-ProtoRPC" ss.dependency "#{s.name}/Messages" end s.pod_target_xcconfig = { # This is needed by all pods that depend on Protobuf: 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1', # This is needed by all pods that depend on gRPC-RxLibrary: 'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES', } end grpc-1.3.2/src/objective-c/tests/RemoteTestClient/messages.proto000066400000000000000000000106631310511640000247160ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Message definitions to be used by integration test service definitions. syntax = "proto3"; package grpc.testing; option objc_class_prefix = "RMT"; // The type of payload that should be returned. enum PayloadType { // Compressable text format. COMPRESSABLE = 0; // Uncompressable binary format. UNCOMPRESSABLE = 1; // Randomly chosen from all other formats defined in this enum. RANDOM = 2; } // A block of data, to simply increase gRPC message size. message Payload { // The type of data in body. PayloadType type = 1; // Primary contents of payload. bytes body = 2; } // Unary request. message SimpleRequest { // Desired payload type in the response from the server. // If response_type is RANDOM, server randomly chooses one from other formats. PayloadType response_type = 1; // Desired payload size in the response from the server. // If response_type is COMPRESSABLE, this denotes the size before compression. int32 response_size = 2; // Optional input payload sent along with the request. Payload payload = 3; // Whether SimpleResponse should include username. bool fill_username = 4; // Whether SimpleResponse should include OAuth scope. bool fill_oauth_scope = 5; } // Unary response, as configured by the request. message SimpleResponse { // Payload to increase message size. Payload payload = 1; // The user the request came from, for verifying authentication was // successful when the client expected it. string username = 2; // OAuth scope. string oauth_scope = 3; } // Client-streaming request. message StreamingInputCallRequest { // Optional input payload sent along with the request. Payload payload = 1; // Not expecting any payload from the response. } // Client-streaming response. message StreamingInputCallResponse { // Aggregated size of payloads received from the client. int32 aggregated_payload_size = 1; } // Configuration for a particular response. message ResponseParameters { // Desired payload sizes in responses from the server. // If response_type is COMPRESSABLE, this denotes the size before compression. int32 size = 1; // Desired interval between consecutive responses in the response stream in // microseconds. int32 interval_us = 2; } // Server-streaming request. message StreamingOutputCallRequest { // Desired payload type in the response from the server. // If response_type is RANDOM, the payload from each response in the stream // might be of different types. This is to simulate a mixed type of payload // stream. PayloadType response_type = 1; // Configuration for each expected response message. repeated ResponseParameters response_parameters = 2; // Optional input payload sent along with the request. Payload payload = 3; } // Server-streaming response, as configured by the request and parameters. message StreamingOutputCallResponse { // Payload to increase response size. Payload payload = 1; } grpc-1.3.2/src/objective-c/tests/RemoteTestClient/test.proto000066400000000000000000000064371310511640000240720ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // An integration test service that covers all the method signature permutations // of unary/streaming requests/responses. syntax = "proto3"; import "google/protobuf/empty.proto"; import "messages.proto"; package grpc.testing; option objc_class_prefix = "RMT"; // A simple service to test the various types of RPCs and experiment with // performance with various types of payload. service TestService { // One empty request followed by one empty response. rpc EmptyCall(google.protobuf.Empty) returns (google.protobuf.Empty); // One request followed by one response. rpc UnaryCall(SimpleRequest) returns (SimpleResponse); // One request followed by a sequence of responses (streamed download). // The server returns the payload with client desired type and sizes. rpc StreamingOutputCall(StreamingOutputCallRequest) returns (stream StreamingOutputCallResponse); // A sequence of requests followed by one response (streamed upload). // The server returns the aggregated size of client payload as the result. rpc StreamingInputCall(stream StreamingInputCallRequest) returns (StreamingInputCallResponse); // A sequence of requests with each request served by the server immediately. // As one request could lead to multiple responses, this interface // demonstrates the idea of full duplexing. rpc FullDuplexCall(stream StreamingOutputCallRequest) returns (stream StreamingOutputCallResponse); // A sequence of requests followed by a sequence of responses. // The server buffers all the client requests and then serves them in order. A // stream of responses are returned to the client when the server starts with // first request. rpc HalfDuplexCall(stream StreamingOutputCallRequest) returns (stream StreamingOutputCallResponse); } grpc-1.3.2/src/objective-c/tests/RxLibraryUnitTests.m000066400000000000000000000156531310511640000225530ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import #import #import #import #import // A mock of a GRXSingleValueHandler block that can be queried for how many times it was called and // what were the last values passed to it. // // TODO(jcanizales): Move this to a test util library, and add tests for it. @interface CapturingSingleValueHandler : NSObject @property (nonatomic, readonly) void (^block)(id value, NSError *errorOrNil); @property (nonatomic, readonly) NSUInteger timesCalled; @property (nonatomic, readonly) id value; @property (nonatomic, readonly) NSError *errorOrNil; + (instancetype)handler; @end @implementation CapturingSingleValueHandler + (instancetype)handler { return [[self alloc] init]; } - (GRXSingleHandler)block { return ^(id value, NSError *errorOrNil) { ++_timesCalled; _value = value; _errorOrNil = errorOrNil; }; } @end // TODO(jcanizales): Split into one file per tested class. @interface RxLibraryUnitTests : XCTestCase @end @implementation RxLibraryUnitTests #pragma mark Writeable - (void)testWriteableSingleHandlerIsCalledForValue { // Given: CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler]; id anyValue = @7; // If: id writeable = [GRXWriteable writeableWithSingleHandler:handler.block]; [writeable writeValue:anyValue]; [writeable writesFinishedWithError:nil]; // Then: XCTAssertEqual(handler.timesCalled, 1); XCTAssertEqualObjects(handler.value, anyValue); XCTAssertEqualObjects(handler.errorOrNil, nil); } - (void)testWriteableSingleHandlerIsCalledForError { // Given: CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler]; NSError *anyError = [NSError errorWithDomain:@"domain" code:7 userInfo:nil]; // If: id writeable = [GRXWriteable writeableWithSingleHandler:handler.block]; [writeable writesFinishedWithError:anyError]; // Then: XCTAssertEqual(handler.timesCalled, 1); XCTAssertEqualObjects(handler.value, nil); XCTAssertEqualObjects(handler.errorOrNil, anyError); } - (void)testWriteableSingleHandlerIsCalledOnlyOnce_ValueThenError { // Given: CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler]; id anyValue = @7; NSError *anyError = [NSError errorWithDomain:@"domain" code:7 userInfo:nil]; // If: id writeable = [GRXWriteable writeableWithSingleHandler:handler.block]; [writeable writeValue:anyValue]; [writeable writesFinishedWithError:anyError]; // Then: XCTAssertEqual(handler.timesCalled, 1); XCTAssertEqualObjects(handler.value, anyValue); XCTAssertEqualObjects(handler.errorOrNil, nil); } - (void)testWriteableSingleHandlerIsCalledOnlyOnce_ValueThenValue { // Given: CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler]; id anyValue = @7; // If: id writeable = [GRXWriteable writeableWithSingleHandler:handler.block]; [writeable writeValue:anyValue]; [writeable writeValue:anyValue]; [writeable writesFinishedWithError:nil]; // Then: XCTAssertEqual(handler.timesCalled, 1); XCTAssertEqualObjects(handler.value, anyValue); XCTAssertEqualObjects(handler.errorOrNil, nil); } - (void)testWriteableSingleHandlerFailsOnEmptyWriter { // Given: CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler]; // If: id writeable = [GRXWriteable writeableWithSingleHandler:handler.block]; [writeable writesFinishedWithError:nil]; // Then: XCTAssertEqual(handler.timesCalled, 1); XCTAssertEqualObjects(handler.value, nil); XCTAssertNotNil(handler.errorOrNil); } #pragma mark BufferedPipe - (void)testBufferedPipePropagatesValue { // Given: CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler]; id writeable = [GRXWriteable writeableWithSingleHandler:handler.block]; id anyValue = @7; // If: GRXBufferedPipe *pipe = [GRXBufferedPipe pipe]; [pipe startWithWriteable:writeable]; [pipe writeValue:anyValue]; // Then: XCTAssertEqual(handler.timesCalled, 1); XCTAssertEqualObjects(handler.value, anyValue); XCTAssertEqualObjects(handler.errorOrNil, nil); } - (void)testBufferedPipePropagatesError { // Given: CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler]; id writeable = [GRXWriteable writeableWithSingleHandler:handler.block]; NSError *anyError = [NSError errorWithDomain:@"domain" code:7 userInfo:nil]; // If: GRXBufferedPipe *pipe = [GRXBufferedPipe pipe]; [pipe startWithWriteable:writeable]; [pipe writesFinishedWithError:anyError]; // Then: XCTAssertEqual(handler.timesCalled, 1); XCTAssertEqualObjects(handler.value, nil); XCTAssertEqualObjects(handler.errorOrNil, anyError); } - (void)testBufferedPipeFinishWriteWhilePaused { // Given: CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler]; id writeable = [GRXWriteable writeableWithSingleHandler:handler.block]; id anyValue = @7; // If: GRXBufferedPipe *pipe = [GRXBufferedPipe pipe]; // Write something, then finish [pipe writeValue:anyValue]; [pipe writesFinishedWithError:nil]; // then start the writeable [pipe startWithWriteable:writeable]; // Then: XCTAssertEqual(handler.timesCalled, 1); XCTAssertEqualObjects(handler.value, anyValue); XCTAssertEqualObjects(handler.errorOrNil, nil); } @end grpc-1.3.2/src/objective-c/tests/TestCertificates.bundle/000077500000000000000000000000001310511640000232775ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/tests/TestCertificates.bundle/test-certificates.pem000066400000000000000000000015271310511640000274310ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIICSjCCAbOgAwIBAgIJAJHGGR4dGioHMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnRlc3RjYTAeFw0xNDExMTEyMjMxMjla Fw0yNDExMDgyMjMxMjlaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0 YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDzANBgNVBAMT BnRlc3RjYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwEDfBV5MYdlHVHJ7 +L4nxrZy7mBfAVXpOc5vMYztssUI7mL2/iYujiIXM+weZYNTEpLdjyJdu7R5gGUu g1jSVK/EPHfc74O7AyZU34PNIP4Sh33N+/A5YexrNgJlPY+E3GdVYi4ldWJjgkAd Qah2PH5ACLrIIC6tRka9hcaBlIECAwEAAaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNV HQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADgYEAHzC7jdYlzAVmddi/gdAeKPau sPBG/C2HCWqHzpCUHcKuvMzDVkY/MP2o6JIW2DBbY64bO/FceExhjcykgaYtCH/m oIU63+CFOTtR7otyQAWHqXa7q4SbCDlG7DyRFxqG0txPtGvy12lgldA2+RgcigQG Dfcog5wrJytaQ6UA0wE= -----END CERTIFICATE----- grpc-1.3.2/src/objective-c/tests/Tests.m000066400000000000000000000032021310511640000200370ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #import @interface Tests : NSObject @end @implementation Tests @end grpc-1.3.2/src/objective-c/tests/Tests.xcodeproj/000077500000000000000000000000001310511640000216605ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/tests/Tests.xcodeproj/project.pbxproj000066400000000000000000003016221310511640000247400ustar00rootroot00000000000000// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 06467F3A8D01EC493D12ADA2 /* libPods-CronetUnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C6134277D2EB8B380862A03F /* libPods-CronetUnitTests.a */; }; 09B76D9585ACE7403804D9DC /* libPods-InteropTestsRemoteWithCronet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9E9444C764F0FFF64A7EB58E /* libPods-InteropTestsRemoteWithCronet.a */; }; 0F9232F984C08643FD40C34F /* libPods-InteropTestsRemote.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DBE059B4AC7A51919467EEC0 /* libPods-InteropTestsRemote.a */; }; 16A9E77B6E336B3C0B9BA6E0 /* libPods-InteropTestsLocalSSL.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DBEDE45BDA60DF1E1C8950C0 /* libPods-InteropTestsLocalSSL.a */; }; 20DFDF829DD993A4A00D5662 /* libPods-RxLibraryUnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A58BE6DF1C62D1739EBB2C78 /* libPods-RxLibraryUnitTests.a */; }; 333E8FC01C8285B7C547D799 /* libPods-InteropTestsLocalCleartext.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FD346DB2C23F676C4842F3FF /* libPods-InteropTestsLocalCleartext.a */; }; 3D7C85F6AA68C4A205E3BA16 /* libPods-Tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 20DFF2F3C97EF098FE5A3171 /* libPods-Tests.a */; }; 5E8A5DA71D3840B4000F8BC4 /* CoreCronetEnd2EndTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E8A5DA61D3840B4000F8BC4 /* CoreCronetEnd2EndTests.m */; }; 5E8A5DA91D3840B4000F8BC4 /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; 5EAD6D271E27047400002378 /* CronetUnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EAD6D261E27047400002378 /* CronetUnitTests.m */; }; 5EAD6D291E27047400002378 /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; 5EE84BF41D4717E40050C6CC /* InteropTestsRemoteWithCronet.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EE84BF31D4717E40050C6CC /* InteropTestsRemoteWithCronet.m */; }; 5EE84BF61D4717E40050C6CC /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; 5EE84BFE1D471D400050C6CC /* InteropTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 635ED2EB1B1A3BC400FDE5C3 /* InteropTests.m */; }; 60D2A57ED559F34428C2EEC5 /* libPods-CoreCronetEnd2EndTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FBD98AC417B9882D32B19F28 /* libPods-CoreCronetEnd2EndTests.a */; }; 6312AE4E1B1BF49B00341DEE /* GRPCClientTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6312AE4D1B1BF49B00341DEE /* GRPCClientTests.m */; }; 63423F4A1B150A5F006CF63C /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; 635697CD1B14FC11007A7283 /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 635697CC1B14FC11007A7283 /* Tests.m */; }; 635ED2EC1B1A3BC400FDE5C3 /* InteropTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 635ED2EB1B1A3BC400FDE5C3 /* InteropTests.m */; }; 63715F561B780C020029CB0B /* InteropTestsLocalCleartext.m in Sources */ = {isa = PBXBuildFile; fileRef = 63715F551B780C020029CB0B /* InteropTestsLocalCleartext.m */; }; 6379CC4D1BE1662A001BC0A1 /* InteropTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 635ED2EB1B1A3BC400FDE5C3 /* InteropTests.m */; }; 6379CC4E1BE1662B001BC0A1 /* InteropTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 635ED2EB1B1A3BC400FDE5C3 /* InteropTests.m */; }; 6379CC501BE16703001BC0A1 /* InteropTestsRemote.m in Sources */ = {isa = PBXBuildFile; fileRef = 6379CC4F1BE16703001BC0A1 /* InteropTestsRemote.m */; }; 6379CC511BE1683B001BC0A1 /* InteropTestsRemote.m in Sources */ = {isa = PBXBuildFile; fileRef = 6379CC4F1BE16703001BC0A1 /* InteropTestsRemote.m */; }; 6379CC531BE17709001BC0A1 /* TestCertificates.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 63E240CF1B6C63DC005F3B0E /* TestCertificates.bundle */; }; 63DC84181BE15179000708E8 /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; 63DC841E1BE15180000708E8 /* RxLibraryUnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63423F501B151B77006CF63C /* RxLibraryUnitTests.m */; }; 63DC84281BE15267000708E8 /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; 63DC842E1BE15278000708E8 /* RxLibraryUnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63423F501B151B77006CF63C /* RxLibraryUnitTests.m */; }; 63DC842F1BE1527D000708E8 /* InteropTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 635ED2EB1B1A3BC400FDE5C3 /* InteropTests.m */; }; 63DC84391BE15294000708E8 /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; 63DC84481BE152B5000708E8 /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; 63DC844E1BE15350000708E8 /* InteropTestsLocalCleartext.m in Sources */ = {isa = PBXBuildFile; fileRef = 63715F551B780C020029CB0B /* InteropTestsLocalCleartext.m */; }; 63DC844F1BE15353000708E8 /* InteropTestsLocalSSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 63E240CD1B6C4E2B005F3B0E /* InteropTestsLocalSSL.m */; }; 63DC84501BE153AA000708E8 /* GRPCClientTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6312AE4D1B1BF49B00341DEE /* GRPCClientTests.m */; }; 63E240CE1B6C4E2B005F3B0E /* InteropTestsLocalSSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 63E240CD1B6C4E2B005F3B0E /* InteropTestsLocalSSL.m */; }; 63E240D01B6C63DC005F3B0E /* TestCertificates.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 63E240CF1B6C63DC005F3B0E /* TestCertificates.bundle */; }; F15EF7852DC70770EFDB1D2C /* libPods-AllTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CAE086D5B470DA367D415AB0 /* libPods-AllTests.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 5E8A5DAA1D3840B4000F8BC4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 635697BF1B14FC11007A7283 /* Project object */; proxyType = 1; remoteGlobalIDString = 635697C61B14FC11007A7283; remoteInfo = Tests; }; 5EAD6D2A1E27047400002378 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 635697BF1B14FC11007A7283 /* Project object */; proxyType = 1; remoteGlobalIDString = 635697C61B14FC11007A7283; remoteInfo = Tests; }; 5EE84BF71D4717E40050C6CC /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 635697BF1B14FC11007A7283 /* Project object */; proxyType = 1; remoteGlobalIDString = 635697C61B14FC11007A7283; remoteInfo = Tests; }; 63423F4B1B150A5F006CF63C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 635697BF1B14FC11007A7283 /* Project object */; proxyType = 1; remoteGlobalIDString = 635697C61B14FC11007A7283; remoteInfo = Tests; }; 63DC84191BE15179000708E8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 635697BF1B14FC11007A7283 /* Project object */; proxyType = 1; remoteGlobalIDString = 635697C61B14FC11007A7283; remoteInfo = Tests; }; 63DC84291BE15267000708E8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 635697BF1B14FC11007A7283 /* Project object */; proxyType = 1; remoteGlobalIDString = 635697C61B14FC11007A7283; remoteInfo = Tests; }; 63DC843A1BE15294000708E8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 635697BF1B14FC11007A7283 /* Project object */; proxyType = 1; remoteGlobalIDString = 635697C61B14FC11007A7283; remoteInfo = Tests; }; 63DC84491BE152B5000708E8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 635697BF1B14FC11007A7283 /* Project object */; proxyType = 1; remoteGlobalIDString = 635697C61B14FC11007A7283; remoteInfo = Tests; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ 635697C51B14FC11007A7283 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = "include/$(PRODUCT_NAME)"; dstSubfolderSpec = 16; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 02192CF1FF9534E3D18C65FC /* Pods-CronetUnitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CronetUnitTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-CronetUnitTests/Pods-CronetUnitTests.release.xcconfig"; sourceTree = ""; }; 060EF32D7EC0DF67ED617507 /* Pods-Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.debug.xcconfig"; sourceTree = ""; }; 07D10A965323BEA7FE59A74B /* Pods-RxLibraryUnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxLibraryUnitTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RxLibraryUnitTests/Pods-RxLibraryUnitTests.debug.xcconfig"; sourceTree = ""; }; 0A4F89D9C90E9C30990218F0 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; 0D2284C3DF7E57F0ED504E39 /* Pods-CoreCronetEnd2EndTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CoreCronetEnd2EndTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests.debug.xcconfig"; sourceTree = ""; }; 14B09A58FEE53A7A6B838920 /* Pods-InteropTestsLocalSSL.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSL.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL.cronet.xcconfig"; sourceTree = ""; }; 1588C85DEAF7FC0ACDEA4C02 /* Pods-InteropTestsLocalCleartext.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.test.xcconfig"; sourceTree = ""; }; 17F60BF2871F6AF85FB3FA12 /* Pods-InteropTestsRemoteWithCronet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.debug.xcconfig"; sourceTree = ""; }; 20DFF2F3C97EF098FE5A3171 /* libPods-Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 2B89F3037963E6EDDD48D8C3 /* Pods-InteropTestsRemoteWithCronet.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.test.xcconfig"; sourceTree = ""; }; 35F2B6BF3BAE8F0DC4AFD76E /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 386712AEACF7C2190C4B8B3F /* Pods-CronetUnitTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CronetUnitTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-CronetUnitTests/Pods-CronetUnitTests.cronet.xcconfig"; sourceTree = ""; }; 3B0861FC805389C52DB260D4 /* Pods-RxLibraryUnitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxLibraryUnitTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-RxLibraryUnitTests/Pods-RxLibraryUnitTests.release.xcconfig"; sourceTree = ""; }; 3F27B2E744482771EB93C394 /* Pods-InteropTestsRemoteWithCronet.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.cronet.xcconfig"; sourceTree = ""; }; 4AD97096D13D7416DC91A72A /* Pods-CoreCronetEnd2EndTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CoreCronetEnd2EndTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests.release.xcconfig"; sourceTree = ""; }; 4ADEA1C8BBE10D90940AC68E /* Pods-InteropTestsRemote.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemote.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote.cronet.xcconfig"; sourceTree = ""; }; 51A275E86C141416ED63FF76 /* Pods-InteropTestsLocalCleartext.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.release.xcconfig"; sourceTree = ""; }; 553BBBED24E4162D1F769D65 /* Pods-InteropTestsLocalSSL.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSL.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL.debug.xcconfig"; sourceTree = ""; }; 573450F334B331D0BED8B961 /* Pods-CoreCronetEnd2EndTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CoreCronetEnd2EndTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests.cronet.xcconfig"; sourceTree = ""; }; 5761E98978DDDF136A58CB7E /* Pods-AllTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.release.xcconfig"; sourceTree = ""; }; 5E8A5DA41D3840B4000F8BC4 /* CoreCronetEnd2EndTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreCronetEnd2EndTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 5E8A5DA61D3840B4000F8BC4 /* CoreCronetEnd2EndTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CoreCronetEnd2EndTests.m; sourceTree = ""; }; 5EAD6D241E27047400002378 /* CronetUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CronetUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 5EAD6D261E27047400002378 /* CronetUnitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CronetUnitTests.m; sourceTree = ""; }; 5EAD6D281E27047400002378 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 5EE84BF11D4717E40050C6CC /* InteropTestsRemoteWithCronet.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InteropTestsRemoteWithCronet.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 5EE84BF31D4717E40050C6CC /* InteropTestsRemoteWithCronet.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InteropTestsRemoteWithCronet.m; sourceTree = ""; }; 5EE84BF51D4717E40050C6CC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 6312AE4D1B1BF49B00341DEE /* GRPCClientTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GRPCClientTests.m; sourceTree = ""; }; 63423F441B150A5F006CF63C /* AllTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AllTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 63423F501B151B77006CF63C /* RxLibraryUnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RxLibraryUnitTests.m; sourceTree = ""; }; 635697C71B14FC11007A7283 /* libTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTests.a; sourceTree = BUILT_PRODUCTS_DIR; }; 635697CC1B14FC11007A7283 /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = ""; }; 635697D81B14FC11007A7283 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 635ED2EB1B1A3BC400FDE5C3 /* InteropTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InteropTests.m; sourceTree = ""; }; 63715F551B780C020029CB0B /* InteropTestsLocalCleartext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InteropTestsLocalCleartext.m; sourceTree = ""; }; 6379CC4F1BE16703001BC0A1 /* InteropTestsRemote.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InteropTestsRemote.m; sourceTree = ""; }; 63DC84131BE15179000708E8 /* RxLibraryUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RxLibraryUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 63DC84231BE15267000708E8 /* InteropTestsRemote.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InteropTestsRemote.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 63DC84341BE15294000708E8 /* InteropTestsLocalSSL.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InteropTestsLocalSSL.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 63DC84431BE152B5000708E8 /* InteropTestsLocalCleartext.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InteropTestsLocalCleartext.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 63E240CC1B6C4D3A005F3B0E /* InteropTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InteropTests.h; sourceTree = ""; }; 63E240CD1B6C4E2B005F3B0E /* InteropTestsLocalSSL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InteropTestsLocalSSL.m; sourceTree = ""; }; 63E240CF1B6C63DC005F3B0E /* TestCertificates.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = TestCertificates.bundle; sourceTree = ""; }; 64F68A9A6A63CC930DD30A6E /* Pods-CronetUnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CronetUnitTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-CronetUnitTests/Pods-CronetUnitTests.debug.xcconfig"; sourceTree = ""; }; 6793C9D019CB268C5BB491A2 /* Pods-CoreCronetEnd2EndTests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CoreCronetEnd2EndTests.test.xcconfig"; path = "Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests.test.xcconfig"; sourceTree = ""; }; 781089FAE980F51F88A3BE0B /* Pods-RxLibraryUnitTests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxLibraryUnitTests.test.xcconfig"; path = "Pods/Target Support Files/Pods-RxLibraryUnitTests/Pods-RxLibraryUnitTests.test.xcconfig"; sourceTree = ""; }; 79C68EFFCB5533475D810B79 /* Pods-RxLibraryUnitTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxLibraryUnitTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-RxLibraryUnitTests/Pods-RxLibraryUnitTests.cronet.xcconfig"; sourceTree = ""; }; 7A2E97E3F469CC2A758D77DE /* Pods-InteropTestsLocalSSL.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSL.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL.release.xcconfig"; sourceTree = ""; }; 9E9444C764F0FFF64A7EB58E /* libPods-InteropTestsRemoteWithCronet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsRemoteWithCronet.a"; sourceTree = BUILT_PRODUCTS_DIR; }; A0361771A855917162911180 /* Pods-Tests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.test.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.test.xcconfig"; sourceTree = ""; }; A58BE6DF1C62D1739EBB2C78 /* libPods-RxLibraryUnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RxLibraryUnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; A6F832FCEFA6F6881E620F12 /* Pods-InteropTestsRemote.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemote.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote.test.xcconfig"; sourceTree = ""; }; AA7CB64B4DD9915AE7C03163 /* Pods-InteropTestsLocalCleartext.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.cronet.xcconfig"; sourceTree = ""; }; AC414EF7A6BF76ED02B6E480 /* Pods-InteropTestsRemoteWithCronet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.release.xcconfig"; sourceTree = ""; }; B226619DC4E709E0FFFF94B8 /* Pods-CronetUnitTests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CronetUnitTests.test.xcconfig"; path = "Pods/Target Support Files/Pods-CronetUnitTests/Pods-CronetUnitTests.test.xcconfig"; sourceTree = ""; }; B94C27C06733CF98CE1B2757 /* Pods-AllTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.debug.xcconfig"; sourceTree = ""; }; C6134277D2EB8B380862A03F /* libPods-CronetUnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-CronetUnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; CAE086D5B470DA367D415AB0 /* libPods-AllTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AllTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; D13BEC8181B8E678A1B52F54 /* Pods-InteropTestsLocalSSL.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSL.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL.test.xcconfig"; sourceTree = ""; }; DB1F4391AF69D20D38D74B67 /* Pods-AllTests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.test.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.test.xcconfig"; sourceTree = ""; }; DBE059B4AC7A51919467EEC0 /* libPods-InteropTestsRemote.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsRemote.a"; sourceTree = BUILT_PRODUCTS_DIR; }; DBEDE45BDA60DF1E1C8950C0 /* libPods-InteropTestsLocalSSL.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsLocalSSL.a"; sourceTree = BUILT_PRODUCTS_DIR; }; DC3CA1D948F068E76957A861 /* Pods-InteropTestsRemote.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemote.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote.debug.xcconfig"; sourceTree = ""; }; E1486220285AF123EB124008 /* Pods-InteropTestsLocalCleartext.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.debug.xcconfig"; sourceTree = ""; }; E4275A759BDBDF143B9B438F /* Pods-InteropTestsRemote.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemote.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote.release.xcconfig"; sourceTree = ""; }; E6733B838B28453434B556E2 /* Pods-Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.release.xcconfig"; sourceTree = ""; }; E7E4D3FD76E3B745D992AF5F /* Pods-AllTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.cronet.xcconfig"; sourceTree = ""; }; F671D4CAD2864FB203B920B4 /* Pods-Tests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.cronet.xcconfig"; sourceTree = ""; }; FBD98AC417B9882D32B19F28 /* libPods-CoreCronetEnd2EndTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-CoreCronetEnd2EndTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; FD346DB2C23F676C4842F3FF /* libPods-InteropTestsLocalCleartext.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsLocalCleartext.a"; sourceTree = BUILT_PRODUCTS_DIR; }; FF7B5489BCFE40111D768DD0 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 5E8A5DA11D3840B4000F8BC4 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 5E8A5DA91D3840B4000F8BC4 /* libTests.a in Frameworks */, 60D2A57ED559F34428C2EEC5 /* libPods-CoreCronetEnd2EndTests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 5EAD6D211E27047400002378 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 5EAD6D291E27047400002378 /* libTests.a in Frameworks */, 06467F3A8D01EC493D12ADA2 /* libPods-CronetUnitTests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 5EE84BEE1D4717E40050C6CC /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 5EE84BF61D4717E40050C6CC /* libTests.a in Frameworks */, 09B76D9585ACE7403804D9DC /* libPods-InteropTestsRemoteWithCronet.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 63423F411B150A5F006CF63C /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 63423F4A1B150A5F006CF63C /* libTests.a in Frameworks */, F15EF7852DC70770EFDB1D2C /* libPods-AllTests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 635697C41B14FC11007A7283 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 3D7C85F6AA68C4A205E3BA16 /* libPods-Tests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 63DC84101BE15179000708E8 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 63DC84181BE15179000708E8 /* libTests.a in Frameworks */, 20DFDF829DD993A4A00D5662 /* libPods-RxLibraryUnitTests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 63DC84201BE15267000708E8 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 63DC84281BE15267000708E8 /* libTests.a in Frameworks */, 0F9232F984C08643FD40C34F /* libPods-InteropTestsRemote.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 63DC84311BE15294000708E8 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 63DC84391BE15294000708E8 /* libTests.a in Frameworks */, 16A9E77B6E336B3C0B9BA6E0 /* libPods-InteropTestsLocalSSL.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 63DC84401BE152B5000708E8 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 63DC84481BE152B5000708E8 /* libTests.a in Frameworks */, 333E8FC01C8285B7C547D799 /* libPods-InteropTestsLocalCleartext.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 136D535E19727099B941D7B1 /* Frameworks */ = { isa = PBXGroup; children = ( 35F2B6BF3BAE8F0DC4AFD76E /* libPods.a */, CAE086D5B470DA367D415AB0 /* libPods-AllTests.a */, FD346DB2C23F676C4842F3FF /* libPods-InteropTestsLocalCleartext.a */, DBEDE45BDA60DF1E1C8950C0 /* libPods-InteropTestsLocalSSL.a */, DBE059B4AC7A51919467EEC0 /* libPods-InteropTestsRemote.a */, A58BE6DF1C62D1739EBB2C78 /* libPods-RxLibraryUnitTests.a */, 20DFF2F3C97EF098FE5A3171 /* libPods-Tests.a */, FBD98AC417B9882D32B19F28 /* libPods-CoreCronetEnd2EndTests.a */, 9E9444C764F0FFF64A7EB58E /* libPods-InteropTestsRemoteWithCronet.a */, C6134277D2EB8B380862A03F /* libPods-CronetUnitTests.a */, ); name = Frameworks; sourceTree = ""; }; 51E4650F34F854F41FF053B3 /* Pods */ = { isa = PBXGroup; children = ( FF7B5489BCFE40111D768DD0 /* Pods.debug.xcconfig */, 0A4F89D9C90E9C30990218F0 /* Pods.release.xcconfig */, B94C27C06733CF98CE1B2757 /* Pods-AllTests.debug.xcconfig */, 5761E98978DDDF136A58CB7E /* Pods-AllTests.release.xcconfig */, E1486220285AF123EB124008 /* Pods-InteropTestsLocalCleartext.debug.xcconfig */, 51A275E86C141416ED63FF76 /* Pods-InteropTestsLocalCleartext.release.xcconfig */, 553BBBED24E4162D1F769D65 /* Pods-InteropTestsLocalSSL.debug.xcconfig */, 7A2E97E3F469CC2A758D77DE /* Pods-InteropTestsLocalSSL.release.xcconfig */, DC3CA1D948F068E76957A861 /* Pods-InteropTestsRemote.debug.xcconfig */, E4275A759BDBDF143B9B438F /* Pods-InteropTestsRemote.release.xcconfig */, 07D10A965323BEA7FE59A74B /* Pods-RxLibraryUnitTests.debug.xcconfig */, 3B0861FC805389C52DB260D4 /* Pods-RxLibraryUnitTests.release.xcconfig */, 060EF32D7EC0DF67ED617507 /* Pods-Tests.debug.xcconfig */, E6733B838B28453434B556E2 /* Pods-Tests.release.xcconfig */, 0D2284C3DF7E57F0ED504E39 /* Pods-CoreCronetEnd2EndTests.debug.xcconfig */, 4AD97096D13D7416DC91A72A /* Pods-CoreCronetEnd2EndTests.release.xcconfig */, 17F60BF2871F6AF85FB3FA12 /* Pods-InteropTestsRemoteWithCronet.debug.xcconfig */, AC414EF7A6BF76ED02B6E480 /* Pods-InteropTestsRemoteWithCronet.release.xcconfig */, E7E4D3FD76E3B745D992AF5F /* Pods-AllTests.cronet.xcconfig */, 573450F334B331D0BED8B961 /* Pods-CoreCronetEnd2EndTests.cronet.xcconfig */, AA7CB64B4DD9915AE7C03163 /* Pods-InteropTestsLocalCleartext.cronet.xcconfig */, 14B09A58FEE53A7A6B838920 /* Pods-InteropTestsLocalSSL.cronet.xcconfig */, 4ADEA1C8BBE10D90940AC68E /* Pods-InteropTestsRemote.cronet.xcconfig */, 3F27B2E744482771EB93C394 /* Pods-InteropTestsRemoteWithCronet.cronet.xcconfig */, 79C68EFFCB5533475D810B79 /* Pods-RxLibraryUnitTests.cronet.xcconfig */, F671D4CAD2864FB203B920B4 /* Pods-Tests.cronet.xcconfig */, 64F68A9A6A63CC930DD30A6E /* Pods-CronetUnitTests.debug.xcconfig */, 386712AEACF7C2190C4B8B3F /* Pods-CronetUnitTests.cronet.xcconfig */, 02192CF1FF9534E3D18C65FC /* Pods-CronetUnitTests.release.xcconfig */, DB1F4391AF69D20D38D74B67 /* Pods-AllTests.test.xcconfig */, 6793C9D019CB268C5BB491A2 /* Pods-CoreCronetEnd2EndTests.test.xcconfig */, B226619DC4E709E0FFFF94B8 /* Pods-CronetUnitTests.test.xcconfig */, 1588C85DEAF7FC0ACDEA4C02 /* Pods-InteropTestsLocalCleartext.test.xcconfig */, D13BEC8181B8E678A1B52F54 /* Pods-InteropTestsLocalSSL.test.xcconfig */, A6F832FCEFA6F6881E620F12 /* Pods-InteropTestsRemote.test.xcconfig */, 2B89F3037963E6EDDD48D8C3 /* Pods-InteropTestsRemoteWithCronet.test.xcconfig */, 781089FAE980F51F88A3BE0B /* Pods-RxLibraryUnitTests.test.xcconfig */, A0361771A855917162911180 /* Pods-Tests.test.xcconfig */, ); name = Pods; sourceTree = ""; }; 5E8A5DA51D3840B4000F8BC4 /* CoreCronetEnd2EndTests */ = { isa = PBXGroup; children = ( 5E8A5DA61D3840B4000F8BC4 /* CoreCronetEnd2EndTests.m */, ); path = CoreCronetEnd2EndTests; sourceTree = ""; }; 5EAD6D251E27047400002378 /* CronetUnitTests */ = { isa = PBXGroup; children = ( 5EAD6D261E27047400002378 /* CronetUnitTests.m */, 5EAD6D281E27047400002378 /* Info.plist */, ); path = CronetUnitTests; sourceTree = ""; }; 5EE84BF21D4717E40050C6CC /* InteropTestsRemoteWithCronet */ = { isa = PBXGroup; children = ( 5EE84BF31D4717E40050C6CC /* InteropTestsRemoteWithCronet.m */, 5EE84BF51D4717E40050C6CC /* Info.plist */, ); path = InteropTestsRemoteWithCronet; sourceTree = ""; }; 635697BE1B14FC11007A7283 = { isa = PBXGroup; children = ( 635697C91B14FC11007A7283 /* Tests */, 63E240CF1B6C63DC005F3B0E /* TestCertificates.bundle */, 5E8A5DA51D3840B4000F8BC4 /* CoreCronetEnd2EndTests */, 5EE84BF21D4717E40050C6CC /* InteropTestsRemoteWithCronet */, 5EAD6D251E27047400002378 /* CronetUnitTests */, 635697C81B14FC11007A7283 /* Products */, 51E4650F34F854F41FF053B3 /* Pods */, 136D535E19727099B941D7B1 /* Frameworks */, ); sourceTree = ""; }; 635697C81B14FC11007A7283 /* Products */ = { isa = PBXGroup; children = ( 635697C71B14FC11007A7283 /* libTests.a */, 63423F441B150A5F006CF63C /* AllTests.xctest */, 63DC84131BE15179000708E8 /* RxLibraryUnitTests.xctest */, 63DC84231BE15267000708E8 /* InteropTestsRemote.xctest */, 63DC84341BE15294000708E8 /* InteropTestsLocalSSL.xctest */, 63DC84431BE152B5000708E8 /* InteropTestsLocalCleartext.xctest */, 5E8A5DA41D3840B4000F8BC4 /* CoreCronetEnd2EndTests.xctest */, 5EE84BF11D4717E40050C6CC /* InteropTestsRemoteWithCronet.xctest */, 5EAD6D241E27047400002378 /* CronetUnitTests.xctest */, ); name = Products; sourceTree = ""; }; 635697C91B14FC11007A7283 /* Tests */ = { isa = PBXGroup; children = ( 6312AE4D1B1BF49B00341DEE /* GRPCClientTests.m */, 63E240CC1B6C4D3A005F3B0E /* InteropTests.h */, 635ED2EB1B1A3BC400FDE5C3 /* InteropTests.m */, 6379CC4F1BE16703001BC0A1 /* InteropTestsRemote.m */, 63E240CD1B6C4E2B005F3B0E /* InteropTestsLocalSSL.m */, 63715F551B780C020029CB0B /* InteropTestsLocalCleartext.m */, 63423F501B151B77006CF63C /* RxLibraryUnitTests.m */, 635697CC1B14FC11007A7283 /* Tests.m */, 635697D71B14FC11007A7283 /* Supporting Files */, ); name = Tests; sourceTree = SOURCE_ROOT; }; 635697D71B14FC11007A7283 /* Supporting Files */ = { isa = PBXGroup; children = ( 635697D81B14FC11007A7283 /* Info.plist */, ); name = "Supporting Files"; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 5E8A5DA31D3840B4000F8BC4 /* CoreCronetEnd2EndTests */ = { isa = PBXNativeTarget; buildConfigurationList = 5E8A5DAE1D3840B4000F8BC4 /* Build configuration list for PBXNativeTarget "CoreCronetEnd2EndTests" */; buildPhases = ( F58F17E425446B15028B9F74 /* [CP] Check Pods Manifest.lock */, 5E8A5DA01D3840B4000F8BC4 /* Sources */, 5E8A5DA11D3840B4000F8BC4 /* Frameworks */, 5E8A5DA21D3840B4000F8BC4 /* Resources */, E63468C760D0724F18861822 /* [CP] Embed Pods Frameworks */, 6DFE9E77CAB5760196D79E0F /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( 5E8A5DAB1D3840B4000F8BC4 /* PBXTargetDependency */, ); name = CoreCronetEnd2EndTests; productName = CoreCronetEnd2EndTests; productReference = 5E8A5DA41D3840B4000F8BC4 /* CoreCronetEnd2EndTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; 5EAD6D231E27047400002378 /* CronetUnitTests */ = { isa = PBXNativeTarget; buildConfigurationList = 5EAD6D2F1E27047400002378 /* Build configuration list for PBXNativeTarget "CronetUnitTests" */; buildPhases = ( 80E2DDD2EC04A4009F45E933 /* [CP] Check Pods Manifest.lock */, 5EAD6D201E27047400002378 /* Sources */, 5EAD6D211E27047400002378 /* Frameworks */, 5EAD6D221E27047400002378 /* Resources */, A686B9967BB4CB81B1CBF8F8 /* [CP] Embed Pods Frameworks */, 051806D6A59B19C8A0B76BED /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( 5EAD6D2B1E27047400002378 /* PBXTargetDependency */, ); name = CronetUnitTests; productName = CronetUnitTests; productReference = 5EAD6D241E27047400002378 /* CronetUnitTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; 5EE84BF01D4717E40050C6CC /* InteropTestsRemoteWithCronet */ = { isa = PBXNativeTarget; buildConfigurationList = 5EE84BFB1D4717E40050C6CC /* Build configuration list for PBXNativeTarget "InteropTestsRemoteWithCronet" */; buildPhases = ( C0F7B1FF6F88CC5FBF362F4C /* [CP] Check Pods Manifest.lock */, 5EE84BED1D4717E40050C6CC /* Sources */, 5EE84BEE1D4717E40050C6CC /* Frameworks */, 5EE84BEF1D4717E40050C6CC /* Resources */, 31F8D1C407195CBF0C02929B /* [CP] Embed Pods Frameworks */, DB4D0E73C229F2FF3B364AB3 /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( 5EE84BF81D4717E40050C6CC /* PBXTargetDependency */, ); name = InteropTestsRemoteWithCronet; productName = InteropTestsRemoteWithCronet; productReference = 5EE84BF11D4717E40050C6CC /* InteropTestsRemoteWithCronet.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; 63423F431B150A5F006CF63C /* AllTests */ = { isa = PBXNativeTarget; buildConfigurationList = 63423F4D1B150A5F006CF63C /* Build configuration list for PBXNativeTarget "AllTests" */; buildPhases = ( 914ADDD7106BA9BB8A7E569F /* [CP] Check Pods Manifest.lock */, 63423F401B150A5F006CF63C /* Sources */, 63423F411B150A5F006CF63C /* Frameworks */, 63423F421B150A5F006CF63C /* Resources */, A441F71824DCB9D0CA297748 /* [CP] Copy Pods Resources */, 5F14F59509E10C2852014F9E /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); dependencies = ( 63423F4C1B150A5F006CF63C /* PBXTargetDependency */, ); name = AllTests; productName = AllTests; productReference = 63423F441B150A5F006CF63C /* AllTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; 635697C61B14FC11007A7283 /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 635697DB1B14FC11007A7283 /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 796680C7599CB4ED736DD62A /* [CP] Check Pods Manifest.lock */, 635697C31B14FC11007A7283 /* Sources */, 635697C41B14FC11007A7283 /* Frameworks */, 635697C51B14FC11007A7283 /* CopyFiles */, AEEBFC914CBAEE347382E8C4 /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = Tests; productReference = 635697C71B14FC11007A7283 /* libTests.a */; productType = "com.apple.product-type.library.static"; }; 63DC84121BE15179000708E8 /* RxLibraryUnitTests */ = { isa = PBXNativeTarget; buildConfigurationList = 63DC841B1BE15179000708E8 /* Build configuration list for PBXNativeTarget "RxLibraryUnitTests" */; buildPhases = ( B2986CEEE8CDD4901C97598B /* [CP] Check Pods Manifest.lock */, 63DC840F1BE15179000708E8 /* Sources */, 63DC84101BE15179000708E8 /* Frameworks */, 63DC84111BE15179000708E8 /* Resources */, 4F5690DC0E6AD6663FE78B8B /* [CP] Embed Pods Frameworks */, C977426A8727267BBAC7D48E /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( 63DC841A1BE15179000708E8 /* PBXTargetDependency */, ); name = RxLibraryUnitTests; productName = RxLibraryUnitTests; productReference = 63DC84131BE15179000708E8 /* RxLibraryUnitTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; 63DC84221BE15267000708E8 /* InteropTestsRemote */ = { isa = PBXNativeTarget; buildConfigurationList = 63DC842B1BE15267000708E8 /* Build configuration list for PBXNativeTarget "InteropTestsRemote" */; buildPhases = ( 4C406327D3907A5E5FBA8AC9 /* [CP] Check Pods Manifest.lock */, 63DC841F1BE15267000708E8 /* Sources */, 63DC84201BE15267000708E8 /* Frameworks */, 63DC84211BE15267000708E8 /* Resources */, 900B6EDD4D16BE7D765C3885 /* [CP] Embed Pods Frameworks */, C2E09DC4BD239F71160F0CC1 /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( 63DC842A1BE15267000708E8 /* PBXTargetDependency */, ); name = InteropTestsRemote; productName = InteropTests; productReference = 63DC84231BE15267000708E8 /* InteropTestsRemote.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; 63DC84331BE15294000708E8 /* InteropTestsLocalSSL */ = { isa = PBXNativeTarget; buildConfigurationList = 63DC843C1BE15294000708E8 /* Build configuration list for PBXNativeTarget "InteropTestsLocalSSL" */; buildPhases = ( 5C20DCCB71C3991E6FE78C22 /* [CP] Check Pods Manifest.lock */, 63DC84301BE15294000708E8 /* Sources */, 63DC84311BE15294000708E8 /* Frameworks */, 63DC84321BE15294000708E8 /* Resources */, C591129ACE9F6CC5EE03FCDE /* [CP] Embed Pods Frameworks */, 693DD0B453431D64EA24FD66 /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( 63DC843B1BE15294000708E8 /* PBXTargetDependency */, ); name = InteropTestsLocalSSL; productName = InteropTestsLocalSSL; productReference = 63DC84341BE15294000708E8 /* InteropTestsLocalSSL.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; 63DC84421BE152B5000708E8 /* InteropTestsLocalCleartext */ = { isa = PBXNativeTarget; buildConfigurationList = 63DC844B1BE152B5000708E8 /* Build configuration list for PBXNativeTarget "InteropTestsLocalCleartext" */; buildPhases = ( 7418AC7B3844B29E48D24FC7 /* [CP] Check Pods Manifest.lock */, 63DC843F1BE152B5000708E8 /* Sources */, 63DC84401BE152B5000708E8 /* Frameworks */, 63DC84411BE152B5000708E8 /* Resources */, A8E3AC66DF770B774114A30E /* [CP] Embed Pods Frameworks */, 8AD3130D3C58A0FB32FF2A36 /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( 63DC844A1BE152B5000708E8 /* PBXTargetDependency */, ); name = InteropTestsLocalCleartext; productName = InteropTestsLocalCleartext; productReference = 63DC84431BE152B5000708E8 /* InteropTestsLocalCleartext.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 635697BF1B14FC11007A7283 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0630; ORGANIZATIONNAME = gRPC; TargetAttributes = { 5E8A5DA31D3840B4000F8BC4 = { CreatedOnToolsVersion = 7.3.1; }; 5EAD6D231E27047400002378 = { CreatedOnToolsVersion = 7.3.1; }; 5EE84BF01D4717E40050C6CC = { CreatedOnToolsVersion = 7.3.1; }; 63423F431B150A5F006CF63C = { CreatedOnToolsVersion = 6.3.1; }; 635697C61B14FC11007A7283 = { CreatedOnToolsVersion = 6.3.1; }; 63DC84121BE15179000708E8 = { CreatedOnToolsVersion = 7.0.1; }; 63DC84221BE15267000708E8 = { CreatedOnToolsVersion = 7.0.1; }; 63DC84331BE15294000708E8 = { CreatedOnToolsVersion = 7.0.1; }; 63DC84421BE152B5000708E8 = { CreatedOnToolsVersion = 7.0.1; }; }; }; buildConfigurationList = 635697C21B14FC11007A7283 /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 635697BE1B14FC11007A7283; productRefGroup = 635697C81B14FC11007A7283 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 635697C61B14FC11007A7283 /* Tests */, 63423F431B150A5F006CF63C /* AllTests */, 63DC84121BE15179000708E8 /* RxLibraryUnitTests */, 63DC84221BE15267000708E8 /* InteropTestsRemote */, 63DC84331BE15294000708E8 /* InteropTestsLocalSSL */, 63DC84421BE152B5000708E8 /* InteropTestsLocalCleartext */, 5E8A5DA31D3840B4000F8BC4 /* CoreCronetEnd2EndTests */, 5EE84BF01D4717E40050C6CC /* InteropTestsRemoteWithCronet */, 5EAD6D231E27047400002378 /* CronetUnitTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 5E8A5DA21D3840B4000F8BC4 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 5EAD6D221E27047400002378 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 5EE84BEF1D4717E40050C6CC /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 63423F421B150A5F006CF63C /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 63E240D01B6C63DC005F3B0E /* TestCertificates.bundle in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; 63DC84111BE15179000708E8 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 63DC84211BE15267000708E8 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 63DC84321BE15294000708E8 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 6379CC531BE17709001BC0A1 /* TestCertificates.bundle in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; 63DC84411BE152B5000708E8 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 051806D6A59B19C8A0B76BED /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-CronetUnitTests/Pods-CronetUnitTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; 31F8D1C407195CBF0C02929B /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; 4C406327D3907A5E5FBA8AC9 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; 4F5690DC0E6AD6663FE78B8B /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RxLibraryUnitTests/Pods-RxLibraryUnitTests-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; 5C20DCCB71C3991E6FE78C22 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; 5F14F59509E10C2852014F9E /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AllTests/Pods-AllTests-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; 693DD0B453431D64EA24FD66 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL-resources.sh\"\n"; showEnvVarsInLog = 0; }; 6DFE9E77CAB5760196D79E0F /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; 7418AC7B3844B29E48D24FC7 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; 796680C7599CB4ED736DD62A /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; 80E2DDD2EC04A4009F45E933 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; 8AD3130D3C58A0FB32FF2A36 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext-resources.sh\"\n"; showEnvVarsInLog = 0; }; 900B6EDD4D16BE7D765C3885 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; 914ADDD7106BA9BB8A7E569F /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; A441F71824DCB9D0CA297748 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AllTests/Pods-AllTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; A686B9967BB4CB81B1CBF8F8 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-CronetUnitTests/Pods-CronetUnitTests-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; A8E3AC66DF770B774114A30E /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; AEEBFC914CBAEE347382E8C4 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-resources.sh\"\n"; showEnvVarsInLog = 0; }; B2986CEEE8CDD4901C97598B /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; C0F7B1FF6F88CC5FBF362F4C /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; C2E09DC4BD239F71160F0CC1 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote-resources.sh\"\n"; showEnvVarsInLog = 0; }; C591129ACE9F6CC5EE03FCDE /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; C977426A8727267BBAC7D48E /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RxLibraryUnitTests/Pods-RxLibraryUnitTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; DB4D0E73C229F2FF3B364AB3 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet-resources.sh\"\n"; showEnvVarsInLog = 0; }; E63468C760D0724F18861822 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; F58F17E425446B15028B9F74 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 5E8A5DA01D3840B4000F8BC4 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 5E8A5DA71D3840B4000F8BC4 /* CoreCronetEnd2EndTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 5EAD6D201E27047400002378 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 5EAD6D271E27047400002378 /* CronetUnitTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 5EE84BED1D4717E40050C6CC /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 5EE84BFE1D471D400050C6CC /* InteropTests.m in Sources */, 5EE84BF41D4717E40050C6CC /* InteropTestsRemoteWithCronet.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 63423F401B150A5F006CF63C /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 63715F561B780C020029CB0B /* InteropTestsLocalCleartext.m in Sources */, 6379CC511BE1683B001BC0A1 /* InteropTestsRemote.m in Sources */, 63E240CE1B6C4E2B005F3B0E /* InteropTestsLocalSSL.m in Sources */, 6312AE4E1B1BF49B00341DEE /* GRPCClientTests.m in Sources */, 635ED2EC1B1A3BC400FDE5C3 /* InteropTests.m in Sources */, 63DC842E1BE15278000708E8 /* RxLibraryUnitTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 635697C31B14FC11007A7283 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 635697CD1B14FC11007A7283 /* Tests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 63DC840F1BE15179000708E8 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 63DC841E1BE15180000708E8 /* RxLibraryUnitTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 63DC841F1BE15267000708E8 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 63DC842F1BE1527D000708E8 /* InteropTests.m in Sources */, 6379CC501BE16703001BC0A1 /* InteropTestsRemote.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 63DC84301BE15294000708E8 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 63DC844F1BE15353000708E8 /* InteropTestsLocalSSL.m in Sources */, 6379CC4D1BE1662A001BC0A1 /* InteropTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 63DC843F1BE152B5000708E8 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 63DC84501BE153AA000708E8 /* GRPCClientTests.m in Sources */, 63DC844E1BE15350000708E8 /* InteropTestsLocalCleartext.m in Sources */, 6379CC4E1BE1662B001BC0A1 /* InteropTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 5E8A5DAB1D3840B4000F8BC4 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 635697C61B14FC11007A7283 /* Tests */; targetProxy = 5E8A5DAA1D3840B4000F8BC4 /* PBXContainerItemProxy */; }; 5EAD6D2B1E27047400002378 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 635697C61B14FC11007A7283 /* Tests */; targetProxy = 5EAD6D2A1E27047400002378 /* PBXContainerItemProxy */; }; 5EE84BF81D4717E40050C6CC /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 635697C61B14FC11007A7283 /* Tests */; targetProxy = 5EE84BF71D4717E40050C6CC /* PBXContainerItemProxy */; }; 63423F4C1B150A5F006CF63C /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 635697C61B14FC11007A7283 /* Tests */; targetProxy = 63423F4B1B150A5F006CF63C /* PBXContainerItemProxy */; }; 63DC841A1BE15179000708E8 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 635697C61B14FC11007A7283 /* Tests */; targetProxy = 63DC84191BE15179000708E8 /* PBXContainerItemProxy */; }; 63DC842A1BE15267000708E8 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 635697C61B14FC11007A7283 /* Tests */; targetProxy = 63DC84291BE15267000708E8 /* PBXContainerItemProxy */; }; 63DC843B1BE15294000708E8 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 635697C61B14FC11007A7283 /* Tests */; targetProxy = 63DC843A1BE15294000708E8 /* PBXContainerItemProxy */; }; 63DC844A1BE152B5000708E8 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 635697C61B14FC11007A7283 /* Tests */; targetProxy = 63DC84491BE152B5000708E8 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ 5E1228981E4D400F00E8504F /* Test */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.3; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; }; name = Test; }; 5E1228991E4D400F00E8504F /* Test */ = { isa = XCBuildConfiguration; baseConfigurationReference = A0361771A855917162911180 /* Pods-Tests.test.xcconfig */; buildSettings = { GCC_TREAT_WARNINGS_AS_ERRORS = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; name = Test; }; 5E12289A1E4D400F00E8504F /* Test */ = { isa = XCBuildConfiguration; baseConfigurationReference = DB1F4391AF69D20D38D74B67 /* Pods-AllTests.test.xcconfig */; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", ); GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", "GRPC_TEST_OBJC=1", ); INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Test; }; 5E12289B1E4D400F00E8504F /* Test */ = { isa = XCBuildConfiguration; baseConfigurationReference = 781089FAE980F51F88A3BE0B /* Pods-RxLibraryUnitTests.test.xcconfig */; buildSettings = { DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; INFOPLIST_FILE = Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.RxLibraryUnitTests; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Test; }; 5E12289C1E4D400F00E8504F /* Test */ = { isa = XCBuildConfiguration; baseConfigurationReference = A6F832FCEFA6F6881E620F12 /* Pods-InteropTestsRemote.test.xcconfig */; buildSettings = { DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "COCOAPODS=1", "$(inherited)", "GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1", "GRPC_TEST_OBJC=1", ); INFOPLIST_FILE = Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTests; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Test; }; 5E12289D1E4D400F00E8504F /* Test */ = { isa = XCBuildConfiguration; baseConfigurationReference = D13BEC8181B8E678A1B52F54 /* Pods-InteropTestsLocalSSL.test.xcconfig */; buildSettings = { DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "COCOAPODS=1", "$(inherited)", "GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1", "GRPC_TEST_OBJC=1", ); INFOPLIST_FILE = Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsLocalSSL; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Test; }; 5E12289E1E4D400F00E8504F /* Test */ = { isa = XCBuildConfiguration; baseConfigurationReference = 1588C85DEAF7FC0ACDEA4C02 /* Pods-InteropTestsLocalCleartext.test.xcconfig */; buildSettings = { DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "COCOAPODS=1", "GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1", "GRPC_TEST_OBJC=1", ); INFOPLIST_FILE = Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsLocalCleartext; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Test; }; 5E12289F1E4D400F00E8504F /* Test */ = { isa = XCBuildConfiguration; baseConfigurationReference = 6793C9D019CB268C5BB491A2 /* Pods-CoreCronetEnd2EndTests.test.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; INFOPLIST_FILE = CoreCronetEnd2EndTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.CoreCronetEnd2EndTests; PRODUCT_NAME = "$(TARGET_NAME)"; USER_HEADER_SEARCH_PATHS = "$(inherited) \"${PODS_ROOT}/../../../..\""; }; name = Test; }; 5E1228A01E4D400F00E8504F /* Test */ = { isa = XCBuildConfiguration; baseConfigurationReference = 2B89F3037963E6EDDD48D8C3 /* Pods-InteropTestsRemoteWithCronet.test.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "COCOAPODS=1", "GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1", "GRPC_TEST_OBJC=1", ); INFOPLIST_FILE = InteropTestsRemoteWithCronet/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsRemoteWithCronet; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Test; }; 5E1228A11E4D400F00E8504F /* Test */ = { isa = XCBuildConfiguration; baseConfigurationReference = B226619DC4E709E0FFFF94B8 /* Pods-CronetUnitTests.test.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; INFOPLIST_FILE = CronetUnitTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.CronetUnitTests; PRODUCT_NAME = "$(TARGET_NAME)"; USER_HEADER_SEARCH_PATHS = "\"${PODS_ROOT}/../../../..\" $(inherited)"; }; name = Test; }; 5E8A5DAC1D3840B4000F8BC4 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 0D2284C3DF7E57F0ED504E39 /* Pods-CoreCronetEnd2EndTests.debug.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; INFOPLIST_FILE = CoreCronetEnd2EndTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.CoreCronetEnd2EndTests; PRODUCT_NAME = "$(TARGET_NAME)"; USER_HEADER_SEARCH_PATHS = "$(inherited) \"${PODS_ROOT}/../../../..\""; }; name = Debug; }; 5E8A5DAD1D3840B4000F8BC4 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 4AD97096D13D7416DC91A72A /* Pods-CoreCronetEnd2EndTests.release.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; INFOPLIST_FILE = CoreCronetEnd2EndTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.CoreCronetEnd2EndTests; PRODUCT_NAME = "$(TARGET_NAME)"; USER_HEADER_SEARCH_PATHS = "$(inherited) \"${PODS_ROOT}/../../../..\""; }; name = Release; }; 5EAD6D2C1E27047400002378 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 64F68A9A6A63CC930DD30A6E /* Pods-CronetUnitTests.debug.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; INFOPLIST_FILE = CronetUnitTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.CronetUnitTests; PRODUCT_NAME = "$(TARGET_NAME)"; USER_HEADER_SEARCH_PATHS = "\"${PODS_ROOT}/../../../..\" $(inherited)"; }; name = Debug; }; 5EAD6D2D1E27047400002378 /* Cronet */ = { isa = XCBuildConfiguration; baseConfigurationReference = 386712AEACF7C2190C4B8B3F /* Pods-CronetUnitTests.cronet.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; INFOPLIST_FILE = CronetUnitTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.CronetUnitTests; PRODUCT_NAME = "$(TARGET_NAME)"; USER_HEADER_SEARCH_PATHS = "\"${PODS_ROOT}/../../../..\" $(inherited)"; }; name = Cronet; }; 5EAD6D2E1E27047400002378 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 02192CF1FF9534E3D18C65FC /* Pods-CronetUnitTests.release.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; INFOPLIST_FILE = CronetUnitTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.CronetUnitTests; PRODUCT_NAME = "$(TARGET_NAME)"; USER_HEADER_SEARCH_PATHS = "\"${PODS_ROOT}/../../../..\" $(inherited)"; }; name = Release; }; 5EC3C7A01D4FC18C000330E2 /* Cronet */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.3; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; }; name = Cronet; }; 5EC3C7A11D4FC18C000330E2 /* Cronet */ = { isa = XCBuildConfiguration; baseConfigurationReference = F671D4CAD2864FB203B920B4 /* Pods-Tests.cronet.xcconfig */; buildSettings = { GCC_TREAT_WARNINGS_AS_ERRORS = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; name = Cronet; }; 5EC3C7A21D4FC18C000330E2 /* Cronet */ = { isa = XCBuildConfiguration; baseConfigurationReference = E7E4D3FD76E3B745D992AF5F /* Pods-AllTests.cronet.xcconfig */; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", ); GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Cronet; }; 5EC3C7A31D4FC18C000330E2 /* Cronet */ = { isa = XCBuildConfiguration; baseConfigurationReference = 79C68EFFCB5533475D810B79 /* Pods-RxLibraryUnitTests.cronet.xcconfig */; buildSettings = { DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; INFOPLIST_FILE = Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.RxLibraryUnitTests; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Cronet; }; 5EC3C7A41D4FC18C000330E2 /* Cronet */ = { isa = XCBuildConfiguration; baseConfigurationReference = 4ADEA1C8BBE10D90940AC68E /* Pods-InteropTestsRemote.cronet.xcconfig */; buildSettings = { DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "COCOAPODS=1", "$(inherited)", "GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1", ); INFOPLIST_FILE = Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTests; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Cronet; }; 5EC3C7A51D4FC18C000330E2 /* Cronet */ = { isa = XCBuildConfiguration; baseConfigurationReference = 14B09A58FEE53A7A6B838920 /* Pods-InteropTestsLocalSSL.cronet.xcconfig */; buildSettings = { DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; INFOPLIST_FILE = Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsLocalSSL; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Cronet; }; 5EC3C7A61D4FC18C000330E2 /* Cronet */ = { isa = XCBuildConfiguration; baseConfigurationReference = AA7CB64B4DD9915AE7C03163 /* Pods-InteropTestsLocalCleartext.cronet.xcconfig */; buildSettings = { DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; INFOPLIST_FILE = Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsLocalCleartext; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Cronet; }; 5EC3C7A71D4FC18C000330E2 /* Cronet */ = { isa = XCBuildConfiguration; baseConfigurationReference = 573450F334B331D0BED8B961 /* Pods-CoreCronetEnd2EndTests.cronet.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; INFOPLIST_FILE = CoreCronetEnd2EndTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.CoreCronetEnd2EndTests; PRODUCT_NAME = "$(TARGET_NAME)"; USER_HEADER_SEARCH_PATHS = "$(inherited) \"${PODS_ROOT}/../../../..\""; }; name = Cronet; }; 5EC3C7A81D4FC18C000330E2 /* Cronet */ = { isa = XCBuildConfiguration; baseConfigurationReference = 3F27B2E744482771EB93C394 /* Pods-InteropTestsRemoteWithCronet.cronet.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "COCOAPODS=1", "GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1", "GRPC_COMPILE_WITH_CRONET=1", "GRPC_CRONET_WITH_PACKET_COALESCING=1", "GRPC_TEST_OBJC=1", ); INFOPLIST_FILE = InteropTestsRemoteWithCronet/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsRemoteWithCronet; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Cronet; }; 5EE84BF91D4717E40050C6CC /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 17F60BF2871F6AF85FB3FA12 /* Pods-InteropTestsRemoteWithCronet.debug.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "COCOAPODS=1", "GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1", ); INFOPLIST_FILE = InteropTestsRemoteWithCronet/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsRemoteWithCronet; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 5EE84BFA1D4717E40050C6CC /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = AC414EF7A6BF76ED02B6E480 /* Pods-InteropTestsRemoteWithCronet.release.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "COCOAPODS=1", "$(inherited)", "GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1", "GRPC_COMPILE_WITH_CRONET=1", ); INFOPLIST_FILE = InteropTestsRemoteWithCronet/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsRemoteWithCronet; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; 63423F4E1B150A5F006CF63C /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = B94C27C06733CF98CE1B2757 /* Pods-AllTests.debug.xcconfig */; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", ); GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 63423F4F1B150A5F006CF63C /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 5761E98978DDDF136A58CB7E /* Pods-AllTests.release.xcconfig */; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", ); INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; 635697D91B14FC11007A7283 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.3; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; }; name = Debug; }; 635697DA1B14FC11007A7283 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.3; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; }; name = Release; }; 635697DC1B14FC11007A7283 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 060EF32D7EC0DF67ED617507 /* Pods-Tests.debug.xcconfig */; buildSettings = { GCC_TREAT_WARNINGS_AS_ERRORS = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; name = Debug; }; 635697DD1B14FC11007A7283 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = E6733B838B28453434B556E2 /* Pods-Tests.release.xcconfig */; buildSettings = { GCC_TREAT_WARNINGS_AS_ERRORS = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; name = Release; }; 63DC841C1BE15179000708E8 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 07D10A965323BEA7FE59A74B /* Pods-RxLibraryUnitTests.debug.xcconfig */; buildSettings = { DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; INFOPLIST_FILE = Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.RxLibraryUnitTests; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 63DC841D1BE15179000708E8 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 3B0861FC805389C52DB260D4 /* Pods-RxLibraryUnitTests.release.xcconfig */; buildSettings = { INFOPLIST_FILE = Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.RxLibraryUnitTests; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; 63DC842C1BE15267000708E8 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = DC3CA1D948F068E76957A861 /* Pods-InteropTestsRemote.debug.xcconfig */; buildSettings = { DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; INFOPLIST_FILE = Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTests; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 63DC842D1BE15267000708E8 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = E4275A759BDBDF143B9B438F /* Pods-InteropTestsRemote.release.xcconfig */; buildSettings = { INFOPLIST_FILE = Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTests; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; 63DC843D1BE15294000708E8 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 553BBBED24E4162D1F769D65 /* Pods-InteropTestsLocalSSL.debug.xcconfig */; buildSettings = { DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; INFOPLIST_FILE = Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsLocalSSL; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 63DC843E1BE15294000708E8 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 7A2E97E3F469CC2A758D77DE /* Pods-InteropTestsLocalSSL.release.xcconfig */; buildSettings = { INFOPLIST_FILE = Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsLocalSSL; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; 63DC844C1BE152B5000708E8 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = E1486220285AF123EB124008 /* Pods-InteropTestsLocalCleartext.debug.xcconfig */; buildSettings = { DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; INFOPLIST_FILE = Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsLocalCleartext; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 63DC844D1BE152B5000708E8 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 51A275E86C141416ED63FF76 /* Pods-InteropTestsLocalCleartext.release.xcconfig */; buildSettings = { INFOPLIST_FILE = Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsLocalCleartext; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 5E8A5DAE1D3840B4000F8BC4 /* Build configuration list for PBXNativeTarget "CoreCronetEnd2EndTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 5E8A5DAC1D3840B4000F8BC4 /* Debug */, 5E12289F1E4D400F00E8504F /* Test */, 5EC3C7A71D4FC18C000330E2 /* Cronet */, 5E8A5DAD1D3840B4000F8BC4 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 5EAD6D2F1E27047400002378 /* Build configuration list for PBXNativeTarget "CronetUnitTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 5EAD6D2C1E27047400002378 /* Debug */, 5E1228A11E4D400F00E8504F /* Test */, 5EAD6D2D1E27047400002378 /* Cronet */, 5EAD6D2E1E27047400002378 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 5EE84BFB1D4717E40050C6CC /* Build configuration list for PBXNativeTarget "InteropTestsRemoteWithCronet" */ = { isa = XCConfigurationList; buildConfigurations = ( 5EE84BF91D4717E40050C6CC /* Debug */, 5E1228A01E4D400F00E8504F /* Test */, 5EC3C7A81D4FC18C000330E2 /* Cronet */, 5EE84BFA1D4717E40050C6CC /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 63423F4D1B150A5F006CF63C /* Build configuration list for PBXNativeTarget "AllTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 63423F4E1B150A5F006CF63C /* Debug */, 5E12289A1E4D400F00E8504F /* Test */, 5EC3C7A21D4FC18C000330E2 /* Cronet */, 63423F4F1B150A5F006CF63C /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 635697C21B14FC11007A7283 /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 635697D91B14FC11007A7283 /* Debug */, 5E1228981E4D400F00E8504F /* Test */, 5EC3C7A01D4FC18C000330E2 /* Cronet */, 635697DA1B14FC11007A7283 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 635697DB1B14FC11007A7283 /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 635697DC1B14FC11007A7283 /* Debug */, 5E1228991E4D400F00E8504F /* Test */, 5EC3C7A11D4FC18C000330E2 /* Cronet */, 635697DD1B14FC11007A7283 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 63DC841B1BE15179000708E8 /* Build configuration list for PBXNativeTarget "RxLibraryUnitTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 63DC841C1BE15179000708E8 /* Debug */, 5E12289B1E4D400F00E8504F /* Test */, 5EC3C7A31D4FC18C000330E2 /* Cronet */, 63DC841D1BE15179000708E8 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 63DC842B1BE15267000708E8 /* Build configuration list for PBXNativeTarget "InteropTestsRemote" */ = { isa = XCConfigurationList; buildConfigurations = ( 63DC842C1BE15267000708E8 /* Debug */, 5E12289C1E4D400F00E8504F /* Test */, 5EC3C7A41D4FC18C000330E2 /* Cronet */, 63DC842D1BE15267000708E8 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 63DC843C1BE15294000708E8 /* Build configuration list for PBXNativeTarget "InteropTestsLocalSSL" */ = { isa = XCConfigurationList; buildConfigurations = ( 63DC843D1BE15294000708E8 /* Debug */, 5E12289D1E4D400F00E8504F /* Test */, 5EC3C7A51D4FC18C000330E2 /* Cronet */, 63DC843E1BE15294000708E8 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 63DC844B1BE152B5000708E8 /* Build configuration list for PBXNativeTarget "InteropTestsLocalCleartext" */ = { isa = XCConfigurationList; buildConfigurations = ( 63DC844C1BE152B5000708E8 /* Debug */, 5E12289E1E4D400F00E8504F /* Test */, 5EC3C7A61D4FC18C000330E2 /* Cronet */, 63DC844D1BE152B5000708E8 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 635697BF1B14FC11007A7283 /* Project object */; } grpc-1.3.2/src/objective-c/tests/Tests.xcodeproj/project.xcworkspace/000077500000000000000000000000001310511640000256565ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata000066400000000000000000000002261310511640000326200ustar00rootroot00000000000000 grpc-1.3.2/src/objective-c/tests/Tests.xcodeproj/xcshareddata/000077500000000000000000000000001310511640000243135ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/000077500000000000000000000000001310511640000262755ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme000066400000000000000000000076221310511640000315600ustar00rootroot00000000000000 CoreCronetEnd2EndTests.xcscheme000066400000000000000000000072571310511640000342000ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes grpc-1.3.2/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/CronetUnitTests.xcscheme000066400000000000000000000036031310511640000331350ustar00rootroot00000000000000 InteropTestsLocalCleartext.xcscheme000066400000000000000000000073001310511640000352310ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes InteropTestsLocalSSL.xcscheme000066400000000000000000000066521310511640000337500ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes grpc-1.3.2/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsRemote.xcscheme000066400000000000000000000066321310511640000336440ustar00rootroot00000000000000 InteropTestsRemoteWithCronet.xcscheme000066400000000000000000000075761310511640000356040ustar00rootroot00000000000000grpc-1.3.2/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes grpc-1.3.2/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/RxLibraryUnitTests.xcscheme000066400000000000000000000064131310511640000336230ustar00rootroot00000000000000 grpc-1.3.2/src/objective-c/tests/build_example_test.sh000077500000000000000000000052351310511640000227770ustar00rootroot00000000000000#!/bin/bash # Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Don't run this script standalone. Instead, run from the repository root: # ./tools/run_tests/run_tests.py -l objc set -evo pipefail cd `dirname $0` trap 'echo "EXIT TIME: $(date)"' EXIT echo "TIME: $(date)" SCHEME=HelloWorld \ EXAMPLE_PATH=examples/objective-c/helloworld \ ./build_one_example.sh echo "TIME: $(date)" SCHEME=RouteGuideClient \ EXAMPLE_PATH=examples/objective-c/route_guide \ ./build_one_example.sh echo "TIME: $(date)" SCHEME=AuthSample \ EXAMPLE_PATH=examples/objective-c/auth_sample \ ./build_one_example.sh rm -f ../examples/RemoteTestClient/*.{h,m} echo "TIME: $(date)" SCHEME=Sample \ EXAMPLE_PATH=src/objective-c/examples/Sample \ ./build_one_example.sh echo "TIME: $(date)" SCHEME=Sample \ EXAMPLE_PATH=src/objective-c/examples/Sample \ FRAMEWORKS=YES \ ./build_one_example.sh echo "TIME: $(date)" SCHEME=SwiftSample \ EXAMPLE_PATH=src/objective-c/examples/SwiftSample \ ./build_one_example.sh grpc-1.3.2/src/objective-c/tests/build_one_example.sh000077500000000000000000000042401310511640000225740ustar00rootroot00000000000000#!/bin/bash # Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Don't run this script standalone. Instead, run from the repository root: # ./tools/run_tests/run_tests.py -l objc set -ev # Params: # EXAMPLE_PATH - directory of the example # SCHEME - scheme of the example, used by xcodebuild # CocoaPods requires the terminal to be using UTF-8 encoding. export LANG=en_US.UTF-8 cd `dirname $0`/../../.. cd $EXAMPLE_PATH # clean the directory rm -rf Pods rm -rf $SCHEME.xcworkspace rm -f Podfile.lock pod install set -o pipefail XCODEBUILD_FILTER='(^===|^\*\*|\bfatal\b|\berror\b|\bwarning\b|\bfail)' xcodebuild \ build \ -workspace *.xcworkspace \ -scheme $SCHEME \ -destination name="iPhone 6" | xcpretty grpc-1.3.2/src/objective-c/tests/build_tests.sh000077500000000000000000000040711310511640000214440ustar00rootroot00000000000000#!/bin/bash # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Don't run this script standalone. Instead, run from the repository root: # ./tools/run_tests/run_tests.py -l objc set -e # CocoaPods requires the terminal to be using UTF-8 encoding. export LANG=en_US.UTF-8 cd $(dirname $0) hash pod 2>/dev/null || { echo >&2 "Cocoapods needs to be installed."; exit 1; } hash xcodebuild 2>/dev/null || { echo >&2 "XCode command-line tools need to be installed." exit 1 } # clean the directory rm -rf Pods rm -rf Tests.xcworkspace rm -f Podfile.lock rm -f RemoteTestClient/*.{h,m} echo "TIME: $(date)" pod install grpc-1.3.2/src/objective-c/tests/run_tests.sh000077500000000000000000000062301310511640000211500ustar00rootroot00000000000000#!/bin/bash # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Don't run this script standalone. Instead, run from the repository root: # ./tools/run_tests/run_tests.py -l objc set -ev cd $(dirname $0) # Run the tests server. BINDIR=../../../bins/$CONFIG [ -f $BINDIR/interop_server ] || { echo >&2 "Can't find the test server. Make sure run_tests.py is making" \ "interop_server before calling this script." exit 1 } $BINDIR/interop_server --port=5050 --max_send_message_size=8388608 & $BINDIR/interop_server --port=5051 --max_send_message_size=8388608 --use_tls & # Kill them when this script exits. trap 'kill -9 `jobs -p` ; echo "EXIT TIME: $(date)"' EXIT # xcodebuild is very verbose. We filter its output and tell Bash to fail if any # element of the pipe fails. # TODO(jcanizales): Use xctool instead? Issue #2540. set -o pipefail XCODEBUILD_FILTER='(^===|^\*\*|\bfatal\b|\berror\b|\bwarning\b|\bfail)' echo "TIME: $(date)" xcodebuild \ -workspace Tests.xcworkspace \ -scheme AllTests \ -destination name="iPhone 6" \ test | xcpretty echo "TIME: $(date)" xcodebuild \ -workspace Tests.xcworkspace \ -scheme CoreCronetEnd2EndTests \ -destination name="iPhone 6" \ test | xcpretty # Temporarily disabled for (possible) flakiness on Jenkins. # Fix or reenable after confirmation/disconfirmation that it is the source of # Jenkins problem. # echo "TIME: $(date)" # xcodebuild \ # -workspace Tests.xcworkspace \ # -scheme CronetUnitTests \ # -destination name="iPhone 6" \ # test | xcpretty echo "TIME: $(date)" xcodebuild \ -workspace Tests.xcworkspace \ -scheme InteropTestsRemoteWithCronet \ -destination name="iPhone 6" \ test | xcpretty grpc-1.3.2/src/php/000077500000000000000000000000001310511640000140155ustar00rootroot00000000000000grpc-1.3.2/src/php/.gitignore000066400000000000000000000003471310511640000160110ustar00rootroot00000000000000.libs/ build/ modules/ autom4te.cache/ *.lo *.la .deps acinclude.m4 aclocal.m4 config.* configure* Makefile* run-tests.php install-sh libtool missing mkinstalldirs ext/grpc/ltmain.sh composer.lock vendor/ *.pb.php *_grpc_pb.php grpc-1.3.2/src/php/README.md000066400000000000000000000156011310511640000152770ustar00rootroot00000000000000 # Overview This directory contains source code for PHP implementation of gRPC layered on shared C library. ## Environment **Prerequisite:** * `php` 5.5 or above, 7.0 or above * `pecl` * `composer` * `phpunit` (optional) **Install PHP and PECL on Ubuntu/Debian:** For PHP5: ```sh $ sudo apt-get install php5 php5-dev php-pear phpunit ``` For PHP7: ```sh $ sudo apt-get install php7.0 php7.0-dev php-pear phpunit ``` **Install PHP and PECL on CentOS/RHEL 7:** ```sh $ sudo rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm $ sudo rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm $ sudo yum install php56w php56w-devel php-pear phpunit gcc zlib-devel ``` **Install PECL on Mac:** ```sh $ curl -O http://pear.php.net/go-pear.phar $ sudo php -d detect_unicode=0 go-pear.phar ``` **Install Composer (Linux or Mac):** ```sh $ curl -sS https://getcomposer.org/installer | php $ sudo mv composer.phar /usr/local/bin/composer ``` **Install PHPUnit (Linux or Mac):** ```sh $ wget https://phar.phpunit.de/phpunit-old.phar $ chmod +x phpunit-old.phar $ sudo mv phpunit-old.phar /usr/bin/phpunit ``` ## Quick Install **Install the gRPC PHP extension** ```sh sudo pecl install grpc ``` This will compile and install the gRPC PHP extension into the standard PHP extension directory. You should be able to run the [unit tests](#unit-tests), with the PHP extension installed. Note: For users on CentOS/RHEL 6, unfortunately this step won't work. Please follow the instructions below to compile the extension from source. **Update php.ini** Add this line to your `php.ini` file, e.g. `/etc/php5/cli/php.ini` ```sh extension=grpc.so ``` **Add the gRPC PHP library as a Composer dependency** You need to add this to your project's `composer.json` file. ``` "require": { "grpc/grpc": "v1.1.0" } ``` To run tests with generated stub code from `.proto` files, you will also need the `composer` and `protoc` binaries. You can find out how to get these [below](#generated-code-tests). ## Build from Source ### gRPC C core library Clone this repository ```sh $ git clone -b $(curl -L http://grpc.io/release) https://github.com/grpc/grpc ``` Build and install the gRPC C core library ```sh $ cd grpc $ git pull --recurse-submodules && git submodule update --init --recursive $ make $ sudo make install ``` ### gRPC PHP extension Compile the gRPC PHP extension ```sh $ cd grpc/src/php/ext/grpc $ phpize $ ./configure $ make $ sudo make install ``` ## Unit Tests You will need the source code to run tests ```sh $ git clone -b $(curl -L http://grpc.io/release) https://github.com/grpc/grpc $ cd grpc $ git pull --recurse-submodules && git submodule update --init --recursive ``` Run unit tests ```sh $ cd grpc/src/php $ ./bin/run_tests.sh ``` ## Generated Code Tests This section specifies the prerequisites for running the generated code tests, as well as how to run the tests themselves. ### Composer Install the runtime dependencies via `composer install`. ```sh $ cd grpc/src/php $ composer install ``` ### Protobuf compiler Again if you don't have it already, you need to install the protobuf compiler `protoc`, version 3.1.0+ (the newer the better). If `protoc` hasn't been installed, you can download the `protoc` binaries from [the protocol buffers Github repository](https://github.com/google/protobuf/releases). If you really must compile `protoc` from source, you can run the following commands, but this is risky because there is no easy way to uninstall / upgrade to a newer release. ```sh $ cd grpc/third_party/protobuf $ ./autogen.sh && ./configure && make $ sudo make install ``` ### PHP Protoc Plugin You need the gRPC PHP protoc plugin to generate the client stub classes. It should already been compiled when you run `make` from the root directory of this repo. The plugin can be found in the `bins/opt` directory. We are planning to provide a better way to download and install the plugin in the future. You can also just build the gRPC PHP protoc plugin by running: ```sh $ cd grpc $ make grpc_php_plugin ``` ### Client Stub Generate client stub classes from `.proto` files ```sh $ cd grpc/src/php $ ./bin/generate_proto_php.sh ``` ### Run test server Run a local server serving the math services. Please see [Node][] for how to run an example server. ```sh $ cd grpc $ npm install $ node src/node/test/math/math_server.js ``` ### Run test client Run the generated code tests ```sh $ cd grpc/src/php $ ./bin/run_gen_code_test.sh ``` ## Use the gRPC PHP extension with Apache Install `apache2`, in addition to `php5` above ```sh $ sudo apt-get install apache2 ``` Add this line to your `php.ini` file, e.g. `/etc/php5/apache2/php.ini` or `/etc/php/7.0/apache2/php.ini` ```sh extension=grpc.so ``` Restart apache ```sh $ sudo service apache2 restart ``` Make sure the Node math server is still running, as above. ```sh $ cd grpc $ npm install $ node src/node/test/math/math_server.js ``` Make sure you have run `composer install` to generate the `vendor/autoload.php` file ```sh $ cd grpc/src/php $ composer install ``` Make sure you have generated the client stubs ```sh $ ./bin/generate_proto_php.sh ``` Copy the `math_client.php` file into your Apache document root, e.g. ```sh $ cp tests/generated_code/math_client.php /var/www/html ``` You may have to fix the first line to point the includes to your installation: ```php include 'vendor/autoload.php'; ``` Connect to `localhost/math_client.php` in your browser, or run this from command line: ```sh $ curl localhost/math_client.php ``` ## Use the gRPC PHP extension with Nginx/PHP-FPM Install `nginx` and `php5-fpm`, in addition to `php5` above ```sh $ sudo apt-get install nginx php5-fpm OR $ sudo apt-get install nginx php7.0-fpm ``` Add this line to your `php.ini` file, e.g. `/etc/php5/fpm/php.ini` ```sh extension=grpc.so ``` Uncomment the following lines in your `/etc/nginx/sites-available/default` file: ``` location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php5-fpm.sock; } ``` Restart nginx and php-fpm ```sh $ sudo service nginx restart $ sudo service php5-fpm restart ``` Make sure the Node math server is still running, as above. ```sh $ cd grpc $ npm install $ node src/node/test/math/math_server.js ``` Make sure you have run `composer install` to generate the `vendor/autoload.php` file ```sh $ cd grpc/src/php $ composer install ``` Make sure you have generated the client stubs ```sh $ ./bin/generate_proto_php.sh ``` Copy the `math_client.php` file into your Nginx document root, e.g. ```sh $ cp tests/generated_code/math_client.php /var/www/html ``` You may have to fix the first line to point the includes to your installation: ```php include 'vendor/autoload.php'; ``` Connect to `localhost/math_client.php` in your browser, or run this from command line: ```sh $ curl localhost/math_client.php ``` [Node]:https://github.com/grpc/grpc/tree/master/src/node/examples grpc-1.3.2/src/php/bin/000077500000000000000000000000001310511640000145655ustar00rootroot00000000000000grpc-1.3.2/src/php/bin/determine_extension_dir.sh000077500000000000000000000042231310511640000220330ustar00rootroot00000000000000#!/bin/bash # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. set -e default_extension_dir=$(php-config --extension-dir) if [ ! -e $default_extension_dir/grpc.so ]; then # the grpc extension is not found in the default PHP extension dir # try the source modules directory module_dir=$(pwd)/../ext/grpc/modules if [ ! -e $module_dir/grpc.so ]; then echo "Please run 'phpize && ./configure && make' from ext/grpc first" exit 1 fi # sym-link in system supplied extensions for f in $default_extension_dir/*.so; do ln -s $f $module_dir/$(basename $f) &> /dev/null || true done extension_dir="-d extension_dir=${module_dir} -d extension=grpc.so" else extension_dir="-d extension=grpc.so" fi grpc-1.3.2/src/php/bin/generate_proto_php.sh000077500000000000000000000054511310511640000210150ustar00rootroot00000000000000#!/bin/sh # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. set +e cd $(dirname $0)/../../.. protoc --proto_path=src/proto/math \ --php_out=src/php/tests/generated_code \ --grpc_out=src/php/tests/generated_code \ --plugin=protoc-gen-grpc=bins/opt/grpc_php_plugin \ src/proto/math/math.proto # replace the Empty message with EmptyMessage # because Empty is a PHP reserved word output_file=$(mktemp) sed 's/message Empty/message EmptyMessage/g' \ src/proto/grpc/testing/empty.proto > $output_file mv $output_file ./src/proto/grpc/testing/empty.proto sed 's/grpc\.testing\.Empty/grpc\.testing\.EmptyMessage/g' \ src/proto/grpc/testing/test.proto > $output_file mv $output_file ./src/proto/grpc/testing/test.proto protoc --proto_path=. \ --php_out=src/php/tests/interop \ --grpc_out=src/php/tests/interop \ --plugin=protoc-gen-grpc=bins/opt/grpc_php_plugin \ src/proto/grpc/testing/messages.proto \ src/proto/grpc/testing/empty.proto \ src/proto/grpc/testing/test.proto # change it back sed 's/message EmptyMessage/message Empty/g' \ src/proto/grpc/testing/empty.proto > $output_file mv $output_file ./src/proto/grpc/testing/empty.proto sed 's/grpc\.testing\.EmptyMessage/grpc\.testing\.Empty/g' \ src/proto/grpc/testing/test.proto > $output_file mv $output_file ./src/proto/grpc/testing/test.proto grpc-1.3.2/src/php/bin/interop_client.sh000077500000000000000000000032411310511640000201420ustar00rootroot00000000000000#!/bin/bash # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. set -e cd $(dirname $0) source ./determine_extension_dir.sh cd ../tests/interop php $extension_dir -d max_execution_time=300 \ interop_client.php $@ 1>&2 grpc-1.3.2/src/php/bin/run_gen_code_test.sh000077500000000000000000000035511310511640000206160ustar00rootroot00000000000000#!/bin/bash # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. set -e cd $(dirname $0) source ./determine_extension_dir.sh export GRPC_TEST_HOST=localhost:50051 php $extension_dir -d max_execution_time=300 $(which phpunit) -v --debug \ ../tests/generated_code/GeneratedCodeTest.php php $extension_dir -d max_execution_time=300 $(which phpunit) -v --debug \ ../tests/generated_code/GeneratedCodeWithCallbackTest.php grpc-1.3.2/src/php/bin/run_php_cs_fixer.sh000077500000000000000000000034431310511640000204650ustar00rootroot00000000000000#!/bin/bash # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. set -e command -v php-cs-fixer > /dev/null || { echo "Cannot find php-cs-fixer. Exiting..." exit 1 } cd $(dirname $0)/.. php-cs-fixer fix lib/Grpc || true php-cs-fixer fix tests/generated_code || true php-cs-fixer fix tests/interop || true php-cs-fixer fix tests/unit_tests || true grpc-1.3.2/src/php/bin/run_tests.sh000077500000000000000000000036421310511640000171570ustar00rootroot00000000000000#!/bin/bash # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Loads the local shared library, and runs all of the test cases in tests/ # against it set -ex cd $(dirname $0)/../../.. root=$(pwd) cd src/php/bin source ./determine_extension_dir.sh # in some jenkins macos machine, somehow the PHP build script can't find libgrpc.dylib export DYLD_LIBRARY_PATH=$root/libs/$config php $extension_dir -d max_execution_time=300 $(which phpunit) -v --debug \ ../tests/unit_tests grpc-1.3.2/src/php/bin/stress_client.sh000077500000000000000000000032351310511640000200100ustar00rootroot00000000000000#!/bin/bash # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. set -e cd $(dirname $0) source ./determine_extension_dir.sh php $extension_dir -d max_execution_time=300 \ ../tests/interop/stress_client.php $@ 1>&2 grpc-1.3.2/src/php/composer.json000066400000000000000000000006331310511640000165410ustar00rootroot00000000000000{ "name": "grpc/grpc-dev", "description": "gRPC library for PHP - for Developement use only", "license": "BSD-3-Clause", "version": "1.3.2", "require": { "php": ">=5.5.0", "google/protobuf": "^v3.1.0" }, "require-dev": { "google/auth": "v0.9" }, "autoload": { "psr-4": { "Grpc\\": "lib/Grpc/", "": ["tests/interop/", "tests/generated_code/"] } } } grpc-1.3.2/src/php/ext/000077500000000000000000000000001310511640000146155ustar00rootroot00000000000000grpc-1.3.2/src/php/ext/grpc/000077500000000000000000000000001310511640000155505ustar00rootroot00000000000000grpc-1.3.2/src/php/ext/grpc/CREDITS000066400000000000000000000001561310511640000165720ustar00rootroot00000000000000Michael Lumish (mlumish@google.com) Tim Emiola (temiola@google.com) Stanley Cheung (stanleycheung@google.com) grpc-1.3.2/src/php/ext/grpc/LICENSE000066400000000000000000000027051310511640000165610ustar00rootroot00000000000000Copyright 2015, Google Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/php/ext/grpc/byte_buffer.c000066400000000000000000000053271310511640000202170ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "php_grpc.h" #include #include "byte_buffer.h" #include #include #include grpc_byte_buffer *string_to_byte_buffer(char *string, size_t length) { grpc_slice slice = grpc_slice_from_copied_buffer(string, length); grpc_byte_buffer *buffer = grpc_raw_byte_buffer_create(&slice, 1); grpc_slice_unref(slice); return buffer; } void byte_buffer_to_string(grpc_byte_buffer *buffer, char **out_string, size_t *out_length) { grpc_byte_buffer_reader reader; if (buffer == NULL || !grpc_byte_buffer_reader_init(&reader, buffer)) { /* TODO(dgq): distinguish between the error cases. */ *out_string = NULL; *out_length = 0; return; } grpc_slice slice = grpc_byte_buffer_reader_readall(&reader); size_t length = GRPC_SLICE_LENGTH(slice); char *string = ecalloc(length + 1, sizeof(char)); memcpy(string, GRPC_SLICE_START_PTR(slice), length); grpc_slice_unref(slice); *out_string = string; *out_length = length; } grpc-1.3.2/src/php/ext/grpc/byte_buffer.h000066400000000000000000000035731310511640000202250ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef NET_GRPC_PHP_GRPC_BYTE_BUFFER_H_ #define NET_GRPC_PHP_GRPC_BYTE_BUFFER_H_ #include grpc_byte_buffer *string_to_byte_buffer(char *string, size_t length); void byte_buffer_to_string(grpc_byte_buffer *buffer, char **out_string, size_t *out_length); #endif /* NET_GRPC_PHP_GRPC_BYTE_BUFFER_H_ */ grpc-1.3.2/src/php/ext/grpc/call.c000066400000000000000000000534341310511640000166400ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "call.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "php_grpc.h" #include "call_credentials.h" #include #include #include #include #include #include "completion_queue.h" #include "timeval.h" #include "channel.h" #include "byte_buffer.h" zend_class_entry *grpc_ce_call; #if PHP_MAJOR_VERSION >= 7 static zend_object_handlers call_ce_handlers; #endif /* Frees and destroys an instance of wrapped_grpc_call */ PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_call) if (p->owned && p->wrapped != NULL) { grpc_call_destroy(p->wrapped); } PHP_GRPC_FREE_WRAPPED_FUNC_END() /* Initializes an instance of wrapped_grpc_call to be associated with an * object of a class specified by class_type */ php_grpc_zend_object create_wrapped_grpc_call(zend_class_entry *class_type TSRMLS_DC) { PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_call); zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_call, call_ce_handlers); } /* Creates and returns a PHP array object with the data in a * grpc_metadata_array. Returns NULL on failure */ zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array TSRMLS_DC) { int count = metadata_array->count; grpc_metadata *elements = metadata_array->metadata; zval *array; PHP_GRPC_MAKE_STD_ZVAL(array); array_init(array); int i; HashTable *array_hash; zval *inner_array; char *str_key; char *str_val; size_t key_len; zval *data = NULL; array_hash = Z_ARRVAL_P(array); grpc_metadata *elem; for (i = 0; i < count; i++) { elem = &elements[i]; key_len = GRPC_SLICE_LENGTH(elem->key); str_key = ecalloc(key_len + 1, sizeof(char)); memcpy(str_key, GRPC_SLICE_START_PTR(elem->key), key_len); str_val = ecalloc(GRPC_SLICE_LENGTH(elem->value) + 1, sizeof(char)); memcpy(str_val, GRPC_SLICE_START_PTR(elem->value), GRPC_SLICE_LENGTH(elem->value)); if (php_grpc_zend_hash_find(array_hash, str_key, key_len, (void **)&data) == SUCCESS) { if (Z_TYPE_P(data) != IS_ARRAY) { zend_throw_exception(zend_exception_get_default(TSRMLS_C), "Metadata hash somehow contains wrong types.", 1 TSRMLS_CC); efree(str_key); efree(str_val); return NULL; } php_grpc_add_next_index_stringl(data, str_val, GRPC_SLICE_LENGTH(elem->value), false); } else { PHP_GRPC_MAKE_STD_ZVAL(inner_array); array_init(inner_array); php_grpc_add_next_index_stringl(inner_array, str_val, GRPC_SLICE_LENGTH(elem->value), false); add_assoc_zval(array, str_key, inner_array); PHP_GRPC_FREE_STD_ZVAL(inner_array); } efree(str_key); #if PHP_MAJOR_VERSION >= 7 efree(str_val); #endif } return array; } /* Populates a grpc_metadata_array with the data in a PHP array object. Returns true on success and false on failure */ bool create_metadata_array(zval *array, grpc_metadata_array *metadata) { HashTable *array_hash; HashTable *inner_array_hash; zval *value; zval *inner_array; if (Z_TYPE_P(array) != IS_ARRAY) { return false; } grpc_metadata_array_init(metadata); array_hash = Z_ARRVAL_P(array); char *key; int key_type; PHP_GRPC_HASH_FOREACH_STR_KEY_VAL_START(array_hash, key, key_type, inner_array) if (key_type != HASH_KEY_IS_STRING || key == NULL) { return false; } if (Z_TYPE_P(inner_array) != IS_ARRAY) { return false; } inner_array_hash = Z_ARRVAL_P(inner_array); metadata->capacity += zend_hash_num_elements(inner_array_hash); PHP_GRPC_HASH_FOREACH_END() metadata->metadata = gpr_malloc(metadata->capacity * sizeof(grpc_metadata)); char *key1 = NULL; int key_type1; PHP_GRPC_HASH_FOREACH_STR_KEY_VAL_START(array_hash, key1, key_type1, inner_array) if (key_type1 != HASH_KEY_IS_STRING) { return false; } if (!grpc_header_key_is_legal(grpc_slice_from_static_string(key1))) { return false; } inner_array_hash = Z_ARRVAL_P(inner_array); PHP_GRPC_HASH_FOREACH_VAL_START(inner_array_hash, value) if (Z_TYPE_P(value) != IS_STRING) { return false; } metadata->metadata[metadata->count].key = grpc_slice_from_copied_string(key1); metadata->metadata[metadata->count].value = grpc_slice_from_copied_buffer(Z_STRVAL_P(value), Z_STRLEN_P(value)); metadata->count += 1; PHP_GRPC_HASH_FOREACH_END() PHP_GRPC_HASH_FOREACH_END() return true; } /* Wraps a grpc_call struct in a PHP object. Owned indicates whether the struct should be destroyed at the end of the object's lifecycle */ zval *grpc_php_wrap_call(grpc_call *wrapped, bool owned TSRMLS_DC) { zval *call_object; PHP_GRPC_MAKE_STD_ZVAL(call_object); object_init_ex(call_object, grpc_ce_call); wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(call_object); call->wrapped = wrapped; call->owned = owned; return call_object; } /** * Constructs a new instance of the Call class. * @param Channel $channel_obj The channel to associate the call with. * Must not be closed. * @param string $method The method to call * @param Timeval $deadline_obj The deadline for completing the call * @param string $host_override The host is set by user (optional) */ PHP_METHOD(Call, __construct) { zval *channel_obj; char *method; php_grpc_int method_len; zval *deadline_obj; char *host_override = NULL; php_grpc_int host_override_len = 0; wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); /* "OsO|s" == 1 Object, 1 string, 1 Object, 1 optional string */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OsO|s", &channel_obj, grpc_ce_channel, &method, &method_len, &deadline_obj, grpc_ce_timeval, &host_override, &host_override_len) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "Call expects a Channel, a String, a Timeval and " "an optional String", 1 TSRMLS_CC); return; } wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(channel_obj); if (channel->wrapped == NULL) { zend_throw_exception(spl_ce_InvalidArgumentException, "Call cannot be constructed from a closed Channel", 1 TSRMLS_CC); return; } add_property_zval(getThis(), "channel", channel_obj); wrapped_grpc_timeval *deadline = Z_WRAPPED_GRPC_TIMEVAL_P(deadline_obj); grpc_slice method_slice = grpc_slice_from_copied_string(method); grpc_slice host_slice = host_override != NULL ? grpc_slice_from_copied_string(host_override) : grpc_empty_slice(); call->wrapped = grpc_channel_create_call(channel->wrapped, NULL, GRPC_PROPAGATE_DEFAULTS, completion_queue, method_slice, host_override != NULL ? &host_slice : NULL, deadline->wrapped, NULL); grpc_slice_unref(method_slice); grpc_slice_unref(host_slice); call->owned = true; } /** * Start a batch of RPC actions. * @param array $array Array of actions to take * @return object Object with results of all actions */ PHP_METHOD(Call, startBatch) { zval *result; PHP_GRPC_MAKE_STD_ZVAL(result); object_init(result); php_grpc_ulong index; zval *recv_status; zval *value; zval *inner_value; zval *message_value; zval *message_flags; wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); grpc_op ops[8]; size_t op_num = 0; zval *array; HashTable *array_hash; HashTable *status_hash; HashTable *message_hash; grpc_metadata_array metadata; grpc_metadata_array trailing_metadata; grpc_metadata_array recv_metadata; grpc_metadata_array recv_trailing_metadata; grpc_status_code status; grpc_slice recv_status_details = grpc_empty_slice(); grpc_slice send_status_details = grpc_empty_slice(); grpc_byte_buffer *message; int cancelled; grpc_call_error error; char *message_str; size_t message_len; grpc_metadata_array_init(&metadata); grpc_metadata_array_init(&trailing_metadata); grpc_metadata_array_init(&recv_metadata); grpc_metadata_array_init(&recv_trailing_metadata); memset(ops, 0, sizeof(ops)); /* "a" == 1 array */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "start_batch expects an array", 1 TSRMLS_CC); goto cleanup; } array_hash = Z_ARRVAL_P(array); char *key = NULL; int key_type; PHP_GRPC_HASH_FOREACH_LONG_KEY_VAL_START(array_hash, key, key_type, index, value) if (key_type != HASH_KEY_IS_LONG || key != NULL) { zend_throw_exception(spl_ce_InvalidArgumentException, "batch keys must be integers", 1 TSRMLS_CC); goto cleanup; } switch(index) { case GRPC_OP_SEND_INITIAL_METADATA: if (!create_metadata_array(value, &metadata)) { zend_throw_exception(spl_ce_InvalidArgumentException, "Bad metadata value given", 1 TSRMLS_CC); goto cleanup; } ops[op_num].data.send_initial_metadata.count = metadata.count; ops[op_num].data.send_initial_metadata.metadata = metadata.metadata; break; case GRPC_OP_SEND_MESSAGE: if (Z_TYPE_P(value) != IS_ARRAY) { zend_throw_exception(spl_ce_InvalidArgumentException, "Expected an array for send message", 1 TSRMLS_CC); goto cleanup; } message_hash = Z_ARRVAL_P(value); if (php_grpc_zend_hash_find(message_hash, "flags", sizeof("flags"), (void **)&message_flags) == SUCCESS) { if (Z_TYPE_P(message_flags) != IS_LONG) { zend_throw_exception(spl_ce_InvalidArgumentException, "Expected an int for message flags", 1 TSRMLS_CC); } ops[op_num].flags = Z_LVAL_P(message_flags) & GRPC_WRITE_USED_MASK; } if (php_grpc_zend_hash_find(message_hash, "message", sizeof("message"), (void **)&message_value) != SUCCESS || Z_TYPE_P(message_value) != IS_STRING) { zend_throw_exception(spl_ce_InvalidArgumentException, "Expected a string for send message", 1 TSRMLS_CC); goto cleanup; } ops[op_num].data.send_message.send_message = string_to_byte_buffer(Z_STRVAL_P(message_value), Z_STRLEN_P(message_value)); break; case GRPC_OP_SEND_CLOSE_FROM_CLIENT: break; case GRPC_OP_SEND_STATUS_FROM_SERVER: status_hash = Z_ARRVAL_P(value); if (php_grpc_zend_hash_find(status_hash, "metadata", sizeof("metadata"), (void **)&inner_value) == SUCCESS) { if (!create_metadata_array(inner_value, &trailing_metadata)) { zend_throw_exception(spl_ce_InvalidArgumentException, "Bad trailing metadata value given", 1 TSRMLS_CC); goto cleanup; } ops[op_num].data.send_status_from_server.trailing_metadata = trailing_metadata.metadata; ops[op_num].data.send_status_from_server.trailing_metadata_count = trailing_metadata.count; } if (php_grpc_zend_hash_find(status_hash, "code", sizeof("code"), (void**)&inner_value) == SUCCESS) { if (Z_TYPE_P(inner_value) != IS_LONG) { zend_throw_exception(spl_ce_InvalidArgumentException, "Status code must be an integer", 1 TSRMLS_CC); goto cleanup; } ops[op_num].data.send_status_from_server.status = Z_LVAL_P(inner_value); } else { zend_throw_exception(spl_ce_InvalidArgumentException, "Integer status code is required", 1 TSRMLS_CC); goto cleanup; } if (php_grpc_zend_hash_find(status_hash, "details", sizeof("details"), (void**)&inner_value) == SUCCESS) { if (Z_TYPE_P(inner_value) != IS_STRING) { zend_throw_exception(spl_ce_InvalidArgumentException, "Status details must be a string", 1 TSRMLS_CC); goto cleanup; } send_status_details = grpc_slice_from_copied_string( Z_STRVAL_P(inner_value)); ops[op_num].data.send_status_from_server.status_details = &send_status_details; } else { zend_throw_exception(spl_ce_InvalidArgumentException, "String status details is required", 1 TSRMLS_CC); goto cleanup; } break; case GRPC_OP_RECV_INITIAL_METADATA: ops[op_num].data.recv_initial_metadata.recv_initial_metadata = &recv_metadata; break; case GRPC_OP_RECV_MESSAGE: ops[op_num].data.recv_message.recv_message = &message; break; case GRPC_OP_RECV_STATUS_ON_CLIENT: ops[op_num].data.recv_status_on_client.trailing_metadata = &recv_trailing_metadata; ops[op_num].data.recv_status_on_client.status = &status; ops[op_num].data.recv_status_on_client.status_details = &recv_status_details; break; case GRPC_OP_RECV_CLOSE_ON_SERVER: ops[op_num].data.recv_close_on_server.cancelled = &cancelled; break; default: zend_throw_exception(spl_ce_InvalidArgumentException, "Unrecognized key in batch", 1 TSRMLS_CC); goto cleanup; } ops[op_num].op = (grpc_op_type)index; ops[op_num].flags = 0; ops[op_num].reserved = NULL; op_num++; PHP_GRPC_HASH_FOREACH_END() error = grpc_call_start_batch(call->wrapped, ops, op_num, call->wrapped, NULL); if (error != GRPC_CALL_OK) { zend_throw_exception(spl_ce_LogicException, "start_batch was called incorrectly", (long)error TSRMLS_CC); goto cleanup; } grpc_completion_queue_pluck(completion_queue, call->wrapped, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); #if PHP_MAJOR_VERSION >= 7 zval *recv_md; #endif for (int i = 0; i < op_num; i++) { switch(ops[i].op) { case GRPC_OP_SEND_INITIAL_METADATA: add_property_bool(result, "send_metadata", true); break; case GRPC_OP_SEND_MESSAGE: add_property_bool(result, "send_message", true); break; case GRPC_OP_SEND_CLOSE_FROM_CLIENT: add_property_bool(result, "send_close", true); break; case GRPC_OP_SEND_STATUS_FROM_SERVER: add_property_bool(result, "send_status", true); break; case GRPC_OP_RECV_INITIAL_METADATA: #if PHP_MAJOR_VERSION < 7 array = grpc_parse_metadata_array(&recv_metadata TSRMLS_CC); add_property_zval(result, "metadata", array); #else recv_md = grpc_parse_metadata_array(&recv_metadata); add_property_zval(result, "metadata", recv_md); zval_ptr_dtor(recv_md); PHP_GRPC_FREE_STD_ZVAL(recv_md); #endif PHP_GRPC_DELREF(array); break; case GRPC_OP_RECV_MESSAGE: byte_buffer_to_string(message, &message_str, &message_len); if (message_str == NULL) { add_property_null(result, "message"); } else { php_grpc_add_property_stringl(result, "message", message_str, message_len, false); } break; case GRPC_OP_RECV_STATUS_ON_CLIENT: PHP_GRPC_MAKE_STD_ZVAL(recv_status); object_init(recv_status); #if PHP_MAJOR_VERSION < 7 array = grpc_parse_metadata_array(&recv_trailing_metadata TSRMLS_CC); add_property_zval(recv_status, "metadata", array); #else recv_md = grpc_parse_metadata_array(&recv_trailing_metadata); add_property_zval(recv_status, "metadata", recv_md); zval_ptr_dtor(recv_md); PHP_GRPC_FREE_STD_ZVAL(recv_md); #endif PHP_GRPC_DELREF(array); add_property_long(recv_status, "code", status); char *status_details_text = grpc_slice_to_c_string(recv_status_details); php_grpc_add_property_string(recv_status, "details", status_details_text, true); gpr_free(status_details_text); add_property_zval(result, "status", recv_status); #if PHP_MAJOR_VERSION >= 7 zval_ptr_dtor(recv_status); #endif PHP_GRPC_DELREF(recv_status); PHP_GRPC_FREE_STD_ZVAL(recv_status); break; case GRPC_OP_RECV_CLOSE_ON_SERVER: add_property_bool(result, "cancelled", cancelled); break; default: break; } } cleanup: grpc_metadata_array_destroy(&metadata); grpc_metadata_array_destroy(&trailing_metadata); grpc_metadata_array_destroy(&recv_metadata); grpc_metadata_array_destroy(&recv_trailing_metadata); grpc_slice_unref(recv_status_details); grpc_slice_unref(send_status_details); for (int i = 0; i < op_num; i++) { if (ops[i].op == GRPC_OP_SEND_MESSAGE) { grpc_byte_buffer_destroy(ops[i].data.send_message.send_message); } if (ops[i].op == GRPC_OP_RECV_MESSAGE) { grpc_byte_buffer_destroy(message); PHP_GRPC_FREE_STD_ZVAL(message_str); } } RETURN_DESTROY_ZVAL(result); } /** * Get the endpoint this call/stream is connected to * @return string The URI of the endpoint */ PHP_METHOD(Call, getPeer) { wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); PHP_GRPC_RETURN_STRING(grpc_call_get_peer(call->wrapped), 1); } /** * Cancel the call. This will cause the call to end with STATUS_CANCELLED * if it has not already ended with another status. * @return void */ PHP_METHOD(Call, cancel) { wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); grpc_call_cancel(call->wrapped, NULL); } /** * Set the CallCredentials for this call. * @param CallCredentials $creds_obj The CallCredentials object * @return int The error code */ PHP_METHOD(Call, setCredentials) { zval *creds_obj; /* "O" == 1 Object */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &creds_obj, grpc_ce_call_credentials) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "setCredentials expects 1 CallCredentials", 1 TSRMLS_CC); return; } wrapped_grpc_call_credentials *creds = Z_WRAPPED_GRPC_CALL_CREDS_P(creds_obj); wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); grpc_call_error error = GRPC_CALL_ERROR; error = grpc_call_set_credentials(call->wrapped, creds->wrapped); RETURN_LONG(error); } ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 3) ZEND_ARG_INFO(0, channel) ZEND_ARG_INFO(0, method) ZEND_ARG_INFO(0, deadline) ZEND_ARG_INFO(0, host_override) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_startBatch, 0, 0, 1) ZEND_ARG_INFO(0, ops) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getPeer, 0, 0, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_cancel, 0, 0, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_setCredentials, 0, 0, 1) ZEND_ARG_INFO(0, credentials) ZEND_END_ARG_INFO() static zend_function_entry call_methods[] = { PHP_ME(Call, __construct, arginfo_construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) PHP_ME(Call, startBatch, arginfo_startBatch, ZEND_ACC_PUBLIC) PHP_ME(Call, getPeer, arginfo_getPeer, ZEND_ACC_PUBLIC) PHP_ME(Call, cancel, arginfo_cancel, ZEND_ACC_PUBLIC) PHP_ME(Call, setCredentials, arginfo_setCredentials, ZEND_ACC_PUBLIC) PHP_FE_END }; void grpc_init_call(TSRMLS_D) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "Grpc\\Call", call_methods); ce.create_object = create_wrapped_grpc_call; grpc_ce_call = zend_register_internal_class(&ce TSRMLS_CC); PHP_GRPC_INIT_HANDLER(wrapped_grpc_call, call_ce_handlers); } grpc-1.3.2/src/php/ext/grpc/call.h000066400000000000000000000061151310511640000166370ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef NET_GRPC_PHP_GRPC_CALL_H_ #define NET_GRPC_PHP_GRPC_CALL_H_ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "php_grpc.h" #include /* Class entry for the Call PHP class */ extern zend_class_entry *grpc_ce_call; /* Wrapper struct for grpc_call that can be associated with a PHP object */ PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_call) bool owned; grpc_call *wrapped; PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_call) #if PHP_MAJOR_VERSION < 7 #define Z_WRAPPED_GRPC_CALL_P(zv) \ (wrapped_grpc_call *)zend_object_store_get_object(zv TSRMLS_CC) #else static inline wrapped_grpc_call *wrapped_grpc_call_from_obj(zend_object *obj) { return (wrapped_grpc_call*)((char*)(obj) - XtOffsetOf(wrapped_grpc_call, std)); } #define Z_WRAPPED_GRPC_CALL_P(zv) wrapped_grpc_call_from_obj(Z_OBJ_P((zv))) #endif /* PHP_MAJOR_VERSION */ /* Creates and returns a PHP associative array of metadata from a C array of * call metadata */ zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array TSRMLS_DC); /* Creates a Call object that wraps the given grpc_call struct */ zval *grpc_php_wrap_call(grpc_call *wrapped, bool owned TSRMLS_DC); /* Initializes the Call PHP class */ void grpc_init_call(TSRMLS_D); /* Populates a grpc_metadata_array with the data in a PHP array object. Returns true on success and false on failure */ bool create_metadata_array(zval *array, grpc_metadata_array *metadata); #endif /* NET_GRPC_PHP_GRPC_CHANNEL_H_ */ grpc-1.3.2/src/php/ext/grpc/call_credentials.c000066400000000000000000000214751310511640000212150ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "channel_credentials.h" #include "call_credentials.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "php_grpc.h" #include "call.h" #include #include #include #include zend_class_entry *grpc_ce_call_credentials; #if PHP_MAJOR_VERSION >= 7 static zend_object_handlers call_credentials_ce_handlers; #endif /* Frees and destroys an instance of wrapped_grpc_call_credentials */ PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_call_credentials) if (p->wrapped != NULL) { grpc_call_credentials_release(p->wrapped); } PHP_GRPC_FREE_WRAPPED_FUNC_END() /* Initializes an instance of wrapped_grpc_call_credentials to be * associated with an object of a class specified by class_type */ php_grpc_zend_object create_wrapped_grpc_call_credentials( zend_class_entry *class_type TSRMLS_DC) { PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_call_credentials); zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_call_credentials, call_credentials_ce_handlers); } zval *grpc_php_wrap_call_credentials(grpc_call_credentials *wrapped TSRMLS_DC) { zval *credentials_object; PHP_GRPC_MAKE_STD_ZVAL(credentials_object); object_init_ex(credentials_object, grpc_ce_call_credentials); wrapped_grpc_call_credentials *credentials = Z_WRAPPED_GRPC_CALL_CREDS_P(credentials_object); credentials->wrapped = wrapped; return credentials_object; } /** * Create composite credentials from two existing credentials. * @param CallCredentials $cred1_obj The first credential * @param CallCredentials $cred2_obj The second credential * @return CallCredentials The new composite credentials object */ PHP_METHOD(CallCredentials, createComposite) { zval *cred1_obj; zval *cred2_obj; /* "OO" == 2 Objects */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &cred1_obj, grpc_ce_call_credentials, &cred2_obj, grpc_ce_call_credentials) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "createComposite expects 2 CallCredentials", 1 TSRMLS_CC); return; } wrapped_grpc_call_credentials *cred1 = Z_WRAPPED_GRPC_CALL_CREDS_P(cred1_obj); wrapped_grpc_call_credentials *cred2 = Z_WRAPPED_GRPC_CALL_CREDS_P(cred2_obj); grpc_call_credentials *creds = grpc_composite_call_credentials_create(cred1->wrapped, cred2->wrapped, NULL); zval *creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); } /** * Create a call credentials object from the plugin API * @param function $fci The callback function * @return CallCredentials The new call credentials object */ PHP_METHOD(CallCredentials, createFromPlugin) { zend_fcall_info *fci; zend_fcall_info_cache *fci_cache; fci = (zend_fcall_info *)emalloc(sizeof(zend_fcall_info)); fci_cache = (zend_fcall_info_cache *)emalloc(sizeof(zend_fcall_info_cache)); memset(fci, 0, sizeof(zend_fcall_info)); memset(fci_cache, 0, sizeof(zend_fcall_info_cache)); /* "f" == 1 function */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f*", fci, fci_cache, fci->params, fci->param_count) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "createFromPlugin expects 1 callback", 1 TSRMLS_CC); return; } plugin_state *state; state = (plugin_state *)emalloc(sizeof(plugin_state)); memset(state, 0, sizeof(plugin_state)); /* save the user provided PHP callback function */ state->fci = fci; state->fci_cache = fci_cache; grpc_metadata_credentials_plugin plugin; plugin.get_metadata = plugin_get_metadata; plugin.destroy = plugin_destroy_state; plugin.state = (void *)state; plugin.type = ""; grpc_call_credentials *creds = grpc_metadata_credentials_create_from_plugin(plugin, NULL); zval *creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); } /* Callback function for plugin creds API */ void plugin_get_metadata(void *ptr, grpc_auth_metadata_context context, grpc_credentials_plugin_metadata_cb cb, void *user_data) { TSRMLS_FETCH(); plugin_state *state = (plugin_state *)ptr; /* prepare to call the user callback function with info from the * grpc_auth_metadata_context */ zval *arg; PHP_GRPC_MAKE_STD_ZVAL(arg); object_init(arg); php_grpc_add_property_string(arg, "service_url", context.service_url, true); php_grpc_add_property_string(arg, "method_name", context.method_name, true); zval *retval = NULL; #if PHP_MAJOR_VERSION < 7 zval **params[1]; params[0] = &arg; state->fci->params = params; state->fci->retval_ptr_ptr = &retval; #else PHP_GRPC_MAKE_STD_ZVAL(retval); state->fci->params = arg; state->fci->retval = retval; #endif state->fci->param_count = 1; PHP_GRPC_DELREF(arg); /* call the user callback function */ zend_call_function(state->fci, state->fci_cache TSRMLS_CC); grpc_status_code code = GRPC_STATUS_OK; grpc_metadata_array metadata; bool cleanup = true; if (Z_TYPE_P(retval) != IS_ARRAY) { cleanup = false; code = GRPC_STATUS_INVALID_ARGUMENT; } else if (!create_metadata_array(retval, &metadata)) { code = GRPC_STATUS_INVALID_ARGUMENT; } if (retval != NULL) { #if PHP_MAJOR_VERSION < 7 zval_ptr_dtor(&retval); #else zval_ptr_dtor(arg); zval_ptr_dtor(retval); PHP_GRPC_FREE_STD_ZVAL(arg); PHP_GRPC_FREE_STD_ZVAL(retval); #endif } /* Pass control back to core */ cb(user_data, metadata.metadata, metadata.count, code, NULL); if (cleanup) { for (int i = 0; i < metadata.count; i++) { grpc_slice_unref(metadata.metadata[i].value); } grpc_metadata_array_destroy(&metadata); } } /* Cleanup function for plugin creds API */ void plugin_destroy_state(void *ptr) { plugin_state *state = (plugin_state *)ptr; efree(state->fci); efree(state->fci_cache); #if PHP_MAJOR_VERSION < 7 PHP_GRPC_FREE_STD_ZVAL(state->fci->params); PHP_GRPC_FREE_STD_ZVAL(state->fci->retval); #endif efree(state); } ZEND_BEGIN_ARG_INFO_EX(arginfo_createComposite, 0, 0, 2) ZEND_ARG_INFO(0, creds1) ZEND_ARG_INFO(0, creds2) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_createFromPlugin, 0, 0, 1) ZEND_ARG_INFO(0, callback) ZEND_END_ARG_INFO() static zend_function_entry call_credentials_methods[] = { PHP_ME(CallCredentials, createComposite, arginfo_createComposite, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(CallCredentials, createFromPlugin, arginfo_createFromPlugin, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_FE_END }; void grpc_init_call_credentials(TSRMLS_D) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "Grpc\\CallCredentials", call_credentials_methods); ce.create_object = create_wrapped_grpc_call_credentials; grpc_ce_call_credentials = zend_register_internal_class(&ce TSRMLS_CC); PHP_GRPC_INIT_HANDLER(wrapped_grpc_call_credentials, call_credentials_ce_handlers); } grpc-1.3.2/src/php/ext/grpc/call_credentials.h000077500000000000000000000064031310511640000212170ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef NET_GRPC_PHP_GRPC_CALL_CREDENTIALS_H_ #define NET_GRPC_PHP_GRPC_CALL_CREDENTIALS_H_ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "php_grpc.h" #include "grpc/grpc.h" #include "grpc/grpc_security.h" /* Class entry for the CallCredentials PHP class */ extern zend_class_entry *grpc_ce_call_credentials; /* Wrapper struct for grpc_call_credentials that can be associated * with a PHP object */ PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_call_credentials) grpc_call_credentials *wrapped; PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_call_credentials) #if PHP_MAJOR_VERSION < 7 #define Z_WRAPPED_GRPC_CALL_CREDS_P(zv) \ (wrapped_grpc_call_credentials *)zend_object_store_get_object(zv TSRMLS_CC) #else static inline wrapped_grpc_call_credentials *wrapped_grpc_call_credentials_from_obj(zend_object *obj) { return (wrapped_grpc_call_credentials*)( (char*)(obj) - XtOffsetOf(wrapped_grpc_call_credentials, std)); } #define Z_WRAPPED_GRPC_CALL_CREDS_P(zv) \ wrapped_grpc_call_credentials_from_obj(Z_OBJ_P((zv))) #endif /* PHP_MAJOR_VERSION */ /* Struct to hold callback function for plugin creds API */ typedef struct plugin_state { zend_fcall_info *fci; zend_fcall_info_cache *fci_cache; } plugin_state; /* Callback function for plugin creds API */ void plugin_get_metadata(void *state, grpc_auth_metadata_context context, grpc_credentials_plugin_metadata_cb cb, void *user_data); /* Cleanup function for plugin creds API */ void plugin_destroy_state(void *ptr); /* Initializes the CallCredentials PHP class */ void grpc_init_call_credentials(TSRMLS_D); #endif /* NET_GRPC_PHP_GRPC_CALL_CREDENTIALS_H_ */ grpc-1.3.2/src/php/ext/grpc/channel.c000066400000000000000000000237031310511640000173310ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "channel.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "php_grpc.h" #include #include #include #include #include "completion_queue.h" #include "channel_credentials.h" #include "server.h" #include "timeval.h" zend_class_entry *grpc_ce_channel; #if PHP_MAJOR_VERSION >= 7 static zend_object_handlers channel_ce_handlers; #endif /* Frees and destroys an instance of wrapped_grpc_channel */ PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_channel) if (p->wrapped != NULL) { grpc_channel_destroy(p->wrapped); } PHP_GRPC_FREE_WRAPPED_FUNC_END() /* Initializes an instance of wrapped_grpc_channel to be associated with an * object of a class specified by class_type */ php_grpc_zend_object create_wrapped_grpc_channel(zend_class_entry *class_type TSRMLS_DC) { PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_channel); zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_channel, channel_ce_handlers); } void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args TSRMLS_DC) { HashTable *array_hash; int args_index; array_hash = Z_ARRVAL_P(args_array); if (!array_hash) { zend_throw_exception(spl_ce_InvalidArgumentException, "array_hash is NULL", 1 TSRMLS_CC); return; } args->num_args = zend_hash_num_elements(array_hash); args->args = ecalloc(args->num_args, sizeof(grpc_arg)); args_index = 0; char *key = NULL; zval *data; int key_type; PHP_GRPC_HASH_FOREACH_STR_KEY_VAL_START(array_hash, key, key_type, data) if (key_type != HASH_KEY_IS_STRING) { zend_throw_exception(spl_ce_InvalidArgumentException, "args keys must be strings", 1 TSRMLS_CC); return; } args->args[args_index].key = key; switch (Z_TYPE_P(data)) { case IS_LONG: args->args[args_index].value.integer = (int)Z_LVAL_P(data); args->args[args_index].type = GRPC_ARG_INTEGER; break; case IS_STRING: args->args[args_index].value.string = Z_STRVAL_P(data); args->args[args_index].type = GRPC_ARG_STRING; break; default: zend_throw_exception(spl_ce_InvalidArgumentException, "args values must be int or string", 1 TSRMLS_CC); return; } args_index++; PHP_GRPC_HASH_FOREACH_END() } /** * Construct an instance of the Channel class. If the $args array contains a * "credentials" key mapping to a ChannelCredentials object, a secure channel * will be created with those credentials. * @param string $target The hostname to associate with this channel * @param array $args_array The arguments to pass to the Channel */ PHP_METHOD(Channel, __construct) { wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); zval *creds_obj = NULL; char *target; php_grpc_int target_length; zval *args_array = NULL; grpc_channel_args args; HashTable *array_hash; wrapped_grpc_channel_credentials *creds = NULL; /* "sa" == 1 string, 1 array */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa", &target, &target_length, &args_array) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "Channel expects a string and an array", 1 TSRMLS_CC); return; } array_hash = Z_ARRVAL_P(args_array); if (php_grpc_zend_hash_find(array_hash, "credentials", sizeof("credentials"), (void **)&creds_obj) == SUCCESS) { if (Z_TYPE_P(creds_obj) == IS_NULL) { creds = NULL; php_grpc_zend_hash_del(array_hash, "credentials", sizeof("credentials")); } else if (PHP_GRPC_GET_CLASS_ENTRY(creds_obj) != grpc_ce_channel_credentials) { zend_throw_exception(spl_ce_InvalidArgumentException, "credentials must be a ChannelCredentials object", 1 TSRMLS_CC); return; } else { creds = Z_WRAPPED_GRPC_CHANNEL_CREDS_P(creds_obj); php_grpc_zend_hash_del(array_hash, "credentials", sizeof("credentials")); } } php_grpc_read_args_array(args_array, &args TSRMLS_CC); if (creds == NULL) { channel->wrapped = grpc_insecure_channel_create(target, &args, NULL); } else { channel->wrapped = grpc_secure_channel_create(creds->wrapped, target, &args, NULL); } efree(args.args); } /** * Get the endpoint this call/stream is connected to * @return string The URI of the endpoint */ PHP_METHOD(Channel, getTarget) { wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); PHP_GRPC_RETURN_STRING(grpc_channel_get_target(channel->wrapped), 1); } /** * Get the connectivity state of the channel * @param bool $try_to_connect Try to connect on the channel (optional) * @return long The grpc connectivity state */ PHP_METHOD(Channel, getConnectivityState) { wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); bool try_to_connect = false; /* "|b" == 1 optional bool */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &try_to_connect) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "getConnectivityState expects a bool", 1 TSRMLS_CC); return; } RETURN_LONG(grpc_channel_check_connectivity_state(channel->wrapped, (int)try_to_connect)); } /** * Watch the connectivity state of the channel until it changed * @param long $last_state The previous connectivity state of the channel * @param Timeval $deadline_obj The deadline this function should wait until * @return bool If the connectivity state changes from last_state * before deadline */ PHP_METHOD(Channel, watchConnectivityState) { wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); php_grpc_long last_state; zval *deadline_obj; /* "lO" == 1 long 1 object */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lO", &last_state, &deadline_obj, grpc_ce_timeval) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "watchConnectivityState expects 1 long 1 timeval", 1 TSRMLS_CC); return; } wrapped_grpc_timeval *deadline = Z_WRAPPED_GRPC_TIMEVAL_P(deadline_obj); grpc_channel_watch_connectivity_state(channel->wrapped, (grpc_connectivity_state)last_state, deadline->wrapped, completion_queue, NULL); grpc_event event = grpc_completion_queue_pluck(completion_queue, NULL, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); RETURN_BOOL(event.success); } /** * Close the channel * @return void */ PHP_METHOD(Channel, close) { wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); if (channel->wrapped != NULL) { grpc_channel_destroy(channel->wrapped); channel->wrapped = NULL; } } ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 2) ZEND_ARG_INFO(0, target) ZEND_ARG_INFO(0, args) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getTarget, 0, 0, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_getConnectivityState, 0, 0, 0) ZEND_ARG_INFO(0, try_to_connect) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_watchConnectivityState, 0, 0, 2) ZEND_ARG_INFO(0, last_state) ZEND_ARG_INFO(0, deadline) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_close, 0, 0, 0) ZEND_END_ARG_INFO() static zend_function_entry channel_methods[] = { PHP_ME(Channel, __construct, arginfo_construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) PHP_ME(Channel, getTarget, arginfo_getTarget, ZEND_ACC_PUBLIC) PHP_ME(Channel, getConnectivityState, arginfo_getConnectivityState, ZEND_ACC_PUBLIC) PHP_ME(Channel, watchConnectivityState, arginfo_watchConnectivityState, ZEND_ACC_PUBLIC) PHP_ME(Channel, close, arginfo_close, ZEND_ACC_PUBLIC) PHP_FE_END }; void grpc_init_channel(TSRMLS_D) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "Grpc\\Channel", channel_methods); ce.create_object = create_wrapped_grpc_channel; grpc_ce_channel = zend_register_internal_class(&ce TSRMLS_CC); PHP_GRPC_INIT_HANDLER(wrapped_grpc_channel, channel_ce_handlers); } grpc-1.3.2/src/php/ext/grpc/channel.h000077500000000000000000000054661310511640000173470ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef NET_GRPC_PHP_GRPC_CHANNEL_H_ #define NET_GRPC_PHP_GRPC_CHANNEL_H_ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "php_grpc.h" #include /* Class entry for the PHP Channel class */ extern zend_class_entry *grpc_ce_channel; /* Wrapper struct for grpc_channel that can be associated with a PHP object */ PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_channel) grpc_channel *wrapped; PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_channel) #if PHP_MAJOR_VERSION < 7 #define Z_WRAPPED_GRPC_CHANNEL_P(zv) \ (wrapped_grpc_channel *)zend_object_store_get_object(zv TSRMLS_CC) #else static inline wrapped_grpc_channel *wrapped_grpc_channel_from_obj(zend_object *obj) { return (wrapped_grpc_channel*)((char*)(obj) - XtOffsetOf(wrapped_grpc_channel, std)); } #define Z_WRAPPED_GRPC_CHANNEL_P(zv) \ wrapped_grpc_channel_from_obj(Z_OBJ_P((zv))) #endif /* PHP_MAJOR_VERSION */ /* Initializes the Channel class */ void grpc_init_channel(TSRMLS_D); /* Iterates through a PHP array and populates args with the contents */ void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args TSRMLS_DC); #endif /* NET_GRPC_PHP_GRPC_CHANNEL_H_ */ grpc-1.3.2/src/php/ext/grpc/channel_credentials.c000066400000000000000000000222441310511640000217050ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "channel_credentials.h" #include "call_credentials.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "php_grpc.h" #include #include #include #include #include zend_class_entry *grpc_ce_channel_credentials; #if PHP_MAJOR_VERSION >= 7 static zend_object_handlers channel_credentials_ce_handlers; #endif static char *default_pem_root_certs = NULL; static grpc_ssl_roots_override_result get_ssl_roots_override( char **pem_root_certs) { *pem_root_certs = default_pem_root_certs; if (default_pem_root_certs == NULL) { return GRPC_SSL_ROOTS_OVERRIDE_FAIL; } return GRPC_SSL_ROOTS_OVERRIDE_OK; } /* Frees and destroys an instance of wrapped_grpc_channel_credentials */ PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_channel_credentials) if (p->wrapped != NULL) { grpc_channel_credentials_release(p->wrapped); } PHP_GRPC_FREE_WRAPPED_FUNC_END() /* Initializes an instance of wrapped_grpc_channel_credentials to be * associated with an object of a class specified by class_type */ php_grpc_zend_object create_wrapped_grpc_channel_credentials( zend_class_entry *class_type TSRMLS_DC) { PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_channel_credentials); zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_channel_credentials, channel_credentials_ce_handlers); } zval *grpc_php_wrap_channel_credentials(grpc_channel_credentials *wrapped TSRMLS_DC) { zval *credentials_object; PHP_GRPC_MAKE_STD_ZVAL(credentials_object); object_init_ex(credentials_object, grpc_ce_channel_credentials); wrapped_grpc_channel_credentials *credentials = Z_WRAPPED_GRPC_CHANNEL_CREDS_P(credentials_object); credentials->wrapped = wrapped; return credentials_object; } /** * Set default roots pem. * @param string $pem_roots PEM encoding of the server root certificates * @return void */ PHP_METHOD(ChannelCredentials, setDefaultRootsPem) { char *pem_roots; php_grpc_int pem_roots_length; /* "s" == 1 string */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &pem_roots, &pem_roots_length) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "setDefaultRootsPem expects 1 string", 1 TSRMLS_CC); return; } default_pem_root_certs = gpr_malloc((pem_roots_length + 1) * sizeof(char)); memcpy(default_pem_root_certs, pem_roots, pem_roots_length + 1); } /** * Create a default channel credentials object. * @return ChannelCredentials The new default channel credentials object */ PHP_METHOD(ChannelCredentials, createDefault) { grpc_channel_credentials *creds = grpc_google_default_credentials_create(); zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); } /** * Create SSL credentials. * @param string $pem_root_certs PEM encoding of the server root certificates * @param string $pem_key_cert_pair.private_key PEM encoding of the client's * private key (optional) * @param string $pem_key_cert_pair.cert_chain PEM encoding of the client's * certificate chain (optional) * @return ChannelCredentials The new SSL credentials object */ PHP_METHOD(ChannelCredentials, createSsl) { char *pem_root_certs = NULL; grpc_ssl_pem_key_cert_pair pem_key_cert_pair; php_grpc_int root_certs_length = 0; php_grpc_int private_key_length = 0; php_grpc_int cert_chain_length = 0; pem_key_cert_pair.private_key = pem_key_cert_pair.cert_chain = NULL; /* "|s!s!s!" == 3 optional nullable strings */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!s!s!", &pem_root_certs, &root_certs_length, &pem_key_cert_pair.private_key, &private_key_length, &pem_key_cert_pair.cert_chain, &cert_chain_length) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "createSsl expects 3 optional strings", 1 TSRMLS_CC); return; } grpc_channel_credentials *creds = grpc_ssl_credentials_create( pem_root_certs, pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair, NULL); zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); } /** * Create composite credentials from two existing credentials. * @param ChannelCredentials $cred1_obj The first credential * @param CallCredentials $cred2_obj The second credential * @return ChannelCredentials The new composite credentials object */ PHP_METHOD(ChannelCredentials, createComposite) { zval *cred1_obj; zval *cred2_obj; /* "OO" == 2 Objects */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &cred1_obj, grpc_ce_channel_credentials, &cred2_obj, grpc_ce_call_credentials) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "createComposite expects 2 Credentials", 1 TSRMLS_CC); return; } wrapped_grpc_channel_credentials *cred1 = Z_WRAPPED_GRPC_CHANNEL_CREDS_P(cred1_obj); wrapped_grpc_call_credentials *cred2 = Z_WRAPPED_GRPC_CALL_CREDS_P(cred2_obj); grpc_channel_credentials *creds = grpc_composite_channel_credentials_create(cred1->wrapped, cred2->wrapped, NULL); zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); } /** * Create insecure channel credentials * @return null */ PHP_METHOD(ChannelCredentials, createInsecure) { RETURN_NULL(); } ZEND_BEGIN_ARG_INFO_EX(arginfo_setDefaultRootsPem, 0, 0, 1) ZEND_ARG_INFO(0, pem_roots) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_createDefault, 0, 0, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_createSsl, 0, 0, 0) ZEND_ARG_INFO(0, pem_root_certs) ZEND_ARG_INFO(0, pem_private_key) ZEND_ARG_INFO(0, pem_cert_chain) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_createComposite, 0, 0, 2) ZEND_ARG_INFO(0, channel_creds) ZEND_ARG_INFO(0, call_creds) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_createInsecure, 0, 0, 0) ZEND_END_ARG_INFO() static zend_function_entry channel_credentials_methods[] = { PHP_ME(ChannelCredentials, setDefaultRootsPem, arginfo_setDefaultRootsPem, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(ChannelCredentials, createDefault, arginfo_createDefault, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(ChannelCredentials, createSsl, arginfo_createSsl, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(ChannelCredentials, createComposite, arginfo_createComposite, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(ChannelCredentials, createInsecure, arginfo_createInsecure, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_FE_END }; void grpc_init_channel_credentials(TSRMLS_D) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "Grpc\\ChannelCredentials", channel_credentials_methods); grpc_set_ssl_roots_override_callback(get_ssl_roots_override); ce.create_object = create_wrapped_grpc_channel_credentials; grpc_ce_channel_credentials = zend_register_internal_class(&ce TSRMLS_CC); PHP_GRPC_INIT_HANDLER(wrapped_grpc_channel_credentials, channel_credentials_ce_handlers); } grpc-1.3.2/src/php/ext/grpc/channel_credentials.h000077500000000000000000000055401310511640000217150ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef NET_GRPC_PHP_GRPC_CHANNEL_CREDENTIALS_H_ #define NET_GRPC_PHP_GRPC_CHANNEL_CREDENTIALS_H_ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "php_grpc.h" #include "grpc/grpc.h" #include "grpc/grpc_security.h" /* Class entry for the ChannelCredentials PHP class */ extern zend_class_entry *grpc_ce_channel_credentials; /* Wrapper struct for grpc_channel_credentials that can be associated * with a PHP object */ PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_channel_credentials) grpc_channel_credentials *wrapped; PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_channel_credentials) #if PHP_MAJOR_VERSION < 7 #define Z_WRAPPED_GRPC_CHANNEL_CREDS_P(zv) \ (wrapped_grpc_channel_credentials *)zend_object_store_get_object(zv TSRMLS_CC) #else static inline wrapped_grpc_channel_credentials *wrapped_grpc_channel_credentials_from_obj(zend_object *obj) { return (wrapped_grpc_channel_credentials *)( (char*)(obj) - XtOffsetOf(wrapped_grpc_channel_credentials, std)); } #define Z_WRAPPED_GRPC_CHANNEL_CREDS_P(zv) \ wrapped_grpc_channel_credentials_from_obj(Z_OBJ_P((zv))) #endif /* PHP_MAJOR_VERSION */ /* Initializes the ChannelCredentials PHP class */ void grpc_init_channel_credentials(TSRMLS_D); #endif /* NET_GRPC_PHP_GRPC_CHANNEL_CREDENTIALS_H_ */ grpc-1.3.2/src/php/ext/grpc/completion_queue.c000066400000000000000000000041141310511640000212710ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "completion_queue.h" #include grpc_completion_queue *completion_queue; void grpc_php_init_completion_queue(TSRMLS_D) { completion_queue = grpc_completion_queue_create(NULL); } void grpc_php_shutdown_completion_queue(TSRMLS_D) { grpc_completion_queue_shutdown(completion_queue); while (grpc_completion_queue_next(completion_queue, gpr_inf_future(GPR_CLOCK_REALTIME), NULL).type != GRPC_QUEUE_SHUTDOWN); grpc_completion_queue_destroy(completion_queue); } grpc-1.3.2/src/php/ext/grpc/completion_queue.h000066400000000000000000000037461310511640000213100ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_PHP_GRPC_COMPLETION_QUEUE_H_ #define GRPC_PHP_GRPC_COMPLETION_QUEUE_H_ #include #include /* The global completion queue for all operations */ extern grpc_completion_queue *completion_queue; /* Initializes the completion queue */ void grpc_php_init_completion_queue(TSRMLS_D); /* Shut down the completion queue */ void grpc_php_shutdown_completion_queue(TSRMLS_D); #endif /* GRPC_PHP_GRPC_COMPLETION_QUEUE_H_ */ grpc-1.3.2/src/php/ext/grpc/config.m4000077500000000000000000000102171310511640000172630ustar00rootroot00000000000000PHP_ARG_ENABLE(grpc, whether to enable grpc support, [ --enable-grpc Enable grpc support]) PHP_ARG_ENABLE(coverage, whether to include code coverage symbols, [ --enable-coverage Enable coverage support], no, no) if test "$PHP_GRPC" != "no"; then dnl Write more examples of tests here... dnl # --with-grpc -> check with-path SEARCH_PATH="/usr/local /usr" # you might want to change this SEARCH_FOR="include/grpc/grpc.h" # you most likely want to change this if test -r $PHP_GRPC/$SEARCH_FOR; then # path given as parameter GRPC_DIR=$PHP_GRPC else # search default path list AC_MSG_CHECKING([for grpc files in default path]) for i in $SEARCH_PATH ; do if test -r $i/$SEARCH_FOR; then GRPC_DIR=$i AC_MSG_RESULT(found in $i) fi done fi if test -z "$GRPC_DIR"; then AC_MSG_RESULT([not found]) AC_MSG_ERROR([Please reinstall the grpc distribution]) fi dnl # --with-grpc -> add include path PHP_ADD_INCLUDE($GRPC_DIR/include) LIBS="-lpthread $LIBS" dnl PHP_ADD_LIBRARY(pthread,,GRPC_SHARED_LIBADD) GRPC_SHARED_LIBADD="-lpthread $GRPC_SHARED_LIBADD" PHP_ADD_LIBRARY(pthread) PHP_ADD_LIBRARY(dl,,GRPC_SHARED_LIBADD) PHP_ADD_LIBRARY(dl) case $host in *darwin*) ;; *) PHP_ADD_LIBRARY(rt,,GRPC_SHARED_LIBADD) PHP_ADD_LIBRARY(rt) ;; esac GRPC_LIBDIR=$GRPC_DIR/${GRPC_LIB_SUBDIR-lib} PHP_ADD_LIBPATH($GRPC_LIBDIR) PHP_CHECK_LIBRARY(gpr,gpr_now, [ PHP_ADD_LIBRARY(gpr,,GRPC_SHARED_LIBADD) PHP_ADD_LIBRARY(gpr) AC_DEFINE(HAVE_GPRLIB,1,[ ]) ],[ AC_MSG_ERROR([wrong gpr lib version or lib not found]) ],[ -L$GRPC_LIBDIR ]) PHP_CHECK_LIBRARY(grpc,grpc_channel_destroy, [ PHP_ADD_LIBRARY(grpc,,GRPC_SHARED_LIBADD) dnl PHP_ADD_LIBRARY_WITH_PATH(grpc, $GRPC_DIR/lib, GRPC_SHARED_LIBADD) AC_DEFINE(HAVE_GRPCLIB,1,[ ]) ],[ AC_MSG_ERROR([wrong grpc lib version or lib not found]) ],[ -L$GRPC_LIBDIR ]) PHP_SUBST(GRPC_SHARED_LIBADD) PHP_NEW_EXTENSION(grpc, byte_buffer.c call.c call_credentials.c channel.c \ channel_credentials.c completion_queue.c timeval.c server.c \ server_credentials.c php_grpc.c, $ext_shared, , -Wall -Werror -std=c11) fi if test "$PHP_COVERAGE" = "yes"; then if test "$GCC" != "yes"; then AC_MSG_ERROR([GCC is required for --enable-coverage]) fi dnl Check if ccache is being used case `$php_shtool path $CC` in *ccache*[)] gcc_ccache=yes;; *[)] gcc_ccache=no;; esac if test "$gcc_ccache" = "yes" && (test -z "$CCACHE_DISABLE" || test "$CCACHE_DISABLE" != "1"); then AC_MSG_ERROR([ccache must be disabled when --enable-coverage option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.]) fi lcov_version_list="1.5 1.6 1.7 1.9 1.10 1.11" AC_CHECK_PROG(LCOV, lcov, lcov) AC_CHECK_PROG(GENHTML, genhtml, genhtml) PHP_SUBST(LCOV) PHP_SUBST(GENHTML) if test "$LCOV"; then AC_CACHE_CHECK([for lcov version], php_cv_lcov_version, [ php_cv_lcov_version=invalid lcov_version=`$LCOV -v 2>/dev/null | $SED -e 's/^.* //'` #' for lcov_check_version in $lcov_version_list; do if test "$lcov_version" = "$lcov_check_version"; then php_cv_lcov_version="$lcov_check_version (ok)" fi done ]) else lcov_msg="To enable code coverage reporting you must have one of the following LCOV versions installed: $lcov_version_list" AC_MSG_ERROR([$lcov_msg]) fi case $php_cv_lcov_version in ""|invalid[)] lcov_msg="You must have one of the following versions of LCOV: $lcov_version_list (found: $lcov_version)." AC_MSG_ERROR([$lcov_msg]) LCOV="exit 0;" ;; esac if test -z "$GENHTML"; then AC_MSG_ERROR([Could not find genhtml from the LCOV package]) fi PHP_ADD_MAKEFILE_FRAGMENT dnl Remove all optimization flags from CFLAGS changequote({,}) CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9s]*//g'` CXXFLAGS=`echo "$CXXFLAGS" | $SED -e 's/-O[0-9s]*//g'` changequote([,]) dnl Add the special gcc flags CFLAGS="$CFLAGS -O0 -ggdb -fprofile-arcs -ftest-coverage" CXXFLAGS="$CXXFLAGS -ggdb -O0 -fprofile-arcs -ftest-coverage" fi grpc-1.3.2/src/php/ext/grpc/php7_wrapper.h000066400000000000000000000203641310511640000203440ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef PHP7_WRAPPER_GRPC_H #define PHP7_WRAPPER_GRPC_H #if PHP_MAJOR_VERSION < 7 #define php_grpc_int int #define php_grpc_long long #define php_grpc_ulong ulong #define php_grpc_zend_object zend_object_value #define php_grpc_add_property_string(arg, name, context, b) \ add_property_string(arg, name, context, b) #define php_grpc_add_property_stringl(res, name, str, len, b) \ add_property_stringl(res, name, str, len, b) #define php_grpc_add_next_index_stringl(data, str, len, b) \ add_next_index_stringl(data, str, len, b) #define PHP_GRPC_RETURN_STRING(val, dup) RETURN_STRING(val, dup) #define PHP_GRPC_MAKE_STD_ZVAL(pzv) MAKE_STD_ZVAL(pzv) #define PHP_GRPC_FREE_STD_ZVAL(pzv) #define PHP_GRPC_DELREF(zv) Z_DELREF_P(zv) #define RETURN_DESTROY_ZVAL(val) \ RETURN_ZVAL(val, false /* Don't execute copy constructor */, \ true /* Dealloc original before returning */) #define PHP_GRPC_WRAP_OBJECT_START(name) \ typedef struct name { \ zend_object std; #define PHP_GRPC_WRAP_OBJECT_END(name) \ } name; #define PHP_GRPC_FREE_WRAPPED_FUNC_START(class_object) \ void free_##class_object(void *object TSRMLS_DC) { \ class_object *p = (class_object *)object; #define PHP_GRPC_FREE_WRAPPED_FUNC_END() \ zend_object_std_dtor(&p->std TSRMLS_CC); \ efree(p); \ } #define PHP_GRPC_ALLOC_CLASS_OBJECT(class_object) \ class_object *intern; \ zend_object_value retval; \ intern = (class_object *)emalloc(sizeof(class_object)); \ memset(intern, 0, sizeof(class_object)); #define PHP_GRPC_FREE_CLASS_OBJECT(class_object, handler) \ retval.handle = zend_objects_store_put( \ intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, \ free_##class_object, NULL TSRMLS_CC); \ retval.handlers = zend_get_std_object_handlers(); \ return retval; #define PHP_GRPC_HASH_FOREACH_VAL_START(ht, data) \ zval **tmp_data = NULL; \ for (zend_hash_internal_pointer_reset(ht); \ zend_hash_get_current_data(ht, (void**)&tmp_data) == SUCCESS; \ zend_hash_move_forward(ht)) { \ data = *tmp_data; #define PHP_GRPC_HASH_FOREACH_STR_KEY_VAL_START(ht, key, key_type, data) \ zval **tmp##key = NULL; \ ulong index##key; \ uint len##key; \ for (zend_hash_internal_pointer_reset(ht); \ zend_hash_get_current_data(ht, (void**)&tmp##key) == SUCCESS; \ zend_hash_move_forward(ht)) { \ key_type = zend_hash_get_current_key_ex(ht, &key, &len##key, &index##key,\ 0, NULL); \ data = *tmp##key; #define PHP_GRPC_HASH_FOREACH_LONG_KEY_VAL_START(ht, key, key_type, index,\ data) \ zval **tmp##key = NULL; \ uint len##key; \ for (zend_hash_internal_pointer_reset(ht); \ zend_hash_get_current_data(ht, (void**)&tmp##key) == SUCCESS; \ zend_hash_move_forward(ht)) { \ key_type = zend_hash_get_current_key_ex(ht, &key, &len##key, &index,\ 0, NULL); \ data = *tmp##key; #define PHP_GRPC_HASH_FOREACH_END() } static inline int php_grpc_zend_hash_find(HashTable *ht, char *key, int len, void **value) { zval **data = NULL; if (zend_hash_find(ht, key, len, (void **)&data) == SUCCESS) { *value = *data; return SUCCESS; } else { *value = NULL; return FAILURE; } } #define php_grpc_zend_hash_del zend_hash_del #define PHP_GRPC_GET_CLASS_ENTRY(object) zend_get_class_entry(object TSRMLS_CC) #define PHP_GRPC_INIT_HANDLER(class_object, handler_name) #else #define php_grpc_int size_t #define php_grpc_long zend_long #define php_grpc_ulong zend_ulong #define php_grpc_zend_object zend_object* #define php_grpc_add_property_string(arg, name, context, b) \ add_property_string(arg, name, context) #define php_grpc_add_property_stringl(res, name, str, len, b) \ add_property_stringl(res, name, str, len) #define php_grpc_add_next_index_stringl(data, str, len, b) \ add_next_index_stringl(data, str, len) #define PHP_GRPC_RETURN_STRING(val, dup) RETURN_STRING(val) #define PHP_GRPC_MAKE_STD_ZVAL(pzv) \ pzv = (zval *)emalloc(sizeof(zval)); #define PHP_GRPC_FREE_STD_ZVAL(pzv) efree(pzv); #define PHP_GRPC_DELREF(zv) #define RETURN_DESTROY_ZVAL(val) \ RETVAL_ZVAL(val, false /* Don't execute copy constructor */, \ true /* Dealloc original before returning */); \ efree(val); \ return #define PHP_GRPC_WRAP_OBJECT_START(name) \ typedef struct name { #define PHP_GRPC_WRAP_OBJECT_END(name) \ zend_object std; \ } name; #define WRAPPED_OBJECT_FROM_OBJ(class_object, obj) \ class_object##_from_obj(obj); #define PHP_GRPC_FREE_WRAPPED_FUNC_START(class_object) \ static void free_##class_object(zend_object *object) { \ class_object *p = WRAPPED_OBJECT_FROM_OBJ(class_object, object) #define PHP_GRPC_FREE_WRAPPED_FUNC_END() \ zend_object_std_dtor(&p->std); \ } #define PHP_GRPC_ALLOC_CLASS_OBJECT(class_object) \ class_object *intern; \ intern = ecalloc(1, sizeof(class_object) + \ zend_object_properties_size(class_type)); #define PHP_GRPC_FREE_CLASS_OBJECT(class_object, handler) \ intern->std.handlers = &handler; \ return &intern->std; #define PHP_GRPC_HASH_FOREACH_VAL_START(ht, data) \ ZEND_HASH_FOREACH_VAL(ht, data) { #define PHP_GRPC_HASH_FOREACH_STR_KEY_VAL_START(ht, key, key_type, data) \ zend_string *(zs_##key); \ ZEND_HASH_FOREACH_STR_KEY_VAL(ht, (zs_##key), data) { \ if ((zs_##key) == NULL) {key = NULL; key_type = HASH_KEY_IS_LONG;} \ else {key = (zs_##key)->val; key_type = HASH_KEY_IS_STRING;} #define PHP_GRPC_HASH_FOREACH_LONG_KEY_VAL_START(ht, key, key_type, index, \ data) \ zend_string *(zs_##key); \ ZEND_HASH_FOREACH_KEY_VAL(ht, index, zs_##key, data) { \ if ((zs_##key) == NULL) {key = NULL; key_type = HASH_KEY_IS_LONG;} \ else {key = (zs_##key)->val; key_type = HASH_KEY_IS_STRING;} #define PHP_GRPC_HASH_FOREACH_END() } ZEND_HASH_FOREACH_END(); static inline int php_grpc_zend_hash_find(HashTable *ht, char *key, int len, void **value) { zval *value_tmp = zend_hash_str_find(ht, key, len -1); if (value_tmp == NULL) { return FAILURE; } else { *value = (void *)value_tmp; return SUCCESS; } } static inline int php_grpc_zend_hash_del(HashTable *ht, char *key, int len) { return zend_hash_str_del(ht, key, len - 1); } #define PHP_GRPC_GET_CLASS_ENTRY(object) Z_OBJ_P(object)->ce #define PHP_GRPC_INIT_HANDLER(class_object, handler_name) \ memcpy(&handler_name, zend_get_std_object_handlers(), \ sizeof(zend_object_handlers)); \ handler_name.offset = XtOffsetOf(class_object, std); \ handler_name.free_obj = free_##class_object #endif /* PHP_MAJOR_VERSION */ #endif /* PHP7_WRAPPER_GRPC_H */ grpc-1.3.2/src/php/ext/grpc/php_grpc.c000066400000000000000000000260171310511640000175240ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "call.h" #include "channel.h" #include "server.h" #include "timeval.h" #include "channel_credentials.h" #include "call_credentials.h" #include "server_credentials.h" #include "completion_queue.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "php_grpc.h" // ZEND_DECLARE_MODULE_GLOBALS(grpc) /* {{{ grpc_functions[] * * Every user visible function must have an entry in grpc_functions[]. */ const zend_function_entry grpc_functions[] = { PHP_FE_END /* Must be the last line in grpc_functions[] */ }; /* }}} */ /* {{{ grpc_module_entry */ zend_module_entry grpc_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif "grpc", grpc_functions, PHP_MINIT(grpc), PHP_MSHUTDOWN(grpc), NULL, NULL, PHP_MINFO(grpc), #if ZEND_MODULE_API_NO >= 20010901 PHP_GRPC_VERSION, #endif STANDARD_MODULE_PROPERTIES}; /* }}} */ #ifdef COMPILE_DL_GRPC ZEND_GET_MODULE(grpc) #endif /* {{{ PHP_INI */ /* Remove comments and fill if you need to have entries in php.ini PHP_INI_BEGIN() STD_PHP_INI_ENTRY("grpc.global_value", "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_grpc_globals, grpc_globals) STD_PHP_INI_ENTRY("grpc.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_grpc_globals, grpc_globals) PHP_INI_END() */ /* }}} */ /* {{{ php_grpc_init_globals */ /* Uncomment this function if you have INI entries static void php_grpc_init_globals(zend_grpc_globals *grpc_globals) { grpc_globals->global_value = 0; grpc_globals->global_string = NULL; } */ /* }}} */ /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(grpc) { /* If you have INI entries, uncomment these lines REGISTER_INI_ENTRIES(); */ /* Register call error constants */ grpc_init(); REGISTER_LONG_CONSTANT("Grpc\\CALL_OK", GRPC_CALL_OK, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\CALL_ERROR", GRPC_CALL_ERROR, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\CALL_ERROR_NOT_ON_SERVER", GRPC_CALL_ERROR_NOT_ON_SERVER, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\CALL_ERROR_NOT_ON_CLIENT", GRPC_CALL_ERROR_NOT_ON_CLIENT, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\CALL_ERROR_ALREADY_INVOKED", GRPC_CALL_ERROR_ALREADY_INVOKED, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\CALL_ERROR_NOT_INVOKED", GRPC_CALL_ERROR_NOT_INVOKED, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\CALL_ERROR_ALREADY_FINISHED", GRPC_CALL_ERROR_ALREADY_FINISHED, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\CALL_ERROR_TOO_MANY_OPERATIONS", GRPC_CALL_ERROR_TOO_MANY_OPERATIONS, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\CALL_ERROR_INVALID_FLAGS", GRPC_CALL_ERROR_INVALID_FLAGS, CONST_CS | CONST_PERSISTENT); /* Register flag constants */ REGISTER_LONG_CONSTANT("Grpc\\WRITE_BUFFER_HINT", GRPC_WRITE_BUFFER_HINT, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\WRITE_NO_COMPRESS", GRPC_WRITE_NO_COMPRESS, CONST_CS | CONST_PERSISTENT); /* Register status constants */ REGISTER_LONG_CONSTANT("Grpc\\STATUS_OK", GRPC_STATUS_OK, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\STATUS_CANCELLED", GRPC_STATUS_CANCELLED, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\STATUS_UNKNOWN", GRPC_STATUS_UNKNOWN, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\STATUS_INVALID_ARGUMENT", GRPC_STATUS_INVALID_ARGUMENT, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\STATUS_DEADLINE_EXCEEDED", GRPC_STATUS_DEADLINE_EXCEEDED, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\STATUS_NOT_FOUND", GRPC_STATUS_NOT_FOUND, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\STATUS_ALREADY_EXISTS", GRPC_STATUS_ALREADY_EXISTS, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\STATUS_PERMISSION_DENIED", GRPC_STATUS_PERMISSION_DENIED, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\STATUS_UNAUTHENTICATED", GRPC_STATUS_UNAUTHENTICATED, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\STATUS_RESOURCE_EXHAUSTED", GRPC_STATUS_RESOURCE_EXHAUSTED, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\STATUS_FAILED_PRECONDITION", GRPC_STATUS_FAILED_PRECONDITION, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\STATUS_ABORTED", GRPC_STATUS_ABORTED, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\STATUS_OUT_OF_RANGE", GRPC_STATUS_OUT_OF_RANGE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\STATUS_UNIMPLEMENTED", GRPC_STATUS_UNIMPLEMENTED, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\STATUS_INTERNAL", GRPC_STATUS_INTERNAL, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\STATUS_UNAVAILABLE", GRPC_STATUS_UNAVAILABLE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\STATUS_DATA_LOSS", GRPC_STATUS_DATA_LOSS, CONST_CS | CONST_PERSISTENT); /* Register op type constants */ REGISTER_LONG_CONSTANT("Grpc\\OP_SEND_INITIAL_METADATA", GRPC_OP_SEND_INITIAL_METADATA, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\OP_SEND_MESSAGE", GRPC_OP_SEND_MESSAGE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\OP_SEND_CLOSE_FROM_CLIENT", GRPC_OP_SEND_CLOSE_FROM_CLIENT, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\OP_SEND_STATUS_FROM_SERVER", GRPC_OP_SEND_STATUS_FROM_SERVER, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\OP_RECV_INITIAL_METADATA", GRPC_OP_RECV_INITIAL_METADATA, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\OP_RECV_MESSAGE", GRPC_OP_RECV_MESSAGE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\OP_RECV_STATUS_ON_CLIENT", GRPC_OP_RECV_STATUS_ON_CLIENT, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\OP_RECV_CLOSE_ON_SERVER", GRPC_OP_RECV_CLOSE_ON_SERVER, CONST_CS | CONST_PERSISTENT); /* Register connectivity state constants */ REGISTER_LONG_CONSTANT("Grpc\\CHANNEL_IDLE", GRPC_CHANNEL_IDLE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\CHANNEL_CONNECTING", GRPC_CHANNEL_CONNECTING, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\CHANNEL_READY", GRPC_CHANNEL_READY, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\CHANNEL_TRANSIENT_FAILURE", GRPC_CHANNEL_TRANSIENT_FAILURE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Grpc\\CHANNEL_FATAL_FAILURE", GRPC_CHANNEL_SHUTDOWN, CONST_CS | CONST_PERSISTENT); grpc_init_call(TSRMLS_C); grpc_init_channel(TSRMLS_C); grpc_init_server(TSRMLS_C); grpc_init_timeval(TSRMLS_C); grpc_init_channel_credentials(TSRMLS_C); grpc_init_call_credentials(TSRMLS_C); grpc_init_server_credentials(TSRMLS_C); grpc_php_init_completion_queue(TSRMLS_C); return SUCCESS; } /* }}} */ /* {{{ PHP_MSHUTDOWN_FUNCTION */ PHP_MSHUTDOWN_FUNCTION(grpc) { /* uncomment this line if you have INI entries UNREGISTER_INI_ENTRIES(); */ // WARNING: This function IS being called by PHP when the extension // is unloaded but the logs were somehow suppressed. grpc_shutdown_timeval(TSRMLS_C); grpc_php_shutdown_completion_queue(TSRMLS_C); grpc_shutdown(); return SUCCESS; } /* }}} */ /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(grpc) { php_info_print_table_start(); php_info_print_table_header(2, "grpc support", "enabled"); php_info_print_table_end(); /* Remove comments if you have entries in php.ini DISPLAY_INI_ENTRIES(); */ } /* }}} */ /* The previous line is meant for vim and emacs, so it can correctly fold and unfold functions in source code. See the corresponding marks just before function definition, where the functions purpose is also documented. Please follow this convention for the convenience of others editing your code. */ grpc-1.3.2/src/php/ext/grpc/php_grpc.h000066400000000000000000000061611310511640000175270ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef PHP_GRPC_H #define PHP_GRPC_H #include extern zend_module_entry grpc_module_entry; #define phpext_grpc_ptr &grpc_module_entry #define PHP_GRPC_VERSION \ "0.1.0" /* Replace with version number for your extension */ #ifdef PHP_WIN32 #define PHP_GRPC_API __declspec(dllexport) #elif defined(__GNUC__) && __GNUC__ >= 4 #define PHP_GRPC_API __attribute__((visibility("default"))) #else #define PHP_GRPC_API #endif #ifdef ZTS #include "TSRM.h" #endif #include "php.h" #include "php7_wrapper.h" #include "grpc/grpc.h" /* These are all function declarations */ /* Code that runs at module initialization */ PHP_MINIT_FUNCTION(grpc); /* Code that runs at module shutdown */ PHP_MSHUTDOWN_FUNCTION(grpc); /* Displays information about the module */ PHP_MINFO_FUNCTION(grpc); /* Declare any global variables you may need between the BEGIN and END macros here: ZEND_BEGIN_MODULE_GLOBALS(grpc) ZEND_END_MODULE_GLOBALS(grpc) */ /* In every utility function you add that needs to use variables in php_grpc_globals, call TSRMLS_FETCH(); after declaring other variables used by that function, or better yet, pass in TSRMLS_CC after the last function argument and declare your utility function with TSRMLS_DC after the last declared argument. Always refer to the globals in your function as GRPC_G(variable). You are encouraged to rename these macros something shorter, see examples in any other php module directory. */ #ifdef ZTS #define GRPC_G(v) TSRMG(grpc_globals_id, zend_grpc_globals *, v) #else #define GRPC_G(v) (grpc_globals.v) #endif #endif /* PHP_GRPC_H */ grpc-1.3.2/src/php/ext/grpc/server.c000066400000000000000000000227301310511640000172260ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "call.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "php_grpc.h" #include #include #include #include #include #include #include "completion_queue.h" #include "server.h" #include "channel.h" #include "server_credentials.h" #include "timeval.h" zend_class_entry *grpc_ce_server; #if PHP_MAJOR_VERSION >= 7 static zend_object_handlers server_ce_handlers; #endif /* Frees and destroys an instance of wrapped_grpc_server */ PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_server) if (p->wrapped != NULL) { grpc_server_shutdown_and_notify(p->wrapped, completion_queue, NULL); grpc_server_cancel_all_calls(p->wrapped); grpc_completion_queue_pluck(completion_queue, NULL, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); grpc_server_destroy(p->wrapped); } PHP_GRPC_FREE_WRAPPED_FUNC_END() /* Initializes an instance of wrapped_grpc_call to be associated with an * object of a class specified by class_type */ php_grpc_zend_object create_wrapped_grpc_server(zend_class_entry *class_type TSRMLS_DC) { PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_server); zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_server, server_ce_handlers); } /** * Constructs a new instance of the Server class * @param array $args_array The arguments to pass to the server (optional) */ PHP_METHOD(Server, __construct) { wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis()); zval *args_array = NULL; grpc_channel_args args; /* "|a" == 1 optional array */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a", &args_array) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "Server expects an array", 1 TSRMLS_CC); return; } if (args_array == NULL) { server->wrapped = grpc_server_create(NULL, NULL); } else { //TODO(thinkerou): deal it if key of array is long, crash now on php7 // and update unit test case php_grpc_read_args_array(args_array, &args TSRMLS_CC); server->wrapped = grpc_server_create(&args, NULL); efree(args.args); } grpc_server_register_completion_queue(server->wrapped, completion_queue, NULL); } /** * Request a call on a server. Creates a single GRPC_SERVER_RPC_NEW event. * @return void */ PHP_METHOD(Server, requestCall) { grpc_call_error error_code; grpc_call *call; grpc_call_details details; grpc_metadata_array metadata; grpc_event event; wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis()); zval *result; PHP_GRPC_MAKE_STD_ZVAL(result); object_init(result); grpc_call_details_init(&details); grpc_metadata_array_init(&metadata); error_code = grpc_server_request_call(server->wrapped, &call, &details, &metadata, completion_queue, completion_queue, NULL); if (error_code != GRPC_CALL_OK) { zend_throw_exception(spl_ce_LogicException, "request_call failed", (long)error_code TSRMLS_CC); goto cleanup; } event = grpc_completion_queue_pluck(completion_queue, NULL, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); if (!event.success) { zend_throw_exception(spl_ce_LogicException, "Failed to request a call for some reason", 1 TSRMLS_CC); goto cleanup; } char *method_text = grpc_slice_to_c_string(details.method); char *host_text = grpc_slice_to_c_string(details.host); php_grpc_add_property_string(result, "method", method_text, true); php_grpc_add_property_string(result, "host", host_text, true); gpr_free(method_text); gpr_free(host_text); #if PHP_MAJOR_VERSION < 7 add_property_zval(result, "call", grpc_php_wrap_call(call, true TSRMLS_CC)); add_property_zval(result, "absolute_deadline", grpc_php_wrap_timeval(details.deadline TSRMLS_CC)); add_property_zval(result, "metadata", grpc_parse_metadata_array(&metadata TSRMLS_CC)); #else zval zv_call; zval zv_timeval; zval zv_md; //TODO(thinkerou): why use zval* to unit test error? zv_call = *grpc_php_wrap_call(call, true); zv_timeval = *grpc_php_wrap_timeval(details.deadline); zv_md = *grpc_parse_metadata_array(&metadata); add_property_zval(result, "call", &zv_call); add_property_zval(result, "absolute_deadline", &zv_timeval); add_property_zval(result, "metadata", &zv_md); #endif cleanup: grpc_call_details_destroy(&details); grpc_metadata_array_destroy(&metadata); RETURN_DESTROY_ZVAL(result); } /** * Add a http2 over tcp listener. * @param string $addr The address to add * @return bool True on success, false on failure */ PHP_METHOD(Server, addHttp2Port) { const char *addr; php_grpc_int addr_len; wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis()); /* "s" == 1 string */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &addr, &addr_len) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "add_http2_port expects a string", 1 TSRMLS_CC); return; } RETURN_LONG(grpc_server_add_insecure_http2_port(server->wrapped, addr)); } /** * Add a secure http2 over tcp listener. * @param string $addr The address to add * @param ServerCredentials The ServerCredentials object * @return bool True on success, false on failure */ PHP_METHOD(Server, addSecureHttp2Port) { const char *addr; php_grpc_int addr_len; zval *creds_obj; wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis()); /* "sO" == 1 string, 1 object */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sO", &addr, &addr_len, &creds_obj, grpc_ce_server_credentials) == FAILURE) { zend_throw_exception( spl_ce_InvalidArgumentException, "add_http2_port expects a string and a ServerCredentials", 1 TSRMLS_CC); return; } wrapped_grpc_server_credentials *creds = Z_WRAPPED_GRPC_SERVER_CREDS_P(creds_obj); RETURN_LONG(grpc_server_add_secure_http2_port(server->wrapped, addr, creds->wrapped)); } /** * Start a server - tells all listeners to start listening * @return void */ PHP_METHOD(Server, start) { wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis()); grpc_server_start(server->wrapped); } ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 0) ZEND_ARG_INFO(0, args) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_requestCall, 0, 0, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_addHttp2Port, 0, 0, 1) ZEND_ARG_INFO(0, addr) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_addSecureHttp2Port, 0, 0, 2) ZEND_ARG_INFO(0, addr) ZEND_ARG_INFO(0, server_creds) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_start, 0, 0, 0) ZEND_END_ARG_INFO() static zend_function_entry server_methods[] = { PHP_ME(Server, __construct, arginfo_construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) PHP_ME(Server, requestCall, arginfo_requestCall, ZEND_ACC_PUBLIC) PHP_ME(Server, addHttp2Port, arginfo_addHttp2Port, ZEND_ACC_PUBLIC) PHP_ME(Server, addSecureHttp2Port, arginfo_addSecureHttp2Port, ZEND_ACC_PUBLIC) PHP_ME(Server, start, arginfo_start, ZEND_ACC_PUBLIC) PHP_FE_END }; void grpc_init_server(TSRMLS_D) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "Grpc\\Server", server_methods); ce.create_object = create_wrapped_grpc_server; grpc_ce_server = zend_register_internal_class(&ce TSRMLS_CC); PHP_GRPC_INIT_HANDLER(wrapped_grpc_server, server_ce_handlers); } grpc-1.3.2/src/php/ext/grpc/server.h000077500000000000000000000051431310511640000172350ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef NET_GRPC_PHP_GRPC_SERVER_H_ #define NET_GRPC_PHP_GRPC_SERVER_H_ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "php_grpc.h" #include /* Class entry for the Server PHP class */ extern zend_class_entry *grpc_ce_server; /* Wrapper struct for grpc_server that can be associated with a PHP object */ PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_server) grpc_server *wrapped; PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_server) #if PHP_MAJOR_VERSION < 7 #define Z_WRAPPED_GRPC_SERVER_P(zv) \ (wrapped_grpc_server *)zend_object_store_get_object(zv TSRMLS_CC) #else static inline wrapped_grpc_server *wrapped_grpc_server_from_obj(zend_object *obj) { return (wrapped_grpc_server*)((char*)(obj) - XtOffsetOf(wrapped_grpc_server, std)); } #define Z_WRAPPED_GRPC_SERVER_P(zv) wrapped_grpc_server_from_obj(Z_OBJ_P((zv))) #endif /* PHP_MAJOR_VERSION */ /* Initializes the Server class */ void grpc_init_server(TSRMLS_D); #endif /* NET_GRPC_PHP_GRPC_SERVER_H_ */ grpc-1.3.2/src/php/ext/grpc/server_credentials.c000066400000000000000000000126651310511640000216110ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "server_credentials.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "php_grpc.h" #include #include #include #include zend_class_entry *grpc_ce_server_credentials; #if PHP_MAJOR_VERSION >= 7 static zend_object_handlers server_credentials_ce_handlers; #endif /* Frees and destroys an instace of wrapped_grpc_server_credentials */ PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_server_credentials) if (p->wrapped != NULL) { grpc_server_credentials_release(p->wrapped); } PHP_GRPC_FREE_WRAPPED_FUNC_END() /* Initializes an instace of wrapped_grpc_server_credentials to be * associated with an object of a class specified by class_type */ php_grpc_zend_object create_wrapped_grpc_server_credentials( zend_class_entry *class_type TSRMLS_DC) { PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_server_credentials); zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_server_credentials, server_credentials_ce_handlers); } zval *grpc_php_wrap_server_credentials(grpc_server_credentials *wrapped TSRMLS_DC) { zval *server_credentials_object; PHP_GRPC_MAKE_STD_ZVAL(server_credentials_object); object_init_ex(server_credentials_object, grpc_ce_server_credentials); wrapped_grpc_server_credentials *server_credentials = Z_WRAPPED_GRPC_SERVER_CREDS_P(server_credentials_object); server_credentials->wrapped = wrapped; return server_credentials_object; } /** * Create SSL credentials. * @param string pem_root_certs PEM encoding of the server root certificates * @param string pem_private_key PEM encoding of the client's private key * @param string pem_cert_chain PEM encoding of the client's certificate chain * @return Credentials The new SSL credentials object */ PHP_METHOD(ServerCredentials, createSsl) { char *pem_root_certs = 0; grpc_ssl_pem_key_cert_pair pem_key_cert_pair; php_grpc_int root_certs_length = 0; php_grpc_int private_key_length; php_grpc_int cert_chain_length; /* "s!ss" == 1 nullable string, 2 strings */ /* TODO: support multiple key cert pairs. */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!ss", &pem_root_certs, &root_certs_length, &pem_key_cert_pair.private_key, &private_key_length, &pem_key_cert_pair.cert_chain, &cert_chain_length) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "createSsl expects 3 strings", 1 TSRMLS_CC); return; } /* TODO: add a client_certificate_request field in ServerCredentials and pass * it as the last parameter. */ grpc_server_credentials *creds = grpc_ssl_server_credentials_create_ex( pem_root_certs, &pem_key_cert_pair, 1, GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, NULL); zval *creds_object = grpc_php_wrap_server_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); } ZEND_BEGIN_ARG_INFO_EX(arginfo_createSsl, 0, 0, 3) ZEND_ARG_INFO(0, pem_root_certs) ZEND_ARG_INFO(0, pem_private_key) ZEND_ARG_INFO(0, pem_cert_chain) ZEND_END_ARG_INFO() static zend_function_entry server_credentials_methods[] = { PHP_ME(ServerCredentials, createSsl, arginfo_createSsl, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_FE_END }; void grpc_init_server_credentials(TSRMLS_D) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "Grpc\\ServerCredentials", server_credentials_methods); ce.create_object = create_wrapped_grpc_server_credentials; grpc_ce_server_credentials = zend_register_internal_class(&ce TSRMLS_CC); PHP_GRPC_INIT_HANDLER(wrapped_grpc_server_credentials, server_credentials_ce_handlers); } grpc-1.3.2/src/php/ext/grpc/server_credentials.h000077500000000000000000000055151310511640000216150ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef NET_GRPC_PHP_GRPC_SERVER_CREDENTIALS_H_ #define NET_GRPC_PHP_GRPC_SERVER_CREDENTIALS_H_ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "php_grpc.h" #include #include /* Class entry for the Server_Credentials PHP class */ extern zend_class_entry *grpc_ce_server_credentials; /* Wrapper struct for grpc_server_credentials that can be associated with a PHP * object */ PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_server_credentials) grpc_server_credentials *wrapped; PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_server_credentials) #if PHP_MAJOR_VERSION < 7 #define Z_WRAPPED_GRPC_SERVER_CREDS_P(zv) \ (wrapped_grpc_server_credentials *)zend_object_store_get_object(zv TSRMLS_CC) #else static inline wrapped_grpc_server_credentials *wrapped_grpc_server_credentials_from_obj(zend_object *obj) { return (wrapped_grpc_server_credentials*)( (char*)(obj) - XtOffsetOf(wrapped_grpc_server_credentials, std)); } #define Z_WRAPPED_GRPC_SERVER_CREDS_P(zv) \ wrapped_grpc_server_credentials_from_obj(Z_OBJ_P((zv))) #endif /* PHP_MAJOR_VERSION */ /* Initializes the Server_Credentials PHP class */ void grpc_init_server_credentials(TSRMLS_D); #endif /* NET_GRPC_PHP_GRPC_SERVER_CREDENTIALS_H_ */ grpc-1.3.2/src/php/ext/grpc/tests/000077500000000000000000000000001310511640000167125ustar00rootroot00000000000000grpc-1.3.2/src/php/ext/grpc/tests/grpc-basic.phpt000066400000000000000000000002771310511640000216270ustar00rootroot00000000000000--TEST-- Check for grpc presence --SKIPIF-- --FILE-- --EXPECT-- grpc extension is availablegrpc-1.3.2/src/php/ext/grpc/timeval.c000066400000000000000000000251151310511640000173610ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "timeval.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "php_grpc.h" #include #include #include #include zend_class_entry *grpc_ce_timeval; #if PHP_MAJOR_VERSION >= 7 static zend_object_handlers timeval_ce_handlers; #endif /* Frees and destroys an instance of wrapped_grpc_call */ PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_timeval) PHP_GRPC_FREE_WRAPPED_FUNC_END() /* Initializes an instance of wrapped_grpc_timeval to be associated with an * object of a class specified by class_type */ php_grpc_zend_object create_wrapped_grpc_timeval(zend_class_entry *class_type TSRMLS_DC) { PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_timeval); zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_timeval, timeval_ce_handlers); } zval *grpc_php_wrap_timeval(gpr_timespec wrapped TSRMLS_DC) { zval *timeval_object; PHP_GRPC_MAKE_STD_ZVAL(timeval_object); object_init_ex(timeval_object, grpc_ce_timeval); wrapped_grpc_timeval *timeval = Z_WRAPPED_GRPC_TIMEVAL_P(timeval_object); memcpy(&timeval->wrapped, &wrapped, sizeof(gpr_timespec)); return timeval_object; } /** * Constructs a new instance of the Timeval class * @param long $microseconds The number of microseconds in the interval */ PHP_METHOD(Timeval, __construct) { wrapped_grpc_timeval *timeval = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); php_grpc_long microseconds; /* "l" == 1 long */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", µseconds) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "Timeval expects a long", 1 TSRMLS_CC); return; } gpr_timespec time = gpr_time_from_micros(microseconds, GPR_TIMESPAN); memcpy(&timeval->wrapped, &time, sizeof(gpr_timespec)); } /** * Adds another Timeval to this one and returns the sum. Calculations saturate * at infinities. * @param Timeval $other_obj The other Timeval object to add * @return Timeval A new Timeval object containing the sum */ PHP_METHOD(Timeval, add) { zval *other_obj; /* "O" == 1 Object */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &other_obj, grpc_ce_timeval) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "add expects a Timeval", 1 TSRMLS_CC); return; } wrapped_grpc_timeval *self = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); wrapped_grpc_timeval *other = Z_WRAPPED_GRPC_TIMEVAL_P(other_obj); zval *sum = grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped) TSRMLS_CC); RETURN_DESTROY_ZVAL(sum); } /** * Subtracts another Timeval from this one and returns the difference. * Calculations saturate at infinities. * @param Timeval $other_obj The other Timeval object to subtract * @return Timeval A new Timeval object containing the diff */ PHP_METHOD(Timeval, subtract) { zval *other_obj; /* "O" == 1 Object */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &other_obj, grpc_ce_timeval) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "subtract expects a Timeval", 1 TSRMLS_CC); return; } wrapped_grpc_timeval *self = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); wrapped_grpc_timeval *other = Z_WRAPPED_GRPC_TIMEVAL_P(other_obj); zval *diff = grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped) TSRMLS_CC); RETURN_DESTROY_ZVAL(diff); } /** * Return negative, 0, or positive according to whether a < b, a == b, * or a > b respectively. * @param Timeval $a_obj The first time to compare * @param Timeval $b_obj The second time to compare * @return long */ PHP_METHOD(Timeval, compare) { zval *a_obj; zval *b_obj; /* "OO" == 2 Objects */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &a_obj, grpc_ce_timeval, &b_obj, grpc_ce_timeval) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "compare expects two Timevals", 1 TSRMLS_CC); return; } wrapped_grpc_timeval *a = Z_WRAPPED_GRPC_TIMEVAL_P(a_obj); wrapped_grpc_timeval *b = Z_WRAPPED_GRPC_TIMEVAL_P(b_obj); long result = gpr_time_cmp(a->wrapped, b->wrapped); RETURN_LONG(result); } /** * Checks whether the two times are within $threshold of each other * @param Timeval $a_obj The first time to compare * @param Timeval $b_obj The second time to compare * @param Timeval $thresh_obj The threshold to check against * @return bool True if $a and $b are within $threshold, False otherwise */ PHP_METHOD(Timeval, similar) { zval *a_obj; zval *b_obj; zval *thresh_obj; /* "OOO" == 3 Objects */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OOO", &a_obj, grpc_ce_timeval, &b_obj, grpc_ce_timeval, &thresh_obj, grpc_ce_timeval) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "compare expects three Timevals", 1 TSRMLS_CC); return; } wrapped_grpc_timeval *a = Z_WRAPPED_GRPC_TIMEVAL_P(a_obj); wrapped_grpc_timeval *b = Z_WRAPPED_GRPC_TIMEVAL_P(b_obj); wrapped_grpc_timeval *thresh = Z_WRAPPED_GRPC_TIMEVAL_P(thresh_obj); int result = gpr_time_similar(a->wrapped, b->wrapped, thresh->wrapped); RETURN_BOOL(result); } /** * Returns the current time as a timeval object * @return Timeval The current time */ PHP_METHOD(Timeval, now) { zval *now = grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_DESTROY_ZVAL(now); } /** * Returns the zero time interval as a timeval object * @return Timeval Zero length time interval */ PHP_METHOD(Timeval, zero) { zval *grpc_php_timeval_zero = grpc_php_wrap_timeval(gpr_time_0(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_DESTROY_ZVAL(grpc_php_timeval_zero); } /** * Returns the infinite future time value as a timeval object * @return Timeval Infinite future time value */ PHP_METHOD(Timeval, infFuture) { zval *grpc_php_timeval_inf_future = grpc_php_wrap_timeval(gpr_inf_future(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_future); } /** * Returns the infinite past time value as a timeval object * @return Timeval Infinite past time value */ PHP_METHOD(Timeval, infPast) { zval *grpc_php_timeval_inf_past = grpc_php_wrap_timeval(gpr_inf_past(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_past); } /** * Sleep until this time, interpreted as an absolute timeout * @return void */ PHP_METHOD(Timeval, sleepUntil) { wrapped_grpc_timeval *this = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); gpr_sleep_until(this->wrapped); } ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 1) ZEND_ARG_INFO(0, microseconds) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_add, 0, 0, 1) ZEND_ARG_INFO(0, timeval) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_compare, 0, 0, 2) ZEND_ARG_INFO(0, a_timeval) ZEND_ARG_INFO(0, b_timeval) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_infFuture, 0, 0, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_infPast, 0, 0, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_now, 0, 0, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_similar, 0, 0, 3) ZEND_ARG_INFO(0, a_timeval) ZEND_ARG_INFO(0, b_timeval) ZEND_ARG_INFO(0, threshold_timeval) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_sleepUntil, 0, 0, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_subtract, 0, 0, 1) ZEND_ARG_INFO(0, timeval) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_zero, 0, 0, 0) ZEND_END_ARG_INFO() static zend_function_entry timeval_methods[] = { PHP_ME(Timeval, __construct, arginfo_construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) PHP_ME(Timeval, add, arginfo_add, ZEND_ACC_PUBLIC) PHP_ME(Timeval, compare, arginfo_compare, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(Timeval, infFuture, arginfo_infFuture, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(Timeval, infPast, arginfo_infPast, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(Timeval, now, arginfo_now, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(Timeval, similar, arginfo_similar, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(Timeval, sleepUntil, arginfo_sleepUntil, ZEND_ACC_PUBLIC) PHP_ME(Timeval, subtract, arginfo_subtract, ZEND_ACC_PUBLIC) PHP_ME(Timeval, zero, arginfo_zero, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_FE_END }; void grpc_init_timeval(TSRMLS_D) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "Grpc\\Timeval", timeval_methods); ce.create_object = create_wrapped_grpc_timeval; grpc_ce_timeval = zend_register_internal_class(&ce TSRMLS_CC); PHP_GRPC_INIT_HANDLER(wrapped_grpc_timeval, timeval_ce_handlers); } void grpc_shutdown_timeval(TSRMLS_D) {} grpc-1.3.2/src/php/ext/grpc/timeval.h000077500000000000000000000055441310511640000173750ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef NET_GRPC_PHP_GRPC_TIMEVAL_H_ #define NET_GRPC_PHP_GRPC_TIMEVAL_H_ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "php_grpc.h" #include #include /* Class entry for the Timeval PHP Class */ extern zend_class_entry *grpc_ce_timeval; /* Wrapper struct for timeval that can be associated with a PHP object */ PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_timeval) gpr_timespec wrapped; PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_timeval) #if PHP_MAJOR_VERSION < 7 #define Z_WRAPPED_GRPC_TIMEVAL_P(zv) \ (wrapped_grpc_timeval *)zend_object_store_get_object(zv TSRMLS_CC) #else static inline wrapped_grpc_timeval *wrapped_grpc_timeval_from_obj(zend_object *obj) { return (wrapped_grpc_timeval*)((char*)(obj) - XtOffsetOf(wrapped_grpc_timeval, std)); } #define Z_WRAPPED_GRPC_TIMEVAL_P(zv) \ wrapped_grpc_timeval_from_obj(Z_OBJ_P((zv))) #endif /* PHP_MAJOR_VERSION */ /* Initialize the Timeval PHP class */ void grpc_init_timeval(TSRMLS_D); /* Shutdown the Timeval PHP class */ void grpc_shutdown_timeval(TSRMLS_D); /* Creates a Timeval object that wraps the given timeval struct */ zval *grpc_php_wrap_timeval(gpr_timespec wrapped TSRMLS_DC); #endif /* NET_GRPC_PHP_GRPC_TIMEVAL_H_ */ grpc-1.3.2/src/php/lib/000077500000000000000000000000001310511640000145635ustar00rootroot00000000000000grpc-1.3.2/src/php/lib/Grpc/000077500000000000000000000000001310511640000154565ustar00rootroot00000000000000grpc-1.3.2/src/php/lib/Grpc/AbstractCall.php000066400000000000000000000126561310511640000205400ustar00rootroot00000000000000add($delta); } else { $deadline = Timeval::infFuture(); } $this->call = new Call($channel, $method, $deadline); $this->deserialize = $deserialize; $this->metadata = null; $this->trailing_metadata = null; if (array_key_exists('call_credentials_callback', $options) && is_callable($call_credentials_callback = $options['call_credentials_callback']) ) { $call_credentials = CallCredentials::createFromPlugin( $call_credentials_callback ); $this->call->setCredentials($call_credentials); } } /** * @return mixed The metadata sent by the server */ public function getMetadata() { return $this->metadata; } /** * @return mixed The trailing metadata sent by the server */ public function getTrailingMetadata() { return $this->trailing_metadata; } /** * @return string The URI of the endpoint */ public function getPeer() { return $this->call->getPeer(); } /** * Cancels the call. */ public function cancel() { $this->call->cancel(); } /** * Serialize a message to the protobuf binary format. * * @param mixed $data The Protobuf message * * @return string The protobuf binary format */ protected function _serializeMessage($data) { // Proto3 implementation if (method_exists($data, 'encode')) { return $data->encode(); } elseif (method_exists($data, 'serializeToString')) { return $data->serializeToString(); } // Protobuf-PHP implementation return $data->serialize(); } /** * Deserialize a response value to an object. * * @param string $value The binary value to deserialize * * @return mixed The deserialized value */ protected function _deserializeResponse($value) { if ($value === null) { return; } // Proto3 implementation if (is_array($this->deserialize)) { list($className, $deserializeFunc) = $this->deserialize; $obj = new $className(); if (method_exists($obj, $deserializeFunc)) { $obj->$deserializeFunc($value); } else { $obj->mergeFromString($value); } return $obj; } // Protobuf-PHP implementation return call_user_func($this->deserialize, $value); } /** * Set the CallCredentials for the underlying Call. * * @param CallCredentials $call_credentials The CallCredentials object */ public function setCallCredentials($call_credentials) { $this->call->setCredentials($call_credentials); } } grpc-1.3.2/src/php/lib/Grpc/BaseStub.php000066400000000000000000000320651310511640000177050ustar00rootroot00000000000000hostname = $hostname; $this->update_metadata = null; if (isset($opts['update_metadata'])) { if (is_callable($opts['update_metadata'])) { $this->update_metadata = $opts['update_metadata']; } unset($opts['update_metadata']); } $package_config = json_decode( file_get_contents(dirname(__FILE__).'/../../composer.json'), true); if (!empty($opts['grpc.primary_user_agent'])) { $opts['grpc.primary_user_agent'] .= ' '; } else { $opts['grpc.primary_user_agent'] = ''; } if (!empty($opts['grpc.ssl_target_name_override'])) { $this->hostname_override = $opts['grpc.ssl_target_name_override']; } $opts['grpc.primary_user_agent'] .= 'grpc-php/'.$package_config['version']; if (!array_key_exists('credentials', $opts)) { throw new \Exception("The opts['credentials'] key is now ". 'required. Please see one of the '. 'ChannelCredentials::create methods'); } if ($channel) { if (!is_a($channel, 'Channel')) { throw new \Exception('The channel argument is not a'. 'Channel object'); } $this->channel = $channel; } else { $this->channel = new Channel($hostname, $opts); } } /** * @return string The URI of the endpoint */ public function getTarget() { return $this->channel->getTarget(); } /** * @param bool $try_to_connect (optional) * * @return int The grpc connectivity state */ public function getConnectivityState($try_to_connect = false) { return $this->channel->getConnectivityState($try_to_connect); } /** * @param int $timeout in microseconds * * @return bool true if channel is ready * @throw Exception if channel is in FATAL_ERROR state */ public function waitForReady($timeout) { $new_state = $this->getConnectivityState(true); if ($this->_checkConnectivityState($new_state)) { return true; } $now = Timeval::now(); $delta = new Timeval($timeout); $deadline = $now->add($delta); while ($this->channel->watchConnectivityState($new_state, $deadline)) { // state has changed before deadline $new_state = $this->getConnectivityState(); if ($this->_checkConnectivityState($new_state)) { return true; } } // deadline has passed $new_state = $this->getConnectivityState(); return $this->_checkConnectivityState($new_state); } /** * Close the communication channel associated with this stub. */ public function close() { $this->channel->close(); } /** * @param $new_state Connect state * * @return bool true if state is CHANNEL_READY * @throw Exception if state is CHANNEL_FATAL_FAILURE */ private function _checkConnectivityState($new_state) { if ($new_state == \Grpc\CHANNEL_READY) { return true; } if ($new_state == \Grpc\CHANNEL_FATAL_FAILURE) { throw new \Exception('Failed to connect to server'); } return false; } /** * constructs the auth uri for the jwt. * * @param string $method The method string * * @return string The URL string */ private function _get_jwt_aud_uri($method) { $last_slash_idx = strrpos($method, '/'); if ($last_slash_idx === false) { throw new \InvalidArgumentException( 'service name must have a slash'); } $service_name = substr($method, 0, $last_slash_idx); if ($this->hostname_override) { $hostname = $this->hostname_override; } else { $hostname = $this->hostname; } return 'https://'.$hostname.$service_name; } /** * validate and normalize the metadata array. * * @param array $metadata The metadata map * * @return array $metadata Validated and key-normalized metadata map * @throw InvalidArgumentException if key contains invalid characters */ private function _validate_and_normalize_metadata($metadata) { $metadata_copy = []; foreach ($metadata as $key => $value) { if (!preg_match('/^[A-Za-z\d_-]+$/', $key)) { throw new \InvalidArgumentException( 'Metadata keys must be nonempty strings containing only '. 'alphanumeric characters, hyphens and underscores'); } $metadata_copy[strtolower($key)] = $value; } return $metadata_copy; } /* This class is intended to be subclassed by generated code, so * all functions begin with "_" to avoid name collisions. */ /** * Call a remote method that takes a single argument and has a * single output. * * @param string $method The name of the method to call * @param mixed $argument The argument to the method * @param callable $deserialize A function that deserializes the response * @param array $metadata A metadata map to send to the server * (optional) * @param array $options An array of options (optional) * * @return SimpleSurfaceActiveCall The active call object */ protected function _simpleRequest($method, $argument, $deserialize, array $metadata = [], array $options = []) { $call = new UnaryCall($this->channel, $method, $deserialize, $options); $jwt_aud_uri = $this->_get_jwt_aud_uri($method); if (is_callable($this->update_metadata)) { $metadata = call_user_func($this->update_metadata, $metadata, $jwt_aud_uri); } $metadata = $this->_validate_and_normalize_metadata( $metadata); $call->start($argument, $metadata, $options); return $call; } /** * Call a remote method that takes a stream of arguments and has a single * output. * * @param string $method The name of the method to call * @param callable $deserialize A function that deserializes the response * @param array $metadata A metadata map to send to the server * (optional) * @param array $options An array of options (optional) * * @return ClientStreamingSurfaceActiveCall The active call object */ protected function _clientStreamRequest($method, $deserialize, array $metadata = [], array $options = []) { $call = new ClientStreamingCall($this->channel, $method, $deserialize, $options); $jwt_aud_uri = $this->_get_jwt_aud_uri($method); if (is_callable($this->update_metadata)) { $metadata = call_user_func($this->update_metadata, $metadata, $jwt_aud_uri); } $metadata = $this->_validate_and_normalize_metadata( $metadata); $call->start($metadata); return $call; } /** * Call a remote method that takes a single argument and returns a stream * of responses. * * @param string $method The name of the method to call * @param mixed $argument The argument to the method * @param callable $deserialize A function that deserializes the responses * @param array $metadata A metadata map to send to the server * (optional) * @param array $options An array of options (optional) * * @return ServerStreamingSurfaceActiveCall The active call object */ protected function _serverStreamRequest($method, $argument, $deserialize, array $metadata = [], array $options = []) { $call = new ServerStreamingCall($this->channel, $method, $deserialize, $options); $jwt_aud_uri = $this->_get_jwt_aud_uri($method); if (is_callable($this->update_metadata)) { $metadata = call_user_func($this->update_metadata, $metadata, $jwt_aud_uri); } $metadata = $this->_validate_and_normalize_metadata( $metadata); $call->start($argument, $metadata, $options); return $call; } /** * Call a remote method with messages streaming in both directions. * * @param string $method The name of the method to call * @param callable $deserialize A function that deserializes the responses * @param array $metadata A metadata map to send to the server * (optional) * @param array $options An array of options (optional) * * @return BidiStreamingSurfaceActiveCall The active call object */ protected function _bidiRequest($method, $deserialize, array $metadata = [], array $options = []) { $call = new BidiStreamingCall($this->channel, $method, $deserialize, $options); $jwt_aud_uri = $this->_get_jwt_aud_uri($method); if (is_callable($this->update_metadata)) { $metadata = call_user_func($this->update_metadata, $metadata, $jwt_aud_uri); } $metadata = $this->_validate_and_normalize_metadata( $metadata); $call->start($metadata); return $call; } } grpc-1.3.2/src/php/lib/Grpc/BidiStreamingCall.php000066400000000000000000000076141310511640000215140ustar00rootroot00000000000000call->startBatch([ OP_SEND_INITIAL_METADATA => $metadata, ]); } /** * Reads the next value from the server. * * @return mixed The next value from the server, or null if there is none */ public function read() { $batch = [OP_RECV_MESSAGE => true]; if ($this->metadata === null) { $batch[OP_RECV_INITIAL_METADATA] = true; } $read_event = $this->call->startBatch($batch); if ($this->metadata === null) { $this->metadata = $read_event->metadata; } return $this->_deserializeResponse($read_event->message); } /** * Write a single message to the server. This cannot be called after * writesDone is called. * * @param ByteBuffer $data The data to write * @param array $options An array of options, possible keys: * 'flags' => a number (optional) */ public function write($data, array $options = []) { $message_array = ['message' => $this->_serializeMessage($data)]; if (array_key_exists('flags', $options)) { $message_array['flags'] = $options['flags']; } $this->call->startBatch([ OP_SEND_MESSAGE => $message_array, ]); } /** * Indicate that no more writes will be sent. */ public function writesDone() { $this->call->startBatch([ OP_SEND_CLOSE_FROM_CLIENT => true, ]); } /** * Wait for the server to send the status, and return it. * * @return \stdClass The status object, with integer $code, string * $details, and array $metadata members */ public function getStatus() { $status_event = $this->call->startBatch([ OP_RECV_STATUS_ON_CLIENT => true, ]); $this->trailing_metadata = $status_event->status->metadata; return $status_event->status; } } grpc-1.3.2/src/php/lib/Grpc/ClientStreamingCall.php000066400000000000000000000064051310511640000220600ustar00rootroot00000000000000call->startBatch([ OP_SEND_INITIAL_METADATA => $metadata, ]); } /** * Write a single message to the server. This cannot be called after * wait is called. * * @param ByteBuffer $data The data to write * @param array $options An array of options, possible keys: * 'flags' => a number (optional) */ public function write($data, array $options = []) { $message_array = ['message' => $this->_serializeMessage($data)]; if (array_key_exists('flags', $options)) { $message_array['flags'] = $options['flags']; } $this->call->startBatch([ OP_SEND_MESSAGE => $message_array, ]); } /** * Wait for the server to respond with data and a status. * * @return array [response data, status] */ public function wait() { $event = $this->call->startBatch([ OP_SEND_CLOSE_FROM_CLIENT => true, OP_RECV_INITIAL_METADATA => true, OP_RECV_MESSAGE => true, OP_RECV_STATUS_ON_CLIENT => true, ]); $this->metadata = $event->metadata; $status = $event->status; $this->trailing_metadata = $status->metadata; return [$this->_deserializeResponse($event->message), $status]; } } grpc-1.3.2/src/php/lib/Grpc/ServerStreamingCall.php000066400000000000000000000067651310511640000221210ustar00rootroot00000000000000 a number (optional) */ public function start($data, array $metadata = [], array $options = []) { $message_array = ['message' => $this->_serializeMessage($data)]; if (array_key_exists('flags', $options)) { $message_array['flags'] = $options['flags']; } $event = $this->call->startBatch([ OP_SEND_INITIAL_METADATA => $metadata, OP_RECV_INITIAL_METADATA => true, OP_SEND_MESSAGE => $message_array, OP_SEND_CLOSE_FROM_CLIENT => true, ]); $this->metadata = $event->metadata; } /** * @return mixed An iterator of response values */ public function responses() { $response = $this->call->startBatch([ OP_RECV_MESSAGE => true, ])->message; while ($response !== null) { yield $this->_deserializeResponse($response); $response = $this->call->startBatch([ OP_RECV_MESSAGE => true, ])->message; } } /** * Wait for the server to send the status, and return it. * * @return \stdClass The status object, with integer $code, string * $details, and array $metadata members */ public function getStatus() { $status_event = $this->call->startBatch([ OP_RECV_STATUS_ON_CLIENT => true, ]); $this->trailing_metadata = $status_event->status->metadata; return $status_event->status; } } grpc-1.3.2/src/php/lib/Grpc/UnaryCall.php000066400000000000000000000060341310511640000200640ustar00rootroot00000000000000 a number (optional) */ public function start($data, array $metadata = [], array $options = []) { $message_array = ['message' => $this->_serializeMessage($data)]; if (isset($options['flags'])) { $message_array['flags'] = $options['flags']; } $event = $this->call->startBatch([ OP_SEND_INITIAL_METADATA => $metadata, OP_RECV_INITIAL_METADATA => true, OP_SEND_MESSAGE => $message_array, OP_SEND_CLOSE_FROM_CLIENT => true, ]); $this->metadata = $event->metadata; } /** * Wait for the server to respond with data and a status. * * @return array [response data, status] */ public function wait() { $event = $this->call->startBatch([ OP_RECV_MESSAGE => true, OP_RECV_STATUS_ON_CLIENT => true, ]); $status = $event->status; $this->trailing_metadata = $status->metadata; return [$this->_deserializeResponse($event->message), $status]; } } grpc-1.3.2/src/php/phpunit.xml000066400000000000000000000013621310511640000162300ustar00rootroot00000000000000 tests/unit_tests tests/generated_code/GeneratedCodeTest.php tests/generated_code/GeneratedCodeWithCallbackTest.php lib/Grpc grpc-1.3.2/src/php/tests/000077500000000000000000000000001310511640000151575ustar00rootroot00000000000000grpc-1.3.2/src/php/tests/bootstrap.php000066400000000000000000000013231310511640000177040ustar00rootroot00000000000000assertFalse(self::$client->waitForReady(1)); } public function testWaitForReady() { $this->assertTrue(self::$client->waitForReady(250000)); } public function testAlreadyReady() { $this->assertTrue(self::$client->waitForReady(250000)); $this->assertTrue(self::$client->waitForReady(100)); } public function testGetTarget() { $this->assertTrue(is_string(self::$client->getTarget())); } /** * @expectedException InvalidArgumentException */ public function testClose() { self::$client->close(); $div_arg = new Math\DivArgs(); $call = self::$client->Div($div_arg); } /** * @expectedException InvalidArgumentException */ public function testInvalidMetadata() { $div_arg = new Math\DivArgs(); $call = self::$client->Div($div_arg, [' ' => 'abc123']); } public function testGetCallMetadata() { $div_arg = new Math\DivArgs(); $call = self::$client->Div($div_arg); $this->assertTrue(is_array($call->getMetadata())); } public function testTimeout() { $div_arg = new Math\DivArgs(); $call = self::$client->Div($div_arg, [], ['timeout' => 1]); list($response, $status) = $call->wait(); $this->assertSame(\Grpc\STATUS_DEADLINE_EXCEEDED, $status->code); } public function testCancel() { $div_arg = new Math\DivArgs(); $call = self::$client->Div($div_arg); $call->cancel(); list($response, $status) = $call->wait(); $this->assertSame(\Grpc\STATUS_CANCELLED, $status->code); } public function testCallCredentialsCallback() { $div_arg = new Math\DivArgs(); $call = self::$client->Div($div_arg, array(), array( 'call_credentials_callback' => function ($context) { return array(); }, )); $call->cancel(); list($response, $status) = $call->wait(); $this->assertSame(\Grpc\STATUS_CANCELLED, $status->code); } public function testCallCredentialsCallback2() { $div_arg = new Math\DivArgs(); $call = self::$client->Div($div_arg); $call_credentials = Grpc\CallCredentials::createFromPlugin( function ($context) { return array(); } ); $call->setCallCredentials($call_credentials); $call->cancel(); list($response, $status) = $call->wait(); $this->assertSame(\Grpc\STATUS_CANCELLED, $status->code); } /** * @expectedException InvalidArgumentException */ public function testInvalidMethodName() { $invalid_client = new DummyInvalidClient('host', [ 'credentials' => Grpc\ChannelCredentials::createInsecure(), ]); $div_arg = new Math\DivArgs(); $invalid_client->InvalidUnaryCall($div_arg); } /** * @expectedException Exception */ public function testMissingCredentials() { $invalid_client = new DummyInvalidClient('host', [ ]); } public function testPrimaryUserAgentString() { $invalid_client = new DummyInvalidClient('host', [ 'credentials' => Grpc\ChannelCredentials::createInsecure(), 'grpc.primary_user_agent' => 'testUserAgent', ]); } public function testWriteFlags() { $div_arg = new Math\DivArgs(); $div_arg->setDividend(7); $div_arg->setDivisor(4); $call = self::$client->Div($div_arg, [], ['flags' => Grpc\WRITE_NO_COMPRESS]); $this->assertTrue(is_string($call->getPeer())); list($response, $status) = $call->wait(); $this->assertSame(1, $response->getQuotient()); $this->assertSame(3, $response->getRemainder()); $this->assertSame(\Grpc\STATUS_OK, $status->code); } public function testWriteFlagsServerStreaming() { $fib_arg = new Math\FibArgs(); $fib_arg->setLimit(7); $call = self::$client->Fib($fib_arg, [], ['flags' => Grpc\WRITE_NO_COMPRESS]); $result_array = iterator_to_array($call->responses()); $status = $call->getStatus(); $this->assertSame(\Grpc\STATUS_OK, $status->code); } public function testWriteFlagsClientStreaming() { $call = self::$client->Sum(); $num = new Math\Num(); $num->setNum(1); $call->write($num, ['flags' => Grpc\WRITE_NO_COMPRESS]); list($response, $status) = $call->wait(); $this->assertSame(\Grpc\STATUS_OK, $status->code); } public function testWriteFlagsBidiStreaming() { $call = self::$client->DivMany(); $div_arg = new Math\DivArgs(); $div_arg->setDividend(7); $div_arg->setDivisor(4); $call->write($div_arg, ['flags' => Grpc\WRITE_NO_COMPRESS]); $response = $call->read(); $call->writesDone(); $status = $call->getStatus(); $this->assertSame(\Grpc\STATUS_OK, $status->code); } public function testSimpleRequest() { $div_arg = new Math\DivArgs(); $div_arg->setDividend(7); $div_arg->setDivisor(4); $call = self::$client->Div($div_arg); $this->assertTrue(is_string($call->getPeer())); list($response, $status) = $call->wait(); $this->assertSame(1, $response->getQuotient()); $this->assertSame(3, $response->getRemainder()); $this->assertSame(\Grpc\STATUS_OK, $status->code); } public function testServerStreaming() { $fib_arg = new Math\FibArgs(); $fib_arg->setLimit(7); $call = self::$client->Fib($fib_arg); $this->assertTrue(is_string($call->getPeer())); $result_array = iterator_to_array($call->responses()); $extract_num = function ($num) { return $num->getNum(); }; $values = array_map($extract_num, $result_array); $this->assertSame([1, 1, 2, 3, 5, 8, 13], $values); $status = $call->getStatus(); $this->assertSame(\Grpc\STATUS_OK, $status->code); } public function testClientStreaming() { $call = self::$client->Sum(); $this->assertTrue(is_string($call->getPeer())); for ($i = 0; $i < 7; ++$i) { $num = new Math\Num(); $num->setNum($i); $call->write($num); } list($response, $status) = $call->wait(); $this->assertSame(21, $response->getNum()); $this->assertSame(\Grpc\STATUS_OK, $status->code); } public function testBidiStreaming() { $call = self::$client->DivMany(); $this->assertTrue(is_string($call->getPeer())); for ($i = 0; $i < 7; ++$i) { $div_arg = new Math\DivArgs(); $div_arg->setDividend(2 * $i + 1); $div_arg->setDivisor(2); $call->write($div_arg); $response = $call->read(); $this->assertSame($i, $response->getQuotient()); $this->assertSame(1, $response->getRemainder()); } $call->writesDone(); $status = $call->getStatus(); $this->assertSame(\Grpc\STATUS_OK, $status->code); } } class DummyInvalidClient extends \Grpc\BaseStub { public function InvalidUnaryCall(\Math\DivArgs $argument, $metadata = [], $options = []) { return $this->_simpleRequest('invalidMethodName', $argument, function () {}, $metadata, $options); } } grpc-1.3.2/src/php/tests/generated_code/GeneratedCodeTest.php000077500000000000000000000037141310511640000241610ustar00rootroot00000000000000 Grpc\ChannelCredentials::createInsecure(), ]); } public function tearDown() { self::$client->close(); } } grpc-1.3.2/src/php/tests/generated_code/GeneratedCodeWithCallbackTest.php000066400000000000000000000043601310511640000264250ustar00rootroot00000000000000 Grpc\ChannelCredentials::createInsecure(), 'update_metadata' => function ($a_hash, $client = []) { $a_copy = $a_hash; $a_copy['foo'] = ['bar']; return $a_copy; }, ]); } public function tearDown() { self::$client->close(); } } grpc-1.3.2/src/php/tests/generated_code/math_client.php000066400000000000000000000070171310511640000231140ustar00rootroot00000000000000\n"; } $host = 'localhost:50051'; p("Connecting to host: $host"); $client = new Math\MathClient($host, [ 'credentials' => Grpc\ChannelCredentials::createInsecure(), ]); p('Client class: '.get_class($client)); p(''); p('Running unary call test:'); $dividend = 7; $divisor = 4; $div_arg = new Math\DivArgs(); $div_arg->setDividend($dividend); $div_arg->setDivisor($divisor); $call = $client->Div($div_arg); p('Call peer: '.$call->getPeer()); p("Dividing $dividend by $divisor"); list($response, $status) = $call->wait(); p('quotient = '.$response->getQuotient()); p('remainder = '.$response->getRemainder()); p(''); p('Running server streaming test:'); $limit = 7; $fib_arg = new Math\FibArgs(); $fib_arg->setLimit($limit); $call = $client->Fib($fib_arg); $result_array = iterator_to_array($call->responses()); $result = ''; foreach ($result_array as $num) { $result .= ' '.$num->getNum(); } p("The first $limit Fibonacci numbers are:".$result); p(''); p('Running client streaming test:'); $call = $client->Sum(); for ($i = 0; $i <= $limit; ++$i) { $num = new Math\Num(); $num->setNum($i); $call->write($num); } list($response, $status) = $call->wait(); p(sprintf('The first %d positive integers sum to: %d', $limit, $response->getNum())); p(''); p('Running bidi-streaming test:'); $call = $client->DivMany(); for ($i = 0; $i < 7; ++$i) { $div_arg = new Math\DivArgs(); $dividend = 2 * $i + 1; $divisor = 3; $div_arg->setDividend($dividend); $div_arg->setDivisor($divisor); $call->write($div_arg); p("client writing: $dividend / $divisor"); $response = $call->read(); p(sprintf('server writing: quotient = %d, remainder = %d', $response->getQuotient(), $response->getRemainder())); } $call->writesDone(); grpc-1.3.2/src/php/tests/interop/000077500000000000000000000000001310511640000166375ustar00rootroot00000000000000grpc-1.3.2/src/php/tests/interop/interop_client.php000077500000000000000000000570121310511640000223760ustar00rootroot00000000000000code !== Grpc\STATUS_OK) { echo "Call did not complete successfully. Status object:\n"; var_dump($status); exit(1); } } /** * Run the empty_unary test. * * @param $stub Stub object that has service methods */ function emptyUnary($stub) { list($result, $status) = $stub->EmptyCall(new Grpc\Testing\EmptyMessage())->wait(); hardAssertIfStatusOk($status); hardAssert($result !== null, 'Call completed with a null response'); } /** * Run the large_unary test. * * @param $stub Stub object that has service methods */ function largeUnary($stub) { performLargeUnary($stub); } /** * Shared code between large unary test and auth test. * * @param $stub Stub object that has service methods * @param $fillUsername boolean whether to fill result with username * @param $fillOauthScope boolean whether to fill result with oauth scope */ function performLargeUnary($stub, $fillUsername = false, $fillOauthScope = false, $callback = false) { $request_len = 271828; $response_len = 314159; $request = new Grpc\Testing\SimpleRequest(); $request->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE); $request->setResponseSize($response_len); $payload = new Grpc\Testing\Payload(); $payload->setType(Grpc\Testing\PayloadType::COMPRESSABLE); $payload->setBody(str_repeat("\0", $request_len)); $request->setPayload($payload); $request->setFillUsername($fillUsername); $request->setFillOauthScope($fillOauthScope); $options = []; if ($callback) { $options['call_credentials_callback'] = $callback; } list($result, $status) = $stub->UnaryCall($request, [], $options)->wait(); hardAssertIfStatusOk($status); hardAssert($result !== null, 'Call returned a null response'); $payload = $result->getPayload(); hardAssert($payload->getType() === Grpc\Testing\PayloadType::COMPRESSABLE, 'Payload had the wrong type'); hardAssert(strlen($payload->getBody()) === $response_len, 'Payload had the wrong length'); hardAssert($payload->getBody() === str_repeat("\0", $response_len), 'Payload had the wrong content'); return $result; } /** * Run the service account credentials auth test. * * @param $stub Stub object that has service methods * @param $args array command line args */ function serviceAccountCreds($stub, $args) { if (!array_key_exists('oauth_scope', $args)) { throw new Exception('Missing oauth scope'); } $jsonKey = json_decode( file_get_contents(getenv(CredentialsLoader::ENV_VAR)), true); $result = performLargeUnary($stub, $fillUsername = true, $fillOauthScope = true); hardAssert($result->getUsername() === $jsonKey['client_email'], 'invalid email returned'); hardAssert(strpos($args['oauth_scope'], $result->getOauthScope()) !== false, 'invalid oauth scope returned'); } /** * Run the compute engine credentials auth test. * Has not been run from gcloud as of 2015-05-05. * * @param $stub Stub object that has service methods * @param $args array command line args */ function computeEngineCreds($stub, $args) { if (!array_key_exists('oauth_scope', $args)) { throw new Exception('Missing oauth scope'); } if (!array_key_exists('default_service_account', $args)) { throw new Exception('Missing default_service_account'); } $result = performLargeUnary($stub, $fillUsername = true, $fillOauthScope = true); hardAssert($args['default_service_account'] === $result->getUsername(), 'invalid email returned'); } /** * Run the jwt token credentials auth test. * * @param $stub Stub object that has service methods * @param $args array command line args */ function jwtTokenCreds($stub, $args) { $jsonKey = json_decode( file_get_contents(getenv(CredentialsLoader::ENV_VAR)), true); $result = performLargeUnary($stub, $fillUsername = true, $fillOauthScope = true); hardAssert($result->getUsername() === $jsonKey['client_email'], 'invalid email returned'); } /** * Run the oauth2_auth_token auth test. * * @param $stub Stub object that has service methods * @param $args array command line args */ function oauth2AuthToken($stub, $args) { $jsonKey = json_decode( file_get_contents(getenv(CredentialsLoader::ENV_VAR)), true); $result = performLargeUnary($stub, $fillUsername = true, $fillOauthScope = true); hardAssert($result->getUsername() === $jsonKey['client_email'], 'invalid email returned'); } function updateAuthMetadataCallback($context) { $authUri = $context->service_url; $methodName = $context->method_name; $auth_credentials = ApplicationDefaultCredentials::getCredentials(); $metadata = []; $result = $auth_credentials->updateMetadata([], $authUri); foreach ($result as $key => $value) { $metadata[strtolower($key)] = $value; } return $metadata; } /** * Run the per_rpc_creds auth test. * * @param $stub Stub object that has service methods * @param $args array command line args */ function perRpcCreds($stub, $args) { $jsonKey = json_decode( file_get_contents(getenv(CredentialsLoader::ENV_VAR)), true); $result = performLargeUnary($stub, $fillUsername = true, $fillOauthScope = true, 'updateAuthMetadataCallback'); hardAssert($result->getUsername() === $jsonKey['client_email'], 'invalid email returned'); } /** * Run the client_streaming test. * * @param $stub Stub object that has service methods */ function clientStreaming($stub) { $request_lengths = [27182, 8, 1828, 45904]; $requests = array_map( function ($length) { $request = new Grpc\Testing\StreamingInputCallRequest(); $payload = new Grpc\Testing\Payload(); $payload->setBody(str_repeat("\0", $length)); $request->setPayload($payload); return $request; }, $request_lengths); $call = $stub->StreamingInputCall(); foreach ($requests as $request) { $call->write($request); } list($result, $status) = $call->wait(); hardAssertIfStatusOk($status); hardAssert($result->getAggregatedPayloadSize() === 74922, 'aggregated_payload_size was incorrect'); } /** * Run the server_streaming test. * * @param $stub Stub object that has service methods. */ function serverStreaming($stub) { $sizes = [31415, 9, 2653, 58979]; $request = new Grpc\Testing\StreamingOutputCallRequest(); $request->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE); foreach ($sizes as $size) { $response_parameters = new Grpc\Testing\ResponseParameters(); $response_parameters->setSize($size); $request->getResponseParameters()[] = $response_parameters; } $call = $stub->StreamingOutputCall($request); $i = 0; foreach ($call->responses() as $value) { hardAssert($i < 4, 'Too many responses'); $payload = $value->getPayload(); hardAssert( $payload->getType() === Grpc\Testing\PayloadType::COMPRESSABLE, 'Payload '.$i.' had the wrong type'); hardAssert(strlen($payload->getBody()) === $sizes[$i], 'Response '.$i.' had the wrong length'); $i += 1; } hardAssertIfStatusOk($call->getStatus()); } /** * Run the ping_pong test. * * @param $stub Stub object that has service methods. */ function pingPong($stub) { $request_lengths = [27182, 8, 1828, 45904]; $response_lengths = [31415, 9, 2653, 58979]; $call = $stub->FullDuplexCall(); for ($i = 0; $i < 4; ++$i) { $request = new Grpc\Testing\StreamingOutputCallRequest(); $request->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE); $response_parameters = new Grpc\Testing\ResponseParameters(); $response_parameters->setSize($response_lengths[$i]); $request->getResponseParameters()[] = $response_parameters; $payload = new Grpc\Testing\Payload(); $payload->setBody(str_repeat("\0", $request_lengths[$i])); $request->setPayload($payload); $call->write($request); $response = $call->read(); hardAssert($response !== null, 'Server returned too few responses'); $payload = $response->getPayload(); hardAssert( $payload->getType() === Grpc\Testing\PayloadType::COMPRESSABLE, 'Payload '.$i.' had the wrong type'); hardAssert(strlen($payload->getBody()) === $response_lengths[$i], 'Payload '.$i.' had the wrong length'); } $call->writesDone(); hardAssert($call->read() === null, 'Server returned too many responses'); hardAssertIfStatusOk($call->getStatus()); } /** * Run the empty_stream test. * * @param $stub Stub object that has service methods. */ function emptyStream($stub) { $call = $stub->FullDuplexCall(); $call->writesDone(); hardAssert($call->read() === null, 'Server returned too many responses'); hardAssertIfStatusOk($call->getStatus()); } /** * Run the cancel_after_begin test. * * @param $stub Stub object that has service methods. */ function cancelAfterBegin($stub) { $call = $stub->StreamingInputCall(); $call->cancel(); list($result, $status) = $call->wait(); hardAssert($status->code === Grpc\STATUS_CANCELLED, 'Call status was not CANCELLED'); } /** * Run the cancel_after_first_response test. * * @param $stub Stub object that has service methods. */ function cancelAfterFirstResponse($stub) { $call = $stub->FullDuplexCall(); $request = new Grpc\Testing\StreamingOutputCallRequest(); $request->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE); $response_parameters = new Grpc\Testing\ResponseParameters(); $response_parameters->setSize(31415); $request->getResponseParameters()[] = $response_parameters; $payload = new Grpc\Testing\Payload(); $payload->setBody(str_repeat("\0", 27182)); $request->setPayload($payload); $call->write($request); $response = $call->read(); $call->cancel(); hardAssert($call->getStatus()->code === Grpc\STATUS_CANCELLED, 'Call status was not CANCELLED'); } function timeoutOnSleepingServer($stub) { $call = $stub->FullDuplexCall([], ['timeout' => 1000]); $request = new Grpc\Testing\StreamingOutputCallRequest(); $request->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE); $response_parameters = new Grpc\Testing\ResponseParameters(); $response_parameters->setSize(8); $request->getResponseParameters()[] = $response_parameters; $payload = new Grpc\Testing\Payload(); $payload->setBody(str_repeat("\0", 9)); $request->setPayload($payload); $call->write($request); $response = $call->read(); hardAssert($call->getStatus()->code === Grpc\STATUS_DEADLINE_EXCEEDED, 'Call status was not DEADLINE_EXCEEDED'); } function customMetadata($stub) { $ECHO_INITIAL_KEY = 'x-grpc-test-echo-initial'; $ECHO_INITIAL_VALUE = 'test_initial_metadata_value'; $ECHO_TRAILING_KEY = 'x-grpc-test-echo-trailing-bin'; $ECHO_TRAILING_VALUE = 'ababab'; $request_len = 271828; $response_len = 314159; $request = new Grpc\Testing\SimpleRequest(); $request->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE); $request->setResponseSize($response_len); $payload = new Grpc\Testing\Payload(); $payload->setType(Grpc\Testing\PayloadType::COMPRESSABLE); $payload->setBody(str_repeat("\0", $request_len)); $request->setPayload($payload); $metadata = [ $ECHO_INITIAL_KEY => [$ECHO_INITIAL_VALUE], $ECHO_TRAILING_KEY => [$ECHO_TRAILING_VALUE], ]; $call = $stub->UnaryCall($request, $metadata); $initial_metadata = $call->getMetadata(); hardAssert(array_key_exists($ECHO_INITIAL_KEY, $initial_metadata), 'Initial metadata does not contain expected key'); hardAssert( $initial_metadata[$ECHO_INITIAL_KEY][0] === $ECHO_INITIAL_VALUE, 'Incorrect initial metadata value'); list($result, $status) = $call->wait(); hardAssertIfStatusOk($status); $trailing_metadata = $call->getTrailingMetadata(); hardAssert(array_key_exists($ECHO_TRAILING_KEY, $trailing_metadata), 'Trailing metadata does not contain expected key'); hardAssert( $trailing_metadata[$ECHO_TRAILING_KEY][0] === $ECHO_TRAILING_VALUE, 'Incorrect trailing metadata value'); $streaming_call = $stub->FullDuplexCall($metadata); $streaming_request = new Grpc\Testing\StreamingOutputCallRequest(); $streaming_request->setPayload($payload); $response_parameters = new Grpc\Testing\ResponseParameters(); $response_parameters->setSize($response_len); $streaming_request->getResponseParameters()[] = $response_parameters; $streaming_call->write($streaming_request); $streaming_call->writesDone(); $result = $streaming_call->read(); hardAssertIfStatusOk($streaming_call->getStatus()); $streaming_initial_metadata = $streaming_call->getMetadata(); hardAssert(array_key_exists($ECHO_INITIAL_KEY, $streaming_initial_metadata), 'Initial metadata does not contain expected key'); hardAssert( $streaming_initial_metadata[$ECHO_INITIAL_KEY][0] === $ECHO_INITIAL_VALUE, 'Incorrect initial metadata value'); $streaming_trailing_metadata = $streaming_call->getTrailingMetadata(); hardAssert(array_key_exists($ECHO_TRAILING_KEY, $streaming_trailing_metadata), 'Trailing metadata does not contain expected key'); hardAssert($streaming_trailing_metadata[$ECHO_TRAILING_KEY][0] === $ECHO_TRAILING_VALUE, 'Incorrect trailing metadata value'); } function statusCodeAndMessage($stub) { $echo_status = new Grpc\Testing\EchoStatus(); $echo_status->setCode(2); $echo_status->setMessage('test status message'); $request = new Grpc\Testing\SimpleRequest(); $request->setResponseStatus($echo_status); $call = $stub->UnaryCall($request); list($result, $status) = $call->wait(); hardAssert($status->code === 2, 'Received unexpected UnaryCall status code: '. $status->code); hardAssert($status->details === 'test status message', 'Received unexpected UnaryCall status details: '. $status->details); $streaming_call = $stub->FullDuplexCall(); $streaming_request = new Grpc\Testing\StreamingOutputCallRequest(); $streaming_request->setResponseStatus($echo_status); $streaming_call->write($streaming_request); $streaming_call->writesDone(); $result = $streaming_call->read(); $status = $streaming_call->getStatus(); hardAssert($status->code === 2, 'Received unexpected FullDuplexCall status code: '. $status->code); hardAssert($status->details === 'test status message', 'Received unexpected FullDuplexCall status details: '. $status->details); } # NOTE: the stub input to this function is from UnimplementedService function unimplementedService($stub) { $call = $stub->UnimplementedCall(new Grpc\Testing\EmptyMessage()); list($result, $status) = $call->wait(); hardAssert($status->code === Grpc\STATUS_UNIMPLEMENTED, 'Received unexpected status code'); } # NOTE: the stub input to this function is from TestService function unimplementedMethod($stub) { $call = $stub->UnimplementedCall(new Grpc\Testing\EmptyMessage()); list($result, $status) = $call->wait(); hardAssert($status->code === Grpc\STATUS_UNIMPLEMENTED, 'Received unexpected status code'); } function _makeStub($args) { if (!array_key_exists('server_host', $args)) { throw new Exception('Missing argument: --server_host is required'); } if (!array_key_exists('server_port', $args)) { throw new Exception('Missing argument: --server_port is required'); } if (!array_key_exists('test_case', $args)) { throw new Exception('Missing argument: --test_case is required'); } if ($args['server_port'] === 443) { $server_address = $args['server_host']; } else { $server_address = $args['server_host'].':'.$args['server_port']; } $test_case = $args['test_case']; $host_override = 'foo.test.google.fr'; if (array_key_exists('server_host_override', $args)) { $host_override = $args['server_host_override']; } $use_tls = false; if (array_key_exists('use_tls', $args) && $args['use_tls'] != 'false') { $use_tls = true; } $use_test_ca = false; if (array_key_exists('use_test_ca', $args) && $args['use_test_ca'] != 'false') { $use_test_ca = true; } $opts = []; if ($use_tls) { if ($use_test_ca) { $ssl_credentials = Grpc\ChannelCredentials::createSsl( file_get_contents(dirname(__FILE__).'/../data/ca.pem')); } else { $ssl_credentials = Grpc\ChannelCredentials::createSsl(); } $opts['credentials'] = $ssl_credentials; $opts['grpc.ssl_target_name_override'] = $host_override; } else { $opts['credentials'] = Grpc\ChannelCredentials::createInsecure(); } if (in_array($test_case, ['service_account_creds', 'compute_engine_creds', 'jwt_token_creds', ])) { if ($test_case === 'jwt_token_creds') { $auth_credentials = ApplicationDefaultCredentials::getCredentials(); } else { $auth_credentials = ApplicationDefaultCredentials::getCredentials( $args['oauth_scope'] ); } $opts['update_metadata'] = $auth_credentials->getUpdateMetadataFunc(); } if ($test_case === 'oauth2_auth_token') { $auth_credentials = ApplicationDefaultCredentials::getCredentials( $args['oauth_scope'] ); $token = $auth_credentials->fetchAuthToken(); $update_metadata = function ($metadata, $authUri = null, ClientInterface $client = null) use ($token) { $metadata_copy = $metadata; $metadata_copy[CredentialsLoader::AUTH_METADATA_KEY] = [sprintf('%s %s', $token['token_type'], $token['access_token'])]; return $metadata_copy; }; $opts['update_metadata'] = $update_metadata; } if ($test_case === 'unimplemented_service') { $stub = new Grpc\Testing\UnimplementedServiceClient($server_address, $opts); } else { $stub = new Grpc\Testing\TestServiceClient($server_address, $opts); } return $stub; } function interop_main($args, $stub = false) { if (!$stub) { $stub = _makeStub($args); } $test_case = $args['test_case']; echo "Running test case $test_case\n"; switch ($test_case) { case 'empty_unary': emptyUnary($stub); break; case 'large_unary': largeUnary($stub); break; case 'client_streaming': clientStreaming($stub); break; case 'server_streaming': serverStreaming($stub); break; case 'ping_pong': pingPong($stub); break; case 'empty_stream': emptyStream($stub); break; case 'cancel_after_begin': cancelAfterBegin($stub); break; case 'cancel_after_first_response': cancelAfterFirstResponse($stub); break; case 'timeout_on_sleeping_server': timeoutOnSleepingServer($stub); break; case 'custom_metadata': customMetadata($stub); break; case 'status_code_and_message': statusCodeAndMessage($stub); break; case 'unimplemented_service': unimplementedService($stub); break; case 'unimplemented_method': unimplementedMethod($stub); break; case 'service_account_creds': serviceAccountCreds($stub, $args); break; case 'compute_engine_creds': computeEngineCreds($stub, $args); break; case 'jwt_token_creds': jwtTokenCreds($stub, $args); break; case 'oauth2_auth_token': oauth2AuthToken($stub, $args); break; case 'per_rpc_creds': perRpcCreds($stub, $args); break; default: echo "Unsupported test case $test_case\n"; exit(1); } return $stub; } if (isset($_SERVER['PHP_SELF']) && preg_match('/interop_client/', $_SERVER['PHP_SELF'])) { $args = getopt('', ['server_host:', 'server_port:', 'test_case:', 'use_tls::', 'use_test_ca::', 'server_host_override:', 'oauth_scope:', 'default_service_account:', ]); interop_main($args); } grpc-1.3.2/src/php/tests/interop/metrics_client.php000066400000000000000000000040271310511640000223570ustar00rootroot00000000000000 $deadline) { break; } if ($client_connection = socket_accept($socket)) { // there is an incoming request, respond with qps metrics $input = socket_read($client_connection, 1024); $qps = round($count / ($current_time - $start_time)); socket_write($client_connection, "qps: $qps"); socket_close($client_connection); } else { // do actual work, run one interop test case $args['test_case'] = $args['test_cases'][mt_rand(0, $num_test_cases - 1)]; $stub = @interop_main($args, $stub); ++$count; } } socket_close($socket); echo "Number of interop tests run in $args[test_duration_secs] ". "seconds: $count.\n"; } // process command line arguments $raw_args = getopt('', ['server_addresses::', 'test_cases:', 'metrics_port::', 'test_duration_secs::', 'num_channels_per_server::', 'num_stubs_per_channel::', ]); $args = []; if (empty($raw_args['server_addresses'])) { $args['server_host'] = 'localhost'; $args['server_port'] = '8080'; } else { $parts = explode(':', $raw_args['server_addresses']); $args['server_host'] = $parts[0]; $args['server_port'] = (count($parts) == 2) ? $parts[1] : ''; } $args['metrics_port'] = empty($raw_args['metrics_port']) ? '8081' : $raw_args['metrics_port']; $args['test_duration_secs'] = empty($raw_args['test_duration_secs']) || $raw_args['test_duration_secs'] == -1 ? false : $raw_args['test_duration_secs']; $test_cases = []; $test_case_strs = explode(',', $raw_args['test_cases']); foreach ($test_case_strs as $test_case_str) { $parts = explode(':', $test_case_str); $test_cases = array_merge($test_cases, array_fill(0, $parts[1], $parts[0])); } $args['test_cases'] = $test_cases; stress_main($args); grpc-1.3.2/src/php/tests/qps/000077500000000000000000000000001310511640000157625ustar00rootroot00000000000000grpc-1.3.2/src/php/tests/qps/client.php000066400000000000000000000151751310511640000177620ustar00rootroot00000000000000code !== Grpc\STATUS_OK) { echo "Call did not complete successfully. Status object:\n"; var_dump($status); exit(1); } } /* Start the actual client */ function qps_client_main($proxy_address) { echo "Initiating php client\n"; $proxystubopts = []; $proxystubopts['credentials'] = Grpc\ChannelCredentials::createInsecure(); $proxystub = new Grpc\Testing\ProxyClientServiceClient($proxy_address, $proxystubopts); list($config, $status) = $proxystub->GetConfig(new Grpc\Testing\Void())->wait(); hardAssertIfStatusOk($status); hardAssert($config->getClientChannels() == 1, "Only 1 channel supported"); hardAssert($config->getOutstandingRpcsPerChannel() == 1, "Only 1 outstanding RPC supported"); echo "Got configuration from proxy, target is " . $config->getServerTargets()[0] . "\n"; $stubopts = []; if ($config->getSecurityParams()) { if ($config->getSecurityParams()->getUseTestCa()) { $stubopts['credentials'] = Grpc\ChannelCredentials::createSsl( file_get_contents(dirname(__FILE__).'/../data/ca.pem')); } else { $stubopts['credentials'] = Grpc\ChannelCredentials::createSsl(null); } $override = $config->getSecurityParams()->getServerHostOverride(); if ($override) { $stubopts['grpc.ssl_target_name_override'] = $override; $stubopts['grpc.default_authority'] = $override; } } else { $stubopts['credentials'] = Grpc\ChannelCredentials::createInsecure(); } echo "Initiating php benchmarking client\n"; $stub = new Grpc\Testing\BenchmarkServiceClient( $config->getServerTargets()[0], $stubopts); $req = new Grpc\Testing\SimpleRequest(); $req->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE); $req->setResponseSize($config->getPayloadConfig()->getSimpleParams()->getRespSize()); $payload = new Grpc\Testing\Payload(); $payload->setType(Grpc\Testing\PayloadType::COMPRESSABLE); $payload->setBody(str_repeat("\0", $config->getPayloadConfig()->getSimpleParams()->getReqSize())); $req->setPayload($payload); /* TODO(stanley-cheung): Enable the following by removing the 0&& once protobuf * properly supports oneof in PHP */ if (0 && $config->getLoadParams()->getLoad() == "poisson") { $poisson = true; $lamrecip = 1.0/($config->getLoadParams()->getPoisson()->getOfferedLoad()); $issue = microtime(true) + $lamrecip * -log(1.0-rand()/(getrandmax()+1)); } else { $poisson = false; } $metric = new Grpc\Testing\ProxyStat; $telemetry = $proxystub->ReportTime(); if ($config->getRpcType() == Grpc\Testing\RpcType::UNARY) { while (1) { if ($poisson) { time_sleep_until($issue); $issue = $issue + $lamrecip * -log(1.0-rand()/(getrandmax()+1)); } $startreq = microtime(true); list($resp,$status) = $stub->UnaryCall($req)->wait(); hardAssertIfStatusOk($status); $metric->setLatency(microtime(true)-$startreq); $telemetry->write($metric); } } else { $stream = $stub->StreamingCall(); while (1) { if ($poisson) { time_sleep_until($issue); $issue = $issue + $lamrecip * -log(1.0-rand()/(getrandmax()+1)); } $startreq = microtime(true); $stream->write($req); $resp = $stream->read(); $metric->setLatency(microtime(true)-$startreq); $telemetry->write($metric); } } } ini_set('display_startup_errors', 1); ini_set('display_errors', 1); error_reporting(-1); qps_client_main($argv[1]); grpc-1.3.2/src/php/tests/qps/composer.json000066400000000000000000000002311310511640000205000ustar00rootroot00000000000000{ "minimum-stability": "dev", "require": { "grpc/grpc": "dev-master" }, "autoload": { "psr-4": { "": "generated_code/" } } } grpc-1.3.2/src/php/tests/qps/generated_code/000077500000000000000000000000001310511640000207125ustar00rootroot00000000000000grpc-1.3.2/src/php/tests/qps/generated_code/GPBMetadata/000077500000000000000000000000001310511640000227635ustar00rootroot00000000000000grpc-1.3.2/src/php/tests/qps/generated_code/GPBMetadata/Src/000077500000000000000000000000001310511640000235125ustar00rootroot00000000000000grpc-1.3.2/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/000077500000000000000000000000001310511640000246155ustar00rootroot00000000000000grpc-1.3.2/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/000077500000000000000000000000001310511640000255105ustar00rootroot00000000000000grpc-1.3.2/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/000077500000000000000000000000001310511640000271255ustar00rootroot00000000000000grpc-1.3.2/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Control.php000066400000000000000000000204221310511640000312560ustar00rootroot00000000000000internalAddGeneratedFile(hex2bin( "0add170a247372632f70726f746f2f677270632f74657374696e672f636f" . "6e74726f6c2e70726f746f120c677270632e74657374696e671a25737263" . "2f70726f746f2f677270632f74657374696e672f7061796c6f6164732e70" . "726f746f1a227372632f70726f746f2f677270632f74657374696e672f73" . "746174732e70726f746f22250a0d506f6973736f6e506172616d7312140a" . "0c6f6666657265645f6c6f616418012001280122120a10436c6f7365644c" . "6f6f70506172616d73227b0a0a4c6f6164506172616d7312350a0b636c6f" . "7365645f6c6f6f7018012001280b321e2e677270632e74657374696e672e" . "436c6f7365644c6f6f70506172616d734800122e0a07706f6973736f6e18" . "022001280b321b2e677270632e74657374696e672e506f6973736f6e5061" . "72616d73480042060a046c6f616422430a0e536563757269747950617261" . "6d7312130a0b7573655f746573745f6361180120012808121c0a14736572" . "7665725f686f73745f6f76657272696465180220012809224d0a0a436861" . "6e6e656c417267120c0a046e616d6518012001280912130a097374725f76" . "616c7565180220012809480012130a09696e745f76616c75651803200128" . "05480042070a0576616c756522a0040a0c436c69656e74436f6e66696712" . "160a0e7365727665725f74617267657473180120032809122d0a0b636c69" . "656e745f7479706518022001280e32182e677270632e74657374696e672e" . "436c69656e745479706512350a0f73656375726974795f706172616d7318" . "032001280b321c2e677270632e74657374696e672e536563757269747950" . "6172616d7312240a1c6f75747374616e64696e675f727063735f7065725f" . "6368616e6e656c18042001280512170a0f636c69656e745f6368616e6e65" . "6c73180520012805121c0a146173796e635f636c69656e745f7468726561" . "647318072001280512270a087270635f7479706518082001280e32152e67" . "7270632e74657374696e672e52706354797065122d0a0b6c6f61645f7061" . "72616d73180a2001280b32182e677270632e74657374696e672e4c6f6164" . "506172616d7312330a0e7061796c6f61645f636f6e666967180b2001280b" . "321b2e677270632e74657374696e672e5061796c6f6164436f6e66696712" . "370a10686973746f6772616d5f706172616d73180c2001280b321d2e6772" . "70632e74657374696e672e486973746f6772616d506172616d7312110a09" . "636f72655f6c697374180d2003280512120a0a636f72655f6c696d697418" . "0e2001280512180a106f746865725f636c69656e745f617069180f200128" . "09122e0a0c6368616e6e656c5f6172677318102003280b32182e67727063" . "2e74657374696e672e4368616e6e656c41726722380a0c436c69656e7453" . "746174757312280a05737461747318012001280b32192e677270632e7465" . "7374696e672e436c69656e74537461747322150a044d61726b120d0a0572" . "6573657418012001280822680a0a436c69656e7441726773122b0a057365" . "74757018012001280b321a2e677270632e74657374696e672e436c69656e" . "74436f6e666967480012220a046d61726b18022001280b32122e67727063" . "2e74657374696e672e4d61726b480042090a076172677479706522b4020a" . "0c536572766572436f6e666967122d0a0b7365727665725f747970651801" . "2001280e32182e677270632e74657374696e672e53657276657254797065" . "12350a0f73656375726974795f706172616d7318022001280b321c2e6772" . "70632e74657374696e672e5365637572697479506172616d73120c0a0470" . "6f7274180420012805121c0a146173796e635f7365727665725f74687265" . "61647318072001280512120a0a636f72655f6c696d697418082001280512" . "330a0e7061796c6f61645f636f6e66696718092001280b321b2e67727063" . "2e74657374696e672e5061796c6f6164436f6e66696712110a09636f7265" . "5f6c697374180a2003280512180a106f746865725f7365727665725f6170" . "69180b20012809121c0a137265736f757263655f71756f74615f73697a65" . "18e9072001280522680a0a53657276657241726773122b0a057365747570" . "18012001280b321a2e677270632e74657374696e672e536572766572436f" . "6e666967480012220a046d61726b18022001280b32122e677270632e7465" . "7374696e672e4d61726b480042090a076172677479706522550a0c536572" . "76657253746174757312280a05737461747318012001280b32192e677270" . "632e74657374696e672e5365727665725374617473120c0a04706f727418" . "0220012805120d0a05636f726573180320012805220d0a0b436f72655265" . "7175657374221d0a0c436f7265526573706f6e7365120d0a05636f726573" . "18012001280522060a04566f696422fd010a085363656e6172696f120c0a" . "046e616d6518012001280912310a0d636c69656e745f636f6e6669671802" . "2001280b321a2e677270632e74657374696e672e436c69656e74436f6e66" . "696712130a0b6e756d5f636c69656e747318032001280512310a0d736572" . "7665725f636f6e66696718042001280b321a2e677270632e74657374696e" . "672e536572766572436f6e66696712130a0b6e756d5f7365727665727318" . "052001280512160a0e7761726d75705f7365636f6e647318062001280512" . "190a1162656e63686d61726b5f7365636f6e647318072001280512200a18" . "737061776e5f6c6f63616c5f776f726b65725f636f756e74180820012805" . "22360a095363656e6172696f7312290a097363656e6172696f7318012003" . "280b32162e677270632e74657374696e672e5363656e6172696f22f8020a" . "155363656e6172696f526573756c7453756d6d617279120b0a0371707318" . "0120012801121b0a137170735f7065725f7365727665725f636f72651802" . "20012801121a0a127365727665725f73797374656d5f74696d6518032001" . "280112180a107365727665725f757365725f74696d65180420012801121a" . "0a12636c69656e745f73797374656d5f74696d6518052001280112180a10" . "636c69656e745f757365725f74696d6518062001280112120a0a6c617465" . "6e63795f353018072001280112120a0a6c6174656e63795f393018082001" . "280112120a0a6c6174656e63795f393518092001280112120a0a6c617465" . "6e63795f3939180a2001280112130a0b6c6174656e63795f393939180b20" . "01280112180a107365727665725f6370755f7573616765180c2001280112" . "260a1e7375636365737366756c5f72657175657374735f7065725f736563" . "6f6e64180d2001280112220a1a6661696c65645f72657175657374735f70" . "65725f7365636f6e64180e200128012283030a0e5363656e6172696f5265" . "73756c7412280a087363656e6172696f18012001280b32162e677270632e" . "74657374696e672e5363656e6172696f122e0a096c6174656e6369657318" . "022001280b321b2e677270632e74657374696e672e486973746f6772616d" . "44617461122f0a0c636c69656e745f737461747318032003280b32192e67" . "7270632e74657374696e672e436c69656e745374617473122f0a0c736572" . "7665725f737461747318042003280b32192e677270632e74657374696e67" . "2e536572766572537461747312140a0c7365727665725f636f7265731805" . "2003280512340a0773756d6d61727918062001280b32232e677270632e74" . "657374696e672e5363656e6172696f526573756c7453756d6d6172791216" . "0a0e636c69656e745f7375636365737318072003280812160a0e73657276" . "65725f7375636365737318082003280812390a0f726571756573745f7265" . "73756c747318092003280b32202e677270632e74657374696e672e526571" . "75657374526573756c74436f756e742a410a0a436c69656e745479706512" . "0f0a0b53594e435f434c49454e54100012100a0c4153594e435f434c4945" . "4e54100112100a0c4f544845525f434c49454e5410022a5b0a0a53657276" . "657254797065120f0a0b53594e435f534552564552100012100a0c415359" . "4e435f534552564552100112180a144153594e435f47454e455249435f53" . "4552564552100212100a0c4f544845525f53455256455210032a230a0752" . "70635479706512090a05554e4152591000120d0a0953545245414d494e47" . "1001620670726f746f33" )); static::$is_initialized = true; } } grpc-1.3.2/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Messages.php000066400000000000000000000077131310511640000314150ustar00rootroot00000000000000internalAddGeneratedFile(hex2bin( "0ad50a0a257372632f70726f746f2f677270632f74657374696e672f6d65" . "7373616765732e70726f746f120c677270632e74657374696e67221a0a09" . "426f6f6c56616c7565120d0a0576616c756518012001280822400a075061" . "796c6f616412270a047479706518012001280e32192e677270632e746573" . "74696e672e5061796c6f616454797065120c0a04626f647918022001280c" . "222b0a0a4563686f537461747573120c0a04636f6465180120012805120f" . "0a076d65737361676518022001280922ce020a0d53696d706c6552657175" . "65737412300a0d726573706f6e73655f7479706518012001280e32192e67" . "7270632e74657374696e672e5061796c6f61645479706512150a0d726573" . "706f6e73655f73697a6518022001280512260a077061796c6f6164180320" . "01280b32152e677270632e74657374696e672e5061796c6f616412150a0d" . "66696c6c5f757365726e616d6518042001280812180a1066696c6c5f6f61" . "7574685f73636f706518052001280812340a13726573706f6e73655f636f" . "6d7072657373656418062001280b32172e677270632e74657374696e672e" . "426f6f6c56616c756512310a0f726573706f6e73655f7374617475731807" . "2001280b32182e677270632e74657374696e672e4563686f537461747573" . "12320a116578706563745f636f6d7072657373656418082001280b32172e" . "677270632e74657374696e672e426f6f6c56616c7565225f0a0e53696d70" . "6c65526573706f6e736512260a077061796c6f616418012001280b32152e" . "677270632e74657374696e672e5061796c6f616412100a08757365726e61" . "6d6518022001280912130a0b6f617574685f73636f706518032001280922" . "770a1953747265616d696e67496e70757443616c6c526571756573741226" . "0a077061796c6f616418012001280b32152e677270632e74657374696e67" . "2e5061796c6f616412320a116578706563745f636f6d7072657373656418" . "022001280b32172e677270632e74657374696e672e426f6f6c56616c7565" . "223d0a1a53747265616d696e67496e70757443616c6c526573706f6e7365" . "121f0a17616767726567617465645f7061796c6f61645f73697a65180120" . "01280522640a12526573706f6e7365506172616d6574657273120c0a0473" . "697a6518012001280512130a0b696e74657276616c5f7573180220012805" . "122b0a0a636f6d7072657373656418032001280b32172e677270632e7465" . "7374696e672e426f6f6c56616c756522e8010a1a53747265616d696e674f" . "757470757443616c6c5265717565737412300a0d726573706f6e73655f74" . "79706518012001280e32192e677270632e74657374696e672e5061796c6f" . "616454797065123d0a13726573706f6e73655f706172616d657465727318" . "022003280b32202e677270632e74657374696e672e526573706f6e736550" . "6172616d657465727312260a077061796c6f616418032001280b32152e67" . "7270632e74657374696e672e5061796c6f616412310a0f726573706f6e73" . "655f73746174757318072001280b32182e677270632e74657374696e672e" . "4563686f53746174757322450a1b53747265616d696e674f757470757443" . "616c6c526573706f6e736512260a077061796c6f616418012001280b3215" . "2e677270632e74657374696e672e5061796c6f616422330a0f5265636f6e" . "6e656374506172616d7312200a186d61785f7265636f6e6e6563745f6261" . "636b6f66665f6d7318012001280522330a0d5265636f6e6e656374496e66" . "6f120e0a0670617373656418012001280812120a0a6261636b6f66665f6d" . "731802200328052a1f0a0b5061796c6f61645479706512100a0c434f4d50" . "5245535341424c451000620670726f746f33" )); static::$is_initialized = true; } } grpc-1.3.2/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Payloads.php000066400000000000000000000030471310511640000314160ustar00rootroot00000000000000internalAddGeneratedFile(hex2bin( "0a93030a257372632f70726f746f2f677270632f74657374696e672f7061" . "796c6f6164732e70726f746f120c677270632e74657374696e6722370a10" . "42797465427566666572506172616d7312100a087265715f73697a651801" . "2001280512110a09726573705f73697a6518022001280522380a1153696d" . "706c6550726f746f506172616d7312100a087265715f73697a6518012001" . "280512110a09726573705f73697a6518022001280522140a12436f6d706c" . "657850726f746f506172616d7322ca010a0d5061796c6f6164436f6e6669" . "6712380a0e627974656275665f706172616d7318012001280b321e2e6772" . "70632e74657374696e672e42797465427566666572506172616d73480012" . "380a0d73696d706c655f706172616d7318022001280b321f2e677270632e" . "74657374696e672e53696d706c6550726f746f506172616d734800123a0a" . "0e636f6d706c65785f706172616d7318032001280b32202e677270632e74" . "657374696e672e436f6d706c657850726f746f506172616d73480042090a" . "077061796c6f6164620670726f746f33" )); static::$is_initialized = true; } } grpc-1.3.2/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/ProxyService.php000066400000000000000000000024651310511640000323070ustar00rootroot00000000000000internalAddGeneratedFile(hex2bin( "0a97020a2a7372632f70726f746f2f677270632f74657374696e672f7072" . "6f78792d736572766963652e70726f746f120c677270632e74657374696e" . "671a247372632f70726f746f2f677270632f74657374696e672f636f6e74" . "726f6c2e70726f746f221c0a0950726f787953746174120f0a076c617465" . "6e6379180120012801328e010a1250726f7879436c69656e745365727669" . "6365123b0a09476574436f6e66696712122e677270632e74657374696e67" . "2e566f69641a1a2e677270632e74657374696e672e436c69656e74436f6e" . "666967123b0a0a5265706f727454696d6512172e677270632e7465737469" . "6e672e50726f7879537461741a122e677270632e74657374696e672e566f" . "69642801620670726f746f33" )); static::$is_initialized = true; } } grpc-1.3.2/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Services.php000066400000000000000000000042141310511640000314220ustar00rootroot00000000000000internalAddGeneratedFile(hex2bin( "0ad1040a257372632f70726f746f2f677270632f74657374696e672f7365" . "7276696365732e70726f746f120c677270632e74657374696e671a257372" . "632f70726f746f2f677270632f74657374696e672f6d657373616765732e" . "70726f746f1a247372632f70726f746f2f677270632f74657374696e672f" . "636f6e74726f6c2e70726f746f32aa010a1042656e63686d61726b536572" . "7669636512460a09556e61727943616c6c121b2e677270632e7465737469" . "6e672e53696d706c65526571756573741a1c2e677270632e74657374696e" . "672e53696d706c65526573706f6e7365124e0a0d53747265616d696e6743" . "616c6c121b2e677270632e74657374696e672e53696d706c655265717565" . "73741a1c2e677270632e74657374696e672e53696d706c65526573706f6e" . "7365280130013297020a0d576f726b65725365727669636512450a095275" . "6e53657276657212182e677270632e74657374696e672e53657276657241" . "7267731a1a2e677270632e74657374696e672e5365727665725374617475" . "732801300112450a0952756e436c69656e7412182e677270632e74657374" . "696e672e436c69656e74417267731a1a2e677270632e74657374696e672e" . "436c69656e745374617475732801300112420a09436f7265436f756e7412" . "192e677270632e74657374696e672e436f7265526571756573741a1a2e67" . "7270632e74657374696e672e436f7265526573706f6e736512340a0a5175" . "6974576f726b657212122e677270632e74657374696e672e566f69641a12" . "2e677270632e74657374696e672e566f6964620670726f746f33" )); static::$is_initialized = true; } } grpc-1.3.2/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Stats.php000066400000000000000000000040601310511640000307340ustar00rootroot00000000000000internalAddGeneratedFile(hex2bin( "0adf040a227372632f70726f746f2f677270632f74657374696e672f7374" . "6174732e70726f746f120c677270632e74657374696e67227a0a0b536572" . "766572537461747312140a0c74696d655f656c6170736564180120012801" . "12110a0974696d655f7573657218022001280112130a0b74696d655f7379" . "7374656d18032001280112160a0e746f74616c5f6370755f74696d651804" . "2001280412150a0d69646c655f6370755f74696d65180520012804223b0a" . "0f486973746f6772616d506172616d7312120a0a7265736f6c7574696f6e" . "18012001280112140a0c6d61785f706f737369626c651802200128012277" . "0a0d486973746f6772616d44617461120e0a066275636b65741801200328" . "0d12100a086d696e5f7365656e18022001280112100a086d61785f736565" . "6e180320012801120b0a0373756d18042001280112160a0e73756d5f6f66" . "5f73717561726573180520012801120d0a05636f756e7418062001280122" . "380a1252657175657374526573756c74436f756e7412130a0b7374617475" . "735f636f6465180120012805120d0a05636f756e7418022001280322b601" . "0a0b436c69656e745374617473122e0a096c6174656e6369657318012001" . "280b321b2e677270632e74657374696e672e486973746f6772616d446174" . "6112140a0c74696d655f656c617073656418022001280112110a0974696d" . "655f7573657218032001280112130a0b74696d655f73797374656d180420" . "01280112390a0f726571756573745f726573756c747318052003280b3220" . "2e677270632e74657374696e672e52657175657374526573756c74436f75" . "6e74620670726f746f33" )); static::$is_initialized = true; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/000077500000000000000000000000001310511640000216055ustar00rootroot00000000000000grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/000077500000000000000000000000001310511640000232225ustar00rootroot00000000000000grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/BenchmarkServiceClient.php000066400000000000000000000060521310511640000303100ustar00rootroot00000000000000_simpleRequest('/grpc.testing.BenchmarkService/UnaryCall', $argument, ['\Grpc\Testing\SimpleResponse', 'decode'], $metadata, $options); } /** * One request followed by one response. * The server returns the client payload as-is. * @param array $metadata metadata * @param array $options call options */ public function StreamingCall($metadata = [], $options = []) { return $this->_bidiRequest('/grpc.testing.BenchmarkService/StreamingCall', ['\Grpc\Testing\SimpleResponse','decode'], $metadata, $options); } } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/BoolValue.php000066400000000000000000000023331310511640000256240ustar00rootroot00000000000000 * TODO(dgq): Go back to using well-known types once * https://github.com/grpc/grpc/issues/6980 has been fixed. * import "google/protobuf/wrappers.proto"; * * * Protobuf type grpc.testing.BoolValue */ class BoolValue extends \Google\Protobuf\Internal\Message { /** *
     * The bool value.
     * 
* * bool value = 1; */ private $value = false; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); parent::__construct(); } /** *
     * The bool value.
     * 
* * bool value = 1; */ public function getValue() { return $this->value; } /** *
     * The bool value.
     * 
* * bool value = 1; */ public function setValue($var) { GPBUtil::checkBool($var); $this->value = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/ByteBufferParams.php000066400000000000000000000024571310511640000271440ustar00rootroot00000000000000grpc.testing.ByteBufferParams */ class ByteBufferParams extends \Google\Protobuf\Internal\Message { /** * int32 req_size = 1; */ private $req_size = 0; /** * int32 resp_size = 2; */ private $resp_size = 0; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Payloads::initOnce(); parent::__construct(); } /** * int32 req_size = 1; */ public function getReqSize() { return $this->req_size; } /** * int32 req_size = 1; */ public function setReqSize($var) { GPBUtil::checkInt32($var); $this->req_size = $var; } /** * int32 resp_size = 2; */ public function getRespSize() { return $this->resp_size; } /** * int32 resp_size = 2; */ public function setRespSize($var) { GPBUtil::checkInt32($var); $this->resp_size = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/ChannelArg.php000066400000000000000000000031641310511640000257410ustar00rootroot00000000000000grpc.testing.ChannelArg */ class ChannelArg extends \Google\Protobuf\Internal\Message { /** * string name = 1; */ private $name = ''; protected $value; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); parent::__construct(); } /** * string name = 1; */ public function getName() { return $this->name; } /** * string name = 1; */ public function setName($var) { GPBUtil::checkString($var, True); $this->name = $var; } /** * string str_value = 2; */ public function getStrValue() { return $this->readOneof(2); } /** * string str_value = 2; */ public function setStrValue($var) { GPBUtil::checkString($var, True); $this->writeOneof(2, $var); } /** * int32 int_value = 3; */ public function getIntValue() { return $this->readOneof(3); } /** * int32 int_value = 3; */ public function setIntValue($var) { GPBUtil::checkInt32($var); $this->writeOneof(3, $var); } public function getValue() { return $this->whichOneof("value"); } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/ClientArgs.php000066400000000000000000000025461310511640000257750ustar00rootroot00000000000000grpc.testing.ClientArgs */ class ClientArgs extends \Google\Protobuf\Internal\Message { protected $argtype; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); parent::__construct(); } /** * .grpc.testing.ClientConfig setup = 1; */ public function getSetup() { return $this->readOneof(1); } /** * .grpc.testing.ClientConfig setup = 1; */ public function setSetup(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\ClientConfig::class); $this->writeOneof(1, $var); } /** * .grpc.testing.Mark mark = 2; */ public function getMark() { return $this->readOneof(2); } /** * .grpc.testing.Mark mark = 2; */ public function setMark(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\Mark::class); $this->writeOneof(2, $var); } public function getArgtype() { return $this->whichOneof("argtype"); } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/ClientConfig.php000066400000000000000000000240721310511640000263040ustar00rootroot00000000000000grpc.testing.ClientConfig */ class ClientConfig extends \Google\Protobuf\Internal\Message { /** *
     * List of targets to connect to. At least one target needs to be specified.
     * 
* * repeated string server_targets = 1; */ private $server_targets; /** * .grpc.testing.ClientType client_type = 2; */ private $client_type = 0; /** * .grpc.testing.SecurityParams security_params = 3; */ private $security_params = null; /** *
     * How many concurrent RPCs to start for each channel.
     * For synchronous client, use a separate thread for each outstanding RPC.
     * 
* * int32 outstanding_rpcs_per_channel = 4; */ private $outstanding_rpcs_per_channel = 0; /** *
     * Number of independent client channels to create.
     * i-th channel will connect to server_target[i % server_targets.size()]
     * 
* * int32 client_channels = 5; */ private $client_channels = 0; /** *
     * Only for async client. Number of threads to use to start/manage RPCs.
     * 
* * int32 async_client_threads = 7; */ private $async_client_threads = 0; /** * .grpc.testing.RpcType rpc_type = 8; */ private $rpc_type = 0; /** *
     * The requested load for the entire client (aggregated over all the threads).
     * 
* * .grpc.testing.LoadParams load_params = 10; */ private $load_params = null; /** * .grpc.testing.PayloadConfig payload_config = 11; */ private $payload_config = null; /** * .grpc.testing.HistogramParams histogram_params = 12; */ private $histogram_params = null; /** *
     * Specify the cores we should run the client on, if desired
     * 
* * repeated int32 core_list = 13; */ private $core_list; /** * int32 core_limit = 14; */ private $core_limit = 0; /** *
     * If we use an OTHER_CLIENT client_type, this string gives more detail
     * 
* * string other_client_api = 15; */ private $other_client_api = ''; /** * repeated .grpc.testing.ChannelArg channel_args = 16; */ private $channel_args; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); parent::__construct(); } /** *
     * List of targets to connect to. At least one target needs to be specified.
     * 
* * repeated string server_targets = 1; */ public function getServerTargets() { return $this->server_targets; } /** *
     * List of targets to connect to. At least one target needs to be specified.
     * 
* * repeated string server_targets = 1; */ public function setServerTargets(&$var) { GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING); $this->server_targets = $var; } /** * .grpc.testing.ClientType client_type = 2; */ public function getClientType() { return $this->client_type; } /** * .grpc.testing.ClientType client_type = 2; */ public function setClientType($var) { GPBUtil::checkEnum($var, \Grpc\Testing\ClientType::class); $this->client_type = $var; } /** * .grpc.testing.SecurityParams security_params = 3; */ public function getSecurityParams() { return $this->security_params; } /** * .grpc.testing.SecurityParams security_params = 3; */ public function setSecurityParams(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\SecurityParams::class); $this->security_params = $var; } /** *
     * How many concurrent RPCs to start for each channel.
     * For synchronous client, use a separate thread for each outstanding RPC.
     * 
* * int32 outstanding_rpcs_per_channel = 4; */ public function getOutstandingRpcsPerChannel() { return $this->outstanding_rpcs_per_channel; } /** *
     * How many concurrent RPCs to start for each channel.
     * For synchronous client, use a separate thread for each outstanding RPC.
     * 
* * int32 outstanding_rpcs_per_channel = 4; */ public function setOutstandingRpcsPerChannel($var) { GPBUtil::checkInt32($var); $this->outstanding_rpcs_per_channel = $var; } /** *
     * Number of independent client channels to create.
     * i-th channel will connect to server_target[i % server_targets.size()]
     * 
* * int32 client_channels = 5; */ public function getClientChannels() { return $this->client_channels; } /** *
     * Number of independent client channels to create.
     * i-th channel will connect to server_target[i % server_targets.size()]
     * 
* * int32 client_channels = 5; */ public function setClientChannels($var) { GPBUtil::checkInt32($var); $this->client_channels = $var; } /** *
     * Only for async client. Number of threads to use to start/manage RPCs.
     * 
* * int32 async_client_threads = 7; */ public function getAsyncClientThreads() { return $this->async_client_threads; } /** *
     * Only for async client. Number of threads to use to start/manage RPCs.
     * 
* * int32 async_client_threads = 7; */ public function setAsyncClientThreads($var) { GPBUtil::checkInt32($var); $this->async_client_threads = $var; } /** * .grpc.testing.RpcType rpc_type = 8; */ public function getRpcType() { return $this->rpc_type; } /** * .grpc.testing.RpcType rpc_type = 8; */ public function setRpcType($var) { GPBUtil::checkEnum($var, \Grpc\Testing\RpcType::class); $this->rpc_type = $var; } /** *
     * The requested load for the entire client (aggregated over all the threads).
     * 
* * .grpc.testing.LoadParams load_params = 10; */ public function getLoadParams() { return $this->load_params; } /** *
     * The requested load for the entire client (aggregated over all the threads).
     * 
* * .grpc.testing.LoadParams load_params = 10; */ public function setLoadParams(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\LoadParams::class); $this->load_params = $var; } /** * .grpc.testing.PayloadConfig payload_config = 11; */ public function getPayloadConfig() { return $this->payload_config; } /** * .grpc.testing.PayloadConfig payload_config = 11; */ public function setPayloadConfig(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\PayloadConfig::class); $this->payload_config = $var; } /** * .grpc.testing.HistogramParams histogram_params = 12; */ public function getHistogramParams() { return $this->histogram_params; } /** * .grpc.testing.HistogramParams histogram_params = 12; */ public function setHistogramParams(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\HistogramParams::class); $this->histogram_params = $var; } /** *
     * Specify the cores we should run the client on, if desired
     * 
* * repeated int32 core_list = 13; */ public function getCoreList() { return $this->core_list; } /** *
     * Specify the cores we should run the client on, if desired
     * 
* * repeated int32 core_list = 13; */ public function setCoreList(&$var) { GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32); $this->core_list = $var; } /** * int32 core_limit = 14; */ public function getCoreLimit() { return $this->core_limit; } /** * int32 core_limit = 14; */ public function setCoreLimit($var) { GPBUtil::checkInt32($var); $this->core_limit = $var; } /** *
     * If we use an OTHER_CLIENT client_type, this string gives more detail
     * 
* * string other_client_api = 15; */ public function getOtherClientApi() { return $this->other_client_api; } /** *
     * If we use an OTHER_CLIENT client_type, this string gives more detail
     * 
* * string other_client_api = 15; */ public function setOtherClientApi($var) { GPBUtil::checkString($var, True); $this->other_client_api = $var; } /** * repeated .grpc.testing.ChannelArg channel_args = 16; */ public function getChannelArgs() { return $this->channel_args; } /** * repeated .grpc.testing.ChannelArg channel_args = 16; */ public function setChannelArgs(&$var) { GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\ChannelArg::class); $this->channel_args = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/ClientStats.php000066400000000000000000000071731310511640000262000ustar00rootroot00000000000000grpc.testing.ClientStats */ class ClientStats extends \Google\Protobuf\Internal\Message { /** *
     * Latency histogram. Data points are in nanoseconds.
     * 
* * .grpc.testing.HistogramData latencies = 1; */ private $latencies = null; /** *
     * See ServerStats for details.
     * 
* * double time_elapsed = 2; */ private $time_elapsed = 0.0; /** * double time_user = 3; */ private $time_user = 0.0; /** * double time_system = 4; */ private $time_system = 0.0; /** *
     * Number of failed requests (one row per status code seen)
     * 
* * repeated .grpc.testing.RequestResultCount request_results = 5; */ private $request_results; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce(); parent::__construct(); } /** *
     * Latency histogram. Data points are in nanoseconds.
     * 
* * .grpc.testing.HistogramData latencies = 1; */ public function getLatencies() { return $this->latencies; } /** *
     * Latency histogram. Data points are in nanoseconds.
     * 
* * .grpc.testing.HistogramData latencies = 1; */ public function setLatencies(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\HistogramData::class); $this->latencies = $var; } /** *
     * See ServerStats for details.
     * 
* * double time_elapsed = 2; */ public function getTimeElapsed() { return $this->time_elapsed; } /** *
     * See ServerStats for details.
     * 
* * double time_elapsed = 2; */ public function setTimeElapsed($var) { GPBUtil::checkDouble($var); $this->time_elapsed = $var; } /** * double time_user = 3; */ public function getTimeUser() { return $this->time_user; } /** * double time_user = 3; */ public function setTimeUser($var) { GPBUtil::checkDouble($var); $this->time_user = $var; } /** * double time_system = 4; */ public function getTimeSystem() { return $this->time_system; } /** * double time_system = 4; */ public function setTimeSystem($var) { GPBUtil::checkDouble($var); $this->time_system = $var; } /** *
     * Number of failed requests (one row per status code seen)
     * 
* * repeated .grpc.testing.RequestResultCount request_results = 5; */ public function getRequestResults() { return $this->request_results; } /** *
     * Number of failed requests (one row per status code seen)
     * 
* * repeated .grpc.testing.RequestResultCount request_results = 5; */ public function setRequestResults(&$var) { GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\RequestResultCount::class); $this->request_results = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/ClientStatus.php000066400000000000000000000017451310511640000263640ustar00rootroot00000000000000grpc.testing.ClientStatus */ class ClientStatus extends \Google\Protobuf\Internal\Message { /** * .grpc.testing.ClientStats stats = 1; */ private $stats = null; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); parent::__construct(); } /** * .grpc.testing.ClientStats stats = 1; */ public function getStats() { return $this->stats; } /** * .grpc.testing.ClientStats stats = 1; */ public function setStats(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\ClientStats::class); $this->stats = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/ClientType.php000066400000000000000000000013051310511640000260120ustar00rootroot00000000000000grpc.testing.ClientType */ class ClientType { /** *
     * Many languages support a basic distinction between using
     * sync or async client, and this allows the specification
     * 
* * SYNC_CLIENT = 0; */ const SYNC_CLIENT = 0; /** * ASYNC_CLIENT = 1; */ const ASYNC_CLIENT = 1; /** *
     * used for some language-specific variants
     * 
* * OTHER_CLIENT = 2; */ const OTHER_CLIENT = 2; } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/ClosedLoopParams.php000066400000000000000000000012141310511640000271400ustar00rootroot00000000000000 * Once an RPC finishes, immediately start a new one. * No configuration parameters needed. * * * Protobuf type grpc.testing.ClosedLoopParams */ class ClosedLoopParams extends \Google\Protobuf\Internal\Message { public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); parent::__construct(); } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/ComplexProtoParams.php000066400000000000000000000012411310511640000275300ustar00rootroot00000000000000 * TODO (vpai): Fill this in once the details of complex, representative * protos are decided * * * Protobuf type grpc.testing.ComplexProtoParams */ class ComplexProtoParams extends \Google\Protobuf\Internal\Message { public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Payloads::initOnce(); parent::__construct(); } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/CoreRequest.php000066400000000000000000000010171310511640000261730ustar00rootroot00000000000000grpc.testing.CoreRequest */ class CoreRequest extends \Google\Protobuf\Internal\Message { public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); parent::__construct(); } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/CoreResponse.php000066400000000000000000000021641310511640000263450ustar00rootroot00000000000000grpc.testing.CoreResponse */ class CoreResponse extends \Google\Protobuf\Internal\Message { /** *
     * Number of cores available on the server
     * 
* * int32 cores = 1; */ private $cores = 0; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); parent::__construct(); } /** *
     * Number of cores available on the server
     * 
* * int32 cores = 1; */ public function getCores() { return $this->cores; } /** *
     * Number of cores available on the server
     * 
* * int32 cores = 1; */ public function setCores($var) { GPBUtil::checkInt32($var); $this->cores = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/EchoStatus.php000066400000000000000000000026441310511640000260230ustar00rootroot00000000000000 * A protobuf representation for grpc status. This is used by test * clients to specify a status that the server should attempt to return. * * * Protobuf type grpc.testing.EchoStatus */ class EchoStatus extends \Google\Protobuf\Internal\Message { /** * int32 code = 1; */ private $code = 0; /** * string message = 2; */ private $message = ''; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); parent::__construct(); } /** * int32 code = 1; */ public function getCode() { return $this->code; } /** * int32 code = 1; */ public function setCode($var) { GPBUtil::checkInt32($var); $this->code = $var; } /** * string message = 2; */ public function getMessage() { return $this->message; } /** * string message = 2; */ public function setMessage($var) { GPBUtil::checkString($var, True); $this->message = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/HistogramData.php000066400000000000000000000057151310511640000264720ustar00rootroot00000000000000 * Histogram data based on grpc/support/histogram.c * * * Protobuf type grpc.testing.HistogramData */ class HistogramData extends \Google\Protobuf\Internal\Message { /** * repeated uint32 bucket = 1; */ private $bucket; /** * double min_seen = 2; */ private $min_seen = 0.0; /** * double max_seen = 3; */ private $max_seen = 0.0; /** * double sum = 4; */ private $sum = 0.0; /** * double sum_of_squares = 5; */ private $sum_of_squares = 0.0; /** * double count = 6; */ private $count = 0.0; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce(); parent::__construct(); } /** * repeated uint32 bucket = 1; */ public function getBucket() { return $this->bucket; } /** * repeated uint32 bucket = 1; */ public function setBucket(&$var) { GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::UINT32); $this->bucket = $var; } /** * double min_seen = 2; */ public function getMinSeen() { return $this->min_seen; } /** * double min_seen = 2; */ public function setMinSeen($var) { GPBUtil::checkDouble($var); $this->min_seen = $var; } /** * double max_seen = 3; */ public function getMaxSeen() { return $this->max_seen; } /** * double max_seen = 3; */ public function setMaxSeen($var) { GPBUtil::checkDouble($var); $this->max_seen = $var; } /** * double sum = 4; */ public function getSum() { return $this->sum; } /** * double sum = 4; */ public function setSum($var) { GPBUtil::checkDouble($var); $this->sum = $var; } /** * double sum_of_squares = 5; */ public function getSumOfSquares() { return $this->sum_of_squares; } /** * double sum_of_squares = 5; */ public function setSumOfSquares($var) { GPBUtil::checkDouble($var); $this->sum_of_squares = $var; } /** * double count = 6; */ public function getCount() { return $this->count; } /** * double count = 6; */ public function setCount($var) { GPBUtil::checkDouble($var); $this->count = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/HistogramParams.php000066400000000000000000000036001310511640000270330ustar00rootroot00000000000000 * Histogram params based on grpc/support/histogram.c * * * Protobuf type grpc.testing.HistogramParams */ class HistogramParams extends \Google\Protobuf\Internal\Message { /** *
     * first bucket is [0, 1 + resolution)
     * 
* * double resolution = 1; */ private $resolution = 0.0; /** *
     * use enough buckets to allow this value
     * 
* * double max_possible = 2; */ private $max_possible = 0.0; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce(); parent::__construct(); } /** *
     * first bucket is [0, 1 + resolution)
     * 
* * double resolution = 1; */ public function getResolution() { return $this->resolution; } /** *
     * first bucket is [0, 1 + resolution)
     * 
* * double resolution = 1; */ public function setResolution($var) { GPBUtil::checkDouble($var); $this->resolution = $var; } /** *
     * use enough buckets to allow this value
     * 
* * double max_possible = 2; */ public function getMaxPossible() { return $this->max_possible; } /** *
     * use enough buckets to allow this value
     * 
* * double max_possible = 2; */ public function setMaxPossible($var) { GPBUtil::checkDouble($var); $this->max_possible = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/LoadParams.php000066400000000000000000000026461310511640000257660ustar00rootroot00000000000000grpc.testing.LoadParams */ class LoadParams extends \Google\Protobuf\Internal\Message { protected $load; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); parent::__construct(); } /** * .grpc.testing.ClosedLoopParams closed_loop = 1; */ public function getClosedLoop() { return $this->readOneof(1); } /** * .grpc.testing.ClosedLoopParams closed_loop = 1; */ public function setClosedLoop(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\ClosedLoopParams::class); $this->writeOneof(1, $var); } /** * .grpc.testing.PoissonParams poisson = 2; */ public function getPoisson() { return $this->readOneof(2); } /** * .grpc.testing.PoissonParams poisson = 2; */ public function setPoisson(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\PoissonParams::class); $this->writeOneof(2, $var); } public function getLoad() { return $this->whichOneof("load"); } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/Mark.php000066400000000000000000000023251310511640000246270ustar00rootroot00000000000000 * Request current stats * * * Protobuf type grpc.testing.Mark */ class Mark extends \Google\Protobuf\Internal\Message { /** *
     * if true, the stats will be reset after taking their snapshot.
     * 
* * bool reset = 1; */ private $reset = false; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); parent::__construct(); } /** *
     * if true, the stats will be reset after taking their snapshot.
     * 
* * bool reset = 1; */ public function getReset() { return $this->reset; } /** *
     * if true, the stats will be reset after taking their snapshot.
     * 
* * bool reset = 1; */ public function setReset($var) { GPBUtil::checkBool($var); $this->reset = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/Payload.php000066400000000000000000000037111310511640000253260ustar00rootroot00000000000000 * A block of data, to simply increase gRPC message size. * * * Protobuf type grpc.testing.Payload */ class Payload extends \Google\Protobuf\Internal\Message { /** *
     * DEPRECATED, don't use. To be removed shortly.
     * The type of data in body.
     * 
* * .grpc.testing.PayloadType type = 1; */ private $type = 0; /** *
     * Primary contents of payload.
     * 
* * bytes body = 2; */ private $body = ''; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); parent::__construct(); } /** *
     * DEPRECATED, don't use. To be removed shortly.
     * The type of data in body.
     * 
* * .grpc.testing.PayloadType type = 1; */ public function getType() { return $this->type; } /** *
     * DEPRECATED, don't use. To be removed shortly.
     * The type of data in body.
     * 
* * .grpc.testing.PayloadType type = 1; */ public function setType($var) { GPBUtil::checkEnum($var, \Grpc\Testing\PayloadType::class); $this->type = $var; } /** *
     * Primary contents of payload.
     * 
* * bytes body = 2; */ public function getBody() { return $this->body; } /** *
     * Primary contents of payload.
     * 
* * bytes body = 2; */ public function setBody($var) { GPBUtil::checkString($var, False); $this->body = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/PayloadConfig.php000066400000000000000000000036321310511640000264560ustar00rootroot00000000000000grpc.testing.PayloadConfig */ class PayloadConfig extends \Google\Protobuf\Internal\Message { protected $payload; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Payloads::initOnce(); parent::__construct(); } /** * .grpc.testing.ByteBufferParams bytebuf_params = 1; */ public function getBytebufParams() { return $this->readOneof(1); } /** * .grpc.testing.ByteBufferParams bytebuf_params = 1; */ public function setBytebufParams(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\ByteBufferParams::class); $this->writeOneof(1, $var); } /** * .grpc.testing.SimpleProtoParams simple_params = 2; */ public function getSimpleParams() { return $this->readOneof(2); } /** * .grpc.testing.SimpleProtoParams simple_params = 2; */ public function setSimpleParams(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\SimpleProtoParams::class); $this->writeOneof(2, $var); } /** * .grpc.testing.ComplexProtoParams complex_params = 3; */ public function getComplexParams() { return $this->readOneof(3); } /** * .grpc.testing.ComplexProtoParams complex_params = 3; */ public function setComplexParams(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\ComplexProtoParams::class); $this->writeOneof(3, $var); } public function getPayload() { return $this->whichOneof("payload"); } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/PayloadType.php000066400000000000000000000007551310511640000261750ustar00rootroot00000000000000 * DEPRECATED, don't use. To be removed shortly. * The type of payload that should be returned. * * * Protobuf enum grpc.testing.PayloadType */ class PayloadType { /** *
     * Compressable text format.
     * 
* * COMPRESSABLE = 0; */ const COMPRESSABLE = 0; } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/PoissonParams.php000066400000000000000000000026761310511640000265440ustar00rootroot00000000000000 * Parameters of poisson process distribution, which is a good representation * of activity coming in from independent identical stationary sources. * * * Protobuf type grpc.testing.PoissonParams */ class PoissonParams extends \Google\Protobuf\Internal\Message { /** *
     * The rate of arrivals (a.k.a. lambda parameter of the exp distribution).
     * 
* * double offered_load = 1; */ private $offered_load = 0.0; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); parent::__construct(); } /** *
     * The rate of arrivals (a.k.a. lambda parameter of the exp distribution).
     * 
* * double offered_load = 1; */ public function getOfferedLoad() { return $this->offered_load; } /** *
     * The rate of arrivals (a.k.a. lambda parameter of the exp distribution).
     * 
* * double offered_load = 1; */ public function setOfferedLoad($var) { GPBUtil::checkDouble($var); $this->offered_load = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/ProxyClientServiceClient.php000066400000000000000000000053271310511640000307020ustar00rootroot00000000000000_simpleRequest('/grpc.testing.ProxyClientService/GetConfig', $argument, ['\Grpc\Testing\ClientConfig', 'decode'], $metadata, $options); } /** * @param array $metadata metadata * @param array $options call options */ public function ReportTime($metadata = [], $options = []) { return $this->_clientStreamRequest('/grpc.testing.ProxyClientService/ReportTime', ['\Grpc\Testing\Void','decode'], $metadata, $options); } } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/ProxyStat.php000066400000000000000000000016341310511640000257140ustar00rootroot00000000000000grpc.testing.ProxyStat */ class ProxyStat extends \Google\Protobuf\Internal\Message { /** * double latency = 1; */ private $latency = 0.0; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\ProxyService::initOnce(); parent::__construct(); } /** * double latency = 1; */ public function getLatency() { return $this->latency; } /** * double latency = 1; */ public function setLatency($var) { GPBUtil::checkDouble($var); $this->latency = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/ReconnectInfo.php000066400000000000000000000030221310511640000264640ustar00rootroot00000000000000 * For reconnect interop test only. * Server tells client whether its reconnects are following the spec and the * reconnect backoffs it saw. * * * Protobuf type grpc.testing.ReconnectInfo */ class ReconnectInfo extends \Google\Protobuf\Internal\Message { /** * bool passed = 1; */ private $passed = false; /** * repeated int32 backoff_ms = 2; */ private $backoff_ms; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); parent::__construct(); } /** * bool passed = 1; */ public function getPassed() { return $this->passed; } /** * bool passed = 1; */ public function setPassed($var) { GPBUtil::checkBool($var); $this->passed = $var; } /** * repeated int32 backoff_ms = 2; */ public function getBackoffMs() { return $this->backoff_ms; } /** * repeated int32 backoff_ms = 2; */ public function setBackoffMs(&$var) { GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32); $this->backoff_ms = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/ReconnectParams.php000066400000000000000000000022221310511640000270150ustar00rootroot00000000000000 * For reconnect interop test only. * Client tells server what reconnection parameters it used. * * * Protobuf type grpc.testing.ReconnectParams */ class ReconnectParams extends \Google\Protobuf\Internal\Message { /** * int32 max_reconnect_backoff_ms = 1; */ private $max_reconnect_backoff_ms = 0; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); parent::__construct(); } /** * int32 max_reconnect_backoff_ms = 1; */ public function getMaxReconnectBackoffMs() { return $this->max_reconnect_backoff_ms; } /** * int32 max_reconnect_backoff_ms = 1; */ public function setMaxReconnectBackoffMs($var) { GPBUtil::checkInt32($var); $this->max_reconnect_backoff_ms = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/RequestResultCount.php000066400000000000000000000024471310511640000276020ustar00rootroot00000000000000grpc.testing.RequestResultCount */ class RequestResultCount extends \Google\Protobuf\Internal\Message { /** * int32 status_code = 1; */ private $status_code = 0; /** * int64 count = 2; */ private $count = 0; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce(); parent::__construct(); } /** * int32 status_code = 1; */ public function getStatusCode() { return $this->status_code; } /** * int32 status_code = 1; */ public function setStatusCode($var) { GPBUtil::checkInt32($var); $this->status_code = $var; } /** * int64 count = 2; */ public function getCount() { return $this->count; } /** * int64 count = 2; */ public function setCount($var) { GPBUtil::checkInt64($var); $this->count = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/ResponseParameters.php000066400000000000000000000066571310511640000275730ustar00rootroot00000000000000 * Configuration for a particular response. * * * Protobuf type grpc.testing.ResponseParameters */ class ResponseParameters extends \Google\Protobuf\Internal\Message { /** *
     * Desired payload sizes in responses from the server.
     * 
* * int32 size = 1; */ private $size = 0; /** *
     * Desired interval between consecutive responses in the response stream in
     * microseconds.
     * 
* * int32 interval_us = 2; */ private $interval_us = 0; /** *
     * Whether to request the server to compress the response. This field is
     * "nullable" in order to interoperate seamlessly with clients not able to
     * implement the full compression tests by introspecting the call to verify
     * the response's compression status.
     * 
* * .grpc.testing.BoolValue compressed = 3; */ private $compressed = null; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); parent::__construct(); } /** *
     * Desired payload sizes in responses from the server.
     * 
* * int32 size = 1; */ public function getSize() { return $this->size; } /** *
     * Desired payload sizes in responses from the server.
     * 
* * int32 size = 1; */ public function setSize($var) { GPBUtil::checkInt32($var); $this->size = $var; } /** *
     * Desired interval between consecutive responses in the response stream in
     * microseconds.
     * 
* * int32 interval_us = 2; */ public function getIntervalUs() { return $this->interval_us; } /** *
     * Desired interval between consecutive responses in the response stream in
     * microseconds.
     * 
* * int32 interval_us = 2; */ public function setIntervalUs($var) { GPBUtil::checkInt32($var); $this->interval_us = $var; } /** *
     * Whether to request the server to compress the response. This field is
     * "nullable" in order to interoperate seamlessly with clients not able to
     * implement the full compression tests by introspecting the call to verify
     * the response's compression status.
     * 
* * .grpc.testing.BoolValue compressed = 3; */ public function getCompressed() { return $this->compressed; } /** *
     * Whether to request the server to compress the response. This field is
     * "nullable" in order to interoperate seamlessly with clients not able to
     * implement the full compression tests by introspecting the call to verify
     * the response's compression status.
     * 
* * .grpc.testing.BoolValue compressed = 3; */ public function setCompressed(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\BoolValue::class); $this->compressed = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/RpcType.php000066400000000000000000000005501310511640000253210ustar00rootroot00000000000000grpc.testing.RpcType */ class RpcType { /** * UNARY = 0; */ const UNARY = 0; /** * STREAMING = 1; */ const STREAMING = 1; } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/Scenario.php000066400000000000000000000136501310511640000255030ustar00rootroot00000000000000 * A single performance scenario: input to qps_json_driver * * * Protobuf type grpc.testing.Scenario */ class Scenario extends \Google\Protobuf\Internal\Message { /** *
     * Human readable name for this scenario
     * 
* * string name = 1; */ private $name = ''; /** *
     * Client configuration
     * 
* * .grpc.testing.ClientConfig client_config = 2; */ private $client_config = null; /** *
     * Number of clients to start for the test
     * 
* * int32 num_clients = 3; */ private $num_clients = 0; /** *
     * Server configuration
     * 
* * .grpc.testing.ServerConfig server_config = 4; */ private $server_config = null; /** *
     * Number of servers to start for the test
     * 
* * int32 num_servers = 5; */ private $num_servers = 0; /** *
     * Warmup period, in seconds
     * 
* * int32 warmup_seconds = 6; */ private $warmup_seconds = 0; /** *
     * Benchmark time, in seconds
     * 
* * int32 benchmark_seconds = 7; */ private $benchmark_seconds = 0; /** *
     * Number of workers to spawn locally (usually zero)
     * 
* * int32 spawn_local_worker_count = 8; */ private $spawn_local_worker_count = 0; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); parent::__construct(); } /** *
     * Human readable name for this scenario
     * 
* * string name = 1; */ public function getName() { return $this->name; } /** *
     * Human readable name for this scenario
     * 
* * string name = 1; */ public function setName($var) { GPBUtil::checkString($var, True); $this->name = $var; } /** *
     * Client configuration
     * 
* * .grpc.testing.ClientConfig client_config = 2; */ public function getClientConfig() { return $this->client_config; } /** *
     * Client configuration
     * 
* * .grpc.testing.ClientConfig client_config = 2; */ public function setClientConfig(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\ClientConfig::class); $this->client_config = $var; } /** *
     * Number of clients to start for the test
     * 
* * int32 num_clients = 3; */ public function getNumClients() { return $this->num_clients; } /** *
     * Number of clients to start for the test
     * 
* * int32 num_clients = 3; */ public function setNumClients($var) { GPBUtil::checkInt32($var); $this->num_clients = $var; } /** *
     * Server configuration
     * 
* * .grpc.testing.ServerConfig server_config = 4; */ public function getServerConfig() { return $this->server_config; } /** *
     * Server configuration
     * 
* * .grpc.testing.ServerConfig server_config = 4; */ public function setServerConfig(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\ServerConfig::class); $this->server_config = $var; } /** *
     * Number of servers to start for the test
     * 
* * int32 num_servers = 5; */ public function getNumServers() { return $this->num_servers; } /** *
     * Number of servers to start for the test
     * 
* * int32 num_servers = 5; */ public function setNumServers($var) { GPBUtil::checkInt32($var); $this->num_servers = $var; } /** *
     * Warmup period, in seconds
     * 
* * int32 warmup_seconds = 6; */ public function getWarmupSeconds() { return $this->warmup_seconds; } /** *
     * Warmup period, in seconds
     * 
* * int32 warmup_seconds = 6; */ public function setWarmupSeconds($var) { GPBUtil::checkInt32($var); $this->warmup_seconds = $var; } /** *
     * Benchmark time, in seconds
     * 
* * int32 benchmark_seconds = 7; */ public function getBenchmarkSeconds() { return $this->benchmark_seconds; } /** *
     * Benchmark time, in seconds
     * 
* * int32 benchmark_seconds = 7; */ public function setBenchmarkSeconds($var) { GPBUtil::checkInt32($var); $this->benchmark_seconds = $var; } /** *
     * Number of workers to spawn locally (usually zero)
     * 
* * int32 spawn_local_worker_count = 8; */ public function getSpawnLocalWorkerCount() { return $this->spawn_local_worker_count; } /** *
     * Number of workers to spawn locally (usually zero)
     * 
* * int32 spawn_local_worker_count = 8; */ public function setSpawnLocalWorkerCount($var) { GPBUtil::checkInt32($var); $this->spawn_local_worker_count = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/ScenarioResult.php000066400000000000000000000163721310511640000267060ustar00rootroot00000000000000 * Results of a single benchmark scenario. * * * Protobuf type grpc.testing.ScenarioResult */ class ScenarioResult extends \Google\Protobuf\Internal\Message { /** *
     * Inputs used to run the scenario.
     * 
* * .grpc.testing.Scenario scenario = 1; */ private $scenario = null; /** *
     * Histograms from all clients merged into one histogram.
     * 
* * .grpc.testing.HistogramData latencies = 2; */ private $latencies = null; /** *
     * Client stats for each client
     * 
* * repeated .grpc.testing.ClientStats client_stats = 3; */ private $client_stats; /** *
     * Server stats for each server
     * 
* * repeated .grpc.testing.ServerStats server_stats = 4; */ private $server_stats; /** *
     * Number of cores available to each server
     * 
* * repeated int32 server_cores = 5; */ private $server_cores; /** *
     * An after-the-fact computed summary
     * 
* * .grpc.testing.ScenarioResultSummary summary = 6; */ private $summary = null; /** *
     * Information on success or failure of each worker
     * 
* * repeated bool client_success = 7; */ private $client_success; /** * repeated bool server_success = 8; */ private $server_success; /** *
     * Number of failed requests (one row per status code seen)
     * 
* * repeated .grpc.testing.RequestResultCount request_results = 9; */ private $request_results; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); parent::__construct(); } /** *
     * Inputs used to run the scenario.
     * 
* * .grpc.testing.Scenario scenario = 1; */ public function getScenario() { return $this->scenario; } /** *
     * Inputs used to run the scenario.
     * 
* * .grpc.testing.Scenario scenario = 1; */ public function setScenario(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\Scenario::class); $this->scenario = $var; } /** *
     * Histograms from all clients merged into one histogram.
     * 
* * .grpc.testing.HistogramData latencies = 2; */ public function getLatencies() { return $this->latencies; } /** *
     * Histograms from all clients merged into one histogram.
     * 
* * .grpc.testing.HistogramData latencies = 2; */ public function setLatencies(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\HistogramData::class); $this->latencies = $var; } /** *
     * Client stats for each client
     * 
* * repeated .grpc.testing.ClientStats client_stats = 3; */ public function getClientStats() { return $this->client_stats; } /** *
     * Client stats for each client
     * 
* * repeated .grpc.testing.ClientStats client_stats = 3; */ public function setClientStats(&$var) { GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\ClientStats::class); $this->client_stats = $var; } /** *
     * Server stats for each server
     * 
* * repeated .grpc.testing.ServerStats server_stats = 4; */ public function getServerStats() { return $this->server_stats; } /** *
     * Server stats for each server
     * 
* * repeated .grpc.testing.ServerStats server_stats = 4; */ public function setServerStats(&$var) { GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\ServerStats::class); $this->server_stats = $var; } /** *
     * Number of cores available to each server
     * 
* * repeated int32 server_cores = 5; */ public function getServerCores() { return $this->server_cores; } /** *
     * Number of cores available to each server
     * 
* * repeated int32 server_cores = 5; */ public function setServerCores(&$var) { GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32); $this->server_cores = $var; } /** *
     * An after-the-fact computed summary
     * 
* * .grpc.testing.ScenarioResultSummary summary = 6; */ public function getSummary() { return $this->summary; } /** *
     * An after-the-fact computed summary
     * 
* * .grpc.testing.ScenarioResultSummary summary = 6; */ public function setSummary(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\ScenarioResultSummary::class); $this->summary = $var; } /** *
     * Information on success or failure of each worker
     * 
* * repeated bool client_success = 7; */ public function getClientSuccess() { return $this->client_success; } /** *
     * Information on success or failure of each worker
     * 
* * repeated bool client_success = 7; */ public function setClientSuccess(&$var) { GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::BOOL); $this->client_success = $var; } /** * repeated bool server_success = 8; */ public function getServerSuccess() { return $this->server_success; } /** * repeated bool server_success = 8; */ public function setServerSuccess(&$var) { GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::BOOL); $this->server_success = $var; } /** *
     * Number of failed requests (one row per status code seen)
     * 
* * repeated .grpc.testing.RequestResultCount request_results = 9; */ public function getRequestResults() { return $this->request_results; } /** *
     * Number of failed requests (one row per status code seen)
     * 
* * repeated .grpc.testing.RequestResultCount request_results = 9; */ public function setRequestResults(&$var) { GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\RequestResultCount::class); $this->request_results = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/ScenarioResultSummary.php000066400000000000000000000221071310511640000302550ustar00rootroot00000000000000 * Basic summary that can be computed from ClientStats and ServerStats * once the scenario has finished. * * * Protobuf type grpc.testing.ScenarioResultSummary */ class ScenarioResultSummary extends \Google\Protobuf\Internal\Message { /** *
     * Total number of operations per second over all clients.
     * 
* * double qps = 1; */ private $qps = 0.0; /** *
     * QPS per one server core.
     * 
* * double qps_per_server_core = 2; */ private $qps_per_server_core = 0.0; /** *
     * server load based on system_time (0.85 => 85%)
     * 
* * double server_system_time = 3; */ private $server_system_time = 0.0; /** *
     * server load based on user_time (0.85 => 85%)
     * 
* * double server_user_time = 4; */ private $server_user_time = 0.0; /** *
     * client load based on system_time (0.85 => 85%)
     * 
* * double client_system_time = 5; */ private $client_system_time = 0.0; /** *
     * client load based on user_time (0.85 => 85%)
     * 
* * double client_user_time = 6; */ private $client_user_time = 0.0; /** *
     * X% latency percentiles (in nanoseconds)
     * 
* * double latency_50 = 7; */ private $latency_50 = 0.0; /** * double latency_90 = 8; */ private $latency_90 = 0.0; /** * double latency_95 = 9; */ private $latency_95 = 0.0; /** * double latency_99 = 10; */ private $latency_99 = 0.0; /** * double latency_999 = 11; */ private $latency_999 = 0.0; /** *
     * server cpu usage percentage
     * 
* * double server_cpu_usage = 12; */ private $server_cpu_usage = 0.0; /** *
     * Number of requests that succeeded/failed
     * 
* * double successful_requests_per_second = 13; */ private $successful_requests_per_second = 0.0; /** * double failed_requests_per_second = 14; */ private $failed_requests_per_second = 0.0; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); parent::__construct(); } /** *
     * Total number of operations per second over all clients.
     * 
* * double qps = 1; */ public function getQps() { return $this->qps; } /** *
     * Total number of operations per second over all clients.
     * 
* * double qps = 1; */ public function setQps($var) { GPBUtil::checkDouble($var); $this->qps = $var; } /** *
     * QPS per one server core.
     * 
* * double qps_per_server_core = 2; */ public function getQpsPerServerCore() { return $this->qps_per_server_core; } /** *
     * QPS per one server core.
     * 
* * double qps_per_server_core = 2; */ public function setQpsPerServerCore($var) { GPBUtil::checkDouble($var); $this->qps_per_server_core = $var; } /** *
     * server load based on system_time (0.85 => 85%)
     * 
* * double server_system_time = 3; */ public function getServerSystemTime() { return $this->server_system_time; } /** *
     * server load based on system_time (0.85 => 85%)
     * 
* * double server_system_time = 3; */ public function setServerSystemTime($var) { GPBUtil::checkDouble($var); $this->server_system_time = $var; } /** *
     * server load based on user_time (0.85 => 85%)
     * 
* * double server_user_time = 4; */ public function getServerUserTime() { return $this->server_user_time; } /** *
     * server load based on user_time (0.85 => 85%)
     * 
* * double server_user_time = 4; */ public function setServerUserTime($var) { GPBUtil::checkDouble($var); $this->server_user_time = $var; } /** *
     * client load based on system_time (0.85 => 85%)
     * 
* * double client_system_time = 5; */ public function getClientSystemTime() { return $this->client_system_time; } /** *
     * client load based on system_time (0.85 => 85%)
     * 
* * double client_system_time = 5; */ public function setClientSystemTime($var) { GPBUtil::checkDouble($var); $this->client_system_time = $var; } /** *
     * client load based on user_time (0.85 => 85%)
     * 
* * double client_user_time = 6; */ public function getClientUserTime() { return $this->client_user_time; } /** *
     * client load based on user_time (0.85 => 85%)
     * 
* * double client_user_time = 6; */ public function setClientUserTime($var) { GPBUtil::checkDouble($var); $this->client_user_time = $var; } /** *
     * X% latency percentiles (in nanoseconds)
     * 
* * double latency_50 = 7; */ public function getLatency50() { return $this->latency_50; } /** *
     * X% latency percentiles (in nanoseconds)
     * 
* * double latency_50 = 7; */ public function setLatency50($var) { GPBUtil::checkDouble($var); $this->latency_50 = $var; } /** * double latency_90 = 8; */ public function getLatency90() { return $this->latency_90; } /** * double latency_90 = 8; */ public function setLatency90($var) { GPBUtil::checkDouble($var); $this->latency_90 = $var; } /** * double latency_95 = 9; */ public function getLatency95() { return $this->latency_95; } /** * double latency_95 = 9; */ public function setLatency95($var) { GPBUtil::checkDouble($var); $this->latency_95 = $var; } /** * double latency_99 = 10; */ public function getLatency99() { return $this->latency_99; } /** * double latency_99 = 10; */ public function setLatency99($var) { GPBUtil::checkDouble($var); $this->latency_99 = $var; } /** * double latency_999 = 11; */ public function getLatency999() { return $this->latency_999; } /** * double latency_999 = 11; */ public function setLatency999($var) { GPBUtil::checkDouble($var); $this->latency_999 = $var; } /** *
     * server cpu usage percentage
     * 
* * double server_cpu_usage = 12; */ public function getServerCpuUsage() { return $this->server_cpu_usage; } /** *
     * server cpu usage percentage
     * 
* * double server_cpu_usage = 12; */ public function setServerCpuUsage($var) { GPBUtil::checkDouble($var); $this->server_cpu_usage = $var; } /** *
     * Number of requests that succeeded/failed
     * 
* * double successful_requests_per_second = 13; */ public function getSuccessfulRequestsPerSecond() { return $this->successful_requests_per_second; } /** *
     * Number of requests that succeeded/failed
     * 
* * double successful_requests_per_second = 13; */ public function setSuccessfulRequestsPerSecond($var) { GPBUtil::checkDouble($var); $this->successful_requests_per_second = $var; } /** * double failed_requests_per_second = 14; */ public function getFailedRequestsPerSecond() { return $this->failed_requests_per_second; } /** * double failed_requests_per_second = 14; */ public function setFailedRequestsPerSecond($var) { GPBUtil::checkDouble($var); $this->failed_requests_per_second = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/Scenarios.php000066400000000000000000000022041310511640000256570ustar00rootroot00000000000000 * A set of scenarios to be run with qps_json_driver * * * Protobuf type grpc.testing.Scenarios */ class Scenarios extends \Google\Protobuf\Internal\Message { /** * repeated .grpc.testing.Scenario scenarios = 1; */ private $scenarios; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); parent::__construct(); } /** * repeated .grpc.testing.Scenario scenarios = 1; */ public function getScenarios() { return $this->scenarios; } /** * repeated .grpc.testing.Scenario scenarios = 1; */ public function setScenarios(&$var) { GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\Scenario::class); $this->scenarios = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/SecurityParams.php000066400000000000000000000027471310511640000267200ustar00rootroot00000000000000 * presence of SecurityParams implies use of TLS * * * Protobuf type grpc.testing.SecurityParams */ class SecurityParams extends \Google\Protobuf\Internal\Message { /** * bool use_test_ca = 1; */ private $use_test_ca = false; /** * string server_host_override = 2; */ private $server_host_override = ''; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); parent::__construct(); } /** * bool use_test_ca = 1; */ public function getUseTestCa() { return $this->use_test_ca; } /** * bool use_test_ca = 1; */ public function setUseTestCa($var) { GPBUtil::checkBool($var); $this->use_test_ca = $var; } /** * string server_host_override = 2; */ public function getServerHostOverride() { return $this->server_host_override; } /** * string server_host_override = 2; */ public function setServerHostOverride($var) { GPBUtil::checkString($var, True); $this->server_host_override = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/ServerArgs.php000066400000000000000000000025461310511640000260250ustar00rootroot00000000000000grpc.testing.ServerArgs */ class ServerArgs extends \Google\Protobuf\Internal\Message { protected $argtype; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); parent::__construct(); } /** * .grpc.testing.ServerConfig setup = 1; */ public function getSetup() { return $this->readOneof(1); } /** * .grpc.testing.ServerConfig setup = 1; */ public function setSetup(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\ServerConfig::class); $this->writeOneof(1, $var); } /** * .grpc.testing.Mark mark = 2; */ public function getMark() { return $this->readOneof(2); } /** * .grpc.testing.Mark mark = 2; */ public function setMark(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\Mark::class); $this->writeOneof(2, $var); } public function getArgtype() { return $this->whichOneof("argtype"); } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/ServerConfig.php000066400000000000000000000165411310511640000263360ustar00rootroot00000000000000grpc.testing.ServerConfig */ class ServerConfig extends \Google\Protobuf\Internal\Message { /** * .grpc.testing.ServerType server_type = 1; */ private $server_type = 0; /** * .grpc.testing.SecurityParams security_params = 2; */ private $security_params = null; /** *
     * Port on which to listen. Zero means pick unused port.
     * 
* * int32 port = 4; */ private $port = 0; /** *
     * Only for async server. Number of threads used to serve the requests.
     * 
* * int32 async_server_threads = 7; */ private $async_server_threads = 0; /** *
     * Specify the number of cores to limit server to, if desired
     * 
* * int32 core_limit = 8; */ private $core_limit = 0; /** *
     * payload config, used in generic server.
     * Note this must NOT be used in proto (non-generic) servers. For proto servers,
     * 'response sizes' must be configured from the 'response_size' field of the
     * 'SimpleRequest' objects in RPC requests.
     * 
* * .grpc.testing.PayloadConfig payload_config = 9; */ private $payload_config = null; /** *
     * Specify the cores we should run the server on, if desired
     * 
* * repeated int32 core_list = 10; */ private $core_list; /** *
     * If we use an OTHER_SERVER client_type, this string gives more detail
     * 
* * string other_server_api = 11; */ private $other_server_api = ''; /** *
     * Buffer pool size (no buffer pool specified if unset)
     * 
* * int32 resource_quota_size = 1001; */ private $resource_quota_size = 0; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); parent::__construct(); } /** * .grpc.testing.ServerType server_type = 1; */ public function getServerType() { return $this->server_type; } /** * .grpc.testing.ServerType server_type = 1; */ public function setServerType($var) { GPBUtil::checkEnum($var, \Grpc\Testing\ServerType::class); $this->server_type = $var; } /** * .grpc.testing.SecurityParams security_params = 2; */ public function getSecurityParams() { return $this->security_params; } /** * .grpc.testing.SecurityParams security_params = 2; */ public function setSecurityParams(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\SecurityParams::class); $this->security_params = $var; } /** *
     * Port on which to listen. Zero means pick unused port.
     * 
* * int32 port = 4; */ public function getPort() { return $this->port; } /** *
     * Port on which to listen. Zero means pick unused port.
     * 
* * int32 port = 4; */ public function setPort($var) { GPBUtil::checkInt32($var); $this->port = $var; } /** *
     * Only for async server. Number of threads used to serve the requests.
     * 
* * int32 async_server_threads = 7; */ public function getAsyncServerThreads() { return $this->async_server_threads; } /** *
     * Only for async server. Number of threads used to serve the requests.
     * 
* * int32 async_server_threads = 7; */ public function setAsyncServerThreads($var) { GPBUtil::checkInt32($var); $this->async_server_threads = $var; } /** *
     * Specify the number of cores to limit server to, if desired
     * 
* * int32 core_limit = 8; */ public function getCoreLimit() { return $this->core_limit; } /** *
     * Specify the number of cores to limit server to, if desired
     * 
* * int32 core_limit = 8; */ public function setCoreLimit($var) { GPBUtil::checkInt32($var); $this->core_limit = $var; } /** *
     * payload config, used in generic server.
     * Note this must NOT be used in proto (non-generic) servers. For proto servers,
     * 'response sizes' must be configured from the 'response_size' field of the
     * 'SimpleRequest' objects in RPC requests.
     * 
* * .grpc.testing.PayloadConfig payload_config = 9; */ public function getPayloadConfig() { return $this->payload_config; } /** *
     * payload config, used in generic server.
     * Note this must NOT be used in proto (non-generic) servers. For proto servers,
     * 'response sizes' must be configured from the 'response_size' field of the
     * 'SimpleRequest' objects in RPC requests.
     * 
* * .grpc.testing.PayloadConfig payload_config = 9; */ public function setPayloadConfig(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\PayloadConfig::class); $this->payload_config = $var; } /** *
     * Specify the cores we should run the server on, if desired
     * 
* * repeated int32 core_list = 10; */ public function getCoreList() { return $this->core_list; } /** *
     * Specify the cores we should run the server on, if desired
     * 
* * repeated int32 core_list = 10; */ public function setCoreList(&$var) { GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32); $this->core_list = $var; } /** *
     * If we use an OTHER_SERVER client_type, this string gives more detail
     * 
* * string other_server_api = 11; */ public function getOtherServerApi() { return $this->other_server_api; } /** *
     * If we use an OTHER_SERVER client_type, this string gives more detail
     * 
* * string other_server_api = 11; */ public function setOtherServerApi($var) { GPBUtil::checkString($var, True); $this->other_server_api = $var; } /** *
     * Buffer pool size (no buffer pool specified if unset)
     * 
* * int32 resource_quota_size = 1001; */ public function getResourceQuotaSize() { return $this->resource_quota_size; } /** *
     * Buffer pool size (no buffer pool specified if unset)
     * 
* * int32 resource_quota_size = 1001; */ public function setResourceQuotaSize($var) { GPBUtil::checkInt32($var); $this->resource_quota_size = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/ServerStats.php000066400000000000000000000102671310511640000262260ustar00rootroot00000000000000grpc.testing.ServerStats */ class ServerStats extends \Google\Protobuf\Internal\Message { /** *
     * wall clock time change in seconds since last reset
     * 
* * double time_elapsed = 1; */ private $time_elapsed = 0.0; /** *
     * change in user time (in seconds) used by the server since last reset
     * 
* * double time_user = 2; */ private $time_user = 0.0; /** *
     * change in server time (in seconds) used by the server process and all
     * threads since last reset
     * 
* * double time_system = 3; */ private $time_system = 0.0; /** *
     * change in total cpu time of the server (data from proc/stat)
     * 
* * uint64 total_cpu_time = 4; */ private $total_cpu_time = 0; /** *
     * change in idle time of the server (data from proc/stat)
     * 
* * uint64 idle_cpu_time = 5; */ private $idle_cpu_time = 0; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce(); parent::__construct(); } /** *
     * wall clock time change in seconds since last reset
     * 
* * double time_elapsed = 1; */ public function getTimeElapsed() { return $this->time_elapsed; } /** *
     * wall clock time change in seconds since last reset
     * 
* * double time_elapsed = 1; */ public function setTimeElapsed($var) { GPBUtil::checkDouble($var); $this->time_elapsed = $var; } /** *
     * change in user time (in seconds) used by the server since last reset
     * 
* * double time_user = 2; */ public function getTimeUser() { return $this->time_user; } /** *
     * change in user time (in seconds) used by the server since last reset
     * 
* * double time_user = 2; */ public function setTimeUser($var) { GPBUtil::checkDouble($var); $this->time_user = $var; } /** *
     * change in server time (in seconds) used by the server process and all
     * threads since last reset
     * 
* * double time_system = 3; */ public function getTimeSystem() { return $this->time_system; } /** *
     * change in server time (in seconds) used by the server process and all
     * threads since last reset
     * 
* * double time_system = 3; */ public function setTimeSystem($var) { GPBUtil::checkDouble($var); $this->time_system = $var; } /** *
     * change in total cpu time of the server (data from proc/stat)
     * 
* * uint64 total_cpu_time = 4; */ public function getTotalCpuTime() { return $this->total_cpu_time; } /** *
     * change in total cpu time of the server (data from proc/stat)
     * 
* * uint64 total_cpu_time = 4; */ public function setTotalCpuTime($var) { GPBUtil::checkUint64($var); $this->total_cpu_time = $var; } /** *
     * change in idle time of the server (data from proc/stat)
     * 
* * uint64 idle_cpu_time = 5; */ public function getIdleCpuTime() { return $this->idle_cpu_time; } /** *
     * change in idle time of the server (data from proc/stat)
     * 
* * uint64 idle_cpu_time = 5; */ public function setIdleCpuTime($var) { GPBUtil::checkUint64($var); $this->idle_cpu_time = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/ServerStatus.php000066400000000000000000000042021310511640000264030ustar00rootroot00000000000000grpc.testing.ServerStatus */ class ServerStatus extends \Google\Protobuf\Internal\Message { /** * .grpc.testing.ServerStats stats = 1; */ private $stats = null; /** *
     * the port bound by the server
     * 
* * int32 port = 2; */ private $port = 0; /** *
     * Number of cores available to the server
     * 
* * int32 cores = 3; */ private $cores = 0; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); parent::__construct(); } /** * .grpc.testing.ServerStats stats = 1; */ public function getStats() { return $this->stats; } /** * .grpc.testing.ServerStats stats = 1; */ public function setStats(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\ServerStats::class); $this->stats = $var; } /** *
     * the port bound by the server
     * 
* * int32 port = 2; */ public function getPort() { return $this->port; } /** *
     * the port bound by the server
     * 
* * int32 port = 2; */ public function setPort($var) { GPBUtil::checkInt32($var); $this->port = $var; } /** *
     * Number of cores available to the server
     * 
* * int32 cores = 3; */ public function getCores() { return $this->cores; } /** *
     * Number of cores available to the server
     * 
* * int32 cores = 3; */ public function setCores($var) { GPBUtil::checkInt32($var); $this->cores = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/ServerType.php000066400000000000000000000012061310511640000260420ustar00rootroot00000000000000grpc.testing.ServerType */ class ServerType { /** * SYNC_SERVER = 0; */ const SYNC_SERVER = 0; /** * ASYNC_SERVER = 1; */ const ASYNC_SERVER = 1; /** * ASYNC_GENERIC_SERVER = 2; */ const ASYNC_GENERIC_SERVER = 2; /** *
     * used for some language-specific variants
     * 
* * OTHER_SERVER = 3; */ const OTHER_SERVER = 3; } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/SimpleProtoParams.php000066400000000000000000000024611310511640000273570ustar00rootroot00000000000000grpc.testing.SimpleProtoParams */ class SimpleProtoParams extends \Google\Protobuf\Internal\Message { /** * int32 req_size = 1; */ private $req_size = 0; /** * int32 resp_size = 2; */ private $resp_size = 0; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Payloads::initOnce(); parent::__construct(); } /** * int32 req_size = 1; */ public function getReqSize() { return $this->req_size; } /** * int32 req_size = 1; */ public function setReqSize($var) { GPBUtil::checkInt32($var); $this->req_size = $var; } /** * int32 resp_size = 2; */ public function getRespSize() { return $this->resp_size; } /** * int32 resp_size = 2; */ public function setRespSize($var) { GPBUtil::checkInt32($var); $this->resp_size = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/SimpleRequest.php000066400000000000000000000172501310511640000265420ustar00rootroot00000000000000 * Unary request. * * * Protobuf type grpc.testing.SimpleRequest */ class SimpleRequest extends \Google\Protobuf\Internal\Message { /** *
     * DEPRECATED, don't use. To be removed shortly.
     * Desired payload type in the response from the server.
     * If response_type is RANDOM, server randomly chooses one from other formats.
     * 
* * .grpc.testing.PayloadType response_type = 1; */ private $response_type = 0; /** *
     * Desired payload size in the response from the server.
     * 
* * int32 response_size = 2; */ private $response_size = 0; /** *
     * Optional input payload sent along with the request.
     * 
* * .grpc.testing.Payload payload = 3; */ private $payload = null; /** *
     * Whether SimpleResponse should include username.
     * 
* * bool fill_username = 4; */ private $fill_username = false; /** *
     * Whether SimpleResponse should include OAuth scope.
     * 
* * bool fill_oauth_scope = 5; */ private $fill_oauth_scope = false; /** *
     * Whether to request the server to compress the response. This field is
     * "nullable" in order to interoperate seamlessly with clients not able to
     * implement the full compression tests by introspecting the call to verify
     * the response's compression status.
     * 
* * .grpc.testing.BoolValue response_compressed = 6; */ private $response_compressed = null; /** *
     * Whether server should return a given status
     * 
* * .grpc.testing.EchoStatus response_status = 7; */ private $response_status = null; /** *
     * Whether the server should expect this request to be compressed.
     * 
* * .grpc.testing.BoolValue expect_compressed = 8; */ private $expect_compressed = null; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); parent::__construct(); } /** *
     * DEPRECATED, don't use. To be removed shortly.
     * Desired payload type in the response from the server.
     * If response_type is RANDOM, server randomly chooses one from other formats.
     * 
* * .grpc.testing.PayloadType response_type = 1; */ public function getResponseType() { return $this->response_type; } /** *
     * DEPRECATED, don't use. To be removed shortly.
     * Desired payload type in the response from the server.
     * If response_type is RANDOM, server randomly chooses one from other formats.
     * 
* * .grpc.testing.PayloadType response_type = 1; */ public function setResponseType($var) { GPBUtil::checkEnum($var, \Grpc\Testing\PayloadType::class); $this->response_type = $var; } /** *
     * Desired payload size in the response from the server.
     * 
* * int32 response_size = 2; */ public function getResponseSize() { return $this->response_size; } /** *
     * Desired payload size in the response from the server.
     * 
* * int32 response_size = 2; */ public function setResponseSize($var) { GPBUtil::checkInt32($var); $this->response_size = $var; } /** *
     * Optional input payload sent along with the request.
     * 
* * .grpc.testing.Payload payload = 3; */ public function getPayload() { return $this->payload; } /** *
     * Optional input payload sent along with the request.
     * 
* * .grpc.testing.Payload payload = 3; */ public function setPayload(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\Payload::class); $this->payload = $var; } /** *
     * Whether SimpleResponse should include username.
     * 
* * bool fill_username = 4; */ public function getFillUsername() { return $this->fill_username; } /** *
     * Whether SimpleResponse should include username.
     * 
* * bool fill_username = 4; */ public function setFillUsername($var) { GPBUtil::checkBool($var); $this->fill_username = $var; } /** *
     * Whether SimpleResponse should include OAuth scope.
     * 
* * bool fill_oauth_scope = 5; */ public function getFillOauthScope() { return $this->fill_oauth_scope; } /** *
     * Whether SimpleResponse should include OAuth scope.
     * 
* * bool fill_oauth_scope = 5; */ public function setFillOauthScope($var) { GPBUtil::checkBool($var); $this->fill_oauth_scope = $var; } /** *
     * Whether to request the server to compress the response. This field is
     * "nullable" in order to interoperate seamlessly with clients not able to
     * implement the full compression tests by introspecting the call to verify
     * the response's compression status.
     * 
* * .grpc.testing.BoolValue response_compressed = 6; */ public function getResponseCompressed() { return $this->response_compressed; } /** *
     * Whether to request the server to compress the response. This field is
     * "nullable" in order to interoperate seamlessly with clients not able to
     * implement the full compression tests by introspecting the call to verify
     * the response's compression status.
     * 
* * .grpc.testing.BoolValue response_compressed = 6; */ public function setResponseCompressed(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\BoolValue::class); $this->response_compressed = $var; } /** *
     * Whether server should return a given status
     * 
* * .grpc.testing.EchoStatus response_status = 7; */ public function getResponseStatus() { return $this->response_status; } /** *
     * Whether server should return a given status
     * 
* * .grpc.testing.EchoStatus response_status = 7; */ public function setResponseStatus(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\EchoStatus::class); $this->response_status = $var; } /** *
     * Whether the server should expect this request to be compressed.
     * 
* * .grpc.testing.BoolValue expect_compressed = 8; */ public function getExpectCompressed() { return $this->expect_compressed; } /** *
     * Whether the server should expect this request to be compressed.
     * 
* * .grpc.testing.BoolValue expect_compressed = 8; */ public function setExpectCompressed(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\BoolValue::class); $this->expect_compressed = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/SimpleResponse.php000066400000000000000000000052741310511640000267130ustar00rootroot00000000000000 * Unary response, as configured by the request. * * * Protobuf type grpc.testing.SimpleResponse */ class SimpleResponse extends \Google\Protobuf\Internal\Message { /** *
     * Payload to increase message size.
     * 
* * .grpc.testing.Payload payload = 1; */ private $payload = null; /** *
     * The user the request came from, for verifying authentication was
     * successful when the client expected it.
     * 
* * string username = 2; */ private $username = ''; /** *
     * OAuth scope.
     * 
* * string oauth_scope = 3; */ private $oauth_scope = ''; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); parent::__construct(); } /** *
     * Payload to increase message size.
     * 
* * .grpc.testing.Payload payload = 1; */ public function getPayload() { return $this->payload; } /** *
     * Payload to increase message size.
     * 
* * .grpc.testing.Payload payload = 1; */ public function setPayload(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\Payload::class); $this->payload = $var; } /** *
     * The user the request came from, for verifying authentication was
     * successful when the client expected it.
     * 
* * string username = 2; */ public function getUsername() { return $this->username; } /** *
     * The user the request came from, for verifying authentication was
     * successful when the client expected it.
     * 
* * string username = 2; */ public function setUsername($var) { GPBUtil::checkString($var, True); $this->username = $var; } /** *
     * OAuth scope.
     * 
* * string oauth_scope = 3; */ public function getOauthScope() { return $this->oauth_scope; } /** *
     * OAuth scope.
     * 
* * string oauth_scope = 3; */ public function setOauthScope($var) { GPBUtil::checkString($var, True); $this->oauth_scope = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/StreamingInputCallRequest.php000066400000000000000000000054621310511640000310600ustar00rootroot00000000000000 * Client-streaming request. * * * Protobuf type grpc.testing.StreamingInputCallRequest */ class StreamingInputCallRequest extends \Google\Protobuf\Internal\Message { /** *
     * Optional input payload sent along with the request.
     * 
* * .grpc.testing.Payload payload = 1; */ private $payload = null; /** *
     * Whether the server should expect this request to be compressed. This field
     * is "nullable" in order to interoperate seamlessly with servers not able to
     * implement the full compression tests by introspecting the call to verify
     * the request's compression status.
     * 
* * .grpc.testing.BoolValue expect_compressed = 2; */ private $expect_compressed = null; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); parent::__construct(); } /** *
     * Optional input payload sent along with the request.
     * 
* * .grpc.testing.Payload payload = 1; */ public function getPayload() { return $this->payload; } /** *
     * Optional input payload sent along with the request.
     * 
* * .grpc.testing.Payload payload = 1; */ public function setPayload(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\Payload::class); $this->payload = $var; } /** *
     * Whether the server should expect this request to be compressed. This field
     * is "nullable" in order to interoperate seamlessly with servers not able to
     * implement the full compression tests by introspecting the call to verify
     * the request's compression status.
     * 
* * .grpc.testing.BoolValue expect_compressed = 2; */ public function getExpectCompressed() { return $this->expect_compressed; } /** *
     * Whether the server should expect this request to be compressed. This field
     * is "nullable" in order to interoperate seamlessly with servers not able to
     * implement the full compression tests by introspecting the call to verify
     * the request's compression status.
     * 
* * .grpc.testing.BoolValue expect_compressed = 2; */ public function setExpectCompressed(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\BoolValue::class); $this->expect_compressed = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/StreamingInputCallResponse.php000066400000000000000000000025741310511640000312270ustar00rootroot00000000000000 * Client-streaming response. * * * Protobuf type grpc.testing.StreamingInputCallResponse */ class StreamingInputCallResponse extends \Google\Protobuf\Internal\Message { /** *
     * Aggregated size of payloads received from the client.
     * 
* * int32 aggregated_payload_size = 1; */ private $aggregated_payload_size = 0; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); parent::__construct(); } /** *
     * Aggregated size of payloads received from the client.
     * 
* * int32 aggregated_payload_size = 1; */ public function getAggregatedPayloadSize() { return $this->aggregated_payload_size; } /** *
     * Aggregated size of payloads received from the client.
     * 
* * int32 aggregated_payload_size = 1; */ public function setAggregatedPayloadSize($var) { GPBUtil::checkInt32($var); $this->aggregated_payload_size = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/StreamingOutputCallRequest.php000066400000000000000000000107631310511640000312610ustar00rootroot00000000000000 * Server-streaming request. * * * Protobuf type grpc.testing.StreamingOutputCallRequest */ class StreamingOutputCallRequest extends \Google\Protobuf\Internal\Message { /** *
     * DEPRECATED, don't use. To be removed shortly.
     * Desired payload type in the response from the server.
     * If response_type is RANDOM, the payload from each response in the stream
     * might be of different types. This is to simulate a mixed type of payload
     * stream.
     * 
* * .grpc.testing.PayloadType response_type = 1; */ private $response_type = 0; /** *
     * Configuration for each expected response message.
     * 
* * repeated .grpc.testing.ResponseParameters response_parameters = 2; */ private $response_parameters; /** *
     * Optional input payload sent along with the request.
     * 
* * .grpc.testing.Payload payload = 3; */ private $payload = null; /** *
     * Whether server should return a given status
     * 
* * .grpc.testing.EchoStatus response_status = 7; */ private $response_status = null; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); parent::__construct(); } /** *
     * DEPRECATED, don't use. To be removed shortly.
     * Desired payload type in the response from the server.
     * If response_type is RANDOM, the payload from each response in the stream
     * might be of different types. This is to simulate a mixed type of payload
     * stream.
     * 
* * .grpc.testing.PayloadType response_type = 1; */ public function getResponseType() { return $this->response_type; } /** *
     * DEPRECATED, don't use. To be removed shortly.
     * Desired payload type in the response from the server.
     * If response_type is RANDOM, the payload from each response in the stream
     * might be of different types. This is to simulate a mixed type of payload
     * stream.
     * 
* * .grpc.testing.PayloadType response_type = 1; */ public function setResponseType($var) { GPBUtil::checkEnum($var, \Grpc\Testing\PayloadType::class); $this->response_type = $var; } /** *
     * Configuration for each expected response message.
     * 
* * repeated .grpc.testing.ResponseParameters response_parameters = 2; */ public function getResponseParameters() { return $this->response_parameters; } /** *
     * Configuration for each expected response message.
     * 
* * repeated .grpc.testing.ResponseParameters response_parameters = 2; */ public function setResponseParameters(&$var) { GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\ResponseParameters::class); $this->response_parameters = $var; } /** *
     * Optional input payload sent along with the request.
     * 
* * .grpc.testing.Payload payload = 3; */ public function getPayload() { return $this->payload; } /** *
     * Optional input payload sent along with the request.
     * 
* * .grpc.testing.Payload payload = 3; */ public function setPayload(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\Payload::class); $this->payload = $var; } /** *
     * Whether server should return a given status
     * 
* * .grpc.testing.EchoStatus response_status = 7; */ public function getResponseStatus() { return $this->response_status; } /** *
     * Whether server should return a given status
     * 
* * .grpc.testing.EchoStatus response_status = 7; */ public function setResponseStatus(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\EchoStatus::class); $this->response_status = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/StreamingOutputCallResponse.php000066400000000000000000000025121310511640000314200ustar00rootroot00000000000000 * Server-streaming response, as configured by the request and parameters. * * * Protobuf type grpc.testing.StreamingOutputCallResponse */ class StreamingOutputCallResponse extends \Google\Protobuf\Internal\Message { /** *
     * Payload to increase response size.
     * 
* * .grpc.testing.Payload payload = 1; */ private $payload = null; public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce(); parent::__construct(); } /** *
     * Payload to increase response size.
     * 
* * .grpc.testing.Payload payload = 1; */ public function getPayload() { return $this->payload; } /** *
     * Payload to increase response size.
     * 
* * .grpc.testing.Payload payload = 1; */ public function setPayload(&$var) { GPBUtil::checkMessage($var, \Grpc\Testing\Payload::class); $this->payload = $var; } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/Void.php000066400000000000000000000010011310511640000246240ustar00rootroot00000000000000grpc.testing.Void */ class Void extends \Google\Protobuf\Internal\Message { public function __construct() { \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce(); parent::__construct(); } } grpc-1.3.2/src/php/tests/qps/generated_code/Grpc/Testing/WorkerServiceClient.php000066400000000000000000000105441310511640000276700ustar00rootroot00000000000000_bidiRequest('/grpc.testing.WorkerService/RunServer', ['\Grpc\Testing\ServerStatus','decode'], $metadata, $options); } /** * Start client with specified workload. * First request sent specifies the ClientConfig followed by ClientStatus * response. After that, a "Mark" can be sent anytime to request the latest * stats. Closing the stream will initiate shutdown of the test client * and once the shutdown has finished, the OK status is sent to terminate * this RPC. * @param array $metadata metadata * @param array $options call options */ public function RunClient($metadata = [], $options = []) { return $this->_bidiRequest('/grpc.testing.WorkerService/RunClient', ['\Grpc\Testing\ClientStatus','decode'], $metadata, $options); } /** * Just return the core count - unary call * @param \Grpc\Testing\CoreRequest $argument input argument * @param array $metadata metadata * @param array $options call options */ public function CoreCount(\Grpc\Testing\CoreRequest $argument, $metadata = [], $options = []) { return $this->_simpleRequest('/grpc.testing.WorkerService/CoreCount', $argument, ['\Grpc\Testing\CoreResponse', 'decode'], $metadata, $options); } /** * Quit this worker * @param \Grpc\Testing\Void $argument input argument * @param array $metadata metadata * @param array $options call options */ public function QuitWorker(\Grpc\Testing\Void $argument, $metadata = [], $options = []) { return $this->_simpleRequest('/grpc.testing.WorkerService/QuitWorker', $argument, ['\Grpc\Testing\Void', 'decode'], $metadata, $options); } } } grpc-1.3.2/src/php/tests/unit_tests/000077500000000000000000000000001310511640000173605ustar00rootroot00000000000000grpc-1.3.2/src/php/tests/unit_tests/CallCredentials2Test.php000066400000000000000000000161771310511640000240600ustar00rootroot00000000000000server = new Grpc\Server(); $this->port = $this->server->addSecureHttp2Port('0.0.0.0:0', $server_credentials); $this->server->start(); $this->host_override = 'foo.test.google.fr'; $this->channel = new Grpc\Channel( 'localhost:'.$this->port, [ 'grpc.ssl_target_name_override' => $this->host_override, 'grpc.default_authority' => $this->host_override, 'credentials' => $credentials, ] ); } public function tearDown() { unset($this->channel); unset($this->server); } public function callbackFunc($context) { $this->assertTrue(is_string($context->service_url)); $this->assertTrue(is_string($context->method_name)); return ['k1' => ['v1'], 'k2' => ['v2']]; } public function testCreateFromPlugin() { $deadline = Grpc\Timeval::infFuture(); $status_text = 'xyz'; $call = new Grpc\Call($this->channel, '/abc/dummy_method', $deadline, $this->host_override); $call_credentials = Grpc\CallCredentials::createFromPlugin( array($this, 'callbackFunc')); $call->setCredentials($call_credentials); $event = $call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, ]); $this->assertTrue($event->send_metadata); $this->assertTrue($event->send_close); $event = $this->server->requestCall(); $this->assertTrue(is_array($event->metadata)); $metadata = $event->metadata; $this->assertTrue(array_key_exists('k1', $metadata)); $this->assertTrue(array_key_exists('k2', $metadata)); $this->assertSame($metadata['k1'], ['v1']); $this->assertSame($metadata['k2'], ['v2']); $this->assertSame('/abc/dummy_method', $event->method); $server_call = $event->call; $event = $server_call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_STATUS_FROM_SERVER => [ 'metadata' => [], 'code' => Grpc\STATUS_OK, 'details' => $status_text, ], Grpc\OP_RECV_CLOSE_ON_SERVER => true, ]); $this->assertTrue($event->send_metadata); $this->assertTrue($event->send_status); $this->assertFalse($event->cancelled); $event = $call->startBatch([ Grpc\OP_RECV_INITIAL_METADATA => true, Grpc\OP_RECV_STATUS_ON_CLIENT => true, ]); $this->assertSame([], $event->metadata); $status = $event->status; $this->assertSame([], $status->metadata); $this->assertSame(Grpc\STATUS_OK, $status->code); $this->assertSame($status_text, $status->details); unset($call); unset($server_call); } public function invalidKeyCallbackFunc($context) { $this->assertTrue(is_string($context->service_url)); $this->assertTrue(is_string($context->method_name)); return ['K1' => ['v1']]; } public function testCallbackWithInvalidKey() { $deadline = Grpc\Timeval::infFuture(); $status_text = 'xyz'; $call = new Grpc\Call($this->channel, '/abc/dummy_method', $deadline, $this->host_override); $call_credentials = Grpc\CallCredentials::createFromPlugin( array($this, 'invalidKeyCallbackFunc')); $call->setCredentials($call_credentials); $event = $call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, Grpc\OP_RECV_STATUS_ON_CLIENT => true, ]); $this->assertTrue($event->send_metadata); $this->assertTrue($event->send_close); $this->assertTrue($event->status->code == Grpc\STATUS_UNAUTHENTICATED); } public function invalidReturnCallbackFunc($context) { $this->assertTrue(is_string($context->service_url)); $this->assertTrue(is_string($context->method_name)); return 'a string'; } public function testCallbackWithInvalidReturnValue() { $deadline = Grpc\Timeval::infFuture(); $status_text = 'xyz'; $call = new Grpc\Call($this->channel, '/abc/dummy_method', $deadline, $this->host_override); $call_credentials = Grpc\CallCredentials::createFromPlugin( array($this, 'invalidReturnCallbackFunc')); $call->setCredentials($call_credentials); $event = $call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, Grpc\OP_RECV_STATUS_ON_CLIENT => true, ]); $this->assertTrue($event->send_metadata); $this->assertTrue($event->send_close); $this->assertTrue($event->status->code == Grpc\STATUS_UNAUTHENTICATED); } } grpc-1.3.2/src/php/tests/unit_tests/CallCredentialsTest.php000066400000000000000000000140761310511640000237720ustar00rootroot00000000000000credentials = Grpc\ChannelCredentials::createSsl( file_get_contents(dirname(__FILE__).'/../data/ca.pem')); $this->call_credentials = Grpc\CallCredentials::createFromPlugin( [$this, 'callbackFunc']); $this->credentials = Grpc\ChannelCredentials::createComposite( $this->credentials, $this->call_credentials ); $server_credentials = Grpc\ServerCredentials::createSsl( null, file_get_contents(dirname(__FILE__).'/../data/server1.key'), file_get_contents(dirname(__FILE__).'/../data/server1.pem')); $this->server = new Grpc\Server(); $this->port = $this->server->addSecureHttp2Port('0.0.0.0:0', $server_credentials); $this->server->start(); $this->host_override = 'foo.test.google.fr'; $this->channel = new Grpc\Channel( 'localhost:'.$this->port, [ 'grpc.ssl_target_name_override' => $this->host_override, 'grpc.default_authority' => $this->host_override, 'credentials' => $this->credentials, ] ); } public function tearDown() { unset($this->channel); unset($this->server); } public function callbackFunc($context) { $this->assertTrue(is_string($context->service_url)); $this->assertTrue(is_string($context->method_name)); return ['k1' => ['v1'], 'k2' => ['v2']]; } public function testCreateFromPlugin() { $deadline = Grpc\Timeval::infFuture(); $status_text = 'xyz'; $call = new Grpc\Call($this->channel, '/abc/dummy_method', $deadline, $this->host_override); $event = $call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, ]); $this->assertTrue($event->send_metadata); $this->assertTrue($event->send_close); $event = $this->server->requestCall(); $this->assertTrue(is_array($event->metadata)); $metadata = $event->metadata; $this->assertTrue(array_key_exists('k1', $metadata)); $this->assertTrue(array_key_exists('k2', $metadata)); $this->assertSame($metadata['k1'], ['v1']); $this->assertSame($metadata['k2'], ['v2']); $this->assertSame('/abc/dummy_method', $event->method); $server_call = $event->call; $event = $server_call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_STATUS_FROM_SERVER => [ 'metadata' => [], 'code' => Grpc\STATUS_OK, 'details' => $status_text, ], Grpc\OP_RECV_CLOSE_ON_SERVER => true, ]); $this->assertTrue($event->send_metadata); $this->assertTrue($event->send_status); $this->assertFalse($event->cancelled); $event = $call->startBatch([ Grpc\OP_RECV_INITIAL_METADATA => true, Grpc\OP_RECV_STATUS_ON_CLIENT => true, ]); $this->assertSame([], $event->metadata); $status = $event->status; $this->assertSame([], $status->metadata); $this->assertSame(Grpc\STATUS_OK, $status->code); $this->assertSame($status_text, $status->details); unset($call); unset($server_call); } public function callbackFunc2($context) { return []; } public function testCreateComposite() { $call_credentials2 = Grpc\CallCredentials::createFromPlugin( [$this, 'callbackFunc2']); $call_credentials3 = Grpc\CallCredentials::createComposite( $this->call_credentials, $call_credentials2 ); $this->assertSame('Grpc\CallCredentials', get_class($call_credentials3)); } /** * @expectedException InvalidArgumentException */ public function testCreateFromPluginInvalidParam() { $call_credentials = Grpc\CallCredentials::createFromPlugin( 'callbackFunc' ); } /** * @expectedException InvalidArgumentException */ public function testCreateCompositeInvalidParam() { $call_credentials3 = Grpc\CallCredentials::createComposite( $this->call_credentials, $this->credentials ); } } grpc-1.3.2/src/php/tests/unit_tests/CallTest.php000066400000000000000000000130261310511640000216060ustar00rootroot00000000000000addHttp2Port('0.0.0.0:0'); } public function setUp() { $this->channel = new Grpc\Channel('localhost:'.self::$port, []); $this->call = new Grpc\Call($this->channel, '/foo', Grpc\Timeval::infFuture()); } public function tearDown() { unset($this->call); unset($this->channel); } public function testConstructor() { $this->assertSame('Grpc\Call', get_class($this->call)); $this->assertObjectHasAttribute('channel', $this->call); } public function testAddEmptyMetadata() { $batch = [ Grpc\OP_SEND_INITIAL_METADATA => [], ]; $result = $this->call->startBatch($batch); $this->assertTrue($result->send_metadata); } public function testAddSingleMetadata() { $batch = [ Grpc\OP_SEND_INITIAL_METADATA => ['key' => ['value']], ]; $result = $this->call->startBatch($batch); $this->assertTrue($result->send_metadata); } public function testAddMultiValueMetadata() { $batch = [ Grpc\OP_SEND_INITIAL_METADATA => ['key' => ['value1', 'value2']], ]; $result = $this->call->startBatch($batch); $this->assertTrue($result->send_metadata); } public function testAddSingleAndMultiValueMetadata() { $batch = [ Grpc\OP_SEND_INITIAL_METADATA => ['key1' => ['value1'], 'key2' => ['value2', 'value3', ], ], ]; $result = $this->call->startBatch($batch); $this->assertTrue($result->send_metadata); } public function testGetPeer() { $this->assertTrue(is_string($this->call->getPeer())); } public function testCancel() { $this->assertNull($this->call->cancel()); } /** * @expectedException InvalidArgumentException */ public function testInvalidStartBatchKey() { $batch = [ 'invalid' => ['key1' => 'value1'], ]; $result = $this->call->startBatch($batch); } /** * @expectedException InvalidArgumentException */ public function testInvalidMetadataStrKey() { $batch = [ Grpc\OP_SEND_INITIAL_METADATA => ['Key' => ['value1', 'value2']], ]; $result = $this->call->startBatch($batch); } /** * @expectedException InvalidArgumentException */ public function testInvalidMetadataIntKey() { $batch = [ Grpc\OP_SEND_INITIAL_METADATA => [1 => ['value1', 'value2']], ]; $result = $this->call->startBatch($batch); } /** * @expectedException InvalidArgumentException */ public function testInvalidMetadataInnerValue() { $batch = [ Grpc\OP_SEND_INITIAL_METADATA => ['key1' => 'value1'], ]; $result = $this->call->startBatch($batch); } /** * @expectedException InvalidArgumentException */ public function testInvalidConstuctor() { $this->call = new Grpc\Call(); $this->assertNull($this->call); } /** * @expectedException InvalidArgumentException */ public function testInvalidConstuctor2() { $this->call = new Grpc\Call('hi', 'hi', 'hi'); $this->assertNull($this->call); } /** * @expectedException InvalidArgumentException */ public function testInvalidSetCredentials() { $this->call->setCredentials('hi'); } /** * @expectedException InvalidArgumentException */ public function testInvalidSetCredentials2() { $this->call->setCredentials([]); } } grpc-1.3.2/src/php/tests/unit_tests/ChannelCredentialsTest.php000066400000000000000000000053541310511640000244660ustar00rootroot00000000000000assertNotNull($channel_credentials); } public function testCreateSslWith3NullString() { $channel_credentials = Grpc\ChannelCredentials::createSsl('', '', ''); $this->assertNotNull($channel_credentials); } public function testCreateInsecure() { $channel_credentials = Grpc\ChannelCredentials::createInsecure(); $this->assertNull($channel_credentials); } /** * @expectedException InvalidArgumentException */ public function testInvalidCreateSsl() { $channel_credentials = Grpc\ChannelCredentials::createSsl([]); } /** * @expectedException InvalidArgumentException */ public function testInvalidCreateComposite() { $channel_credentials = Grpc\ChannelCredentials::createComposite( 'something', 'something'); } } grpc-1.3.2/src/php/tests/unit_tests/ChannelTest.php000066400000000000000000000137751310511640000223160ustar00rootroot00000000000000channel); } public function testInsecureCredentials() { $this->channel = new Grpc\Channel( 'localhost:0', [ 'credentials' => Grpc\ChannelCredentials::createInsecure(), ] ); $this->assertSame('Grpc\Channel', get_class($this->channel)); } public function testGetConnectivityState() { $this->channel = new Grpc\Channel('localhost:0', ['credentials' => Grpc\ChannelCredentials::createInsecure()]); $state = $this->channel->getConnectivityState(); $this->assertEquals(0, $state); } public function testGetConnectivityStateWithInt() { $this->channel = new Grpc\Channel('localhost:0', ['credentials' => Grpc\ChannelCredentials::createInsecure()]); $state = $this->channel->getConnectivityState(123); $this->assertEquals(0, $state); } public function testGetConnectivityStateWithString() { $this->channel = new Grpc\Channel('localhost:0', ['credentials' => Grpc\ChannelCredentials::createInsecure()]); $state = $this->channel->getConnectivityState('hello'); $this->assertEquals(0, $state); } public function testGetConnectivityStateWithBool() { $this->channel = new Grpc\Channel('localhost:0', ['credentials' => Grpc\ChannelCredentials::createInsecure()]); $state = $this->channel->getConnectivityState(true); $this->assertEquals(0, $state); } public function testGetTarget() { $this->channel = new Grpc\Channel('localhost:8888', ['credentials' => Grpc\ChannelCredentials::createInsecure()]); $target = $this->channel->getTarget(); $this->assertTrue(is_string($target)); } public function testWatchConnectivityState() { $this->channel = new Grpc\Channel('localhost:0', ['credentials' => Grpc\ChannelCredentials::createInsecure()]); $time = new Grpc\Timeval(1000); $state = $this->channel->watchConnectivityState(1, $time); $this->assertTrue($state); unset($time); } public function testClose() { $this->channel = new Grpc\Channel('localhost:0', ['credentials' => Grpc\ChannelCredentials::createInsecure()]); $this->assertNotNull($this->channel); $this->channel->close(); } /** * @expectedException InvalidArgumentException */ public function testInvalidConstructorWithNull() { $this->channel = new Grpc\Channel(); $this->assertNull($this->channel); } /** * @expectedException InvalidArgumentException */ public function testInvalidConstructorWith() { $this->channel = new Grpc\Channel('localhost', 'invalid'); $this->assertNull($this->channel); } /** * @expectedException InvalidArgumentException */ public function testInvalidCredentials() { $this->channel = new Grpc\Channel( 'localhost:0', [ 'credentials' => new Grpc\Timeval(100), ] ); } /** * @expectedException InvalidArgumentException */ public function testInvalidOptionsArray() { $this->channel = new Grpc\Channel( 'localhost:0', [ 'abc' => [], ] ); } /** * @expectedException InvalidArgumentException */ public function testInvalidGetConnectivityStateWithArray() { $this->channel = new Grpc\Channel('localhost:0', ['credentials' => Grpc\ChannelCredentials::createInsecure()]); $this->channel->getConnectivityState([]); } /** * @expectedException InvalidArgumentException */ public function testInvalidWatchConnectivityState() { $this->channel = new Grpc\Channel('localhost:0', ['credentials' => Grpc\ChannelCredentials::createInsecure()]); $this->channel->watchConnectivityState([]); } /** * @expectedException InvalidArgumentException */ public function testInvalidWatchConnectivityState2() { $this->channel = new Grpc\Channel('localhost:0', ['credentials' => Grpc\ChannelCredentials::createInsecure()]); $this->channel->watchConnectivityState(1, 'hi'); } } grpc-1.3.2/src/php/tests/unit_tests/EndToEndTest.php000066400000000000000000000504061310511640000223760ustar00rootroot00000000000000server = new Grpc\Server([]); $this->port = $this->server->addHttp2Port('0.0.0.0:0'); $this->channel = new Grpc\Channel('localhost:'.$this->port, []); $this->server->start(); } public function tearDown() { unset($this->channel); unset($this->server); } public function testSimpleRequestBody() { $deadline = Grpc\Timeval::infFuture(); $status_text = 'xyz'; $call = new Grpc\Call($this->channel, 'dummy_method', $deadline); $event = $call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, ]); $this->assertTrue($event->send_metadata); $this->assertTrue($event->send_close); $event = $this->server->requestCall(); $this->assertSame('dummy_method', $event->method); $server_call = $event->call; $event = $server_call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_STATUS_FROM_SERVER => [ 'metadata' => [], 'code' => Grpc\STATUS_OK, 'details' => $status_text, ], Grpc\OP_RECV_CLOSE_ON_SERVER => true, ]); $this->assertTrue($event->send_metadata); $this->assertTrue($event->send_status); $this->assertFalse($event->cancelled); $event = $call->startBatch([ Grpc\OP_RECV_INITIAL_METADATA => true, Grpc\OP_RECV_STATUS_ON_CLIENT => true, ]); $status = $event->status; $this->assertSame([], $status->metadata); $this->assertSame(Grpc\STATUS_OK, $status->code); $this->assertSame($status_text, $status->details); unset($call); unset($server_call); } public function testMessageWriteFlags() { $deadline = Grpc\Timeval::infFuture(); $req_text = 'message_write_flags_test'; $status_text = 'xyz'; $call = new Grpc\Call($this->channel, 'dummy_method', $deadline); $event = $call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_MESSAGE => ['message' => $req_text, 'flags' => Grpc\WRITE_NO_COMPRESS, ], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, ]); $this->assertTrue($event->send_metadata); $this->assertTrue($event->send_close); $event = $this->server->requestCall(); $this->assertSame('dummy_method', $event->method); $server_call = $event->call; $event = $server_call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_STATUS_FROM_SERVER => [ 'metadata' => [], 'code' => Grpc\STATUS_OK, 'details' => $status_text, ], ]); $event = $call->startBatch([ Grpc\OP_RECV_INITIAL_METADATA => true, Grpc\OP_RECV_STATUS_ON_CLIENT => true, ]); $status = $event->status; $this->assertSame([], $status->metadata); $this->assertSame(Grpc\STATUS_OK, $status->code); $this->assertSame($status_text, $status->details); unset($call); unset($server_call); } public function testClientServerFullRequestResponse() { $deadline = Grpc\Timeval::infFuture(); $req_text = 'client_server_full_request_response'; $reply_text = 'reply:client_server_full_request_response'; $status_text = 'status:client_server_full_response_text'; $call = new Grpc\Call($this->channel, 'dummy_method', $deadline); $event = $call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, Grpc\OP_SEND_MESSAGE => ['message' => $req_text], ]); $this->assertTrue($event->send_metadata); $this->assertTrue($event->send_close); $this->assertTrue($event->send_message); $event = $this->server->requestCall(); $this->assertSame('dummy_method', $event->method); $server_call = $event->call; $event = $server_call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], Grpc\OP_SEND_STATUS_FROM_SERVER => [ 'metadata' => [], 'code' => Grpc\STATUS_OK, 'details' => $status_text, ], Grpc\OP_RECV_MESSAGE => true, Grpc\OP_RECV_CLOSE_ON_SERVER => true, ]); $this->assertTrue($event->send_metadata); $this->assertTrue($event->send_status); $this->assertTrue($event->send_message); $this->assertFalse($event->cancelled); $this->assertSame($req_text, $event->message); $event = $call->startBatch([ Grpc\OP_RECV_INITIAL_METADATA => true, Grpc\OP_RECV_MESSAGE => true, Grpc\OP_RECV_STATUS_ON_CLIENT => true, ]); $this->assertSame([], $event->metadata); $this->assertSame($reply_text, $event->message); $status = $event->status; $this->assertSame([], $status->metadata); $this->assertSame(Grpc\STATUS_OK, $status->code); $this->assertSame($status_text, $status->details); unset($call); unset($server_call); } /** * @expectedException InvalidArgumentException */ public function testInvalidClientMessageArray() { $deadline = Grpc\Timeval::infFuture(); $req_text = 'client_server_full_request_response'; $reply_text = 'reply:client_server_full_request_response'; $status_text = 'status:client_server_full_response_text'; $call = new Grpc\Call($this->channel, 'dummy_method', $deadline); $event = $call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, Grpc\OP_SEND_MESSAGE => 'invalid', ]); } /** * @expectedException InvalidArgumentException */ public function testInvalidClientMessageString() { $deadline = Grpc\Timeval::infFuture(); $req_text = 'client_server_full_request_response'; $reply_text = 'reply:client_server_full_request_response'; $status_text = 'status:client_server_full_response_text'; $call = new Grpc\Call($this->channel, 'dummy_method', $deadline); $event = $call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, Grpc\OP_SEND_MESSAGE => ['message' => 0], ]); } /** * @expectedException InvalidArgumentException */ public function testInvalidClientMessageFlags() { $deadline = Grpc\Timeval::infFuture(); $req_text = 'client_server_full_request_response'; $reply_text = 'reply:client_server_full_request_response'; $status_text = 'status:client_server_full_response_text'; $call = new Grpc\Call($this->channel, 'dummy_method', $deadline); $event = $call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, Grpc\OP_SEND_MESSAGE => ['message' => 'abc', 'flags' => 'invalid', ], ]); } /** * @expectedException InvalidArgumentException */ public function testInvalidServerStatusMetadata() { $deadline = Grpc\Timeval::infFuture(); $req_text = 'client_server_full_request_response'; $reply_text = 'reply:client_server_full_request_response'; $status_text = 'status:client_server_full_response_text'; $call = new Grpc\Call($this->channel, 'dummy_method', $deadline); $event = $call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, Grpc\OP_SEND_MESSAGE => ['message' => $req_text], ]); $this->assertTrue($event->send_metadata); $this->assertTrue($event->send_close); $this->assertTrue($event->send_message); $event = $this->server->requestCall(); $this->assertSame('dummy_method', $event->method); $server_call = $event->call; $event = $server_call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], Grpc\OP_SEND_STATUS_FROM_SERVER => [ 'metadata' => 'invalid', 'code' => Grpc\STATUS_OK, 'details' => $status_text, ], Grpc\OP_RECV_MESSAGE => true, Grpc\OP_RECV_CLOSE_ON_SERVER => true, ]); } /** * @expectedException InvalidArgumentException */ public function testInvalidServerStatusCode() { $deadline = Grpc\Timeval::infFuture(); $req_text = 'client_server_full_request_response'; $reply_text = 'reply:client_server_full_request_response'; $status_text = 'status:client_server_full_response_text'; $call = new Grpc\Call($this->channel, 'dummy_method', $deadline); $event = $call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, Grpc\OP_SEND_MESSAGE => ['message' => $req_text], ]); $this->assertTrue($event->send_metadata); $this->assertTrue($event->send_close); $this->assertTrue($event->send_message); $event = $this->server->requestCall(); $this->assertSame('dummy_method', $event->method); $server_call = $event->call; $event = $server_call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], Grpc\OP_SEND_STATUS_FROM_SERVER => [ 'metadata' => [], 'code' => 'invalid', 'details' => $status_text, ], Grpc\OP_RECV_MESSAGE => true, Grpc\OP_RECV_CLOSE_ON_SERVER => true, ]); } /** * @expectedException InvalidArgumentException */ public function testMissingServerStatusCode() { $deadline = Grpc\Timeval::infFuture(); $req_text = 'client_server_full_request_response'; $reply_text = 'reply:client_server_full_request_response'; $status_text = 'status:client_server_full_response_text'; $call = new Grpc\Call($this->channel, 'dummy_method', $deadline); $event = $call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, Grpc\OP_SEND_MESSAGE => ['message' => $req_text], ]); $this->assertTrue($event->send_metadata); $this->assertTrue($event->send_close); $this->assertTrue($event->send_message); $event = $this->server->requestCall(); $this->assertSame('dummy_method', $event->method); $server_call = $event->call; $event = $server_call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], Grpc\OP_SEND_STATUS_FROM_SERVER => [ 'metadata' => [], 'details' => $status_text, ], Grpc\OP_RECV_MESSAGE => true, Grpc\OP_RECV_CLOSE_ON_SERVER => true, ]); } /** * @expectedException InvalidArgumentException */ public function testInvalidServerStatusDetails() { $deadline = Grpc\Timeval::infFuture(); $req_text = 'client_server_full_request_response'; $reply_text = 'reply:client_server_full_request_response'; $status_text = 'status:client_server_full_response_text'; $call = new Grpc\Call($this->channel, 'dummy_method', $deadline); $event = $call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, Grpc\OP_SEND_MESSAGE => ['message' => $req_text], ]); $this->assertTrue($event->send_metadata); $this->assertTrue($event->send_close); $this->assertTrue($event->send_message); $event = $this->server->requestCall(); $this->assertSame('dummy_method', $event->method); $server_call = $event->call; $event = $server_call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], Grpc\OP_SEND_STATUS_FROM_SERVER => [ 'metadata' => [], 'code' => Grpc\STATUS_OK, 'details' => 0, ], Grpc\OP_RECV_MESSAGE => true, Grpc\OP_RECV_CLOSE_ON_SERVER => true, ]); } /** * @expectedException InvalidArgumentException */ public function testMissingServerStatusDetails() { $deadline = Grpc\Timeval::infFuture(); $req_text = 'client_server_full_request_response'; $reply_text = 'reply:client_server_full_request_response'; $status_text = 'status:client_server_full_response_text'; $call = new Grpc\Call($this->channel, 'dummy_method', $deadline); $event = $call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, Grpc\OP_SEND_MESSAGE => ['message' => $req_text], ]); $this->assertTrue($event->send_metadata); $this->assertTrue($event->send_close); $this->assertTrue($event->send_message); $event = $this->server->requestCall(); $this->assertSame('dummy_method', $event->method); $server_call = $event->call; $event = $server_call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], Grpc\OP_SEND_STATUS_FROM_SERVER => [ 'metadata' => [], 'code' => Grpc\STATUS_OK, ], Grpc\OP_RECV_MESSAGE => true, Grpc\OP_RECV_CLOSE_ON_SERVER => true, ]); } /** * @expectedException InvalidArgumentException */ public function testInvalidStartBatchKey() { $deadline = Grpc\Timeval::infFuture(); $req_text = 'client_server_full_request_response'; $reply_text = 'reply:client_server_full_request_response'; $status_text = 'status:client_server_full_response_text'; $call = new Grpc\Call($this->channel, 'dummy_method', $deadline); $event = $call->startBatch([ 9999999 => [], ]); } /** * @expectedException LogicException */ public function testInvalidStartBatch() { $deadline = Grpc\Timeval::infFuture(); $req_text = 'client_server_full_request_response'; $reply_text = 'reply:client_server_full_request_response'; $status_text = 'status:client_server_full_response_text'; $call = new Grpc\Call($this->channel, 'dummy_method', $deadline); $event = $call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, Grpc\OP_SEND_MESSAGE => ['message' => $req_text], Grpc\OP_SEND_STATUS_FROM_SERVER => [ 'metadata' => [], 'code' => Grpc\STATUS_OK, 'details' => 'abc', ], ]); } public function testGetTarget() { $this->assertTrue(is_string($this->channel->getTarget())); } public function testGetConnectivityState() { $this->assertTrue($this->channel->getConnectivityState() == Grpc\CHANNEL_IDLE); } public function testWatchConnectivityStateFailed() { $idle_state = $this->channel->getConnectivityState(); $this->assertTrue($idle_state == Grpc\CHANNEL_IDLE); $now = Grpc\Timeval::now(); $delta = new Grpc\Timeval(500000); // should timeout $deadline = $now->add($delta); $this->assertFalse($this->channel->watchConnectivityState( $idle_state, $deadline)); } public function testWatchConnectivityStateSuccess() { $idle_state = $this->channel->getConnectivityState(true); $this->assertTrue($idle_state == Grpc\CHANNEL_IDLE); $now = Grpc\Timeval::now(); $delta = new Grpc\Timeval(3000000); // should finish well before $deadline = $now->add($delta); $this->assertTrue($this->channel->watchConnectivityState( $idle_state, $deadline)); $new_state = $this->channel->getConnectivityState(); $this->assertTrue($idle_state != $new_state); } public function testWatchConnectivityStateDoNothing() { $idle_state = $this->channel->getConnectivityState(); $this->assertTrue($idle_state == Grpc\CHANNEL_IDLE); $now = Grpc\Timeval::now(); $delta = new Grpc\Timeval(100000); $deadline = $now->add($delta); $this->assertFalse($this->channel->watchConnectivityState( $idle_state, $deadline)); $new_state = $this->channel->getConnectivityState(); $this->assertTrue($new_state == Grpc\CHANNEL_IDLE); } /** * @expectedException InvalidArgumentException */ public function testGetConnectivityStateInvalidParam() { $this->assertTrue($this->channel->getConnectivityState( new Grpc\Timeval())); } /** * @expectedException InvalidArgumentException */ public function testWatchConnectivityStateInvalidParam() { $this->assertTrue($this->channel->watchConnectivityState( 0, 1000)); } /** * @expectedException InvalidArgumentException */ public function testChannelConstructorInvalidParam() { $this->channel = new Grpc\Channel('localhost:'.$this->port, null); } public function testClose() { $this->assertNull($this->channel->close()); } } grpc-1.3.2/src/php/tests/unit_tests/SecureEndToEndTest.php000066400000000000000000000200651310511640000235430ustar00rootroot00000000000000server = new Grpc\Server(); $this->port = $this->server->addSecureHttp2Port('0.0.0.0:0', $server_credentials); $this->server->start(); $this->host_override = 'foo.test.google.fr'; $this->channel = new Grpc\Channel( 'localhost:'.$this->port, [ 'grpc.ssl_target_name_override' => $this->host_override, 'grpc.default_authority' => $this->host_override, 'credentials' => $credentials, ] ); } public function tearDown() { unset($this->channel); unset($this->server); } public function testSimpleRequestBody() { $deadline = Grpc\Timeval::infFuture(); $status_text = 'xyz'; $call = new Grpc\Call($this->channel, 'dummy_method', $deadline, $this->host_override); $event = $call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, ]); $this->assertTrue($event->send_metadata); $this->assertTrue($event->send_close); $event = $this->server->requestCall(); $this->assertSame('dummy_method', $event->method); $server_call = $event->call; $event = $server_call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_STATUS_FROM_SERVER => [ 'metadata' => [], 'code' => Grpc\STATUS_OK, 'details' => $status_text, ], Grpc\OP_RECV_CLOSE_ON_SERVER => true, ]); $this->assertTrue($event->send_metadata); $this->assertTrue($event->send_status); $this->assertFalse($event->cancelled); $event = $call->startBatch([ Grpc\OP_RECV_INITIAL_METADATA => true, Grpc\OP_RECV_STATUS_ON_CLIENT => true, ]); $this->assertSame([], $event->metadata); $status = $event->status; $this->assertSame([], $status->metadata); $this->assertSame(Grpc\STATUS_OK, $status->code); $this->assertSame($status_text, $status->details); unset($call); unset($server_call); } public function testMessageWriteFlags() { $deadline = Grpc\Timeval::infFuture(); $req_text = 'message_write_flags_test'; $status_text = 'xyz'; $call = new Grpc\Call($this->channel, 'dummy_method', $deadline, $this->host_override); $event = $call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_MESSAGE => ['message' => $req_text, 'flags' => Grpc\WRITE_NO_COMPRESS, ], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, ]); $this->assertTrue($event->send_metadata); $this->assertTrue($event->send_close); $event = $this->server->requestCall(); $this->assertSame('dummy_method', $event->method); $server_call = $event->call; $event = $server_call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_STATUS_FROM_SERVER => [ 'metadata' => [], 'code' => Grpc\STATUS_OK, 'details' => $status_text, ], ]); $event = $call->startBatch([ Grpc\OP_RECV_INITIAL_METADATA => true, Grpc\OP_RECV_STATUS_ON_CLIENT => true, ]); $this->assertSame([], $event->metadata); $status = $event->status; $this->assertSame([], $status->metadata); $this->assertSame(Grpc\STATUS_OK, $status->code); $this->assertSame($status_text, $status->details); unset($call); unset($server_call); } public function testClientServerFullRequestResponse() { $deadline = Grpc\Timeval::infFuture(); $req_text = 'client_server_full_request_response'; $reply_text = 'reply:client_server_full_request_response'; $status_text = 'status:client_server_full_response_text'; $call = new Grpc\Call($this->channel, 'dummy_method', $deadline, $this->host_override); $event = $call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, Grpc\OP_SEND_MESSAGE => ['message' => $req_text], ]); $this->assertTrue($event->send_metadata); $this->assertTrue($event->send_close); $this->assertTrue($event->send_message); $event = $this->server->requestCall(); $this->assertSame('dummy_method', $event->method); $server_call = $event->call; $event = $server_call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], Grpc\OP_SEND_STATUS_FROM_SERVER => [ 'metadata' => [], 'code' => Grpc\STATUS_OK, 'details' => $status_text, ], Grpc\OP_RECV_MESSAGE => true, Grpc\OP_RECV_CLOSE_ON_SERVER => true, ]); $this->assertTrue($event->send_metadata); $this->assertTrue($event->send_status); $this->assertTrue($event->send_message); $this->assertFalse($event->cancelled); $this->assertSame($req_text, $event->message); $event = $call->startBatch([ Grpc\OP_RECV_INITIAL_METADATA => true, Grpc\OP_RECV_MESSAGE => true, Grpc\OP_RECV_STATUS_ON_CLIENT => true, ]); $this->assertSame([], $event->metadata); $this->assertSame($reply_text, $event->message); $status = $event->status; $this->assertSame([], $status->metadata); $this->assertSame(Grpc\STATUS_OK, $status->code); $this->assertSame($status_text, $status->details); unset($call); unset($server_call); } } grpc-1.3.2/src/php/tests/unit_tests/ServerTest.php000066400000000000000000000115351310511640000222040ustar00rootroot00000000000000server = null; } public function tearDown() { unset($this->server); } public function testConstructorWithNull() { $this->server = new Grpc\Server(); $this->assertNotNull($this->server); } public function testConstructorWithNullArray() { $this->server = new Grpc\Server([]); $this->assertNotNull($this->server); } public function testConstructorWithArray() { // key of array must be string $this->server = new Grpc\Server(['ip' => '127.0.0.1', 'port' => '8080', ]); $this->assertNotNull($this->server); } public function testRequestCall() { $this->server = new Grpc\Server(); $port = $this->server->addHttp2Port('0.0.0.0:0'); $this->server->start(); $channel = new Grpc\Channel('localhost:'.$port, ['credentials' => Grpc\ChannelCredentials::createInsecure()]); $deadline = Grpc\Timeval::infFuture(); $call = new Grpc\Call($channel, 'dummy_method', $deadline); $event = $call->startBatch([Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, ]); $c = $this->server->requestCall(); $this->assertObjectHasAttribute('call', $c); $this->assertObjectHasAttribute('method', $c); $this->assertSame('dummy_method', $c->method); $this->assertObjectHasAttribute('host', $c); $this->assertTrue(is_string($c->host)); $this->assertObjectHasAttribute('absolute_deadline', $c); $this->assertObjectHasAttribute('metadata', $c); unset($call); unset($channel); } private function createSslObj() { $server_credentials = Grpc\ServerCredentials::createSsl( null, file_get_contents(dirname(__FILE__).'/../data/server1.key'), file_get_contents(dirname(__FILE__).'/../data/server1.pem')); return $server_credentials; } /** * @expectedException InvalidArgumentException */ public function testInvalidConstructor() { $this->server = new Grpc\Server('invalid_host'); $this->assertNull($this->server); } /** * @expectedException InvalidArgumentException */ public function testInvalidAddHttp2Port() { $this->server = new Grpc\Server([]); $port = $this->server->addHttp2Port(['0.0.0.0:0']); } /** * @expectedException InvalidArgumentException */ public function testInvalidAddSecureHttp2Port() { $this->server = new Grpc\Server([]); $port = $this->server->addSecureHttp2Port(['0.0.0.0:0']); } /** * @expectedException InvalidArgumentException */ public function testInvalidAddSecureHttp2Port2() { $this->server = new Grpc\Server(); $port = $this->server->addSecureHttp2Port('0.0.0.0:0'); } /** * @expectedException InvalidArgumentException */ public function testInvalidAddSecureHttp2Port3() { $this->server = new Grpc\Server(); $port = $this->server->addSecureHttp2Port('0.0.0.0:0', 'invalid'); } } grpc-1.3.2/src/php/tests/unit_tests/TimevalTest.php000066400000000000000000000147521310511640000223430ustar00rootroot00000000000000time); } public function testConstructorWithInt() { $this->time = new Grpc\Timeval(1234); $this->assertNotNull($this->time); $this->assertSame('Grpc\Timeval', get_class($this->time)); } public function testConstructorWithNegative() { $this->time = new Grpc\Timeval(-123); $this->assertNotNull($this->time); $this->assertSame('Grpc\Timeval', get_class($this->time)); } public function testConstructorWithZero() { $this->time = new Grpc\Timeval(0); $this->assertNotNull($this->time); $this->assertSame('Grpc\Timeval', get_class($this->time)); } public function testConstructorWithOct() { $this->time = new Grpc\Timeval(0123); $this->assertNotNull($this->time); $this->assertSame('Grpc\Timeval', get_class($this->time)); } public function testConstructorWithHex() { $this->time = new Grpc\Timeval(0x1A); $this->assertNotNull($this->time); $this->assertSame('Grpc\Timeval', get_class($this->time)); } public function testConstructorWithFloat() { $this->time = new Grpc\Timeval(123.456); $this->assertNotNull($this->time); $this->assertSame('Grpc\Timeval', get_class($this->time)); } public function testCompareSame() { $zero = Grpc\Timeval::zero(); $this->assertSame(0, Grpc\Timeval::compare($zero, $zero)); } public function testPastIsLessThanZero() { $zero = Grpc\Timeval::zero(); $past = Grpc\Timeval::infPast(); $this->assertLessThan(0, Grpc\Timeval::compare($past, $zero)); $this->assertGreaterThan(0, Grpc\Timeval::compare($zero, $past)); } public function testFutureIsGreaterThanZero() { $zero = Grpc\Timeval::zero(); $future = Grpc\Timeval::infFuture(); $this->assertLessThan(0, Grpc\Timeval::compare($zero, $future)); $this->assertGreaterThan(0, Grpc\Timeval::compare($future, $zero)); } /** * @depends testFutureIsGreaterThanZero */ public function testNowIsBetweenZeroAndFuture() { $zero = Grpc\Timeval::zero(); $future = Grpc\Timeval::infFuture(); $now = Grpc\Timeval::now(); $this->assertLessThan(0, Grpc\Timeval::compare($zero, $now)); $this->assertLessThan(0, Grpc\Timeval::compare($now, $future)); } public function testNowAndAdd() { $now = Grpc\Timeval::now(); $this->assertNotNull($now); $delta = new Grpc\Timeval(1000); $deadline = $now->add($delta); $this->assertGreaterThan(0, Grpc\Timeval::compare($deadline, $now)); } public function testNowAndSubtract() { $now = Grpc\Timeval::now(); $delta = new Grpc\Timeval(1000); $deadline = $now->subtract($delta); $this->assertLessThan(0, Grpc\Timeval::compare($deadline, $now)); } public function testAddAndSubtract() { $now = Grpc\Timeval::now(); $delta = new Grpc\Timeval(1000); $deadline = $now->add($delta); $back_to_now = $deadline->subtract($delta); $this->assertSame(0, Grpc\Timeval::compare($back_to_now, $now)); } public function testSimilar() { $a = Grpc\Timeval::now(); $delta = new Grpc\Timeval(1000); $b = $a->add($delta); $thresh = new Grpc\Timeval(1100); $this->assertTrue(Grpc\Timeval::similar($a, $b, $thresh)); $thresh = new Grpc\Timeval(900); $this->assertFalse(Grpc\Timeval::similar($a, $b, $thresh)); } public function testSleepUntil() { $curr_microtime = microtime(true); $now = Grpc\Timeval::now(); $delta = new Grpc\Timeval(1000); $deadline = $now->add($delta); $deadline->sleepUntil(); $done_microtime = microtime(true); $this->assertTrue(($done_microtime - $curr_microtime) > 0.0009); } /** * @expectedException InvalidArgumentException */ public function testConstructorInvalidParam() { $delta = new Grpc\Timeval('abc'); } /** * @expectedException InvalidArgumentException */ public function testAddInvalidParam() { $a = Grpc\Timeval::now(); $a->add(1000); } /** * @expectedException InvalidArgumentException */ public function testSubtractInvalidParam() { $a = Grpc\Timeval::now(); $a->subtract(1000); } /** * @expectedException InvalidArgumentException */ public function testCompareInvalidParam() { $a = Grpc\Timeval::compare(1000, 1100); } /** * @expectedException InvalidArgumentException */ public function testSimilarInvalidParam() { $a = Grpc\Timeval::similar(1000, 1100, 1200); $this->assertNull($delta); } } grpc-1.3.2/src/proto/000077500000000000000000000000001310511640000143715ustar00rootroot00000000000000grpc-1.3.2/src/proto/census/000077500000000000000000000000001310511640000156715ustar00rootroot00000000000000grpc-1.3.2/src/proto/census/census.options000066400000000000000000000001601310511640000206030ustar00rootroot00000000000000google.census.Tag.key max_size:255 google.census.Tag.value max_size:255 google.census.View.tag_key max_count:15 grpc-1.3.2/src/proto/census/census.proto000066400000000000000000000270561310511640000202700ustar00rootroot00000000000000// Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package google.census; // All the census protos. // // Nomenclature note: capitalized names below (like Resource) are protos. // // Census lets you define a Resource - something which can be measured, like the // latency of an RPC, the number of CPU cycles spent on an operation, or // anything else you care to measure. You can record individual instances of // measurements (a double value) for every Resource of interest. These // individual measurements are aggregated together into an Aggregation. There // are two Aggregation types available: Distribution (describes the // distribution of all measurements, possibly with a histogram) and // IntervalStats (the count and mean of measurements across specified time // periods). An Aggregation is described by an AggregationDescriptor. // // You can define how your stats are broken down by Tag values and which // Aggregations to use through a View. The corresponding combination of // Resource/View/Aggregation which is available to census clients is called a // Metric. // The following two types are copied from // google/protobuf/{duration,timestamp}.proto. Ideally, we would be able to // import them, but this causes compilation issues on C-based systems // (e.g. https://koti.kapsi.fi/jpa/nanopb/), which cannot process the C++ // headers generated from the standard protobuf distribution. See the relevant // proto files for full documentation of these types. message Duration { // Signed seconds of the span of time. Must be from -315,576,000,000 // to +315,576,000,000 inclusive. int64 seconds = 1; // Signed fractions of a second at nanosecond resolution of the span // of time. Durations less than one second are represented with a 0 // `seconds` field and a positive or negative `nanos` field. For durations // of one second or more, a non-zero value for the `nanos` field must be // of the same sign as the `seconds` field. Must be from -999,999,999 // to +999,999,999 inclusive. int32 nanos = 2; } message Timestamp { // Represents seconds of UTC time since Unix epoch // 1970-01-01T00:00:00Z. Must be from from 0001-01-01T00:00:00Z to // 9999-12-31T23:59:59Z inclusive. int64 seconds = 1; // Non-negative fractions of a second at nanosecond resolution. Negative // second values with fractions must still have non-negative nanos values // that count forward in time. Must be from 0 to 999,999,999 // inclusive. int32 nanos = 2; } // Describes a Resource. message Resource { // name of resource, e.g. rpc_latency, cpu. Must be unique. string name = 1; // More detailed description of the resource, used in documentation. string description = 2; // Fundamental units of measurement supported by Census // TODO(aveitch): expand this to include other S.I. units? enum BasicUnit { UNKNOWN = 0; BITS = 1; BYTES = 2; SECS = 3; CORES = 4; MAX_UNITS = 5; } // MeasurementUnit lets you build compound units of the form // 10^n * (A * B * ...) / (X * Y * ...), // where the elements in the numerator and denominator are all BasicUnits. A // MeasurementUnit must have at least one BasicUnit in its numerator. // // To specify multiplication in the numerator or denominator, simply specify // multiple numerator or denominator fields. For example: // // - byte-seconds (i.e. bytes * seconds): // numerator: BYTES // numerator: SECS // // - events/sec^2 (i.e. rate of change of events/sec): // numerator: COUNT // denominator: SECS // denominator: SECS // // To specify multiples (in power of 10) of units, specify a non-zero prefix // value, for example: // // - MB/s (i.e. megabytes / s): // prefix: 6 // numerator: BYTES // denominator: SECS // // - nanoseconds // prefix: -9 // numerator: SECS message MeasurementUnit { int32 prefix = 1; repeated BasicUnit numerator = 2; repeated BasicUnit denominator = 3; } // The units in which Resource values are measured. MeasurementUnit unit = 3; } // An Aggregation summarizes a series of individual Resource measurements, an // AggregationDescriptor describes an Aggregation. message AggregationDescriptor { enum AggregationType { // Unspecified. Should not be used. UNKNOWN = 0; // A count of measurements made. COUNT = 1; // A Distribution. DISTRIBUTION = 2; // Counts over fixed time intervals. INTERVAL = 3; } // The type of Aggregation. AggregationType type = 1; // At most one set of options. It is illegal to specifiy an option for // COUNT Aggregations. interval_boundaries must be set for INTERVAL types. // bucket_boundaries are optional for DISTRIBUTION types. oneof options { // Defines histogram bucket boundaries for Distributions. BucketBoundaries bucket_boundaries = 2; // Defines the time windows to record for IntervalStats. IntervalBoundaries interval_boundaries = 3; } // A Distribution may optionally contain a histogram of the values in the // population. The bucket boundaries for that histogram are described by // `bucket_boundaries`. This defines `size(bounds) + 1` (= N) buckets. The // boundaries for bucket index i are: // // [-infinity, bounds[i]) for i == 0 // [bounds[i-1], bounds[i]) for 0 < i < N-2 // [bounds[i-1], +infinity) for i == N-1 // // i.e. an underflow bucket (number 0), zero or more finite buckets (1 // through N - 2, and an overflow bucket (N - 1), with inclusive lower // bounds and exclusive upper bounds. // // There must be at least one element in `bounds`. If `bounds` has only one // element, there are no finite buckets, and that single element is the // common boundary of the overflow and underflow buckets. message BucketBoundaries { // The values must be monotonically increasing. repeated double bounds = 1; } // For Interval stats, describe the size of each window. message IntervalBoundaries { // For each time window, specify a duration in seconds. repeated double window_size = 1; } } // Distribution contains summary statistics for a population of values and, // optionally, a histogram representing the distribution of those values across // a specified set of histogram buckets, as defined in // Aggregation.bucket_options. // // The summary statistics are the count, mean, minimum, and the maximum of the // set of population of values. // // Although it is not forbidden, it is generally a bad idea to include // non-finite values (infinities or NaNs) in the population of values, as this // will render the `mean` field meaningless. message Distribution { // The number of values in the population. Must be non-negative. int64 count = 1; // The arithmetic mean of the values in the population. If `count` is zero // then this field must be zero. double mean = 2; // Describes a range of population values. message Range { // The minimum of the population values. double min = 1; // The maximum of the population values. double max = 2; } // The range of the population values. If `count` is zero, this field will not // be defined. Range range = 3; // A Distribution may optionally contain a histogram of the values in the // population. The histogram is given in `bucket_count` as counts of values // that fall into one of a sequence of non-overlapping buckets, as described // by `AggregationDescriptor.options.bucket_boundaries`. // The sum of the values in `bucket_counts` must equal the value in `count`. // // Bucket counts are given in order under the numbering scheme described // above (the underflow bucket has number 0; the finite buckets, if any, // have numbers 1 through N-2; the overflow bucket has number N-1). // // The size of `bucket_count` must be no greater than N as defined in // `bucket_boundaries`. // // Any suffix of trailing zero bucket_count fields may be omitted. repeated int64 bucket_count = 4; } // Record summary stats over various time windows. message IntervalStats { // Summary statistic over a single time window. message Window { // The window duration. Must be positive. Duration window_size = 1; // The number of measurements in this window. int64 count = 2; // The arithmetic mean of all measurements in the window. double mean = 3; } // Full set of windows for this aggregation. repeated Window window = 1; } // A Tag: key-value pair. message Tag { string key = 1; string value = 2; } // A View specifies an Aggregation and a set of tag keys. The Aggregation will // be broken down by the unique set of matching tag values for each measurement. message View { // Name of view. Must be unique. string name = 1; // More detailed description, for documentation purposes. string description = 2; // Name of Resource to be broken down for this view. string resource_name = 3; // Aggregation type to associate with this View. AggregationDescriptor aggregation = 4; // Tag keys to match with a given Resource measurement. If no keys are // specified, then all stats are recorded. Keys must be unique. repeated string tag_key = 5; } // An Aggregation summarizes a series of individual Resource measurements. message Aggregation { // Name of this aggregation. string name = 1; // More detailed description, for documentation purposes. string description = 2; // The data for this Aggregation. oneof data { uint64 count = 3; Distribution distribution = 4; IntervalStats interval_stats = 5; } // Tags associated with this Aggregation. repeated Tag tag = 6; } // A Metric represents all the Aggregations for a particular view. message Metric { // View associated with this Metric. string view_name = 1; // Aggregations - each will have a unique set of tag values for the tag_keys // associated with the corresponding View. repeated Aggregation aggregation = 2; // Start and end timestamps over which the metric was accumulated. These // values are not relevant/defined for IntervalStats aggregations, which are // always accumulated over a fixed time period. Timestamp start = 3; Timestamp end = 4; } grpc-1.3.2/src/proto/census/trace_context.options000066400000000000000000000000001310511640000221360ustar00rootroot00000000000000grpc-1.3.2/src/proto/census/trace_context.proto000066400000000000000000000037731310511640000216320ustar00rootroot00000000000000// Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package google.trace; // Tracing information that is propagated with RPC's. message TraceContext { // A TraceId uniquely represents a single Trace. It is a 128-bit nonce. // The 128-bit ID is split into 2 64-bit chunks. (REQUIRED) fixed64 trace_id_hi = 1; fixed64 trace_id_lo = 2; // ID of parent (client) span. (REQUIRED) fixed64 span_id = 3; // Span option flags. First bit is true if this trace is sampled. (OPTIONAL) fixed32 span_options = 4; } grpc-1.3.2/src/proto/gen_build_yaml.py000077500000000000000000000063731310511640000177310ustar00rootroot00000000000000#!/usr/bin/env python2.7 # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Generates the appropriate build.json data for all the proto files.""" import yaml import collections import os import re import sys def update_deps(key, proto_filename, deps, deps_external, is_trans, visited): if not proto_filename in visited: visited.append(proto_filename) with open(proto_filename) as inp: for line in inp: imp = re.search(r'import "([^"]*)"', line) if not imp: continue imp_proto = imp.group(1) # This indicates an external dependency, which we should handle # differently and not traverse recursively if imp_proto.startswith('google/'): if key not in deps_external: deps_external[key] = [] deps_external[key].append(imp_proto[:-6]) continue if key not in deps: deps[key] = [] deps[key].append(imp_proto[:-6]) if is_trans: update_deps(key, imp_proto, deps, deps_external, is_trans, visited) def main(): proto_dir = os.path.abspath(os.path.dirname(sys.argv[0])) os.chdir(os.path.join(proto_dir, '../..')) deps = {} deps_trans = {} deps_external = {} deps_external_trans = {} for root, dirs, files in os.walk('src/proto'): for f in files: if f[-6:] != '.proto': continue look_at = os.path.join(root, f) deps_for = look_at[:-6] # First level deps update_deps(deps_for, look_at, deps, deps_external, False, []) # Transitive deps update_deps(deps_for, look_at, deps_trans, deps_external_trans, True, []) json = { 'proto_deps': deps, 'proto_transitive_deps': deps_trans, 'proto_external_deps': deps_external, 'proto_transitive_external_deps': deps_external_trans } print yaml.dump(json) if __name__ == '__main__': main() grpc-1.3.2/src/proto/grpc/000077500000000000000000000000001310511640000153245ustar00rootroot00000000000000grpc-1.3.2/src/proto/grpc/binary_log/000077500000000000000000000000001310511640000174515ustar00rootroot00000000000000grpc-1.3.2/src/proto/grpc/binary_log/v1alpha/000077500000000000000000000000001310511640000210055ustar00rootroot00000000000000grpc-1.3.2/src/proto/grpc/binary_log/v1alpha/log.proto000066400000000000000000000072341310511640000226610ustar00rootroot00000000000000// Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; import "google/protobuf/timestamp.proto"; package grpc.binary_log.v1alpha; enum Direction { SERVER_SEND = 0; SERVER_RECV = 1; CLIENT_SEND = 2; CLIENT_RECV = 3; } message KeyValuePair { string key = 1; string value = 2; } // Any sort of metadata that may be sent in either direction during a call message Metadata { // Cryptographically unique identifier, generated on the client and sent // to the server. uint64 rpc_id = 1; // Timestamp of logging the metadata google.protobuf.Timestamp timestamp = 2; Direction direction = 3; // The actual metadata that is being sent repeated KeyValuePair metadata = 4; // Initial metadata sent by the client to initiate a request message ClientInitialMetadata { // The full method name that is being called string method_name = 1; // The call's deadline google.protobuf.Timestamp deadline = 2; // The address of the connected peer string peer = 3; } // Arbitrary key/value pairs specified by the user that are not sent over // the network but are nonetheless useful to log message UserData { } // Initial metadata response sent by the server after accepting the request message ServerInitialMetadata { } // Status sent by the server when closing the call on the server side message ServerStatus { // The status code uint32 code = 1; // The status details string details = 2; } oneof kind { ClientInitialMetadata client_initial_metadata = 5; UserData user_data = 6; ServerInitialMetadata server_initial_metadata = 7; ServerStatus server_status = 8; } } // A message that is sent during a call message Message { // Cryptographically unique identifier, generated on the client and sent // to the server. uint64 rpc_id = 1; // The sequence number of the message. Messages sent by the client and by the // server should have independently incrementing sequence numbers. uint32 sequence_number = 2; Direction direction = 3; // The length of the complete message. uint32 length = 4; // The contents of the message. May be a prefix instead of the complete // message. bytes data = 5; } grpc-1.3.2/src/proto/grpc/health/000077500000000000000000000000001310511640000165715ustar00rootroot00000000000000grpc-1.3.2/src/proto/grpc/health/v1/000077500000000000000000000000001310511640000171175ustar00rootroot00000000000000grpc-1.3.2/src/proto/grpc/health/v1/health.options000066400000000000000000000000671310511640000220040ustar00rootroot00000000000000grpc.health.v1.HealthCheckRequest.service max_size:200 grpc-1.3.2/src/proto/grpc/health/v1/health.proto000066400000000000000000000036051310511640000214550ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package grpc.health.v1; option csharp_namespace = "Grpc.Health.V1"; message HealthCheckRequest { string service = 1; } message HealthCheckResponse { enum ServingStatus { UNKNOWN = 0; SERVING = 1; NOT_SERVING = 2; } ServingStatus status = 1; } service Health { rpc Check(HealthCheckRequest) returns (HealthCheckResponse); } grpc-1.3.2/src/proto/grpc/lb/000077500000000000000000000000001310511640000157215ustar00rootroot00000000000000grpc-1.3.2/src/proto/grpc/lb/v1/000077500000000000000000000000001310511640000162475ustar00rootroot00000000000000grpc-1.3.2/src/proto/grpc/lb/v1/load_balancer.options000066400000000000000000000003751310511640000224370ustar00rootroot00000000000000grpc.lb.v1.InitialLoadBalanceRequest.name max_size:128 grpc.lb.v1.InitialLoadBalanceResponse.load_balancer_delegate max_size:64 grpc.lb.v1.Server.ip_address max_size:16 grpc.lb.v1.Server.load_balance_token max_size:50 load_balancer.proto no_unions:true grpc-1.3.2/src/proto/grpc/lb/v1/load_balancer.proto000066400000000000000000000132311310511640000221020ustar00rootroot00000000000000// Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package grpc.lb.v1; message Duration { // Signed seconds of the span of time. Must be from -315,576,000,000 // to +315,576,000,000 inclusive. int64 seconds = 1; // Signed fractions of a second at nanosecond resolution of the span // of time. Durations less than one second are represented with a 0 // `seconds` field and a positive or negative `nanos` field. For durations // of one second or more, a non-zero value for the `nanos` field must be // of the same sign as the `seconds` field. Must be from -999,999,999 // to +999,999,999 inclusive. int32 nanos = 2; } service LoadBalancer { // Bidirectional rpc to get a list of servers. rpc BalanceLoad(stream LoadBalanceRequest) returns (stream LoadBalanceResponse); } message LoadBalanceRequest { oneof load_balance_request_type { // This message should be sent on the first request to the load balancer. InitialLoadBalanceRequest initial_request = 1; // The client stats should be periodically reported to the load balancer // based on the duration defined in the InitialLoadBalanceResponse. ClientStats client_stats = 2; } } message InitialLoadBalanceRequest { // Name of load balanced service (IE, service.grpc.gslb.google.com). Its // length should be less than 256 bytes. string name = 1; } // Contains client level statistics that are useful to load balancing. Each // count should be reset to zero after reporting the stats. message ClientStats { // The total number of requests sent by the client since the last report. int64 total_requests = 1; // The number of client rpc errors since the last report. int64 client_rpc_errors = 2; // The number of dropped requests since the last report. int64 dropped_requests = 3; } message LoadBalanceResponse { oneof load_balance_response_type { // This message should be sent on the first response to the client. InitialLoadBalanceResponse initial_response = 1; // Contains the list of servers selected by the load balancer. The client // should send requests to these servers in the specified order. ServerList server_list = 2; } } message InitialLoadBalanceResponse { // This is an application layer redirect that indicates the client should use // the specified server for load balancing. When this field is non-empty in // the response, the client should open a separate connection to the // load_balancer_delegate and call the BalanceLoad method. Its length should // be less than 64 bytes. string load_balancer_delegate = 1; // This interval defines how often the client should send the client stats // to the load balancer. Stats should only be reported when the duration is // positive. Duration client_stats_report_interval = 2; } message ServerList { // Contains a list of servers selected by the load balancer. The list will // be updated when server resolutions change or as needed to balance load // across more servers. The client should consume the server list in order // unless instructed otherwise via the client_config. repeated Server servers = 1; // Indicates the amount of time that the client should consider this server // list as valid. It may be considered stale after waiting this interval of // time after receiving the list. If the interval is not positive, the // client can assume the list is valid until the next list is received. Duration expiration_interval = 3; } message Server { // A resolved address for the server, serialized in network-byte-order. It may // either be an IPv4 or IPv6 address. bytes ip_address = 1; // A resolved port number for the server. int32 port = 2; // An opaque but printable token given to the frontend for each pick. All // frontend requests for that pick must include the token in its initial // metadata. The token is used by the backend to verify the request and to // allow the backend to report load to the gRPC LB system. // // Its length is variable but less than 50 bytes. string load_balance_token = 3; // Indicates whether this particular request should be dropped by the client // when this server is chosen from the list. bool drop_request = 4; } grpc-1.3.2/src/proto/grpc/reflection/000077500000000000000000000000001310511640000174565ustar00rootroot00000000000000grpc-1.3.2/src/proto/grpc/reflection/v1alpha/000077500000000000000000000000001310511640000210125ustar00rootroot00000000000000grpc-1.3.2/src/proto/grpc/reflection/v1alpha/BUILD000066400000000000000000000033511310511640000215760ustar00rootroot00000000000000# Copyright 2017, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. licenses(["notice"]) # 3-clause BSD package(default_visibility = ["//visibility:public"]) load("//bazel:grpc_build_system.bzl", "grpc_proto_library") grpc_proto_library( name = "reflection_proto", srcs = ["reflection.proto"], ) grpc-1.3.2/src/proto/grpc/reflection/v1alpha/reflection.proto000066400000000000000000000144101310511640000242310ustar00rootroot00000000000000// Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Service exported by server reflection syntax = "proto3"; package grpc.reflection.v1alpha; service ServerReflection { // The reflection service is structured as a bidirectional stream, ensuring // all related requests go to a single server. rpc ServerReflectionInfo(stream ServerReflectionRequest) returns (stream ServerReflectionResponse); } // The message sent by the client when calling ServerReflectionInfo method. message ServerReflectionRequest { string host = 1; // To use reflection service, the client should set one of the following // fields in message_request. The server distinguishes requests by their // defined field and then handles them using corresponding methods. oneof message_request { // Find a proto file by the file name. string file_by_filename = 3; // Find the proto file that declares the given fully-qualified symbol name. // This field should be a fully-qualified symbol name // (e.g. .[.] or .). string file_containing_symbol = 4; // Find the proto file which defines an extension extending the given // message type with the given field number. ExtensionRequest file_containing_extension = 5; // Finds the tag numbers used by all known extensions of the given message // type, and appends them to ExtensionNumberResponse in an undefined order. // Its corresponding method is best-effort: it's not guaranteed that the // reflection service will implement this method, and it's not guaranteed // that this method will provide all extensions. Returns // StatusCode::UNIMPLEMENTED if it's not implemented. // This field should be a fully-qualified type name. The format is // . string all_extension_numbers_of_type = 6; // List the full names of registered services. The content will not be // checked. string list_services = 7; } } // The type name and extension number sent by the client when requesting // file_containing_extension. message ExtensionRequest { // Fully-qualified type name. The format should be . string containing_type = 1; int32 extension_number = 2; } // The message sent by the server to answer ServerReflectionInfo method. message ServerReflectionResponse { string valid_host = 1; ServerReflectionRequest original_request = 2; // The server set one of the following fields accroding to the message_request // in the request. oneof message_response { // This message is used to answer file_by_filename, file_containing_symbol, // file_containing_extension requests with transitive dependencies. As // the repeated label is not allowed in oneof fields, we use a // FileDescriptorResponse message to encapsulate the repeated fields. // The reflection service is allowed to avoid sending FileDescriptorProtos // that were previously sent in response to earlier requests in the stream. FileDescriptorResponse file_descriptor_response = 4; // This message is used to answer all_extension_numbers_of_type requst. ExtensionNumberResponse all_extension_numbers_response = 5; // This message is used to answer list_services request. ListServiceResponse list_services_response = 6; // This message is used when an error occurs. ErrorResponse error_response = 7; } } // Serialized FileDescriptorProto messages sent by the server answering // a file_by_filename, file_containing_symbol, or file_containing_extension // request. message FileDescriptorResponse { // Serialized FileDescriptorProto messages. We avoid taking a dependency on // descriptor.proto, which uses proto2 only features, by making them opaque // bytes instead. repeated bytes file_descriptor_proto = 1; } // A list of extension numbers sent by the server answering // all_extension_numbers_of_type request. message ExtensionNumberResponse { // Full name of the base type, including the package name. The format // is . string base_type_name = 1; repeated int32 extension_number = 2; } // A list of ServiceResponse sent by the server answering list_services request. message ListServiceResponse { // The information of each service may be expanded in the future, so we use // ServiceResponse message to encapsulate it. repeated ServiceResponse service = 1; } // The information of a single service used by ListServiceResponse to answer // list_services request. message ServiceResponse { // Full name of a registered service, including its package name. The format // is . string name = 1; } // The error code and error message sent by the server when an error occurs. message ErrorResponse { // This field uses the error codes defined in grpc::StatusCode. int32 error_code = 1; string error_message = 2; } grpc-1.3.2/src/proto/grpc/status/000077500000000000000000000000001310511640000166475ustar00rootroot00000000000000grpc-1.3.2/src/proto/grpc/status/BUILD000066400000000000000000000035001310511640000174270ustar00rootroot00000000000000# Copyright 2017, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. licenses(["notice"]) # 3-clause BSD package(default_visibility = ["//visibility:public"]) load("//bazel:grpc_build_system.bzl", "grpc_proto_library") grpc_proto_library( name = "status_proto", srcs = ["status.proto"], has_services = False, well_known_protos = "@submodule_protobuf//:well_known_protos", ) grpc-1.3.2/src/proto/grpc/status/README000066400000000000000000000001631310511640000175270ustar00rootroot00000000000000The status.proto file is copied from https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto. grpc-1.3.2/src/proto/grpc/status/status.proto000066400000000000000000000077351310511640000212730ustar00rootroot00000000000000// Copyright 2016 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. syntax = "proto3"; package google.rpc; import "google/protobuf/any.proto"; option go_package = "google.golang.org/genproto/googleapis/rpc/status;status"; option java_multiple_files = true; option java_outer_classname = "StatusProto"; option java_package = "com.google.rpc"; option objc_class_prefix = "RPC"; // The `Status` type defines a logical error model that is suitable for different // programming environments, including REST APIs and RPC APIs. It is used by // [gRPC](https://github.com/grpc). The error model is designed to be: // // - Simple to use and understand for most users // - Flexible enough to meet unexpected needs // // # Overview // // The `Status` message contains three pieces of data: error code, error message, // and error details. The error code should be an enum value of // [google.rpc.Code][google.rpc.Code], but it may accept additional error codes if needed. The // error message should be a developer-facing English message that helps // developers *understand* and *resolve* the error. If a localized user-facing // error message is needed, put the localized message in the error details or // localize it in the client. The optional error details may contain arbitrary // information about the error. There is a predefined set of error detail types // in the package `google.rpc` which can be used for common error conditions. // // # Language mapping // // The `Status` message is the logical representation of the error model, but it // is not necessarily the actual wire format. When the `Status` message is // exposed in different client libraries and different wire protocols, it can be // mapped differently. For example, it will likely be mapped to some exceptions // in Java, but more likely mapped to some error codes in C. // // # Other uses // // The error model and the `Status` message can be used in a variety of // environments, either with or without APIs, to provide a // consistent developer experience across different environments. // // Example uses of this error model include: // // - Partial errors. If a service needs to return partial errors to the client, // it may embed the `Status` in the normal response to indicate the partial // errors. // // - Workflow errors. A typical workflow has multiple steps. Each step may // have a `Status` message for error reporting purpose. // // - Batch operations. If a client uses batch request and batch response, the // `Status` message should be used directly inside batch response, one for // each error sub-response. // // - Asynchronous operations. If an API call embeds asynchronous operation // results in its response, the status of those operations should be // represented directly using the `Status` message. // // - Logging. If some API errors are stored in logs, the message `Status` could // be used directly after any stripping needed for security/privacy reasons. message Status { // The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. int32 code = 1; // A developer-facing error message, which should be in English. Any // user-facing error message should be localized and sent in the // [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client. string message = 2; // A list of messages that carry the error details. There will be a // common set of message types for APIs to use. repeated google.protobuf.Any details = 3; } grpc-1.3.2/src/proto/grpc/testing/000077500000000000000000000000001310511640000170015ustar00rootroot00000000000000grpc-1.3.2/src/proto/grpc/testing/BUILD000066400000000000000000000056211310511640000175670ustar00rootroot00000000000000# Copyright 2017, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. licenses(["notice"]) # 3-clause BSD package(default_visibility = ["//visibility:public"]) load("//bazel:grpc_build_system.bzl", "grpc_proto_library") grpc_proto_library( name = "compiler_test_proto", srcs = ["compiler_test.proto"], ) grpc_proto_library( name = "control_proto", srcs = ["control.proto"], deps = ["payloads_proto", "stats_proto"], has_services = False, ) grpc_proto_library( name = "echo_messages_proto", srcs = ["echo_messages.proto"], has_services = False, ) grpc_proto_library( name = "echo_proto", srcs = ["echo.proto"], deps = ["echo_messages_proto"], ) grpc_proto_library( name = "empty_proto", srcs = ["empty.proto"], has_services = False, ) grpc_proto_library( name = "messages_proto", srcs = ["messages.proto"], has_services = False, ) grpc_proto_library( name = "metrics_proto", srcs = ["metrics.proto"], ) grpc_proto_library( name = "payloads_proto", srcs = ["payloads.proto"], has_services = False, ) grpc_proto_library( name = "services_proto", srcs = ["services.proto"], deps = [ "control_proto", "messages_proto", "stats_proto", ], ) grpc_proto_library( name = "stats_proto", srcs = ["stats.proto"], has_services = False, ) grpc_proto_library( name = "test_proto", srcs = ["test.proto"], deps = ["empty_proto", "messages_proto"], ) grpc-1.3.2/src/proto/grpc/testing/compiler_test.proto000066400000000000000000000047171310511640000227500ustar00rootroot00000000000000// Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // File detached comment 1 // File detached comment 2 // File leading comment 1 syntax = "proto3"; // Ignored detached comment // Ignored package leading comment package grpc.testing; message Request { } message Response { } // ServiceA detached comment 1 // ServiceA detached comment 2 // ServiceA leading comment 1 service ServiceA { // MethodA1 leading comment 1 rpc MethodA1(Request) returns (Response); // MethodA1 trailing comment 1 // MethodA2 detached leading comment 1 // Method A2 leading comment 1 // Method A2 leading comment 2 rpc MethodA2(stream Request) returns (Response); // MethodA2 trailing comment 1 } // Ignored ServiceA trailing comment 1 // ServiceB leading comment 1 service ServiceB { // ServiceB trailing comment 1 // MethodB1 leading comment 1 rpc MethodB1(Request) returns (Response); // MethodB1 trailing comment 1 } // Ignored ServiceB trailing comment 2 // Ignored file trailing comment grpc-1.3.2/src/proto/grpc/testing/control.proto000066400000000000000000000202061310511640000215460ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; import "src/proto/grpc/testing/payloads.proto"; import "src/proto/grpc/testing/stats.proto"; package grpc.testing; enum ClientType { // Many languages support a basic distinction between using // sync or async client, and this allows the specification SYNC_CLIENT = 0; ASYNC_CLIENT = 1; OTHER_CLIENT = 2; // used for some language-specific variants } enum ServerType { SYNC_SERVER = 0; ASYNC_SERVER = 1; ASYNC_GENERIC_SERVER = 2; OTHER_SERVER = 3; // used for some language-specific variants } enum RpcType { UNARY = 0; STREAMING = 1; } // Parameters of poisson process distribution, which is a good representation // of activity coming in from independent identical stationary sources. message PoissonParams { // The rate of arrivals (a.k.a. lambda parameter of the exp distribution). double offered_load = 1; } // Once an RPC finishes, immediately start a new one. // No configuration parameters needed. message ClosedLoopParams {} message LoadParams { oneof load { ClosedLoopParams closed_loop = 1; PoissonParams poisson = 2; }; } // presence of SecurityParams implies use of TLS message SecurityParams { bool use_test_ca = 1; string server_host_override = 2; } message ChannelArg { string name = 1; oneof value { string str_value = 2; int32 int_value = 3; } } message ClientConfig { // List of targets to connect to. At least one target needs to be specified. repeated string server_targets = 1; ClientType client_type = 2; SecurityParams security_params = 3; // How many concurrent RPCs to start for each channel. // For synchronous client, use a separate thread for each outstanding RPC. int32 outstanding_rpcs_per_channel = 4; // Number of independent client channels to create. // i-th channel will connect to server_target[i % server_targets.size()] int32 client_channels = 5; // Only for async client. Number of threads to use to start/manage RPCs. int32 async_client_threads = 7; RpcType rpc_type = 8; // The requested load for the entire client (aggregated over all the threads). LoadParams load_params = 10; PayloadConfig payload_config = 11; HistogramParams histogram_params = 12; // Specify the cores we should run the client on, if desired repeated int32 core_list = 13; int32 core_limit = 14; // If we use an OTHER_CLIENT client_type, this string gives more detail string other_client_api = 15; repeated ChannelArg channel_args = 16; // Number of messages on a stream before it gets finished/restarted int32 messages_per_stream = 18; } message ClientStatus { ClientStats stats = 1; } // Request current stats message Mark { // if true, the stats will be reset after taking their snapshot. bool reset = 1; } message ClientArgs { oneof argtype { ClientConfig setup = 1; Mark mark = 2; } } message ServerConfig { ServerType server_type = 1; SecurityParams security_params = 2; // Port on which to listen. Zero means pick unused port. int32 port = 4; // Only for async server. Number of threads used to serve the requests. int32 async_server_threads = 7; // Specify the number of cores to limit server to, if desired int32 core_limit = 8; // payload config, used in generic server. // Note this must NOT be used in proto (non-generic) servers. For proto servers, // 'response sizes' must be configured from the 'response_size' field of the // 'SimpleRequest' objects in RPC requests. PayloadConfig payload_config = 9; // Specify the cores we should run the server on, if desired repeated int32 core_list = 10; // If we use an OTHER_SERVER client_type, this string gives more detail string other_server_api = 11; // c++-only options (for now) -------------------------------- // Buffer pool size (no buffer pool specified if unset) int32 resource_quota_size = 1001; } message ServerArgs { oneof argtype { ServerConfig setup = 1; Mark mark = 2; } } message ServerStatus { ServerStats stats = 1; // the port bound by the server int32 port = 2; // Number of cores available to the server int32 cores = 3; } message CoreRequest { } message CoreResponse { // Number of cores available on the server int32 cores = 1; } message Void { } // A single performance scenario: input to qps_json_driver message Scenario { // Human readable name for this scenario string name = 1; // Client configuration ClientConfig client_config = 2; // Number of clients to start for the test int32 num_clients = 3; // Server configuration ServerConfig server_config = 4; // Number of servers to start for the test int32 num_servers = 5; // Warmup period, in seconds int32 warmup_seconds = 6; // Benchmark time, in seconds int32 benchmark_seconds = 7; // Number of workers to spawn locally (usually zero) int32 spawn_local_worker_count = 8; } // A set of scenarios to be run with qps_json_driver message Scenarios { repeated Scenario scenarios = 1; } // Basic summary that can be computed from ClientStats and ServerStats // once the scenario has finished. message ScenarioResultSummary { // Total number of operations per second over all clients. double qps = 1; // QPS per one server core. double qps_per_server_core = 2; // server load based on system_time (0.85 => 85%) double server_system_time = 3; // server load based on user_time (0.85 => 85%) double server_user_time = 4; // client load based on system_time (0.85 => 85%) double client_system_time = 5; // client load based on user_time (0.85 => 85%) double client_user_time = 6; // X% latency percentiles (in nanoseconds) double latency_50 = 7; double latency_90 = 8; double latency_95 = 9; double latency_99 = 10; double latency_999 = 11; // server cpu usage percentage double server_cpu_usage = 12; // Number of requests that succeeded/failed double successful_requests_per_second = 13; double failed_requests_per_second = 14; } // Results of a single benchmark scenario. message ScenarioResult { // Inputs used to run the scenario. Scenario scenario = 1; // Histograms from all clients merged into one histogram. HistogramData latencies = 2; // Client stats for each client repeated ClientStats client_stats = 3; // Server stats for each server repeated ServerStats server_stats = 4; // Number of cores available to each server repeated int32 server_cores = 5; // An after-the-fact computed summary ScenarioResultSummary summary = 6; // Information on success or failure of each worker repeated bool client_success = 7; repeated bool server_success = 8; // Number of failed requests (one row per status code seen) repeated RequestResultCount request_results = 9; } grpc-1.3.2/src/proto/grpc/testing/duplicate/000077500000000000000000000000001310511640000207535ustar00rootroot00000000000000grpc-1.3.2/src/proto/grpc/testing/duplicate/BUILD000066400000000000000000000034561310511640000215450ustar00rootroot00000000000000# Copyright 2017, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. licenses(["notice"]) # 3-clause BSD package(default_visibility = ["//visibility:public"]) load("//bazel:grpc_build_system.bzl", "grpc_proto_library") grpc_proto_library( name = "echo_duplicate_proto", srcs = ["echo_duplicate.proto"], deps = ["//src/proto/grpc/testing:echo_messages_proto"], ) grpc-1.3.2/src/proto/grpc/testing/duplicate/echo_duplicate.proto000066400000000000000000000035601310511640000250140ustar00rootroot00000000000000 // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // This is a partial copy of echo.proto with a different package name. syntax = "proto3"; import "src/proto/grpc/testing/echo_messages.proto"; package grpc.testing.duplicate; service EchoTestService { rpc Echo(grpc.testing.EchoRequest) returns (grpc.testing.EchoResponse); rpc ResponseStream(EchoRequest) returns (stream EchoResponse); } grpc-1.3.2/src/proto/grpc/testing/echo.proto000066400000000000000000000041611310511640000210060ustar00rootroot00000000000000 // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; import "src/proto/grpc/testing/echo_messages.proto"; package grpc.testing; service EchoTestService { rpc Echo(EchoRequest) returns (EchoResponse); rpc RequestStream(stream EchoRequest) returns (EchoResponse); rpc ResponseStream(EchoRequest) returns (stream EchoResponse); rpc BidiStream(stream EchoRequest) returns (stream EchoResponse); rpc Unimplemented(EchoRequest) returns (EchoResponse); } service UnimplementedEchoService { rpc Unimplemented(EchoRequest) returns (EchoResponse); } // A service without any rpc defined to test coverage. service NoRpcService { } grpc-1.3.2/src/proto/grpc/testing/echo_messages.proto000066400000000000000000000052051310511640000226750ustar00rootroot00000000000000 // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package grpc.testing; // Message to be echoed back serialized in trailer. message DebugInfo { repeated string stack_entries = 1; string detail = 2; } // Error status client expects to see. message ErrorStatus { int32 code = 1; string error_message = 2; string binary_error_details = 3; } message RequestParams { bool echo_deadline = 1; int32 client_cancel_after_us = 2; int32 server_cancel_after_us = 3; bool echo_metadata = 4; bool check_auth_context = 5; int32 response_message_length = 6; bool echo_peer = 7; string expected_client_identity = 8; // will force check_auth_context. bool skip_cancelled_check = 9; string expected_transport_security_type = 10; DebugInfo debug_info = 11; bool server_die = 12; // Server should not see a request with this set. string binary_error_details = 13; ErrorStatus expected_error = 14; } message EchoRequest { string message = 1; RequestParams param = 2; } message ResponseParams { int64 request_deadline = 1; string host = 2; string peer = 3; } message EchoResponse { string message = 1; ResponseParams param = 2; } grpc-1.3.2/src/proto/grpc/testing/empty.proto000066400000000000000000000036031310511640000212260ustar00rootroot00000000000000 // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package grpc.testing; // An empty message that you can re-use to avoid defining duplicated empty // messages in your project. A typical example is to use it as argument or the // return value of a service API. For instance: // // service Foo { // rpc Bar (grpc.testing.Empty) returns (grpc.testing.Empty) { }; // }; // message Empty {} grpc-1.3.2/src/proto/grpc/testing/messages.proto000066400000000000000000000144051310511640000217010ustar00rootroot00000000000000 // Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Message definitions to be used by integration test service definitions. syntax = "proto3"; package grpc.testing; // TODO(dgq): Go back to using well-known types once // https://github.com/grpc/grpc/issues/6980 has been fixed. // import "google/protobuf/wrappers.proto"; message BoolValue { // The bool value. bool value = 1; } // DEPRECATED, don't use. To be removed shortly. // The type of payload that should be returned. enum PayloadType { // Compressable text format. COMPRESSABLE = 0; } // A block of data, to simply increase gRPC message size. message Payload { // DEPRECATED, don't use. To be removed shortly. // The type of data in body. PayloadType type = 1; // Primary contents of payload. bytes body = 2; } // A protobuf representation for grpc status. This is used by test // clients to specify a status that the server should attempt to return. message EchoStatus { int32 code = 1; string message = 2; } // Unary request. message SimpleRequest { // DEPRECATED, don't use. To be removed shortly. // Desired payload type in the response from the server. // If response_type is RANDOM, server randomly chooses one from other formats. PayloadType response_type = 1; // Desired payload size in the response from the server. int32 response_size = 2; // Optional input payload sent along with the request. Payload payload = 3; // Whether SimpleResponse should include username. bool fill_username = 4; // Whether SimpleResponse should include OAuth scope. bool fill_oauth_scope = 5; // Whether to request the server to compress the response. This field is // "nullable" in order to interoperate seamlessly with clients not able to // implement the full compression tests by introspecting the call to verify // the response's compression status. BoolValue response_compressed = 6; // Whether server should return a given status EchoStatus response_status = 7; // Whether the server should expect this request to be compressed. BoolValue expect_compressed = 8; } // Unary response, as configured by the request. message SimpleResponse { // Payload to increase message size. Payload payload = 1; // The user the request came from, for verifying authentication was // successful when the client expected it. string username = 2; // OAuth scope. string oauth_scope = 3; } // Client-streaming request. message StreamingInputCallRequest { // Optional input payload sent along with the request. Payload payload = 1; // Whether the server should expect this request to be compressed. This field // is "nullable" in order to interoperate seamlessly with servers not able to // implement the full compression tests by introspecting the call to verify // the request's compression status. BoolValue expect_compressed = 2; // Not expecting any payload from the response. } // Client-streaming response. message StreamingInputCallResponse { // Aggregated size of payloads received from the client. int32 aggregated_payload_size = 1; } // Configuration for a particular response. message ResponseParameters { // Desired payload sizes in responses from the server. int32 size = 1; // Desired interval between consecutive responses in the response stream in // microseconds. int32 interval_us = 2; // Whether to request the server to compress the response. This field is // "nullable" in order to interoperate seamlessly with clients not able to // implement the full compression tests by introspecting the call to verify // the response's compression status. BoolValue compressed = 3; } // Server-streaming request. message StreamingOutputCallRequest { // DEPRECATED, don't use. To be removed shortly. // Desired payload type in the response from the server. // If response_type is RANDOM, the payload from each response in the stream // might be of different types. This is to simulate a mixed type of payload // stream. PayloadType response_type = 1; // Configuration for each expected response message. repeated ResponseParameters response_parameters = 2; // Optional input payload sent along with the request. Payload payload = 3; // Whether server should return a given status EchoStatus response_status = 7; } // Server-streaming response, as configured by the request and parameters. message StreamingOutputCallResponse { // Payload to increase response size. Payload payload = 1; } // For reconnect interop test only. // Client tells server what reconnection parameters it used. message ReconnectParams { int32 max_reconnect_backoff_ms = 1; } // For reconnect interop test only. // Server tells client whether its reconnects are following the spec and the // reconnect backoffs it saw. message ReconnectInfo { bool passed = 1; repeated int32 backoff_ms = 2; } grpc-1.3.2/src/proto/grpc/testing/metrics.proto000066400000000000000000000046511310511640000215420ustar00rootroot00000000000000// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Contains the definitions for a metrics service and the type of metrics // exposed by the service. // // Currently, 'Gauge' (i.e a metric that represents the measured value of // something at an instant of time) is the only metric type supported by the // service. syntax = "proto3"; package grpc.testing; // Reponse message containing the gauge name and value message GaugeResponse { string name = 1; oneof value { int64 long_value = 2; double double_value = 3; string string_value = 4; } } // Request message containing the gauge name message GaugeRequest { string name = 1; } message EmptyMessage {} service MetricsService { // Returns the values of all the gauges that are currently being maintained by // the service rpc GetAllGauges(EmptyMessage) returns (stream GaugeResponse); // Returns the value of one gauge rpc GetGauge(GaugeRequest) returns (GaugeResponse); } grpc-1.3.2/src/proto/grpc/testing/payloads.proto000066400000000000000000000040241310511640000217020ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package grpc.testing; message ByteBufferParams { int32 req_size = 1; int32 resp_size = 2; } message SimpleProtoParams { int32 req_size = 1; int32 resp_size = 2; } message ComplexProtoParams { // TODO (vpai): Fill this in once the details of complex, representative // protos are decided } message PayloadConfig { oneof payload { ByteBufferParams bytebuf_params = 1; SimpleProtoParams simple_params = 2; ComplexProtoParams complex_params = 3; } } grpc-1.3.2/src/proto/grpc/testing/proto2/000077500000000000000000000000001310511640000202265ustar00rootroot00000000000000grpc-1.3.2/src/proto/grpc/testing/proto2/empty2.proto000066400000000000000000000032011310511640000225270ustar00rootroot00000000000000 // Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto2"; package grpc.testing.proto2; message EmptyWithExtensions { extensions 100 to 999; } grpc-1.3.2/src/proto/grpc/testing/proto2/empty2_extensions.proto000066400000000000000000000035661310511640000250240ustar00rootroot00000000000000// Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto2"; import "src/proto/grpc/testing/proto2/empty2.proto"; package grpc.testing.proto2; // Fill emptiness with music. extend grpc.testing.proto2.EmptyWithExtensions { optional int64 Deadmau5 = 124; optional float Madeon = 125; optional string AboveAndBeyond = 126; optional bool Tycho = 127; optional fixed64 Pendulum = 128; } grpc-1.3.2/src/proto/grpc/testing/proxy-service.proto000066400000000000000000000034361310511640000227130ustar00rootroot00000000000000// Copyright 2017, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; import "src/proto/grpc/testing/control.proto"; package grpc.testing; message ProxyStat { double latency = 1; } service ProxyClientService { rpc GetConfig(Void) returns (ClientConfig); rpc ReportTime(stream ProxyStat) returns (Void); } grpc-1.3.2/src/proto/grpc/testing/services.proto000066400000000000000000000065101310511640000217130ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // An integration test service that covers all the method signature permutations // of unary/streaming requests/responses. syntax = "proto3"; import "src/proto/grpc/testing/messages.proto"; import "src/proto/grpc/testing/control.proto"; import "src/proto/grpc/testing/stats.proto"; package grpc.testing; service BenchmarkService { // One request followed by one response. // The server returns the client payload as-is. rpc UnaryCall(SimpleRequest) returns (SimpleResponse); // One request followed by one response. // The server returns the client payload as-is. rpc StreamingCall(stream SimpleRequest) returns (stream SimpleResponse); } service WorkerService { // Start server with specified workload. // First request sent specifies the ServerConfig followed by ServerStatus // response. After that, a "Mark" can be sent anytime to request the latest // stats. Closing the stream will initiate shutdown of the test server // and once the shutdown has finished, the OK status is sent to terminate // this RPC. rpc RunServer(stream ServerArgs) returns (stream ServerStatus); // Start client with specified workload. // First request sent specifies the ClientConfig followed by ClientStatus // response. After that, a "Mark" can be sent anytime to request the latest // stats. Closing the stream will initiate shutdown of the test client // and once the shutdown has finished, the OK status is sent to terminate // this RPC. rpc RunClient(stream ClientArgs) returns (stream ClientStatus); // Just return the core count - unary call rpc CoreCount(CoreRequest) returns (CoreResponse); // Quit this worker rpc QuitWorker(Void) returns (Void); } service ReportQpsScenarioService { // Report results of a QPS test benchmark scenario. rpc ReportScenario(ScenarioResult) returns (Void); } grpc-1.3.2/src/proto/grpc/testing/stats.proto000066400000000000000000000056421310511640000212330ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package grpc.testing; message ServerStats { // wall clock time change in seconds since last reset double time_elapsed = 1; // change in user time (in seconds) used by the server since last reset double time_user = 2; // change in server time (in seconds) used by the server process and all // threads since last reset double time_system = 3; // change in total cpu time of the server (data from proc/stat) uint64 total_cpu_time = 4; // change in idle time of the server (data from proc/stat) uint64 idle_cpu_time = 5; } // Histogram params based on grpc/support/histogram.c message HistogramParams { double resolution = 1; // first bucket is [0, 1 + resolution) double max_possible = 2; // use enough buckets to allow this value } // Histogram data based on grpc/support/histogram.c message HistogramData { repeated uint32 bucket = 1; double min_seen = 2; double max_seen = 3; double sum = 4; double sum_of_squares = 5; double count = 6; } message RequestResultCount { int32 status_code = 1; int64 count = 2; } message ClientStats { // Latency histogram. Data points are in nanoseconds. HistogramData latencies = 1; // See ServerStats for details. double time_elapsed = 2; double time_user = 3; double time_system = 4; // Number of failed requests (one row per status code seen) repeated RequestResultCount request_results = 5; } grpc-1.3.2/src/proto/grpc/testing/test.proto000066400000000000000000000102421310511640000210440ustar00rootroot00000000000000 // Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // An integration test service that covers all the method signature permutations // of unary/streaming requests/responses. syntax = "proto3"; import "src/proto/grpc/testing/empty.proto"; import "src/proto/grpc/testing/messages.proto"; package grpc.testing; // A simple service to test the various types of RPCs and experiment with // performance with various types of payload. service TestService { // One empty request followed by one empty response. rpc EmptyCall(grpc.testing.Empty) returns (grpc.testing.Empty); // One request followed by one response. rpc UnaryCall(SimpleRequest) returns (SimpleResponse); // One request followed by one response. Response has cache control // headers set such that a caching HTTP proxy (such as GFE) can // satisfy subsequent requests. rpc CacheableUnaryCall(SimpleRequest) returns (SimpleResponse); // One request followed by a sequence of responses (streamed download). // The server returns the payload with client desired type and sizes. rpc StreamingOutputCall(StreamingOutputCallRequest) returns (stream StreamingOutputCallResponse); // A sequence of requests followed by one response (streamed upload). // The server returns the aggregated size of client payload as the result. rpc StreamingInputCall(stream StreamingInputCallRequest) returns (StreamingInputCallResponse); // A sequence of requests with each request served by the server immediately. // As one request could lead to multiple responses, this interface // demonstrates the idea of full duplexing. rpc FullDuplexCall(stream StreamingOutputCallRequest) returns (stream StreamingOutputCallResponse); // A sequence of requests followed by a sequence of responses. // The server buffers all the client requests and then serves them in order. A // stream of responses are returned to the client when the server starts with // first request. rpc HalfDuplexCall(stream StreamingOutputCallRequest) returns (stream StreamingOutputCallResponse); // The test server will not implement this method. It will be used // to test the behavior when clients call unimplemented methods. rpc UnimplementedCall(grpc.testing.Empty) returns (grpc.testing.Empty); } // A simple service NOT implemented at servers so clients can test for // that case. service UnimplementedService { // A call that no server should implement rpc UnimplementedCall(grpc.testing.Empty) returns (grpc.testing.Empty); } // A service used to control reconnect server. service ReconnectService { rpc Start(grpc.testing.ReconnectParams) returns (grpc.testing.Empty); rpc Stop(grpc.testing.Empty) returns (grpc.testing.ReconnectInfo); } grpc-1.3.2/src/proto/math/000077500000000000000000000000001310511640000153225ustar00rootroot00000000000000grpc-1.3.2/src/proto/math/math.proto000066400000000000000000000053261310511640000173460ustar00rootroot00000000000000 // Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package math; message DivArgs { int64 dividend = 1; int64 divisor = 2; } message DivReply { int64 quotient = 1; int64 remainder = 2; } message FibArgs { int64 limit = 1; } message Num { int64 num = 1; } message FibReply { int64 count = 1; } service Math { // Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient // and remainder. rpc Div (DivArgs) returns (DivReply) { } // DivMany accepts an arbitrary number of division args from the client stream // and sends back the results in the reply stream. The stream continues until // the client closes its end; the server does the same after sending all the // replies. The stream ends immediately if either end aborts. rpc DivMany (stream DivArgs) returns (stream DivReply) { } // Fib generates numbers in the Fibonacci sequence. If FibArgs.limit > 0, Fib // generates up to limit numbers; otherwise it continues until the call is // canceled. Unlike Fib above, Fib has no final FibReply. rpc Fib (FibArgs) returns (stream Num) { } // Sum sums a stream of numbers, returning the final result once the stream // is closed. rpc Sum (stream Num) returns (Num) { } } grpc-1.3.2/src/python/000077500000000000000000000000001310511640000145475ustar00rootroot00000000000000grpc-1.3.2/src/python/.gitignore000066400000000000000000000000351310511640000165350ustar00rootroot00000000000000gens/ *_pb2.py *_pb2_grpc.py grpc-1.3.2/src/python/grpcio/000077500000000000000000000000001310511640000160325ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio/.gitignore000066400000000000000000000002611310511640000200210ustar00rootroot00000000000000MANIFEST *.egg-info/ build/ dist/ *.egg *.egg/ *.eggs/ *_pb2.py .coverage .coverage.* .cache/ nosetests.xml doc/ _grpcio_metadata.py htmlcov/ grpc/_cython/_credentials poison.c grpc-1.3.2/src/python/grpcio/README.rst000066400000000000000000000051751310511640000175310ustar00rootroot00000000000000gRPC Python =========== Package for gRPC Python. Installation ------------ gRPC Python is available for Linux, Mac OS X, and Windows running Python 2.7. From PyPI ~~~~~~~~~ If you are installing locally... :: $ pip install grpcio Else system wide (on Ubuntu)... :: $ sudo pip install grpcio If you're on Windows make sure that you installed the :code:`pip.exe` component when you installed Python (if not go back and install it!) then invoke: :: $ pip.exe install grpcio Windows users may need to invoke :code:`pip.exe` from a command line ran as administrator. n.b. On Windows and on Mac OS X one *must* have a recent release of :code:`pip` to retrieve the proper wheel from PyPI. Be sure to upgrade to the latest version! From Source ~~~~~~~~~~~ Building from source requires that you have the Python headers (usually a package named :code:`python-dev`). :: $ export REPO_ROOT=grpc # REPO_ROOT can be any directory of your choice $ git clone -b $(curl -L http://grpc.io/release) https://github.com/grpc/grpc $REPO_ROOT $ cd $REPO_ROOT $ git submodule update --init # For the next two commands do `sudo pip install` if you get permission-denied errors $ pip install -rrequirements.txt $ GRPC_PYTHON_BUILD_WITH_CYTHON=1 pip install . You cannot currently install Python from source on Windows. Things might work out for you in MSYS2 (follow the Linux instructions), but it isn't officially supported at the moment. Troubleshooting ~~~~~~~~~~~~~~~ Help, I ... * **... see a** :code:`pkg_resources.VersionConflict` **when I try to install grpc** This is likely because :code:`pip` doesn't own the offending dependency, which in turn is likely because your operating system's package manager owns it. You'll need to force the installation of the dependency: :code:`pip install --ignore-installed $OFFENDING_DEPENDENCY` For example, if you get an error like the following: :: Traceback (most recent call last): File "", line 17, in ... File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 509, in find raise VersionConflict(dist, req) pkg_resources.VersionConflict: (six 1.8.0 (/usr/lib/python2.7/dist-packages), Requirement.parse('six>=1.10')) You can fix it by doing: :: sudo pip install --ignore-installed six * **... see the following error on some platforms** :: /tmp/pip-build-U8pSsr/cython/Cython/Plex/Scanners.c:4:20: fatal error: Python.h: No such file or directory #include "Python.h" ^ compilation terminated. You can fix it by installing `python-dev` package. i.e :: sudo apt-get install python-dev grpc-1.3.2/src/python/grpcio/_spawn_patch.py000066400000000000000000000060661310511640000210620ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Patches the spawn() command for windows compilers. Windows has an 8191 character command line limit, but some compilers support an @command_file directive where command_file is a file containing the full command line. """ from distutils import ccompiler import os import os.path import shutil import sys import tempfile MAX_COMMAND_LENGTH = 8191 _classic_spawn = ccompiler.CCompiler.spawn def _commandfile_spawn(self, command): command_length = sum([len(arg) for arg in command]) if os.name == 'nt' and command_length > MAX_COMMAND_LENGTH: # Even if this command doesn't support the @command_file, it will # fail as is so we try blindly print('Command line length exceeded, using command file') print(' '.join(command)) temporary_directory = tempfile.mkdtemp() command_filename = os.path.abspath( os.path.join(temporary_directory, 'command')) with open(command_filename, 'w') as command_file: escaped_args = [ '"' + arg.replace('\\', '\\\\') + '"' for arg in command[1:] ] command_file.write(' '.join(escaped_args)) modified_command = command[:1] + ['@{}'.format(command_filename)] try: _classic_spawn(self, modified_command) finally: shutil.rmtree(temporary_directory) else: _classic_spawn(self, command) def monkeypatch_spawn(): """Monkeypatching is dumb, but it's either that or we become maintainers of something much, much bigger.""" ccompiler.CCompiler.spawn = _commandfile_spawn grpc-1.3.2/src/python/grpcio/commands.py000066400000000000000000000266641310511640000202230ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Provides distutils command classes for the GRPC Python setup process.""" import distutils import glob import os import os.path import platform import re import shutil import subprocess import sys import traceback import setuptools from setuptools.command import build_ext from setuptools.command import build_py from setuptools.command import easy_install from setuptools.command import install from setuptools.command import test import support PYTHON_STEM = os.path.dirname(os.path.abspath(__file__)) GRPC_STEM = os.path.abspath(PYTHON_STEM + '../../../../') PROTO_STEM = os.path.join(GRPC_STEM, 'src', 'proto') PROTO_GEN_STEM = os.path.join(GRPC_STEM, 'src', 'python', 'gens') CYTHON_STEM = os.path.join(PYTHON_STEM, 'grpc', '_cython') CONF_PY_ADDENDUM = """ extensions.append('sphinx.ext.napoleon') napoleon_google_docstring = True napoleon_numpy_docstring = True napoleon_include_special_with_doc = True html_theme = 'sphinx_rtd_theme' copyright = "2016, The gRPC Authors" """ API_GLOSSARY = """ Glossary ================ .. glossary:: metadatum A key-value pair included in the HTTP header. It is a 2-tuple where the first entry is the key and the second is the value, i.e. (key, value). The metadata key is an ASCII str, and must be a valid HTTP header name. The metadata value can be either a valid HTTP ASCII str, or bytes. If bytes are provided, the key must end with '-bin', i.e. ``('binary-metadata-bin', b'\\x00\\xFF')`` metadata A sequence of metadatum. """ class CommandError(Exception): """Simple exception class for GRPC custom commands.""" # TODO(atash): Remove this once PyPI has better Linux bdist support. See # https://bitbucket.org/pypa/pypi/issues/120/binary-wheels-for-linux-are-not-supported def _get_grpc_custom_bdist(decorated_basename, target_bdist_basename): """Returns a string path to a bdist file for Linux to install. If we can retrieve a pre-compiled bdist from online, uses it. Else, emits a warning and builds from source. """ # TODO(atash): somehow the name that's returned from `wheel` is different # between different versions of 'wheel' (but from a compatibility standpoint, # the names are compatible); we should have some way of determining name # compatibility in the same way `wheel` does to avoid having to rename all of # the custom wheels that we build/upload to GCS. # Break import style to ensure that setup.py has had a chance to install the # relevant package. from six.moves.urllib import request decorated_path = decorated_basename + GRPC_CUSTOM_BDIST_EXT try: url = BINARIES_REPOSITORY + '/{target}'.format(target=decorated_path) bdist_data = request.urlopen(url).read() except IOError as error: raise CommandError('{}\n\nCould not find the bdist {}: {}'.format( traceback.format_exc(), decorated_path, error.message)) # Our chosen local bdist path. bdist_path = target_bdist_basename + GRPC_CUSTOM_BDIST_EXT try: with open(bdist_path, 'w') as bdist_file: bdist_file.write(bdist_data) except IOError as error: raise CommandError('{}\n\nCould not write grpcio bdist: {}' .format(traceback.format_exc(), error.message)) return bdist_path class SphinxDocumentation(setuptools.Command): """Command to generate documentation via sphinx.""" description = 'generate sphinx documentation' user_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): # We import here to ensure that setup.py has had a chance to install the # relevant package eggs first. import sphinx import sphinx.apidoc metadata = self.distribution.metadata src_dir = os.path.join(PYTHON_STEM, 'grpc') sys.path.append(src_dir) sphinx.apidoc.main([ '', '--force', '--full', '-H', metadata.name, '-A', metadata.author, '-V', metadata.version, '-R', metadata.version, '-o', os.path.join('doc', 'src'), src_dir ]) conf_filepath = os.path.join('doc', 'src', 'conf.py') with open(conf_filepath, 'a') as conf_file: conf_file.write(CONF_PY_ADDENDUM) glossary_filepath = os.path.join('doc', 'src', 'grpc.rst') with open(glossary_filepath, 'a') as glossary_filepath: glossary_filepath.write(API_GLOSSARY) sphinx.main( ['', os.path.join('doc', 'src'), os.path.join('doc', 'build')]) class BuildProjectMetadata(setuptools.Command): """Command to generate project metadata in a module.""" description = 'build grpcio project metadata files' user_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): with open(os.path.join(PYTHON_STEM, 'grpc/_grpcio_metadata.py'), 'w') as module_file: module_file.write('__version__ = """{}"""'.format( self.distribution.get_version())) class BuildPy(build_py.build_py): """Custom project build command.""" def run(self): self.run_command('build_project_metadata') build_py.build_py.run(self) def _poison_extensions(extensions, message): """Includes a file that will always fail to compile in all extensions.""" poison_filename = os.path.join(PYTHON_STEM, 'poison.c') with open(poison_filename, 'w') as poison: poison.write('#error {}'.format(message)) for extension in extensions: extension.sources = [poison_filename] def check_and_update_cythonization(extensions): """Replace .pyx files with their generated counterparts and return whether or not cythonization still needs to occur.""" for extension in extensions: generated_pyx_sources = [] other_sources = [] for source in extension.sources: base, file_ext = os.path.splitext(source) if file_ext == '.pyx': generated_pyx_source = next((base + gen_ext for gen_ext in ('.c', '.cpp',) if os.path.isfile(base + gen_ext)), None) if generated_pyx_source: generated_pyx_sources.append(generated_pyx_source) else: sys.stderr.write('Cython-generated files are missing...\n') return False else: other_sources.append(source) extension.sources = generated_pyx_sources + other_sources sys.stderr.write('Found cython-generated files...\n') return True def try_cythonize(extensions, linetracing=False, mandatory=True): """Attempt to cythonize the extensions. Args: extensions: A list of `distutils.extension.Extension`. linetracing: A bool indicating whether or not to enable linetracing. mandatory: Whether or not having Cython-generated files is mandatory. If it is, extensions will be poisoned when they can't be fully generated. """ try: # Break import style to ensure we have access to Cython post-setup_requires import Cython.Build except ImportError: if mandatory: sys.stderr.write( "This package needs to generate C files with Cython but it cannot. " "Poisoning extension sources to disallow extension commands...") _poison_extensions( extensions, "Extensions have been poisoned due to missing Cython-generated code." ) return extensions cython_compiler_directives = {} if linetracing: additional_define_macros = [('CYTHON_TRACE_NOGIL', '1')] cython_compiler_directives['linetrace'] = True return Cython.Build.cythonize( extensions, include_path=[ include_dir for extension in extensions for include_dir in extension.include_dirs ] + [CYTHON_STEM], compiler_directives=cython_compiler_directives) class BuildExt(build_ext.build_ext): """Custom build_ext command to enable compiler-specific flags.""" C_OPTIONS = { 'unix': ('-pthread', '-std=gnu99'), 'msvc': (), } LINK_OPTIONS = {} def build_extensions(self): compiler = self.compiler.compiler_type if compiler in BuildExt.C_OPTIONS: for extension in self.extensions: extension.extra_compile_args += list( BuildExt.C_OPTIONS[compiler]) if compiler in BuildExt.LINK_OPTIONS: for extension in self.extensions: extension.extra_link_args += list( BuildExt.LINK_OPTIONS[compiler]) if not check_and_update_cythonization(self.extensions): self.extensions = try_cythonize(self.extensions) try: build_ext.build_ext.build_extensions(self) except Exception as error: formatted_exception = traceback.format_exc() support.diagnose_build_ext_error(self, error, formatted_exception) raise CommandError( "Failed `build_ext` step:\n{}".format(formatted_exception)) class Gather(setuptools.Command): """Command to gather project dependencies.""" description = 'gather dependencies for grpcio' user_options = [ ('test', 't', 'flag indicating to gather test dependencies'), ('install', 'i', 'flag indicating to gather install dependencies') ] def initialize_options(self): self.test = False self.install = False def finalize_options(self): # distutils requires this override. pass def run(self): if self.install and self.distribution.install_requires: self.distribution.fetch_build_eggs( self.distribution.install_requires) if self.test and self.distribution.tests_require: self.distribution.fetch_build_eggs(self.distribution.tests_require) grpc-1.3.2/src/python/grpcio/grpc/000077500000000000000000000000001310511640000167655ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio/grpc/__init__.py000066400000000000000000001407701310511640000211070ustar00rootroot00000000000000# Copyright 2015-2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """gRPC's Python API.""" import abc import enum import sys import six from grpc._cython import cygrpc as _cygrpc ############################## Future Interface ############################### class FutureTimeoutError(Exception): """Indicates that a method call on a Future timed out.""" class FutureCancelledError(Exception): """Indicates that the computation underlying a Future was cancelled.""" class Future(six.with_metaclass(abc.ABCMeta)): """A representation of a computation in another control flow. Computations represented by a Future may be yet to be begun, may be ongoing, or may have already completed. """ @abc.abstractmethod def cancel(self): """Attempts to cancel the computation. This method does not block. Returns: True if the computation has not yet begun, will not be allowed to take place, and determination of both was possible without blocking. False under all other circumstances including but not limited to the computation's already having begun, the computation's already having finished, and the computation's having been scheduled for execution on a remote system for which a determination of whether or not it commenced before being cancelled cannot be made without blocking. """ raise NotImplementedError() @abc.abstractmethod def cancelled(self): """Describes whether the computation was cancelled. This method does not block. Returns: True if the computation was cancelled any time before its result became immediately available. False under all other circumstances including but not limited to this object's cancel method not having been called and the computation's result having become immediately available. """ raise NotImplementedError() @abc.abstractmethod def running(self): """Describes whether the computation is taking place. This method does not block. Returns: True if the computation is scheduled to take place in the future or is taking place now, or False if the computation took place in the past or was cancelled. """ raise NotImplementedError() @abc.abstractmethod def done(self): """Describes whether the computation has taken place. This method does not block. Returns: True if the computation is known to have either completed or have been unscheduled or interrupted. False if the computation may possibly be executing or scheduled to execute later. """ raise NotImplementedError() @abc.abstractmethod def result(self, timeout=None): """Accesses the outcome of the computation or raises its exception. This method may return immediately or may block. Args: timeout: The length of time in seconds to wait for the computation to finish or be cancelled, or None if this method should block until the computation has finished or is cancelled no matter how long that takes. Returns: The return value of the computation. Raises: FutureTimeoutError: If a timeout value is passed and the computation does not terminate within the allotted time. FutureCancelledError: If the computation was cancelled. Exception: If the computation raised an exception, this call will raise the same exception. """ raise NotImplementedError() @abc.abstractmethod def exception(self, timeout=None): """Return the exception raised by the computation. This method may return immediately or may block. Args: timeout: The length of time in seconds to wait for the computation to terminate or be cancelled, or None if this method should block until the computation is terminated or is cancelled no matter how long that takes. Returns: The exception raised by the computation, or None if the computation did not raise an exception. Raises: FutureTimeoutError: If a timeout value is passed and the computation does not terminate within the allotted time. FutureCancelledError: If the computation was cancelled. """ raise NotImplementedError() @abc.abstractmethod def traceback(self, timeout=None): """Access the traceback of the exception raised by the computation. This method may return immediately or may block. Args: timeout: The length of time in seconds to wait for the computation to terminate or be cancelled, or None if this method should block until the computation is terminated or is cancelled no matter how long that takes. Returns: The traceback of the exception raised by the computation, or None if the computation did not raise an exception. Raises: FutureTimeoutError: If a timeout value is passed and the computation does not terminate within the allotted time. FutureCancelledError: If the computation was cancelled. """ raise NotImplementedError() @abc.abstractmethod def add_done_callback(self, fn): """Adds a function to be called at completion of the computation. The callback will be passed this Future object describing the outcome of the computation. If the computation has already completed, the callback will be called immediately. Args: fn: A callable taking this Future object as its single parameter. """ raise NotImplementedError() ################################ gRPC Enums ################################## @enum.unique class ChannelConnectivity(enum.Enum): """Mirrors grpc_connectivity_state in the gRPC Core. Attributes: IDLE: The channel is idle. CONNECTING: The channel is connecting. READY: The channel is ready to conduct RPCs. TRANSIENT_FAILURE: The channel has seen a failure from which it expects to recover. SHUTDOWN: The channel has seen a failure from which it cannot recover. """ IDLE = (_cygrpc.ConnectivityState.idle, 'idle') CONNECTING = (_cygrpc.ConnectivityState.connecting, 'connecting') READY = (_cygrpc.ConnectivityState.ready, 'ready') TRANSIENT_FAILURE = (_cygrpc.ConnectivityState.transient_failure, 'transient failure') SHUTDOWN = (_cygrpc.ConnectivityState.shutdown, 'shutdown') @enum.unique class StatusCode(enum.Enum): """Mirrors grpc_status_code in the gRPC Core.""" OK = (_cygrpc.StatusCode.ok, 'ok') CANCELLED = (_cygrpc.StatusCode.cancelled, 'cancelled') UNKNOWN = (_cygrpc.StatusCode.unknown, 'unknown') INVALID_ARGUMENT = (_cygrpc.StatusCode.invalid_argument, 'invalid argument') DEADLINE_EXCEEDED = (_cygrpc.StatusCode.deadline_exceeded, 'deadline exceeded') NOT_FOUND = (_cygrpc.StatusCode.not_found, 'not found') ALREADY_EXISTS = (_cygrpc.StatusCode.already_exists, 'already exists') PERMISSION_DENIED = (_cygrpc.StatusCode.permission_denied, 'permission denied') RESOURCE_EXHAUSTED = (_cygrpc.StatusCode.resource_exhausted, 'resource exhausted') FAILED_PRECONDITION = (_cygrpc.StatusCode.failed_precondition, 'failed precondition') ABORTED = (_cygrpc.StatusCode.aborted, 'aborted') OUT_OF_RANGE = (_cygrpc.StatusCode.out_of_range, 'out of range') UNIMPLEMENTED = (_cygrpc.StatusCode.unimplemented, 'unimplemented') INTERNAL = (_cygrpc.StatusCode.internal, 'internal') UNAVAILABLE = (_cygrpc.StatusCode.unavailable, 'unavailable') DATA_LOSS = (_cygrpc.StatusCode.data_loss, 'data loss') UNAUTHENTICATED = (_cygrpc.StatusCode.unauthenticated, 'unauthenticated') ############################# gRPC Exceptions ################################ class RpcError(Exception): """Raised by the gRPC library to indicate non-OK-status RPC termination.""" ############################## Shared Context ################################ class RpcContext(six.with_metaclass(abc.ABCMeta)): """Provides RPC-related information and action.""" @abc.abstractmethod def is_active(self): """Describes whether the RPC is active or has terminated.""" raise NotImplementedError() @abc.abstractmethod def time_remaining(self): """Describes the length of allowed time remaining for the RPC. Returns: A nonnegative float indicating the length of allowed time in seconds remaining for the RPC to complete before it is considered to have timed out, or None if no deadline was specified for the RPC. """ raise NotImplementedError() @abc.abstractmethod def cancel(self): """Cancels the RPC. Idempotent and has no effect if the RPC has already terminated. """ raise NotImplementedError() @abc.abstractmethod def add_callback(self, callback): """Registers a callback to be called on RPC termination. Args: callback: A no-parameter callable to be called on RPC termination. Returns: True if the callback was added and will be called later; False if the callback was not added and will not later be called (because the RPC already terminated or some other reason). """ raise NotImplementedError() ######################### Invocation-Side Context ############################ class Call(six.with_metaclass(abc.ABCMeta, RpcContext)): """Invocation-side utility object for an RPC.""" @abc.abstractmethod def initial_metadata(self): """Accesses the initial metadata from the service-side of the RPC. This method blocks until the value is available. Returns: The initial :term:`metadata`. """ raise NotImplementedError() @abc.abstractmethod def trailing_metadata(self): """Accesses the trailing metadata from the service-side of the RPC. This method blocks until the value is available. Returns: The trailing :term:`metadata`. """ raise NotImplementedError() @abc.abstractmethod def code(self): """Accesses the status code emitted by the service-side of the RPC. This method blocks until the value is available. Returns: The StatusCode value for the RPC. """ raise NotImplementedError() @abc.abstractmethod def details(self): """Accesses the details value emitted by the service-side of the RPC. This method blocks until the value is available. Returns: The details string of the RPC. """ raise NotImplementedError() ############ Authentication & Authorization Interfaces & Classes ############# class ChannelCredentials(object): """A value encapsulating the data required to create a secure Channel. This class has no supported interface - it exists to define the type of its instances and its instances exist to be passed to other functions. """ def __init__(self, credentials): self._credentials = credentials class CallCredentials(object): """A value encapsulating data asserting an identity over a channel. A CallCredentials may be composed with ChannelCredentials to always assert identity for every call over that Channel. This class has no supported interface - it exists to define the type of its instances and its instances exist to be passed to other functions. """ def __init__(self, credentials): self._credentials = credentials class AuthMetadataContext(six.with_metaclass(abc.ABCMeta)): """Provides information to call credentials metadata plugins. Attributes: service_url: A string URL of the service being called into. method_name: A string of the fully qualified method name being called. """ class AuthMetadataPluginCallback(six.with_metaclass(abc.ABCMeta)): """Callback object received by a metadata plugin.""" def __call__(self, metadata, error): """Inform the gRPC runtime of the metadata to construct a CallCredentials. Args: metadata: The :term:`metadata` used to construct the CallCredentials. error: An Exception to indicate error or None to indicate success. """ raise NotImplementedError() class AuthMetadataPlugin(six.with_metaclass(abc.ABCMeta)): """A specification for custom authentication.""" def __call__(self, context, callback): """Implements authentication by passing metadata to a callback. Implementations of this method must not block. Args: context: An AuthMetadataContext providing information on the RPC that the plugin is being called to authenticate. callback: An AuthMetadataPluginCallback to be invoked either synchronously or asynchronously. """ raise NotImplementedError() class ServerCredentials(object): """A value encapsulating the data required to open a secure port on a Server. This class has no supported interface - it exists to define the type of its instances and its instances exist to be passed to other functions. """ def __init__(self, credentials): self._credentials = credentials ######################## Multi-Callable Interfaces ########################### class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): """Affords invoking a unary-unary RPC.""" @abc.abstractmethod def __call__(self, request, timeout=None, metadata=None, credentials=None): """Synchronously invokes the underlying RPC. Args: request: The request value for the RPC. timeout: An optional duration of time in seconds to allow for the RPC. metadata: Optional :term:`metadata` to be transmitted to the service-side of the RPC. credentials: An optional CallCredentials for the RPC. Returns: The response value for the RPC. Raises: RpcError: Indicating that the RPC terminated with non-OK status. The raised RpcError will also be a Call for the RPC affording the RPC's metadata, status code, and details. """ raise NotImplementedError() @abc.abstractmethod def with_call(self, request, timeout=None, metadata=None, credentials=None): """Synchronously invokes the underlying RPC. Args: request: The request value for the RPC. timeout: An optional durating of time in seconds to allow for the RPC. metadata: Optional :term:`metadata` to be transmitted to the service-side of the RPC. credentials: An optional CallCredentials for the RPC. Returns: The response value for the RPC and a Call value for the RPC. Raises: RpcError: Indicating that the RPC terminated with non-OK status. The raised RpcError will also be a Call for the RPC affording the RPC's metadata, status code, and details. """ raise NotImplementedError() @abc.abstractmethod def future(self, request, timeout=None, metadata=None, credentials=None): """Asynchronously invokes the underlying RPC. Args: request: The request value for the RPC. timeout: An optional duration of time in seconds to allow for the RPC. metadata: Optional :term:`metadata` to be transmitted to the service-side of the RPC. credentials: An optional CallCredentials for the RPC. Returns: An object that is both a Call for the RPC and a Future. In the event of RPC completion, the return Call-Future's result value will be the response message of the RPC. Should the event terminate with non-OK status, the returned Call-Future's exception value will be an RpcError. """ raise NotImplementedError() class UnaryStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): """Affords invoking a unary-stream RPC.""" @abc.abstractmethod def __call__(self, request, timeout=None, metadata=None, credentials=None): """Invokes the underlying RPC. Args: request: The request value for the RPC. timeout: An optional duration of time in seconds to allow for the RPC. metadata: An optional :term:`metadata` to be transmitted to the service-side of the RPC. credentials: An optional CallCredentials for the RPC. Returns: An object that is both a Call for the RPC and an iterator of response values. Drawing response values from the returned Call-iterator may raise RpcError indicating termination of the RPC with non-OK status. """ raise NotImplementedError() class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): """Affords invoking a stream-unary RPC in any call style.""" @abc.abstractmethod def __call__(self, request_iterator, timeout=None, metadata=None, credentials=None): """Synchronously invokes the underlying RPC. Args: request_iterator: An iterator that yields request values for the RPC. timeout: An optional duration of time in seconds to allow for the RPC. metadata: Optional :term:`metadata` to be transmitted to the service-side of the RPC. credentials: An optional CallCredentials for the RPC. Returns: The response value for the RPC. Raises: RpcError: Indicating that the RPC terminated with non-OK status. The raised RpcError will also be a Call for the RPC affording the RPC's metadata, status code, and details. """ raise NotImplementedError() @abc.abstractmethod def with_call(self, request_iterator, timeout=None, metadata=None, credentials=None): """Synchronously invokes the underlying RPC. Args: request_iterator: An iterator that yields request values for the RPC. timeout: An optional duration of time in seconds to allow for the RPC. metadata: Optional :term:`metadata` to be transmitted to the service-side of the RPC. credentials: An optional CallCredentials for the RPC. Returns: The response value for the RPC and a Call for the RPC. Raises: RpcError: Indicating that the RPC terminated with non-OK status. The raised RpcError will also be a Call for the RPC affording the RPC's metadata, status code, and details. """ raise NotImplementedError() @abc.abstractmethod def future(self, request_iterator, timeout=None, metadata=None, credentials=None): """Asynchronously invokes the underlying RPC. Args: request_iterator: An iterator that yields request values for the RPC. timeout: An optional duration of time in seconds to allow for the RPC. metadata: Optional :term:`metadata` to be transmitted to the service-side of the RPC. credentials: An optional CallCredentials for the RPC. Returns: An object that is both a Call for the RPC and a Future. In the event of RPC completion, the return Call-Future's result value will be the response message of the RPC. Should the event terminate with non-OK status, the returned Call-Future's exception value will be an RpcError. """ raise NotImplementedError() class StreamStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): """Affords invoking a stream-stream RPC in any call style.""" @abc.abstractmethod def __call__(self, request_iterator, timeout=None, metadata=None, credentials=None): """Invokes the underlying RPC. Args: request_iterator: An iterator that yields request values for the RPC. timeout: An optional duration of time in seconds to allow for the RPC. metadata: Optional :term:`metadata` to be transmitted to the service-side of the RPC. credentials: An optional CallCredentials for the RPC. Returns: An object that is both a Call for the RPC and an iterator of response values. Drawing response values from the returned Call-iterator may raise RpcError indicating termination of the RPC with non-OK status. """ raise NotImplementedError() ############################# Channel Interface ############################## class Channel(six.with_metaclass(abc.ABCMeta)): """Affords RPC invocation via generic methods.""" @abc.abstractmethod def subscribe(self, callback, try_to_connect=False): """Subscribes to this Channel's connectivity. Args: callback: A callable to be invoked and passed a ChannelConnectivity value describing this Channel's connectivity. The callable will be invoked immediately upon subscription and again for every change to this Channel's connectivity thereafter until it is unsubscribed or this Channel object goes out of scope. try_to_connect: A boolean indicating whether or not this Channel should attempt to connect if it is not already connected and ready to conduct RPCs. """ raise NotImplementedError() @abc.abstractmethod def unsubscribe(self, callback): """Unsubscribes a callback from this Channel's connectivity. Args: callback: A callable previously registered with this Channel from having been passed to its "subscribe" method. """ raise NotImplementedError() @abc.abstractmethod def unary_unary(self, method, request_serializer=None, response_deserializer=None): """Creates a UnaryUnaryMultiCallable for a unary-unary method. Args: method: The name of the RPC method. request_serializer: Optional behaviour for serializing the request message. Request goes unserialized in case None is passed. response_deserializer: Optional behaviour for deserializing the response message. Response goes undeserialized in case None is passed. Returns: A UnaryUnaryMultiCallable value for the named unary-unary method. """ raise NotImplementedError() @abc.abstractmethod def unary_stream(self, method, request_serializer=None, response_deserializer=None): """Creates a UnaryStreamMultiCallable for a unary-stream method. Args: method: The name of the RPC method. request_serializer: Optional behaviour for serializing the request message. Request goes unserialized in case None is passed. response_deserializer: Optional behaviour for deserializing the response message. Response goes undeserialized in case None is passed. Returns: A UnaryStreamMultiCallable value for the name unary-stream method. """ raise NotImplementedError() @abc.abstractmethod def stream_unary(self, method, request_serializer=None, response_deserializer=None): """Creates a StreamUnaryMultiCallable for a stream-unary method. Args: method: The name of the RPC method. request_serializer: Optional behaviour for serializing the request message. Request goes unserialized in case None is passed. response_deserializer: Optional behaviour for deserializing the response message. Response goes undeserialized in case None is passed. Returns: A StreamUnaryMultiCallable value for the named stream-unary method. """ raise NotImplementedError() @abc.abstractmethod def stream_stream(self, method, request_serializer=None, response_deserializer=None): """Creates a StreamStreamMultiCallable for a stream-stream method. Args: method: The name of the RPC method. request_serializer: Optional behaviour for serializing the request message. Request goes unserialized in case None is passed. response_deserializer: Optional behaviour for deserializing the response message. Response goes undeserialized in case None is passed. Returns: A StreamStreamMultiCallable value for the named stream-stream method. """ raise NotImplementedError() ########################## Service-Side Context ############################## class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): """A context object passed to method implementations.""" @abc.abstractmethod def invocation_metadata(self): """Accesses the metadata from the invocation-side of the RPC. Returns: The invocation :term:`metadata`. """ raise NotImplementedError() @abc.abstractmethod def peer(self): """Identifies the peer that invoked the RPC being serviced. Returns: A string identifying the peer that invoked the RPC being serviced. """ raise NotImplementedError() @abc.abstractmethod def send_initial_metadata(self, initial_metadata): """Sends the initial metadata value to the invocation-side of the RPC. This method need not be called by method implementations if they have no service-side initial metadata to transmit. Args: initial_metadata: The initial :term:`metadata`. """ raise NotImplementedError() @abc.abstractmethod def set_trailing_metadata(self, trailing_metadata): """Accepts the trailing metadata value of the RPC. This method need not be called by method implementations if they have no service-side trailing metadata to transmit. Args: trailing_metadata: The trailing :term:`metadata`. """ raise NotImplementedError() @abc.abstractmethod def set_code(self, code): """Accepts the status code of the RPC. This method need not be called by method implementations if they wish the gRPC runtime to determine the status code of the RPC. Args: code: A StatusCode value to be transmitted to the invocation side of the RPC as the status code of the RPC. """ raise NotImplementedError() @abc.abstractmethod def set_details(self, details): """Accepts the service-side details of the RPC. This method need not be called by method implementations if they have no details to transmit. Args: details: A string to be transmitted to the invocation side of the RPC as the status details of the RPC. """ raise NotImplementedError() ##################### Service-Side Handler Interfaces ######################## class RpcMethodHandler(six.with_metaclass(abc.ABCMeta)): """An implementation of a single RPC method. Attributes: request_streaming: Whether the RPC supports exactly one request message or any arbitrary number of request messages. response_streaming: Whether the RPC supports exactly one response message or any arbitrary number of response messages. request_deserializer: A callable behavior that accepts a byte string and returns an object suitable to be passed to this object's business logic, or None to indicate that this object's business logic should be passed the raw request bytes. response_serializer: A callable behavior that accepts an object produced by this object's business logic and returns a byte string, or None to indicate that the byte strings produced by this object's business logic should be transmitted on the wire as they are. unary_unary: This object's application-specific business logic as a callable value that takes a request value and a ServicerContext object and returns a response value. Only non-None if both request_streaming and response_streaming are False. unary_stream: This object's application-specific business logic as a callable value that takes a request value and a ServicerContext object and returns an iterator of response values. Only non-None if request_streaming is False and response_streaming is True. stream_unary: This object's application-specific business logic as a callable value that takes an iterator of request values and a ServicerContext object and returns a response value. Only non-None if request_streaming is True and response_streaming is False. stream_stream: This object's application-specific business logic as a callable value that takes an iterator of request values and a ServicerContext object and returns an iterator of response values. Only non-None if request_streaming and response_streaming are both True. """ class HandlerCallDetails(six.with_metaclass(abc.ABCMeta)): """Describes an RPC that has just arrived for service. Attributes: method: The method name of the RPC. invocation_metadata: The :term:`metadata` from the invocation side of the RPC. """ class GenericRpcHandler(six.with_metaclass(abc.ABCMeta)): """An implementation of arbitrarily many RPC methods.""" @abc.abstractmethod def service(self, handler_call_details): """Services an RPC (or not). Args: handler_call_details: A HandlerCallDetails describing the RPC. Returns: An RpcMethodHandler with which the RPC may be serviced, or None to indicate that this object will not be servicing the RPC. """ raise NotImplementedError() class ServiceRpcHandler(six.with_metaclass(abc.ABCMeta, GenericRpcHandler)): """An implementation of RPC methods belonging to a service. A service handles RPC methods with structured names of the form '/Service.Name/Service.MethodX', where 'Service.Name' is the value returned by service_name(), and 'Service.MethodX' is the service method name. A service can have multiple service methods names, but only a single service name. """ @abc.abstractmethod def service_name(self): """Returns this services name. Returns: The service name. """ raise NotImplementedError() ############################# Server Interface ############################### class Server(six.with_metaclass(abc.ABCMeta)): """Services RPCs.""" @abc.abstractmethod def add_generic_rpc_handlers(self, generic_rpc_handlers): """Registers GenericRpcHandlers with this Server. This method is only safe to call before the server is started. Args: generic_rpc_handlers: An iterable of GenericRpcHandlers that will be used to service RPCs after this Server is started. """ raise NotImplementedError() @abc.abstractmethod def add_insecure_port(self, address): """Reserves a port for insecure RPC service once this Server becomes active. This method may only be called before calling this Server's start method is called. Args: address: The address for which to open a port. Returns: An integer port on which RPCs will be serviced after this link has been started. This is typically the same number as the port number contained in the passed address, but will likely be different if the port number contained in the passed address was zero. """ raise NotImplementedError() @abc.abstractmethod def add_secure_port(self, address, server_credentials): """Reserves a port for secure RPC service after this Server becomes active. This method may only be called before calling this Server's start method is called. Args: address: The address for which to open a port. server_credentials: A ServerCredentials. Returns: An integer port on which RPCs will be serviced after this link has been started. This is typically the same number as the port number contained in the passed address, but will likely be different if the port number contained in the passed address was zero. """ raise NotImplementedError() @abc.abstractmethod def start(self): """Starts this Server's service of RPCs. This method may only be called while the server is not serving RPCs (i.e. it is not idempotent). """ raise NotImplementedError() @abc.abstractmethod def stop(self, grace): """Stops this Server's service of RPCs. All calls to this method immediately stop service of new RPCs. When existing RPCs are aborted is controlled by the grace period parameter passed to this method. This method may be called at any time and is idempotent. Passing a smaller grace value than has been passed in a previous call will have the effect of stopping the Server sooner. Passing a larger grace value than has been passed in a previous call will not have the effect of stopping the server later. This method does not block for any significant length of time. If None is passed as the grace value, existing RPCs are immediately aborted and this method blocks until this Server is completely stopped. Args: grace: A duration of time in seconds or None. If a duration of time in seconds, the time to allow existing RPCs to complete before being aborted by this Server's stopping. If None, all RPCs will be aborted immediately and this method will block until this Server is completely stopped. Returns: A threading.Event that will be set when this Server has completely stopped. The returned event may not be set until after the full grace period (if some ongoing RPC continues for the full length of the period) of it may be set much sooner (such as if this Server had no RPCs underway at the time it was stopped or if all RPCs that it had underway completed very early in the grace period). """ raise NotImplementedError() ################################# Functions ################################ def unary_unary_rpc_method_handler(behavior, request_deserializer=None, response_serializer=None): """Creates an RpcMethodHandler for a unary-unary RPC method. Args: behavior: The implementation of an RPC method as a callable behavior taking a single request value and returning a single response value. request_deserializer: An optional request deserialization behavior. response_serializer: An optional response serialization behavior. Returns: An RpcMethodHandler for a unary-unary RPC method constructed from the given parameters. """ from grpc import _utilities # pylint: disable=cyclic-import return _utilities.RpcMethodHandler(False, False, request_deserializer, response_serializer, behavior, None, None, None) def unary_stream_rpc_method_handler(behavior, request_deserializer=None, response_serializer=None): """Creates an RpcMethodHandler for a unary-stream RPC method. Args: behavior: The implementation of an RPC method as a callable behavior taking a single request value and returning an iterator of response values. request_deserializer: An optional request deserialization behavior. response_serializer: An optional response serialization behavior. Returns: An RpcMethodHandler for a unary-stream RPC method constructed from the given parameters. """ from grpc import _utilities # pylint: disable=cyclic-import return _utilities.RpcMethodHandler(False, True, request_deserializer, response_serializer, None, behavior, None, None) def stream_unary_rpc_method_handler(behavior, request_deserializer=None, response_serializer=None): """Creates an RpcMethodHandler for a stream-unary RPC method. Args: behavior: The implementation of an RPC method as a callable behavior taking an iterator of request values and returning a single response value. request_deserializer: An optional request deserialization behavior. response_serializer: An optional response serialization behavior. Returns: An RpcMethodHandler for a stream-unary RPC method constructed from the given parameters. """ from grpc import _utilities # pylint: disable=cyclic-import return _utilities.RpcMethodHandler(True, False, request_deserializer, response_serializer, None, None, behavior, None) def stream_stream_rpc_method_handler(behavior, request_deserializer=None, response_serializer=None): """Creates an RpcMethodHandler for a stream-stream RPC method. Args: behavior: The implementation of an RPC method as a callable behavior taking an iterator of request values and returning an iterator of response values. request_deserializer: An optional request deserialization behavior. response_serializer: An optional response serialization behavior. Returns: An RpcMethodHandler for a stream-stream RPC method constructed from the given parameters. """ from grpc import _utilities # pylint: disable=cyclic-import return _utilities.RpcMethodHandler(True, True, request_deserializer, response_serializer, None, None, None, behavior) def method_handlers_generic_handler(service, method_handlers): """Creates a grpc.GenericRpcHandler from RpcMethodHandlers. Args: service: A service name to be used for the given method handlers. method_handlers: A dictionary from method name to RpcMethodHandler implementing the named method. Returns: A GenericRpcHandler constructed from the given parameters. """ from grpc import _utilities # pylint: disable=cyclic-import return _utilities.DictionaryGenericHandler(service, method_handlers) def ssl_channel_credentials(root_certificates=None, private_key=None, certificate_chain=None): """Creates a ChannelCredentials for use with an SSL-enabled Channel. Args: root_certificates: The PEM-encoded root certificates or unset to ask for them to be retrieved from a default location. private_key: The PEM-encoded private key to use or unset if no private key should be used. certificate_chain: The PEM-encoded certificate chain to use or unset if no certificate chain should be used. Returns: A ChannelCredentials for use with an SSL-enabled Channel. """ if private_key is not None or certificate_chain is not None: pair = _cygrpc.SslPemKeyCertPair(private_key, certificate_chain) else: pair = None return ChannelCredentials( _cygrpc.channel_credentials_ssl(root_certificates, pair)) def metadata_call_credentials(metadata_plugin, name=None): """Construct CallCredentials from an AuthMetadataPlugin. Args: metadata_plugin: An AuthMetadataPlugin to use as the authentication behavior in the created CallCredentials. name: A name for the plugin. Returns: A CallCredentials. """ from grpc import _plugin_wrapping # pylint: disable=cyclic-import if name is None: try: effective_name = metadata_plugin.__name__ except AttributeError: effective_name = metadata_plugin.__class__.__name__ else: effective_name = name return CallCredentials( _plugin_wrapping.call_credentials_metadata_plugin(metadata_plugin, effective_name)) def access_token_call_credentials(access_token): """Construct CallCredentials from an access token. Args: access_token: A string to place directly in the http request authorization header, ie "authorization: Bearer ". Returns: A CallCredentials. """ from grpc import _auth # pylint: disable=cyclic-import return metadata_call_credentials( _auth.AccessTokenCallCredentials(access_token)) def composite_call_credentials(*call_credentials): """Compose multiple CallCredentials to make a new CallCredentials. Args: *call_credentials: At least two CallCredentials objects. Returns: A CallCredentials object composed of the given CallCredentials objects. """ from grpc import _credential_composition # pylint: disable=cyclic-import cygrpc_call_credentials = tuple( single_call_credentials._credentials for single_call_credentials in call_credentials) return CallCredentials( _credential_composition.call(cygrpc_call_credentials)) def composite_channel_credentials(channel_credentials, *call_credentials): """Compose a ChannelCredentials and one or more CallCredentials objects. Args: channel_credentials: A ChannelCredentials. *call_credentials: One or more CallCredentials objects. Returns: A ChannelCredentials composed of the given ChannelCredentials and CallCredentials objects. """ from grpc import _credential_composition # pylint: disable=cyclic-import cygrpc_call_credentials = tuple( single_call_credentials._credentials for single_call_credentials in call_credentials) return ChannelCredentials( _credential_composition.channel(channel_credentials._credentials, cygrpc_call_credentials)) def ssl_server_credentials(private_key_certificate_chain_pairs, root_certificates=None, require_client_auth=False): """Creates a ServerCredentials for use with an SSL-enabled Server. Args: private_key_certificate_chain_pairs: A nonempty sequence each element of which is a pair the first element of which is a PEM-encoded private key and the second element of which is the corresponding PEM-encoded certificate chain. root_certificates: PEM-encoded client root certificates to be used for verifying authenticated clients. If omitted, require_client_auth must also be omitted or be False. require_client_auth: A boolean indicating whether or not to require clients to be authenticated. May only be True if root_certificates is not None. Returns: A ServerCredentials for use with an SSL-enabled Server. """ if len(private_key_certificate_chain_pairs) == 0: raise ValueError( 'At least one private key-certificate chain pair is required!') elif require_client_auth and root_certificates is None: raise ValueError( 'Illegal to require client auth without providing root certificates!' ) else: return ServerCredentials( _cygrpc.server_credentials_ssl(root_certificates, [ _cygrpc.SslPemKeyCertPair(key, pem) for key, pem in private_key_certificate_chain_pairs ], require_client_auth)) def channel_ready_future(channel): """Creates a Future tracking when a Channel is ready. Cancelling the returned Future does not tell the given Channel to abandon attempts it may have been making to connect; cancelling merely deactivates the returned Future's subscription to the given Channel's connectivity. Args: channel: A Channel. Returns: A Future that matures when the given Channel has connectivity ChannelConnectivity.READY. """ from grpc import _utilities # pylint: disable=cyclic-import return _utilities.channel_ready_future(channel) def insecure_channel(target, options=None): """Creates an insecure Channel to a server. Args: target: The target to which to connect. options: A sequence of string-value pairs according to which to configure the created channel. Returns: A Channel to the target through which RPCs may be conducted. """ from grpc import _channel # pylint: disable=cyclic-import return _channel.Channel(target, () if options is None else options, None) def secure_channel(target, credentials, options=None): """Creates a secure Channel to a server. Args: target: The target to which to connect. credentials: A ChannelCredentials instance. options: A sequence of string-value pairs according to which to configure the created channel. Returns: A Channel to the target through which RPCs may be conducted. """ from grpc import _channel # pylint: disable=cyclic-import return _channel.Channel(target, () if options is None else options, credentials._credentials) def server(thread_pool, handlers=None, options=None, maximum_concurrent_rpcs=None): """Creates a Server with which RPCs can be serviced. Args: thread_pool: A futures.ThreadPoolExecutor to be used by the returned Server to service RPCs. handlers: An optional sequence of GenericRpcHandlers to be used to service RPCs after the returned Server is started. These handlers need not be the only handlers the server will use to service RPCs; other handlers may later be added by calling add_generic_rpc_handlers any time before the returned Server is started. options: A sequence of string-value pairs according to which to configure the created server. maximum_concurrent_rpcs: The maximum number of concurrent RPCs this server will service before returning status RESOURCE_EXHAUSTED, or None to indicate no limit. Returns: A Server with which RPCs can be serviced. """ from grpc import _server # pylint: disable=cyclic-import return _server.Server(thread_pool, () if handlers is None else handlers, () if options is None else options, maximum_concurrent_rpcs) ################################### __all__ ################################# __all__ = ('FutureTimeoutError', 'FutureCancelledError', 'Future', 'ChannelConnectivity', 'StatusCode', 'RpcError', 'RpcContext', 'Call', 'ChannelCredentials', 'CallCredentials', 'AuthMetadataContext', 'AuthMetadataPluginCallback', 'AuthMetadataPlugin', 'ServerCredentials', 'UnaryUnaryMultiCallable', 'UnaryStreamMultiCallable', 'StreamUnaryMultiCallable', 'StreamStreamMultiCallable', 'Channel', 'ServicerContext', 'RpcMethodHandler', 'HandlerCallDetails', 'GenericRpcHandler', 'ServiceRpcHandler', 'Server', 'unary_unary_rpc_method_handler', 'unary_stream_rpc_method_handler', 'stream_unary_rpc_method_handler', 'stream_stream_rpc_method_handler', 'method_handlers_generic_handler', 'ssl_channel_credentials', 'metadata_call_credentials', 'access_token_call_credentials', 'composite_call_credentials', 'composite_channel_credentials', 'ssl_server_credentials', 'channel_ready_future', 'insecure_channel', 'secure_channel', 'server',) ############################### Extension Shims ################################ # Here to maintain backwards compatibility; avoid using these in new code! try: import grpc_tools sys.modules.update({'grpc.tools': grpc_tools}) except ImportError: pass try: import grpc_health sys.modules.update({'grpc.health': grpc_health}) except ImportError: pass try: import grpc_reflection sys.modules.update({'grpc.reflection': grpc_reflection}) except ImportError: pass grpc-1.3.2/src/python/grpcio/grpc/_auth.py000066400000000000000000000066461310511640000204530ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """GRPCAuthMetadataPlugins for standard authentication.""" import inspect from concurrent import futures import grpc def _sign_request(callback, token, error): metadata = (('authorization', 'Bearer {}'.format(token)),) callback(metadata, error) def _create_get_token_callback(callback): def get_token_callback(future): try: access_token = future.result().access_token except Exception as exception: # pylint: disable=broad-except _sign_request(callback, None, exception) else: _sign_request(callback, access_token, None) return get_token_callback class GoogleCallCredentials(grpc.AuthMetadataPlugin): """Metadata wrapper for GoogleCredentials from the oauth2client library.""" def __init__(self, credentials): self._credentials = credentials self._pool = futures.ThreadPoolExecutor(max_workers=1) # Hack to determine if these are JWT creds and we need to pass # additional_claims when getting a token self._is_jwt = 'additional_claims' in inspect.getargspec( credentials.get_access_token).args def __call__(self, context, callback): # MetadataPlugins cannot block (see grpc.beta.interfaces.py) if self._is_jwt: future = self._pool.submit( self._credentials.get_access_token, additional_claims={'aud': context.service_url}) else: future = self._pool.submit(self._credentials.get_access_token) future.add_done_callback(_create_get_token_callback(callback)) def __del__(self): self._pool.shutdown(wait=False) class AccessTokenCallCredentials(grpc.AuthMetadataPlugin): """Metadata wrapper for raw access token credentials.""" def __init__(self, access_token): self._access_token = access_token def __call__(self, context, callback): _sign_request(callback, self._access_token, None) grpc-1.3.2/src/python/grpcio/grpc/_channel.py000066400000000000000000001166141310511640000211170ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Invocation-side implementation of gRPC Python.""" import sys import threading import time import logging import grpc from grpc import _common from grpc import _grpcio_metadata from grpc._cython import cygrpc from grpc.framework.foundation import callable_util _USER_AGENT = 'grpc-python/{}'.format(_grpcio_metadata.__version__) _EMPTY_FLAGS = 0 _INFINITE_FUTURE = cygrpc.Timespec(float('+inf')) _UNARY_UNARY_INITIAL_DUE = (cygrpc.OperationType.send_initial_metadata, cygrpc.OperationType.send_message, cygrpc.OperationType.send_close_from_client, cygrpc.OperationType.receive_initial_metadata, cygrpc.OperationType.receive_message, cygrpc.OperationType.receive_status_on_client,) _UNARY_STREAM_INITIAL_DUE = (cygrpc.OperationType.send_initial_metadata, cygrpc.OperationType.send_message, cygrpc.OperationType.send_close_from_client, cygrpc.OperationType.receive_initial_metadata, cygrpc.OperationType.receive_status_on_client,) _STREAM_UNARY_INITIAL_DUE = (cygrpc.OperationType.send_initial_metadata, cygrpc.OperationType.receive_initial_metadata, cygrpc.OperationType.receive_message, cygrpc.OperationType.receive_status_on_client,) _STREAM_STREAM_INITIAL_DUE = (cygrpc.OperationType.send_initial_metadata, cygrpc.OperationType.receive_initial_metadata, cygrpc.OperationType.receive_status_on_client,) _CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE = ( 'Exception calling channel subscription callback!') def _deadline(timeout): if timeout is None: return None, _INFINITE_FUTURE else: deadline = time.time() + timeout return deadline, cygrpc.Timespec(deadline) def _unknown_code_details(unknown_cygrpc_code, details): return 'Server sent unknown code {} and details "{}"'.format( unknown_cygrpc_code, details) def _wait_once_until(condition, until): if until is None: condition.wait() else: remaining = until - time.time() if remaining < 0: raise grpc.FutureTimeoutError() else: condition.wait(timeout=remaining) _INTERNAL_CALL_ERROR_MESSAGE_FORMAT = ( 'Internal gRPC call error %d. ' + 'Please report to https://github.com/grpc/grpc/issues') def _check_call_error(call_error, metadata): if call_error == cygrpc.CallError.invalid_metadata: raise ValueError('metadata was invalid: %s' % metadata) elif call_error != cygrpc.CallError.ok: raise ValueError(_INTERNAL_CALL_ERROR_MESSAGE_FORMAT % call_error) def _call_error_set_RPCstate(state, call_error, metadata): if call_error == cygrpc.CallError.invalid_metadata: _abort(state, grpc.StatusCode.INTERNAL, 'metadata was invalid: %s' % metadata) else: _abort(state, grpc.StatusCode.INTERNAL, _INTERNAL_CALL_ERROR_MESSAGE_FORMAT % call_error) class _RPCState(object): def __init__(self, due, initial_metadata, trailing_metadata, code, details): self.condition = threading.Condition() # The cygrpc.OperationType objects representing events due from the RPC's # completion queue. self.due = set(due) self.initial_metadata = initial_metadata self.response = None self.trailing_metadata = trailing_metadata self.code = code self.details = details # The semantics of grpc.Future.cancel and grpc.Future.cancelled are # slightly wonky, so they have to be tracked separately from the rest of the # result of the RPC. This field tracks whether cancellation was requested # prior to termination of the RPC. self.cancelled = False self.callbacks = [] def _abort(state, code, details): if state.code is None: state.code = code state.details = details if state.initial_metadata is None: state.initial_metadata = _common.EMPTY_METADATA state.trailing_metadata = _common.EMPTY_METADATA def _handle_event(event, state, response_deserializer): callbacks = [] for batch_operation in event.batch_operations: operation_type = batch_operation.type state.due.remove(operation_type) if operation_type == cygrpc.OperationType.receive_initial_metadata: state.initial_metadata = batch_operation.received_metadata elif operation_type == cygrpc.OperationType.receive_message: serialized_response = batch_operation.received_message.bytes() if serialized_response is not None: response = _common.deserialize(serialized_response, response_deserializer) if response is None: details = 'Exception deserializing response!' _abort(state, grpc.StatusCode.INTERNAL, details) else: state.response = response elif operation_type == cygrpc.OperationType.receive_status_on_client: state.trailing_metadata = batch_operation.received_metadata if state.code is None: code = _common.CYGRPC_STATUS_CODE_TO_STATUS_CODE.get( batch_operation.received_status_code) if code is None: state.code = grpc.StatusCode.UNKNOWN state.details = _unknown_code_details( batch_operation.received_status_code, batch_operation.received_status_details) else: state.code = code state.details = batch_operation.received_status_details callbacks.extend(state.callbacks) state.callbacks = None return callbacks def _event_handler(state, call, response_deserializer): def handle_event(event): with state.condition: callbacks = _handle_event(event, state, response_deserializer) state.condition.notify_all() done = not state.due for callback in callbacks: callback() return call if done else None return handle_event def _consume_request_iterator(request_iterator, state, call, request_serializer): event_handler = _event_handler(state, call, None) def consume_request_iterator(): while True: try: request = next(request_iterator) except StopIteration: break except Exception: # pylint: disable=broad-except logging.exception("Exception iterating requests!") call.cancel() _abort(state, grpc.StatusCode.UNKNOWN, "Exception iterating requests!") return serialized_request = _common.serialize(request, request_serializer) with state.condition: if state.code is None and not state.cancelled: if serialized_request is None: call.cancel() details = 'Exception serializing request!' _abort(state, grpc.StatusCode.INTERNAL, details) return else: operations = (cygrpc.operation_send_message( serialized_request, _EMPTY_FLAGS),) call.start_client_batch( cygrpc.Operations(operations), event_handler) state.due.add(cygrpc.OperationType.send_message) while True: state.condition.wait() if state.code is None: if cygrpc.OperationType.send_message not in state.due: break else: return else: return with state.condition: if state.code is None: operations = ( cygrpc.operation_send_close_from_client(_EMPTY_FLAGS),) call.start_client_batch( cygrpc.Operations(operations), event_handler) state.due.add(cygrpc.OperationType.send_close_from_client) def stop_consumption_thread(timeout): # pylint: disable=unused-argument with state.condition: if state.code is None: call.cancel() state.cancelled = True _abort(state, grpc.StatusCode.CANCELLED, 'Cancelled!') state.condition.notify_all() consumption_thread = _common.CleanupThread( stop_consumption_thread, target=consume_request_iterator) consumption_thread.start() class _Rendezvous(grpc.RpcError, grpc.Future, grpc.Call): def __init__(self, state, call, response_deserializer, deadline): super(_Rendezvous, self).__init__() self._state = state self._call = call self._response_deserializer = response_deserializer self._deadline = deadline def cancel(self): with self._state.condition: if self._state.code is None: self._call.cancel() self._state.cancelled = True _abort(self._state, grpc.StatusCode.CANCELLED, 'Cancelled!') self._state.condition.notify_all() return False def cancelled(self): with self._state.condition: return self._state.cancelled def running(self): with self._state.condition: return self._state.code is None def done(self): with self._state.condition: return self._state.code is not None def result(self, timeout=None): until = None if timeout is None else time.time() + timeout with self._state.condition: while True: if self._state.code is None: _wait_once_until(self._state.condition, until) elif self._state.code is grpc.StatusCode.OK: return self._state.response elif self._state.cancelled: raise grpc.FutureCancelledError() else: raise self def exception(self, timeout=None): until = None if timeout is None else time.time() + timeout with self._state.condition: while True: if self._state.code is None: _wait_once_until(self._state.condition, until) elif self._state.code is grpc.StatusCode.OK: return None elif self._state.cancelled: raise grpc.FutureCancelledError() else: return self def traceback(self, timeout=None): until = None if timeout is None else time.time() + timeout with self._state.condition: while True: if self._state.code is None: _wait_once_until(self._state.condition, until) elif self._state.code is grpc.StatusCode.OK: return None elif self._state.cancelled: raise grpc.FutureCancelledError() else: try: raise self except grpc.RpcError: return sys.exc_info()[2] def add_done_callback(self, fn): with self._state.condition: if self._state.code is None: self._state.callbacks.append(lambda: fn(self)) return fn(self) def _next(self): with self._state.condition: if self._state.code is None: event_handler = _event_handler(self._state, self._call, self._response_deserializer) self._call.start_client_batch( cygrpc.Operations( (cygrpc.operation_receive_message(_EMPTY_FLAGS),)), event_handler) self._state.due.add(cygrpc.OperationType.receive_message) elif self._state.code is grpc.StatusCode.OK: raise StopIteration() else: raise self while True: self._state.condition.wait() if self._state.response is not None: response = self._state.response self._state.response = None return response elif cygrpc.OperationType.receive_message not in self._state.due: if self._state.code is grpc.StatusCode.OK: raise StopIteration() elif self._state.code is not None: raise self def __iter__(self): return self def __next__(self): return self._next() def next(self): return self._next() def is_active(self): with self._state.condition: return self._state.code is None def time_remaining(self): if self._deadline is None: return None else: return max(self._deadline - time.time(), 0) def add_callback(self, callback): with self._state.condition: if self._state.callbacks is None: return False else: self._state.callbacks.append(callback) return True def initial_metadata(self): with self._state.condition: while self._state.initial_metadata is None: self._state.condition.wait() return _common.to_application_metadata(self._state.initial_metadata) def trailing_metadata(self): with self._state.condition: while self._state.trailing_metadata is None: self._state.condition.wait() return _common.to_application_metadata( self._state.trailing_metadata) def code(self): with self._state.condition: while self._state.code is None: self._state.condition.wait() return self._state.code def details(self): with self._state.condition: while self._state.details is None: self._state.condition.wait() return _common.decode(self._state.details) def _repr(self): with self._state.condition: if self._state.code is None: return '<_Rendezvous object of in-flight RPC>' else: return '<_Rendezvous of RPC that terminated with ({}, {})>'.format( self._state.code, _common.decode(self._state.details)) def __repr__(self): return self._repr() def __str__(self): return self._repr() def __del__(self): with self._state.condition: if self._state.code is None: self._call.cancel() self._state.cancelled = True self._state.code = grpc.StatusCode.CANCELLED self._state.condition.notify_all() def _start_unary_request(request, timeout, request_serializer): deadline, deadline_timespec = _deadline(timeout) serialized_request = _common.serialize(request, request_serializer) if serialized_request is None: state = _RPCState((), _common.EMPTY_METADATA, _common.EMPTY_METADATA, grpc.StatusCode.INTERNAL, 'Exception serializing request!') rendezvous = _Rendezvous(state, None, None, deadline) return deadline, deadline_timespec, None, rendezvous else: return deadline, deadline_timespec, serialized_request, None def _end_unary_response_blocking(state, call, with_call, deadline): if state.code is grpc.StatusCode.OK: if with_call: rendezvous = _Rendezvous(state, call, None, deadline) return state.response, rendezvous else: return state.response else: raise _Rendezvous(state, None, None, deadline) class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): def __init__(self, channel, managed_call, method, request_serializer, response_deserializer): self._channel = channel self._managed_call = managed_call self._method = method self._request_serializer = request_serializer self._response_deserializer = response_deserializer def _prepare(self, request, timeout, metadata): deadline, deadline_timespec, serialized_request, rendezvous = ( _start_unary_request(request, timeout, self._request_serializer)) if serialized_request is None: return None, None, None, None, rendezvous else: state = _RPCState(_UNARY_UNARY_INITIAL_DUE, None, None, None, None) operations = ( cygrpc.operation_send_initial_metadata( _common.to_cygrpc_metadata(metadata), _EMPTY_FLAGS), cygrpc.operation_send_message(serialized_request, _EMPTY_FLAGS), cygrpc.operation_send_close_from_client(_EMPTY_FLAGS), cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS), cygrpc.operation_receive_message(_EMPTY_FLAGS), cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS),) return state, operations, deadline, deadline_timespec, None def _blocking(self, request, timeout, metadata, credentials): state, operations, deadline, deadline_timespec, rendezvous = self._prepare( request, timeout, metadata) if rendezvous: raise rendezvous else: completion_queue = cygrpc.CompletionQueue() call = self._channel.create_call(None, 0, completion_queue, self._method, None, deadline_timespec) if credentials is not None: call.set_credentials(credentials._credentials) call_error = call.start_client_batch( cygrpc.Operations(operations), None) _check_call_error(call_error, metadata) _handle_event(completion_queue.poll(), state, self._response_deserializer) return state, call, deadline def __call__(self, request, timeout=None, metadata=None, credentials=None): state, call, deadline = self._blocking(request, timeout, metadata, credentials) return _end_unary_response_blocking(state, call, False, deadline) def with_call(self, request, timeout=None, metadata=None, credentials=None): state, call, deadline = self._blocking(request, timeout, metadata, credentials) return _end_unary_response_blocking(state, call, True, deadline) def future(self, request, timeout=None, metadata=None, credentials=None): state, operations, deadline, deadline_timespec, rendezvous = self._prepare( request, timeout, metadata) if rendezvous: return rendezvous else: call, drive_call = self._managed_call(None, 0, self._method, None, deadline_timespec) if credentials is not None: call.set_credentials(credentials._credentials) event_handler = _event_handler(state, call, self._response_deserializer) with state.condition: call_error = call.start_client_batch( cygrpc.Operations(operations), event_handler) if call_error != cygrpc.CallError.ok: _call_error_set_RPCstate(state, call_error, metadata) return _Rendezvous(state, None, None, deadline) drive_call() return _Rendezvous(state, call, self._response_deserializer, deadline) class _UnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable): def __init__(self, channel, managed_call, method, request_serializer, response_deserializer): self._channel = channel self._managed_call = managed_call self._method = method self._request_serializer = request_serializer self._response_deserializer = response_deserializer def __call__(self, request, timeout=None, metadata=None, credentials=None): deadline, deadline_timespec, serialized_request, rendezvous = ( _start_unary_request(request, timeout, self._request_serializer)) if serialized_request is None: raise rendezvous else: state = _RPCState(_UNARY_STREAM_INITIAL_DUE, None, None, None, None) call, drive_call = self._managed_call(None, 0, self._method, None, deadline_timespec) if credentials is not None: call.set_credentials(credentials._credentials) event_handler = _event_handler(state, call, self._response_deserializer) with state.condition: call.start_client_batch( cygrpc.Operations(( cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS), )), event_handler) operations = ( cygrpc.operation_send_initial_metadata( _common.to_cygrpc_metadata(metadata), _EMPTY_FLAGS), cygrpc.operation_send_message( serialized_request, _EMPTY_FLAGS), cygrpc.operation_send_close_from_client(_EMPTY_FLAGS), cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS),) call_error = call.start_client_batch( cygrpc.Operations(operations), event_handler) if call_error != cygrpc.CallError.ok: _call_error_set_RPCstate(state, call_error, metadata) return _Rendezvous(state, None, None, deadline) drive_call() return _Rendezvous(state, call, self._response_deserializer, deadline) class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): def __init__(self, channel, managed_call, method, request_serializer, response_deserializer): self._channel = channel self._managed_call = managed_call self._method = method self._request_serializer = request_serializer self._response_deserializer = response_deserializer def _blocking(self, request_iterator, timeout, metadata, credentials): deadline, deadline_timespec = _deadline(timeout) state = _RPCState(_STREAM_UNARY_INITIAL_DUE, None, None, None, None) completion_queue = cygrpc.CompletionQueue() call = self._channel.create_call(None, 0, completion_queue, self._method, None, deadline_timespec) if credentials is not None: call.set_credentials(credentials._credentials) with state.condition: call.start_client_batch( cygrpc.Operations( (cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS),)), None) operations = ( cygrpc.operation_send_initial_metadata( _common.to_cygrpc_metadata(metadata), _EMPTY_FLAGS), cygrpc.operation_receive_message(_EMPTY_FLAGS), cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS),) call_error = call.start_client_batch( cygrpc.Operations(operations), None) _check_call_error(call_error, metadata) _consume_request_iterator(request_iterator, state, call, self._request_serializer) while True: event = completion_queue.poll() with state.condition: _handle_event(event, state, self._response_deserializer) state.condition.notify_all() if not state.due: break return state, call, deadline def __call__(self, request_iterator, timeout=None, metadata=None, credentials=None): state, call, deadline = self._blocking(request_iterator, timeout, metadata, credentials) return _end_unary_response_blocking(state, call, False, deadline) def with_call(self, request_iterator, timeout=None, metadata=None, credentials=None): state, call, deadline = self._blocking(request_iterator, timeout, metadata, credentials) return _end_unary_response_blocking(state, call, True, deadline) def future(self, request_iterator, timeout=None, metadata=None, credentials=None): deadline, deadline_timespec = _deadline(timeout) state = _RPCState(_STREAM_UNARY_INITIAL_DUE, None, None, None, None) call, drive_call = self._managed_call(None, 0, self._method, None, deadline_timespec) if credentials is not None: call.set_credentials(credentials._credentials) event_handler = _event_handler(state, call, self._response_deserializer) with state.condition: call.start_client_batch( cygrpc.Operations( (cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS),)), event_handler) operations = ( cygrpc.operation_send_initial_metadata( _common.to_cygrpc_metadata(metadata), _EMPTY_FLAGS), cygrpc.operation_receive_message(_EMPTY_FLAGS), cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS),) call_error = call.start_client_batch( cygrpc.Operations(operations), event_handler) if call_error != cygrpc.CallError.ok: _call_error_set_RPCstate(state, call_error, metadata) return _Rendezvous(state, None, None, deadline) drive_call() _consume_request_iterator(request_iterator, state, call, self._request_serializer) return _Rendezvous(state, call, self._response_deserializer, deadline) class _StreamStreamMultiCallable(grpc.StreamStreamMultiCallable): def __init__(self, channel, managed_call, method, request_serializer, response_deserializer): self._channel = channel self._managed_call = managed_call self._method = method self._request_serializer = request_serializer self._response_deserializer = response_deserializer def __call__(self, request_iterator, timeout=None, metadata=None, credentials=None): deadline, deadline_timespec = _deadline(timeout) state = _RPCState(_STREAM_STREAM_INITIAL_DUE, None, None, None, None) call, drive_call = self._managed_call(None, 0, self._method, None, deadline_timespec) if credentials is not None: call.set_credentials(credentials._credentials) event_handler = _event_handler(state, call, self._response_deserializer) with state.condition: call.start_client_batch( cygrpc.Operations( (cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS),)), event_handler) operations = ( cygrpc.operation_send_initial_metadata( _common.to_cygrpc_metadata(metadata), _EMPTY_FLAGS), cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS),) call_error = call.start_client_batch( cygrpc.Operations(operations), event_handler) if call_error != cygrpc.CallError.ok: _call_error_set_RPCstate(state, call_error, metadata) return _Rendezvous(state, None, None, deadline) drive_call() _consume_request_iterator(request_iterator, state, call, self._request_serializer) return _Rendezvous(state, call, self._response_deserializer, deadline) class _ChannelCallState(object): def __init__(self, channel): self.lock = threading.Lock() self.channel = channel self.completion_queue = cygrpc.CompletionQueue() self.managed_calls = None def _run_channel_spin_thread(state): def channel_spin(): while True: event = state.completion_queue.poll() completed_call = event.tag(event) if completed_call is not None: with state.lock: state.managed_calls.remove(completed_call) if not state.managed_calls: state.managed_calls = None return def stop_channel_spin(timeout): # pylint: disable=unused-argument with state.lock: if state.managed_calls is not None: for call in state.managed_calls: call.cancel() channel_spin_thread = _common.CleanupThread( stop_channel_spin, target=channel_spin) channel_spin_thread.start() def _channel_managed_call_management(state): def create(parent, flags, method, host, deadline): """Creates a managed cygrpc.Call and a function to call to drive it. If operations are successfully added to the returned cygrpc.Call, the returned function must be called. If operations are not successfully added to the returned cygrpc.Call, the returned function must not be called. Args: parent: A cygrpc.Call to be used as the parent of the created call. flags: An integer bitfield of call flags. method: The RPC method. host: A host string for the created call. deadline: A cygrpc.Timespec to be the deadline of the created call. Returns: A cygrpc.Call with which to conduct an RPC and a function to call if operations are successfully started on the call. """ call = state.channel.create_call(parent, flags, state.completion_queue, method, host, deadline) def drive(): with state.lock: if state.managed_calls is None: state.managed_calls = set((call,)) _run_channel_spin_thread(state) else: state.managed_calls.add(call) return call, drive return create class _ChannelConnectivityState(object): def __init__(self, channel): self.lock = threading.Lock() self.channel = channel self.polling = False self.connectivity = None self.try_to_connect = False self.callbacks_and_connectivities = [] self.delivering = False def _deliveries(state): callbacks_needing_update = [] for callback_and_connectivity in state.callbacks_and_connectivities: callback, callback_connectivity, = callback_and_connectivity if callback_connectivity is not state.connectivity: callbacks_needing_update.append(callback) callback_and_connectivity[1] = state.connectivity return callbacks_needing_update def _deliver(state, initial_connectivity, initial_callbacks): connectivity = initial_connectivity callbacks = initial_callbacks while True: for callback in callbacks: callable_util.call_logging_exceptions( callback, _CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE, connectivity) with state.lock: callbacks = _deliveries(state) if callbacks: connectivity = state.connectivity else: state.delivering = False return def _spawn_delivery(state, callbacks): delivering_thread = threading.Thread( target=_deliver, args=(state, state.connectivity, callbacks,)) delivering_thread.start() state.delivering = True # NOTE(https://github.com/grpc/grpc/issues/3064): We'd rather not poll. def _poll_connectivity(state, channel, initial_try_to_connect): try_to_connect = initial_try_to_connect connectivity = channel.check_connectivity_state(try_to_connect) with state.lock: state.connectivity = ( _common.CYGRPC_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY[ connectivity]) callbacks = tuple(callback for callback, unused_but_known_to_be_none_connectivity in state.callbacks_and_connectivities) for callback_and_connectivity in state.callbacks_and_connectivities: callback_and_connectivity[1] = state.connectivity if callbacks: _spawn_delivery(state, callbacks) completion_queue = cygrpc.CompletionQueue() while True: channel.watch_connectivity_state(connectivity, cygrpc.Timespec(time.time() + 0.2), completion_queue, None) event = completion_queue.poll() with state.lock: if not state.callbacks_and_connectivities and not state.try_to_connect: state.polling = False state.connectivity = None break try_to_connect = state.try_to_connect state.try_to_connect = False if event.success or try_to_connect: connectivity = channel.check_connectivity_state(try_to_connect) with state.lock: state.connectivity = ( _common.CYGRPC_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY[ connectivity]) if not state.delivering: callbacks = _deliveries(state) if callbacks: _spawn_delivery(state, callbacks) def _moot(state): with state.lock: del state.callbacks_and_connectivities[:] def _subscribe(state, callback, try_to_connect): with state.lock: if not state.callbacks_and_connectivities and not state.polling: polling_thread = _common.CleanupThread( lambda timeout: _moot(state), target=_poll_connectivity, args=(state, state.channel, bool(try_to_connect))) polling_thread.start() state.polling = True state.callbacks_and_connectivities.append([callback, None]) elif not state.delivering and state.connectivity is not None: _spawn_delivery(state, (callback,)) state.try_to_connect |= bool(try_to_connect) state.callbacks_and_connectivities.append( [callback, state.connectivity]) else: state.try_to_connect |= bool(try_to_connect) state.callbacks_and_connectivities.append([callback, None]) def _unsubscribe(state, callback): with state.lock: for index, (subscribed_callback, unused_connectivity ) in enumerate(state.callbacks_and_connectivities): if callback == subscribed_callback: state.callbacks_and_connectivities.pop(index) break def _options(options): return list(options) + [ (cygrpc.ChannelArgKey.primary_user_agent_string, _USER_AGENT) ] class Channel(grpc.Channel): """A cygrpc.Channel-backed implementation of grpc.Channel.""" def __init__(self, target, options, credentials): """Constructor. Args: target: The target to which to connect. options: Configuration options for the channel. credentials: A cygrpc.ChannelCredentials or None. """ self._channel = cygrpc.Channel( _common.encode(target), _common.channel_args(_options(options)), credentials) self._call_state = _ChannelCallState(self._channel) self._connectivity_state = _ChannelConnectivityState(self._channel) def subscribe(self, callback, try_to_connect=None): _subscribe(self._connectivity_state, callback, try_to_connect) def unsubscribe(self, callback): _unsubscribe(self._connectivity_state, callback) def unary_unary(self, method, request_serializer=None, response_deserializer=None): return _UnaryUnaryMultiCallable( self._channel, _channel_managed_call_management(self._call_state), _common.encode(method), request_serializer, response_deserializer) def unary_stream(self, method, request_serializer=None, response_deserializer=None): return _UnaryStreamMultiCallable( self._channel, _channel_managed_call_management(self._call_state), _common.encode(method), request_serializer, response_deserializer) def stream_unary(self, method, request_serializer=None, response_deserializer=None): return _StreamUnaryMultiCallable( self._channel, _channel_managed_call_management(self._call_state), _common.encode(method), request_serializer, response_deserializer) def stream_stream(self, method, request_serializer=None, response_deserializer=None): return _StreamStreamMultiCallable( self._channel, _channel_managed_call_management(self._call_state), _common.encode(method), request_serializer, response_deserializer) def __del__(self): _moot(self._connectivity_state) grpc-1.3.2/src/python/grpcio/grpc/_common.py000066400000000000000000000146721310511640000210000ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Shared implementation.""" import logging import threading import time import six import grpc from grpc._cython import cygrpc EMPTY_METADATA = cygrpc.Metadata(()) CYGRPC_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY = { cygrpc.ConnectivityState.idle: grpc.ChannelConnectivity.IDLE, cygrpc.ConnectivityState.connecting: grpc.ChannelConnectivity.CONNECTING, cygrpc.ConnectivityState.ready: grpc.ChannelConnectivity.READY, cygrpc.ConnectivityState.transient_failure: grpc.ChannelConnectivity.TRANSIENT_FAILURE, cygrpc.ConnectivityState.shutdown: grpc.ChannelConnectivity.SHUTDOWN, } CYGRPC_STATUS_CODE_TO_STATUS_CODE = { cygrpc.StatusCode.ok: grpc.StatusCode.OK, cygrpc.StatusCode.cancelled: grpc.StatusCode.CANCELLED, cygrpc.StatusCode.unknown: grpc.StatusCode.UNKNOWN, cygrpc.StatusCode.invalid_argument: grpc.StatusCode.INVALID_ARGUMENT, cygrpc.StatusCode.deadline_exceeded: grpc.StatusCode.DEADLINE_EXCEEDED, cygrpc.StatusCode.not_found: grpc.StatusCode.NOT_FOUND, cygrpc.StatusCode.already_exists: grpc.StatusCode.ALREADY_EXISTS, cygrpc.StatusCode.permission_denied: grpc.StatusCode.PERMISSION_DENIED, cygrpc.StatusCode.unauthenticated: grpc.StatusCode.UNAUTHENTICATED, cygrpc.StatusCode.resource_exhausted: grpc.StatusCode.RESOURCE_EXHAUSTED, cygrpc.StatusCode.failed_precondition: grpc.StatusCode.FAILED_PRECONDITION, cygrpc.StatusCode.aborted: grpc.StatusCode.ABORTED, cygrpc.StatusCode.out_of_range: grpc.StatusCode.OUT_OF_RANGE, cygrpc.StatusCode.unimplemented: grpc.StatusCode.UNIMPLEMENTED, cygrpc.StatusCode.internal: grpc.StatusCode.INTERNAL, cygrpc.StatusCode.unavailable: grpc.StatusCode.UNAVAILABLE, cygrpc.StatusCode.data_loss: grpc.StatusCode.DATA_LOSS, } STATUS_CODE_TO_CYGRPC_STATUS_CODE = { grpc_code: cygrpc_code for cygrpc_code, grpc_code in six.iteritems( CYGRPC_STATUS_CODE_TO_STATUS_CODE) } def encode(s): if isinstance(s, bytes): return s else: return s.encode('ascii') def decode(b): if isinstance(b, str): return b else: try: return b.decode('utf8') except UnicodeDecodeError: logging.exception('Invalid encoding on %s', b) return b.decode('latin1') def channel_args(options): cygrpc_args = [] for key, value in options: if isinstance(value, six.string_types): cygrpc_args.append(cygrpc.ChannelArg(encode(key), encode(value))) else: cygrpc_args.append(cygrpc.ChannelArg(encode(key), value)) return cygrpc.ChannelArgs(cygrpc_args) def to_cygrpc_metadata(application_metadata): return EMPTY_METADATA if application_metadata is None else cygrpc.Metadata( cygrpc.Metadatum(encode(key), encode(value)) for key, value in application_metadata) def to_application_metadata(cygrpc_metadata): if cygrpc_metadata is None: return () else: return tuple((decode(key), value if key[-4:] == b'-bin' else decode(value)) for key, value in cygrpc_metadata) def _transform(message, transformer, exception_message): if transformer is None: return message else: try: return transformer(message) except Exception: # pylint: disable=broad-except logging.exception(exception_message) return None def serialize(message, serializer): return _transform(message, serializer, 'Exception serializing message!') def deserialize(serialized_message, deserializer): return _transform(serialized_message, deserializer, 'Exception deserializing message!') def fully_qualified_method(group, method): return '/{}/{}'.format(group, method) class CleanupThread(threading.Thread): """A threading.Thread subclass supporting custom behavior on join(). On Python Interpreter exit, Python will attempt to join outstanding threads prior to garbage collection. We may need to do additional cleanup, and we accomplish this by overriding the join() method. """ def __init__(self, behavior, *args, **kwargs): """Constructor. Args: behavior (function): Function called on join() with a single argument, timeout, indicating the maximum duration of `behavior`, or None indicating `behavior` has no deadline. `behavior` must be idempotent. args: Positional arguments passed to threading.Thread constructor. kwargs: Keyword arguments passed to threading.Thread constructor. """ super(CleanupThread, self).__init__(*args, **kwargs) self._behavior = behavior def join(self, timeout=None): start_time = time.time() self._behavior(timeout) end_time = time.time() if timeout is not None: timeout -= end_time - start_time timeout = max(timeout, 0) super(CleanupThread, self).join(timeout) grpc-1.3.2/src/python/grpcio/grpc/_credential_composition.py000066400000000000000000000041721310511640000242370ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from grpc._cython import cygrpc def _call(call_credentialses): call_credentials_iterator = iter(call_credentialses) composition = next(call_credentials_iterator) for additional_call_credentials in call_credentials_iterator: composition = cygrpc.call_credentials_composite( composition, additional_call_credentials) return composition def call(call_credentialses): return _call(call_credentialses) def channel(channel_credentials, call_credentialses): return cygrpc.channel_credentials_composite(channel_credentials, _call(call_credentialses)) grpc-1.3.2/src/python/grpcio/grpc/_cython/000077500000000000000000000000001310511640000204305ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio/grpc/_cython/.gitignore000066400000000000000000000000441310511640000224160ustar00rootroot00000000000000cygrpc.c *.a *.so *.dll *.pyc *.pyd grpc-1.3.2/src/python/grpcio/grpc/_cython/README.rst000066400000000000000000000043061310511640000221220ustar00rootroot00000000000000GRPC Python Cython layer ======================== Package for the GRPC Python Cython layer. What is Cython? --------------- Cython is both a superset of the Python language with extensions for dealing with C types and a tool that transpiles this superset into C code. It provides convenient means of statically typing expressions and of converting Python strings to pointers (among other niceties), thus dramatically smoothing the Python/C interop by allowing fluid use of APIs in both from the same source. See the wonderful `Cython website`_. Why Cython? ----------- - **Python 2 and 3 support** Cython generated C code has precompiler macros to target both Python 2 and Python 3 C APIs, even while acting as a superset of just the Python 2 language (e.g. using ``basestring``). - **Significantly less semantic noise** A lot of CPython code is just glue, especially human-error-prone ``Py_INCREF``-ing and ``Py_DECREF``-ing around error handlers and such. Cython takes care of that automagically. - **Possible PyPy support** One of the major developments in Cython over the past few years was the addition of support for PyPy. We might soon be able to provide such support ourselves through our use of Cython. - **Less Python glue code** There existed several adapter layers in and around the original CPython code to smooth the surface exposed to Python due to how much trouble it was to make such a smooth surface via the CPython API alone. Cython makes writing such a surface incredibly easy, so these adapter layers may be removed. Implications for Users ---------------------- Nothing additional will be required for users. PyPI packages will contain Cython generated C code and thus not necessitate a Cython installation. Implications for GRPC Developers -------------------------------- A typical edit-compile-debug cycle now requires Cython. We install Cython in the ``virtualenv`` generated for the Python tests in this repository, so initial test runs may take an extra 2+ minutes to complete. Subsequent test runs won't reinstall ``Cython`` (unless required versions change and the ``virtualenv`` doesn't have installed versions that satisfy the change). .. _`Cython website`: http://cython.org/ grpc-1.3.2/src/python/grpcio/grpc/_cython/__init__.py000066400000000000000000000027701310511640000225470ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio/grpc/_cython/_cygrpc/000077500000000000000000000000001310511640000220565ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio/grpc/_cython/_cygrpc/__init__.py000066400000000000000000000027701310511640000241750ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio/grpc/_cython/_cygrpc/call.pxd.pxi000066400000000000000000000030751310511640000243120ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cdef class Call: cdef grpc_call *c_call cdef list references grpc-1.3.2/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi000066400000000000000000000101651310511640000243350ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cimport cpython cdef class Call: def __cinit__(self): # Create an *empty* call grpc_init() self.c_call = NULL self.references = [] def _start_batch(self, operations, tag, retain_self): if not self.is_valid: raise ValueError("invalid call object cannot be used from Python") cdef grpc_call_error result cdef Operations cy_operations = Operations(operations) cdef OperationTag operation_tag = OperationTag(tag) if retain_self: operation_tag.operation_call = self else: operation_tag.operation_call = None operation_tag.batch_operations = cy_operations cpython.Py_INCREF(operation_tag) with nogil: result = grpc_call_start_batch( self.c_call, cy_operations.c_ops, cy_operations.c_nops, operation_tag, NULL) return result def start_client_batch(self, operations, tag): # We don't reference this call in the operations tag because # it should be cancelled when it goes out of scope return self._start_batch(operations, tag, False) def start_server_batch(self, operations, tag): return self._start_batch(operations, tag, True) def cancel( self, grpc_status_code error_code=GRPC_STATUS__DO_NOT_USE, details=None): details = str_to_bytes(details) if not self.is_valid: raise ValueError("invalid call object cannot be used from Python") if (details is None) != (error_code == GRPC_STATUS__DO_NOT_USE): raise ValueError("if error_code is specified, so must details " "(and vice-versa)") cdef grpc_call_error result cdef char *c_details = NULL if error_code != GRPC_STATUS__DO_NOT_USE: self.references.append(details) c_details = details with nogil: result = grpc_call_cancel_with_status( self.c_call, error_code, c_details, NULL) return result else: with nogil: result = grpc_call_cancel(self.c_call, NULL) return result def set_credentials( self, CallCredentials call_credentials not None): cdef grpc_call_error result with nogil: result = grpc_call_set_credentials( self.c_call, call_credentials.c_credentials) return result def peer(self): cdef char *peer = NULL with nogil: peer = grpc_call_get_peer(self.c_call) result = peer with nogil: gpr_free(peer) return result def __dealloc__(self): if self.c_call != NULL: grpc_call_destroy(self.c_call) grpc_shutdown() # The object *should* always be valid from Python. Used for debugging. @property def is_valid(self): return self.c_call != NULL grpc-1.3.2/src/python/grpcio/grpc/_cython/_cygrpc/channel.pxd.pxi000066400000000000000000000031051310511640000250010ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cdef class Channel: cdef grpc_channel *c_channel cdef list references grpc-1.3.2/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi000066400000000000000000000106311310511640000250300ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cimport cpython cdef class Channel: def __cinit__(self, bytes target, ChannelArgs arguments, ChannelCredentials channel_credentials=None): grpc_init() cdef grpc_channel_args *c_arguments = NULL cdef char *c_target = NULL self.c_channel = NULL self.references = [] if len(arguments) > 0: c_arguments = &arguments.c_args self.references.append(arguments) c_target = target if channel_credentials is None: with nogil: self.c_channel = grpc_insecure_channel_create(c_target, c_arguments, NULL) else: with nogil: self.c_channel = grpc_secure_channel_create( channel_credentials.c_credentials, c_target, c_arguments, NULL) self.references.append(channel_credentials) self.references.append(target) self.references.append(arguments) def create_call(self, Call parent, int flags, CompletionQueue queue not None, method, host, Timespec deadline not None): if queue.is_shutting_down: raise ValueError("queue must not be shutting down or shutdown") cdef grpc_slice method_slice = _slice_from_bytes(method) cdef grpc_slice host_slice cdef grpc_slice *host_slice_ptr = NULL if host is not None: host_slice = _slice_from_bytes(host) host_slice_ptr = &host_slice cdef Call operation_call = Call() operation_call.references = [self, queue] cdef grpc_call *parent_call = NULL if parent is not None: parent_call = parent.c_call with nogil: operation_call.c_call = grpc_channel_create_call( self.c_channel, parent_call, flags, queue.c_completion_queue, method_slice, host_slice_ptr, deadline.c_time, NULL) grpc_slice_unref(method_slice) if host_slice_ptr: grpc_slice_unref(host_slice) return operation_call def check_connectivity_state(self, bint try_to_connect): cdef grpc_connectivity_state result with nogil: result = grpc_channel_check_connectivity_state(self.c_channel, try_to_connect) return result def watch_connectivity_state( self, grpc_connectivity_state last_observed_state, Timespec deadline not None, CompletionQueue queue not None, tag): cdef OperationTag operation_tag = OperationTag(tag) cpython.Py_INCREF(operation_tag) with nogil: grpc_channel_watch_connectivity_state( self.c_channel, last_observed_state, deadline.c_time, queue.c_completion_queue, operation_tag) def target(self): cdef char *target = NULL with nogil: target = grpc_channel_get_target(self.c_channel) result = target with nogil: gpr_free(target) return result def __dealloc__(self): if self.c_channel != NULL: grpc_channel_destroy(self.c_channel) grpc_shutdown() grpc-1.3.2/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pxd.pxi000066400000000000000000000032561310511640000267550ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cdef class CompletionQueue: cdef grpc_completion_queue *c_completion_queue cdef bint is_shutting_down cdef bint is_shutdown cdef _interpret_event(self, grpc_event event) grpc-1.3.2/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi000066400000000000000000000130421310511640000267740ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cimport cpython import threading import time cdef int _INTERRUPT_CHECK_PERIOD_MS = 200 cdef class CompletionQueue: def __cinit__(self): grpc_init() with nogil: self.c_completion_queue = grpc_completion_queue_create(NULL) self.is_shutting_down = False self.is_shutdown = False cdef _interpret_event(self, grpc_event event): cdef OperationTag tag = None cdef object user_tag = None cdef Call operation_call = None cdef CallDetails request_call_details = None cdef Metadata request_metadata = None cdef Operations batch_operations = None cdef Operation batch_operation = None if event.type == GRPC_QUEUE_TIMEOUT: return Event( event.type, False, None, None, None, None, False, None) elif event.type == GRPC_QUEUE_SHUTDOWN: self.is_shutdown = True return Event( event.type, True, None, None, None, None, False, None) else: if event.tag != NULL: tag = event.tag # We receive event tags only after they've been inc-ref'd elsewhere in # the code. cpython.Py_DECREF(tag) if tag.shutting_down_server is not None: tag.shutting_down_server.notify_shutdown_complete() user_tag = tag.user_tag operation_call = tag.operation_call request_call_details = tag.request_call_details if tag.request_metadata is not None: request_metadata = tag.request_metadata request_metadata._claim_slice_ownership() batch_operations = tag.batch_operations if tag.batch_operations is not None: for op in batch_operations.operations: batch_operation = op if batch_operation._received_metadata is not None: batch_operation._received_metadata._claim_slice_ownership() if tag.is_new_request: # Stuff in the tag not explicitly handled by us needs to live through # the life of the call operation_call.references.extend(tag.references) return Event( event.type, event.success, user_tag, operation_call, request_call_details, request_metadata, tag.is_new_request, batch_operations) def poll(self, Timespec deadline=None): # We name this 'poll' to avoid problems with CPython's expectations for # 'special' methods (like next and __next__). cdef gpr_timespec c_increment cdef gpr_timespec c_timeout cdef gpr_timespec c_deadline with nogil: c_increment = gpr_time_from_millis(_INTERRUPT_CHECK_PERIOD_MS, GPR_TIMESPAN) c_deadline = gpr_inf_future(GPR_CLOCK_REALTIME) if deadline is not None: c_deadline = deadline.c_time while True: c_timeout = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c_increment) if gpr_time_cmp(c_timeout, c_deadline) > 0: c_timeout = c_deadline event = grpc_completion_queue_next( self.c_completion_queue, c_timeout, NULL) if event.type != GRPC_QUEUE_TIMEOUT or gpr_time_cmp(c_timeout, c_deadline) == 0: break; # Handle any signals with gil: cpython.PyErr_CheckSignals() return self._interpret_event(event) def shutdown(self): with nogil: grpc_completion_queue_shutdown(self.c_completion_queue) self.is_shutting_down = True def clear(self): if not self.is_shutting_down: raise ValueError('queue must be shutting down to be cleared') while self.poll().type != GRPC_QUEUE_SHUTDOWN: pass def __dealloc__(self): cdef gpr_timespec c_deadline c_deadline = gpr_inf_future(GPR_CLOCK_REALTIME) if self.c_completion_queue != NULL: # Ensure shutdown if not self.is_shutting_down: grpc_completion_queue_shutdown(self.c_completion_queue) # Pump the queue (All outstanding calls should have been cancelled) while not self.is_shutdown: event = grpc_completion_queue_next( self.c_completion_queue, c_deadline, NULL) self._interpret_event(event) grpc_completion_queue_destroy(self.c_completion_queue) grpc_shutdown() grpc-1.3.2/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pxd.pxi000066400000000000000000000046411310511640000256740ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cimport cpython cdef class ChannelCredentials: cdef grpc_channel_credentials *c_credentials cdef grpc_ssl_pem_key_cert_pair c_ssl_pem_key_cert_pair cdef list references cdef class CallCredentials: cdef grpc_call_credentials *c_credentials cdef list references cdef class ServerCredentials: cdef grpc_server_credentials *c_credentials cdef grpc_ssl_pem_key_cert_pair *c_ssl_pem_key_cert_pairs cdef size_t c_ssl_pem_key_cert_pairs_count cdef list references cdef class CredentialsMetadataPlugin: cdef object plugin_callback cdef bytes plugin_name cdef grpc_metadata_credentials_plugin make_c_plugin(self) cdef class AuthMetadataContext: cdef grpc_auth_metadata_context context cdef void plugin_get_metadata( void *state, grpc_auth_metadata_context context, grpc_credentials_plugin_metadata_cb cb, void *user_data) with gil cdef void plugin_destroy_c_plugin_state(void *state) with gil grpc-1.3.2/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi000066400000000000000000000260201310511640000257140ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cimport cpython import traceback cdef class ChannelCredentials: def __cinit__(self): grpc_init() self.c_credentials = NULL self.c_ssl_pem_key_cert_pair.private_key = NULL self.c_ssl_pem_key_cert_pair.certificate_chain = NULL self.references = [] # The object *can* be invalid in Python if we fail to make the credentials # (and the core thus returns NULL credentials). Used primarily for debugging. @property def is_valid(self): return self.c_credentials != NULL def __dealloc__(self): if self.c_credentials != NULL: grpc_channel_credentials_release(self.c_credentials) grpc_shutdown() cdef class CallCredentials: def __cinit__(self): grpc_init() self.c_credentials = NULL self.references = [] # The object *can* be invalid in Python if we fail to make the credentials # (and the core thus returns NULL credentials). Used primarily for debugging. @property def is_valid(self): return self.c_credentials != NULL def __dealloc__(self): if self.c_credentials != NULL: grpc_call_credentials_release(self.c_credentials) grpc_shutdown() cdef class ServerCredentials: def __cinit__(self): grpc_init() self.c_credentials = NULL self.references = [] def __dealloc__(self): if self.c_credentials != NULL: grpc_server_credentials_release(self.c_credentials) grpc_shutdown() cdef class CredentialsMetadataPlugin: def __cinit__(self, object plugin_callback, bytes name): """ Args: plugin_callback (callable): Callback accepting a service URL (str/bytes) and callback object (accepting a Metadata, grpc_status_code, and a str/bytes error message). This argument when called should be non-blocking and eventually call the callback object with the appropriate status code/details and metadata (if successful). name (bytes): Plugin name. """ grpc_init() if not callable(plugin_callback): raise ValueError('expected callable plugin_callback') self.plugin_callback = plugin_callback self.plugin_name = name @staticmethod cdef grpc_metadata_credentials_plugin make_c_plugin(self): cdef grpc_metadata_credentials_plugin result result.get_metadata = plugin_get_metadata result.destroy = plugin_destroy_c_plugin_state result.state = self result.type = self.plugin_name cpython.Py_INCREF(self) return result def __dealloc__(self): grpc_shutdown() cdef class AuthMetadataContext: def __cinit__(self): grpc_init() self.context.service_url = NULL self.context.method_name = NULL @property def service_url(self): return self.context.service_url @property def method_name(self): return self.context.method_name def __dealloc__(self): grpc_shutdown() cdef void plugin_get_metadata( void *state, grpc_auth_metadata_context context, grpc_credentials_plugin_metadata_cb cb, void *user_data) with gil: called_flag = [False] def python_callback( Metadata metadata, grpc_status_code status, bytes error_details): cb(user_data, metadata.c_metadata_array.metadata, metadata.c_metadata_array.count, status, error_details) called_flag[0] = True cdef CredentialsMetadataPlugin self = state cdef AuthMetadataContext cy_context = AuthMetadataContext() cy_context.context = context try: self.plugin_callback(cy_context, python_callback) except Exception as error: if not called_flag[0]: cb(user_data, Metadata([]).c_metadata_array.metadata, 0, StatusCode.unknown, traceback.format_exc().encode()) cdef void plugin_destroy_c_plugin_state(void *state) with gil: cpython.Py_DECREF(state) def channel_credentials_google_default(): cdef ChannelCredentials credentials = ChannelCredentials(); with nogil: credentials.c_credentials = grpc_google_default_credentials_create() return credentials def channel_credentials_ssl(pem_root_certificates, SslPemKeyCertPair ssl_pem_key_cert_pair): pem_root_certificates = str_to_bytes(pem_root_certificates) cdef ChannelCredentials credentials = ChannelCredentials() cdef const char *c_pem_root_certificates = NULL if pem_root_certificates is not None: c_pem_root_certificates = pem_root_certificates credentials.references.append(pem_root_certificates) if ssl_pem_key_cert_pair is not None: with nogil: credentials.c_credentials = grpc_ssl_credentials_create( c_pem_root_certificates, &ssl_pem_key_cert_pair.c_pair, NULL) credentials.references.append(ssl_pem_key_cert_pair) else: with nogil: credentials.c_credentials = grpc_ssl_credentials_create( c_pem_root_certificates, NULL, NULL) return credentials def channel_credentials_composite( ChannelCredentials credentials_1 not None, CallCredentials credentials_2 not None): if not credentials_1.is_valid or not credentials_2.is_valid: raise ValueError("passed credentials must both be valid") cdef ChannelCredentials credentials = ChannelCredentials() with nogil: credentials.c_credentials = grpc_composite_channel_credentials_create( credentials_1.c_credentials, credentials_2.c_credentials, NULL) credentials.references.append(credentials_1) credentials.references.append(credentials_2) return credentials def call_credentials_composite( CallCredentials credentials_1 not None, CallCredentials credentials_2 not None): if not credentials_1.is_valid or not credentials_2.is_valid: raise ValueError("passed credentials must both be valid") cdef CallCredentials credentials = CallCredentials() with nogil: credentials.c_credentials = grpc_composite_call_credentials_create( credentials_1.c_credentials, credentials_2.c_credentials, NULL) credentials.references.append(credentials_1) credentials.references.append(credentials_2) return credentials def call_credentials_google_compute_engine(): cdef CallCredentials credentials = CallCredentials() with nogil: credentials.c_credentials = ( grpc_google_compute_engine_credentials_create(NULL)) return credentials def call_credentials_service_account_jwt_access( json_key, Timespec token_lifetime not None): json_key = str_to_bytes(json_key) cdef CallCredentials credentials = CallCredentials() cdef char *json_key_c_string = json_key with nogil: credentials.c_credentials = ( grpc_service_account_jwt_access_credentials_create( json_key_c_string, token_lifetime.c_time, NULL)) credentials.references.append(json_key) return credentials def call_credentials_google_refresh_token(json_refresh_token): json_refresh_token = str_to_bytes(json_refresh_token) cdef CallCredentials credentials = CallCredentials() cdef char *json_refresh_token_c_string = json_refresh_token with nogil: credentials.c_credentials = grpc_google_refresh_token_credentials_create( json_refresh_token_c_string, NULL) credentials.references.append(json_refresh_token) return credentials def call_credentials_google_iam(authorization_token, authority_selector): authorization_token = str_to_bytes(authorization_token) authority_selector = str_to_bytes(authority_selector) cdef CallCredentials credentials = CallCredentials() cdef char *authorization_token_c_string = authorization_token cdef char *authority_selector_c_string = authority_selector with nogil: credentials.c_credentials = grpc_google_iam_credentials_create( authorization_token_c_string, authority_selector_c_string, NULL) credentials.references.append(authorization_token) credentials.references.append(authority_selector) return credentials def call_credentials_metadata_plugin(CredentialsMetadataPlugin plugin): cdef CallCredentials credentials = CallCredentials() cdef grpc_metadata_credentials_plugin c_plugin = plugin.make_c_plugin() with nogil: credentials.c_credentials = ( grpc_metadata_credentials_create_from_plugin(c_plugin, NULL)) # TODO(atash): the following held reference is *probably* never necessary credentials.references.append(plugin) return credentials def server_credentials_ssl(pem_root_certs, pem_key_cert_pairs, bint force_client_auth): pem_root_certs = str_to_bytes(pem_root_certs) cdef char *c_pem_root_certs = NULL if pem_root_certs is not None: c_pem_root_certs = pem_root_certs pem_key_cert_pairs = list(pem_key_cert_pairs) for pair in pem_key_cert_pairs: if not isinstance(pair, SslPemKeyCertPair): raise TypeError("expected pem_key_cert_pairs to be sequence of " "SslPemKeyCertPair") cdef ServerCredentials credentials = ServerCredentials() credentials.references.append(pem_key_cert_pairs) credentials.references.append(pem_root_certs) credentials.c_ssl_pem_key_cert_pairs_count = len(pem_key_cert_pairs) with nogil: credentials.c_ssl_pem_key_cert_pairs = ( gpr_malloc( sizeof(grpc_ssl_pem_key_cert_pair) * credentials.c_ssl_pem_key_cert_pairs_count )) for i in range(credentials.c_ssl_pem_key_cert_pairs_count): credentials.c_ssl_pem_key_cert_pairs[i] = ( (pem_key_cert_pairs[i]).c_pair) credentials.c_credentials = grpc_ssl_server_credentials_create( c_pem_root_certs, credentials.c_ssl_pem_key_cert_pairs, credentials.c_ssl_pem_key_cert_pairs_count, GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY if force_client_auth else GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, NULL) return credentials grpc-1.3.2/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi000066400000000000000000000446301310511640000235420ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cimport libc.time # Typedef types with approximately the same semantics to provide their names to # Cython ctypedef int int32_t ctypedef unsigned uint32_t ctypedef long int64_t cdef extern from "grpc/support/alloc.h": void *gpr_malloc(size_t size) nogil void gpr_free(void *ptr) nogil void *gpr_realloc(void *p, size_t size) nogil cdef extern from "grpc/byte_buffer_reader.h": struct grpc_byte_buffer_reader: # We don't care about the internals pass cdef extern from "grpc/impl/codegen/exec_ctx_fwd.h": struct grpc_exec_ctx: # We don't care about the internals pass cdef extern from "grpc/grpc.h": ctypedef struct grpc_slice: # don't worry about writing out the members of grpc_slice; we never access # them directly. pass grpc_slice grpc_slice_ref(grpc_slice s) nogil void grpc_slice_unref(grpc_slice s) nogil grpc_slice grpc_empty_slice() nogil grpc_slice grpc_slice_new(void *p, size_t len, void (*destroy)(void *)) nogil grpc_slice grpc_slice_new_with_len( void *p, size_t len, void (*destroy)(void *, size_t)) nogil grpc_slice grpc_slice_malloc(size_t length) nogil grpc_slice grpc_slice_from_copied_string(const char *source) nogil grpc_slice grpc_slice_from_copied_buffer(const char *source, size_t len) nogil # Declare functions for function-like macros (because Cython)... void *grpc_slice_start_ptr "GRPC_SLICE_START_PTR" (grpc_slice s) nogil size_t grpc_slice_length "GRPC_SLICE_LENGTH" (grpc_slice s) nogil ctypedef enum gpr_clock_type: GPR_CLOCK_MONOTONIC GPR_CLOCK_REALTIME GPR_CLOCK_PRECISE GPR_TIMESPAN ctypedef struct gpr_timespec: int64_t seconds "tv_sec" int32_t nanoseconds "tv_nsec" gpr_clock_type clock_type gpr_timespec gpr_time_0(gpr_clock_type type) nogil gpr_timespec gpr_inf_future(gpr_clock_type type) nogil gpr_timespec gpr_inf_past(gpr_clock_type type) nogil gpr_timespec gpr_now(gpr_clock_type clock) nogil gpr_timespec gpr_convert_clock_type(gpr_timespec t, gpr_clock_type target_clock) nogil gpr_timespec gpr_time_from_millis(int64_t ms, gpr_clock_type type) nogil gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b) nogil int gpr_time_cmp(gpr_timespec a, gpr_timespec b) nogil ctypedef struct grpc_byte_buffer: # We don't care about the internals. pass grpc_byte_buffer *grpc_raw_byte_buffer_create(grpc_slice *slices, size_t nslices) nogil size_t grpc_byte_buffer_length(grpc_byte_buffer *bb) nogil void grpc_byte_buffer_destroy(grpc_byte_buffer *byte_buffer) nogil int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader, grpc_byte_buffer *buffer) nogil int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader *reader, grpc_slice *slice) nogil void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader) nogil ctypedef enum grpc_status_code: GRPC_STATUS_OK GRPC_STATUS_CANCELLED GRPC_STATUS_UNKNOWN GRPC_STATUS_INVALID_ARGUMENT GRPC_STATUS_DEADLINE_EXCEEDED GRPC_STATUS_NOT_FOUND GRPC_STATUS_ALREADY_EXISTS GRPC_STATUS_PERMISSION_DENIED GRPC_STATUS_UNAUTHENTICATED GRPC_STATUS_RESOURCE_EXHAUSTED GRPC_STATUS_FAILED_PRECONDITION GRPC_STATUS_ABORTED GRPC_STATUS_OUT_OF_RANGE GRPC_STATUS_UNIMPLEMENTED GRPC_STATUS_INTERNAL GRPC_STATUS_UNAVAILABLE GRPC_STATUS_DATA_LOSS GRPC_STATUS__DO_NOT_USE const char *GRPC_ARG_PRIMARY_USER_AGENT_STRING const char *GRPC_ARG_ENABLE_CENSUS const char *GRPC_ARG_MAX_CONCURRENT_STREAMS const char *GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH const char *GRPC_ARG_MAX_SEND_MESSAGE_LENGTH const char *GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER const char *GRPC_ARG_DEFAULT_AUTHORITY const char *GRPC_ARG_PRIMARY_USER_AGENT_STRING const char *GRPC_ARG_SECONDARY_USER_AGENT_STRING const char *GRPC_SSL_TARGET_NAME_OVERRIDE_ARG const char *GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM const char *GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL const char *GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET const int GRPC_WRITE_BUFFER_HINT const int GRPC_WRITE_NO_COMPRESS const int GRPC_WRITE_USED_MASK const int GRPC_MAX_COMPLETION_QUEUE_PLUCKERS ctypedef struct grpc_completion_queue: # We don't care about the internals (and in fact don't know them) pass ctypedef struct grpc_channel: # We don't care about the internals (and in fact don't know them) pass ctypedef struct grpc_server: # We don't care about the internals (and in fact don't know them) pass ctypedef struct grpc_call: # We don't care about the internals (and in fact don't know them) pass ctypedef enum grpc_arg_type: GRPC_ARG_STRING GRPC_ARG_INTEGER GRPC_ARG_POINTER ctypedef struct grpc_arg_pointer_vtable: void *(*copy)(void *) void (*destroy)(grpc_exec_ctx *, void *) int (*cmp)(void *, void *) ctypedef struct grpc_arg_value_pointer: void *address "p" grpc_arg_pointer_vtable *vtable union grpc_arg_value: char *string int integer grpc_arg_value_pointer pointer ctypedef struct grpc_arg: grpc_arg_type type char *key grpc_arg_value value ctypedef struct grpc_channel_args: size_t arguments_length "num_args" grpc_arg *arguments "args" ctypedef enum grpc_call_error: GRPC_CALL_OK GRPC_CALL_ERROR GRPC_CALL_ERROR_NOT_ON_SERVER GRPC_CALL_ERROR_NOT_ON_CLIENT GRPC_CALL_ERROR_ALREADY_ACCEPTED GRPC_CALL_ERROR_ALREADY_INVOKED GRPC_CALL_ERROR_NOT_INVOKED GRPC_CALL_ERROR_ALREADY_FINISHED GRPC_CALL_ERROR_TOO_MANY_OPERATIONS GRPC_CALL_ERROR_INVALID_FLAGS GRPC_CALL_ERROR_INVALID_METADATA ctypedef enum grpc_connectivity_state: GRPC_CHANNEL_IDLE GRPC_CHANNEL_CONNECTING GRPC_CHANNEL_READY GRPC_CHANNEL_TRANSIENT_FAILURE GRPC_CHANNEL_SHUTDOWN ctypedef struct grpc_metadata: grpc_slice key grpc_slice value # ignore the 'internal_data.obfuscated' fields. ctypedef enum grpc_completion_type: GRPC_QUEUE_SHUTDOWN GRPC_QUEUE_TIMEOUT GRPC_OP_COMPLETE ctypedef struct grpc_event: grpc_completion_type type int success void *tag ctypedef struct grpc_metadata_array: size_t count size_t capacity grpc_metadata *metadata void grpc_metadata_array_init(grpc_metadata_array *array) nogil void grpc_metadata_array_destroy(grpc_metadata_array *array) nogil ctypedef struct grpc_call_details: grpc_slice method grpc_slice host gpr_timespec deadline void grpc_call_details_init(grpc_call_details *details) nogil void grpc_call_details_destroy(grpc_call_details *details) nogil ctypedef enum grpc_op_type: GRPC_OP_SEND_INITIAL_METADATA GRPC_OP_SEND_MESSAGE GRPC_OP_SEND_CLOSE_FROM_CLIENT GRPC_OP_SEND_STATUS_FROM_SERVER GRPC_OP_RECV_INITIAL_METADATA GRPC_OP_RECV_MESSAGE GRPC_OP_RECV_STATUS_ON_CLIENT GRPC_OP_RECV_CLOSE_ON_SERVER ctypedef struct grpc_op_data_send_initial_metadata: size_t count grpc_metadata *metadata ctypedef struct grpc_op_data_send_status_from_server: size_t trailing_metadata_count grpc_metadata *trailing_metadata grpc_status_code status grpc_slice *status_details ctypedef struct grpc_op_data_recv_status_on_client: grpc_metadata_array *trailing_metadata grpc_status_code *status grpc_slice *status_details ctypedef struct grpc_op_data_recv_close_on_server: int *cancelled ctypedef struct grpc_op_data_send_message: grpc_byte_buffer *send_message ctypedef struct grpc_op_data_receive_message: grpc_byte_buffer **receive_message "recv_message" ctypedef struct grpc_op_data_receive_initial_metadata: grpc_metadata_array *receive_initial_metadata "recv_initial_metadata" union grpc_op_data: grpc_op_data_send_initial_metadata send_initial_metadata grpc_op_data_send_message send_message grpc_op_data_send_status_from_server send_status_from_server grpc_op_data_receive_initial_metadata receive_initial_metadata "recv_initial_metadata" grpc_op_data_receive_message receive_message "recv_message" grpc_op_data_recv_status_on_client receive_status_on_client "recv_status_on_client" grpc_op_data_recv_close_on_server receive_close_on_server "recv_close_on_server" ctypedef struct grpc_op: grpc_op_type type "op" uint32_t flags grpc_op_data data void grpc_init() nogil void grpc_shutdown() nogil grpc_completion_queue *grpc_completion_queue_create(void *reserved) nogil grpc_event grpc_completion_queue_next(grpc_completion_queue *cq, gpr_timespec deadline, void *reserved) nogil grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cq, void *tag, gpr_timespec deadline, void *reserved) nogil void grpc_completion_queue_shutdown(grpc_completion_queue *cq) nogil void grpc_completion_queue_destroy(grpc_completion_queue *cq) nogil grpc_call_error grpc_call_start_batch( grpc_call *call, const grpc_op *ops, size_t nops, void *tag, void *reserved) nogil grpc_call_error grpc_call_cancel(grpc_call *call, void *reserved) nogil grpc_call_error grpc_call_cancel_with_status(grpc_call *call, grpc_status_code status, const char *description, void *reserved) nogil char *grpc_call_get_peer(grpc_call *call) nogil void grpc_call_destroy(grpc_call *call) nogil grpc_channel *grpc_insecure_channel_create(const char *target, const grpc_channel_args *args, void *reserved) nogil grpc_call *grpc_channel_create_call( grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_completion_queue *completion_queue, grpc_slice method, const grpc_slice *host, gpr_timespec deadline, void *reserved) nogil grpc_connectivity_state grpc_channel_check_connectivity_state( grpc_channel *channel, int try_to_connect) nogil void grpc_channel_watch_connectivity_state( grpc_channel *channel, grpc_connectivity_state last_observed_state, gpr_timespec deadline, grpc_completion_queue *cq, void *tag) nogil char *grpc_channel_get_target(grpc_channel *channel) nogil void grpc_channel_destroy(grpc_channel *channel) nogil grpc_server *grpc_server_create( const grpc_channel_args *args, void *reserved) nogil grpc_call_error grpc_server_request_call( grpc_server *server, grpc_call **call, grpc_call_details *details, grpc_metadata_array *request_metadata, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new) nogil void grpc_server_register_completion_queue(grpc_server *server, grpc_completion_queue *cq, void *reserved) nogil void grpc_server_register_non_listening_completion_queue( grpc_server *server, grpc_completion_queue *cq, void *reserved) nogil int grpc_server_add_insecure_http2_port( grpc_server *server, const char *addr) nogil void grpc_server_start(grpc_server *server) nogil void grpc_server_shutdown_and_notify( grpc_server *server, grpc_completion_queue *cq, void *tag) nogil void grpc_server_cancel_all_calls(grpc_server *server) nogil void grpc_server_destroy(grpc_server *server) nogil cdef extern from "grpc/grpc_security.h": ctypedef enum grpc_ssl_roots_override_result: GRPC_SSL_ROOTS_OVERRIDE_OK GRPC_SSL_ROOTS_OVERRIDE_FAILED_PERMANENTLY GRPC_SSL_ROOTS_OVERRIDE_FAILED ctypedef enum grpc_ssl_client_certificate_request_type: GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY ctypedef struct grpc_ssl_pem_key_cert_pair: const char *private_key const char *certificate_chain "cert_chain" ctypedef struct grpc_channel_credentials: # We don't care about the internals (and in fact don't know them) pass ctypedef struct grpc_call_credentials: # We don't care about the internals (and in fact don't know them) pass ctypedef void (*grpc_ssl_roots_override_callback)(char **pem_root_certs) void grpc_set_ssl_roots_override_callback( grpc_ssl_roots_override_callback cb) nogil grpc_channel_credentials *grpc_google_default_credentials_create() nogil grpc_channel_credentials *grpc_ssl_credentials_create( const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair, void *reserved) nogil grpc_channel_credentials *grpc_composite_channel_credentials_create( grpc_channel_credentials *creds1, grpc_call_credentials *creds2, void *reserved) nogil void grpc_channel_credentials_release(grpc_channel_credentials *creds) nogil grpc_call_credentials *grpc_composite_call_credentials_create( grpc_call_credentials *creds1, grpc_call_credentials *creds2, void *reserved) nogil grpc_call_credentials *grpc_google_compute_engine_credentials_create( void *reserved) nogil grpc_call_credentials *grpc_service_account_jwt_access_credentials_create( const char *json_key, gpr_timespec token_lifetime, void *reserved) nogil grpc_call_credentials *grpc_google_refresh_token_credentials_create( const char *json_refresh_token, void *reserved) nogil grpc_call_credentials *grpc_google_iam_credentials_create( const char *authorization_token, const char *authority_selector, void *reserved) nogil void grpc_call_credentials_release(grpc_call_credentials *creds) nogil grpc_channel *grpc_secure_channel_create( grpc_channel_credentials *creds, const char *target, const grpc_channel_args *args, void *reserved) nogil ctypedef struct grpc_server_credentials: # We don't care about the internals (and in fact don't know them) pass grpc_server_credentials *grpc_ssl_server_credentials_create( const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, size_t num_key_cert_pairs, int force_client_auth, void *reserved) void grpc_server_credentials_release(grpc_server_credentials *creds) nogil int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, grpc_server_credentials *creds) nogil grpc_call_error grpc_call_set_credentials(grpc_call *call, grpc_call_credentials *creds) nogil ctypedef struct grpc_auth_context: # We don't care about the internals (and in fact don't know them) pass ctypedef struct grpc_auth_metadata_context: const char *service_url const char *method_name const grpc_auth_context *channel_auth_context ctypedef void (*grpc_credentials_plugin_metadata_cb)( void *user_data, const grpc_metadata *creds_md, size_t num_creds_md, grpc_status_code status, const char *error_details) ctypedef struct grpc_metadata_credentials_plugin: void (*get_metadata)( void *state, grpc_auth_metadata_context context, grpc_credentials_plugin_metadata_cb cb, void *user_data) void (*destroy)(void *state) void *state const char *type grpc_call_credentials *grpc_metadata_credentials_create_from_plugin( grpc_metadata_credentials_plugin plugin, void *reserved) nogil cdef extern from "grpc/compression.h": ctypedef enum grpc_compression_algorithm: GRPC_COMPRESS_NONE GRPC_COMPRESS_DEFLATE GRPC_COMPRESS_GZIP GRPC_COMPRESS_ALGORITHMS_COUNT ctypedef enum grpc_compression_level: GRPC_COMPRESS_LEVEL_NONE GRPC_COMPRESS_LEVEL_LOW GRPC_COMPRESS_LEVEL_MED GRPC_COMPRESS_LEVEL_HIGH GRPC_COMPRESS_LEVEL_COUNT ctypedef struct grpc_compression_options: uint32_t enabled_algorithms_bitset grpc_compression_algorithm default_compression_algorithm int grpc_compression_algorithm_parse( grpc_slice value, grpc_compression_algorithm *algorithm) nogil int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm, char **name) nogil grpc_compression_algorithm grpc_compression_algorithm_for_level( grpc_compression_level level, uint32_t accepted_encodings) nogil void grpc_compression_options_init(grpc_compression_options *opts) nogil void grpc_compression_options_enable_algorithm( grpc_compression_options *opts, grpc_compression_algorithm algorithm) nogil void grpc_compression_options_disable_algorithm( grpc_compression_options *opts, grpc_compression_algorithm algorithm) nogil int grpc_compression_options_is_algorithm_enabled( const grpc_compression_options *opts, grpc_compression_algorithm algorithm) nogil grpc-1.3.2/src/python/grpcio/grpc/_cython/_cygrpc/grpc_string.pyx.pxi000066400000000000000000000035431310511640000257450ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # This function will ascii encode unicode string inputs if neccesary. # In Python3, unicode strings are the default str type. cdef bytes str_to_bytes(object s): if s is None or isinstance(s, bytes): return s elif isinstance(s, unicode): return s.encode('ascii') else: raise TypeError('Expected bytes, str, or unicode, not {}'.format(type(s))) grpc-1.3.2/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi000066400000000000000000000071161310511640000250400ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cdef bytes _slice_bytes(grpc_slice slice) cdef grpc_slice _copy_slice(grpc_slice slice) nogil cdef grpc_slice _slice_from_bytes(bytes value) nogil cdef class Timespec: cdef gpr_timespec c_time cdef class CallDetails: cdef grpc_call_details c_details cdef class OperationTag: cdef object user_tag cdef list references # This allows CompletionQueue to notify the Python Server object that the # underlying GRPC core server has shutdown cdef Server shutting_down_server cdef Call operation_call cdef CallDetails request_call_details cdef Metadata request_metadata cdef Operations batch_operations cdef bint is_new_request cdef class Event: cdef readonly grpc_completion_type type cdef readonly bint success cdef readonly object tag # For Server.request_call cdef readonly bint is_new_request cdef readonly CallDetails request_call_details cdef readonly Metadata request_metadata # For server calls cdef readonly Call operation_call # For Call.start_batch cdef readonly Operations batch_operations cdef class ByteBuffer: cdef grpc_byte_buffer *c_byte_buffer cdef class SslPemKeyCertPair: cdef grpc_ssl_pem_key_cert_pair c_pair cdef readonly object private_key, certificate_chain cdef class ChannelArg: cdef grpc_arg c_arg cdef grpc_arg_pointer_vtable ptr_vtable cdef readonly object key, value cdef class ChannelArgs: cdef grpc_channel_args c_args cdef list args cdef class Metadatum: cdef grpc_metadata c_metadata cdef void _copy_metadatum(self, grpc_metadata *destination) nogil cdef class Metadata: cdef grpc_metadata_array c_metadata_array cdef void _claim_slice_ownership(self) cdef class Operation: cdef grpc_op c_op cdef ByteBuffer _received_message cdef Metadata _received_metadata cdef grpc_status_code _received_status_code cdef grpc_slice _status_details cdef int _received_cancelled cdef readonly bint is_valid cdef object references cdef class Operations: cdef grpc_op *c_ops cdef size_t c_nops cdef list operations cdef class CompressionOptions: cdef grpc_compression_options c_options grpc-1.3.2/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi000066400000000000000000000577341310511640000251000ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from libc.stdint cimport intptr_t cdef bytes _slice_bytes(grpc_slice slice): cdef void *start = grpc_slice_start_ptr(slice) cdef size_t length = grpc_slice_length(slice) return (start)[:length] cdef grpc_slice _copy_slice(grpc_slice slice) nogil: cdef void *start = grpc_slice_start_ptr(slice) cdef size_t length = grpc_slice_length(slice) return grpc_slice_from_copied_buffer(start, length) cdef grpc_slice _slice_from_bytes(bytes value) nogil: cdef const char *value_ptr cdef size_t length with gil: value_ptr = value length = len(value) return grpc_slice_from_copied_buffer(value_ptr, length) class ConnectivityState: idle = GRPC_CHANNEL_IDLE connecting = GRPC_CHANNEL_CONNECTING ready = GRPC_CHANNEL_READY transient_failure = GRPC_CHANNEL_TRANSIENT_FAILURE shutdown = GRPC_CHANNEL_SHUTDOWN class ChannelArgKey: enable_census = GRPC_ARG_ENABLE_CENSUS max_concurrent_streams = GRPC_ARG_MAX_CONCURRENT_STREAMS max_receive_message_length = GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH max_send_message_length = GRPC_ARG_MAX_SEND_MESSAGE_LENGTH http2_initial_sequence_number = GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER default_authority = GRPC_ARG_DEFAULT_AUTHORITY primary_user_agent_string = GRPC_ARG_PRIMARY_USER_AGENT_STRING secondary_user_agent_string = GRPC_ARG_SECONDARY_USER_AGENT_STRING ssl_target_name_override = GRPC_SSL_TARGET_NAME_OVERRIDE_ARG class WriteFlag: buffer_hint = GRPC_WRITE_BUFFER_HINT no_compress = GRPC_WRITE_NO_COMPRESS class StatusCode: ok = GRPC_STATUS_OK cancelled = GRPC_STATUS_CANCELLED unknown = GRPC_STATUS_UNKNOWN invalid_argument = GRPC_STATUS_INVALID_ARGUMENT deadline_exceeded = GRPC_STATUS_DEADLINE_EXCEEDED not_found = GRPC_STATUS_NOT_FOUND already_exists = GRPC_STATUS_ALREADY_EXISTS permission_denied = GRPC_STATUS_PERMISSION_DENIED unauthenticated = GRPC_STATUS_UNAUTHENTICATED resource_exhausted = GRPC_STATUS_RESOURCE_EXHAUSTED failed_precondition = GRPC_STATUS_FAILED_PRECONDITION aborted = GRPC_STATUS_ABORTED out_of_range = GRPC_STATUS_OUT_OF_RANGE unimplemented = GRPC_STATUS_UNIMPLEMENTED internal = GRPC_STATUS_INTERNAL unavailable = GRPC_STATUS_UNAVAILABLE data_loss = GRPC_STATUS_DATA_LOSS class CallError: ok = GRPC_CALL_OK error = GRPC_CALL_ERROR not_on_server = GRPC_CALL_ERROR_NOT_ON_SERVER not_on_client = GRPC_CALL_ERROR_NOT_ON_CLIENT already_accepted = GRPC_CALL_ERROR_ALREADY_ACCEPTED already_invoked = GRPC_CALL_ERROR_ALREADY_INVOKED not_invoked = GRPC_CALL_ERROR_NOT_INVOKED already_finished = GRPC_CALL_ERROR_ALREADY_FINISHED too_many_operations = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS invalid_flags = GRPC_CALL_ERROR_INVALID_FLAGS invalid_metadata = GRPC_CALL_ERROR_INVALID_METADATA class CompletionType: queue_shutdown = GRPC_QUEUE_SHUTDOWN queue_timeout = GRPC_QUEUE_TIMEOUT operation_complete = GRPC_OP_COMPLETE class OperationType: send_initial_metadata = GRPC_OP_SEND_INITIAL_METADATA send_message = GRPC_OP_SEND_MESSAGE send_close_from_client = GRPC_OP_SEND_CLOSE_FROM_CLIENT send_status_from_server = GRPC_OP_SEND_STATUS_FROM_SERVER receive_initial_metadata = GRPC_OP_RECV_INITIAL_METADATA receive_message = GRPC_OP_RECV_MESSAGE receive_status_on_client = GRPC_OP_RECV_STATUS_ON_CLIENT receive_close_on_server = GRPC_OP_RECV_CLOSE_ON_SERVER class CompressionAlgorithm: none = GRPC_COMPRESS_NONE deflate = GRPC_COMPRESS_DEFLATE gzip = GRPC_COMPRESS_GZIP class CompressionLevel: none = GRPC_COMPRESS_LEVEL_NONE low = GRPC_COMPRESS_LEVEL_LOW medium = GRPC_COMPRESS_LEVEL_MED high = GRPC_COMPRESS_LEVEL_HIGH cdef class Timespec: def __cinit__(self, time): if time is None: with nogil: self.c_time = gpr_now(GPR_CLOCK_REALTIME) return if isinstance(time, int): time = float(time) if isinstance(time, float): if time == float("+inf"): with nogil: self.c_time = gpr_inf_future(GPR_CLOCK_REALTIME) elif time == float("-inf"): with nogil: self.c_time = gpr_inf_past(GPR_CLOCK_REALTIME) else: self.c_time.seconds = time self.c_time.nanoseconds = (time - float(self.c_time.seconds)) * 1e9 self.c_time.clock_type = GPR_CLOCK_REALTIME elif isinstance(time, Timespec): self.c_time = (time).c_time else: raise TypeError("expected time to be float, int, or Timespec, not {}" .format(type(time))) @property def seconds(self): # TODO(atash) ensure that everywhere a Timespec is created that it's # converted to GPR_CLOCK_REALTIME then and not every time someone wants to # read values off in Python. cdef gpr_timespec real_time with nogil: real_time = ( gpr_convert_clock_type(self.c_time, GPR_CLOCK_REALTIME)) return real_time.seconds @property def nanoseconds(self): cdef gpr_timespec real_time = ( gpr_convert_clock_type(self.c_time, GPR_CLOCK_REALTIME)) return real_time.nanoseconds def __float__(self): cdef gpr_timespec real_time = ( gpr_convert_clock_type(self.c_time, GPR_CLOCK_REALTIME)) return real_time.seconds + real_time.nanoseconds / 1e9 @staticmethod def infinite_future(): return Timespec(float("+inf")) @staticmethod def infinite_past(): return Timespec(float("-inf")) def __richcmp__(Timespec self not None, Timespec other not None, int op): cdef gpr_timespec self_c_time = self.c_time cdef gpr_timespec other_c_time = other.c_time cdef int result = gpr_time_cmp(self_c_time, other_c_time) if op == 0: # < return result < 0 elif op == 2: # == return result == 0 elif op == 4: # > return result > 0 elif op == 1: # <= return result <= 0 elif op == 3: # != return result != 0 elif op == 5: # >= return result >= 0 else: raise ValueError('__richcmp__ `op` contract violated') cdef class CallDetails: def __cinit__(self): grpc_init() with nogil: grpc_call_details_init(&self.c_details) def __dealloc__(self): with nogil: grpc_call_details_destroy(&self.c_details) grpc_shutdown() @property def method(self): return _slice_bytes(self.c_details.method) @property def host(self): return _slice_bytes(self.c_details.host) @property def deadline(self): timespec = Timespec(float("-inf")) timespec.c_time = self.c_details.deadline return timespec cdef class OperationTag: def __cinit__(self, user_tag): self.user_tag = user_tag self.references = [] cdef class Event: def __cinit__(self, grpc_completion_type type, bint success, object tag, Call operation_call, CallDetails request_call_details, Metadata request_metadata, bint is_new_request, Operations batch_operations): self.type = type self.success = success self.tag = tag self.operation_call = operation_call self.request_call_details = request_call_details self.request_metadata = request_metadata self.batch_operations = batch_operations self.is_new_request = is_new_request cdef class ByteBuffer: def __cinit__(self, bytes data): grpc_init() if data is None: self.c_byte_buffer = NULL return cdef char *c_data = data cdef grpc_slice data_slice cdef size_t data_length = len(data) with nogil: data_slice = grpc_slice_from_copied_buffer(c_data, data_length) with nogil: self.c_byte_buffer = grpc_raw_byte_buffer_create( &data_slice, 1) with nogil: grpc_slice_unref(data_slice) def bytes(self): cdef grpc_byte_buffer_reader reader cdef grpc_slice data_slice cdef size_t data_slice_length cdef void *data_slice_pointer cdef bint reader_status if self.c_byte_buffer != NULL: with nogil: reader_status = grpc_byte_buffer_reader_init( &reader, self.c_byte_buffer) if not reader_status: return None result = bytearray() with nogil: while grpc_byte_buffer_reader_next(&reader, &data_slice): data_slice_pointer = grpc_slice_start_ptr(data_slice) data_slice_length = grpc_slice_length(data_slice) with gil: result += (data_slice_pointer)[:data_slice_length] grpc_slice_unref(data_slice) with nogil: grpc_byte_buffer_reader_destroy(&reader) return bytes(result) else: return None def __len__(self): cdef size_t result if self.c_byte_buffer != NULL: with nogil: result = grpc_byte_buffer_length(self.c_byte_buffer) return result else: return 0 def __str__(self): return self.bytes() def __dealloc__(self): if self.c_byte_buffer != NULL: grpc_byte_buffer_destroy(self.c_byte_buffer) grpc_shutdown() cdef class SslPemKeyCertPair: def __cinit__(self, bytes private_key, bytes certificate_chain): self.private_key = private_key self.certificate_chain = certificate_chain self.c_pair.private_key = self.private_key self.c_pair.certificate_chain = self.certificate_chain cdef void* copy_ptr(void* ptr): return ptr cdef void destroy_ptr(grpc_exec_ctx* ctx, void* ptr): pass cdef int compare_ptr(void* ptr1, void* ptr2): if ptr1 < ptr2: return -1 elif ptr1 > ptr2: return 1 else: return 0 cdef class ChannelArg: def __cinit__(self, bytes key, value): self.key = key self.value = value self.c_arg.key = self.key if isinstance(value, int): self.c_arg.type = GRPC_ARG_INTEGER self.c_arg.value.integer = self.value elif isinstance(value, bytes): self.c_arg.type = GRPC_ARG_STRING self.c_arg.value.string = self.value elif hasattr(value, '__int__'): # Pointer objects must override __int__() to return # the underlying C address (Python ints are word size). The # lifecycle of the pointer is fixed to the lifecycle of the # python object wrapping it. self.ptr_vtable.copy = ©_ptr self.ptr_vtable.destroy = &destroy_ptr self.ptr_vtable.cmp = &compare_ptr self.c_arg.type = GRPC_ARG_POINTER self.c_arg.value.pointer.vtable = &self.ptr_vtable self.c_arg.value.pointer.address = (int(self.value)) else: # TODO Add supported pointer types to this message raise TypeError('Expected int or bytes, got {}'.format(type(value))) cdef class ChannelArgs: def __cinit__(self, args): grpc_init() self.args = list(args) for arg in self.args: if not isinstance(arg, ChannelArg): raise TypeError("expected list of ChannelArg") self.c_args.arguments_length = len(self.args) with nogil: self.c_args.arguments = gpr_malloc( self.c_args.arguments_length*sizeof(grpc_arg)) for i in range(self.c_args.arguments_length): self.c_args.arguments[i] = (self.args[i]).c_arg def __dealloc__(self): with nogil: gpr_free(self.c_args.arguments) grpc_shutdown() def __len__(self): # self.args is never stale; it's only updated from this file return len(self.args) def __getitem__(self, size_t i): # self.args is never stale; it's only updated from this file return self.args[i] cdef class Metadatum: def __cinit__(self, bytes key, bytes value): self.c_metadata.key = _slice_from_bytes(key) self.c_metadata.value = _slice_from_bytes(value) cdef void _copy_metadatum(self, grpc_metadata *destination) nogil: destination[0].key = _copy_slice(self.c_metadata.key) destination[0].value = _copy_slice(self.c_metadata.value) @property def key(self): return _slice_bytes(self.c_metadata.key) @property def value(self): return _slice_bytes(self.c_metadata.value) def __len__(self): return 2 def __getitem__(self, size_t i): if i == 0: return self.key elif i == 1: return self.value else: raise IndexError("index must be 0 (key) or 1 (value)") def __iter__(self): return iter((self.key, self.value)) def __dealloc__(self): grpc_slice_unref(self.c_metadata.key) grpc_slice_unref(self.c_metadata.value) cdef class _MetadataIterator: cdef size_t i cdef Metadata metadata def __cinit__(self, Metadata metadata not None): self.i = 0 self.metadata = metadata def __iter__(self): return self def __next__(self): if self.i < len(self.metadata): result = self.metadata[self.i] self.i = self.i + 1 return result else: raise StopIteration cdef class Metadata: def __cinit__(self, metadata_iterable): with nogil: grpc_init() grpc_metadata_array_init(&self.c_metadata_array) metadata = list(metadata_iterable) for metadatum in metadata: if not isinstance(metadatum, Metadatum): raise TypeError("expected list of Metadatum") self.c_metadata_array.count = len(metadata) self.c_metadata_array.capacity = len(metadata) with nogil: self.c_metadata_array.metadata = gpr_malloc( self.c_metadata_array.count*sizeof(grpc_metadata) ) for i in range(self.c_metadata_array.count): (metadata[i])._copy_metadatum(&self.c_metadata_array.metadata[i]) def __dealloc__(self): with nogil: # this frees the allocated memory for the grpc_metadata_array (although # it'd be nice if that were documented somewhere...) # TODO(atash): document this in the C core grpc_metadata_array_destroy(&self.c_metadata_array) grpc_shutdown() def __len__(self): return self.c_metadata_array.count def __getitem__(self, size_t i): if i >= self.c_metadata_array.count: raise IndexError key = _slice_bytes(self.c_metadata_array.metadata[i].key) value = _slice_bytes(self.c_metadata_array.metadata[i].value) return Metadatum(key=key, value=value) def __iter__(self): return _MetadataIterator(self) cdef void _claim_slice_ownership(self): cdef grpc_metadata_array new_c_metadata_array grpc_metadata_array_init(&new_c_metadata_array) new_c_metadata_array.metadata = gpr_malloc( self.c_metadata_array.count*sizeof(grpc_metadata)) new_c_metadata_array.count = self.c_metadata_array.count for i in range(self.c_metadata_array.count): new_c_metadata_array.metadata[i].key = _copy_slice( self.c_metadata_array.metadata[i].key) new_c_metadata_array.metadata[i].value = _copy_slice( self.c_metadata_array.metadata[i].value) grpc_metadata_array_destroy(&self.c_metadata_array) self.c_metadata_array = new_c_metadata_array cdef class Operation: def __cinit__(self): grpc_init() self.references = [] self._status_details = grpc_empty_slice() self.is_valid = False @property def type(self): return self.c_op.type @property def flags(self): return self.c_op.flags @property def has_status(self): return self.c_op.type == GRPC_OP_RECV_STATUS_ON_CLIENT @property def received_message(self): if self.c_op.type != GRPC_OP_RECV_MESSAGE: raise TypeError("self must be an operation receiving a message") return self._received_message @property def received_message_or_none(self): if self.c_op.type != GRPC_OP_RECV_MESSAGE: return None return self._received_message @property def received_metadata(self): if (self.c_op.type != GRPC_OP_RECV_INITIAL_METADATA and self.c_op.type != GRPC_OP_RECV_STATUS_ON_CLIENT): raise TypeError("self must be an operation receiving metadata") return self._received_metadata @property def received_metadata_or_none(self): if (self.c_op.type != GRPC_OP_RECV_INITIAL_METADATA and self.c_op.type != GRPC_OP_RECV_STATUS_ON_CLIENT): return None return self._received_metadata @property def received_status_code(self): if self.c_op.type != GRPC_OP_RECV_STATUS_ON_CLIENT: raise TypeError("self must be an operation receiving a status code") return self._received_status_code @property def received_status_code_or_none(self): if self.c_op.type != GRPC_OP_RECV_STATUS_ON_CLIENT: return None return self._received_status_code @property def received_status_details(self): if self.c_op.type != GRPC_OP_RECV_STATUS_ON_CLIENT: raise TypeError("self must be an operation receiving status details") return _slice_bytes(self._status_details) @property def received_status_details_or_none(self): if self.c_op.type != GRPC_OP_RECV_STATUS_ON_CLIENT: return None return _slice_bytes(self._status_details) @property def received_cancelled(self): if self.c_op.type != GRPC_OP_RECV_CLOSE_ON_SERVER: raise TypeError("self must be an operation receiving cancellation " "information") return False if self._received_cancelled == 0 else True @property def received_cancelled_or_none(self): if self.c_op.type != GRPC_OP_RECV_CLOSE_ON_SERVER: return None return False if self._received_cancelled == 0 else True def __dealloc__(self): grpc_slice_unref(self._status_details) grpc_shutdown() def operation_send_initial_metadata(Metadata metadata, int flags): cdef Operation op = Operation() op.c_op.type = GRPC_OP_SEND_INITIAL_METADATA op.c_op.flags = flags op.c_op.data.send_initial_metadata.count = metadata.c_metadata_array.count op.c_op.data.send_initial_metadata.metadata = ( metadata.c_metadata_array.metadata) op.references.append(metadata) op.is_valid = True return op def operation_send_message(data, int flags): cdef Operation op = Operation() op.c_op.type = GRPC_OP_SEND_MESSAGE op.c_op.flags = flags byte_buffer = ByteBuffer(data) op.c_op.data.send_message.send_message = byte_buffer.c_byte_buffer op.references.append(byte_buffer) op.is_valid = True return op def operation_send_close_from_client(int flags): cdef Operation op = Operation() op.c_op.type = GRPC_OP_SEND_CLOSE_FROM_CLIENT op.c_op.flags = flags op.is_valid = True return op def operation_send_status_from_server( Metadata metadata, grpc_status_code code, bytes details, int flags): cdef Operation op = Operation() op.c_op.type = GRPC_OP_SEND_STATUS_FROM_SERVER op.c_op.flags = flags op.c_op.data.send_status_from_server.trailing_metadata_count = ( metadata.c_metadata_array.count) op.c_op.data.send_status_from_server.trailing_metadata = ( metadata.c_metadata_array.metadata) op.c_op.data.send_status_from_server.status = code grpc_slice_unref(op._status_details) op._status_details = _slice_from_bytes(details) op.c_op.data.send_status_from_server.status_details = &op._status_details op.references.append(metadata) op.is_valid = True return op def operation_receive_initial_metadata(int flags): cdef Operation op = Operation() op.c_op.type = GRPC_OP_RECV_INITIAL_METADATA op.c_op.flags = flags op._received_metadata = Metadata([]) op.c_op.data.receive_initial_metadata.receive_initial_metadata = ( &op._received_metadata.c_metadata_array) op.is_valid = True return op def operation_receive_message(int flags): cdef Operation op = Operation() op.c_op.type = GRPC_OP_RECV_MESSAGE op.c_op.flags = flags op._received_message = ByteBuffer(None) # n.b. the c_op.data.receive_message field needs to be deleted by us, # anyway, so we just let that be handled by the ByteBuffer() we allocated # the line before. op.c_op.data.receive_message.receive_message = ( &op._received_message.c_byte_buffer) op.is_valid = True return op def operation_receive_status_on_client(int flags): cdef Operation op = Operation() op.c_op.type = GRPC_OP_RECV_STATUS_ON_CLIENT op.c_op.flags = flags op._received_metadata = Metadata([]) op.c_op.data.receive_status_on_client.trailing_metadata = ( &op._received_metadata.c_metadata_array) op.c_op.data.receive_status_on_client.status = ( &op._received_status_code) op.c_op.data.receive_status_on_client.status_details = ( &op._status_details) op.is_valid = True return op def operation_receive_close_on_server(int flags): cdef Operation op = Operation() op.c_op.type = GRPC_OP_RECV_CLOSE_ON_SERVER op.c_op.flags = flags op.c_op.data.receive_close_on_server.cancelled = &op._received_cancelled op.is_valid = True return op cdef class _OperationsIterator: cdef size_t i cdef Operations operations def __cinit__(self, Operations operations not None): self.i = 0 self.operations = operations def __iter__(self): return self def __next__(self): if self.i < len(self.operations): result = self.operations[self.i] self.i = self.i + 1 return result else: raise StopIteration cdef class Operations: def __cinit__(self, operations): grpc_init() self.operations = list(operations) # normalize iterable self.c_ops = NULL self.c_nops = 0 for operation in self.operations: if not isinstance(operation, Operation): raise TypeError("expected operations to be iterable of Operation") self.c_nops = len(self.operations) with nogil: self.c_ops = gpr_malloc(sizeof(grpc_op)*self.c_nops) for i in range(self.c_nops): self.c_ops[i] = ((self.operations[i])).c_op def __len__(self): return self.c_nops def __getitem__(self, size_t i): # self.operations is never stale; it's only updated from this file return self.operations[i] def __dealloc__(self): with nogil: gpr_free(self.c_ops) grpc_shutdown() def __iter__(self): return _OperationsIterator(self) cdef class CompressionOptions: def __cinit__(self): with nogil: grpc_compression_options_init(&self.c_options) def enable_algorithm(self, grpc_compression_algorithm algorithm): with nogil: grpc_compression_options_enable_algorithm(&self.c_options, algorithm) def disable_algorithm(self, grpc_compression_algorithm algorithm): with nogil: grpc_compression_options_disable_algorithm(&self.c_options, algorithm) def is_algorithm_enabled(self, grpc_compression_algorithm algorithm): cdef int result with nogil: result = grpc_compression_options_is_algorithm_enabled( &self.c_options, algorithm) return result def to_channel_arg(self): return ChannelArg(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET, self.c_options.enabled_algorithms_bitset) def compression_algorithm_name(grpc_compression_algorithm algorithm): cdef char* name with nogil: grpc_compression_algorithm_name(algorithm, &name) # Let Cython do the right thing with string casting return name grpc-1.3.2/src/python/grpcio/grpc/_cython/_cygrpc/security.pxd.pxi000066400000000000000000000031341310511640000252420ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cdef grpc_ssl_roots_override_result ssl_roots_override_callback( char **pem_root_certs) nogil grpc-1.3.2/src/python/grpcio/grpc/_cython/_cygrpc/security.pyx.pxi000066400000000000000000000040731310511640000252720ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from libc.string cimport memcpy import pkg_resources cdef grpc_ssl_roots_override_result ssl_roots_override_callback( char **pem_root_certs) nogil: with gil: temporary_pem_root_certs = pkg_resources.resource_string( __name__.rstrip('.cygrpc'), '_credentials/roots.pem') pem_root_certs[0] = gpr_malloc(len(temporary_pem_root_certs) + 1) memcpy( pem_root_certs[0], temporary_pem_root_certs, len(temporary_pem_root_certs)) pem_root_certs[0][len(temporary_pem_root_certs)] = '\0' return GRPC_SSL_ROOTS_OVERRIDE_OK grpc-1.3.2/src/python/grpcio/grpc/_cython/_cygrpc/server.pxd.pxi000066400000000000000000000037251310511640000247070ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cdef class Server: cdef grpc_server *c_server cdef bint is_started # start has been called cdef bint is_shutting_down # shutdown has been called cdef bint is_shutdown # notification of complete shutdown received # used at dealloc when user forgets to shutdown cdef CompletionQueue backup_shutdown_queue cdef list references cdef list registered_completion_queues cdef _c_shutdown(self, CompletionQueue queue, tag) cdef notify_shutdown_complete(self) grpc-1.3.2/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi000066400000000000000000000154461310511640000247370ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cimport cpython import time cdef class Server: def __cinit__(self, ChannelArgs arguments): grpc_init() cdef grpc_channel_args *c_arguments = NULL self.references = [] self.registered_completion_queues = [] if len(arguments) > 0: c_arguments = &arguments.c_args self.references.append(arguments) with nogil: self.c_server = grpc_server_create(c_arguments, NULL) self.is_started = False self.is_shutting_down = False self.is_shutdown = False def request_call( self, CompletionQueue call_queue not None, CompletionQueue server_queue not None, tag): if not self.is_started or self.is_shutting_down: raise ValueError("server must be started and not shutting down") if server_queue not in self.registered_completion_queues: raise ValueError("server_queue must be a registered completion queue") cdef grpc_call_error result cdef OperationTag operation_tag = OperationTag(tag) operation_tag.operation_call = Call() operation_tag.request_call_details = CallDetails() operation_tag.request_metadata = Metadata([]) operation_tag.references.extend([self, call_queue, server_queue]) operation_tag.is_new_request = True operation_tag.batch_operations = Operations([]) cpython.Py_INCREF(operation_tag) with nogil: result = grpc_server_request_call( self.c_server, &operation_tag.operation_call.c_call, &operation_tag.request_call_details.c_details, &operation_tag.request_metadata.c_metadata_array, call_queue.c_completion_queue, server_queue.c_completion_queue, operation_tag) return result def register_completion_queue( self, CompletionQueue queue not None): if self.is_started: raise ValueError("cannot register completion queues after start") with nogil: grpc_server_register_completion_queue( self.c_server, queue.c_completion_queue, NULL) self.registered_completion_queues.append(queue) def register_non_listening_completion_queue( self, CompletionQueue queue not None): if self.is_started: raise ValueError("cannot register completion queues after start") with nogil: grpc_server_register_non_listening_completion_queue( self.c_server, queue.c_completion_queue, NULL) self.registered_completion_queues.append(queue) def start(self): if self.is_started: raise ValueError("the server has already started") self.backup_shutdown_queue = CompletionQueue() self.register_non_listening_completion_queue(self.backup_shutdown_queue) self.is_started = True with nogil: grpc_server_start(self.c_server) # Ensure the core has gotten a chance to do the start-up work self.backup_shutdown_queue.poll(Timespec(None)) def add_http2_port(self, bytes address, ServerCredentials server_credentials=None): address = str_to_bytes(address) self.references.append(address) cdef int result cdef char *address_c_string = address if server_credentials is not None: self.references.append(server_credentials) with nogil: result = grpc_server_add_secure_http2_port( self.c_server, address_c_string, server_credentials.c_credentials) else: with nogil: result = grpc_server_add_insecure_http2_port(self.c_server, address_c_string) return result cdef _c_shutdown(self, CompletionQueue queue, tag): self.is_shutting_down = True operation_tag = OperationTag(tag) operation_tag.shutting_down_server = self cpython.Py_INCREF(operation_tag) with nogil: grpc_server_shutdown_and_notify( self.c_server, queue.c_completion_queue, operation_tag) def shutdown(self, CompletionQueue queue not None, tag): cdef OperationTag operation_tag if queue.is_shutting_down: raise ValueError("queue must be live") elif not self.is_started: raise ValueError("the server hasn't started yet") elif self.is_shutting_down: return elif queue not in self.registered_completion_queues: raise ValueError("expected registered completion queue") else: self._c_shutdown(queue, tag) cdef notify_shutdown_complete(self): # called only by a completion queue on receiving our shutdown operation tag self.is_shutdown = True def cancel_all_calls(self): if not self.is_shutting_down: raise RuntimeError("the server must be shutting down to cancel all calls") elif self.is_shutdown: return else: with nogil: grpc_server_cancel_all_calls(self.c_server) def __dealloc__(self): if self.c_server != NULL: if not self.is_started: pass elif self.is_shutdown: pass elif not self.is_shutting_down: # the user didn't call shutdown - use our backup queue self._c_shutdown(self.backup_shutdown_queue, None) # and now we wait while not self.is_shutdown: self.backup_shutdown_queue.poll() else: # We're in the process of shutting down, but have not shutdown; can't do # much but repeatedly release the GIL and wait while not self.is_shutdown: time.sleep(0) grpc_server_destroy(self.c_server) grpc_shutdown() grpc-1.3.2/src/python/grpcio/grpc/_cython/cygrpc.pxd000066400000000000000000000034151310511640000224370ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include "_cygrpc/grpc.pxi" include "_cygrpc/call.pxd.pxi" include "_cygrpc/channel.pxd.pxi" include "_cygrpc/credentials.pxd.pxi" include "_cygrpc/completion_queue.pxd.pxi" include "_cygrpc/records.pxd.pxi" include "_cygrpc/security.pxd.pxi" include "_cygrpc/server.pxd.pxi" grpc-1.3.2/src/python/grpcio/grpc/_cython/cygrpc.pyx000066400000000000000000000045131310511640000224640ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cimport cpython import pkg_resources import os.path import sys # TODO(atash): figure out why the coverage tool gets confused about the Cython # coverage plugin when the following files don't have a '.pxi' suffix. include "_cygrpc/grpc_string.pyx.pxi" include "_cygrpc/call.pyx.pxi" include "_cygrpc/channel.pyx.pxi" include "_cygrpc/credentials.pyx.pxi" include "_cygrpc/completion_queue.pyx.pxi" include "_cygrpc/records.pyx.pxi" include "_cygrpc/security.pyx.pxi" include "_cygrpc/server.pyx.pxi" # # initialize gRPC # cdef extern from "Python.h": int PyEval_InitThreads() cdef _initialize(): # We have Python callbacks called by c-core threads, this ensures the GIL # is initialized. PyEval_InitThreads() grpc_set_ssl_roots_override_callback( ssl_roots_override_callback) _initialize() grpc-1.3.2/src/python/grpcio/grpc/_plugin_wrapping.py000066400000000000000000000107721310511640000227120ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import collections import threading import grpc from grpc import _common from grpc._cython import cygrpc class AuthMetadataContext( collections.namedtuple('AuthMetadataContext', ( 'service_url', 'method_name',)), grpc.AuthMetadataContext): pass class AuthMetadataPluginCallback(grpc.AuthMetadataContext): def __init__(self, callback): self._callback = callback def __call__(self, metadata, error): self._callback(metadata, error) class _WrappedCygrpcCallback(object): def __init__(self, cygrpc_callback): self.is_called = False self.error = None self.is_called_lock = threading.Lock() self.cygrpc_callback = cygrpc_callback def _invoke_failure(self, error): # TODO(atash) translate different Exception superclasses into different # status codes. self.cygrpc_callback(_common.EMPTY_METADATA, cygrpc.StatusCode.internal, _common.encode(str(error))) def _invoke_success(self, metadata): try: cygrpc_metadata = _common.to_cygrpc_metadata(metadata) except Exception as exception: # pylint: disable=broad-except self._invoke_failure(exception) return self.cygrpc_callback(cygrpc_metadata, cygrpc.StatusCode.ok, b'') def __call__(self, metadata, error): with self.is_called_lock: if self.is_called: raise RuntimeError('callback should only ever be invoked once') if self.error: self._invoke_failure(self.error) return self.is_called = True if error is None: self._invoke_success(metadata) else: self._invoke_failure(error) def notify_failure(self, error): with self.is_called_lock: if not self.is_called: self.error = error class _WrappedPlugin(object): def __init__(self, plugin): self.plugin = plugin def __call__(self, context, cygrpc_callback): wrapped_cygrpc_callback = _WrappedCygrpcCallback(cygrpc_callback) wrapped_context = AuthMetadataContext( _common.decode(context.service_url), _common.decode(context.method_name)) try: self.plugin(wrapped_context, AuthMetadataPluginCallback(wrapped_cygrpc_callback)) except Exception as error: wrapped_cygrpc_callback.notify_failure(error) raise def call_credentials_metadata_plugin(plugin, name): """ Args: plugin: A callable accepting a grpc.AuthMetadataContext object and a callback (itself accepting a list of metadata key/value 2-tuples and a None-able exception value). The callback must be eventually called, but need not be called in plugin's invocation. plugin's invocation must be non-blocking. """ return cygrpc.call_credentials_metadata_plugin( cygrpc.CredentialsMetadataPlugin( _WrappedPlugin(plugin), _common.encode(name))) grpc-1.3.2/src/python/grpcio/grpc/_server.py000066400000000000000000000740431310511640000210140ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Service-side implementation of gRPC Python.""" import collections import enum import logging import threading import time import grpc from grpc import _common from grpc._cython import cygrpc from grpc.framework.foundation import callable_util _SHUTDOWN_TAG = 'shutdown' _REQUEST_CALL_TAG = 'request_call' _RECEIVE_CLOSE_ON_SERVER_TOKEN = 'receive_close_on_server' _SEND_INITIAL_METADATA_TOKEN = 'send_initial_metadata' _RECEIVE_MESSAGE_TOKEN = 'receive_message' _SEND_MESSAGE_TOKEN = 'send_message' _SEND_INITIAL_METADATA_AND_SEND_MESSAGE_TOKEN = ( 'send_initial_metadata * send_message') _SEND_STATUS_FROM_SERVER_TOKEN = 'send_status_from_server' _SEND_INITIAL_METADATA_AND_SEND_STATUS_FROM_SERVER_TOKEN = ( 'send_initial_metadata * send_status_from_server') _OPEN = 'open' _CLOSED = 'closed' _CANCELLED = 'cancelled' _EMPTY_FLAGS = 0 _UNEXPECTED_EXIT_SERVER_GRACE = 1.0 def _serialized_request(request_event): return request_event.batch_operations[0].received_message.bytes() def _application_code(code): cygrpc_code = _common.STATUS_CODE_TO_CYGRPC_STATUS_CODE.get(code) return cygrpc.StatusCode.unknown if cygrpc_code is None else cygrpc_code def _completion_code(state): if state.code is None: return cygrpc.StatusCode.ok else: return _application_code(state.code) def _abortion_code(state, code): if state.code is None: return code else: return _application_code(state.code) def _details(state): return b'' if state.details is None else state.details class _HandlerCallDetails( collections.namedtuple('_HandlerCallDetails', ( 'method', 'invocation_metadata',)), grpc.HandlerCallDetails): pass class _RPCState(object): def __init__(self): self.condition = threading.Condition() self.due = set() self.request = None self.client = _OPEN self.initial_metadata_allowed = True self.disable_next_compression = False self.trailing_metadata = None self.code = None self.details = None self.statused = False self.rpc_errors = [] self.callbacks = [] def _raise_rpc_error(state): rpc_error = grpc.RpcError() state.rpc_errors.append(rpc_error) raise rpc_error def _possibly_finish_call(state, token): state.due.remove(token) if (state.client is _CANCELLED or state.statused) and not state.due: callbacks = state.callbacks state.callbacks = None return state, callbacks else: return None, () def _send_status_from_server(state, token): def send_status_from_server(unused_send_status_from_server_event): with state.condition: return _possibly_finish_call(state, token) return send_status_from_server def _abort(state, call, code, details): if state.client is not _CANCELLED: effective_code = _abortion_code(state, code) effective_details = details if state.details is None else state.details if state.initial_metadata_allowed: operations = (cygrpc.operation_send_initial_metadata( _common.EMPTY_METADATA, _EMPTY_FLAGS), cygrpc.operation_send_status_from_server( _common.to_cygrpc_metadata(state.trailing_metadata), effective_code, effective_details, _EMPTY_FLAGS),) token = _SEND_INITIAL_METADATA_AND_SEND_STATUS_FROM_SERVER_TOKEN else: operations = (cygrpc.operation_send_status_from_server( _common.to_cygrpc_metadata(state.trailing_metadata), effective_code, effective_details, _EMPTY_FLAGS),) token = _SEND_STATUS_FROM_SERVER_TOKEN call.start_server_batch( cygrpc.Operations(operations), _send_status_from_server(state, token)) state.statused = True state.due.add(token) def _receive_close_on_server(state): def receive_close_on_server(receive_close_on_server_event): with state.condition: if receive_close_on_server_event.batch_operations[ 0].received_cancelled: state.client = _CANCELLED elif state.client is _OPEN: state.client = _CLOSED state.condition.notify_all() return _possibly_finish_call(state, _RECEIVE_CLOSE_ON_SERVER_TOKEN) return receive_close_on_server def _receive_message(state, call, request_deserializer): def receive_message(receive_message_event): serialized_request = _serialized_request(receive_message_event) if serialized_request is None: with state.condition: if state.client is _OPEN: state.client = _CLOSED state.condition.notify_all() return _possibly_finish_call(state, _RECEIVE_MESSAGE_TOKEN) else: request = _common.deserialize(serialized_request, request_deserializer) with state.condition: if request is None: _abort(state, call, cygrpc.StatusCode.internal, b'Exception deserializing request!') else: state.request = request state.condition.notify_all() return _possibly_finish_call(state, _RECEIVE_MESSAGE_TOKEN) return receive_message def _send_initial_metadata(state): def send_initial_metadata(unused_send_initial_metadata_event): with state.condition: return _possibly_finish_call(state, _SEND_INITIAL_METADATA_TOKEN) return send_initial_metadata def _send_message(state, token): def send_message(unused_send_message_event): with state.condition: state.condition.notify_all() return _possibly_finish_call(state, token) return send_message class _Context(grpc.ServicerContext): def __init__(self, rpc_event, state, request_deserializer): self._rpc_event = rpc_event self._state = state self._request_deserializer = request_deserializer def is_active(self): with self._state.condition: return self._state.client is not _CANCELLED and not self._state.statused def time_remaining(self): return max( float(self._rpc_event.request_call_details.deadline) - time.time(), 0) def cancel(self): self._rpc_event.operation_call.cancel() def add_callback(self, callback): with self._state.condition: if self._state.callbacks is None: return False else: self._state.callbacks.append(callback) return True def disable_next_message_compression(self): with self._state.condition: self._state.disable_next_compression = True def invocation_metadata(self): return _common.to_application_metadata(self._rpc_event.request_metadata) def peer(self): return _common.decode(self._rpc_event.operation_call.peer()) def send_initial_metadata(self, initial_metadata): with self._state.condition: if self._state.client is _CANCELLED: _raise_rpc_error(self._state) else: if self._state.initial_metadata_allowed: operation = cygrpc.operation_send_initial_metadata( _common.to_cygrpc_metadata(initial_metadata), _EMPTY_FLAGS) self._rpc_event.operation_call.start_server_batch( cygrpc.Operations((operation,)), _send_initial_metadata(self._state)) self._state.initial_metadata_allowed = False self._state.due.add(_SEND_INITIAL_METADATA_TOKEN) else: raise ValueError('Initial metadata no longer allowed!') def set_trailing_metadata(self, trailing_metadata): with self._state.condition: self._state.trailing_metadata = _common.to_cygrpc_metadata( trailing_metadata) def set_code(self, code): with self._state.condition: self._state.code = code def set_details(self, details): with self._state.condition: self._state.details = _common.encode(details) class _RequestIterator(object): def __init__(self, state, call, request_deserializer): self._state = state self._call = call self._request_deserializer = request_deserializer def _raise_or_start_receive_message(self): if self._state.client is _CANCELLED: _raise_rpc_error(self._state) elif self._state.client is _CLOSED or self._state.statused: raise StopIteration() else: self._call.start_server_batch( cygrpc.Operations( (cygrpc.operation_receive_message(_EMPTY_FLAGS),)), _receive_message(self._state, self._call, self._request_deserializer)) self._state.due.add(_RECEIVE_MESSAGE_TOKEN) def _look_for_request(self): if self._state.client is _CANCELLED: _raise_rpc_error(self._state) elif (self._state.request is None and _RECEIVE_MESSAGE_TOKEN not in self._state.due): raise StopIteration() else: request = self._state.request self._state.request = None return request def _next(self): with self._state.condition: self._raise_or_start_receive_message() while True: self._state.condition.wait() request = self._look_for_request() if request is not None: return request def __iter__(self): return self def __next__(self): return self._next() def next(self): return self._next() def _unary_request(rpc_event, state, request_deserializer): def unary_request(): with state.condition: if state.client is _CANCELLED or state.statused: return None else: rpc_event.operation_call.start_server_batch( cygrpc.Operations( (cygrpc.operation_receive_message(_EMPTY_FLAGS),)), _receive_message(state, rpc_event.operation_call, request_deserializer)) state.due.add(_RECEIVE_MESSAGE_TOKEN) while True: state.condition.wait() if state.request is None: if state.client is _CLOSED: details = '"{}" requires exactly one request message.'.format( rpc_event.request_call_details.method) _abort(state, rpc_event.operation_call, cygrpc.StatusCode.unimplemented, _common.encode(details)) return None elif state.client is _CANCELLED: return None else: request = state.request state.request = None return request return unary_request def _call_behavior(rpc_event, state, behavior, argument, request_deserializer): context = _Context(rpc_event, state, request_deserializer) try: return behavior(argument, context), True except Exception as e: # pylint: disable=broad-except with state.condition: if e not in state.rpc_errors: details = 'Exception calling application: {}'.format(e) logging.exception(details) _abort(state, rpc_event.operation_call, cygrpc.StatusCode.unknown, _common.encode(details)) return None, False def _take_response_from_response_iterator(rpc_event, state, response_iterator): try: return next(response_iterator), True except StopIteration: return None, True except Exception as e: # pylint: disable=broad-except with state.condition: if e not in state.rpc_errors: details = 'Exception iterating responses: {}'.format(e) logging.exception(details) _abort(state, rpc_event.operation_call, cygrpc.StatusCode.unknown, _common.encode(details)) return None, False def _serialize_response(rpc_event, state, response, response_serializer): serialized_response = _common.serialize(response, response_serializer) if serialized_response is None: with state.condition: _abort(state, rpc_event.operation_call, cygrpc.StatusCode.internal, b'Failed to serialize response!') return None else: return serialized_response def _send_response(rpc_event, state, serialized_response): with state.condition: if state.client is _CANCELLED or state.statused: return False else: if state.initial_metadata_allowed: operations = (cygrpc.operation_send_initial_metadata( _common.EMPTY_METADATA, _EMPTY_FLAGS), cygrpc.operation_send_message(serialized_response, _EMPTY_FLAGS),) state.initial_metadata_allowed = False token = _SEND_INITIAL_METADATA_AND_SEND_MESSAGE_TOKEN else: operations = (cygrpc.operation_send_message(serialized_response, _EMPTY_FLAGS),) token = _SEND_MESSAGE_TOKEN rpc_event.operation_call.start_server_batch( cygrpc.Operations(operations), _send_message(state, token)) state.due.add(token) while True: state.condition.wait() if token not in state.due: return state.client is not _CANCELLED and not state.statused def _status(rpc_event, state, serialized_response): with state.condition: if state.client is not _CANCELLED: trailing_metadata = _common.to_cygrpc_metadata( state.trailing_metadata) code = _completion_code(state) details = _details(state) operations = [ cygrpc.operation_send_status_from_server( trailing_metadata, code, details, _EMPTY_FLAGS), ] if state.initial_metadata_allowed: operations.append( cygrpc.operation_send_initial_metadata( _common.EMPTY_METADATA, _EMPTY_FLAGS)) if serialized_response is not None: operations.append( cygrpc.operation_send_message(serialized_response, _EMPTY_FLAGS)) rpc_event.operation_call.start_server_batch( cygrpc.Operations(operations), _send_status_from_server(state, _SEND_STATUS_FROM_SERVER_TOKEN)) state.statused = True state.due.add(_SEND_STATUS_FROM_SERVER_TOKEN) def _unary_response_in_pool(rpc_event, state, behavior, argument_thunk, request_deserializer, response_serializer): argument = argument_thunk() if argument is not None: response, proceed = _call_behavior(rpc_event, state, behavior, argument, request_deserializer) if proceed: serialized_response = _serialize_response( rpc_event, state, response, response_serializer) if serialized_response is not None: _status(rpc_event, state, serialized_response) def _stream_response_in_pool(rpc_event, state, behavior, argument_thunk, request_deserializer, response_serializer): argument = argument_thunk() if argument is not None: response_iterator, proceed = _call_behavior( rpc_event, state, behavior, argument, request_deserializer) if proceed: while True: response, proceed = _take_response_from_response_iterator( rpc_event, state, response_iterator) if proceed: if response is None: _status(rpc_event, state, None) break else: serialized_response = _serialize_response( rpc_event, state, response, response_serializer) if serialized_response is not None: proceed = _send_response(rpc_event, state, serialized_response) if not proceed: break else: break else: break def _handle_unary_unary(rpc_event, state, method_handler, thread_pool): unary_request = _unary_request(rpc_event, state, method_handler.request_deserializer) return thread_pool.submit(_unary_response_in_pool, rpc_event, state, method_handler.unary_unary, unary_request, method_handler.request_deserializer, method_handler.response_serializer) def _handle_unary_stream(rpc_event, state, method_handler, thread_pool): unary_request = _unary_request(rpc_event, state, method_handler.request_deserializer) return thread_pool.submit(_stream_response_in_pool, rpc_event, state, method_handler.unary_stream, unary_request, method_handler.request_deserializer, method_handler.response_serializer) def _handle_stream_unary(rpc_event, state, method_handler, thread_pool): request_iterator = _RequestIterator(state, rpc_event.operation_call, method_handler.request_deserializer) return thread_pool.submit( _unary_response_in_pool, rpc_event, state, method_handler.stream_unary, lambda: request_iterator, method_handler.request_deserializer, method_handler.response_serializer) def _handle_stream_stream(rpc_event, state, method_handler, thread_pool): request_iterator = _RequestIterator(state, rpc_event.operation_call, method_handler.request_deserializer) return thread_pool.submit( _stream_response_in_pool, rpc_event, state, method_handler.stream_stream, lambda: request_iterator, method_handler.request_deserializer, method_handler.response_serializer) def _find_method_handler(rpc_event, generic_handlers): for generic_handler in generic_handlers: method_handler = generic_handler.service( _HandlerCallDetails( _common.decode(rpc_event.request_call_details.method), rpc_event.request_metadata)) if method_handler is not None: return method_handler else: return None def _reject_rpc(rpc_event, status, details): operations = (cygrpc.operation_send_initial_metadata(_common.EMPTY_METADATA, _EMPTY_FLAGS), cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS), cygrpc.operation_send_status_from_server( _common.EMPTY_METADATA, status, details, _EMPTY_FLAGS),) rpc_state = _RPCState() rpc_event.operation_call.start_server_batch( operations, lambda ignored_event: (rpc_state, (),)) return rpc_state def _handle_with_method_handler(rpc_event, method_handler, thread_pool): state = _RPCState() with state.condition: rpc_event.operation_call.start_server_batch( cygrpc.Operations( (cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS),)), _receive_close_on_server(state)) state.due.add(_RECEIVE_CLOSE_ON_SERVER_TOKEN) if method_handler.request_streaming: if method_handler.response_streaming: return state, _handle_stream_stream(rpc_event, state, method_handler, thread_pool) else: return state, _handle_stream_unary(rpc_event, state, method_handler, thread_pool) else: if method_handler.response_streaming: return state, _handle_unary_stream(rpc_event, state, method_handler, thread_pool) else: return state, _handle_unary_unary(rpc_event, state, method_handler, thread_pool) def _handle_call(rpc_event, generic_handlers, thread_pool, concurrency_exceeded): if not rpc_event.success: return None, None if rpc_event.request_call_details.method is not None: method_handler = _find_method_handler(rpc_event, generic_handlers) if method_handler is None: return _reject_rpc(rpc_event, cygrpc.StatusCode.unimplemented, b'Method not found!'), None elif concurrency_exceeded: return _reject_rpc(rpc_event, cygrpc.StatusCode.resource_exhausted, b'Concurrent RPC limit exceeded!'), None else: return _handle_with_method_handler(rpc_event, method_handler, thread_pool) else: return None, None @enum.unique class _ServerStage(enum.Enum): STOPPED = 'stopped' STARTED = 'started' GRACE = 'grace' class _ServerState(object): def __init__(self, completion_queue, server, generic_handlers, thread_pool, maximum_concurrent_rpcs): self.lock = threading.Lock() self.completion_queue = completion_queue self.server = server self.generic_handlers = list(generic_handlers) self.thread_pool = thread_pool self.stage = _ServerStage.STOPPED self.shutdown_events = None self.maximum_concurrent_rpcs = maximum_concurrent_rpcs self.active_rpc_count = 0 # TODO(https://github.com/grpc/grpc/issues/6597): eliminate these fields. self.rpc_states = set() self.due = set() def _add_generic_handlers(state, generic_handlers): with state.lock: state.generic_handlers.extend(generic_handlers) def _add_insecure_port(state, address): with state.lock: return state.server.add_http2_port(address) def _add_secure_port(state, address, server_credentials): with state.lock: return state.server.add_http2_port(address, server_credentials._credentials) def _request_call(state): state.server.request_call(state.completion_queue, state.completion_queue, _REQUEST_CALL_TAG) state.due.add(_REQUEST_CALL_TAG) # TODO(https://github.com/grpc/grpc/issues/6597): delete this function. def _stop_serving(state): if not state.rpc_states and not state.due: for shutdown_event in state.shutdown_events: shutdown_event.set() state.stage = _ServerStage.STOPPED return True else: return False def _on_call_completed(state): with state.lock: state.active_rpc_count -= 1 def _serve(state): while True: event = state.completion_queue.poll() if event.tag is _SHUTDOWN_TAG: with state.lock: state.due.remove(_SHUTDOWN_TAG) if _stop_serving(state): return elif event.tag is _REQUEST_CALL_TAG: with state.lock: state.due.remove(_REQUEST_CALL_TAG) concurrency_exceeded = ( state.maximum_concurrent_rpcs is not None and state.active_rpc_count >= state.maximum_concurrent_rpcs) rpc_state, rpc_future = _handle_call( event, state.generic_handlers, state.thread_pool, concurrency_exceeded) if rpc_state is not None: state.rpc_states.add(rpc_state) if rpc_future is not None: state.active_rpc_count += 1 rpc_future.add_done_callback( lambda unused_future: _on_call_completed(state)) if state.stage is _ServerStage.STARTED: _request_call(state) elif _stop_serving(state): return else: rpc_state, callbacks = event.tag(event) for callback in callbacks: callable_util.call_logging_exceptions( callback, 'Exception calling callback!') if rpc_state is not None: with state.lock: state.rpc_states.remove(rpc_state) if _stop_serving(state): return # We want to force the deletion of the previous event # ~before~ we poll again; if the event has a reference # to a shutdown Call object, this can induce spinlock. event = None def _stop(state, grace): with state.lock: if state.stage is _ServerStage.STOPPED: shutdown_event = threading.Event() shutdown_event.set() return shutdown_event else: if state.stage is _ServerStage.STARTED: state.server.shutdown(state.completion_queue, _SHUTDOWN_TAG) state.stage = _ServerStage.GRACE state.shutdown_events = [] state.due.add(_SHUTDOWN_TAG) shutdown_event = threading.Event() state.shutdown_events.append(shutdown_event) if grace is None: state.server.cancel_all_calls() # TODO(https://github.com/grpc/grpc/issues/6597): delete this loop. for rpc_state in state.rpc_states: with rpc_state.condition: rpc_state.client = _CANCELLED rpc_state.condition.notify_all() else: def cancel_all_calls_after_grace(): shutdown_event.wait(timeout=grace) with state.lock: state.server.cancel_all_calls() # TODO(https://github.com/grpc/grpc/issues/6597): delete this loop. for rpc_state in state.rpc_states: with rpc_state.condition: rpc_state.client = _CANCELLED rpc_state.condition.notify_all() thread = threading.Thread(target=cancel_all_calls_after_grace) thread.start() return shutdown_event shutdown_event.wait() return shutdown_event def _start(state): with state.lock: if state.stage is not _ServerStage.STOPPED: raise ValueError('Cannot start already-started server!') state.server.start() state.stage = _ServerStage.STARTED _request_call(state) def cleanup_server(timeout): if timeout is None: _stop(state, _UNEXPECTED_EXIT_SERVER_GRACE).wait() else: _stop(state, timeout).wait() thread = _common.CleanupThread( cleanup_server, target=_serve, args=(state,)) thread.start() class Server(grpc.Server): def __init__(self, thread_pool, generic_handlers, options, maximum_concurrent_rpcs): completion_queue = cygrpc.CompletionQueue() server = cygrpc.Server(_common.channel_args(options)) server.register_completion_queue(completion_queue) self._state = _ServerState(completion_queue, server, generic_handlers, thread_pool, maximum_concurrent_rpcs) def add_generic_rpc_handlers(self, generic_rpc_handlers): _add_generic_handlers(self._state, generic_rpc_handlers) def add_insecure_port(self, address): return _add_insecure_port(self._state, _common.encode(address)) def add_secure_port(self, address, server_credentials): return _add_secure_port(self._state, _common.encode(address), server_credentials) def start(self): _start(self._state) def stop(self, grace): return _stop(self._state, grace) def __del__(self): _stop(self._state, None) grpc-1.3.2/src/python/grpcio/grpc/_utilities.py000066400000000000000000000135321310511640000215150ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Internal utilities for gRPC Python.""" import collections import threading import time import six import grpc from grpc import _common from grpc.framework.foundation import callable_util _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE = ( 'Exception calling connectivity future "done" callback!') class RpcMethodHandler( collections.namedtuple('_RpcMethodHandler', ( 'request_streaming', 'response_streaming', 'request_deserializer', 'response_serializer', 'unary_unary', 'unary_stream', 'stream_unary', 'stream_stream',)), grpc.RpcMethodHandler): pass class DictionaryGenericHandler(grpc.ServiceRpcHandler): def __init__(self, service, method_handlers): self._name = service self._method_handlers = { _common.fully_qualified_method(service, method): method_handler for method, method_handler in six.iteritems(method_handlers) } def service_name(self): return self._name def service(self, handler_call_details): return self._method_handlers.get(handler_call_details.method) class _ChannelReadyFuture(grpc.Future): def __init__(self, channel): self._condition = threading.Condition() self._channel = channel self._matured = False self._cancelled = False self._done_callbacks = [] def _block(self, timeout): until = None if timeout is None else time.time() + timeout with self._condition: while True: if self._cancelled: raise grpc.FutureCancelledError() elif self._matured: return else: if until is None: self._condition.wait() else: remaining = until - time.time() if remaining < 0: raise grpc.FutureTimeoutError() else: self._condition.wait(timeout=remaining) def _update(self, connectivity): with self._condition: if (not self._cancelled and connectivity is grpc.ChannelConnectivity.READY): self._matured = True self._channel.unsubscribe(self._update) self._condition.notify_all() done_callbacks = tuple(self._done_callbacks) self._done_callbacks = None else: return for done_callback in done_callbacks: callable_util.call_logging_exceptions( done_callback, _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE, self) def cancel(self): with self._condition: if not self._matured: self._cancelled = True self._channel.unsubscribe(self._update) self._condition.notify_all() done_callbacks = tuple(self._done_callbacks) self._done_callbacks = None else: return False for done_callback in done_callbacks: callable_util.call_logging_exceptions( done_callback, _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE, self) def cancelled(self): with self._condition: return self._cancelled def running(self): with self._condition: return not self._cancelled and not self._matured def done(self): with self._condition: return self._cancelled or self._matured def result(self, timeout=None): self._block(timeout) return None def exception(self, timeout=None): self._block(timeout) return None def traceback(self, timeout=None): self._block(timeout) return None def add_done_callback(self, fn): with self._condition: if not self._cancelled and not self._matured: self._done_callbacks.append(fn) return fn(self) def start(self): with self._condition: self._channel.subscribe(self._update, try_to_connect=True) def __del__(self): with self._condition: if not self._cancelled and not self._matured: self._channel.unsubscribe(self._update) def channel_ready_future(channel): ready_future = _ChannelReadyFuture(channel) ready_future.start() return ready_future grpc-1.3.2/src/python/grpcio/grpc/beta/000077500000000000000000000000001310511640000177005ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio/grpc/beta/__init__.py000066400000000000000000000027701310511640000220170ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio/grpc/beta/_client_adaptations.py000066400000000000000000000646561310511640000242770ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Translates gRPC's client-side API into gRPC's client-side Beta API.""" import grpc from grpc import _common from grpc.beta import interfaces from grpc.framework.common import cardinality from grpc.framework.foundation import future from grpc.framework.interfaces.face import face # pylint: disable=too-many-arguments,too-many-locals,unused-argument _STATUS_CODE_TO_ABORTION_KIND_AND_ABORTION_ERROR_CLASS = { grpc.StatusCode.CANCELLED: (face.Abortion.Kind.CANCELLED, face.CancellationError), grpc.StatusCode.UNKNOWN: (face.Abortion.Kind.REMOTE_FAILURE, face.RemoteError), grpc.StatusCode.DEADLINE_EXCEEDED: (face.Abortion.Kind.EXPIRED, face.ExpirationError), grpc.StatusCode.UNIMPLEMENTED: (face.Abortion.Kind.LOCAL_FAILURE, face.LocalError), } def _effective_metadata(metadata, metadata_transformer): non_none_metadata = () if metadata is None else metadata if metadata_transformer is None: return non_none_metadata else: return metadata_transformer(non_none_metadata) def _credentials(grpc_call_options): return None if grpc_call_options is None else grpc_call_options.credentials def _abortion(rpc_error_call): code = rpc_error_call.code() pair = _STATUS_CODE_TO_ABORTION_KIND_AND_ABORTION_ERROR_CLASS.get(code) error_kind = face.Abortion.Kind.LOCAL_FAILURE if pair is None else pair[0] return face.Abortion(error_kind, rpc_error_call.initial_metadata(), rpc_error_call.trailing_metadata(), code, rpc_error_call.details()) def _abortion_error(rpc_error_call): code = rpc_error_call.code() pair = _STATUS_CODE_TO_ABORTION_KIND_AND_ABORTION_ERROR_CLASS.get(code) exception_class = face.AbortionError if pair is None else pair[1] return exception_class(rpc_error_call.initial_metadata(), rpc_error_call.trailing_metadata(), code, rpc_error_call.details()) class _InvocationProtocolContext(interfaces.GRPCInvocationContext): def disable_next_request_compression(self): pass # TODO(https://github.com/grpc/grpc/issues/4078): design, implement. class _Rendezvous(future.Future, face.Call): def __init__(self, response_future, response_iterator, call): self._future = response_future self._iterator = response_iterator self._call = call def cancel(self): return self._call.cancel() def cancelled(self): return self._future.cancelled() def running(self): return self._future.running() def done(self): return self._future.done() def result(self, timeout=None): try: return self._future.result(timeout=timeout) except grpc.RpcError as rpc_error_call: raise _abortion_error(rpc_error_call) except grpc.FutureTimeoutError: raise future.TimeoutError() except grpc.FutureCancelledError: raise future.CancelledError() def exception(self, timeout=None): try: rpc_error_call = self._future.exception(timeout=timeout) if rpc_error_call is None: return None else: return _abortion_error(rpc_error_call) except grpc.FutureTimeoutError: raise future.TimeoutError() except grpc.FutureCancelledError: raise future.CancelledError() def traceback(self, timeout=None): try: return self._future.traceback(timeout=timeout) except grpc.FutureTimeoutError: raise future.TimeoutError() except grpc.FutureCancelledError: raise future.CancelledError() def add_done_callback(self, fn): self._future.add_done_callback(lambda ignored_callback: fn(self)) def __iter__(self): return self def _next(self): try: return next(self._iterator) except grpc.RpcError as rpc_error_call: raise _abortion_error(rpc_error_call) def __next__(self): return self._next() def next(self): return self._next() def is_active(self): return self._call.is_active() def time_remaining(self): return self._call.time_remaining() def add_abortion_callback(self, abortion_callback): def done_callback(): if self.code() is not grpc.StatusCode.OK: abortion_callback(_abortion(self._call)) registered = self._call.add_callback(done_callback) return None if registered else done_callback() def protocol_context(self): return _InvocationProtocolContext() def initial_metadata(self): return self._call.initial_metadata() def terminal_metadata(self): return self._call.terminal_metadata() def code(self): return self._call.code() def details(self): return self._call.details() def _blocking_unary_unary(channel, group, method, timeout, with_call, protocol_options, metadata, metadata_transformer, request, request_serializer, response_deserializer): try: multi_callable = channel.unary_unary( _common.fully_qualified_method(group, method), request_serializer=request_serializer, response_deserializer=response_deserializer) effective_metadata = _effective_metadata(metadata, metadata_transformer) if with_call: response, call = multi_callable.with_call( request, timeout=timeout, metadata=effective_metadata, credentials=_credentials(protocol_options)) return response, _Rendezvous(None, None, call) else: return multi_callable( request, timeout=timeout, metadata=effective_metadata, credentials=_credentials(protocol_options)) except grpc.RpcError as rpc_error_call: raise _abortion_error(rpc_error_call) def _future_unary_unary(channel, group, method, timeout, protocol_options, metadata, metadata_transformer, request, request_serializer, response_deserializer): multi_callable = channel.unary_unary( _common.fully_qualified_method(group, method), request_serializer=request_serializer, response_deserializer=response_deserializer) effective_metadata = _effective_metadata(metadata, metadata_transformer) response_future = multi_callable.future( request, timeout=timeout, metadata=effective_metadata, credentials=_credentials(protocol_options)) return _Rendezvous(response_future, None, response_future) def _unary_stream(channel, group, method, timeout, protocol_options, metadata, metadata_transformer, request, request_serializer, response_deserializer): multi_callable = channel.unary_stream( _common.fully_qualified_method(group, method), request_serializer=request_serializer, response_deserializer=response_deserializer) effective_metadata = _effective_metadata(metadata, metadata_transformer) response_iterator = multi_callable( request, timeout=timeout, metadata=effective_metadata, credentials=_credentials(protocol_options)) return _Rendezvous(None, response_iterator, response_iterator) def _blocking_stream_unary(channel, group, method, timeout, with_call, protocol_options, metadata, metadata_transformer, request_iterator, request_serializer, response_deserializer): try: multi_callable = channel.stream_unary( _common.fully_qualified_method(group, method), request_serializer=request_serializer, response_deserializer=response_deserializer) effective_metadata = _effective_metadata(metadata, metadata_transformer) if with_call: response, call = multi_callable.with_call( request_iterator, timeout=timeout, metadata=effective_metadata, credentials=_credentials(protocol_options)) return response, _Rendezvous(None, None, call) else: return multi_callable( request_iterator, timeout=timeout, metadata=effective_metadata, credentials=_credentials(protocol_options)) except grpc.RpcError as rpc_error_call: raise _abortion_error(rpc_error_call) def _future_stream_unary(channel, group, method, timeout, protocol_options, metadata, metadata_transformer, request_iterator, request_serializer, response_deserializer): multi_callable = channel.stream_unary( _common.fully_qualified_method(group, method), request_serializer=request_serializer, response_deserializer=response_deserializer) effective_metadata = _effective_metadata(metadata, metadata_transformer) response_future = multi_callable.future( request_iterator, timeout=timeout, metadata=effective_metadata, credentials=_credentials(protocol_options)) return _Rendezvous(response_future, None, response_future) def _stream_stream(channel, group, method, timeout, protocol_options, metadata, metadata_transformer, request_iterator, request_serializer, response_deserializer): multi_callable = channel.stream_stream( _common.fully_qualified_method(group, method), request_serializer=request_serializer, response_deserializer=response_deserializer) effective_metadata = _effective_metadata(metadata, metadata_transformer) response_iterator = multi_callable( request_iterator, timeout=timeout, metadata=effective_metadata, credentials=_credentials(protocol_options)) return _Rendezvous(None, response_iterator, response_iterator) class _UnaryUnaryMultiCallable(face.UnaryUnaryMultiCallable): def __init__(self, channel, group, method, metadata_transformer, request_serializer, response_deserializer): self._channel = channel self._group = group self._method = method self._metadata_transformer = metadata_transformer self._request_serializer = request_serializer self._response_deserializer = response_deserializer def __call__(self, request, timeout, metadata=None, with_call=False, protocol_options=None): return _blocking_unary_unary( self._channel, self._group, self._method, timeout, with_call, protocol_options, metadata, self._metadata_transformer, request, self._request_serializer, self._response_deserializer) def future(self, request, timeout, metadata=None, protocol_options=None): return _future_unary_unary( self._channel, self._group, self._method, timeout, protocol_options, metadata, self._metadata_transformer, request, self._request_serializer, self._response_deserializer) def event(self, request, receiver, abortion_callback, timeout, metadata=None, protocol_options=None): raise NotImplementedError() class _UnaryStreamMultiCallable(face.UnaryStreamMultiCallable): def __init__(self, channel, group, method, metadata_transformer, request_serializer, response_deserializer): self._channel = channel self._group = group self._method = method self._metadata_transformer = metadata_transformer self._request_serializer = request_serializer self._response_deserializer = response_deserializer def __call__(self, request, timeout, metadata=None, protocol_options=None): return _unary_stream( self._channel, self._group, self._method, timeout, protocol_options, metadata, self._metadata_transformer, request, self._request_serializer, self._response_deserializer) def event(self, request, receiver, abortion_callback, timeout, metadata=None, protocol_options=None): raise NotImplementedError() class _StreamUnaryMultiCallable(face.StreamUnaryMultiCallable): def __init__(self, channel, group, method, metadata_transformer, request_serializer, response_deserializer): self._channel = channel self._group = group self._method = method self._metadata_transformer = metadata_transformer self._request_serializer = request_serializer self._response_deserializer = response_deserializer def __call__(self, request_iterator, timeout, metadata=None, with_call=False, protocol_options=None): return _blocking_stream_unary( self._channel, self._group, self._method, timeout, with_call, protocol_options, metadata, self._metadata_transformer, request_iterator, self._request_serializer, self._response_deserializer) def future(self, request_iterator, timeout, metadata=None, protocol_options=None): return _future_stream_unary( self._channel, self._group, self._method, timeout, protocol_options, metadata, self._metadata_transformer, request_iterator, self._request_serializer, self._response_deserializer) def event(self, receiver, abortion_callback, timeout, metadata=None, protocol_options=None): raise NotImplementedError() class _StreamStreamMultiCallable(face.StreamStreamMultiCallable): def __init__(self, channel, group, method, metadata_transformer, request_serializer, response_deserializer): self._channel = channel self._group = group self._method = method self._metadata_transformer = metadata_transformer self._request_serializer = request_serializer self._response_deserializer = response_deserializer def __call__(self, request_iterator, timeout, metadata=None, protocol_options=None): return _stream_stream( self._channel, self._group, self._method, timeout, protocol_options, metadata, self._metadata_transformer, request_iterator, self._request_serializer, self._response_deserializer) def event(self, receiver, abortion_callback, timeout, metadata=None, protocol_options=None): raise NotImplementedError() class _GenericStub(face.GenericStub): def __init__(self, channel, metadata_transformer, request_serializers, response_deserializers): self._channel = channel self._metadata_transformer = metadata_transformer self._request_serializers = request_serializers or {} self._response_deserializers = response_deserializers or {} def blocking_unary_unary(self, group, method, request, timeout, metadata=None, with_call=None, protocol_options=None): request_serializer = self._request_serializers.get((group, method,)) response_deserializer = self._response_deserializers.get((group, method,)) return _blocking_unary_unary(self._channel, group, method, timeout, with_call, protocol_options, metadata, self._metadata_transformer, request, request_serializer, response_deserializer) def future_unary_unary(self, group, method, request, timeout, metadata=None, protocol_options=None): request_serializer = self._request_serializers.get((group, method,)) response_deserializer = self._response_deserializers.get((group, method,)) return _future_unary_unary(self._channel, group, method, timeout, protocol_options, metadata, self._metadata_transformer, request, request_serializer, response_deserializer) def inline_unary_stream(self, group, method, request, timeout, metadata=None, protocol_options=None): request_serializer = self._request_serializers.get((group, method,)) response_deserializer = self._response_deserializers.get((group, method,)) return _unary_stream(self._channel, group, method, timeout, protocol_options, metadata, self._metadata_transformer, request, request_serializer, response_deserializer) def blocking_stream_unary(self, group, method, request_iterator, timeout, metadata=None, with_call=None, protocol_options=None): request_serializer = self._request_serializers.get((group, method,)) response_deserializer = self._response_deserializers.get((group, method,)) return _blocking_stream_unary( self._channel, group, method, timeout, with_call, protocol_options, metadata, self._metadata_transformer, request_iterator, request_serializer, response_deserializer) def future_stream_unary(self, group, method, request_iterator, timeout, metadata=None, protocol_options=None): request_serializer = self._request_serializers.get((group, method,)) response_deserializer = self._response_deserializers.get((group, method,)) return _future_stream_unary( self._channel, group, method, timeout, protocol_options, metadata, self._metadata_transformer, request_iterator, request_serializer, response_deserializer) def inline_stream_stream(self, group, method, request_iterator, timeout, metadata=None, protocol_options=None): request_serializer = self._request_serializers.get((group, method,)) response_deserializer = self._response_deserializers.get((group, method,)) return _stream_stream(self._channel, group, method, timeout, protocol_options, metadata, self._metadata_transformer, request_iterator, request_serializer, response_deserializer) def event_unary_unary(self, group, method, request, receiver, abortion_callback, timeout, metadata=None, protocol_options=None): raise NotImplementedError() def event_unary_stream(self, group, method, request, receiver, abortion_callback, timeout, metadata=None, protocol_options=None): raise NotImplementedError() def event_stream_unary(self, group, method, receiver, abortion_callback, timeout, metadata=None, protocol_options=None): raise NotImplementedError() def event_stream_stream(self, group, method, receiver, abortion_callback, timeout, metadata=None, protocol_options=None): raise NotImplementedError() def unary_unary(self, group, method): request_serializer = self._request_serializers.get((group, method,)) response_deserializer = self._response_deserializers.get((group, method,)) return _UnaryUnaryMultiCallable( self._channel, group, method, self._metadata_transformer, request_serializer, response_deserializer) def unary_stream(self, group, method): request_serializer = self._request_serializers.get((group, method,)) response_deserializer = self._response_deserializers.get((group, method,)) return _UnaryStreamMultiCallable( self._channel, group, method, self._metadata_transformer, request_serializer, response_deserializer) def stream_unary(self, group, method): request_serializer = self._request_serializers.get((group, method,)) response_deserializer = self._response_deserializers.get((group, method,)) return _StreamUnaryMultiCallable( self._channel, group, method, self._metadata_transformer, request_serializer, response_deserializer) def stream_stream(self, group, method): request_serializer = self._request_serializers.get((group, method,)) response_deserializer = self._response_deserializers.get((group, method,)) return _StreamStreamMultiCallable( self._channel, group, method, self._metadata_transformer, request_serializer, response_deserializer) def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): return False class _DynamicStub(face.DynamicStub): def __init__(self, backing_generic_stub, group, cardinalities): self._generic_stub = backing_generic_stub self._group = group self._cardinalities = cardinalities def __getattr__(self, attr): method_cardinality = self._cardinalities.get(attr) if method_cardinality is cardinality.Cardinality.UNARY_UNARY: return self._generic_stub.unary_unary(self._group, attr) elif method_cardinality is cardinality.Cardinality.UNARY_STREAM: return self._generic_stub.unary_stream(self._group, attr) elif method_cardinality is cardinality.Cardinality.STREAM_UNARY: return self._generic_stub.stream_unary(self._group, attr) elif method_cardinality is cardinality.Cardinality.STREAM_STREAM: return self._generic_stub.stream_stream(self._group, attr) else: raise AttributeError('_DynamicStub object has no attribute "%s"!' % attr) def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): return False def generic_stub(channel, host, metadata_transformer, request_serializers, response_deserializers): return _GenericStub(channel, metadata_transformer, request_serializers, response_deserializers) def dynamic_stub(channel, service, cardinalities, host, metadata_transformer, request_serializers, response_deserializers): return _DynamicStub( _GenericStub(channel, metadata_transformer, request_serializers, response_deserializers), service, cardinalities) grpc-1.3.2/src/python/grpcio/grpc/beta/_server_adaptations.py000066400000000000000000000346451310511640000243220ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Translates gRPC's server-side API into gRPC's server-side Beta API.""" import collections import threading import grpc from grpc import _common from grpc.beta import interfaces from grpc.framework.common import cardinality from grpc.framework.common import style from grpc.framework.foundation import abandonment from grpc.framework.foundation import logging_pool from grpc.framework.foundation import stream from grpc.framework.interfaces.face import face # pylint: disable=too-many-return-statements _DEFAULT_POOL_SIZE = 8 class _ServerProtocolContext(interfaces.GRPCServicerContext): def __init__(self, servicer_context): self._servicer_context = servicer_context def peer(self): return self._servicer_context.peer() def disable_next_response_compression(self): pass # TODO(https://github.com/grpc/grpc/issues/4078): design, implement. class _FaceServicerContext(face.ServicerContext): def __init__(self, servicer_context): self._servicer_context = servicer_context def is_active(self): return self._servicer_context.is_active() def time_remaining(self): return self._servicer_context.time_remaining() def add_abortion_callback(self, abortion_callback): raise NotImplementedError( 'add_abortion_callback no longer supported server-side!') def cancel(self): self._servicer_context.cancel() def protocol_context(self): return _ServerProtocolContext(self._servicer_context) def invocation_metadata(self): return _common.to_cygrpc_metadata( self._servicer_context.invocation_metadata()) def initial_metadata(self, initial_metadata): self._servicer_context.send_initial_metadata(initial_metadata) def terminal_metadata(self, terminal_metadata): self._servicer_context.set_terminal_metadata(terminal_metadata) def code(self, code): self._servicer_context.set_code(code) def details(self, details): self._servicer_context.set_details(details) def _adapt_unary_request_inline(unary_request_inline): def adaptation(request, servicer_context): return unary_request_inline(request, _FaceServicerContext(servicer_context)) return adaptation def _adapt_stream_request_inline(stream_request_inline): def adaptation(request_iterator, servicer_context): return stream_request_inline(request_iterator, _FaceServicerContext(servicer_context)) return adaptation class _Callback(stream.Consumer): def __init__(self): self._condition = threading.Condition() self._values = [] self._terminated = False self._cancelled = False def consume(self, value): with self._condition: self._values.append(value) self._condition.notify_all() def terminate(self): with self._condition: self._terminated = True self._condition.notify_all() def consume_and_terminate(self, value): with self._condition: self._values.append(value) self._terminated = True self._condition.notify_all() def cancel(self): with self._condition: self._cancelled = True self._condition.notify_all() def draw_one_value(self): with self._condition: while True: if self._cancelled: raise abandonment.Abandoned() elif self._values: return self._values.pop(0) elif self._terminated: return None else: self._condition.wait() def draw_all_values(self): with self._condition: while True: if self._cancelled: raise abandonment.Abandoned() elif self._terminated: all_values = tuple(self._values) self._values = None return all_values else: self._condition.wait() def _run_request_pipe_thread(request_iterator, request_consumer, servicer_context): thread_joined = threading.Event() def pipe_requests(): for request in request_iterator: if not servicer_context.is_active() or thread_joined.is_set(): return request_consumer.consume(request) if not servicer_context.is_active() or thread_joined.is_set(): return request_consumer.terminate() def stop_request_pipe(timeout): # pylint: disable=unused-argument thread_joined.set() request_pipe_thread = _common.CleanupThread( stop_request_pipe, target=pipe_requests) request_pipe_thread.start() def _adapt_unary_unary_event(unary_unary_event): def adaptation(request, servicer_context): callback = _Callback() if not servicer_context.add_callback(callback.cancel): raise abandonment.Abandoned() unary_unary_event(request, callback.consume_and_terminate, _FaceServicerContext(servicer_context)) return callback.draw_all_values()[0] return adaptation def _adapt_unary_stream_event(unary_stream_event): def adaptation(request, servicer_context): callback = _Callback() if not servicer_context.add_callback(callback.cancel): raise abandonment.Abandoned() unary_stream_event(request, callback, _FaceServicerContext(servicer_context)) while True: response = callback.draw_one_value() if response is None: return else: yield response return adaptation def _adapt_stream_unary_event(stream_unary_event): def adaptation(request_iterator, servicer_context): callback = _Callback() if not servicer_context.add_callback(callback.cancel): raise abandonment.Abandoned() request_consumer = stream_unary_event( callback.consume_and_terminate, _FaceServicerContext(servicer_context)) _run_request_pipe_thread(request_iterator, request_consumer, servicer_context) return callback.draw_all_values()[0] return adaptation def _adapt_stream_stream_event(stream_stream_event): def adaptation(request_iterator, servicer_context): callback = _Callback() if not servicer_context.add_callback(callback.cancel): raise abandonment.Abandoned() request_consumer = stream_stream_event( callback, _FaceServicerContext(servicer_context)) _run_request_pipe_thread(request_iterator, request_consumer, servicer_context) while True: response = callback.draw_one_value() if response is None: return else: yield response return adaptation class _SimpleMethodHandler( collections.namedtuple('_MethodHandler', ( 'request_streaming', 'response_streaming', 'request_deserializer', 'response_serializer', 'unary_unary', 'unary_stream', 'stream_unary', 'stream_stream',)), grpc.RpcMethodHandler): pass def _simple_method_handler(implementation, request_deserializer, response_serializer): if implementation.style is style.Service.INLINE: if implementation.cardinality is cardinality.Cardinality.UNARY_UNARY: return _SimpleMethodHandler( False, False, request_deserializer, response_serializer, _adapt_unary_request_inline(implementation.unary_unary_inline), None, None, None) elif implementation.cardinality is cardinality.Cardinality.UNARY_STREAM: return _SimpleMethodHandler( False, True, request_deserializer, response_serializer, None, _adapt_unary_request_inline(implementation.unary_stream_inline), None, None) elif implementation.cardinality is cardinality.Cardinality.STREAM_UNARY: return _SimpleMethodHandler(True, False, request_deserializer, response_serializer, None, None, _adapt_stream_request_inline( implementation.stream_unary_inline), None) elif implementation.cardinality is cardinality.Cardinality.STREAM_STREAM: return _SimpleMethodHandler( True, True, request_deserializer, response_serializer, None, None, None, _adapt_stream_request_inline( implementation.stream_stream_inline)) elif implementation.style is style.Service.EVENT: if implementation.cardinality is cardinality.Cardinality.UNARY_UNARY: return _SimpleMethodHandler( False, False, request_deserializer, response_serializer, _adapt_unary_unary_event(implementation.unary_unary_event), None, None, None) elif implementation.cardinality is cardinality.Cardinality.UNARY_STREAM: return _SimpleMethodHandler( False, True, request_deserializer, response_serializer, None, _adapt_unary_stream_event(implementation.unary_stream_event), None, None) elif implementation.cardinality is cardinality.Cardinality.STREAM_UNARY: return _SimpleMethodHandler( True, False, request_deserializer, response_serializer, None, None, _adapt_stream_unary_event(implementation.stream_unary_event), None) elif implementation.cardinality is cardinality.Cardinality.STREAM_STREAM: return _SimpleMethodHandler( True, True, request_deserializer, response_serializer, None, None, None, _adapt_stream_stream_event(implementation.stream_stream_event)) def _flatten_method_pair_map(method_pair_map): method_pair_map = method_pair_map or {} flat_map = {} for method_pair in method_pair_map: method = _common.fully_qualified_method(method_pair[0], method_pair[1]) flat_map[method] = method_pair_map[method_pair] return flat_map class _GenericRpcHandler(grpc.GenericRpcHandler): def __init__(self, method_implementations, multi_method_implementation, request_deserializers, response_serializers): self._method_implementations = _flatten_method_pair_map( method_implementations) self._request_deserializers = _flatten_method_pair_map( request_deserializers) self._response_serializers = _flatten_method_pair_map( response_serializers) self._multi_method_implementation = multi_method_implementation def service(self, handler_call_details): method_implementation = self._method_implementations.get( handler_call_details.method) if method_implementation is not None: return _simple_method_handler( method_implementation, self._request_deserializers.get(handler_call_details.method), self._response_serializers.get(handler_call_details.method)) elif self._multi_method_implementation is None: return None else: try: return None #TODO(nathaniel): call the multimethod. except face.NoSuchMethodError: return None class _Server(interfaces.Server): def __init__(self, grpc_server): self._grpc_server = grpc_server def add_insecure_port(self, address): return self._grpc_server.add_insecure_port(address) def add_secure_port(self, address, server_credentials): return self._grpc_server.add_secure_port(address, server_credentials) def start(self): self._grpc_server.start() def stop(self, grace): return self._grpc_server.stop(grace) def __enter__(self): self._grpc_server.start() return self def __exit__(self, exc_type, exc_val, exc_tb): self._grpc_server.stop(None) return False def server(service_implementations, multi_method_implementation, request_deserializers, response_serializers, thread_pool, thread_pool_size): generic_rpc_handler = _GenericRpcHandler( service_implementations, multi_method_implementation, request_deserializers, response_serializers) if thread_pool is None: effective_thread_pool = logging_pool.pool(_DEFAULT_POOL_SIZE if thread_pool_size is None else thread_pool_size) else: effective_thread_pool = thread_pool return _Server( grpc.server(effective_thread_pool, handlers=(generic_rpc_handler,))) grpc-1.3.2/src/python/grpcio/grpc/beta/implementations.py000066400000000000000000000303161310511640000234650ustar00rootroot00000000000000# Copyright 2015-2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Entry points into the Beta API of gRPC Python.""" # threading is referenced from specification in this module. import threading # pylint: disable=unused-import # interfaces, cardinality, and face are referenced from specification in this # module. import grpc from grpc import _auth from grpc.beta import _client_adaptations from grpc.beta import _server_adaptations from grpc.beta import interfaces # pylint: disable=unused-import from grpc.framework.common import cardinality # pylint: disable=unused-import from grpc.framework.interfaces.face import face # pylint: disable=unused-import # pylint: disable=too-many-arguments ChannelCredentials = grpc.ChannelCredentials ssl_channel_credentials = grpc.ssl_channel_credentials CallCredentials = grpc.CallCredentials metadata_call_credentials = grpc.metadata_call_credentials def google_call_credentials(credentials): """Construct CallCredentials from GoogleCredentials. Args: credentials: A GoogleCredentials object from the oauth2client library. Returns: A CallCredentials object for use in a GRPCCallOptions object. """ return metadata_call_credentials(_auth.GoogleCallCredentials(credentials)) access_token_call_credentials = grpc.access_token_call_credentials composite_call_credentials = grpc.composite_call_credentials composite_channel_credentials = grpc.composite_channel_credentials class Channel(object): """A channel to a remote host through which RPCs may be conducted. Only the "subscribe" and "unsubscribe" methods are supported for application use. This class' instance constructor and all other attributes are unsupported. """ def __init__(self, channel): self._channel = channel def subscribe(self, callback, try_to_connect=None): """Subscribes to this Channel's connectivity. Args: callback: A callable to be invoked and passed an interfaces.ChannelConnectivity identifying this Channel's connectivity. The callable will be invoked immediately upon subscription and again for every change to this Channel's connectivity thereafter until it is unsubscribed. try_to_connect: A boolean indicating whether or not this Channel should attempt to connect if it is not already connected and ready to conduct RPCs. """ self._channel.subscribe(callback, try_to_connect=try_to_connect) def unsubscribe(self, callback): """Unsubscribes a callback from this Channel's connectivity. Args: callback: A callable previously registered with this Channel from having been passed to its "subscribe" method. """ self._channel.unsubscribe(callback) def insecure_channel(host, port): """Creates an insecure Channel to a remote host. Args: host: The name of the remote host to which to connect. port: The port of the remote host to which to connect. If None only the 'host' part will be used. Returns: A Channel to the remote host through which RPCs may be conducted. """ channel = grpc.insecure_channel(host if port is None else '%s:%d' % (host, port)) return Channel(channel) def secure_channel(host, port, channel_credentials): """Creates a secure Channel to a remote host. Args: host: The name of the remote host to which to connect. port: The port of the remote host to which to connect. If None only the 'host' part will be used. channel_credentials: A ChannelCredentials. Returns: A secure Channel to the remote host through which RPCs may be conducted. """ channel = grpc.secure_channel(host if port is None else '%s:%d' % (host, port), channel_credentials) return Channel(channel) class StubOptions(object): """A value encapsulating the various options for creation of a Stub. This class and its instances have no supported interface - it exists to define the type of its instances and its instances exist to be passed to other functions. """ def __init__(self, host, request_serializers, response_deserializers, metadata_transformer, thread_pool, thread_pool_size): self.host = host self.request_serializers = request_serializers self.response_deserializers = response_deserializers self.metadata_transformer = metadata_transformer self.thread_pool = thread_pool self.thread_pool_size = thread_pool_size _EMPTY_STUB_OPTIONS = StubOptions(None, None, None, None, None, None) def stub_options(host=None, request_serializers=None, response_deserializers=None, metadata_transformer=None, thread_pool=None, thread_pool_size=None): """Creates a StubOptions value to be passed at stub creation. All parameters are optional and should always be passed by keyword. Args: host: A host string to set on RPC calls. request_serializers: A dictionary from service name-method name pair to request serialization behavior. response_deserializers: A dictionary from service name-method name pair to response deserialization behavior. metadata_transformer: A callable that given a metadata object produces another metadata object to be used in the underlying communication on the wire. thread_pool: A thread pool to use in stubs. thread_pool_size: The size of thread pool to create for use in stubs; ignored if thread_pool has been passed. Returns: A StubOptions value created from the passed parameters. """ return StubOptions(host, request_serializers, response_deserializers, metadata_transformer, thread_pool, thread_pool_size) def generic_stub(channel, options=None): """Creates a face.GenericStub on which RPCs can be made. Args: channel: A Channel for use by the created stub. options: A StubOptions customizing the created stub. Returns: A face.GenericStub on which RPCs can be made. """ effective_options = _EMPTY_STUB_OPTIONS if options is None else options return _client_adaptations.generic_stub( channel._channel, # pylint: disable=protected-access effective_options.host, effective_options.metadata_transformer, effective_options.request_serializers, effective_options.response_deserializers) def dynamic_stub(channel, service, cardinalities, options=None): """Creates a face.DynamicStub with which RPCs can be invoked. Args: channel: A Channel for the returned face.DynamicStub to use. service: The package-qualified full name of the service. cardinalities: A dictionary from RPC method name to cardinality.Cardinality value identifying the cardinality of the RPC method. options: An optional StubOptions value further customizing the functionality of the returned face.DynamicStub. Returns: A face.DynamicStub with which RPCs can be invoked. """ effective_options = _EMPTY_STUB_OPTIONS if options is None else options return _client_adaptations.dynamic_stub( channel._channel, # pylint: disable=protected-access service, cardinalities, effective_options.host, effective_options.metadata_transformer, effective_options.request_serializers, effective_options.response_deserializers) ServerCredentials = grpc.ServerCredentials ssl_server_credentials = grpc.ssl_server_credentials class ServerOptions(object): """A value encapsulating the various options for creation of a Server. This class and its instances have no supported interface - it exists to define the type of its instances and its instances exist to be passed to other functions. """ def __init__(self, multi_method_implementation, request_deserializers, response_serializers, thread_pool, thread_pool_size, default_timeout, maximum_timeout): self.multi_method_implementation = multi_method_implementation self.request_deserializers = request_deserializers self.response_serializers = response_serializers self.thread_pool = thread_pool self.thread_pool_size = thread_pool_size self.default_timeout = default_timeout self.maximum_timeout = maximum_timeout _EMPTY_SERVER_OPTIONS = ServerOptions(None, None, None, None, None, None, None) def server_options(multi_method_implementation=None, request_deserializers=None, response_serializers=None, thread_pool=None, thread_pool_size=None, default_timeout=None, maximum_timeout=None): """Creates a ServerOptions value to be passed at server creation. All parameters are optional and should always be passed by keyword. Args: multi_method_implementation: A face.MultiMethodImplementation to be called to service an RPC if the server has no specific method implementation for the name of the RPC for which service was requested. request_deserializers: A dictionary from service name-method name pair to request deserialization behavior. response_serializers: A dictionary from service name-method name pair to response serialization behavior. thread_pool: A thread pool to use in stubs. thread_pool_size: The size of thread pool to create for use in stubs; ignored if thread_pool has been passed. default_timeout: A duration in seconds to allow for RPC service when servicing RPCs that did not include a timeout value when invoked. maximum_timeout: A duration in seconds to allow for RPC service when servicing RPCs no matter what timeout value was passed when the RPC was invoked. Returns: A StubOptions value created from the passed parameters. """ return ServerOptions(multi_method_implementation, request_deserializers, response_serializers, thread_pool, thread_pool_size, default_timeout, maximum_timeout) def server(service_implementations, options=None): """Creates an interfaces.Server with which RPCs can be serviced. Args: service_implementations: A dictionary from service name-method name pair to face.MethodImplementation. options: An optional ServerOptions value further customizing the functionality of the returned Server. Returns: An interfaces.Server with which RPCs can be serviced. """ effective_options = _EMPTY_SERVER_OPTIONS if options is None else options return _server_adaptations.server( service_implementations, effective_options.multi_method_implementation, effective_options.request_deserializers, effective_options.response_serializers, effective_options.thread_pool, effective_options.thread_pool_size) grpc-1.3.2/src/python/grpcio/grpc/beta/interfaces.py000066400000000000000000000153731310511640000224060ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Constants and interfaces of the Beta API of gRPC Python.""" import abc import six import grpc ChannelConnectivity = grpc.ChannelConnectivity # FATAL_FAILURE was a Beta-API name for SHUTDOWN ChannelConnectivity.FATAL_FAILURE = ChannelConnectivity.SHUTDOWN StatusCode = grpc.StatusCode class GRPCCallOptions(object): """A value encapsulating gRPC-specific options passed on RPC invocation. This class and its instances have no supported interface - it exists to define the type of its instances and its instances exist to be passed to other functions. """ def __init__(self, disable_compression, subcall_of, credentials): self.disable_compression = disable_compression self.subcall_of = subcall_of self.credentials = credentials def grpc_call_options(disable_compression=False, credentials=None): """Creates a GRPCCallOptions value to be passed at RPC invocation. All parameters are optional and should always be passed by keyword. Args: disable_compression: A boolean indicating whether or not compression should be disabled for the request object of the RPC. Only valid for request-unary RPCs. credentials: A CallCredentials object to use for the invoked RPC. """ return GRPCCallOptions(disable_compression, None, credentials) GRPCAuthMetadataContext = grpc.AuthMetadataContext GRPCAuthMetadataPluginCallback = grpc.AuthMetadataPluginCallback GRPCAuthMetadataPlugin = grpc.AuthMetadataPlugin class GRPCServicerContext(six.with_metaclass(abc.ABCMeta)): """Exposes gRPC-specific options and behaviors to code servicing RPCs.""" @abc.abstractmethod def peer(self): """Identifies the peer that invoked the RPC being serviced. Returns: A string identifying the peer that invoked the RPC being serviced. """ raise NotImplementedError() @abc.abstractmethod def disable_next_response_compression(self): """Disables compression of the next response passed by the application.""" raise NotImplementedError() class GRPCInvocationContext(six.with_metaclass(abc.ABCMeta)): """Exposes gRPC-specific options and behaviors to code invoking RPCs.""" @abc.abstractmethod def disable_next_request_compression(self): """Disables compression of the next request passed by the application.""" raise NotImplementedError() class Server(six.with_metaclass(abc.ABCMeta)): """Services RPCs.""" @abc.abstractmethod def add_insecure_port(self, address): """Reserves a port for insecure RPC service once this Server becomes active. This method may only be called before calling this Server's start method is called. Args: address: The address for which to open a port. Returns: An integer port on which RPCs will be serviced after this link has been started. This is typically the same number as the port number contained in the passed address, but will likely be different if the port number contained in the passed address was zero. """ raise NotImplementedError() @abc.abstractmethod def add_secure_port(self, address, server_credentials): """Reserves a port for secure RPC service after this Server becomes active. This method may only be called before calling this Server's start method is called. Args: address: The address for which to open a port. server_credentials: A ServerCredentials. Returns: An integer port on which RPCs will be serviced after this link has been started. This is typically the same number as the port number contained in the passed address, but will likely be different if the port number contained in the passed address was zero. """ raise NotImplementedError() @abc.abstractmethod def start(self): """Starts this Server's service of RPCs. This method may only be called while the server is not serving RPCs (i.e. it is not idempotent). """ raise NotImplementedError() @abc.abstractmethod def stop(self, grace): """Stops this Server's service of RPCs. All calls to this method immediately stop service of new RPCs. When existing RPCs are aborted is controlled by the grace period parameter passed to this method. This method may be called at any time and is idempotent. Passing a smaller grace value than has been passed in a previous call will have the effect of stopping the Server sooner. Passing a larger grace value than has been passed in a previous call will not have the effect of stopping the server later. Args: grace: A duration of time in seconds to allow existing RPCs to complete before being aborted by this Server's stopping. May be zero for immediate abortion of all in-progress RPCs. Returns: A threading.Event that will be set when this Server has completely stopped. The returned event may not be set until after the full grace period (if some ongoing RPC continues for the full length of the period) of it may be set much sooner (such as if this Server had no RPCs underway at the time it was stopped or if all RPCs that it had underway completed very early in the grace period). """ raise NotImplementedError() grpc-1.3.2/src/python/grpcio/grpc/beta/utilities.py000066400000000000000000000133471310511640000222750ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Utilities for the gRPC Python Beta API.""" import threading import time # implementations is referenced from specification in this module. from grpc.beta import implementations # pylint: disable=unused-import from grpc.beta import interfaces from grpc.framework.foundation import callable_util from grpc.framework.foundation import future _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE = ( 'Exception calling connectivity future "done" callback!') class _ChannelReadyFuture(future.Future): def __init__(self, channel): self._condition = threading.Condition() self._channel = channel self._matured = False self._cancelled = False self._done_callbacks = [] def _block(self, timeout): until = None if timeout is None else time.time() + timeout with self._condition: while True: if self._cancelled: raise future.CancelledError() elif self._matured: return else: if until is None: self._condition.wait() else: remaining = until - time.time() if remaining < 0: raise future.TimeoutError() else: self._condition.wait(timeout=remaining) def _update(self, connectivity): with self._condition: if (not self._cancelled and connectivity is interfaces.ChannelConnectivity.READY): self._matured = True self._channel.unsubscribe(self._update) self._condition.notify_all() done_callbacks = tuple(self._done_callbacks) self._done_callbacks = None else: return for done_callback in done_callbacks: callable_util.call_logging_exceptions( done_callback, _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE, self) def cancel(self): with self._condition: if not self._matured: self._cancelled = True self._channel.unsubscribe(self._update) self._condition.notify_all() done_callbacks = tuple(self._done_callbacks) self._done_callbacks = None else: return False for done_callback in done_callbacks: callable_util.call_logging_exceptions( done_callback, _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE, self) def cancelled(self): with self._condition: return self._cancelled def running(self): with self._condition: return not self._cancelled and not self._matured def done(self): with self._condition: return self._cancelled or self._matured def result(self, timeout=None): self._block(timeout) return None def exception(self, timeout=None): self._block(timeout) return None def traceback(self, timeout=None): self._block(timeout) return None def add_done_callback(self, fn): with self._condition: if not self._cancelled and not self._matured: self._done_callbacks.append(fn) return fn(self) def start(self): with self._condition: self._channel.subscribe(self._update, try_to_connect=True) def __del__(self): with self._condition: if not self._cancelled and not self._matured: self._channel.unsubscribe(self._update) def channel_ready_future(channel): """Creates a future.Future tracking when an implementations.Channel is ready. Cancelling the returned future.Future does not tell the given implementations.Channel to abandon attempts it may have been making to connect; cancelling merely deactivates the return future.Future's subscription to the given implementations.Channel's connectivity. Args: channel: An implementations.Channel. Returns: A future.Future that matures when the given Channel has connectivity interfaces.ChannelConnectivity.READY. """ ready_future = _ChannelReadyFuture(channel) ready_future.start() return ready_future grpc-1.3.2/src/python/grpcio/grpc/framework/000077500000000000000000000000001310511640000207625ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio/grpc/framework/__init__.py000066400000000000000000000027701310511640000231010ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio/grpc/framework/common/000077500000000000000000000000001310511640000222525ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio/grpc/framework/common/__init__.py000066400000000000000000000027701310511640000243710ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio/grpc/framework/common/cardinality.py000066400000000000000000000036231310511640000251330ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Defines an enum for classifying RPC methods by streaming semantics.""" import enum @enum.unique class Cardinality(enum.Enum): """Describes the streaming semantics of an RPC method.""" UNARY_UNARY = 'request-unary/response-unary' UNARY_STREAM = 'request-unary/response-streaming' STREAM_UNARY = 'request-streaming/response-unary' STREAM_STREAM = 'request-streaming/response-streaming' grpc-1.3.2/src/python/grpcio/grpc/framework/common/style.py000066400000000000000000000033571310511640000237740ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Defines an enum for classifying RPC methods by control flow semantics.""" import enum @enum.unique class Service(enum.Enum): """Describes the control flow style of RPC method implementation.""" INLINE = 'inline' EVENT = 'event' grpc-1.3.2/src/python/grpcio/grpc/framework/foundation/000077500000000000000000000000001310511640000231305ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio/grpc/framework/foundation/__init__.py000066400000000000000000000027701310511640000252470ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio/grpc/framework/foundation/abandonment.py000066400000000000000000000034371310511640000257770ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Utilities for indicating abandonment of computation.""" class Abandoned(Exception): """Indicates that some computation is being abandoned. Abandoning a computation is different than returning a value or raising an exception indicating some operational or programming defect. """ grpc-1.3.2/src/python/grpcio/grpc/framework/foundation/callable_util.py000066400000000000000000000077371310511640000263140ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Utilities for working with callables.""" import abc import collections import enum import functools import logging import six class Outcome(six.with_metaclass(abc.ABCMeta)): """A sum type describing the outcome of some call. Attributes: kind: One of Kind.RETURNED or Kind.RAISED respectively indicating that the call returned a value or raised an exception. return_value: The value returned by the call. Must be present if kind is Kind.RETURNED. exception: The exception raised by the call. Must be present if kind is Kind.RAISED. """ @enum.unique class Kind(enum.Enum): """Identifies the general kind of the outcome of some call.""" RETURNED = object() RAISED = object() class _EasyOutcome( collections.namedtuple('_EasyOutcome', ['kind', 'return_value', 'exception']), Outcome): """A trivial implementation of Outcome.""" def _call_logging_exceptions(behavior, message, *args, **kwargs): try: return _EasyOutcome(Outcome.Kind.RETURNED, behavior(*args, **kwargs), None) except Exception as e: # pylint: disable=broad-except logging.exception(message) return _EasyOutcome(Outcome.Kind.RAISED, None, e) def with_exceptions_logged(behavior, message): """Wraps a callable in a try-except that logs any exceptions it raises. Args: behavior: Any callable. message: A string to log if the behavior raises an exception. Returns: A callable that when executed invokes the given behavior. The returned callable takes the same arguments as the given behavior but returns a future.Outcome describing whether the given behavior returned a value or raised an exception. """ @functools.wraps(behavior) def wrapped_behavior(*args, **kwargs): return _call_logging_exceptions(behavior, message, *args, **kwargs) return wrapped_behavior def call_logging_exceptions(behavior, message, *args, **kwargs): """Calls a behavior in a try-except that logs any exceptions it raises. Args: behavior: Any callable. message: A string to log if the behavior raises an exception. *args: Positional arguments to pass to the given behavior. **kwargs: Keyword arguments to pass to the given behavior. Returns: An Outcome describing whether the given behavior returned a value or raised an exception. """ return _call_logging_exceptions(behavior, message, *args, **kwargs) grpc-1.3.2/src/python/grpcio/grpc/framework/foundation/future.py000066400000000000000000000215221310511640000250160ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """A Future interface. Python doesn't have a Future interface in its standard library. In the absence of such a standard, three separate, incompatible implementations (concurrent.futures.Future, ndb.Future, and asyncio.Future) have appeared. This interface attempts to be as compatible as possible with concurrent.futures.Future. From ndb.Future it adopts a traceback-object accessor method. Unlike the concrete and implemented Future classes listed above, the Future class defined in this module is an entirely abstract interface that anyone may implement and use. The one known incompatibility between this interface and the interface of concurrent.futures.Future is that this interface defines its own CancelledError and TimeoutError exceptions rather than raising the implementation-private concurrent.futures._base.CancelledError and the built-in-but-only-in-3.3-and-later TimeoutError. """ import abc import six class TimeoutError(Exception): """Indicates that a particular call timed out.""" class CancelledError(Exception): """Indicates that the computation underlying a Future was cancelled.""" class Future(six.with_metaclass(abc.ABCMeta)): """A representation of a computation in another control flow. Computations represented by a Future may be yet to be begun, may be ongoing, or may have already completed. """ # NOTE(nathaniel): This isn't the return type that I would want to have if it # were up to me. Were this interface being written from scratch, the return # type of this method would probably be a sum type like: # # NOT_COMMENCED # COMMENCED_AND_NOT_COMPLETED # PARTIAL_RESULT # COMPLETED # UNCANCELLABLE # NOT_IMMEDIATELY_DETERMINABLE @abc.abstractmethod def cancel(self): """Attempts to cancel the computation. This method does not block. Returns: True if the computation has not yet begun, will not be allowed to take place, and determination of both was possible without blocking. False under all other circumstances including but not limited to the computation's already having begun, the computation's already having finished, and the computation's having been scheduled for execution on a remote system for which a determination of whether or not it commenced before being cancelled cannot be made without blocking. """ raise NotImplementedError() # NOTE(nathaniel): Here too this isn't the return type that I'd want this # method to have if it were up to me. I think I'd go with another sum type # like: # # NOT_CANCELLED (this object's cancel method hasn't been called) # NOT_COMMENCED # COMMENCED_AND_NOT_COMPLETED # PARTIAL_RESULT # COMPLETED # UNCANCELLABLE # NOT_IMMEDIATELY_DETERMINABLE # # Notice how giving the cancel method the right semantics obviates most # reasons for this method to exist. @abc.abstractmethod def cancelled(self): """Describes whether the computation was cancelled. This method does not block. Returns: True if the computation was cancelled any time before its result became immediately available. False under all other circumstances including but not limited to this object's cancel method not having been called and the computation's result having become immediately available. """ raise NotImplementedError() @abc.abstractmethod def running(self): """Describes whether the computation is taking place. This method does not block. Returns: True if the computation is scheduled to take place in the future or is taking place now, or False if the computation took place in the past or was cancelled. """ raise NotImplementedError() # NOTE(nathaniel): These aren't quite the semantics I'd like here either. I # would rather this only returned True in cases in which the underlying # computation completed successfully. A computation's having been cancelled # conflicts with considering that computation "done". @abc.abstractmethod def done(self): """Describes whether the computation has taken place. This method does not block. Returns: True if the computation is known to have either completed or have been unscheduled or interrupted. False if the computation may possibly be executing or scheduled to execute later. """ raise NotImplementedError() @abc.abstractmethod def result(self, timeout=None): """Accesses the outcome of the computation or raises its exception. This method may return immediately or may block. Args: timeout: The length of time in seconds to wait for the computation to finish or be cancelled, or None if this method should block until the computation has finished or is cancelled no matter how long that takes. Returns: The return value of the computation. Raises: TimeoutError: If a timeout value is passed and the computation does not terminate within the allotted time. CancelledError: If the computation was cancelled. Exception: If the computation raised an exception, this call will raise the same exception. """ raise NotImplementedError() @abc.abstractmethod def exception(self, timeout=None): """Return the exception raised by the computation. This method may return immediately or may block. Args: timeout: The length of time in seconds to wait for the computation to terminate or be cancelled, or None if this method should block until the computation is terminated or is cancelled no matter how long that takes. Returns: The exception raised by the computation, or None if the computation did not raise an exception. Raises: TimeoutError: If a timeout value is passed and the computation does not terminate within the allotted time. CancelledError: If the computation was cancelled. """ raise NotImplementedError() @abc.abstractmethod def traceback(self, timeout=None): """Access the traceback of the exception raised by the computation. This method may return immediately or may block. Args: timeout: The length of time in seconds to wait for the computation to terminate or be cancelled, or None if this method should block until the computation is terminated or is cancelled no matter how long that takes. Returns: The traceback of the exception raised by the computation, or None if the computation did not raise an exception. Raises: TimeoutError: If a timeout value is passed and the computation does not terminate within the allotted time. CancelledError: If the computation was cancelled. """ raise NotImplementedError() @abc.abstractmethod def add_done_callback(self, fn): """Adds a function to be called at completion of the computation. The callback will be passed this Future object describing the outcome of the computation. If the computation has already completed, the callback will be called immediately. Args: fn: A callable taking this Future object as its single parameter. """ raise NotImplementedError() grpc-1.3.2/src/python/grpcio/grpc/framework/foundation/logging_pool.py000066400000000000000000000060661310511640000261710ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """A thread pool that logs exceptions raised by tasks executed within it.""" import logging from concurrent import futures def _wrap(behavior): """Wraps an arbitrary callable behavior in exception-logging.""" def _wrapping(*args, **kwargs): try: return behavior(*args, **kwargs) except Exception: logging.exception( 'Unexpected exception from %s executed in logging pool!', behavior) raise return _wrapping class _LoggingPool(object): """An exception-logging futures.ThreadPoolExecutor-compatible thread pool.""" def __init__(self, backing_pool): self._backing_pool = backing_pool def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self._backing_pool.shutdown(wait=True) def submit(self, fn, *args, **kwargs): return self._backing_pool.submit(_wrap(fn), *args, **kwargs) def map(self, func, *iterables, **kwargs): return self._backing_pool.map( _wrap(func), *iterables, timeout=kwargs.get('timeout', None)) def shutdown(self, wait=True): self._backing_pool.shutdown(wait=wait) def pool(max_workers): """Creates a thread pool that logs exceptions raised by the tasks within it. Args: max_workers: The maximum number of worker threads to allow the pool. Returns: A futures.ThreadPoolExecutor-compatible thread pool that logs exceptions raised by the tasks executed within it. """ return _LoggingPool(futures.ThreadPoolExecutor(max_workers)) grpc-1.3.2/src/python/grpcio/grpc/framework/foundation/stream.py000066400000000000000000000044441310511640000250030ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Interfaces related to streams of values or objects.""" import abc import six class Consumer(six.with_metaclass(abc.ABCMeta)): """Interface for consumers of finite streams of values or objects.""" @abc.abstractmethod def consume(self, value): """Accepts a value. Args: value: Any value accepted by this Consumer. """ raise NotImplementedError() @abc.abstractmethod def terminate(self): """Indicates to this Consumer that no more values will be supplied.""" raise NotImplementedError() @abc.abstractmethod def consume_and_terminate(self, value): """Supplies a value and signals that no more values will be supplied. Args: value: Any value accepted by this Consumer. """ raise NotImplementedError() grpc-1.3.2/src/python/grpcio/grpc/framework/foundation/stream_util.py000066400000000000000000000131151310511640000260330ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Helpful utilities related to the stream module.""" import logging import threading from grpc.framework.foundation import stream _NO_VALUE = object() class TransformingConsumer(stream.Consumer): """A stream.Consumer that passes a transformation of its input to another.""" def __init__(self, transformation, downstream): self._transformation = transformation self._downstream = downstream def consume(self, value): self._downstream.consume(self._transformation(value)) def terminate(self): self._downstream.terminate() def consume_and_terminate(self, value): self._downstream.consume_and_terminate(self._transformation(value)) class IterableConsumer(stream.Consumer): """A Consumer that when iterated over emits the values it has consumed.""" def __init__(self): self._condition = threading.Condition() self._values = [] self._active = True def consume(self, stock_reply): with self._condition: if self._active: self._values.append(stock_reply) self._condition.notify() def terminate(self): with self._condition: self._active = False self._condition.notify() def consume_and_terminate(self, stock_reply): with self._condition: if self._active: self._values.append(stock_reply) self._active = False self._condition.notify() def __iter__(self): return self def __next__(self): return self.next() def next(self): with self._condition: while self._active and not self._values: self._condition.wait() if self._values: return self._values.pop(0) else: raise StopIteration() class ThreadSwitchingConsumer(stream.Consumer): """A Consumer decorator that affords serialization and asynchrony.""" def __init__(self, sink, pool): self._lock = threading.Lock() self._sink = sink self._pool = pool # True if self._spin has been submitted to the pool to be called once and # that call has not yet returned, False otherwise. self._spinning = False self._values = [] self._active = True def _spin(self, sink, value, terminate): while True: try: if value is _NO_VALUE: sink.terminate() elif terminate: sink.consume_and_terminate(value) else: sink.consume(value) except Exception as e: # pylint:disable=broad-except logging.exception(e) with self._lock: if terminate: self._spinning = False return elif self._values: value = self._values.pop(0) terminate = not self._values and not self._active elif not self._active: value = _NO_VALUE terminate = True else: self._spinning = False return def consume(self, value): with self._lock: if self._active: if self._spinning: self._values.append(value) else: self._pool.submit(self._spin, self._sink, value, False) self._spinning = True def terminate(self): with self._lock: if self._active: self._active = False if not self._spinning: self._pool.submit(self._spin, self._sink, _NO_VALUE, True) self._spinning = True def consume_and_terminate(self, value): with self._lock: if self._active: self._active = False if self._spinning: self._values.append(value) else: self._pool.submit(self._spin, self._sink, value, True) self._spinning = True grpc-1.3.2/src/python/grpcio/grpc/framework/interfaces/000077500000000000000000000000001310511640000231055ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio/grpc/framework/interfaces/__init__.py000066400000000000000000000027701310511640000252240ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio/grpc/framework/interfaces/base/000077500000000000000000000000001310511640000240175ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio/grpc/framework/interfaces/base/__init__.py000066400000000000000000000027701310511640000261360ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio/grpc/framework/interfaces/base/base.py000066400000000000000000000315301310511640000253050ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """The base interface of RPC Framework. Implementations of this interface support the conduct of "operations": exchanges between two distinct ends of an arbitrary number of data payloads and metadata such as a name for the operation, initial and terminal metadata in each direction, and flow control. These operations may be used for transfers of data, remote procedure calls, status indication, or anything else applications choose. """ # threading is referenced from specification in this module. import abc import enum import threading # pylint: disable=unused-import import six # abandonment is referenced from specification in this module. from grpc.framework.foundation import abandonment # pylint: disable=unused-import # pylint: disable=too-many-arguments class NoSuchMethodError(Exception): """Indicates that an unrecognized operation has been called. Attributes: code: A code value to communicate to the other side of the operation along with indication of operation termination. May be None. details: A details value to communicate to the other side of the operation along with indication of operation termination. May be None. """ def __init__(self, code, details): """Constructor. Args: code: A code value to communicate to the other side of the operation along with indication of operation termination. May be None. details: A details value to communicate to the other side of the operation along with indication of operation termination. May be None. """ super(NoSuchMethodError, self).__init__() self.code = code self.details = details class Outcome(object): """The outcome of an operation. Attributes: kind: A Kind value coarsely identifying how the operation terminated. code: An application-specific code value or None if no such value was provided. details: An application-specific details value or None if no such value was provided. """ @enum.unique class Kind(enum.Enum): """Ways in which an operation can terminate.""" COMPLETED = 'completed' CANCELLED = 'cancelled' EXPIRED = 'expired' LOCAL_SHUTDOWN = 'local shutdown' REMOTE_SHUTDOWN = 'remote shutdown' RECEPTION_FAILURE = 'reception failure' TRANSMISSION_FAILURE = 'transmission failure' LOCAL_FAILURE = 'local failure' REMOTE_FAILURE = 'remote failure' class Completion(six.with_metaclass(abc.ABCMeta)): """An aggregate of the values exchanged upon operation completion. Attributes: terminal_metadata: A terminal metadata value for the operaton. code: A code value for the operation. message: A message value for the operation. """ class OperationContext(six.with_metaclass(abc.ABCMeta)): """Provides operation-related information and action.""" @abc.abstractmethod def outcome(self): """Indicates the operation's outcome (or that the operation is ongoing). Returns: None if the operation is still active or the Outcome value for the operation if it has terminated. """ raise NotImplementedError() @abc.abstractmethod def add_termination_callback(self, callback): """Adds a function to be called upon operation termination. Args: callback: A callable to be passed an Outcome value on operation termination. Returns: None if the operation has not yet terminated and the passed callback will later be called when it does terminate, or if the operation has already terminated an Outcome value describing the operation termination and the passed callback will not be called as a result of this method call. """ raise NotImplementedError() @abc.abstractmethod def time_remaining(self): """Describes the length of allowed time remaining for the operation. Returns: A nonnegative float indicating the length of allowed time in seconds remaining for the operation to complete before it is considered to have timed out. Zero is returned if the operation has terminated. """ raise NotImplementedError() @abc.abstractmethod def cancel(self): """Cancels the operation if the operation has not yet terminated.""" raise NotImplementedError() @abc.abstractmethod def fail(self, exception): """Indicates that the operation has failed. Args: exception: An exception germane to the operation failure. May be None. """ raise NotImplementedError() class Operator(six.with_metaclass(abc.ABCMeta)): """An interface through which to participate in an operation.""" @abc.abstractmethod def advance(self, initial_metadata=None, payload=None, completion=None, allowance=None): """Progresses the operation. Args: initial_metadata: An initial metadata value. Only one may ever be communicated in each direction for an operation, and they must be communicated no later than either the first payload or the completion. payload: A payload value. completion: A Completion value. May only ever be non-None once in either direction, and no payloads may be passed after it has been communicated. allowance: A positive integer communicating the number of additional payloads allowed to be passed by the remote side of the operation. """ raise NotImplementedError() class ProtocolReceiver(six.with_metaclass(abc.ABCMeta)): """A means of receiving protocol values during an operation.""" @abc.abstractmethod def context(self, protocol_context): """Accepts the protocol context object for the operation. Args: protocol_context: The protocol context object for the operation. """ raise NotImplementedError() class Subscription(six.with_metaclass(abc.ABCMeta)): """Describes customer code's interest in values from the other side. Attributes: kind: A Kind value describing the overall kind of this value. termination_callback: A callable to be passed the Outcome associated with the operation after it has terminated. Must be non-None if kind is Kind.TERMINATION_ONLY. Must be None otherwise. allowance: A callable behavior that accepts positive integers representing the number of additional payloads allowed to be passed to the other side of the operation. Must be None if kind is Kind.FULL. Must not be None otherwise. operator: An Operator to be passed values from the other side of the operation. Must be non-None if kind is Kind.FULL. Must be None otherwise. protocol_receiver: A ProtocolReceiver to be passed protocol objects as they become available during the operation. Must be non-None if kind is Kind.FULL. """ @enum.unique class Kind(enum.Enum): NONE = 'none' TERMINATION_ONLY = 'termination only' FULL = 'full' class Servicer(six.with_metaclass(abc.ABCMeta)): """Interface for service implementations.""" @abc.abstractmethod def service(self, group, method, context, output_operator): """Services an operation. Args: group: The group identifier of the operation to be serviced. method: The method identifier of the operation to be serviced. context: An OperationContext object affording contextual information and actions. output_operator: An Operator that will accept output values of the operation. Returns: A Subscription via which this object may or may not accept more values of the operation. Raises: NoSuchMethodError: If this Servicer does not handle operations with the given group and method. abandonment.Abandoned: If the operation has been aborted and there no longer is any reason to service the operation. """ raise NotImplementedError() class End(six.with_metaclass(abc.ABCMeta)): """Common type for entry-point objects on both sides of an operation.""" @abc.abstractmethod def start(self): """Starts this object's service of operations.""" raise NotImplementedError() @abc.abstractmethod def stop(self, grace): """Stops this object's service of operations. This object will refuse service of new operations as soon as this method is called but operations under way at the time of the call may be given a grace period during which they are allowed to finish. Args: grace: A duration of time in seconds to allow ongoing operations to terminate before being forcefully terminated by the stopping of this End. May be zero to terminate all ongoing operations and immediately stop. Returns: A threading.Event that will be set to indicate all operations having terminated and this End having completely stopped. The returned event may not be set until after the full grace period (if some ongoing operation continues for the full length of the period) or it may be set much sooner (if for example this End had no operations in progress at the time its stop method was called). """ raise NotImplementedError() @abc.abstractmethod def operate(self, group, method, subscription, timeout, initial_metadata=None, payload=None, completion=None, protocol_options=None): """Commences an operation. Args: group: The group identifier of the invoked operation. method: The method identifier of the invoked operation. subscription: A Subscription to which the results of the operation will be passed. timeout: A length of time in seconds to allow for the operation. initial_metadata: An initial metadata value to be sent to the other side of the operation. May be None if the initial metadata will be later passed via the returned operator or if there will be no initial metadata passed at all. payload: An initial payload for the operation. completion: A Completion value indicating the end of transmission to the other side of the operation. protocol_options: A value specified by the provider of a Base interface implementation affording custom state and behavior. Returns: A pair of objects affording information about the operation and action continuing the operation. The first element of the returned pair is an OperationContext for the operation and the second element of the returned pair is an Operator to which operation values not passed in this call should later be passed. """ raise NotImplementedError() @abc.abstractmethod def operation_stats(self): """Reports the number of terminated operations broken down by outcome. Returns: A dictionary from Outcome.Kind value to an integer identifying the number of operations that terminated with that outcome kind. """ raise NotImplementedError() @abc.abstractmethod def add_idle_action(self, action): """Adds an action to be called when this End has no ongoing operations. Args: action: A callable that accepts no arguments. """ raise NotImplementedError() grpc-1.3.2/src/python/grpcio/grpc/framework/interfaces/base/utilities.py000066400000000000000000000063241310511640000264110ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Utilities for use with the base interface of RPC Framework.""" import collections from grpc.framework.interfaces.base import base class _Completion(base.Completion, collections.namedtuple('_Completion', ('terminal_metadata', 'code', 'message',))): """A trivial implementation of base.Completion.""" class _Subscription(base.Subscription, collections.namedtuple('_Subscription', ( 'kind', 'termination_callback', 'allowance', 'operator', 'protocol_receiver',))): """A trivial implementation of base.Subscription.""" _NONE_SUBSCRIPTION = _Subscription(base.Subscription.Kind.NONE, None, None, None, None) def completion(terminal_metadata, code, message): """Creates a base.Completion aggregating the given operation values. Args: terminal_metadata: A terminal metadata value for an operaton. code: A code value for an operation. message: A message value for an operation. Returns: A base.Completion aggregating the given operation values. """ return _Completion(terminal_metadata, code, message) def full_subscription(operator, protocol_receiver): """Creates a "full" base.Subscription for the given base.Operator. Args: operator: A base.Operator to be used in an operation. protocol_receiver: A base.ProtocolReceiver to be used in an operation. Returns: A base.Subscription of kind base.Subscription.Kind.FULL wrapping the given base.Operator and base.ProtocolReceiver. """ return _Subscription(base.Subscription.Kind.FULL, None, None, operator, protocol_receiver) grpc-1.3.2/src/python/grpcio/grpc/framework/interfaces/face/000077500000000000000000000000001310511640000240035ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio/grpc/framework/interfaces/face/__init__.py000066400000000000000000000027701310511640000261220ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio/grpc/framework/interfaces/face/face.py000066400000000000000000001172461310511640000252660ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Interfaces defining the Face layer of RPC Framework.""" import abc import collections import enum import six # cardinality, style, abandonment, future, and stream are # referenced from specification in this module. from grpc.framework.common import cardinality # pylint: disable=unused-import from grpc.framework.common import style # pylint: disable=unused-import from grpc.framework.foundation import abandonment # pylint: disable=unused-import from grpc.framework.foundation import future # pylint: disable=unused-import from grpc.framework.foundation import stream # pylint: disable=unused-import # pylint: disable=too-many-arguments class NoSuchMethodError(Exception): """Raised by customer code to indicate an unrecognized method. Attributes: group: The group of the unrecognized method. name: The name of the unrecognized method. """ def __init__(self, group, method): """Constructor. Args: group: The group identifier of the unrecognized RPC name. method: The method identifier of the unrecognized RPC name. """ super(NoSuchMethodError, self).__init__() self.group = group self.method = method def __repr__(self): return 'face.NoSuchMethodError(%s, %s)' % (self.group, self.method,) class Abortion( collections.namedtuple('Abortion', ('kind', 'initial_metadata', 'terminal_metadata', 'code', 'details',))): """A value describing RPC abortion. Attributes: kind: A Kind value identifying how the RPC failed. initial_metadata: The initial metadata from the other side of the RPC or None if no initial metadata value was received. terminal_metadata: The terminal metadata from the other side of the RPC or None if no terminal metadata value was received. code: The code value from the other side of the RPC or None if no code value was received. details: The details value from the other side of the RPC or None if no details value was received. """ @enum.unique class Kind(enum.Enum): """Types of RPC abortion.""" CANCELLED = 'cancelled' EXPIRED = 'expired' LOCAL_SHUTDOWN = 'local shutdown' REMOTE_SHUTDOWN = 'remote shutdown' NETWORK_FAILURE = 'network failure' LOCAL_FAILURE = 'local failure' REMOTE_FAILURE = 'remote failure' class AbortionError(six.with_metaclass(abc.ABCMeta, Exception)): """Common super type for exceptions indicating RPC abortion. initial_metadata: The initial metadata from the other side of the RPC or None if no initial metadata value was received. terminal_metadata: The terminal metadata from the other side of the RPC or None if no terminal metadata value was received. code: The code value from the other side of the RPC or None if no code value was received. details: The details value from the other side of the RPC or None if no details value was received. """ def __init__(self, initial_metadata, terminal_metadata, code, details): super(AbortionError, self).__init__() self.initial_metadata = initial_metadata self.terminal_metadata = terminal_metadata self.code = code self.details = details def __str__(self): return '%s(code=%s, details="%s")' % (self.__class__.__name__, self.code, self.details) class CancellationError(AbortionError): """Indicates that an RPC has been cancelled.""" class ExpirationError(AbortionError): """Indicates that an RPC has expired ("timed out").""" class LocalShutdownError(AbortionError): """Indicates that an RPC has terminated due to local shutdown of RPCs.""" class RemoteShutdownError(AbortionError): """Indicates that an RPC has terminated due to remote shutdown of RPCs.""" class NetworkError(AbortionError): """Indicates that some error occurred on the network.""" class LocalError(AbortionError): """Indicates that an RPC has terminated due to a local defect.""" class RemoteError(AbortionError): """Indicates that an RPC has terminated due to a remote defect.""" class RpcContext(six.with_metaclass(abc.ABCMeta)): """Provides RPC-related information and action.""" @abc.abstractmethod def is_active(self): """Describes whether the RPC is active or has terminated.""" raise NotImplementedError() @abc.abstractmethod def time_remaining(self): """Describes the length of allowed time remaining for the RPC. Returns: A nonnegative float indicating the length of allowed time in seconds remaining for the RPC to complete before it is considered to have timed out. """ raise NotImplementedError() @abc.abstractmethod def add_abortion_callback(self, abortion_callback): """Registers a callback to be called if the RPC is aborted. Args: abortion_callback: A callable to be called and passed an Abortion value in the event of RPC abortion. """ raise NotImplementedError() @abc.abstractmethod def cancel(self): """Cancels the RPC. Idempotent and has no effect if the RPC has already terminated. """ raise NotImplementedError() @abc.abstractmethod def protocol_context(self): """Accesses a custom object specified by an implementation provider. Returns: A value specified by the provider of a Face interface implementation affording custom state and behavior. """ raise NotImplementedError() class Call(six.with_metaclass(abc.ABCMeta, RpcContext)): """Invocation-side utility object for an RPC.""" @abc.abstractmethod def initial_metadata(self): """Accesses the initial metadata from the service-side of the RPC. This method blocks until the value is available or is known not to have been emitted from the service-side of the RPC. Returns: The initial metadata object emitted by the service-side of the RPC, or None if there was no such value. """ raise NotImplementedError() @abc.abstractmethod def terminal_metadata(self): """Accesses the terminal metadata from the service-side of the RPC. This method blocks until the value is available or is known not to have been emitted from the service-side of the RPC. Returns: The terminal metadata object emitted by the service-side of the RPC, or None if there was no such value. """ raise NotImplementedError() @abc.abstractmethod def code(self): """Accesses the code emitted by the service-side of the RPC. This method blocks until the value is available or is known not to have been emitted from the service-side of the RPC. Returns: The code object emitted by the service-side of the RPC, or None if there was no such value. """ raise NotImplementedError() @abc.abstractmethod def details(self): """Accesses the details value emitted by the service-side of the RPC. This method blocks until the value is available or is known not to have been emitted from the service-side of the RPC. Returns: The details value emitted by the service-side of the RPC, or None if there was no such value. """ raise NotImplementedError() class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): """A context object passed to method implementations.""" @abc.abstractmethod def invocation_metadata(self): """Accesses the metadata from the invocation-side of the RPC. This method blocks until the value is available or is known not to have been emitted from the invocation-side of the RPC. Returns: The metadata object emitted by the invocation-side of the RPC, or None if there was no such value. """ raise NotImplementedError() @abc.abstractmethod def initial_metadata(self, initial_metadata): """Accepts the service-side initial metadata value of the RPC. This method need not be called by method implementations if they have no service-side initial metadata to transmit. Args: initial_metadata: The service-side initial metadata value of the RPC to be transmitted to the invocation side of the RPC. """ raise NotImplementedError() @abc.abstractmethod def terminal_metadata(self, terminal_metadata): """Accepts the service-side terminal metadata value of the RPC. This method need not be called by method implementations if they have no service-side terminal metadata to transmit. Args: terminal_metadata: The service-side terminal metadata value of the RPC to be transmitted to the invocation side of the RPC. """ raise NotImplementedError() @abc.abstractmethod def code(self, code): """Accepts the service-side code of the RPC. This method need not be called by method implementations if they have no code to transmit. Args: code: The code of the RPC to be transmitted to the invocation side of the RPC. """ raise NotImplementedError() @abc.abstractmethod def details(self, details): """Accepts the service-side details of the RPC. This method need not be called by method implementations if they have no service-side details to transmit. Args: details: The service-side details value of the RPC to be transmitted to the invocation side of the RPC. """ raise NotImplementedError() class ResponseReceiver(six.with_metaclass(abc.ABCMeta)): """Invocation-side object used to accept the output of an RPC.""" @abc.abstractmethod def initial_metadata(self, initial_metadata): """Receives the initial metadata from the service-side of the RPC. Args: initial_metadata: The initial metadata object emitted from the service-side of the RPC. """ raise NotImplementedError() @abc.abstractmethod def response(self, response): """Receives a response from the service-side of the RPC. Args: response: A response object emitted from the service-side of the RPC. """ raise NotImplementedError() @abc.abstractmethod def complete(self, terminal_metadata, code, details): """Receives the completion values emitted from the service-side of the RPC. Args: terminal_metadata: The terminal metadata object emitted from the service-side of the RPC. code: The code object emitted from the service-side of the RPC. details: The details object emitted from the service-side of the RPC. """ raise NotImplementedError() class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): """Affords invoking a unary-unary RPC in any call style.""" @abc.abstractmethod def __call__(self, request, timeout, metadata=None, with_call=False, protocol_options=None): """Synchronously invokes the underlying RPC. Args: request: The request value for the RPC. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. with_call: Whether or not to include return a Call for the RPC in addition to the response. protocol_options: A value specified by the provider of a Face interface implementation affording custom state and behavior. Returns: The response value for the RPC, and a Call for the RPC if with_call was set to True at invocation. Raises: AbortionError: Indicating that the RPC was aborted. """ raise NotImplementedError() @abc.abstractmethod def future(self, request, timeout, metadata=None, protocol_options=None): """Asynchronously invokes the underlying RPC. Args: request: The request value for the RPC. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. protocol_options: A value specified by the provider of a Face interface implementation affording custom state and behavior. Returns: An object that is both a Call for the RPC and a future.Future. In the event of RPC completion, the return Future's result value will be the response value of the RPC. In the event of RPC abortion, the returned Future's exception value will be an AbortionError. """ raise NotImplementedError() @abc.abstractmethod def event(self, request, receiver, abortion_callback, timeout, metadata=None, protocol_options=None): """Asynchronously invokes the underlying RPC. Args: request: The request value for the RPC. receiver: A ResponseReceiver to be passed the response data of the RPC. abortion_callback: A callback to be called and passed an Abortion value in the event of RPC abortion. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. protocol_options: A value specified by the provider of a Face interface implementation affording custom state and behavior. Returns: A Call for the RPC. """ raise NotImplementedError() class UnaryStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): """Affords invoking a unary-stream RPC in any call style.""" @abc.abstractmethod def __call__(self, request, timeout, metadata=None, protocol_options=None): """Invokes the underlying RPC. Args: request: The request value for the RPC. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. protocol_options: A value specified by the provider of a Face interface implementation affording custom state and behavior. Returns: An object that is both a Call for the RPC and an iterator of response values. Drawing response values from the returned iterator may raise AbortionError indicating abortion of the RPC. """ raise NotImplementedError() @abc.abstractmethod def event(self, request, receiver, abortion_callback, timeout, metadata=None, protocol_options=None): """Asynchronously invokes the underlying RPC. Args: request: The request value for the RPC. receiver: A ResponseReceiver to be passed the response data of the RPC. abortion_callback: A callback to be called and passed an Abortion value in the event of RPC abortion. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. protocol_options: A value specified by the provider of a Face interface implementation affording custom state and behavior. Returns: A Call object for the RPC. """ raise NotImplementedError() class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): """Affords invoking a stream-unary RPC in any call style.""" @abc.abstractmethod def __call__(self, request_iterator, timeout, metadata=None, with_call=False, protocol_options=None): """Synchronously invokes the underlying RPC. Args: request_iterator: An iterator that yields request values for the RPC. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. with_call: Whether or not to include return a Call for the RPC in addition to the response. protocol_options: A value specified by the provider of a Face interface implementation affording custom state and behavior. Returns: The response value for the RPC, and a Call for the RPC if with_call was set to True at invocation. Raises: AbortionError: Indicating that the RPC was aborted. """ raise NotImplementedError() @abc.abstractmethod def future(self, request_iterator, timeout, metadata=None, protocol_options=None): """Asynchronously invokes the underlying RPC. Args: request_iterator: An iterator that yields request values for the RPC. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. protocol_options: A value specified by the provider of a Face interface implementation affording custom state and behavior. Returns: An object that is both a Call for the RPC and a future.Future. In the event of RPC completion, the return Future's result value will be the response value of the RPC. In the event of RPC abortion, the returned Future's exception value will be an AbortionError. """ raise NotImplementedError() @abc.abstractmethod def event(self, receiver, abortion_callback, timeout, metadata=None, protocol_options=None): """Asynchronously invokes the underlying RPC. Args: receiver: A ResponseReceiver to be passed the response data of the RPC. abortion_callback: A callback to be called and passed an Abortion value in the event of RPC abortion. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. protocol_options: A value specified by the provider of a Face interface implementation affording custom state and behavior. Returns: A single object that is both a Call object for the RPC and a stream.Consumer to which the request values of the RPC should be passed. """ raise NotImplementedError() class StreamStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): """Affords invoking a stream-stream RPC in any call style.""" @abc.abstractmethod def __call__(self, request_iterator, timeout, metadata=None, protocol_options=None): """Invokes the underlying RPC. Args: request_iterator: An iterator that yields request values for the RPC. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. protocol_options: A value specified by the provider of a Face interface implementation affording custom state and behavior. Returns: An object that is both a Call for the RPC and an iterator of response values. Drawing response values from the returned iterator may raise AbortionError indicating abortion of the RPC. """ raise NotImplementedError() @abc.abstractmethod def event(self, receiver, abortion_callback, timeout, metadata=None, protocol_options=None): """Asynchronously invokes the underlying RPC. Args: receiver: A ResponseReceiver to be passed the response data of the RPC. abortion_callback: A callback to be called and passed an Abortion value in the event of RPC abortion. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. protocol_options: A value specified by the provider of a Face interface implementation affording custom state and behavior. Returns: A single object that is both a Call object for the RPC and a stream.Consumer to which the request values of the RPC should be passed. """ raise NotImplementedError() class MethodImplementation(six.with_metaclass(abc.ABCMeta)): """A sum type that describes a method implementation. Attributes: cardinality: A cardinality.Cardinality value. style: A style.Service value. unary_unary_inline: The implementation of the method as a callable value that takes a request value and a ServicerContext object and returns a response value. Only non-None if cardinality is cardinality.Cardinality.UNARY_UNARY and style is style.Service.INLINE. unary_stream_inline: The implementation of the method as a callable value that takes a request value and a ServicerContext object and returns an iterator of response values. Only non-None if cardinality is cardinality.Cardinality.UNARY_STREAM and style is style.Service.INLINE. stream_unary_inline: The implementation of the method as a callable value that takes an iterator of request values and a ServicerContext object and returns a response value. Only non-None if cardinality is cardinality.Cardinality.STREAM_UNARY and style is style.Service.INLINE. stream_stream_inline: The implementation of the method as a callable value that takes an iterator of request values and a ServicerContext object and returns an iterator of response values. Only non-None if cardinality is cardinality.Cardinality.STREAM_STREAM and style is style.Service.INLINE. unary_unary_event: The implementation of the method as a callable value that takes a request value, a response callback to which to pass the response value of the RPC, and a ServicerContext. Only non-None if cardinality is cardinality.Cardinality.UNARY_UNARY and style is style.Service.EVENT. unary_stream_event: The implementation of the method as a callable value that takes a request value, a stream.Consumer to which to pass the response values of the RPC, and a ServicerContext. Only non-None if cardinality is cardinality.Cardinality.UNARY_STREAM and style is style.Service.EVENT. stream_unary_event: The implementation of the method as a callable value that takes a response callback to which to pass the response value of the RPC and a ServicerContext and returns a stream.Consumer to which the request values of the RPC should be passed. Only non-None if cardinality is cardinality.Cardinality.STREAM_UNARY and style is style.Service.EVENT. stream_stream_event: The implementation of the method as a callable value that takes a stream.Consumer to which to pass the response values of the RPC and a ServicerContext and returns a stream.Consumer to which the request values of the RPC should be passed. Only non-None if cardinality is cardinality.Cardinality.STREAM_STREAM and style is style.Service.EVENT. """ class MultiMethodImplementation(six.with_metaclass(abc.ABCMeta)): """A general type able to service many methods.""" @abc.abstractmethod def service(self, group, method, response_consumer, context): """Services an RPC. Args: group: The group identifier of the RPC. method: The method identifier of the RPC. response_consumer: A stream.Consumer to be called to accept the response values of the RPC. context: a ServicerContext object. Returns: A stream.Consumer with which to accept the request values of the RPC. The consumer returned from this method may or may not be invoked to completion: in the case of RPC abortion, RPC Framework will simply stop passing values to this object. Implementations must not assume that this object will be called to completion of the request stream or even called at all. Raises: abandonment.Abandoned: May or may not be raised when the RPC has been aborted. NoSuchMethodError: If this MultiMethod does not recognize the given group and name for the RPC and is not able to service the RPC. """ raise NotImplementedError() class GenericStub(six.with_metaclass(abc.ABCMeta)): """Affords RPC invocation via generic methods.""" @abc.abstractmethod def blocking_unary_unary(self, group, method, request, timeout, metadata=None, with_call=False, protocol_options=None): """Invokes a unary-request-unary-response method. This method blocks until either returning the response value of the RPC (in the event of RPC completion) or raising an exception (in the event of RPC abortion). Args: group: The group identifier of the RPC. method: The method identifier of the RPC. request: The request value for the RPC. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. with_call: Whether or not to include return a Call for the RPC in addition to the response. protocol_options: A value specified by the provider of a Face interface implementation affording custom state and behavior. Returns: The response value for the RPC, and a Call for the RPC if with_call was set to True at invocation. Raises: AbortionError: Indicating that the RPC was aborted. """ raise NotImplementedError() @abc.abstractmethod def future_unary_unary(self, group, method, request, timeout, metadata=None, protocol_options=None): """Invokes a unary-request-unary-response method. Args: group: The group identifier of the RPC. method: The method identifier of the RPC. request: The request value for the RPC. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. protocol_options: A value specified by the provider of a Face interface implementation affording custom state and behavior. Returns: An object that is both a Call for the RPC and a future.Future. In the event of RPC completion, the return Future's result value will be the response value of the RPC. In the event of RPC abortion, the returned Future's exception value will be an AbortionError. """ raise NotImplementedError() @abc.abstractmethod def inline_unary_stream(self, group, method, request, timeout, metadata=None, protocol_options=None): """Invokes a unary-request-stream-response method. Args: group: The group identifier of the RPC. method: The method identifier of the RPC. request: The request value for the RPC. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. protocol_options: A value specified by the provider of a Face interface implementation affording custom state and behavior. Returns: An object that is both a Call for the RPC and an iterator of response values. Drawing response values from the returned iterator may raise AbortionError indicating abortion of the RPC. """ raise NotImplementedError() @abc.abstractmethod def blocking_stream_unary(self, group, method, request_iterator, timeout, metadata=None, with_call=False, protocol_options=None): """Invokes a stream-request-unary-response method. This method blocks until either returning the response value of the RPC (in the event of RPC completion) or raising an exception (in the event of RPC abortion). Args: group: The group identifier of the RPC. method: The method identifier of the RPC. request_iterator: An iterator that yields request values for the RPC. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. with_call: Whether or not to include return a Call for the RPC in addition to the response. protocol_options: A value specified by the provider of a Face interface implementation affording custom state and behavior. Returns: The response value for the RPC, and a Call for the RPC if with_call was set to True at invocation. Raises: AbortionError: Indicating that the RPC was aborted. """ raise NotImplementedError() @abc.abstractmethod def future_stream_unary(self, group, method, request_iterator, timeout, metadata=None, protocol_options=None): """Invokes a stream-request-unary-response method. Args: group: The group identifier of the RPC. method: The method identifier of the RPC. request_iterator: An iterator that yields request values for the RPC. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. protocol_options: A value specified by the provider of a Face interface implementation affording custom state and behavior. Returns: An object that is both a Call for the RPC and a future.Future. In the event of RPC completion, the return Future's result value will be the response value of the RPC. In the event of RPC abortion, the returned Future's exception value will be an AbortionError. """ raise NotImplementedError() @abc.abstractmethod def inline_stream_stream(self, group, method, request_iterator, timeout, metadata=None, protocol_options=None): """Invokes a stream-request-stream-response method. Args: group: The group identifier of the RPC. method: The method identifier of the RPC. request_iterator: An iterator that yields request values for the RPC. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. protocol_options: A value specified by the provider of a Face interface implementation affording custom state and behavior. Returns: An object that is both a Call for the RPC and an iterator of response values. Drawing response values from the returned iterator may raise AbortionError indicating abortion of the RPC. """ raise NotImplementedError() @abc.abstractmethod def event_unary_unary(self, group, method, request, receiver, abortion_callback, timeout, metadata=None, protocol_options=None): """Event-driven invocation of a unary-request-unary-response method. Args: group: The group identifier of the RPC. method: The method identifier of the RPC. request: The request value for the RPC. receiver: A ResponseReceiver to be passed the response data of the RPC. abortion_callback: A callback to be called and passed an Abortion value in the event of RPC abortion. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. protocol_options: A value specified by the provider of a Face interface implementation affording custom state and behavior. Returns: A Call for the RPC. """ raise NotImplementedError() @abc.abstractmethod def event_unary_stream(self, group, method, request, receiver, abortion_callback, timeout, metadata=None, protocol_options=None): """Event-driven invocation of a unary-request-stream-response method. Args: group: The group identifier of the RPC. method: The method identifier of the RPC. request: The request value for the RPC. receiver: A ResponseReceiver to be passed the response data of the RPC. abortion_callback: A callback to be called and passed an Abortion value in the event of RPC abortion. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. protocol_options: A value specified by the provider of a Face interface implementation affording custom state and behavior. Returns: A Call for the RPC. """ raise NotImplementedError() @abc.abstractmethod def event_stream_unary(self, group, method, receiver, abortion_callback, timeout, metadata=None, protocol_options=None): """Event-driven invocation of a unary-request-unary-response method. Args: group: The group identifier of the RPC. method: The method identifier of the RPC. receiver: A ResponseReceiver to be passed the response data of the RPC. abortion_callback: A callback to be called and passed an Abortion value in the event of RPC abortion. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. protocol_options: A value specified by the provider of a Face interface implementation affording custom state and behavior. Returns: A pair of a Call object for the RPC and a stream.Consumer to which the request values of the RPC should be passed. """ raise NotImplementedError() @abc.abstractmethod def event_stream_stream(self, group, method, receiver, abortion_callback, timeout, metadata=None, protocol_options=None): """Event-driven invocation of a unary-request-stream-response method. Args: group: The group identifier of the RPC. method: The method identifier of the RPC. receiver: A ResponseReceiver to be passed the response data of the RPC. abortion_callback: A callback to be called and passed an Abortion value in the event of RPC abortion. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. protocol_options: A value specified by the provider of a Face interface implementation affording custom state and behavior. Returns: A pair of a Call object for the RPC and a stream.Consumer to which the request values of the RPC should be passed. """ raise NotImplementedError() @abc.abstractmethod def unary_unary(self, group, method): """Creates a UnaryUnaryMultiCallable for a unary-unary method. Args: group: The group identifier of the RPC. method: The method identifier of the RPC. Returns: A UnaryUnaryMultiCallable value for the named unary-unary method. """ raise NotImplementedError() @abc.abstractmethod def unary_stream(self, group, method): """Creates a UnaryStreamMultiCallable for a unary-stream method. Args: group: The group identifier of the RPC. method: The method identifier of the RPC. Returns: A UnaryStreamMultiCallable value for the name unary-stream method. """ raise NotImplementedError() @abc.abstractmethod def stream_unary(self, group, method): """Creates a StreamUnaryMultiCallable for a stream-unary method. Args: group: The group identifier of the RPC. method: The method identifier of the RPC. Returns: A StreamUnaryMultiCallable value for the named stream-unary method. """ raise NotImplementedError() @abc.abstractmethod def stream_stream(self, group, method): """Creates a StreamStreamMultiCallable for a stream-stream method. Args: group: The group identifier of the RPC. method: The method identifier of the RPC. Returns: A StreamStreamMultiCallable value for the named stream-stream method. """ raise NotImplementedError() class DynamicStub(six.with_metaclass(abc.ABCMeta)): """Affords RPC invocation via attributes corresponding to afforded methods. Instances of this type may be scoped to a single group so that attribute access is unambiguous. Instances of this type respond to attribute access as follows: if the requested attribute is the name of a unary-unary method, the value of the attribute will be a UnaryUnaryMultiCallable with which to invoke an RPC; if the requested attribute is the name of a unary-stream method, the value of the attribute will be a UnaryStreamMultiCallable with which to invoke an RPC; if the requested attribute is the name of a stream-unary method, the value of the attribute will be a StreamUnaryMultiCallable with which to invoke an RPC; and if the requested attribute is the name of a stream-stream method, the value of the attribute will be a StreamStreamMultiCallable with which to invoke an RPC. """ grpc-1.3.2/src/python/grpcio/grpc/framework/interfaces/face/utilities.py000066400000000000000000000167561310511640000264070ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Utilities for RPC Framework's Face interface.""" import collections # stream is referenced from specification in this module. from grpc.framework.common import cardinality from grpc.framework.common import style from grpc.framework.foundation import stream # pylint: disable=unused-import from grpc.framework.interfaces.face import face class _MethodImplementation(face.MethodImplementation, collections.namedtuple('_MethodImplementation', [ 'cardinality', 'style', 'unary_unary_inline', 'unary_stream_inline', 'stream_unary_inline', 'stream_stream_inline', 'unary_unary_event', 'unary_stream_event', 'stream_unary_event', 'stream_stream_event', ])): pass def unary_unary_inline(behavior): """Creates an face.MethodImplementation for the given behavior. Args: behavior: The implementation of a unary-unary RPC method as a callable value that takes a request value and an face.ServicerContext object and returns a response value. Returns: An face.MethodImplementation derived from the given behavior. """ return _MethodImplementation(cardinality.Cardinality.UNARY_UNARY, style.Service.INLINE, behavior, None, None, None, None, None, None, None) def unary_stream_inline(behavior): """Creates an face.MethodImplementation for the given behavior. Args: behavior: The implementation of a unary-stream RPC method as a callable value that takes a request value and an face.ServicerContext object and returns an iterator of response values. Returns: An face.MethodImplementation derived from the given behavior. """ return _MethodImplementation(cardinality.Cardinality.UNARY_STREAM, style.Service.INLINE, None, behavior, None, None, None, None, None, None) def stream_unary_inline(behavior): """Creates an face.MethodImplementation for the given behavior. Args: behavior: The implementation of a stream-unary RPC method as a callable value that takes an iterator of request values and an face.ServicerContext object and returns a response value. Returns: An face.MethodImplementation derived from the given behavior. """ return _MethodImplementation(cardinality.Cardinality.STREAM_UNARY, style.Service.INLINE, None, None, behavior, None, None, None, None, None) def stream_stream_inline(behavior): """Creates an face.MethodImplementation for the given behavior. Args: behavior: The implementation of a stream-stream RPC method as a callable value that takes an iterator of request values and an face.ServicerContext object and returns an iterator of response values. Returns: An face.MethodImplementation derived from the given behavior. """ return _MethodImplementation(cardinality.Cardinality.STREAM_STREAM, style.Service.INLINE, None, None, None, behavior, None, None, None, None) def unary_unary_event(behavior): """Creates an face.MethodImplementation for the given behavior. Args: behavior: The implementation of a unary-unary RPC method as a callable value that takes a request value, a response callback to which to pass the response value of the RPC, and an face.ServicerContext. Returns: An face.MethodImplementation derived from the given behavior. """ return _MethodImplementation(cardinality.Cardinality.UNARY_UNARY, style.Service.EVENT, None, None, None, None, behavior, None, None, None) def unary_stream_event(behavior): """Creates an face.MethodImplementation for the given behavior. Args: behavior: The implementation of a unary-stream RPC method as a callable value that takes a request value, a stream.Consumer to which to pass the the response values of the RPC, and an face.ServicerContext. Returns: An face.MethodImplementation derived from the given behavior. """ return _MethodImplementation(cardinality.Cardinality.UNARY_STREAM, style.Service.EVENT, None, None, None, None, None, behavior, None, None) def stream_unary_event(behavior): """Creates an face.MethodImplementation for the given behavior. Args: behavior: The implementation of a stream-unary RPC method as a callable value that takes a response callback to which to pass the response value of the RPC and an face.ServicerContext and returns a stream.Consumer to which the request values of the RPC should be passed. Returns: An face.MethodImplementation derived from the given behavior. """ return _MethodImplementation(cardinality.Cardinality.STREAM_UNARY, style.Service.EVENT, None, None, None, None, None, None, behavior, None) def stream_stream_event(behavior): """Creates an face.MethodImplementation for the given behavior. Args: behavior: The implementation of a stream-stream RPC method as a callable value that takes a stream.Consumer to which to pass the response values of the RPC and an face.ServicerContext and returns a stream.Consumer to which the request values of the RPC should be passed. Returns: An face.MethodImplementation derived from the given behavior. """ return _MethodImplementation(cardinality.Cardinality.STREAM_STREAM, style.Service.EVENT, None, None, None, None, None, None, None, behavior) grpc-1.3.2/src/python/grpcio/grpc_core_dependencies.py000066400000000000000000000772271310511640000230740ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_core_dependencies.py.template`!!! CORE_SOURCE_FILES = [ 'src/core/lib/profiling/basic_timers.c', 'src/core/lib/profiling/stap_timers.c', 'src/core/lib/support/alloc.c', 'src/core/lib/support/arena.c', 'src/core/lib/support/atm.c', 'src/core/lib/support/avl.c', 'src/core/lib/support/backoff.c', 'src/core/lib/support/cmdline.c', 'src/core/lib/support/cpu_iphone.c', 'src/core/lib/support/cpu_linux.c', 'src/core/lib/support/cpu_posix.c', 'src/core/lib/support/cpu_windows.c', 'src/core/lib/support/env_linux.c', 'src/core/lib/support/env_posix.c', 'src/core/lib/support/env_windows.c', 'src/core/lib/support/histogram.c', 'src/core/lib/support/host_port.c', 'src/core/lib/support/log.c', 'src/core/lib/support/log_android.c', 'src/core/lib/support/log_linux.c', 'src/core/lib/support/log_posix.c', 'src/core/lib/support/log_windows.c', 'src/core/lib/support/mpscq.c', 'src/core/lib/support/murmur_hash.c', 'src/core/lib/support/stack_lockfree.c', 'src/core/lib/support/string.c', 'src/core/lib/support/string_posix.c', 'src/core/lib/support/string_util_windows.c', 'src/core/lib/support/string_windows.c', 'src/core/lib/support/subprocess_posix.c', 'src/core/lib/support/subprocess_windows.c', 'src/core/lib/support/sync.c', 'src/core/lib/support/sync_posix.c', 'src/core/lib/support/sync_windows.c', 'src/core/lib/support/thd.c', 'src/core/lib/support/thd_posix.c', 'src/core/lib/support/thd_windows.c', 'src/core/lib/support/time.c', 'src/core/lib/support/time_posix.c', 'src/core/lib/support/time_precise.c', 'src/core/lib/support/time_windows.c', 'src/core/lib/support/tls_pthread.c', 'src/core/lib/support/tmpfile_msys.c', 'src/core/lib/support/tmpfile_posix.c', 'src/core/lib/support/tmpfile_windows.c', 'src/core/lib/support/wrap_memcpy.c', 'src/core/lib/surface/init.c', 'src/core/lib/channel/channel_args.c', 'src/core/lib/channel/channel_stack.c', 'src/core/lib/channel/channel_stack_builder.c', 'src/core/lib/channel/compress_filter.c', 'src/core/lib/channel/connected_channel.c', 'src/core/lib/channel/deadline_filter.c', 'src/core/lib/channel/handshaker.c', 'src/core/lib/channel/handshaker_factory.c', 'src/core/lib/channel/handshaker_registry.c', 'src/core/lib/channel/http_client_filter.c', 'src/core/lib/channel/http_server_filter.c', 'src/core/lib/channel/message_size_filter.c', 'src/core/lib/compression/compression.c', 'src/core/lib/compression/message_compress.c', 'src/core/lib/debug/trace.c', 'src/core/lib/http/format_request.c', 'src/core/lib/http/httpcli.c', 'src/core/lib/http/parser.c', 'src/core/lib/iomgr/closure.c', 'src/core/lib/iomgr/combiner.c', 'src/core/lib/iomgr/endpoint.c', 'src/core/lib/iomgr/endpoint_pair_posix.c', 'src/core/lib/iomgr/endpoint_pair_uv.c', 'src/core/lib/iomgr/endpoint_pair_windows.c', 'src/core/lib/iomgr/error.c', 'src/core/lib/iomgr/ev_epoll_linux.c', 'src/core/lib/iomgr/ev_poll_posix.c', 'src/core/lib/iomgr/ev_posix.c', 'src/core/lib/iomgr/exec_ctx.c', 'src/core/lib/iomgr/executor.c', 'src/core/lib/iomgr/iocp_windows.c', 'src/core/lib/iomgr/iomgr.c', 'src/core/lib/iomgr/iomgr_posix.c', 'src/core/lib/iomgr/iomgr_uv.c', 'src/core/lib/iomgr/iomgr_windows.c', 'src/core/lib/iomgr/load_file.c', 'src/core/lib/iomgr/lockfree_event.c', 'src/core/lib/iomgr/network_status_tracker.c', 'src/core/lib/iomgr/polling_entity.c', 'src/core/lib/iomgr/pollset_set_uv.c', 'src/core/lib/iomgr/pollset_set_windows.c', 'src/core/lib/iomgr/pollset_uv.c', 'src/core/lib/iomgr/pollset_windows.c', 'src/core/lib/iomgr/resolve_address_posix.c', 'src/core/lib/iomgr/resolve_address_uv.c', 'src/core/lib/iomgr/resolve_address_windows.c', 'src/core/lib/iomgr/resource_quota.c', 'src/core/lib/iomgr/sockaddr_utils.c', 'src/core/lib/iomgr/socket_factory_posix.c', 'src/core/lib/iomgr/socket_mutator.c', 'src/core/lib/iomgr/socket_utils_common_posix.c', 'src/core/lib/iomgr/socket_utils_linux.c', 'src/core/lib/iomgr/socket_utils_posix.c', 'src/core/lib/iomgr/socket_utils_uv.c', 'src/core/lib/iomgr/socket_utils_windows.c', 'src/core/lib/iomgr/socket_windows.c', 'src/core/lib/iomgr/tcp_client_posix.c', 'src/core/lib/iomgr/tcp_client_uv.c', 'src/core/lib/iomgr/tcp_client_windows.c', 'src/core/lib/iomgr/tcp_posix.c', 'src/core/lib/iomgr/tcp_server_posix.c', 'src/core/lib/iomgr/tcp_server_utils_posix_common.c', 'src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c', 'src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c', 'src/core/lib/iomgr/tcp_server_uv.c', 'src/core/lib/iomgr/tcp_server_windows.c', 'src/core/lib/iomgr/tcp_uv.c', 'src/core/lib/iomgr/tcp_windows.c', 'src/core/lib/iomgr/time_averaged_stats.c', 'src/core/lib/iomgr/timer_generic.c', 'src/core/lib/iomgr/timer_heap.c', 'src/core/lib/iomgr/timer_uv.c', 'src/core/lib/iomgr/udp_server.c', 'src/core/lib/iomgr/unix_sockets_posix.c', 'src/core/lib/iomgr/unix_sockets_posix_noop.c', 'src/core/lib/iomgr/wakeup_fd_cv.c', 'src/core/lib/iomgr/wakeup_fd_eventfd.c', 'src/core/lib/iomgr/wakeup_fd_nospecial.c', 'src/core/lib/iomgr/wakeup_fd_pipe.c', 'src/core/lib/iomgr/wakeup_fd_posix.c', 'src/core/lib/iomgr/workqueue_uv.c', 'src/core/lib/iomgr/workqueue_windows.c', 'src/core/lib/json/json.c', 'src/core/lib/json/json_reader.c', 'src/core/lib/json/json_string.c', 'src/core/lib/json/json_writer.c', 'src/core/lib/slice/b64.c', 'src/core/lib/slice/percent_encoding.c', 'src/core/lib/slice/slice.c', 'src/core/lib/slice/slice_buffer.c', 'src/core/lib/slice/slice_hash_table.c', 'src/core/lib/slice/slice_intern.c', 'src/core/lib/slice/slice_string_helpers.c', 'src/core/lib/surface/alarm.c', 'src/core/lib/surface/api_trace.c', 'src/core/lib/surface/byte_buffer.c', 'src/core/lib/surface/byte_buffer_reader.c', 'src/core/lib/surface/call.c', 'src/core/lib/surface/call_details.c', 'src/core/lib/surface/call_log_batch.c', 'src/core/lib/surface/channel.c', 'src/core/lib/surface/channel_init.c', 'src/core/lib/surface/channel_ping.c', 'src/core/lib/surface/channel_stack_type.c', 'src/core/lib/surface/completion_queue.c', 'src/core/lib/surface/completion_queue_factory.c', 'src/core/lib/surface/event_string.c', 'src/core/lib/surface/lame_client.c', 'src/core/lib/surface/metadata_array.c', 'src/core/lib/surface/server.c', 'src/core/lib/surface/validate_metadata.c', 'src/core/lib/surface/version.c', 'src/core/lib/transport/bdp_estimator.c', 'src/core/lib/transport/byte_stream.c', 'src/core/lib/transport/connectivity_state.c', 'src/core/lib/transport/error_utils.c', 'src/core/lib/transport/metadata.c', 'src/core/lib/transport/metadata_batch.c', 'src/core/lib/transport/pid_controller.c', 'src/core/lib/transport/service_config.c', 'src/core/lib/transport/static_metadata.c', 'src/core/lib/transport/status_conversion.c', 'src/core/lib/transport/timeout_encoding.c', 'src/core/lib/transport/transport.c', 'src/core/lib/transport/transport_op_string.c', 'src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c', 'src/core/ext/transport/chttp2/transport/bin_decoder.c', 'src/core/ext/transport/chttp2/transport/bin_encoder.c', 'src/core/ext/transport/chttp2/transport/chttp2_plugin.c', 'src/core/ext/transport/chttp2/transport/chttp2_transport.c', 'src/core/ext/transport/chttp2/transport/frame_data.c', 'src/core/ext/transport/chttp2/transport/frame_goaway.c', 'src/core/ext/transport/chttp2/transport/frame_ping.c', 'src/core/ext/transport/chttp2/transport/frame_rst_stream.c', 'src/core/ext/transport/chttp2/transport/frame_settings.c', 'src/core/ext/transport/chttp2/transport/frame_window_update.c', 'src/core/ext/transport/chttp2/transport/hpack_encoder.c', 'src/core/ext/transport/chttp2/transport/hpack_parser.c', 'src/core/ext/transport/chttp2/transport/hpack_table.c', 'src/core/ext/transport/chttp2/transport/http2_settings.c', 'src/core/ext/transport/chttp2/transport/huffsyms.c', 'src/core/ext/transport/chttp2/transport/incoming_metadata.c', 'src/core/ext/transport/chttp2/transport/parsing.c', 'src/core/ext/transport/chttp2/transport/stream_lists.c', 'src/core/ext/transport/chttp2/transport/stream_map.c', 'src/core/ext/transport/chttp2/transport/varint.c', 'src/core/ext/transport/chttp2/transport/writing.c', 'src/core/ext/transport/chttp2/alpn/alpn.c', 'src/core/lib/http/httpcli_security_connector.c', 'src/core/lib/security/context/security_context.c', 'src/core/lib/security/credentials/composite/composite_credentials.c', 'src/core/lib/security/credentials/credentials.c', 'src/core/lib/security/credentials/credentials_metadata.c', 'src/core/lib/security/credentials/fake/fake_credentials.c', 'src/core/lib/security/credentials/google_default/credentials_generic.c', 'src/core/lib/security/credentials/google_default/google_default_credentials.c', 'src/core/lib/security/credentials/iam/iam_credentials.c', 'src/core/lib/security/credentials/jwt/json_token.c', 'src/core/lib/security/credentials/jwt/jwt_credentials.c', 'src/core/lib/security/credentials/jwt/jwt_verifier.c', 'src/core/lib/security/credentials/oauth2/oauth2_credentials.c', 'src/core/lib/security/credentials/plugin/plugin_credentials.c', 'src/core/lib/security/credentials/ssl/ssl_credentials.c', 'src/core/lib/security/transport/client_auth_filter.c', 'src/core/lib/security/transport/lb_targets_info.c', 'src/core/lib/security/transport/secure_endpoint.c', 'src/core/lib/security/transport/security_connector.c', 'src/core/lib/security/transport/security_handshaker.c', 'src/core/lib/security/transport/server_auth_filter.c', 'src/core/lib/security/transport/tsi_error.c', 'src/core/lib/security/util/json_util.c', 'src/core/lib/surface/init_secure.c', 'src/core/tsi/fake_transport_security.c', 'src/core/tsi/ssl_transport_security.c', 'src/core/tsi/transport_security.c', 'src/core/ext/transport/chttp2/server/chttp2_server.c', 'src/core/ext/transport/chttp2/client/secure/secure_channel_create.c', 'src/core/ext/filters/client_channel/channel_connectivity.c', 'src/core/ext/filters/client_channel/client_channel.c', 'src/core/ext/filters/client_channel/client_channel_factory.c', 'src/core/ext/filters/client_channel/client_channel_plugin.c', 'src/core/ext/filters/client_channel/connector.c', 'src/core/ext/filters/client_channel/http_connect_handshaker.c', 'src/core/ext/filters/client_channel/http_proxy.c', 'src/core/ext/filters/client_channel/lb_policy.c', 'src/core/ext/filters/client_channel/lb_policy_factory.c', 'src/core/ext/filters/client_channel/lb_policy_registry.c', 'src/core/ext/filters/client_channel/parse_address.c', 'src/core/ext/filters/client_channel/proxy_mapper.c', 'src/core/ext/filters/client_channel/proxy_mapper_registry.c', 'src/core/ext/filters/client_channel/resolver.c', 'src/core/ext/filters/client_channel/resolver_factory.c', 'src/core/ext/filters/client_channel/resolver_registry.c', 'src/core/ext/filters/client_channel/retry_throttle.c', 'src/core/ext/filters/client_channel/subchannel.c', 'src/core/ext/filters/client_channel/subchannel_index.c', 'src/core/ext/filters/client_channel/uri_parser.c', 'src/core/ext/transport/chttp2/client/chttp2_connector.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', 'third_party/nanopb/pb_decode.c', 'third_party/nanopb/pb_encode.c', 'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c', 'src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c', 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.c', 'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c', 'src/core/ext/filters/load_reporting/load_reporting.c', 'src/core/ext/filters/load_reporting/load_reporting_filter.c', 'src/core/ext/census/base_resources.c', 'src/core/ext/census/context.c', 'src/core/ext/census/gen/census.pb.c', 'src/core/ext/census/gen/trace_context.pb.c', 'src/core/ext/census/grpc_context.c', 'src/core/ext/census/grpc_filter.c', 'src/core/ext/census/grpc_plugin.c', 'src/core/ext/census/initialize.c', 'src/core/ext/census/mlog.c', 'src/core/ext/census/operation.c', 'src/core/ext/census/placeholders.c', 'src/core/ext/census/resource.c', 'src/core/ext/census/trace_context.c', 'src/core/ext/census/tracing.c', 'src/core/ext/filters/max_age/max_age_filter.c', 'src/core/plugin_registry/grpc_plugin_registry.c', 'src/boringssl/err_data.c', 'third_party/boringssl/crypto/aes/aes.c', 'third_party/boringssl/crypto/aes/mode_wrappers.c', 'third_party/boringssl/crypto/asn1/a_bitstr.c', 'third_party/boringssl/crypto/asn1/a_bool.c', 'third_party/boringssl/crypto/asn1/a_d2i_fp.c', 'third_party/boringssl/crypto/asn1/a_dup.c', 'third_party/boringssl/crypto/asn1/a_enum.c', 'third_party/boringssl/crypto/asn1/a_gentm.c', 'third_party/boringssl/crypto/asn1/a_i2d_fp.c', 'third_party/boringssl/crypto/asn1/a_int.c', 'third_party/boringssl/crypto/asn1/a_mbstr.c', 'third_party/boringssl/crypto/asn1/a_object.c', 'third_party/boringssl/crypto/asn1/a_octet.c', 'third_party/boringssl/crypto/asn1/a_print.c', 'third_party/boringssl/crypto/asn1/a_strnid.c', 'third_party/boringssl/crypto/asn1/a_time.c', 'third_party/boringssl/crypto/asn1/a_type.c', 'third_party/boringssl/crypto/asn1/a_utctm.c', 'third_party/boringssl/crypto/asn1/a_utf8.c', 'third_party/boringssl/crypto/asn1/asn1_lib.c', 'third_party/boringssl/crypto/asn1/asn1_par.c', 'third_party/boringssl/crypto/asn1/asn_pack.c', 'third_party/boringssl/crypto/asn1/f_enum.c', 'third_party/boringssl/crypto/asn1/f_int.c', 'third_party/boringssl/crypto/asn1/f_string.c', 'third_party/boringssl/crypto/asn1/t_bitst.c', 'third_party/boringssl/crypto/asn1/tasn_dec.c', 'third_party/boringssl/crypto/asn1/tasn_enc.c', 'third_party/boringssl/crypto/asn1/tasn_fre.c', 'third_party/boringssl/crypto/asn1/tasn_new.c', 'third_party/boringssl/crypto/asn1/tasn_typ.c', 'third_party/boringssl/crypto/asn1/tasn_utl.c', 'third_party/boringssl/crypto/asn1/x_bignum.c', 'third_party/boringssl/crypto/asn1/x_long.c', 'third_party/boringssl/crypto/base64/base64.c', 'third_party/boringssl/crypto/bio/bio.c', 'third_party/boringssl/crypto/bio/bio_mem.c', 'third_party/boringssl/crypto/bio/buffer.c', 'third_party/boringssl/crypto/bio/connect.c', 'third_party/boringssl/crypto/bio/fd.c', 'third_party/boringssl/crypto/bio/file.c', 'third_party/boringssl/crypto/bio/hexdump.c', 'third_party/boringssl/crypto/bio/pair.c', 'third_party/boringssl/crypto/bio/printf.c', 'third_party/boringssl/crypto/bio/socket.c', 'third_party/boringssl/crypto/bio/socket_helper.c', 'third_party/boringssl/crypto/bn/add.c', 'third_party/boringssl/crypto/bn/asm/x86_64-gcc.c', 'third_party/boringssl/crypto/bn/bn.c', 'third_party/boringssl/crypto/bn/bn_asn1.c', 'third_party/boringssl/crypto/bn/cmp.c', 'third_party/boringssl/crypto/bn/convert.c', 'third_party/boringssl/crypto/bn/ctx.c', 'third_party/boringssl/crypto/bn/div.c', 'third_party/boringssl/crypto/bn/exponentiation.c', 'third_party/boringssl/crypto/bn/gcd.c', 'third_party/boringssl/crypto/bn/generic.c', 'third_party/boringssl/crypto/bn/kronecker.c', 'third_party/boringssl/crypto/bn/montgomery.c', 'third_party/boringssl/crypto/bn/montgomery_inv.c', 'third_party/boringssl/crypto/bn/mul.c', 'third_party/boringssl/crypto/bn/prime.c', 'third_party/boringssl/crypto/bn/random.c', 'third_party/boringssl/crypto/bn/rsaz_exp.c', 'third_party/boringssl/crypto/bn/shift.c', 'third_party/boringssl/crypto/bn/sqrt.c', 'third_party/boringssl/crypto/buf/buf.c', 'third_party/boringssl/crypto/bytestring/asn1_compat.c', 'third_party/boringssl/crypto/bytestring/ber.c', 'third_party/boringssl/crypto/bytestring/cbb.c', 'third_party/boringssl/crypto/bytestring/cbs.c', 'third_party/boringssl/crypto/chacha/chacha.c', 'third_party/boringssl/crypto/cipher/aead.c', 'third_party/boringssl/crypto/cipher/cipher.c', 'third_party/boringssl/crypto/cipher/derive_key.c', 'third_party/boringssl/crypto/cipher/e_aes.c', 'third_party/boringssl/crypto/cipher/e_chacha20poly1305.c', 'third_party/boringssl/crypto/cipher/e_des.c', 'third_party/boringssl/crypto/cipher/e_null.c', 'third_party/boringssl/crypto/cipher/e_rc2.c', 'third_party/boringssl/crypto/cipher/e_rc4.c', 'third_party/boringssl/crypto/cipher/e_ssl3.c', 'third_party/boringssl/crypto/cipher/e_tls.c', 'third_party/boringssl/crypto/cipher/tls_cbc.c', 'third_party/boringssl/crypto/cmac/cmac.c', 'third_party/boringssl/crypto/conf/conf.c', 'third_party/boringssl/crypto/cpu-aarch64-linux.c', 'third_party/boringssl/crypto/cpu-arm-linux.c', 'third_party/boringssl/crypto/cpu-arm.c', 'third_party/boringssl/crypto/cpu-intel.c', 'third_party/boringssl/crypto/cpu-ppc64le.c', 'third_party/boringssl/crypto/crypto.c', 'third_party/boringssl/crypto/curve25519/curve25519.c', 'third_party/boringssl/crypto/curve25519/spake25519.c', 'third_party/boringssl/crypto/curve25519/x25519-x86_64.c', 'third_party/boringssl/crypto/des/des.c', 'third_party/boringssl/crypto/dh/check.c', 'third_party/boringssl/crypto/dh/dh.c', 'third_party/boringssl/crypto/dh/dh_asn1.c', 'third_party/boringssl/crypto/dh/params.c', 'third_party/boringssl/crypto/digest/digest.c', 'third_party/boringssl/crypto/digest/digests.c', 'third_party/boringssl/crypto/dsa/dsa.c', 'third_party/boringssl/crypto/dsa/dsa_asn1.c', 'third_party/boringssl/crypto/ec/ec.c', 'third_party/boringssl/crypto/ec/ec_asn1.c', 'third_party/boringssl/crypto/ec/ec_key.c', 'third_party/boringssl/crypto/ec/ec_montgomery.c', 'third_party/boringssl/crypto/ec/oct.c', 'third_party/boringssl/crypto/ec/p224-64.c', 'third_party/boringssl/crypto/ec/p256-64.c', 'third_party/boringssl/crypto/ec/p256-x86_64.c', 'third_party/boringssl/crypto/ec/simple.c', 'third_party/boringssl/crypto/ec/util-64.c', 'third_party/boringssl/crypto/ec/wnaf.c', 'third_party/boringssl/crypto/ecdh/ecdh.c', 'third_party/boringssl/crypto/ecdsa/ecdsa.c', 'third_party/boringssl/crypto/ecdsa/ecdsa_asn1.c', 'third_party/boringssl/crypto/engine/engine.c', 'third_party/boringssl/crypto/err/err.c', 'third_party/boringssl/crypto/evp/digestsign.c', 'third_party/boringssl/crypto/evp/evp.c', 'third_party/boringssl/crypto/evp/evp_asn1.c', 'third_party/boringssl/crypto/evp/evp_ctx.c', 'third_party/boringssl/crypto/evp/p_dsa_asn1.c', 'third_party/boringssl/crypto/evp/p_ec.c', 'third_party/boringssl/crypto/evp/p_ec_asn1.c', 'third_party/boringssl/crypto/evp/p_rsa.c', 'third_party/boringssl/crypto/evp/p_rsa_asn1.c', 'third_party/boringssl/crypto/evp/pbkdf.c', 'third_party/boringssl/crypto/evp/print.c', 'third_party/boringssl/crypto/evp/sign.c', 'third_party/boringssl/crypto/ex_data.c', 'third_party/boringssl/crypto/hkdf/hkdf.c', 'third_party/boringssl/crypto/hmac/hmac.c', 'third_party/boringssl/crypto/lhash/lhash.c', 'third_party/boringssl/crypto/md4/md4.c', 'third_party/boringssl/crypto/md5/md5.c', 'third_party/boringssl/crypto/mem.c', 'third_party/boringssl/crypto/modes/cbc.c', 'third_party/boringssl/crypto/modes/cfb.c', 'third_party/boringssl/crypto/modes/ctr.c', 'third_party/boringssl/crypto/modes/gcm.c', 'third_party/boringssl/crypto/modes/ofb.c', 'third_party/boringssl/crypto/newhope/error_correction.c', 'third_party/boringssl/crypto/newhope/newhope.c', 'third_party/boringssl/crypto/newhope/ntt.c', 'third_party/boringssl/crypto/newhope/poly.c', 'third_party/boringssl/crypto/newhope/precomp.c', 'third_party/boringssl/crypto/newhope/reduce.c', 'third_party/boringssl/crypto/obj/obj.c', 'third_party/boringssl/crypto/obj/obj_xref.c', 'third_party/boringssl/crypto/pem/pem_all.c', 'third_party/boringssl/crypto/pem/pem_info.c', 'third_party/boringssl/crypto/pem/pem_lib.c', 'third_party/boringssl/crypto/pem/pem_oth.c', 'third_party/boringssl/crypto/pem/pem_pk8.c', 'third_party/boringssl/crypto/pem/pem_pkey.c', 'third_party/boringssl/crypto/pem/pem_x509.c', 'third_party/boringssl/crypto/pem/pem_xaux.c', 'third_party/boringssl/crypto/pkcs8/p5_pbe.c', 'third_party/boringssl/crypto/pkcs8/p5_pbev2.c', 'third_party/boringssl/crypto/pkcs8/p8_pkey.c', 'third_party/boringssl/crypto/pkcs8/pkcs8.c', 'third_party/boringssl/crypto/poly1305/poly1305.c', 'third_party/boringssl/crypto/poly1305/poly1305_arm.c', 'third_party/boringssl/crypto/poly1305/poly1305_vec.c', 'third_party/boringssl/crypto/rand/deterministic.c', 'third_party/boringssl/crypto/rand/rand.c', 'third_party/boringssl/crypto/rand/urandom.c', 'third_party/boringssl/crypto/rand/windows.c', 'third_party/boringssl/crypto/rc4/rc4.c', 'third_party/boringssl/crypto/refcount_c11.c', 'third_party/boringssl/crypto/refcount_lock.c', 'third_party/boringssl/crypto/rsa/blinding.c', 'third_party/boringssl/crypto/rsa/padding.c', 'third_party/boringssl/crypto/rsa/rsa.c', 'third_party/boringssl/crypto/rsa/rsa_asn1.c', 'third_party/boringssl/crypto/rsa/rsa_impl.c', 'third_party/boringssl/crypto/sha/sha1.c', 'third_party/boringssl/crypto/sha/sha256.c', 'third_party/boringssl/crypto/sha/sha512.c', 'third_party/boringssl/crypto/stack/stack.c', 'third_party/boringssl/crypto/thread.c', 'third_party/boringssl/crypto/thread_none.c', 'third_party/boringssl/crypto/thread_pthread.c', 'third_party/boringssl/crypto/thread_win.c', 'third_party/boringssl/crypto/time_support.c', 'third_party/boringssl/crypto/x509/a_digest.c', 'third_party/boringssl/crypto/x509/a_sign.c', 'third_party/boringssl/crypto/x509/a_strex.c', 'third_party/boringssl/crypto/x509/a_verify.c', 'third_party/boringssl/crypto/x509/algorithm.c', 'third_party/boringssl/crypto/x509/asn1_gen.c', 'third_party/boringssl/crypto/x509/by_dir.c', 'third_party/boringssl/crypto/x509/by_file.c', 'third_party/boringssl/crypto/x509/i2d_pr.c', 'third_party/boringssl/crypto/x509/pkcs7.c', 'third_party/boringssl/crypto/x509/rsa_pss.c', 'third_party/boringssl/crypto/x509/t_crl.c', 'third_party/boringssl/crypto/x509/t_req.c', 'third_party/boringssl/crypto/x509/t_x509.c', 'third_party/boringssl/crypto/x509/t_x509a.c', 'third_party/boringssl/crypto/x509/x509.c', 'third_party/boringssl/crypto/x509/x509_att.c', 'third_party/boringssl/crypto/x509/x509_cmp.c', 'third_party/boringssl/crypto/x509/x509_d2.c', 'third_party/boringssl/crypto/x509/x509_def.c', 'third_party/boringssl/crypto/x509/x509_ext.c', 'third_party/boringssl/crypto/x509/x509_lu.c', 'third_party/boringssl/crypto/x509/x509_obj.c', 'third_party/boringssl/crypto/x509/x509_r2x.c', 'third_party/boringssl/crypto/x509/x509_req.c', 'third_party/boringssl/crypto/x509/x509_set.c', 'third_party/boringssl/crypto/x509/x509_trs.c', 'third_party/boringssl/crypto/x509/x509_txt.c', 'third_party/boringssl/crypto/x509/x509_v3.c', 'third_party/boringssl/crypto/x509/x509_vfy.c', 'third_party/boringssl/crypto/x509/x509_vpm.c', 'third_party/boringssl/crypto/x509/x509cset.c', 'third_party/boringssl/crypto/x509/x509name.c', 'third_party/boringssl/crypto/x509/x509rset.c', 'third_party/boringssl/crypto/x509/x509spki.c', 'third_party/boringssl/crypto/x509/x509type.c', 'third_party/boringssl/crypto/x509/x_algor.c', 'third_party/boringssl/crypto/x509/x_all.c', 'third_party/boringssl/crypto/x509/x_attrib.c', 'third_party/boringssl/crypto/x509/x_crl.c', 'third_party/boringssl/crypto/x509/x_exten.c', 'third_party/boringssl/crypto/x509/x_info.c', 'third_party/boringssl/crypto/x509/x_name.c', 'third_party/boringssl/crypto/x509/x_pkey.c', 'third_party/boringssl/crypto/x509/x_pubkey.c', 'third_party/boringssl/crypto/x509/x_req.c', 'third_party/boringssl/crypto/x509/x_sig.c', 'third_party/boringssl/crypto/x509/x_spki.c', 'third_party/boringssl/crypto/x509/x_val.c', 'third_party/boringssl/crypto/x509/x_x509.c', 'third_party/boringssl/crypto/x509/x_x509a.c', 'third_party/boringssl/crypto/x509v3/pcy_cache.c', 'third_party/boringssl/crypto/x509v3/pcy_data.c', 'third_party/boringssl/crypto/x509v3/pcy_lib.c', 'third_party/boringssl/crypto/x509v3/pcy_map.c', 'third_party/boringssl/crypto/x509v3/pcy_node.c', 'third_party/boringssl/crypto/x509v3/pcy_tree.c', 'third_party/boringssl/crypto/x509v3/v3_akey.c', 'third_party/boringssl/crypto/x509v3/v3_akeya.c', 'third_party/boringssl/crypto/x509v3/v3_alt.c', 'third_party/boringssl/crypto/x509v3/v3_bcons.c', 'third_party/boringssl/crypto/x509v3/v3_bitst.c', 'third_party/boringssl/crypto/x509v3/v3_conf.c', 'third_party/boringssl/crypto/x509v3/v3_cpols.c', 'third_party/boringssl/crypto/x509v3/v3_crld.c', 'third_party/boringssl/crypto/x509v3/v3_enum.c', 'third_party/boringssl/crypto/x509v3/v3_extku.c', 'third_party/boringssl/crypto/x509v3/v3_genn.c', 'third_party/boringssl/crypto/x509v3/v3_ia5.c', 'third_party/boringssl/crypto/x509v3/v3_info.c', 'third_party/boringssl/crypto/x509v3/v3_int.c', 'third_party/boringssl/crypto/x509v3/v3_lib.c', 'third_party/boringssl/crypto/x509v3/v3_ncons.c', 'third_party/boringssl/crypto/x509v3/v3_pci.c', 'third_party/boringssl/crypto/x509v3/v3_pcia.c', 'third_party/boringssl/crypto/x509v3/v3_pcons.c', 'third_party/boringssl/crypto/x509v3/v3_pku.c', 'third_party/boringssl/crypto/x509v3/v3_pmaps.c', 'third_party/boringssl/crypto/x509v3/v3_prn.c', 'third_party/boringssl/crypto/x509v3/v3_purp.c', 'third_party/boringssl/crypto/x509v3/v3_skey.c', 'third_party/boringssl/crypto/x509v3/v3_sxnet.c', 'third_party/boringssl/crypto/x509v3/v3_utl.c', 'third_party/boringssl/ssl/custom_extensions.c', 'third_party/boringssl/ssl/d1_both.c', 'third_party/boringssl/ssl/d1_lib.c', 'third_party/boringssl/ssl/d1_pkt.c', 'third_party/boringssl/ssl/d1_srtp.c', 'third_party/boringssl/ssl/dtls_method.c', 'third_party/boringssl/ssl/dtls_record.c', 'third_party/boringssl/ssl/handshake_client.c', 'third_party/boringssl/ssl/handshake_server.c', 'third_party/boringssl/ssl/s3_both.c', 'third_party/boringssl/ssl/s3_enc.c', 'third_party/boringssl/ssl/s3_lib.c', 'third_party/boringssl/ssl/s3_pkt.c', 'third_party/boringssl/ssl/ssl_aead_ctx.c', 'third_party/boringssl/ssl/ssl_asn1.c', 'third_party/boringssl/ssl/ssl_buffer.c', 'third_party/boringssl/ssl/ssl_cert.c', 'third_party/boringssl/ssl/ssl_cipher.c', 'third_party/boringssl/ssl/ssl_ecdh.c', 'third_party/boringssl/ssl/ssl_file.c', 'third_party/boringssl/ssl/ssl_lib.c', 'third_party/boringssl/ssl/ssl_rsa.c', 'third_party/boringssl/ssl/ssl_session.c', 'third_party/boringssl/ssl/ssl_stat.c', 'third_party/boringssl/ssl/t1_enc.c', 'third_party/boringssl/ssl/t1_lib.c', 'third_party/boringssl/ssl/tls13_both.c', 'third_party/boringssl/ssl/tls13_client.c', 'third_party/boringssl/ssl/tls13_enc.c', 'third_party/boringssl/ssl/tls13_server.c', 'third_party/boringssl/ssl/tls_method.c', 'third_party/boringssl/ssl/tls_record.c', 'third_party/zlib/adler32.c', 'third_party/zlib/compress.c', 'third_party/zlib/crc32.c', 'third_party/zlib/deflate.c', 'third_party/zlib/gzclose.c', 'third_party/zlib/gzlib.c', 'third_party/zlib/gzread.c', 'third_party/zlib/gzwrite.c', 'third_party/zlib/infback.c', 'third_party/zlib/inffast.c', 'third_party/zlib/inflate.c', 'third_party/zlib/inftrees.c', 'third_party/zlib/trees.c', 'third_party/zlib/uncompr.c', 'third_party/zlib/zutil.c', 'third_party/cares/cares/ares__close_sockets.c', 'third_party/cares/cares/ares__get_hostent.c', 'third_party/cares/cares/ares__read_line.c', 'third_party/cares/cares/ares__timeval.c', 'third_party/cares/cares/ares_cancel.c', 'third_party/cares/cares/ares_create_query.c', 'third_party/cares/cares/ares_data.c', 'third_party/cares/cares/ares_destroy.c', 'third_party/cares/cares/ares_expand_name.c', 'third_party/cares/cares/ares_expand_string.c', 'third_party/cares/cares/ares_fds.c', 'third_party/cares/cares/ares_free_hostent.c', 'third_party/cares/cares/ares_free_string.c', 'third_party/cares/cares/ares_getenv.c', 'third_party/cares/cares/ares_gethostbyaddr.c', 'third_party/cares/cares/ares_gethostbyname.c', 'third_party/cares/cares/ares_getnameinfo.c', 'third_party/cares/cares/ares_getopt.c', 'third_party/cares/cares/ares_getsock.c', 'third_party/cares/cares/ares_init.c', 'third_party/cares/cares/ares_library_init.c', 'third_party/cares/cares/ares_llist.c', 'third_party/cares/cares/ares_mkquery.c', 'third_party/cares/cares/ares_nowarn.c', 'third_party/cares/cares/ares_options.c', 'third_party/cares/cares/ares_parse_a_reply.c', 'third_party/cares/cares/ares_parse_aaaa_reply.c', 'third_party/cares/cares/ares_parse_mx_reply.c', 'third_party/cares/cares/ares_parse_naptr_reply.c', 'third_party/cares/cares/ares_parse_ns_reply.c', 'third_party/cares/cares/ares_parse_ptr_reply.c', 'third_party/cares/cares/ares_parse_soa_reply.c', 'third_party/cares/cares/ares_parse_srv_reply.c', 'third_party/cares/cares/ares_parse_txt_reply.c', 'third_party/cares/cares/ares_platform.c', 'third_party/cares/cares/ares_process.c', 'third_party/cares/cares/ares_query.c', 'third_party/cares/cares/ares_search.c', 'third_party/cares/cares/ares_send.c', 'third_party/cares/cares/ares_strcasecmp.c', 'third_party/cares/cares/ares_strdup.c', 'third_party/cares/cares/ares_strerror.c', 'third_party/cares/cares/ares_timeout.c', 'third_party/cares/cares/ares_version.c', 'third_party/cares/cares/ares_writev.c', 'third_party/cares/cares/bitncmp.c', 'third_party/cares/cares/inet_net_pton.c', 'third_party/cares/cares/inet_ntop.c', 'third_party/cares/cares/windows_port.c', ] grpc-1.3.2/src/python/grpcio/grpc_version.py000066400000000000000000000031451310511640000211070ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!! VERSION='1.3.2' grpc-1.3.2/src/python/grpcio/support.py000066400000000000000000000114341310511640000201230ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import os import os.path import shutil import sys import tempfile from distutils import errors import commands C_PYTHON_DEV = """ #include int main(int argc, char **argv) { return 0; } """ C_PYTHON_DEV_ERROR_MESSAGE = """ Could not find . This could mean the following: * You're on Ubuntu and haven't run `apt-get install python-dev`. * You're on RHEL/Fedora and haven't run `yum install python-devel` or `dnf install python-devel` (make sure you also have redhat-rpm-config installed) * You're on Mac OS X and the usual Python framework was somehow corrupted (check your environment variables or try re-installing?) * You're on Windows and your Python installation was somehow corrupted (check your environment variables or try re-installing?) """ C_CHECKS = { C_PYTHON_DEV: C_PYTHON_DEV_ERROR_MESSAGE, } def _compile(compiler, source_string): tempdir = tempfile.mkdtemp() cpath = os.path.join(tempdir, 'a.c') with open(cpath, 'w') as cfile: cfile.write(source_string) try: compiler.compile([cpath]) except errors.CompileError as error: return error finally: shutil.rmtree(tempdir) def _expect_compile(compiler, source_string, error_message): if _compile(compiler, source_string) is not None: sys.stderr.write(error_message) raise commands.CommandError( "Diagnostics found a compilation environment issue:\n{}" .format(error_message)) def diagnose_compile_error(build_ext, error): """Attempt to diagnose an error during compilation.""" for c_check, message in C_CHECKS.items(): _expect_compile(build_ext.compiler, c_check, message) python_sources = [ source for source in build_ext.get_source_files() if source.startswith('./src/python') and source.endswith('c') ] for source in python_sources: if not os.path.isfile(source): raise commands.CommandError(( "Diagnostics found a missing Python extension source file:\n{}\n\n" "This is usually because the Cython sources haven't been transpiled " "into C yet and you're building from source.\n" "Try setting the environment variable " "`GRPC_PYTHON_BUILD_WITH_CYTHON=1` when invoking `setup.py` or " "when using `pip`, e.g.:\n\n" "pip install -rrequirements.txt\n" "GRPC_PYTHON_BUILD_WITH_CYTHON=1 pip install .").format(source)) def diagnose_attribute_error(build_ext, error): if any('_needs_stub' in arg for arg in error.args): raise commands.CommandError( "We expect a missing `_needs_stub` attribute from older versions of " "setuptools. Consider upgrading setuptools.") _ERROR_DIAGNOSES = { errors.CompileError: diagnose_compile_error, AttributeError: diagnose_attribute_error } def diagnose_build_ext_error(build_ext, error, formatted): diagnostic = _ERROR_DIAGNOSES.get(type(error)) if diagnostic is None: raise commands.CommandError( "\n\nWe could not diagnose your build failure. Please file an issue at " "http://www.github.com/grpc/grpc with `[Python install]` in the title." "\n\n{}".format(formatted)) else: diagnostic(build_ext, error) grpc-1.3.2/src/python/grpcio_health_checking/000077500000000000000000000000001310511640000212125ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_health_checking/.gitignore000066400000000000000000000001151310511640000231770ustar00rootroot00000000000000*.proto *_pb2.py *_pb2_grpc.py build/ grpcio_health_checking.egg-info/ dist/ grpc-1.3.2/src/python/grpcio_health_checking/MANIFEST.in000066400000000000000000000001321310511640000227440ustar00rootroot00000000000000include grpc_version.py include health_commands.py graft grpc_health global-exclude *.pyc grpc-1.3.2/src/python/grpcio_health_checking/README.rst000066400000000000000000000003271310511640000227030ustar00rootroot00000000000000gRPC Python Health Checking =========================== Reference package for GRPC Python health checking. Dependencies ------------ Depends on the `grpcio` package, available from PyPI via `pip install grpcio`. grpc-1.3.2/src/python/grpcio_health_checking/grpc_health/000077500000000000000000000000001310511640000234725ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_health_checking/grpc_health/__init__.py000066400000000000000000000027701310511640000256110ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_health_checking/grpc_health/v1/000077500000000000000000000000001310511640000240205ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_health_checking/grpc_health/v1/__init__.py000066400000000000000000000027701310511640000261370ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_health_checking/grpc_health/v1/health.py000066400000000000000000000051651310511640000256460ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Reference implementation for health checking in gRPC Python.""" import threading import grpc from grpc_health.v1 import health_pb2 from grpc_health.v1 import health_pb2_grpc class HealthServicer(health_pb2_grpc.HealthServicer): """Servicer handling RPCs for service statuses.""" def __init__(self): self._server_status_lock = threading.Lock() self._server_status = {} def Check(self, request, context): with self._server_status_lock: status = self._server_status.get(request.service) if status is None: context.set_code(grpc.StatusCode.NOT_FOUND) return health_pb2.HealthCheckResponse() else: return health_pb2.HealthCheckResponse(status=status) def set(self, service, status): """Sets the status of a service. Args: service: string, the name of the service. NOTE, '' must be set. status: HealthCheckResponse.status enum value indicating the status of the service """ with self._server_status_lock: self._server_status[service] = status grpc-1.3.2/src/python/grpcio_health_checking/grpc_version.py000066400000000000000000000031651310511640000242710ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!! VERSION='1.3.2' grpc-1.3.2/src/python/grpcio_health_checking/health_commands.py000066400000000000000000000055431310511640000247210ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Provides distutils command classes for the GRPC Python setup process.""" import os import shutil import setuptools ROOT_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__))) HEALTH_PROTO = os.path.join(ROOT_DIR, '../../proto/grpc/health/v1/health.proto') class CopyProtoModules(setuptools.Command): """Command to copy proto modules from grpc/src/proto.""" description = '' user_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): if os.path.isfile(HEALTH_PROTO): shutil.copyfile( HEALTH_PROTO, os.path.join(ROOT_DIR, 'grpc_health/v1/health.proto')) class BuildPackageProtos(setuptools.Command): """Command to generate project *_pb2.py modules from proto files.""" description = 'build grpc protobuf modules' user_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): # due to limitations of the proto generator, we require that only *one* # directory is provided as an 'include' directory. We assume it's the '' key # to `self.distribution.package_dir` (and get a key error if it's not # there). from grpc_tools import command command.build_package_protos(self.distribution.package_dir['']) grpc-1.3.2/src/python/grpcio_health_checking/setup.py000066400000000000000000000054001310511640000227230ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Setup module for the GRPC Python package's optional health checking.""" import os import sys import setuptools # Ensure we're in the proper directory whether or not we're being used by pip. os.chdir(os.path.dirname(os.path.abspath(__file__))) # Break import-style to ensure we can actually find our commands module. import health_commands import grpc_version PACKAGE_DIRECTORIES = { '': '.', } SETUP_REQUIRES = ( 'grpcio-tools>={version}'.format(version=grpc_version.VERSION),) INSTALL_REQUIRES = ('protobuf>=3.2.0', 'grpcio>={version}'.format(version=grpc_version.VERSION),) COMMAND_CLASS = { # Run preprocess from the repository *before* doing any packaging! 'preprocess': health_commands.CopyProtoModules, 'build_package_protos': health_commands.BuildPackageProtos, } setuptools.setup( name='grpcio-health-checking', version=grpc_version.VERSION, description='Standard Health Checking Service for gRPC', author='The gRPC Authors', author_email='grpc-io@googlegroups.com', url='http://www.grpc.io', license='3-clause BSD', package_dir=PACKAGE_DIRECTORIES, packages=setuptools.find_packages('.'), install_requires=INSTALL_REQUIRES, setup_requires=SETUP_REQUIRES, cmdclass=COMMAND_CLASS) grpc-1.3.2/src/python/grpcio_reflection/000077500000000000000000000000001310511640000202445ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_reflection/.gitignore000066400000000000000000000000721310511640000222330ustar00rootroot00000000000000*.proto *_pb2.py build/ grpcio_reflection.egg-info/ dist/ grpc-1.3.2/src/python/grpcio_reflection/MANIFEST.in000066400000000000000000000001421310511640000217770ustar00rootroot00000000000000include grpc_version.py include reflection_commands.py graft grpc_reflection global-exclude *.pyc grpc-1.3.2/src/python/grpcio_reflection/grpc_reflection/000077500000000000000000000000001310511640000234115ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_reflection/grpc_reflection/__init__.py000066400000000000000000000027701310511640000255300ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_reflection/grpc_reflection/v1alpha/000077500000000000000000000000001310511640000247455ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_reflection/grpc_reflection/v1alpha/__init__.py000066400000000000000000000027701310511640000270640ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_reflection/grpc_reflection/v1alpha/reflection.py000066400000000000000000000151011310511640000274470ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Reference implementation for reflection in gRPC Python.""" import threading import grpc from google.protobuf import descriptor_pb2 from google.protobuf import descriptor_pool from grpc_reflection.v1alpha import reflection_pb2 from grpc_reflection.v1alpha import reflection_pb2_grpc _POOL = descriptor_pool.Default() def _not_found_error(): return reflection_pb2.ServerReflectionResponse( error_response=reflection_pb2.ErrorResponse( error_code=grpc.StatusCode.NOT_FOUND.value[0], error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(),)) def _file_descriptor_response(descriptor): proto = descriptor_pb2.FileDescriptorProto() descriptor.CopyToProto(proto) serialized_proto = proto.SerializeToString() return reflection_pb2.ServerReflectionResponse( file_descriptor_response=reflection_pb2.FileDescriptorResponse( file_descriptor_proto=(serialized_proto,)),) class ReflectionServicer(reflection_pb2.ServerReflectionServicer): """Servicer handling RPCs for service statuses.""" def __init__(self, service_names, pool=None): """Constructor. Args: service_names: Iterable of fully-qualified service names available. """ self._service_names = tuple(sorted(service_names)) self._pool = _POOL if pool is None else pool def _file_by_filename(self, filename): try: descriptor = self._pool.FindFileByName(filename) except KeyError: return _not_found_error() else: return _file_descriptor_response(descriptor) def _file_containing_symbol(self, fully_qualified_name): try: descriptor = self._pool.FindFileContainingSymbol( fully_qualified_name) except KeyError: return _not_found_error() else: return _file_descriptor_response(descriptor) def _file_containing_extension(self, containing_type, extension_number): try: message_descriptor = self._pool.FindMessageTypeByName(containing_type) extension_descriptor = self._pool.FindExtensionByNumber( message_descriptor, extension_number) descriptor = self._pool.FindFileContainingSymbol( extension_descriptor.full_name) except KeyError: return _not_found_error() else: return _file_descriptor_response(descriptor) def _all_extension_numbers_of_type(self, containing_type): try: message_descriptor = self._pool.FindMessageTypeByName(containing_type) extension_numbers = tuple(sorted( extension.number for extension in self._pool.FindAllExtensions(message_descriptor))) except KeyError: return _not_found_error() else: return reflection_pb2.ServerReflectionResponse( all_extension_numbers_response=reflection_pb2. ExtensionNumberResponse( base_type_name=message_descriptor.full_name, extension_number=extension_numbers)) def _list_services(self): return reflection_pb2.ServerReflectionResponse( list_services_response=reflection_pb2.ListServiceResponse(service=[ reflection_pb2.ServiceResponse(name=service_name) for service_name in self._service_names ])) def ServerReflectionInfo(self, request_iterator, context): for request in request_iterator: if request.HasField('file_by_filename'): yield self._file_by_filename(request.file_by_filename) elif request.HasField('file_containing_symbol'): yield self._file_containing_symbol( request.file_containing_symbol) elif request.HasField('file_containing_extension'): yield self._file_containing_extension( request.file_containing_extension.containing_type, request.file_containing_extension.extension_number) elif request.HasField('all_extension_numbers_of_type'): yield self._all_extension_numbers_of_type( request.all_extension_numbers_of_type) elif request.HasField('list_services'): yield self._list_services() else: yield reflection_pb2.ServerReflectionResponse( error_response=reflection_pb2.ErrorResponse( error_code=grpc.StatusCode.INVALID_ARGUMENT.value[0], error_message=grpc.StatusCode.INVALID_ARGUMENT.value[1] .encode(),)) def enable_server_reflection(service_names, server, pool=None): """Enables server reflection on a server. Args: service_names: Iterable of fully-qualified service names available. server: grpc.Server to which reflection service will be added. pool: DescriptorPool object to use (descriptor_pool.Default() if None). """ reflection_pb2_grpc.add_ServerReflectionServicer_to_server( ReflectionServicer(service_names), server, pool) grpc-1.3.2/src/python/grpcio_reflection/grpc_version.py000066400000000000000000000031601310511640000233160ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!! VERSION='1.3.2' grpc-1.3.2/src/python/grpcio_reflection/reflection_commands.py000066400000000000000000000056371310511640000246440ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Provides distutils command classes for the GRPC Python setup process.""" import os import shutil import setuptools ROOT_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__))) HEALTH_PROTO = os.path.join( ROOT_DIR, '../../proto/grpc/reflection/v1alpha/reflection.proto') class CopyProtoModules(setuptools.Command): """Command to copy proto modules from grpc/src/proto.""" description = '' user_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): if os.path.isfile(HEALTH_PROTO): shutil.copyfile( HEALTH_PROTO, os.path.join(ROOT_DIR, 'grpc_reflection/v1alpha/reflection.proto')) class BuildPackageProtos(setuptools.Command): """Command to generate project *_pb2.py modules from proto files.""" description = 'build grpc protobuf modules' user_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): # due to limitations of the proto generator, we require that only *one* # directory is provided as an 'include' directory. We assume it's the '' key # to `self.distribution.package_dir` (and get a key error if it's not # there). from grpc_tools import command command.build_package_protos(self.distribution.package_dir['']) grpc-1.3.2/src/python/grpcio_reflection/setup.py000066400000000000000000000054061310511640000217630ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Setup module for the GRPC Python package's optional reflection.""" import os import sys import setuptools # Ensure we're in the proper directory whether or not we're being used by pip. os.chdir(os.path.dirname(os.path.abspath(__file__))) # Break import-style to ensure we can actually find our commands module. import reflection_commands import grpc_version PACKAGE_DIRECTORIES = { '': '.', } SETUP_REQUIRES = ( 'grpcio-tools>={version}'.format(version=grpc_version.VERSION),) INSTALL_REQUIRES = ('protobuf>=3.2.0', 'grpcio>={version}'.format(version=grpc_version.VERSION),) COMMAND_CLASS = { # Run preprocess from the repository *before* doing any packaging! 'preprocess': reflection_commands.CopyProtoModules, 'build_package_protos': reflection_commands.BuildPackageProtos, } setuptools.setup( name='grpcio-reflection', version=grpc_version.VERSION, license='3-clause BSD', description='Standard Protobuf Reflection Service for gRPC', author='The gRPC Authors', author_email='grpc-io@googlegroups.com', url='http://www.grpc.io', package_dir=PACKAGE_DIRECTORIES, packages=setuptools.find_packages('.'), install_requires=INSTALL_REQUIRES, setup_requires=SETUP_REQUIRES, cmdclass=COMMAND_CLASS) grpc-1.3.2/src/python/grpcio_tests/000077500000000000000000000000001310511640000172545ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/.gitignore000066400000000000000000000000571310511640000212460ustar00rootroot00000000000000proto/ src/ *_pb2.py *_pb2_grpc.py *.egg-info/ grpc-1.3.2/src/python/grpcio_tests/commands.py000066400000000000000000000166201310511640000214340ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Provides distutils command classes for the gRPC Python setup process.""" from distutils import errors as _errors import glob import os import os.path import platform import re import shutil import subprocess import sys import traceback import setuptools from setuptools.command import build_ext from setuptools.command import build_py from setuptools.command import easy_install from setuptools.command import install from setuptools.command import test PYTHON_STEM = os.path.dirname(os.path.abspath(__file__)) GRPC_STEM = os.path.abspath(PYTHON_STEM + '../../../../') GRPC_PROTO_STEM = os.path.join(GRPC_STEM, 'src', 'proto') PROTO_STEM = os.path.join(PYTHON_STEM, 'src', 'proto') PYTHON_PROTO_TOP_LEVEL = os.path.join(PYTHON_STEM, 'src') class CommandError(object): pass class GatherProto(setuptools.Command): description = 'gather proto dependencies' user_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): # TODO(atash) ensure that we're running from the repository directory when # this command is used try: shutil.rmtree(PROTO_STEM) except Exception as error: # We don't care if this command fails pass shutil.copytree(GRPC_PROTO_STEM, PROTO_STEM) for root, _, _ in os.walk(PYTHON_PROTO_TOP_LEVEL): path = os.path.join(root, '__init__.py') open(path, 'a').close() class BuildProtoModules(setuptools.Command): """Command to generate project *_pb2.py modules from proto files.""" description = 'build protobuf modules' user_options = [ ('include=', None, 'path patterns to include in protobuf generation'), ('exclude=', None, 'path patterns to exclude from protobuf generation') ] def initialize_options(self): self.exclude = None self.include = r'.*\.proto$' def finalize_options(self): pass def run(self): import grpc_tools.protoc as protoc include_regex = re.compile(self.include) exclude_regex = re.compile(self.exclude) if self.exclude else None paths = [] for walk_root, directories, filenames in os.walk(PROTO_STEM): for filename in filenames: path = os.path.join(walk_root, filename) if include_regex.match(path) and not ( exclude_regex and exclude_regex.match(path)): paths.append(path) # TODO(kpayson): It would be nice to do this in a batch command, # but we currently have name conflicts in src/proto for path in paths: command = [ 'grpc_tools.protoc', '-I {}'.format(PROTO_STEM), '--python_out={}'.format(PROTO_STEM), '--grpc_python_out={}'.format(PROTO_STEM), ] + [path] if protoc.main(command) != 0: sys.stderr.write( 'warning: Command:\n{}\nFailed'.format(command)) # Generated proto directories dont include __init__.py, but # these are needed for python package resolution for walk_root, _, _ in os.walk(PROTO_STEM): path = os.path.join(walk_root, '__init__.py') open(path, 'a').close() class BuildPy(build_py.build_py): """Custom project build command.""" def run(self): try: self.run_command('build_package_protos') except CommandError as error: sys.stderr.write('warning: %s\n' % error.message) build_py.build_py.run(self) class TestLite(setuptools.Command): """Command to run tests without fetching or building anything.""" description = 'run tests without fetching or building anything.' user_options = [] def initialize_options(self): pass def finalize_options(self): # distutils requires this override. pass def run(self): self._add_eggs_to_path() import tests loader = tests.Loader() loader.loadTestsFromNames(['tests']) runner = tests.Runner() result = runner.run(loader.suite) if not result.wasSuccessful(): sys.exit('Test failure') def _add_eggs_to_path(self): """Fetch install and test requirements""" self.distribution.fetch_build_eggs(self.distribution.install_requires) self.distribution.fetch_build_eggs(self.distribution.tests_require) class RunInterop(test.test): description = 'run interop test client/server' user_options = [('args=', 'a', 'pass-thru arguments for the client/server'), ('client', 'c', 'flag indicating to run the client'), ('server', 's', 'flag indicating to run the server')] def initialize_options(self): self.args = '' self.client = False self.server = False def finalize_options(self): if self.client and self.server: raise _errors.DistutilsOptionError( 'you may only specify one of client or server') def run(self): if self.distribution.install_requires: self.distribution.fetch_build_eggs( self.distribution.install_requires) if self.distribution.tests_require: self.distribution.fetch_build_eggs(self.distribution.tests_require) if self.client: self.run_client() elif self.server: self.run_server() def run_server(self): # We import here to ensure that our setuptools parent has had a chance to # edit the Python system path. from tests.interop import server sys.argv[1:] = self.args.split() server.serve() def run_client(self): # We import here to ensure that our setuptools parent has had a chance to # edit the Python system path. from tests.interop import client sys.argv[1:] = self.args.split() client.test_interoperability() grpc-1.3.2/src/python/grpcio_tests/grpc_version.py000066400000000000000000000031531310511640000223300ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!! VERSION='1.3.2' grpc-1.3.2/src/python/grpcio_tests/setup.py000066400000000000000000000073031310511640000207710ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """A setup module for the gRPC Python package.""" import os import os.path import sys import setuptools import grpc_tools.command PY3 = sys.version_info.major == 3 # Ensure we're in the proper directory whether or not we're being used by pip. os.chdir(os.path.dirname(os.path.abspath(__file__))) # Break import-style to ensure we can actually find our in-repo dependencies. import commands import grpc_version LICENSE = '3-clause BSD' PACKAGE_DIRECTORIES = { '': '.', } INSTALL_REQUIRES = ( 'coverage>=4.0', 'enum34>=1.0.4', 'futures>=2.2.0', 'grpcio>={version}'.format(version=grpc_version.VERSION), 'grpcio-tools>={version}'.format(version=grpc_version.VERSION), 'grpcio-health-checking>={version}'.format(version=grpc_version.VERSION), 'oauth2client>=1.4.7', 'protobuf>=3.2.0', 'six>=1.10',) COMMAND_CLASS = { # Run `preprocess` *before* doing any packaging! 'preprocess': commands.GatherProto, 'build_package_protos': grpc_tools.command.BuildPackageProtos, 'build_py': commands.BuildPy, 'run_interop': commands.RunInterop, 'test_lite': commands.TestLite } PACKAGE_DATA = { 'tests.interop': [ 'credentials/ca.pem', 'credentials/server1.key', 'credentials/server1.pem', ], 'tests.protoc_plugin.protos.invocation_testing': [ 'same.proto', ], 'tests.protoc_plugin.protos.invocation_testing.split_messages': [ 'messages.proto', ], 'tests.protoc_plugin.protos.invocation_testing.split_services': [ 'services.proto', ], 'tests.unit': [ 'credentials/ca.pem', 'credentials/server1.key', 'credentials/server1.pem', ], 'tests': ['tests.json'], } TEST_SUITE = 'tests' TEST_LOADER = 'tests:Loader' TEST_RUNNER = 'tests:Runner' TESTS_REQUIRE = INSTALL_REQUIRES PACKAGES = setuptools.find_packages('.') setuptools.setup( name='grpcio-tests', version=grpc_version.VERSION, license=LICENSE, packages=list(PACKAGES), package_dir=PACKAGE_DIRECTORIES, package_data=PACKAGE_DATA, install_requires=INSTALL_REQUIRES, cmdclass=COMMAND_CLASS, tests_require=TESTS_REQUIRE, test_suite=TEST_SUITE, test_loader=TEST_LOADER, test_runner=TEST_RUNNER,) grpc-1.3.2/src/python/grpcio_tests/tests/000077500000000000000000000000001310511640000204165ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/__init__.py000066400000000000000000000032061310511640000225300ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from __future__ import absolute_import from tests import _loader from tests import _runner Loader = _loader.Loader Runner = _runner.Runner grpc-1.3.2/src/python/grpcio_tests/tests/_loader.py000066400000000000000000000110271310511640000223760ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from __future__ import absolute_import import importlib import pkgutil import re import unittest import coverage TEST_MODULE_REGEX = r'^.*_test$' class Loader(object): """Test loader for setuptools test suite support. Attributes: suite (unittest.TestSuite): All tests collected by the loader. loader (unittest.TestLoader): Standard Python unittest loader to be ran per module discovered. module_matcher (re.RegexObject): A regular expression object to match against module names and determine whether or not the discovered module contributes to the test suite. """ def __init__(self): self.suite = unittest.TestSuite() self.loader = unittest.TestLoader() self.module_matcher = re.compile(TEST_MODULE_REGEX) def loadTestsFromNames(self, names, module=None): """Function mirroring TestLoader::loadTestsFromNames, as expected by setuptools.setup argument `test_loader`.""" # ensure that we capture decorators and definitions (else our coverage # measure unnecessarily suffers) coverage_context = coverage.Coverage(data_suffix=True) coverage_context.start() modules = [importlib.import_module(name) for name in names] for module in modules: self.visit_module(module) for module in modules: try: package_paths = module.__path__ except: continue self.walk_packages(package_paths) coverage_context.stop() coverage_context.save() return self.suite def walk_packages(self, package_paths): """Walks over the packages, dispatching `visit_module` calls. Args: package_paths (list): A list of paths over which to walk through modules along. """ for importer, module_name, is_package in ( pkgutil.walk_packages(package_paths)): module = importer.find_module(module_name).load_module(module_name) self.visit_module(module) def visit_module(self, module): """Visits the module, adding discovered tests to the test suite. Args: module (module): Module to match against self.module_matcher; if matched it has its tests loaded via self.loader into self.suite. """ if self.module_matcher.match(module.__name__): module_suite = self.loader.loadTestsFromModule(module) self.suite.addTest(module_suite) def iterate_suite_cases(suite): """Generator over all unittest.TestCases in a unittest.TestSuite. Args: suite (unittest.TestSuite): Suite to iterate over in the generator. Returns: generator: A generator over all unittest.TestCases in `suite`. """ for item in suite: if isinstance(item, unittest.TestSuite): for child_item in iterate_suite_cases(item): yield child_item elif isinstance(item, unittest.TestCase): yield item else: raise ValueError( 'unexpected suite item of type {}'.format(type(item))) grpc-1.3.2/src/python/grpcio_tests/tests/_result.py000066400000000000000000000427461310511640000224620ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from __future__ import absolute_import import collections import itertools import traceback import unittest from xml.etree import ElementTree import coverage from six import moves from tests import _loader class CaseResult( collections.namedtuple('CaseResult', [ 'id', 'name', 'kind', 'stdout', 'stderr', 'skip_reason', 'traceback' ])): """A serializable result of a single test case. Attributes: id (object): Any serializable object used to denote the identity of this test case. name (str or None): A human-readable name of the test case. kind (CaseResult.Kind): The kind of test result. stdout (object or None): Output on stdout, or None if nothing was captured. stderr (object or None): Output on stderr, or None if nothing was captured. skip_reason (object or None): The reason the test was skipped. Must be something if self.kind is CaseResult.Kind.SKIP, else None. traceback (object or None): The traceback of the test. Must be something if self.kind is CaseResult.Kind.{ERROR, FAILURE, EXPECTED_FAILURE}, else None. """ class Kind: UNTESTED = 'untested' RUNNING = 'running' ERROR = 'error' FAILURE = 'failure' SUCCESS = 'success' SKIP = 'skip' EXPECTED_FAILURE = 'expected failure' UNEXPECTED_SUCCESS = 'unexpected success' def __new__(cls, id=None, name=None, kind=None, stdout=None, stderr=None, skip_reason=None, traceback=None): """Helper keyword constructor for the namedtuple. See this class' attributes for information on the arguments.""" assert id is not None assert name is None or isinstance(name, str) if kind is CaseResult.Kind.UNTESTED: pass elif kind is CaseResult.Kind.RUNNING: pass elif kind is CaseResult.Kind.ERROR: assert traceback is not None elif kind is CaseResult.Kind.FAILURE: assert traceback is not None elif kind is CaseResult.Kind.SUCCESS: pass elif kind is CaseResult.Kind.SKIP: assert skip_reason is not None elif kind is CaseResult.Kind.EXPECTED_FAILURE: assert traceback is not None elif kind is CaseResult.Kind.UNEXPECTED_SUCCESS: pass else: assert False return super(cls, CaseResult).__new__(cls, id, name, kind, stdout, stderr, skip_reason, traceback) def updated(self, name=None, kind=None, stdout=None, stderr=None, skip_reason=None, traceback=None): """Get a new validated CaseResult with the fields updated. See this class' attributes for information on the arguments.""" name = self.name if name is None else name kind = self.kind if kind is None else kind stdout = self.stdout if stdout is None else stdout stderr = self.stderr if stderr is None else stderr skip_reason = self.skip_reason if skip_reason is None else skip_reason traceback = self.traceback if traceback is None else traceback return CaseResult( id=self.id, name=name, kind=kind, stdout=stdout, stderr=stderr, skip_reason=skip_reason, traceback=traceback) class AugmentedResult(unittest.TestResult): """unittest.Result that keeps track of additional information. Uses CaseResult objects to store test-case results, providing additional information beyond that of the standard Python unittest library, such as standard output. Attributes: id_map (callable): A unary callable mapping unittest.TestCase objects to unique identifiers. cases (dict): A dictionary mapping from the identifiers returned by id_map to CaseResult objects corresponding to those IDs. """ def __init__(self, id_map): """Initialize the object with an identifier mapping. Arguments: id_map (callable): Corresponds to the attribute `id_map`.""" super(AugmentedResult, self).__init__() self.id_map = id_map self.cases = None def startTestRun(self): """See unittest.TestResult.startTestRun.""" super(AugmentedResult, self).startTestRun() self.cases = dict() def stopTestRun(self): """See unittest.TestResult.stopTestRun.""" super(AugmentedResult, self).stopTestRun() def startTest(self, test): """See unittest.TestResult.startTest.""" super(AugmentedResult, self).startTest(test) case_id = self.id_map(test) self.cases[case_id] = CaseResult( id=case_id, name=test.id(), kind=CaseResult.Kind.RUNNING) def addError(self, test, error): """See unittest.TestResult.addError.""" super(AugmentedResult, self).addError(test, error) case_id = self.id_map(test) self.cases[case_id] = self.cases[case_id].updated( kind=CaseResult.Kind.ERROR, traceback=error) def addFailure(self, test, error): """See unittest.TestResult.addFailure.""" super(AugmentedResult, self).addFailure(test, error) case_id = self.id_map(test) self.cases[case_id] = self.cases[case_id].updated( kind=CaseResult.Kind.FAILURE, traceback=error) def addSuccess(self, test): """See unittest.TestResult.addSuccess.""" super(AugmentedResult, self).addSuccess(test) case_id = self.id_map(test) self.cases[case_id] = self.cases[case_id].updated( kind=CaseResult.Kind.SUCCESS) def addSkip(self, test, reason): """See unittest.TestResult.addSkip.""" super(AugmentedResult, self).addSkip(test, reason) case_id = self.id_map(test) self.cases[case_id] = self.cases[case_id].updated( kind=CaseResult.Kind.SKIP, skip_reason=reason) def addExpectedFailure(self, test, error): """See unittest.TestResult.addExpectedFailure.""" super(AugmentedResult, self).addExpectedFailure(test, error) case_id = self.id_map(test) self.cases[case_id] = self.cases[case_id].updated( kind=CaseResult.Kind.EXPECTED_FAILURE, traceback=error) def addUnexpectedSuccess(self, test): """See unittest.TestResult.addUnexpectedSuccess.""" super(AugmentedResult, self).addUnexpectedSuccess(test) case_id = self.id_map(test) self.cases[case_id] = self.cases[case_id].updated( kind=CaseResult.Kind.UNEXPECTED_SUCCESS) def set_output(self, test, stdout, stderr): """Set the output attributes for the CaseResult corresponding to a test. Args: test (unittest.TestCase): The TestCase to set the outputs of. stdout (str): Output from stdout to assign to self.id_map(test). stderr (str): Output from stderr to assign to self.id_map(test). """ case_id = self.id_map(test) self.cases[case_id] = self.cases[case_id].updated( stdout=stdout.decode(), stderr=stderr.decode()) def augmented_results(self, filter): """Convenience method to retrieve filtered case results. Args: filter (callable): A unary predicate to filter over CaseResult objects. """ return (self.cases[case_id] for case_id in self.cases if filter(self.cases[case_id])) class CoverageResult(AugmentedResult): """Extension to AugmentedResult adding coverage.py support per test.\ Attributes: coverage_context (coverage.Coverage): coverage.py management object. """ def __init__(self, id_map): """See AugmentedResult.__init__.""" super(CoverageResult, self).__init__(id_map=id_map) self.coverage_context = None def startTest(self, test): """See unittest.TestResult.startTest. Additionally initializes and begins code coverage tracking.""" super(CoverageResult, self).startTest(test) self.coverage_context = coverage.Coverage(data_suffix=True) self.coverage_context.start() def stopTest(self, test): """See unittest.TestResult.stopTest. Additionally stops and deinitializes code coverage tracking.""" super(CoverageResult, self).stopTest(test) self.coverage_context.stop() self.coverage_context.save() self.coverage_context = None def stopTestRun(self): """See unittest.TestResult.stopTestRun.""" super(CoverageResult, self).stopTestRun() # TODO(atash): Dig deeper into why the following line fails to properly # combine coverage data from the Cython plugin. #coverage.Coverage().combine() class _Colors: """Namespaced constants for terminal color magic numbers.""" HEADER = '\033[95m' INFO = '\033[94m' OK = '\033[92m' WARN = '\033[93m' FAIL = '\033[91m' BOLD = '\033[1m' UNDERLINE = '\033[4m' END = '\033[0m' class TerminalResult(CoverageResult): """Extension to CoverageResult adding basic terminal reporting.""" def __init__(self, out, id_map): """Initialize the result object. Args: out (file-like): Output file to which terminal-colored live results will be written. id_map (callable): See AugmentedResult.__init__. """ super(TerminalResult, self).__init__(id_map=id_map) self.out = out def startTestRun(self): """See unittest.TestResult.startTestRun.""" super(TerminalResult, self).startTestRun() self.out.write(_Colors.HEADER + 'Testing gRPC Python...\n' + _Colors.END) def stopTestRun(self): """See unittest.TestResult.stopTestRun.""" super(TerminalResult, self).stopTestRun() self.out.write(summary(self)) self.out.flush() def addError(self, test, error): """See unittest.TestResult.addError.""" super(TerminalResult, self).addError(test, error) self.out.write(_Colors.FAIL + 'ERROR {}\n'.format(test.id()) + _Colors.END) self.out.flush() def addFailure(self, test, error): """See unittest.TestResult.addFailure.""" super(TerminalResult, self).addFailure(test, error) self.out.write(_Colors.FAIL + 'FAILURE {}\n'.format(test.id()) + _Colors.END) self.out.flush() def addSuccess(self, test): """See unittest.TestResult.addSuccess.""" super(TerminalResult, self).addSuccess(test) self.out.write(_Colors.OK + 'SUCCESS {}\n'.format(test.id()) + _Colors.END) self.out.flush() def addSkip(self, test, reason): """See unittest.TestResult.addSkip.""" super(TerminalResult, self).addSkip(test, reason) self.out.write(_Colors.INFO + 'SKIP {}\n'.format(test.id()) + _Colors.END) self.out.flush() def addExpectedFailure(self, test, error): """See unittest.TestResult.addExpectedFailure.""" super(TerminalResult, self).addExpectedFailure(test, error) self.out.write(_Colors.INFO + 'FAILURE_OK {}\n'.format(test.id()) + _Colors.END) self.out.flush() def addUnexpectedSuccess(self, test): """See unittest.TestResult.addUnexpectedSuccess.""" super(TerminalResult, self).addUnexpectedSuccess(test) self.out.write(_Colors.INFO + 'UNEXPECTED_OK {}\n'.format(test.id()) + _Colors.END) self.out.flush() def _traceback_string(type, value, trace): """Generate a descriptive string of a Python exception traceback. Args: type (class): The type of the exception. value (Exception): The value of the exception. trace (traceback): Traceback of the exception. Returns: str: Formatted exception descriptive string. """ buffer = moves.cStringIO() traceback.print_exception(type, value, trace, file=buffer) return buffer.getvalue() def summary(result): """A summary string of a result object. Args: result (AugmentedResult): The result object to get the summary of. Returns: str: The summary string. """ assert isinstance(result, AugmentedResult) untested = list( result.augmented_results( lambda case_result: case_result.kind is CaseResult.Kind.UNTESTED)) running = list( result.augmented_results( lambda case_result: case_result.kind is CaseResult.Kind.RUNNING)) failures = list( result.augmented_results( lambda case_result: case_result.kind is CaseResult.Kind.FAILURE)) errors = list( result.augmented_results( lambda case_result: case_result.kind is CaseResult.Kind.ERROR)) successes = list( result.augmented_results( lambda case_result: case_result.kind is CaseResult.Kind.SUCCESS)) skips = list( result.augmented_results( lambda case_result: case_result.kind is CaseResult.Kind.SKIP)) expected_failures = list( result.augmented_results( lambda case_result: case_result.kind is CaseResult.Kind.EXPECTED_FAILURE )) unexpected_successes = list( result.augmented_results( lambda case_result: case_result.kind is CaseResult.Kind.UNEXPECTED_SUCCESS )) running_names = [case.name for case in running] finished_count = (len(failures) + len(errors) + len(successes) + len(expected_failures) + len(unexpected_successes)) statistics = ('{finished} tests finished:\n' '\t{successful} successful\n' '\t{unsuccessful} unsuccessful\n' '\t{skipped} skipped\n' '\t{expected_fail} expected failures\n' '\t{unexpected_successful} unexpected successes\n' 'Interrupted Tests:\n' '\t{interrupted}\n'.format( finished=finished_count, successful=len(successes), unsuccessful=(len(failures) + len(errors)), skipped=len(skips), expected_fail=len(expected_failures), unexpected_successful=len(unexpected_successes), interrupted=str(running_names))) tracebacks = '\n\n'.join( [(_Colors.FAIL + '{test_name}' + _Colors.END + '\n' + _Colors.BOLD + 'traceback:' + _Colors.END + '\n' + '{traceback}\n' + _Colors.BOLD + 'stdout:' + _Colors.END + '\n' + '{stdout}\n' + _Colors.BOLD + 'stderr:' + _Colors.END + '\n' + '{stderr}\n').format( test_name=result.name, traceback=_traceback_string(*result.traceback), stdout=result.stdout, stderr=result.stderr) for result in itertools.chain(failures, errors)]) notes = 'Unexpected successes: {}\n'.format( [result.name for result in unexpected_successes]) return statistics + '\nErrors/Failures: \n' + tracebacks + '\n' + notes def jenkins_junit_xml(result): """An XML tree object that when written is recognizable by Jenkins. Args: result (AugmentedResult): The result object to get the junit xml output of. Returns: ElementTree.ElementTree: The XML tree. """ assert isinstance(result, AugmentedResult) root = ElementTree.Element('testsuites') suite = ElementTree.SubElement(root, 'testsuite', { 'name': 'Python gRPC tests', }) for case in result.cases.values(): if case.kind is CaseResult.Kind.SUCCESS: ElementTree.SubElement(suite, 'testcase', { 'name': case.name, }) elif case.kind in (CaseResult.Kind.ERROR, CaseResult.Kind.FAILURE): case_xml = ElementTree.SubElement(suite, 'testcase', { 'name': case.name, }) error_xml = ElementTree.SubElement(case_xml, 'error', {}) error_xml.text = ''.format(case.stderr, case.traceback) return ElementTree.ElementTree(element=root) grpc-1.3.2/src/python/grpcio_tests/tests/_runner.py000066400000000000000000000212351310511640000224430ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from __future__ import absolute_import import collections import multiprocessing import os import select import signal import sys import tempfile import threading import time import unittest import uuid import six from six import moves from tests import _loader from tests import _result class CaptureFile(object): """A context-managed file to redirect output to a byte array. Use by invoking `start` (`__enter__`) and at some point invoking `stop` (`__exit__`). At any point after the initial call to `start` call `output` to get the current redirected output. Note that we don't currently use file locking, so calling `output` between calls to `start` and `stop` may muddle the result (you should only be doing this during a Python-handled interrupt as a last ditch effort to provide output to the user). Attributes: _redirected_fd (int): File descriptor of file to redirect writes from. _saved_fd (int): A copy of the original value of the redirected file descriptor. _into_file (TemporaryFile or None): File to which writes are redirected. Only non-None when self is started. """ def __init__(self, fd): self._redirected_fd = fd self._saved_fd = os.dup(self._redirected_fd) self._into_file = None def output(self): """Get all output from the redirected-to file if it exists.""" if self._into_file: self._into_file.seek(0) return bytes(self._into_file.read()) else: return bytes() def start(self): """Start redirection of writes to the file descriptor.""" self._into_file = tempfile.TemporaryFile() os.dup2(self._into_file.fileno(), self._redirected_fd) def stop(self): """Stop redirection of writes to the file descriptor.""" # n.b. this dup2 call auto-closes self._redirected_fd os.dup2(self._saved_fd, self._redirected_fd) def write_bypass(self, value): """Bypass the redirection and write directly to the original file. Arguments: value (str): What to write to the original file. """ if six.PY3 and not isinstance(value, six.binary_type): value = bytes(value, 'ascii') if self._saved_fd is None: os.write(self._redirect_fd, value) else: os.write(self._saved_fd, value) def __enter__(self): self.start() return self def __exit__(self, type, value, traceback): self.stop() def close(self): """Close any resources used by self not closed by stop().""" os.close(self._saved_fd) class AugmentedCase(collections.namedtuple('AugmentedCase', ['case', 'id'])): """A test case with a guaranteed unique externally specified identifier. Attributes: case (unittest.TestCase): TestCase we're decorating with an additional identifier. id (object): Any identifier that may be considered 'unique' for testing purposes. """ def __new__(cls, case, id=None): if id is None: id = uuid.uuid4() return super(cls, AugmentedCase).__new__(cls, case, id) class Runner(object): def run(self, suite): """See setuptools' test_runner setup argument for information.""" # only run test cases with id starting with given prefix testcase_filter = os.getenv('GRPC_PYTHON_TESTRUNNER_FILTER') filtered_cases = [] for case in _loader.iterate_suite_cases(suite): if not testcase_filter or case.id().startswith(testcase_filter): filtered_cases.append(case) # Ensure that every test case has no collision with any other test case in # the augmented results. augmented_cases = [ AugmentedCase(case, uuid.uuid4()) for case in filtered_cases ] case_id_by_case = dict((augmented_case.case, augmented_case.id) for augmented_case in augmented_cases) result_out = moves.cStringIO() result = _result.TerminalResult( result_out, id_map=lambda case: case_id_by_case[case]) stdout_pipe = CaptureFile(sys.stdout.fileno()) stderr_pipe = CaptureFile(sys.stderr.fileno()) kill_flag = [False] def sigint_handler(signal_number, frame): if signal_number == signal.SIGINT: kill_flag[0] = True # Python 2.7 not having 'local'... :-( signal.signal(signal_number, signal.SIG_DFL) def fault_handler(signal_number, frame): stdout_pipe.write_bypass( 'Received fault signal {}\nstdout:\n{}\n\nstderr:{}\n'.format( signal_number, stdout_pipe.output(), stderr_pipe.output())) os._exit(1) def check_kill_self(): if kill_flag[0]: stdout_pipe.write_bypass('Stopping tests short...') result.stopTestRun() stdout_pipe.write_bypass(result_out.getvalue()) stdout_pipe.write_bypass('\ninterrupted stdout:\n{}\n'.format( stdout_pipe.output().decode())) stderr_pipe.write_bypass('\ninterrupted stderr:\n{}\n'.format( stderr_pipe.output().decode())) os._exit(1) def try_set_handler(name, handler): try: signal.signal(getattr(signal, name), handler) except AttributeError: pass try_set_handler('SIGINT', sigint_handler) try_set_handler('SIGSEGV', fault_handler) try_set_handler('SIGBUS', fault_handler) try_set_handler('SIGABRT', fault_handler) try_set_handler('SIGFPE', fault_handler) try_set_handler('SIGILL', fault_handler) # Sometimes output will lag after a test has successfully finished; we # ignore such writes to our pipes. try_set_handler('SIGPIPE', signal.SIG_IGN) # Run the tests result.startTestRun() for augmented_case in augmented_cases: sys.stdout.write( 'Running {}\n'.format(augmented_case.case.id())) sys.stdout.flush() case_thread = threading.Thread( target=augmented_case.case.run, args=(result,)) try: with stdout_pipe, stderr_pipe: case_thread.start() while case_thread.is_alive(): check_kill_self() time.sleep(0) case_thread.join() except: # re-raise the exception after forcing the with-block to end raise result.set_output(augmented_case.case, stdout_pipe.output(), stderr_pipe.output()) sys.stdout.write(result_out.getvalue()) sys.stdout.flush() result_out.truncate(0) check_kill_self() result.stopTestRun() stdout_pipe.close() stderr_pipe.close() # Report results sys.stdout.write(result_out.getvalue()) sys.stdout.flush() signal.signal(signal.SIGINT, signal.SIG_DFL) with open('report.xml', 'wb') as report_xml_file: _result.jenkins_junit_xml(result).write(report_xml_file) return result grpc-1.3.2/src/python/grpcio_tests/tests/health_check/000077500000000000000000000000001310511640000230205ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/health_check/__init__.py000066400000000000000000000027701310511640000251370ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py000066400000000000000000000100171310511640000277360ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Tests of grpc_health.v1.health.""" import unittest import grpc from grpc.framework.foundation import logging_pool from grpc_health.v1 import health from grpc_health.v1 import health_pb2 from grpc_health.v1 import health_pb2_grpc from tests.unit.framework.common import test_constants class HealthServicerTest(unittest.TestCase): def setUp(self): servicer = health.HealthServicer() servicer.set('', health_pb2.HealthCheckResponse.SERVING) servicer.set('grpc.test.TestServiceServing', health_pb2.HealthCheckResponse.SERVING) servicer.set('grpc.test.TestServiceUnknown', health_pb2.HealthCheckResponse.UNKNOWN) servicer.set('grpc.test.TestServiceNotServing', health_pb2.HealthCheckResponse.NOT_SERVING) server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) self._server = grpc.server(server_pool) port = self._server.add_insecure_port('[::]:0') health_pb2_grpc.add_HealthServicer_to_server(servicer, self._server) self._server.start() channel = grpc.insecure_channel('localhost:%d' % port) self._stub = health_pb2_grpc.HealthStub(channel) def test_empty_service(self): request = health_pb2.HealthCheckRequest() resp = self._stub.Check(request) self.assertEqual(health_pb2.HealthCheckResponse.SERVING, resp.status) def test_serving_service(self): request = health_pb2.HealthCheckRequest( service='grpc.test.TestServiceServing') resp = self._stub.Check(request) self.assertEqual(health_pb2.HealthCheckResponse.SERVING, resp.status) def test_unknown_serivce(self): request = health_pb2.HealthCheckRequest( service='grpc.test.TestServiceUnknown') resp = self._stub.Check(request) self.assertEqual(health_pb2.HealthCheckResponse.UNKNOWN, resp.status) def test_not_serving_service(self): request = health_pb2.HealthCheckRequest( service='grpc.test.TestServiceNotServing') resp = self._stub.Check(request) self.assertEqual(health_pb2.HealthCheckResponse.NOT_SERVING, resp.status) def test_not_found_service(self): request = health_pb2.HealthCheckRequest(service='not-found') with self.assertRaises(grpc.RpcError) as context: resp = self._stub.Check(request) self.assertEqual(grpc.StatusCode.NOT_FOUND, context.exception.code()) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/http2/000077500000000000000000000000001310511640000214575ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/http2/negative_http2_client.py000066400000000000000000000144021310511640000263130ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """The Python client used to test negative http2 conditions.""" import argparse import grpc import time from src.proto.grpc.testing import test_pb2 from src.proto.grpc.testing import messages_pb2 def _validate_payload_type_and_length(response, expected_type, expected_length): if response.payload.type is not expected_type: raise ValueError('expected payload type %s, got %s' % (expected_type, type(response.payload.type))) elif len(response.payload.body) != expected_length: raise ValueError('expected payload body size %d, got %d' % (expected_length, len(response.payload.body))) def _expect_status_code(call, expected_code): if call.code() != expected_code: raise ValueError('expected code %s, got %s' % (expected_code, call.code())) def _expect_status_details(call, expected_details): if call.details() != expected_details: raise ValueError('expected message %s, got %s' % (expected_details, call.details())) def _validate_status_code_and_details(call, expected_code, expected_details): _expect_status_code(call, expected_code) _expect_status_details(call, expected_details) # common requests _REQUEST_SIZE = 314159 _RESPONSE_SIZE = 271828 _SIMPLE_REQUEST = messages_pb2.SimpleRequest( response_type=messages_pb2.COMPRESSABLE, response_size=_RESPONSE_SIZE, payload=messages_pb2.Payload(body=b'\x00' * _REQUEST_SIZE)) def _goaway(stub): first_response = stub.UnaryCall(_SIMPLE_REQUEST) _validate_payload_type_and_length(first_response, messages_pb2.COMPRESSABLE, _RESPONSE_SIZE) time.sleep(1) second_response = stub.UnaryCall(_SIMPLE_REQUEST) _validate_payload_type_and_length(second_response, messages_pb2.COMPRESSABLE, _RESPONSE_SIZE) def _rst_after_header(stub): resp_future = stub.UnaryCall.future(_SIMPLE_REQUEST) _validate_status_code_and_details(resp_future, grpc.StatusCode.INTERNAL, "Received RST_STREAM with error code 0") def _rst_during_data(stub): resp_future = stub.UnaryCall.future(_SIMPLE_REQUEST) _validate_status_code_and_details(resp_future, grpc.StatusCode.INTERNAL, "Received RST_STREAM with error code 0") def _rst_after_data(stub): resp_future = stub.UnaryCall.future(_SIMPLE_REQUEST) _validate_payload_type_and_length( next(resp_future), messages_pb2.COMPRESSABLE, _RESPONSE_SIZE) _validate_status_code_and_details(resp_future, grpc.StatusCode.INTERNAL, "Received RST_STREAM with error code 0") def _ping(stub): response = stub.UnaryCall(_SIMPLE_REQUEST) _validate_payload_type_and_length(response, messages_pb2.COMPRESSABLE, _RESPONSE_SIZE) def _max_streams(stub): # send one req to ensure server sets MAX_STREAMS response = stub.UnaryCall(_SIMPLE_REQUEST) _validate_payload_type_and_length(response, messages_pb2.COMPRESSABLE, _RESPONSE_SIZE) # give the streams a workout futures = [] for _ in range(15): futures.append(stub.UnaryCall.future(_SIMPLE_REQUEST)) for future in futures: _validate_payload_type_and_length( future.result(), messages_pb2.COMPRESSABLE, _RESPONSE_SIZE) def _run_test_case(test_case, stub): if test_case == 'goaway': _goaway(stub) elif test_case == 'rst_after_header': _rst_after_header(stub) elif test_case == 'rst_during_data': _rst_during_data(stub) elif test_case == 'rst_after_data': _rst_after_data(stub) elif test_case == 'ping': _ping(stub) elif test_case == 'max_streams': _max_streams(stub) else: raise ValueError("Invalid test case: %s" % test_case) def _args(): parser = argparse.ArgumentParser() parser.add_argument( '--server_host', help='the host to which to connect', type=str, default="127.0.0.1") parser.add_argument( '--server_port', help='the port to which to connect', type=int, default="8080") parser.add_argument( '--test_case', help='the test case to execute', type=str, default="goaway") return parser.parse_args() def _stub(server_host, server_port): target = '{}:{}'.format(server_host, server_port) channel = grpc.insecure_channel(target) grpc.channel_ready_future(channel).result() return test_pb2.TestServiceStub(channel) def main(): args = _args() stub = _stub(args.server_host, args.server_port) _run_test_case(args.test_case, stub) if __name__ == '__main__': main() grpc-1.3.2/src/python/grpcio_tests/tests/interop/000077500000000000000000000000001310511640000220765ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/interop/__init__.py000066400000000000000000000027701310511640000242150ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/interop/_insecure_intraop_test.py000066400000000000000000000045751310511640000272320ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Insecure client-server interoperability as a unit test.""" from concurrent import futures import unittest import grpc from src.proto.grpc.testing import test_pb2_grpc from tests.interop import _intraop_test_case from tests.interop import methods from tests.interop import server class InsecureIntraopTest(_intraop_test_case.IntraopTestCase, unittest.TestCase): def setUp(self): self.server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) test_pb2_grpc.add_TestServiceServicer_to_server(methods.TestService(), self.server) port = self.server.add_insecure_port('[::]:0') self.server.start() self.stub = test_pb2_grpc.TestServiceStub( grpc.insecure_channel('localhost:{}'.format(port))) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/interop/_intraop_test_case.py000066400000000000000000000054651310511640000263270ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Common code for unit tests of the interoperability test code.""" from tests.interop import methods class IntraopTestCase(object): """Unit test methods. This class must be mixed in with unittest.TestCase and a class that defines setUp and tearDown methods that manage a stub attribute. """ def testEmptyUnary(self): methods.TestCase.EMPTY_UNARY.test_interoperability(self.stub, None) def testLargeUnary(self): methods.TestCase.LARGE_UNARY.test_interoperability(self.stub, None) def testServerStreaming(self): methods.TestCase.SERVER_STREAMING.test_interoperability(self.stub, None) def testClientStreaming(self): methods.TestCase.CLIENT_STREAMING.test_interoperability(self.stub, None) def testPingPong(self): methods.TestCase.PING_PONG.test_interoperability(self.stub, None) def testCancelAfterBegin(self): methods.TestCase.CANCEL_AFTER_BEGIN.test_interoperability(self.stub, None) def testCancelAfterFirstResponse(self): methods.TestCase.CANCEL_AFTER_FIRST_RESPONSE.test_interoperability( self.stub, None) def testTimeoutOnSleepingServer(self): methods.TestCase.TIMEOUT_ON_SLEEPING_SERVER.test_interoperability( self.stub, None) grpc-1.3.2/src/python/grpcio_tests/tests/interop/_secure_intraop_test.py000066400000000000000000000054461310511640000267010ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Secure client-server interoperability as a unit test.""" from concurrent import futures import unittest import grpc from src.proto.grpc.testing import test_pb2_grpc from tests.interop import _intraop_test_case from tests.interop import methods from tests.interop import resources _SERVER_HOST_OVERRIDE = 'foo.test.google.fr' class SecureIntraopTest(_intraop_test_case.IntraopTestCase, unittest.TestCase): def setUp(self): self.server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) test_pb2_grpc.add_TestServiceServicer_to_server(methods.TestService(), self.server) port = self.server.add_secure_port( '[::]:0', grpc.ssl_server_credentials( [(resources.private_key(), resources.certificate_chain())])) self.server.start() self.stub = test_pb2_grpc.TestServiceStub( grpc.secure_channel('localhost:{}'.format(port), grpc.ssl_channel_credentials( resources.test_root_certificates()), ( ('grpc.ssl_target_name_override', _SERVER_HOST_OVERRIDE,),))) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/interop/client.py000066400000000000000000000130161310511640000237270ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """The Python implementation of the GRPC interoperability test client.""" import argparse from oauth2client import client as oauth2client_client import grpc from grpc.beta import implementations from src.proto.grpc.testing import test_pb2 from tests.interop import methods from tests.interop import resources def _args(): parser = argparse.ArgumentParser() parser.add_argument( '--server_host', help='the host to which to connect', type=str, default="localhost") parser.add_argument( '--server_port', help='the port to which to connect', type=int) parser.add_argument( '--test_case', help='the test case to execute', type=str, default="large_unary") parser.add_argument( '--use_tls', help='require a secure connection', default=False, type=resources.parse_bool) parser.add_argument( '--use_test_ca', help='replace platform root CAs with ca.pem', default=False, type=resources.parse_bool) parser.add_argument( '--server_host_override', default="foo.test.google.fr", help='the server host to which to claim to connect', type=str) parser.add_argument( '--oauth_scope', help='scope for OAuth tokens', type=str) parser.add_argument( '--default_service_account', help='email address of the default service account', type=str) return parser.parse_args() def _application_default_credentials(): return oauth2client_client.GoogleCredentials.get_application_default() def _stub(args): target = '{}:{}'.format(args.server_host, args.server_port) if args.test_case == 'oauth2_auth_token': google_credentials = _application_default_credentials() scoped_credentials = google_credentials.create_scoped( [args.oauth_scope]) access_token = scoped_credentials.get_access_token().access_token call_credentials = grpc.access_token_call_credentials(access_token) elif args.test_case == 'compute_engine_creds': google_credentials = _application_default_credentials() scoped_credentials = google_credentials.create_scoped( [args.oauth_scope]) # TODO(https://github.com/grpc/grpc/issues/6799): Eliminate this last # remaining use of the Beta API. call_credentials = implementations.google_call_credentials( scoped_credentials) elif args.test_case == 'jwt_token_creds': google_credentials = _application_default_credentials() # TODO(https://github.com/grpc/grpc/issues/6799): Eliminate this last # remaining use of the Beta API. call_credentials = implementations.google_call_credentials( google_credentials) else: call_credentials = None if args.use_tls: if args.use_test_ca: root_certificates = resources.test_root_certificates() else: root_certificates = None # will load default roots. channel_credentials = grpc.ssl_channel_credentials(root_certificates) if call_credentials is not None: channel_credentials = grpc.composite_channel_credentials( channel_credentials, call_credentials) channel = grpc.secure_channel(target, channel_credentials, ( ('grpc.ssl_target_name_override', args.server_host_override,),)) else: channel = grpc.insecure_channel(target) if args.test_case == "unimplemented_service": return test_pb2.UnimplementedServiceStub(channel) else: return test_pb2.TestServiceStub(channel) def _test_case_from_arg(test_case_arg): for test_case in methods.TestCase: if test_case_arg == test_case.value: return test_case else: raise ValueError('No test case "%s"!' % test_case_arg) def test_interoperability(): args = _args() stub = _stub(args) test_case = _test_case_from_arg(args.test_case) test_case.test_interoperability(stub, args) if __name__ == '__main__': test_interoperability() grpc-1.3.2/src/python/grpcio_tests/tests/interop/credentials/000077500000000000000000000000001310511640000243735ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/interop/credentials/README000066400000000000000000000000641310511640000252530ustar00rootroot00000000000000These are test keys *NOT* to be used in production. grpc-1.3.2/src/python/grpcio_tests/tests/interop/credentials/ca.pem000077500000000000000000000015271310511640000254710ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIICSjCCAbOgAwIBAgIJAJHGGR4dGioHMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnRlc3RjYTAeFw0xNDExMTEyMjMxMjla Fw0yNDExMDgyMjMxMjlaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0 YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDzANBgNVBAMT BnRlc3RjYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwEDfBV5MYdlHVHJ7 +L4nxrZy7mBfAVXpOc5vMYztssUI7mL2/iYujiIXM+weZYNTEpLdjyJdu7R5gGUu g1jSVK/EPHfc74O7AyZU34PNIP4Sh33N+/A5YexrNgJlPY+E3GdVYi4ldWJjgkAd Qah2PH5ACLrIIC6tRka9hcaBlIECAwEAAaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNV HQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADgYEAHzC7jdYlzAVmddi/gdAeKPau sPBG/C2HCWqHzpCUHcKuvMzDVkY/MP2o6JIW2DBbY64bO/FceExhjcykgaYtCH/m oIU63+CFOTtR7otyQAWHqXa7q4SbCDlG7DyRFxqG0txPtGvy12lgldA2+RgcigQG Dfcog5wrJytaQ6UA0wE= -----END CERTIFICATE----- grpc-1.3.2/src/python/grpcio_tests/tests/interop/credentials/server1.key000077500000000000000000000016201310511640000264760ustar00rootroot00000000000000-----BEGIN PRIVATE KEY----- MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOHDFScoLCVJpYDD M4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1BgzkWF+slf 3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd9N8YwbBY AckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAECgYAn7qGnM2vbjJNBm0VZCkOkTIWm V10okw7EPJrdL2mkre9NasghNXbE1y5zDshx5Nt3KsazKOxTT8d0Jwh/3KbaN+YY tTCbKGW0pXDRBhwUHRcuRzScjli8Rih5UOCiZkhefUTcRb6xIhZJuQy71tjaSy0p dHZRmYyBYO2YEQ8xoQJBAPrJPhMBkzmEYFtyIEqAxQ/o/A6E+E4w8i+KM7nQCK7q K4JXzyXVAjLfyBZWHGM2uro/fjqPggGD6QH1qXCkI4MCQQDmdKeb2TrKRh5BY1LR 81aJGKcJ2XbcDu6wMZK4oqWbTX2KiYn9GB0woM6nSr/Y6iy1u145YzYxEV/iMwff DJULAkB8B2MnyzOg0pNFJqBJuH29bKCcHa8gHJzqXhNO5lAlEbMK95p/P2Wi+4Hd aiEIAF1BF326QJcvYKmwSmrORp85AkAlSNxRJ50OWrfMZnBgzVjDx3xG6KsFQVk2 ol6VhqL6dFgKUORFUWBvnKSyhjJxurlPEahV6oo6+A+mPhFY8eUvAkAZQyTdupP3 XEFQKctGz+9+gKkemDp7LBBMEMBXrGTLPhpEfcjv/7KPdnFHYmhYeBTBnuVmTVWe F98XJ7tIFfJq -----END PRIVATE KEY----- grpc-1.3.2/src/python/grpcio_tests/tests/interop/credentials/server1.pem000077500000000000000000000017041310511640000264720ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50 ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd 9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6 hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8 -----END CERTIFICATE----- grpc-1.3.2/src/python/grpcio_tests/tests/interop/methods.py000066400000000000000000000500451310511640000241170ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Implementations of interoperability test methods.""" import enum import json import os import threading from oauth2client import client as oauth2client_client import grpc from grpc.beta import implementations from src.proto.grpc.testing import empty_pb2 from src.proto.grpc.testing import messages_pb2 from src.proto.grpc.testing import test_pb2_grpc _INITIAL_METADATA_KEY = "x-grpc-test-echo-initial" _TRAILING_METADATA_KEY = "x-grpc-test-echo-trailing-bin" def _maybe_echo_metadata(servicer_context): """Copies metadata from request to response if it is present.""" invocation_metadata = dict(servicer_context.invocation_metadata()) if _INITIAL_METADATA_KEY in invocation_metadata: initial_metadatum = (_INITIAL_METADATA_KEY, invocation_metadata[_INITIAL_METADATA_KEY]) servicer_context.send_initial_metadata((initial_metadatum,)) if _TRAILING_METADATA_KEY in invocation_metadata: trailing_metadatum = (_TRAILING_METADATA_KEY, invocation_metadata[_TRAILING_METADATA_KEY]) servicer_context.set_trailing_metadata((trailing_metadatum,)) def _maybe_echo_status_and_message(request, servicer_context): """Sets the response context code and details if the request asks for them""" if request.HasField('response_status'): servicer_context.set_code(request.response_status.code) servicer_context.set_details(request.response_status.message) class TestService(test_pb2_grpc.TestServiceServicer): def EmptyCall(self, request, context): _maybe_echo_metadata(context) return empty_pb2.Empty() def UnaryCall(self, request, context): _maybe_echo_metadata(context) _maybe_echo_status_and_message(request, context) return messages_pb2.SimpleResponse(payload=messages_pb2.Payload( type=messages_pb2.COMPRESSABLE, body=b'\x00' * request.response_size)) def StreamingOutputCall(self, request, context): _maybe_echo_status_and_message(request, context) for response_parameters in request.response_parameters: yield messages_pb2.StreamingOutputCallResponse( payload=messages_pb2.Payload( type=request.response_type, body=b'\x00' * response_parameters.size)) def StreamingInputCall(self, request_iterator, context): aggregate_size = 0 for request in request_iterator: if request.payload is not None and request.payload.body: aggregate_size += len(request.payload.body) return messages_pb2.StreamingInputCallResponse( aggregated_payload_size=aggregate_size) def FullDuplexCall(self, request_iterator, context): _maybe_echo_metadata(context) for request in request_iterator: _maybe_echo_status_and_message(request, context) for response_parameters in request.response_parameters: yield messages_pb2.StreamingOutputCallResponse( payload=messages_pb2.Payload( type=request.payload.type, body=b'\x00' * response_parameters.size)) # NOTE(nathaniel): Apparently this is the same as the full-duplex call? # NOTE(atash): It isn't even called in the interop spec (Oct 22 2015)... def HalfDuplexCall(self, request_iterator, context): return self.FullDuplexCall(request_iterator, context) def _expect_status_code(call, expected_code): if call.code() != expected_code: raise ValueError('expected code %s, got %s' % (expected_code, call.code())) def _expect_status_details(call, expected_details): if call.details() != expected_details: raise ValueError('expected message %s, got %s' % (expected_details, call.details())) def _validate_status_code_and_details(call, expected_code, expected_details): _expect_status_code(call, expected_code) _expect_status_details(call, expected_details) def _validate_payload_type_and_length(response, expected_type, expected_length): if response.payload.type is not expected_type: raise ValueError('expected payload type %s, got %s' % (expected_type, type(response.payload.type))) elif len(response.payload.body) != expected_length: raise ValueError('expected payload body size %d, got %d' % (expected_length, len(response.payload.body))) def _large_unary_common_behavior(stub, fill_username, fill_oauth_scope, call_credentials): size = 314159 request = messages_pb2.SimpleRequest( response_type=messages_pb2.COMPRESSABLE, response_size=size, payload=messages_pb2.Payload(body=b'\x00' * 271828), fill_username=fill_username, fill_oauth_scope=fill_oauth_scope) response_future = stub.UnaryCall.future( request, credentials=call_credentials) response = response_future.result() _validate_payload_type_and_length(response, messages_pb2.COMPRESSABLE, size) return response def _empty_unary(stub): response = stub.EmptyCall(empty_pb2.Empty()) if not isinstance(response, empty_pb2.Empty): raise TypeError('response is of type "%s", not empty_pb2.Empty!', type(response)) def _large_unary(stub): _large_unary_common_behavior(stub, False, False, None) def _client_streaming(stub): payload_body_sizes = (27182, 8, 1828, 45904,) payloads = (messages_pb2.Payload(body=b'\x00' * size) for size in payload_body_sizes) requests = (messages_pb2.StreamingInputCallRequest(payload=payload) for payload in payloads) response = stub.StreamingInputCall(requests) if response.aggregated_payload_size != 74922: raise ValueError('incorrect size %d!' % response.aggregated_payload_size) def _server_streaming(stub): sizes = (31415, 9, 2653, 58979,) request = messages_pb2.StreamingOutputCallRequest( response_type=messages_pb2.COMPRESSABLE, response_parameters=(messages_pb2.ResponseParameters(size=sizes[0]), messages_pb2.ResponseParameters(size=sizes[1]), messages_pb2.ResponseParameters(size=sizes[2]), messages_pb2.ResponseParameters(size=sizes[3]),)) response_iterator = stub.StreamingOutputCall(request) for index, response in enumerate(response_iterator): _validate_payload_type_and_length(response, messages_pb2.COMPRESSABLE, sizes[index]) class _Pipe(object): def __init__(self): self._condition = threading.Condition() self._values = [] self._open = True def __iter__(self): return self def __next__(self): return self.next() def next(self): with self._condition: while not self._values and self._open: self._condition.wait() if self._values: return self._values.pop(0) else: raise StopIteration() def add(self, value): with self._condition: self._values.append(value) self._condition.notify() def close(self): with self._condition: self._open = False self._condition.notify() def __enter__(self): return self def __exit__(self, type, value, traceback): self.close() def _ping_pong(stub): request_response_sizes = (31415, 9, 2653, 58979,) request_payload_sizes = (27182, 8, 1828, 45904,) with _Pipe() as pipe: response_iterator = stub.FullDuplexCall(pipe) for response_size, payload_size in zip(request_response_sizes, request_payload_sizes): request = messages_pb2.StreamingOutputCallRequest( response_type=messages_pb2.COMPRESSABLE, response_parameters=( messages_pb2.ResponseParameters(size=response_size),), payload=messages_pb2.Payload(body=b'\x00' * payload_size)) pipe.add(request) response = next(response_iterator) _validate_payload_type_and_length( response, messages_pb2.COMPRESSABLE, response_size) def _cancel_after_begin(stub): with _Pipe() as pipe: response_future = stub.StreamingInputCall.future(pipe) response_future.cancel() if not response_future.cancelled(): raise ValueError('expected cancelled method to return True') if response_future.code() is not grpc.StatusCode.CANCELLED: raise ValueError('expected status code CANCELLED') def _cancel_after_first_response(stub): request_response_sizes = (31415, 9, 2653, 58979,) request_payload_sizes = (27182, 8, 1828, 45904,) with _Pipe() as pipe: response_iterator = stub.FullDuplexCall(pipe) response_size = request_response_sizes[0] payload_size = request_payload_sizes[0] request = messages_pb2.StreamingOutputCallRequest( response_type=messages_pb2.COMPRESSABLE, response_parameters=( messages_pb2.ResponseParameters(size=response_size),), payload=messages_pb2.Payload(body=b'\x00' * payload_size)) pipe.add(request) response = next(response_iterator) # We test the contents of `response` in the Ping Pong test - don't check # them here. response_iterator.cancel() try: next(response_iterator) except grpc.RpcError as rpc_error: if rpc_error.code() is not grpc.StatusCode.CANCELLED: raise else: raise ValueError('expected call to be cancelled') def _timeout_on_sleeping_server(stub): request_payload_size = 27182 with _Pipe() as pipe: response_iterator = stub.FullDuplexCall(pipe, timeout=0.001) request = messages_pb2.StreamingOutputCallRequest( response_type=messages_pb2.COMPRESSABLE, payload=messages_pb2.Payload(body=b'\x00' * request_payload_size)) pipe.add(request) try: next(response_iterator) except grpc.RpcError as rpc_error: if rpc_error.code() is not grpc.StatusCode.DEADLINE_EXCEEDED: raise else: raise ValueError('expected call to exceed deadline') def _empty_stream(stub): with _Pipe() as pipe: response_iterator = stub.FullDuplexCall(pipe) pipe.close() try: next(response_iterator) raise ValueError('expected exactly 0 responses') except StopIteration: pass def _status_code_and_message(stub): details = 'test status message' code = 2 status = grpc.StatusCode.UNKNOWN # code = 2 # Test with a UnaryCall request = messages_pb2.SimpleRequest( response_type=messages_pb2.COMPRESSABLE, response_size=1, payload=messages_pb2.Payload(body=b'\x00'), response_status=messages_pb2.EchoStatus(code=code, message=details)) response_future = stub.UnaryCall.future(request) _validate_status_code_and_details(response_future, status, details) # Test with a FullDuplexCall with _Pipe() as pipe: response_iterator = stub.FullDuplexCall(pipe) request = messages_pb2.StreamingOutputCallRequest( response_type=messages_pb2.COMPRESSABLE, response_parameters=(messages_pb2.ResponseParameters(size=1),), payload=messages_pb2.Payload(body=b'\x00'), response_status=messages_pb2.EchoStatus(code=code, message=details)) pipe.add(request) # sends the initial request. # Dropping out of with block closes the pipe _validate_status_code_and_details(response_iterator, status, details) def _unimplemented_method(test_service_stub): response_future = ( test_service_stub.UnimplementedCall.future(empty_pb2.Empty())) _expect_status_code(response_future, grpc.StatusCode.UNIMPLEMENTED) def _unimplemented_service(unimplemented_service_stub): response_future = ( unimplemented_service_stub.UnimplementedCall.future(empty_pb2.Empty())) _expect_status_code(response_future, grpc.StatusCode.UNIMPLEMENTED) def _custom_metadata(stub): initial_metadata_value = "test_initial_metadata_value" trailing_metadata_value = "\x0a\x0b\x0a\x0b\x0a\x0b" metadata = ((_INITIAL_METADATA_KEY, initial_metadata_value), (_TRAILING_METADATA_KEY, trailing_metadata_value)) def _validate_metadata(response): initial_metadata = dict(response.initial_metadata()) if initial_metadata[_INITIAL_METADATA_KEY] != initial_metadata_value: raise ValueError('expected initial metadata %s, got %s' % (initial_metadata_value, initial_metadata[_INITIAL_METADATA_KEY])) trailing_metadata = dict(response.trailing_metadata()) if trailing_metadata[_TRAILING_METADATA_KEY] != trailing_metadata_value: raise ValueError('expected trailing metadata %s, got %s' % (trailing_metadata_value, initial_metadata[_TRAILING_METADATA_KEY])) # Testing with UnaryCall request = messages_pb2.SimpleRequest( response_type=messages_pb2.COMPRESSABLE, response_size=1, payload=messages_pb2.Payload(body=b'\x00')) response_future = stub.UnaryCall.future(request, metadata=metadata) _validate_metadata(response_future) # Testing with FullDuplexCall with _Pipe() as pipe: response_iterator = stub.FullDuplexCall(pipe, metadata=metadata) request = messages_pb2.StreamingOutputCallRequest( response_type=messages_pb2.COMPRESSABLE, response_parameters=(messages_pb2.ResponseParameters(size=1),)) pipe.add(request) # Sends the request next(response_iterator) # Causes server to send trailing metadata # Dropping out of the with block closes the pipe _validate_metadata(response_iterator) def _compute_engine_creds(stub, args): response = _large_unary_common_behavior(stub, True, True, None) if args.default_service_account != response.username: raise ValueError('expected username %s, got %s' % (args.default_service_account, response.username)) def _oauth2_auth_token(stub, args): json_key_filename = os.environ[ oauth2client_client.GOOGLE_APPLICATION_CREDENTIALS] wanted_email = json.load(open(json_key_filename, 'rb'))['client_email'] response = _large_unary_common_behavior(stub, True, True, None) if wanted_email != response.username: raise ValueError('expected username %s, got %s' % (wanted_email, response.username)) if args.oauth_scope.find(response.oauth_scope) == -1: raise ValueError('expected to find oauth scope "{}" in received "{}"'. format(response.oauth_scope, args.oauth_scope)) def _jwt_token_creds(stub, args): json_key_filename = os.environ[ oauth2client_client.GOOGLE_APPLICATION_CREDENTIALS] wanted_email = json.load(open(json_key_filename, 'rb'))['client_email'] response = _large_unary_common_behavior(stub, True, False, None) if wanted_email != response.username: raise ValueError('expected username %s, got %s' % (wanted_email, response.username)) def _per_rpc_creds(stub, args): json_key_filename = os.environ[ oauth2client_client.GOOGLE_APPLICATION_CREDENTIALS] wanted_email = json.load(open(json_key_filename, 'rb'))['client_email'] credentials = oauth2client_client.GoogleCredentials.get_application_default() scoped_credentials = credentials.create_scoped([args.oauth_scope]) # TODO(https://github.com/grpc/grpc/issues/6799): Eliminate this last # remaining use of the Beta API. call_credentials = implementations.google_call_credentials( scoped_credentials) response = _large_unary_common_behavior(stub, True, False, call_credentials) if wanted_email != response.username: raise ValueError('expected username %s, got %s' % (wanted_email, response.username)) @enum.unique class TestCase(enum.Enum): EMPTY_UNARY = 'empty_unary' LARGE_UNARY = 'large_unary' SERVER_STREAMING = 'server_streaming' CLIENT_STREAMING = 'client_streaming' PING_PONG = 'ping_pong' CANCEL_AFTER_BEGIN = 'cancel_after_begin' CANCEL_AFTER_FIRST_RESPONSE = 'cancel_after_first_response' EMPTY_STREAM = 'empty_stream' STATUS_CODE_AND_MESSAGE = 'status_code_and_message' UNIMPLEMENTED_METHOD = 'unimplemented_method' UNIMPLEMENTED_SERVICE = 'unimplemented_service' CUSTOM_METADATA = "custom_metadata" COMPUTE_ENGINE_CREDS = 'compute_engine_creds' OAUTH2_AUTH_TOKEN = 'oauth2_auth_token' JWT_TOKEN_CREDS = 'jwt_token_creds' PER_RPC_CREDS = 'per_rpc_creds' TIMEOUT_ON_SLEEPING_SERVER = 'timeout_on_sleeping_server' def test_interoperability(self, stub, args): if self is TestCase.EMPTY_UNARY: _empty_unary(stub) elif self is TestCase.LARGE_UNARY: _large_unary(stub) elif self is TestCase.SERVER_STREAMING: _server_streaming(stub) elif self is TestCase.CLIENT_STREAMING: _client_streaming(stub) elif self is TestCase.PING_PONG: _ping_pong(stub) elif self is TestCase.CANCEL_AFTER_BEGIN: _cancel_after_begin(stub) elif self is TestCase.CANCEL_AFTER_FIRST_RESPONSE: _cancel_after_first_response(stub) elif self is TestCase.TIMEOUT_ON_SLEEPING_SERVER: _timeout_on_sleeping_server(stub) elif self is TestCase.EMPTY_STREAM: _empty_stream(stub) elif self is TestCase.STATUS_CODE_AND_MESSAGE: _status_code_and_message(stub) elif self is TestCase.UNIMPLEMENTED_METHOD: _unimplemented_method(stub) elif self is TestCase.UNIMPLEMENTED_SERVICE: _unimplemented_service(stub) elif self is TestCase.CUSTOM_METADATA: _custom_metadata(stub) elif self is TestCase.COMPUTE_ENGINE_CREDS: _compute_engine_creds(stub, args) elif self is TestCase.OAUTH2_AUTH_TOKEN: _oauth2_auth_token(stub, args) elif self is TestCase.JWT_TOKEN_CREDS: _jwt_token_creds(stub, args) elif self is TestCase.PER_RPC_CREDS: _per_rpc_creds(stub, args) else: raise NotImplementedError('Test case "%s" not implemented!' % self.name) grpc-1.3.2/src/python/grpcio_tests/tests/interop/resources.py000066400000000000000000000045551310511640000244730ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Constants and functions for data used in interoperability testing.""" import argparse import os import pkg_resources _ROOT_CERTIFICATES_RESOURCE_PATH = 'credentials/ca.pem' _PRIVATE_KEY_RESOURCE_PATH = 'credentials/server1.key' _CERTIFICATE_CHAIN_RESOURCE_PATH = 'credentials/server1.pem' def test_root_certificates(): return pkg_resources.resource_string(__name__, _ROOT_CERTIFICATES_RESOURCE_PATH) def private_key(): return pkg_resources.resource_string(__name__, _PRIVATE_KEY_RESOURCE_PATH) def certificate_chain(): return pkg_resources.resource_string(__name__, _CERTIFICATE_CHAIN_RESOURCE_PATH) def parse_bool(value): if value == 'true': return True if value == 'false': return False raise argparse.ArgumentTypeError('Only true/false allowed') grpc-1.3.2/src/python/grpcio_tests/tests/interop/server.py000066400000000000000000000060061310511640000237600ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """The Python implementation of the GRPC interoperability test server.""" import argparse from concurrent import futures import logging import time import grpc from src.proto.grpc.testing import test_pb2_grpc from tests.interop import methods from tests.interop import resources _ONE_DAY_IN_SECONDS = 60 * 60 * 24 def serve(): parser = argparse.ArgumentParser() parser.add_argument('--port', help='the port on which to serve', type=int) parser.add_argument( '--use_tls', help='require a secure connection', default=False, type=resources.parse_bool) args = parser.parse_args() server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) test_pb2_grpc.add_TestServiceServicer_to_server(methods.TestService(), server) if args.use_tls: private_key = resources.private_key() certificate_chain = resources.certificate_chain() credentials = grpc.ssl_server_credentials(( (private_key, certificate_chain),)) server.add_secure_port('[::]:{}'.format(args.port), credentials) else: server.add_insecure_port('[::]:{}'.format(args.port)) server.start() logging.info('Server serving.') try: while True: time.sleep(_ONE_DAY_IN_SECONDS) except BaseException as e: logging.info('Caught exception "%s"; stopping server...', e) server.stop(None) logging.info('Server stopped; exiting.') if __name__ == '__main__': serve() grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/000077500000000000000000000000001310511640000233025ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/__init__.py000066400000000000000000000027701310511640000254210ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/_python_plugin_test.py000066400000000000000000000504001310511640000277500ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import collections from concurrent import futures import contextlib import distutils.spawn import errno import os import shutil import subprocess import sys import tempfile import threading import unittest from six import moves import grpc from tests.unit.framework.common import test_constants import tests.protoc_plugin.protos.payload.test_payload_pb2 as payload_pb2 import tests.protoc_plugin.protos.requests.r.test_requests_pb2 as request_pb2 import tests.protoc_plugin.protos.responses.test_responses_pb2 as response_pb2 import tests.protoc_plugin.protos.service.test_service_pb2 as service_pb2 # Identifiers of entities we expect to find in the generated module. STUB_IDENTIFIER = 'TestServiceStub' SERVICER_IDENTIFIER = 'TestServiceServicer' ADD_SERVICER_TO_SERVER_IDENTIFIER = 'add_TestServiceServicer_to_server' class _ServicerMethods(object): def __init__(self): self._condition = threading.Condition() self._paused = False self._fail = False @contextlib.contextmanager def pause(self): # pylint: disable=invalid-name with self._condition: self._paused = True yield with self._condition: self._paused = False self._condition.notify_all() @contextlib.contextmanager def fail(self): # pylint: disable=invalid-name with self._condition: self._fail = True yield with self._condition: self._fail = False def _control(self): # pylint: disable=invalid-name with self._condition: if self._fail: raise ValueError() while self._paused: self._condition.wait() def UnaryCall(self, request, unused_rpc_context): response = response_pb2.SimpleResponse() response.payload.payload_type = payload_pb2.COMPRESSABLE response.payload.payload_compressable = 'a' * request.response_size self._control() return response def StreamingOutputCall(self, request, unused_rpc_context): for parameter in request.response_parameters: response = response_pb2.StreamingOutputCallResponse() response.payload.payload_type = payload_pb2.COMPRESSABLE response.payload.payload_compressable = 'a' * parameter.size self._control() yield response def StreamingInputCall(self, request_iter, unused_rpc_context): response = response_pb2.StreamingInputCallResponse() aggregated_payload_size = 0 for request in request_iter: aggregated_payload_size += len(request.payload.payload_compressable) response.aggregated_payload_size = aggregated_payload_size self._control() return response def FullDuplexCall(self, request_iter, unused_rpc_context): for request in request_iter: for parameter in request.response_parameters: response = response_pb2.StreamingOutputCallResponse() response.payload.payload_type = payload_pb2.COMPRESSABLE response.payload.payload_compressable = 'a' * parameter.size self._control() yield response def HalfDuplexCall(self, request_iter, unused_rpc_context): responses = [] for request in request_iter: for parameter in request.response_parameters: response = response_pb2.StreamingOutputCallResponse() response.payload.payload_type = payload_pb2.COMPRESSABLE response.payload.payload_compressable = 'a' * parameter.size self._control() responses.append(response) for response in responses: yield response class _Service( collections.namedtuple('_Service', ('servicer_methods', 'server', 'stub',))): """A live and running service. Attributes: servicer_methods: The _ServicerMethods servicing RPCs. server: The grpc.Server servicing RPCs. stub: A stub on which to invoke RPCs. """ def _CreateService(): """Provides a servicer backend and a stub. Returns: A _Service with which to test RPCs. """ servicer_methods = _ServicerMethods() class Servicer(getattr(service_pb2, SERVICER_IDENTIFIER)): def UnaryCall(self, request, context): return servicer_methods.UnaryCall(request, context) def StreamingOutputCall(self, request, context): return servicer_methods.StreamingOutputCall(request, context) def StreamingInputCall(self, request_iter, context): return servicer_methods.StreamingInputCall(request_iter, context) def FullDuplexCall(self, request_iter, context): return servicer_methods.FullDuplexCall(request_iter, context) def HalfDuplexCall(self, request_iter, context): return servicer_methods.HalfDuplexCall(request_iter, context) server = grpc.server( futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE)) getattr(service_pb2, ADD_SERVICER_TO_SERVER_IDENTIFIER)(Servicer(), server) port = server.add_insecure_port('[::]:0') server.start() channel = grpc.insecure_channel('localhost:{}'.format(port)) stub = getattr(service_pb2, STUB_IDENTIFIER)(channel) return _Service(servicer_methods, server, stub) def _CreateIncompleteService(): """Provides a servicer backend that fails to implement methods and its stub. Returns: A _Service with which to test RPCs. The returned _Service's servicer_methods implements none of the methods required of it. """ class Servicer(getattr(service_pb2, SERVICER_IDENTIFIER)): pass server = grpc.server( futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE)) getattr(service_pb2, ADD_SERVICER_TO_SERVER_IDENTIFIER)(Servicer(), server) port = server.add_insecure_port('[::]:0') server.start() channel = grpc.insecure_channel('localhost:{}'.format(port)) stub = getattr(service_pb2, STUB_IDENTIFIER)(channel) return _Service(None, server, stub) def _streaming_input_request_iterator(): for _ in range(3): request = request_pb2.StreamingInputCallRequest() request.payload.payload_type = payload_pb2.COMPRESSABLE request.payload.payload_compressable = 'a' yield request def _streaming_output_request(): request = request_pb2.StreamingOutputCallRequest() sizes = [1, 2, 3] request.response_parameters.add(size=sizes[0], interval_us=0) request.response_parameters.add(size=sizes[1], interval_us=0) request.response_parameters.add(size=sizes[2], interval_us=0) return request def _full_duplex_request_iterator(): request = request_pb2.StreamingOutputCallRequest() request.response_parameters.add(size=1, interval_us=0) yield request request = request_pb2.StreamingOutputCallRequest() request.response_parameters.add(size=2, interval_us=0) request.response_parameters.add(size=3, interval_us=0) yield request class PythonPluginTest(unittest.TestCase): """Test case for the gRPC Python protoc-plugin. While reading these tests, remember that the futures API (`stub.method.future()`) only gives futures for the *response-unary* methods and does not exist for response-streaming methods. """ def testImportAttributes(self): # check that we can access the generated module and its members. self.assertIsNotNone(getattr(service_pb2, STUB_IDENTIFIER, None)) self.assertIsNotNone(getattr(service_pb2, SERVICER_IDENTIFIER, None)) self.assertIsNotNone( getattr(service_pb2, ADD_SERVICER_TO_SERVER_IDENTIFIER, None)) def testUpDown(self): service = _CreateService() self.assertIsNotNone(service.servicer_methods) self.assertIsNotNone(service.server) self.assertIsNotNone(service.stub) def testIncompleteServicer(self): service = _CreateIncompleteService() request = request_pb2.SimpleRequest(response_size=13) with self.assertRaises(grpc.RpcError) as exception_context: service.stub.UnaryCall(request) self.assertIs(exception_context.exception.code(), grpc.StatusCode.UNIMPLEMENTED) def testUnaryCall(self): service = _CreateService() request = request_pb2.SimpleRequest(response_size=13) response = service.stub.UnaryCall(request) expected_response = service.servicer_methods.UnaryCall( request, 'not a real context!') self.assertEqual(expected_response, response) def testUnaryCallFuture(self): service = _CreateService() request = request_pb2.SimpleRequest(response_size=13) # Check that the call does not block waiting for the server to respond. with service.servicer_methods.pause(): response_future = service.stub.UnaryCall.future(request) response = response_future.result() expected_response = service.servicer_methods.UnaryCall( request, 'not a real RpcContext!') self.assertEqual(expected_response, response) def testUnaryCallFutureExpired(self): service = _CreateService() request = request_pb2.SimpleRequest(response_size=13) with service.servicer_methods.pause(): response_future = service.stub.UnaryCall.future( request, timeout=test_constants.SHORT_TIMEOUT) with self.assertRaises(grpc.RpcError) as exception_context: response_future.result() self.assertIs(exception_context.exception.code(), grpc.StatusCode.DEADLINE_EXCEEDED) self.assertIs(response_future.code(), grpc.StatusCode.DEADLINE_EXCEEDED) def testUnaryCallFutureCancelled(self): service = _CreateService() request = request_pb2.SimpleRequest(response_size=13) with service.servicer_methods.pause(): response_future = service.stub.UnaryCall.future(request) response_future.cancel() self.assertTrue(response_future.cancelled()) self.assertIs(response_future.code(), grpc.StatusCode.CANCELLED) def testUnaryCallFutureFailed(self): service = _CreateService() request = request_pb2.SimpleRequest(response_size=13) with service.servicer_methods.fail(): response_future = service.stub.UnaryCall.future(request) self.assertIsNotNone(response_future.exception()) self.assertIs(response_future.code(), grpc.StatusCode.UNKNOWN) def testStreamingOutputCall(self): service = _CreateService() request = _streaming_output_request() responses = service.stub.StreamingOutputCall(request) expected_responses = service.servicer_methods.StreamingOutputCall( request, 'not a real RpcContext!') for expected_response, response in moves.zip_longest(expected_responses, responses): self.assertEqual(expected_response, response) def testStreamingOutputCallExpired(self): service = _CreateService() request = _streaming_output_request() with service.servicer_methods.pause(): responses = service.stub.StreamingOutputCall( request, timeout=test_constants.SHORT_TIMEOUT) with self.assertRaises(grpc.RpcError) as exception_context: list(responses) self.assertIs(exception_context.exception.code(), grpc.StatusCode.DEADLINE_EXCEEDED) def testStreamingOutputCallCancelled(self): service = _CreateService() request = _streaming_output_request() responses = service.stub.StreamingOutputCall(request) next(responses) responses.cancel() with self.assertRaises(grpc.RpcError) as exception_context: next(responses) self.assertIs(responses.code(), grpc.StatusCode.CANCELLED) def testStreamingOutputCallFailed(self): service = _CreateService() request = _streaming_output_request() with service.servicer_methods.fail(): responses = service.stub.StreamingOutputCall(request) self.assertIsNotNone(responses) with self.assertRaises(grpc.RpcError) as exception_context: next(responses) self.assertIs(exception_context.exception.code(), grpc.StatusCode.UNKNOWN) def testStreamingInputCall(self): service = _CreateService() response = service.stub.StreamingInputCall( _streaming_input_request_iterator()) expected_response = service.servicer_methods.StreamingInputCall( _streaming_input_request_iterator(), 'not a real RpcContext!') self.assertEqual(expected_response, response) def testStreamingInputCallFuture(self): service = _CreateService() with service.servicer_methods.pause(): response_future = service.stub.StreamingInputCall.future( _streaming_input_request_iterator()) response = response_future.result() expected_response = service.servicer_methods.StreamingInputCall( _streaming_input_request_iterator(), 'not a real RpcContext!') self.assertEqual(expected_response, response) def testStreamingInputCallFutureExpired(self): service = _CreateService() with service.servicer_methods.pause(): response_future = service.stub.StreamingInputCall.future( _streaming_input_request_iterator(), timeout=test_constants.SHORT_TIMEOUT) with self.assertRaises(grpc.RpcError) as exception_context: response_future.result() self.assertIsInstance(response_future.exception(), grpc.RpcError) self.assertIs(response_future.exception().code(), grpc.StatusCode.DEADLINE_EXCEEDED) self.assertIs(exception_context.exception.code(), grpc.StatusCode.DEADLINE_EXCEEDED) def testStreamingInputCallFutureCancelled(self): service = _CreateService() with service.servicer_methods.pause(): response_future = service.stub.StreamingInputCall.future( _streaming_input_request_iterator()) response_future.cancel() self.assertTrue(response_future.cancelled()) with self.assertRaises(grpc.FutureCancelledError): response_future.result() def testStreamingInputCallFutureFailed(self): service = _CreateService() with service.servicer_methods.fail(): response_future = service.stub.StreamingInputCall.future( _streaming_input_request_iterator()) self.assertIsNotNone(response_future.exception()) self.assertIs(response_future.code(), grpc.StatusCode.UNKNOWN) def testFullDuplexCall(self): service = _CreateService() responses = service.stub.FullDuplexCall(_full_duplex_request_iterator()) expected_responses = service.servicer_methods.FullDuplexCall( _full_duplex_request_iterator(), 'not a real RpcContext!') for expected_response, response in moves.zip_longest(expected_responses, responses): self.assertEqual(expected_response, response) def testFullDuplexCallExpired(self): request_iterator = _full_duplex_request_iterator() service = _CreateService() with service.servicer_methods.pause(): responses = service.stub.FullDuplexCall( request_iterator, timeout=test_constants.SHORT_TIMEOUT) with self.assertRaises(grpc.RpcError) as exception_context: list(responses) self.assertIs(exception_context.exception.code(), grpc.StatusCode.DEADLINE_EXCEEDED) def testFullDuplexCallCancelled(self): service = _CreateService() request_iterator = _full_duplex_request_iterator() responses = service.stub.FullDuplexCall(request_iterator) next(responses) responses.cancel() with self.assertRaises(grpc.RpcError) as exception_context: next(responses) self.assertIs(exception_context.exception.code(), grpc.StatusCode.CANCELLED) def testFullDuplexCallFailed(self): request_iterator = _full_duplex_request_iterator() service = _CreateService() with service.servicer_methods.fail(): responses = service.stub.FullDuplexCall(request_iterator) with self.assertRaises(grpc.RpcError) as exception_context: next(responses) self.assertIs(exception_context.exception.code(), grpc.StatusCode.UNKNOWN) def testHalfDuplexCall(self): service = _CreateService() def half_duplex_request_iterator(): request = request_pb2.StreamingOutputCallRequest() request.response_parameters.add(size=1, interval_us=0) yield request request = request_pb2.StreamingOutputCallRequest() request.response_parameters.add(size=2, interval_us=0) request.response_parameters.add(size=3, interval_us=0) yield request responses = service.stub.HalfDuplexCall(half_duplex_request_iterator()) expected_responses = service.servicer_methods.HalfDuplexCall( half_duplex_request_iterator(), 'not a real RpcContext!') for expected_response, response in moves.zip_longest(expected_responses, responses): self.assertEqual(expected_response, response) def testHalfDuplexCallWedged(self): condition = threading.Condition() wait_cell = [False] @contextlib.contextmanager def wait(): # pylint: disable=invalid-name # Where's Python 3's 'nonlocal' statement when you need it? with condition: wait_cell[0] = True yield with condition: wait_cell[0] = False condition.notify_all() def half_duplex_request_iterator(): request = request_pb2.StreamingOutputCallRequest() request.response_parameters.add(size=1, interval_us=0) yield request with condition: while wait_cell[0]: condition.wait() service = _CreateService() with wait(): responses = service.stub.HalfDuplexCall( half_duplex_request_iterator(), timeout=test_constants.SHORT_TIMEOUT) # half-duplex waits for the client to send all info with self.assertRaises(grpc.RpcError) as exception_context: next(responses) self.assertIs(exception_context.exception.code(), grpc.StatusCode.DEADLINE_EXCEEDED) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py000066400000000000000000000342321310511640000306040ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import collections from concurrent import futures import contextlib import distutils.spawn import errno import importlib import os import os.path import pkgutil import shutil import subprocess import sys import tempfile import threading import unittest import platform import grpc from grpc_tools import protoc from tests.unit.framework.common import test_constants _MESSAGES_IMPORT = b'import "messages.proto";' _SPLIT_NAMESPACE = b'package grpc_protoc_plugin.invocation_testing.split;' _COMMON_NAMESPACE = b'package grpc_protoc_plugin.invocation_testing;' @contextlib.contextmanager def _system_path(path): old_system_path = sys.path[:] sys.path = sys.path[0:1] + path + sys.path[1:] yield sys.path = old_system_path class DummySplitServicer(object): def __init__(self, request_class, response_class): self.request_class = request_class self.response_class = response_class def Call(self, request, context): return self.response_class() class SeparateTestMixin(object): def testImportAttributes(self): with _system_path([self.python_out_directory]): pb2 = importlib.import_module(self.pb2_import) pb2.Request pb2.Response if self.should_find_services_in_pb2: pb2.TestServiceServicer else: with self.assertRaises(AttributeError): pb2.TestServiceServicer with _system_path([self.grpc_python_out_directory]): pb2_grpc = importlib.import_module(self.pb2_grpc_import) pb2_grpc.TestServiceServicer with self.assertRaises(AttributeError): pb2_grpc.Request with self.assertRaises(AttributeError): pb2_grpc.Response def testCall(self): with _system_path([self.python_out_directory]): pb2 = importlib.import_module(self.pb2_import) with _system_path([self.grpc_python_out_directory]): pb2_grpc = importlib.import_module(self.pb2_grpc_import) server = grpc.server( futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE)) pb2_grpc.add_TestServiceServicer_to_server( DummySplitServicer(pb2.Request, pb2.Response), server) port = server.add_insecure_port('[::]:0') server.start() channel = grpc.insecure_channel('localhost:{}'.format(port)) stub = pb2_grpc.TestServiceStub(channel) request = pb2.Request() expected_response = pb2.Response() response = stub.Call(request) self.assertEqual(expected_response, response) class CommonTestMixin(object): def testImportAttributes(self): with _system_path([self.python_out_directory]): pb2 = importlib.import_module(self.pb2_import) pb2.Request pb2.Response if self.should_find_services_in_pb2: pb2.TestServiceServicer else: with self.assertRaises(AttributeError): pb2.TestServiceServicer with _system_path([self.grpc_python_out_directory]): pb2_grpc = importlib.import_module(self.pb2_grpc_import) pb2_grpc.TestServiceServicer with self.assertRaises(AttributeError): pb2_grpc.Request with self.assertRaises(AttributeError): pb2_grpc.Response def testCall(self): with _system_path([self.python_out_directory]): pb2 = importlib.import_module(self.pb2_import) with _system_path([self.grpc_python_out_directory]): pb2_grpc = importlib.import_module(self.pb2_grpc_import) server = grpc.server( futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE)) pb2_grpc.add_TestServiceServicer_to_server( DummySplitServicer(pb2.Request, pb2.Response), server) port = server.add_insecure_port('[::]:0') server.start() channel = grpc.insecure_channel('localhost:{}'.format(port)) stub = pb2_grpc.TestServiceStub(channel) request = pb2.Request() expected_response = pb2.Response() response = stub.Call(request) self.assertEqual(expected_response, response) @unittest.skipIf(platform.python_implementation() == "PyPy", "Skip test if run with PyPy") class SameSeparateTest(unittest.TestCase, SeparateTestMixin): def setUp(self): same_proto_contents = pkgutil.get_data( 'tests.protoc_plugin.protos.invocation_testing', 'same.proto') self.directory = tempfile.mkdtemp(suffix='same_separate', dir='.') self.proto_directory = os.path.join(self.directory, 'proto_path') self.python_out_directory = os.path.join(self.directory, 'python_out') self.grpc_python_out_directory = os.path.join(self.directory, 'grpc_python_out') os.makedirs(self.proto_directory) os.makedirs(self.python_out_directory) os.makedirs(self.grpc_python_out_directory) same_proto_file = os.path.join(self.proto_directory, 'same_separate.proto') open(same_proto_file, 'wb').write( same_proto_contents.replace( _COMMON_NAMESPACE, b'package grpc_protoc_plugin.invocation_testing.same_separate;')) protoc_result = protoc.main([ '', '--proto_path={}'.format(self.proto_directory), '--python_out={}'.format(self.python_out_directory), '--grpc_python_out=grpc_2_0:{}'.format( self.grpc_python_out_directory), same_proto_file, ]) if protoc_result != 0: raise Exception("unexpected protoc error") open(os.path.join(self.grpc_python_out_directory, '__init__.py'), 'w').write('') open(os.path.join(self.python_out_directory, '__init__.py'), 'w').write('') self.pb2_import = 'same_separate_pb2' self.pb2_grpc_import = 'same_separate_pb2_grpc' self.should_find_services_in_pb2 = False def tearDown(self): shutil.rmtree(self.directory) @unittest.skipIf(platform.python_implementation() == "PyPy", "Skip test if run with PyPy") class SameCommonTest(unittest.TestCase, CommonTestMixin): def setUp(self): same_proto_contents = pkgutil.get_data( 'tests.protoc_plugin.protos.invocation_testing', 'same.proto') self.directory = tempfile.mkdtemp(suffix='same_common', dir='.') self.proto_directory = os.path.join(self.directory, 'proto_path') self.python_out_directory = os.path.join(self.directory, 'python_out') self.grpc_python_out_directory = self.python_out_directory os.makedirs(self.proto_directory) os.makedirs(self.python_out_directory) same_proto_file = os.path.join(self.proto_directory, 'same_common.proto') open(same_proto_file, 'wb').write( same_proto_contents.replace( _COMMON_NAMESPACE, b'package grpc_protoc_plugin.invocation_testing.same_common;')) protoc_result = protoc.main([ '', '--proto_path={}'.format(self.proto_directory), '--python_out={}'.format(self.python_out_directory), '--grpc_python_out={}'.format(self.grpc_python_out_directory), same_proto_file, ]) if protoc_result != 0: raise Exception("unexpected protoc error") open(os.path.join(self.python_out_directory, '__init__.py'), 'w').write('') self.pb2_import = 'same_common_pb2' self.pb2_grpc_import = 'same_common_pb2_grpc' self.should_find_services_in_pb2 = True def tearDown(self): shutil.rmtree(self.directory) @unittest.skipIf(platform.python_implementation() == "PyPy", "Skip test if run with PyPy") class SplitCommonTest(unittest.TestCase, CommonTestMixin): def setUp(self): services_proto_contents = pkgutil.get_data( 'tests.protoc_plugin.protos.invocation_testing.split_services', 'services.proto') messages_proto_contents = pkgutil.get_data( 'tests.protoc_plugin.protos.invocation_testing.split_messages', 'messages.proto') self.directory = tempfile.mkdtemp(suffix='split_common', dir='.') self.proto_directory = os.path.join(self.directory, 'proto_path') self.python_out_directory = os.path.join(self.directory, 'python_out') self.grpc_python_out_directory = self.python_out_directory os.makedirs(self.proto_directory) os.makedirs(self.python_out_directory) services_proto_file = os.path.join(self.proto_directory, 'split_common_services.proto') messages_proto_file = os.path.join(self.proto_directory, 'split_common_messages.proto') open(services_proto_file, 'wb').write( services_proto_contents.replace( _MESSAGES_IMPORT, b'import "split_common_messages.proto";') .replace( _SPLIT_NAMESPACE, b'package grpc_protoc_plugin.invocation_testing.split_common;')) open(messages_proto_file, 'wb').write( messages_proto_contents.replace( _SPLIT_NAMESPACE, b'package grpc_protoc_plugin.invocation_testing.split_common;')) protoc_result = protoc.main([ '', '--proto_path={}'.format(self.proto_directory), '--python_out={}'.format(self.python_out_directory), '--grpc_python_out={}'.format(self.grpc_python_out_directory), services_proto_file, messages_proto_file, ]) if protoc_result != 0: raise Exception("unexpected protoc error") open(os.path.join(self.python_out_directory, '__init__.py'), 'w').write('') self.pb2_import = 'split_common_messages_pb2' self.pb2_grpc_import = 'split_common_services_pb2_grpc' self.should_find_services_in_pb2 = False def tearDown(self): shutil.rmtree(self.directory) @unittest.skipIf(platform.python_implementation() == "PyPy", "Skip test if run with PyPy") class SplitSeparateTest(unittest.TestCase, SeparateTestMixin): def setUp(self): services_proto_contents = pkgutil.get_data( 'tests.protoc_plugin.protos.invocation_testing.split_services', 'services.proto') messages_proto_contents = pkgutil.get_data( 'tests.protoc_plugin.protos.invocation_testing.split_messages', 'messages.proto') self.directory = tempfile.mkdtemp(suffix='split_separate', dir='.') self.proto_directory = os.path.join(self.directory, 'proto_path') self.python_out_directory = os.path.join(self.directory, 'python_out') self.grpc_python_out_directory = os.path.join(self.directory, 'grpc_python_out') os.makedirs(self.proto_directory) os.makedirs(self.python_out_directory) os.makedirs(self.grpc_python_out_directory) services_proto_file = os.path.join(self.proto_directory, 'split_separate_services.proto') messages_proto_file = os.path.join(self.proto_directory, 'split_separate_messages.proto') open(services_proto_file, 'wb').write( services_proto_contents.replace( _MESSAGES_IMPORT, b'import "split_separate_messages.proto";') .replace( _SPLIT_NAMESPACE, b'package grpc_protoc_plugin.invocation_testing.split_separate;' )) open(messages_proto_file, 'wb').write( messages_proto_contents.replace( _SPLIT_NAMESPACE, b'package grpc_protoc_plugin.invocation_testing.split_separate;' )) protoc_result = protoc.main([ '', '--proto_path={}'.format(self.proto_directory), '--python_out={}'.format(self.python_out_directory), '--grpc_python_out=grpc_2_0:{}'.format( self.grpc_python_out_directory), services_proto_file, messages_proto_file, ]) if protoc_result != 0: raise Exception("unexpected protoc error") open(os.path.join(self.python_out_directory, '__init__.py'), 'w').write('') self.pb2_import = 'split_separate_messages_pb2' self.pb2_grpc_import = 'split_separate_services_pb2_grpc' self.should_find_services_in_pb2 = False def tearDown(self): shutil.rmtree(self.directory) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/beta_python_plugin_test.py000066400000000000000000000501411310511640000306060ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import argparse import contextlib import distutils.spawn import errno import itertools import os import pkg_resources import shutil import subprocess import sys import tempfile import threading import time import unittest from six import moves from grpc.beta import implementations from grpc.beta import interfaces from grpc.framework.foundation import future from grpc.framework.interfaces.face import face from tests.unit.framework.common import test_constants import tests.protoc_plugin.protos.payload.test_payload_pb2 as payload_pb2 import tests.protoc_plugin.protos.requests.r.test_requests_pb2 as request_pb2 import tests.protoc_plugin.protos.responses.test_responses_pb2 as response_pb2 import tests.protoc_plugin.protos.service.test_service_pb2 as service_pb2 # Identifiers of entities we expect to find in the generated module. SERVICER_IDENTIFIER = 'BetaTestServiceServicer' STUB_IDENTIFIER = 'BetaTestServiceStub' SERVER_FACTORY_IDENTIFIER = 'beta_create_TestService_server' STUB_FACTORY_IDENTIFIER = 'beta_create_TestService_stub' class _ServicerMethods(object): def __init__(self): self._condition = threading.Condition() self._paused = False self._fail = False @contextlib.contextmanager def pause(self): # pylint: disable=invalid-name with self._condition: self._paused = True yield with self._condition: self._paused = False self._condition.notify_all() @contextlib.contextmanager def fail(self): # pylint: disable=invalid-name with self._condition: self._fail = True yield with self._condition: self._fail = False def _control(self): # pylint: disable=invalid-name with self._condition: if self._fail: raise ValueError() while self._paused: self._condition.wait() def UnaryCall(self, request, unused_rpc_context): response = response_pb2.SimpleResponse() response.payload.payload_type = payload_pb2.COMPRESSABLE response.payload.payload_compressable = 'a' * request.response_size self._control() return response def StreamingOutputCall(self, request, unused_rpc_context): for parameter in request.response_parameters: response = response_pb2.StreamingOutputCallResponse() response.payload.payload_type = payload_pb2.COMPRESSABLE response.payload.payload_compressable = 'a' * parameter.size self._control() yield response def StreamingInputCall(self, request_iter, unused_rpc_context): response = response_pb2.StreamingInputCallResponse() aggregated_payload_size = 0 for request in request_iter: aggregated_payload_size += len(request.payload.payload_compressable) response.aggregated_payload_size = aggregated_payload_size self._control() return response def FullDuplexCall(self, request_iter, unused_rpc_context): for request in request_iter: for parameter in request.response_parameters: response = response_pb2.StreamingOutputCallResponse() response.payload.payload_type = payload_pb2.COMPRESSABLE response.payload.payload_compressable = 'a' * parameter.size self._control() yield response def HalfDuplexCall(self, request_iter, unused_rpc_context): responses = [] for request in request_iter: for parameter in request.response_parameters: response = response_pb2.StreamingOutputCallResponse() response.payload.payload_type = payload_pb2.COMPRESSABLE response.payload.payload_compressable = 'a' * parameter.size self._control() responses.append(response) for response in responses: yield response @contextlib.contextmanager def _CreateService(): """Provides a servicer backend and a stub. The servicer is just the implementation of the actual servicer passed to the face player of the python RPC implementation; the two are detached. Yields: A (servicer_methods, stub) pair where servicer_methods is the back-end of the service bound to the stub and and stub is the stub on which to invoke RPCs. """ servicer_methods = _ServicerMethods() class Servicer(getattr(service_pb2, SERVICER_IDENTIFIER)): def UnaryCall(self, request, context): return servicer_methods.UnaryCall(request, context) def StreamingOutputCall(self, request, context): return servicer_methods.StreamingOutputCall(request, context) def StreamingInputCall(self, request_iter, context): return servicer_methods.StreamingInputCall(request_iter, context) def FullDuplexCall(self, request_iter, context): return servicer_methods.FullDuplexCall(request_iter, context) def HalfDuplexCall(self, request_iter, context): return servicer_methods.HalfDuplexCall(request_iter, context) servicer = Servicer() server = getattr(service_pb2, SERVER_FACTORY_IDENTIFIER)(servicer) port = server.add_insecure_port('[::]:0') server.start() channel = implementations.insecure_channel('localhost', port) stub = getattr(service_pb2, STUB_FACTORY_IDENTIFIER)(channel) yield (servicer_methods, stub) server.stop(0) @contextlib.contextmanager def _CreateIncompleteService(): """Provides a servicer backend that fails to implement methods and its stub. The servicer is just the implementation of the actual servicer passed to the face player of the python RPC implementation; the two are detached. Args: service_pb2: The service_pb2 module generated by this test. Yields: A (servicer_methods, stub) pair where servicer_methods is the back-end of the service bound to the stub and and stub is the stub on which to invoke RPCs. """ class Servicer(getattr(service_pb2, SERVICER_IDENTIFIER)): pass servicer = Servicer() server = getattr(service_pb2, SERVER_FACTORY_IDENTIFIER)(servicer) port = server.add_insecure_port('[::]:0') server.start() channel = implementations.insecure_channel('localhost', port) stub = getattr(service_pb2, STUB_FACTORY_IDENTIFIER)(channel) yield None, stub server.stop(0) def _streaming_input_request_iterator(): for _ in range(3): request = request_pb2.StreamingInputCallRequest() request.payload.payload_type = payload_pb2.COMPRESSABLE request.payload.payload_compressable = 'a' yield request def _streaming_output_request(): request = request_pb2.StreamingOutputCallRequest() sizes = [1, 2, 3] request.response_parameters.add(size=sizes[0], interval_us=0) request.response_parameters.add(size=sizes[1], interval_us=0) request.response_parameters.add(size=sizes[2], interval_us=0) return request def _full_duplex_request_iterator(): request = request_pb2.StreamingOutputCallRequest() request.response_parameters.add(size=1, interval_us=0) yield request request = request_pb2.StreamingOutputCallRequest() request.response_parameters.add(size=2, interval_us=0) request.response_parameters.add(size=3, interval_us=0) yield request class PythonPluginTest(unittest.TestCase): """Test case for the gRPC Python protoc-plugin. While reading these tests, remember that the futures API (`stub.method.future()`) only gives futures for the *response-unary* methods and does not exist for response-streaming methods. """ def testImportAttributes(self): # check that we can access the generated module and its members. self.assertIsNotNone(getattr(service_pb2, SERVICER_IDENTIFIER, None)) self.assertIsNotNone(getattr(service_pb2, STUB_IDENTIFIER, None)) self.assertIsNotNone( getattr(service_pb2, SERVER_FACTORY_IDENTIFIER, None)) self.assertIsNotNone( getattr(service_pb2, STUB_FACTORY_IDENTIFIER, None)) def testUpDown(self): with _CreateService(): request_pb2.SimpleRequest(response_size=13) def testIncompleteServicer(self): with _CreateIncompleteService() as (_, stub): request = request_pb2.SimpleRequest(response_size=13) try: stub.UnaryCall(request, test_constants.LONG_TIMEOUT) except face.AbortionError as error: self.assertEqual(interfaces.StatusCode.UNIMPLEMENTED, error.code) def testUnaryCall(self): with _CreateService() as (methods, stub): request = request_pb2.SimpleRequest(response_size=13) response = stub.UnaryCall(request, test_constants.LONG_TIMEOUT) expected_response = methods.UnaryCall(request, 'not a real context!') self.assertEqual(expected_response, response) def testUnaryCallFuture(self): with _CreateService() as (methods, stub): request = request_pb2.SimpleRequest(response_size=13) # Check that the call does not block waiting for the server to respond. with methods.pause(): response_future = stub.UnaryCall.future( request, test_constants.LONG_TIMEOUT) response = response_future.result() expected_response = methods.UnaryCall(request, 'not a real RpcContext!') self.assertEqual(expected_response, response) def testUnaryCallFutureExpired(self): with _CreateService() as (methods, stub): request = request_pb2.SimpleRequest(response_size=13) with methods.pause(): response_future = stub.UnaryCall.future( request, test_constants.SHORT_TIMEOUT) with self.assertRaises(face.ExpirationError): response_future.result() def testUnaryCallFutureCancelled(self): with _CreateService() as (methods, stub): request = request_pb2.SimpleRequest(response_size=13) with methods.pause(): response_future = stub.UnaryCall.future(request, 1) response_future.cancel() self.assertTrue(response_future.cancelled()) def testUnaryCallFutureFailed(self): with _CreateService() as (methods, stub): request = request_pb2.SimpleRequest(response_size=13) with methods.fail(): response_future = stub.UnaryCall.future( request, test_constants.LONG_TIMEOUT) self.assertIsNotNone(response_future.exception()) def testStreamingOutputCall(self): with _CreateService() as (methods, stub): request = _streaming_output_request() responses = stub.StreamingOutputCall(request, test_constants.LONG_TIMEOUT) expected_responses = methods.StreamingOutputCall( request, 'not a real RpcContext!') for expected_response, response in moves.zip_longest( expected_responses, responses): self.assertEqual(expected_response, response) def testStreamingOutputCallExpired(self): with _CreateService() as (methods, stub): request = _streaming_output_request() with methods.pause(): responses = stub.StreamingOutputCall( request, test_constants.SHORT_TIMEOUT) with self.assertRaises(face.ExpirationError): list(responses) def testStreamingOutputCallCancelled(self): with _CreateService() as (methods, stub): request = _streaming_output_request() responses = stub.StreamingOutputCall(request, test_constants.LONG_TIMEOUT) next(responses) responses.cancel() with self.assertRaises(face.CancellationError): next(responses) def testStreamingOutputCallFailed(self): with _CreateService() as (methods, stub): request = _streaming_output_request() with methods.fail(): responses = stub.StreamingOutputCall(request, 1) self.assertIsNotNone(responses) with self.assertRaises(face.RemoteError): next(responses) def testStreamingInputCall(self): with _CreateService() as (methods, stub): response = stub.StreamingInputCall( _streaming_input_request_iterator(), test_constants.LONG_TIMEOUT) expected_response = methods.StreamingInputCall( _streaming_input_request_iterator(), 'not a real RpcContext!') self.assertEqual(expected_response, response) def testStreamingInputCallFuture(self): with _CreateService() as (methods, stub): with methods.pause(): response_future = stub.StreamingInputCall.future( _streaming_input_request_iterator(), test_constants.LONG_TIMEOUT) response = response_future.result() expected_response = methods.StreamingInputCall( _streaming_input_request_iterator(), 'not a real RpcContext!') self.assertEqual(expected_response, response) def testStreamingInputCallFutureExpired(self): with _CreateService() as (methods, stub): with methods.pause(): response_future = stub.StreamingInputCall.future( _streaming_input_request_iterator(), test_constants.SHORT_TIMEOUT) with self.assertRaises(face.ExpirationError): response_future.result() self.assertIsInstance(response_future.exception(), face.ExpirationError) def testStreamingInputCallFutureCancelled(self): with _CreateService() as (methods, stub): with methods.pause(): response_future = stub.StreamingInputCall.future( _streaming_input_request_iterator(), test_constants.LONG_TIMEOUT) response_future.cancel() self.assertTrue(response_future.cancelled()) with self.assertRaises(future.CancelledError): response_future.result() def testStreamingInputCallFutureFailed(self): with _CreateService() as (methods, stub): with methods.fail(): response_future = stub.StreamingInputCall.future( _streaming_input_request_iterator(), test_constants.LONG_TIMEOUT) self.assertIsNotNone(response_future.exception()) def testFullDuplexCall(self): with _CreateService() as (methods, stub): responses = stub.FullDuplexCall(_full_duplex_request_iterator(), test_constants.LONG_TIMEOUT) expected_responses = methods.FullDuplexCall( _full_duplex_request_iterator(), 'not a real RpcContext!') for expected_response, response in moves.zip_longest( expected_responses, responses): self.assertEqual(expected_response, response) def testFullDuplexCallExpired(self): request_iterator = _full_duplex_request_iterator() with _CreateService() as (methods, stub): with methods.pause(): responses = stub.FullDuplexCall(request_iterator, test_constants.SHORT_TIMEOUT) with self.assertRaises(face.ExpirationError): list(responses) def testFullDuplexCallCancelled(self): with _CreateService() as (methods, stub): request_iterator = _full_duplex_request_iterator() responses = stub.FullDuplexCall(request_iterator, test_constants.LONG_TIMEOUT) next(responses) responses.cancel() with self.assertRaises(face.CancellationError): next(responses) def testFullDuplexCallFailed(self): request_iterator = _full_duplex_request_iterator() with _CreateService() as (methods, stub): with methods.fail(): responses = stub.FullDuplexCall(request_iterator, test_constants.LONG_TIMEOUT) self.assertIsNotNone(responses) with self.assertRaises(face.RemoteError): next(responses) def testHalfDuplexCall(self): with _CreateService() as (methods, stub): def half_duplex_request_iterator(): request = request_pb2.StreamingOutputCallRequest() request.response_parameters.add(size=1, interval_us=0) yield request request = request_pb2.StreamingOutputCallRequest() request.response_parameters.add(size=2, interval_us=0) request.response_parameters.add(size=3, interval_us=0) yield request responses = stub.HalfDuplexCall(half_duplex_request_iterator(), test_constants.LONG_TIMEOUT) expected_responses = methods.HalfDuplexCall( half_duplex_request_iterator(), 'not a real RpcContext!') for check in moves.zip_longest(expected_responses, responses): expected_response, response = check self.assertEqual(expected_response, response) def testHalfDuplexCallWedged(self): condition = threading.Condition() wait_cell = [False] @contextlib.contextmanager def wait(): # pylint: disable=invalid-name # Where's Python 3's 'nonlocal' statement when you need it? with condition: wait_cell[0] = True yield with condition: wait_cell[0] = False condition.notify_all() def half_duplex_request_iterator(): request = request_pb2.StreamingOutputCallRequest() request.response_parameters.add(size=1, interval_us=0) yield request with condition: while wait_cell[0]: condition.wait() with _CreateService() as (methods, stub): with wait(): responses = stub.HalfDuplexCall(half_duplex_request_iterator(), test_constants.SHORT_TIMEOUT) # half-duplex waits for the client to send all info with self.assertRaises(face.ExpirationError): next(responses) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/000077500000000000000000000000001310511640000246305ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/__init__.py000066400000000000000000000027701310511640000267470ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/000077500000000000000000000000001310511640000305365ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/__init__.py000066400000000000000000000027701310511640000326550ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/same.proto000066400000000000000000000033011310511640000325450ustar00rootroot00000000000000// Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package grpc_protoc_plugin.invocation_testing; message Request {} message Response {} service TestService { rpc Call(Request) returns (Response); } grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_messages/000077500000000000000000000000001310511640000335605ustar00rootroot00000000000000__init__.py000066400000000000000000000027701310511640000356200ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_messages# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. messages.proto000066400000000000000000000032061310511640000363760ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_messages// Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package grpc_protoc_plugin.invocation_testing.split; message Request {} message Response {} grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_services/000077500000000000000000000000001310511640000335745ustar00rootroot00000000000000__init__.py000066400000000000000000000027701310511640000356340ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_services# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. services.proto000066400000000000000000000032711310511640000364300ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_services// Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; import "messages.proto"; package grpc_protoc_plugin.invocation_testing.split; service TestService { rpc Call(Request) returns (Response); } grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/payload/000077500000000000000000000000001310511640000262615ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/payload/__init__.py000066400000000000000000000027701310511640000304000ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/payload/test_payload.proto000066400000000000000000000036631310511640000320460ustar00rootroot00000000000000// Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package grpc_protoc_plugin; enum PayloadType { // Compressable text format. COMPRESSABLE= 0; // Uncompressable binary format. UNCOMPRESSABLE = 1; // Randomly chosen from all other formats defined in this enum. RANDOM = 2; } message Payload { PayloadType payload_type = 1; oneof payload_body { string payload_compressable = 2; bytes payload_uncompressable = 3; } } grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/requests/000077500000000000000000000000001310511640000265035ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/requests/__init__.py000066400000000000000000000027701310511640000306220ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/requests/r/000077500000000000000000000000001310511640000267445ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/requests/r/__init__.py000066400000000000000000000027701310511640000310630ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/requests/r/test_requests.proto000066400000000000000000000057031310511640000327500ustar00rootroot00000000000000// Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; import "tests/protoc_plugin/protos/payload/test_payload.proto"; package grpc_protoc_plugin; message SimpleRequest { // Desired payload type in the response from the server. // If response_type is RANDOM, server randomly chooses one from other formats. PayloadType response_type = 1; // Desired payload size in the response from the server. // If response_type is COMPRESSABLE, this denotes the size before compression. int32 response_size = 2; // input payload sent along with the request. Payload payload = 3; } message StreamingInputCallRequest { // input payload sent along with the request. Payload payload = 1; // Not expecting any payload from the response. } message ResponseParameters { // Desired payload sizes in responses from the server. // If response_type is COMPRESSABLE, this denotes the size before compression. int32 size = 1; // Desired interval between consecutive responses in the response stream in // microseconds. int32 interval_us = 2; } message StreamingOutputCallRequest { // Desired payload type in the response from the server. // If response_type is RANDOM, the payload from each response in the stream // might be of different types. This is to simulate a mixed type of payload // stream. PayloadType response_type = 1; repeated ResponseParameters response_parameters = 2; // input payload sent along with the request. Payload payload = 3; } grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/responses/000077500000000000000000000000001310511640000266515ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/responses/__init__.py000066400000000000000000000027701310511640000307700ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/responses/test_responses.proto000066400000000000000000000036011310511640000330160ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; import "tests/protoc_plugin/protos/payload/test_payload.proto"; package grpc_protoc_plugin; message SimpleResponse { Payload payload = 1; } message StreamingInputCallResponse { // Aggregated size of payloads received from the client. int32 aggregated_payload_size = 1; } message StreamingOutputCallResponse { Payload payload = 1; } grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/service/000077500000000000000000000000001310511640000262705ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/service/__init__.py000066400000000000000000000027701310511640000304070ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/protoc_plugin/protos/service/test_service.proto000066400000000000000000000060121310511640000320530ustar00rootroot00000000000000// Copyright 2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; import "tests/protoc_plugin/protos/requests/r/test_requests.proto"; import "tests/protoc_plugin/protos/responses/test_responses.proto"; package grpc_protoc_plugin; service TestService { // One request followed by one response. // The server returns the client payload as-is. rpc UnaryCall(SimpleRequest) returns (SimpleResponse); // One request followed by a sequence of responses (streamed download). // The server returns the payload with client desired type and sizes. rpc StreamingOutputCall(StreamingOutputCallRequest) returns (stream StreamingOutputCallResponse); // A sequence of requests followed by one response (streamed upload). // The server returns the aggregated size of client payload as the result. rpc StreamingInputCall(stream StreamingInputCallRequest) returns (StreamingInputCallResponse); // A sequence of requests with each request served by the server immediately. // As one request could lead to multiple responses, this interface // demonstrates the idea of full duplexing. rpc FullDuplexCall(stream StreamingOutputCallRequest) returns (stream StreamingOutputCallResponse); // A sequence of requests followed by a sequence of responses. // The server buffers all the client requests and then serves them in order. A // stream of responses are returned to the client when the server starts with // first request. rpc HalfDuplexCall(stream StreamingOutputCallRequest) returns (stream StreamingOutputCallResponse); } grpc-1.3.2/src/python/grpcio_tests/tests/qps/000077500000000000000000000000001310511640000212215ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/qps/__init__.py000066400000000000000000000027701310511640000233400ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/qps/benchmark_client.py000066400000000000000000000170251310511640000250700ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Defines test client behaviors (UNARY/STREAMING) (SYNC/ASYNC).""" import abc import threading import time from concurrent import futures from six.moves import queue import grpc from src.proto.grpc.testing import messages_pb2 from src.proto.grpc.testing import services_pb2 from tests.unit import resources from tests.unit import test_common _TIMEOUT = 60 * 60 * 24 class GenericStub(object): def __init__(self, channel): self.UnaryCall = channel.unary_unary( '/grpc.testing.BenchmarkService/UnaryCall') self.StreamingCall = channel.stream_stream( '/grpc.testing.BenchmarkService/StreamingCall') class BenchmarkClient: """Benchmark client interface that exposes a non-blocking send_request().""" __metaclass__ = abc.ABCMeta def __init__(self, server, config, hist): # Create the stub if config.HasField('security_params'): creds = grpc.ssl_channel_credentials( resources.test_root_certificates()) channel = test_common.test_secure_channel( server, creds, config.security_params.server_host_override) else: channel = grpc.insecure_channel(server) # waits for the channel to be ready before we start sending messages grpc.channel_ready_future(channel).result() if config.payload_config.WhichOneof('payload') == 'simple_params': self._generic = False self._stub = services_pb2.BenchmarkServiceStub(channel) payload = messages_pb2.Payload( body='\0' * config.payload_config.simple_params.req_size) self._request = messages_pb2.SimpleRequest( payload=payload, response_size=config.payload_config.simple_params.resp_size) else: self._generic = True self._stub = GenericStub(channel) self._request = '\0' * config.payload_config.bytebuf_params.req_size self._hist = hist self._response_callbacks = [] def add_response_callback(self, callback): """callback will be invoked as callback(client, query_time)""" self._response_callbacks.append(callback) @abc.abstractmethod def send_request(self): """Non-blocking wrapper for a client's request operation.""" raise NotImplementedError() def start(self): pass def stop(self): pass def _handle_response(self, client, query_time): self._hist.add(query_time * 1e9) # Report times in nanoseconds for callback in self._response_callbacks: callback(client, query_time) class UnarySyncBenchmarkClient(BenchmarkClient): def __init__(self, server, config, hist): super(UnarySyncBenchmarkClient, self).__init__(server, config, hist) self._pool = futures.ThreadPoolExecutor( max_workers=config.outstanding_rpcs_per_channel) def send_request(self): # Send requests in seperate threads to support multiple outstanding rpcs # (See src/proto/grpc/testing/control.proto) self._pool.submit(self._dispatch_request) def stop(self): self._pool.shutdown(wait=True) self._stub = None def _dispatch_request(self): start_time = time.time() self._stub.UnaryCall(self._request, _TIMEOUT) end_time = time.time() self._handle_response(self, end_time - start_time) class UnaryAsyncBenchmarkClient(BenchmarkClient): def send_request(self): # Use the Future callback api to support multiple outstanding rpcs start_time = time.time() response_future = self._stub.UnaryCall.future(self._request, _TIMEOUT) response_future.add_done_callback( lambda resp: self._response_received(start_time, resp)) def _response_received(self, start_time, resp): resp.result() end_time = time.time() self._handle_response(self, end_time - start_time) def stop(self): self._stub = None class _SyncStream(object): def __init__(self, stub, generic, request, handle_response): self._stub = stub self._generic = generic self._request = request self._handle_response = handle_response self._is_streaming = False self._request_queue = queue.Queue() self._send_time_queue = queue.Queue() def send_request(self): self._send_time_queue.put(time.time()) self._request_queue.put(self._request) def start(self): self._is_streaming = True response_stream = self._stub.StreamingCall(self._request_generator(), _TIMEOUT) for _ in response_stream: self._handle_response( self, time.time() - self._send_time_queue.get_nowait()) def stop(self): self._is_streaming = False def _request_generator(self): while self._is_streaming: try: request = self._request_queue.get(block=True, timeout=1.0) yield request except queue.Empty: pass class StreamingSyncBenchmarkClient(BenchmarkClient): def __init__(self, server, config, hist): super(StreamingSyncBenchmarkClient, self).__init__(server, config, hist) self._pool = futures.ThreadPoolExecutor( max_workers=config.outstanding_rpcs_per_channel) self._streams = [ _SyncStream(self._stub, self._generic, self._request, self._handle_response) for _ in xrange(config.outstanding_rpcs_per_channel) ] self._curr_stream = 0 def send_request(self): # Use a round_robin scheduler to determine what stream to send on self._streams[self._curr_stream].send_request() self._curr_stream = (self._curr_stream + 1) % len(self._streams) def start(self): for stream in self._streams: self._pool.submit(stream.start) def stop(self): for stream in self._streams: stream.stop() self._pool.shutdown(wait=True) self._stub = None grpc-1.3.2/src/python/grpcio_tests/tests/qps/benchmark_server.py000066400000000000000000000050461310511640000251200ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from src.proto.grpc.testing import messages_pb2 from src.proto.grpc.testing import services_pb2 class BenchmarkServer(services_pb2.BenchmarkServiceServicer): """Synchronous Server implementation for the Benchmark service.""" def UnaryCall(self, request, context): payload = messages_pb2.Payload(body='\0' * request.response_size) return messages_pb2.SimpleResponse(payload=payload) def StreamingCall(self, request_iterator, context): for request in request_iterator: payload = messages_pb2.Payload(body='\0' * request.response_size) yield messages_pb2.SimpleResponse(payload=payload) class GenericBenchmarkServer(services_pb2.BenchmarkServiceServicer): """Generic Server implementation for the Benchmark service.""" def __init__(self, resp_size): self._response = '\0' * resp_size def UnaryCall(self, request, context): return self._response def StreamingCall(self, request_iterator, context): for request in request_iterator: yield self._response grpc-1.3.2/src/python/grpcio_tests/tests/qps/client_runner.py000066400000000000000000000070641310511640000244510ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Defines behavior for WHEN clients send requests. Each client exposes a non-blocking send_request() method that the ClientRunner invokes either periodically or in response to some event. """ import abc import threading import time class ClientRunner: """Abstract interface for sending requests from clients.""" __metaclass__ = abc.ABCMeta def __init__(self, client): self._client = client @abc.abstractmethod def start(self): raise NotImplementedError() @abc.abstractmethod def stop(self): raise NotImplementedError() class OpenLoopClientRunner(ClientRunner): def __init__(self, client, interval_generator): super(OpenLoopClientRunner, self).__init__(client) self._is_running = False self._interval_generator = interval_generator self._dispatch_thread = threading.Thread( target=self._dispatch_requests, args=()) def start(self): self._is_running = True self._client.start() self._dispatch_thread.start() def stop(self): self._is_running = False self._client.stop() self._dispatch_thread.join() self._client = None def _dispatch_requests(self): while self._is_running: self._client.send_request() time.sleep(next(self._interval_generator)) class ClosedLoopClientRunner(ClientRunner): def __init__(self, client, request_count): super(ClosedLoopClientRunner, self).__init__(client) self._is_running = False self._request_count = request_count # Send a new request on each response for closed loop self._client.add_response_callback(self._send_request) def start(self): self._is_running = True self._client.start() for _ in xrange(self._request_count): self._client.send_request() def stop(self): self._is_running = False self._client.stop() self._client = None def _send_request(self, client, response_time): if self._is_running: client.send_request() grpc-1.3.2/src/python/grpcio_tests/tests/qps/histogram.py000066400000000000000000000062471310511640000236010ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import math import threading from src.proto.grpc.testing import stats_pb2 class Histogram(object): """Histogram class used for recording performance testing data. This class is thread safe. """ def __init__(self, resolution, max_possible): self._lock = threading.Lock() self._resolution = resolution self._max_possible = max_possible self._sum = 0 self._sum_of_squares = 0 self.multiplier = 1.0 + self._resolution self._count = 0 self._min = self._max_possible self._max = 0 self._buckets = [0] * (self._bucket_for(self._max_possible) + 1) def reset(self): with self._lock: self._sum = 0 self._sum_of_squares = 0 self._count = 0 self._min = self._max_possible self._max = 0 self._buckets = [0] * (self._bucket_for(self._max_possible) + 1) def add(self, val): with self._lock: self._sum += val self._sum_of_squares += val * val self._count += 1 self._min = min(self._min, val) self._max = max(self._max, val) self._buckets[self._bucket_for(val)] += 1 def get_data(self): with self._lock: data = stats_pb2.HistogramData() data.bucket.extend(self._buckets) data.min_seen = self._min data.max_seen = self._max data.sum = self._sum data.sum_of_squares = self._sum_of_squares data.count = self._count return data def _bucket_for(self, val): val = min(val, self._max_possible) return int(math.log(val, self.multiplier)) grpc-1.3.2/src/python/grpcio_tests/tests/qps/qps_worker.py000066400000000000000000000045501310511640000237730ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """The entry point for the qps worker.""" import argparse import time from concurrent import futures import grpc from src.proto.grpc.testing import services_pb2_grpc from tests.qps import worker_server def run_worker_server(port): server = grpc.server(futures.ThreadPoolExecutor(max_workers=5)) servicer = worker_server.WorkerServer() services_pb2_grpc.add_WorkerServiceServicer_to_server(servicer, server) server.add_insecure_port('[::]:{}'.format(port)) server.start() servicer.wait_for_quit() server.stop(0) if __name__ == '__main__': parser = argparse.ArgumentParser( description='gRPC Python performance testing worker') parser.add_argument( '--driver_port', type=int, dest='port', help='The port the worker should listen on') args = parser.parse_args() run_worker_server(args.port) grpc-1.3.2/src/python/grpcio_tests/tests/qps/worker_server.py000066400000000000000000000203661310511640000245010ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import multiprocessing import random import threading import time from concurrent import futures import grpc from src.proto.grpc.testing import control_pb2 from src.proto.grpc.testing import services_pb2_grpc from src.proto.grpc.testing import stats_pb2 from tests.qps import benchmark_client from tests.qps import benchmark_server from tests.qps import client_runner from tests.qps import histogram from tests.unit import resources class WorkerServer(services_pb2_grpc.WorkerServiceServicer): """Python Worker Server implementation.""" def __init__(self): self._quit_event = threading.Event() def RunServer(self, request_iterator, context): config = next(request_iterator).setup server, port = self._create_server(config) cores = multiprocessing.cpu_count() server.start() start_time = time.time() yield self._get_server_status(start_time, start_time, port, cores) for request in request_iterator: end_time = time.time() status = self._get_server_status(start_time, end_time, port, cores) if request.mark.reset: start_time = end_time yield status server.stop(None) def _get_server_status(self, start_time, end_time, port, cores): end_time = time.time() elapsed_time = end_time - start_time stats = stats_pb2.ServerStats( time_elapsed=elapsed_time, time_user=elapsed_time, time_system=elapsed_time) return control_pb2.ServerStatus(stats=stats, port=port, cores=cores) def _create_server(self, config): if config.async_server_threads == 0: # This is the default concurrent.futures thread pool size, but # None doesn't seem to work server_threads = multiprocessing.cpu_count() * 5 else: server_threads = config.async_server_threads server = grpc.server( futures.ThreadPoolExecutor(max_workers=server_threads)) if config.server_type == control_pb2.ASYNC_SERVER: servicer = benchmark_server.BenchmarkServer() services_pb2_grpc.add_BenchmarkServiceServicer_to_server(servicer, server) elif config.server_type == control_pb2.ASYNC_GENERIC_SERVER: resp_size = config.payload_config.bytebuf_params.resp_size servicer = benchmark_server.GenericBenchmarkServer(resp_size) method_implementations = { 'StreamingCall': grpc.stream_stream_rpc_method_handler(servicer.StreamingCall), 'UnaryCall': grpc.unary_unary_rpc_method_handler(servicer.UnaryCall), } handler = grpc.method_handlers_generic_handler( 'grpc.testing.BenchmarkService', method_implementations) server.add_generic_rpc_handlers((handler,)) else: raise Exception( 'Unsupported server type {}'.format(config.server_type)) if config.HasField('security_params'): # Use SSL server_creds = grpc.ssl_server_credentials(( (resources.private_key(), resources.certificate_chain()),)) port = server.add_secure_port('[::]:{}'.format(config.port), server_creds) else: port = server.add_insecure_port('[::]:{}'.format(config.port)) return (server, port) def RunClient(self, request_iterator, context): config = next(request_iterator).setup client_runners = [] qps_data = histogram.Histogram(config.histogram_params.resolution, config.histogram_params.max_possible) start_time = time.time() # Create a client for each channel for i in xrange(config.client_channels): server = config.server_targets[i % len(config.server_targets)] runner = self._create_client_runner(server, config, qps_data) client_runners.append(runner) runner.start() end_time = time.time() yield self._get_client_status(start_time, end_time, qps_data) # Respond to stat requests for request in request_iterator: end_time = time.time() status = self._get_client_status(start_time, end_time, qps_data) if request.mark.reset: qps_data.reset() start_time = time.time() yield status # Cleanup the clients for runner in client_runners: runner.stop() def _get_client_status(self, start_time, end_time, qps_data): latencies = qps_data.get_data() end_time = time.time() elapsed_time = end_time - start_time stats = stats_pb2.ClientStats( latencies=latencies, time_elapsed=elapsed_time, time_user=elapsed_time, time_system=elapsed_time) return control_pb2.ClientStatus(stats=stats) def _create_client_runner(self, server, config, qps_data): if config.client_type == control_pb2.SYNC_CLIENT: if config.rpc_type == control_pb2.UNARY: client = benchmark_client.UnarySyncBenchmarkClient( server, config, qps_data) elif config.rpc_type == control_pb2.STREAMING: client = benchmark_client.StreamingSyncBenchmarkClient( server, config, qps_data) elif config.client_type == control_pb2.ASYNC_CLIENT: if config.rpc_type == control_pb2.UNARY: client = benchmark_client.UnaryAsyncBenchmarkClient( server, config, qps_data) else: raise Exception('Async streaming client not supported') else: raise Exception( 'Unsupported client type {}'.format(config.client_type)) # In multi-channel tests, we split the load across all channels load_factor = float(config.client_channels) if config.load_params.WhichOneof('load') == 'closed_loop': runner = client_runner.ClosedLoopClientRunner( client, config.outstanding_rpcs_per_channel) else: # Open loop Poisson alpha = config.load_params.poisson.offered_load / load_factor def poisson(): while True: yield random.expovariate(alpha) runner = client_runner.OpenLoopClientRunner(client, poisson()) return runner def CoreCount(self, request, context): return control_pb2.CoreResponse(cores=multiprocessing.cpu_count()) def QuitWorker(self, request, context): self._quit_event.set() return control_pb2.Void() def wait_for_quit(self): self._quit_event.wait() grpc-1.3.2/src/python/grpcio_tests/tests/reflection/000077500000000000000000000000001310511640000225505ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/reflection/__init__.py000066400000000000000000000027701310511640000246670ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py000066400000000000000000000207251310511640000303620ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Tests of grpc_reflection.v1alpha.reflection.""" import unittest import grpc from grpc.framework.foundation import logging_pool from grpc_reflection.v1alpha import reflection from grpc_reflection.v1alpha import reflection_pb2 from grpc_reflection.v1alpha import reflection_pb2_grpc from google.protobuf import descriptor_pool from google.protobuf import descriptor_pb2 from src.proto.grpc.testing import empty_pb2 #empty2_pb2 is imported for import-consequent side-effects. from src.proto.grpc.testing.proto2 import empty2_pb2 # pylint: disable=unused-import from src.proto.grpc.testing.proto2 import empty2_extensions_pb2 from tests.unit.framework.common import test_constants _EMPTY_PROTO_FILE_NAME = 'src/proto/grpc/testing/empty.proto' _EMPTY_PROTO_SYMBOL_NAME = 'grpc.testing.Empty' _SERVICE_NAMES = ('Angstrom', 'Bohr', 'Curie', 'Dyson', 'Einstein', 'Feynman', 'Galilei') _EMPTY_EXTENSIONS_SYMBOL_NAME = 'grpc.testing.proto2.EmptyWithExtensions' _EMPTY_EXTENSIONS_NUMBERS = (124, 125, 126, 127, 128,) def _file_descriptor_to_proto(descriptor): proto = descriptor_pb2.FileDescriptorProto() descriptor.CopyToProto(proto) return proto.SerializeToString() class ReflectionServicerTest(unittest.TestCase): def setUp(self): servicer = reflection.ReflectionServicer(service_names=_SERVICE_NAMES) server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) self._server = grpc.server(server_pool) port = self._server.add_insecure_port('[::]:0') reflection_pb2_grpc.add_ServerReflectionServicer_to_server(servicer, self._server) self._server.start() channel = grpc.insecure_channel('localhost:%d' % port) self._stub = reflection_pb2_grpc.ServerReflectionStub(channel) def testFileByName(self): requests = (reflection_pb2.ServerReflectionRequest( file_by_filename=_EMPTY_PROTO_FILE_NAME), reflection_pb2.ServerReflectionRequest( file_by_filename='i-donut-exist'),) responses = tuple(self._stub.ServerReflectionInfo(iter(requests))) expected_responses = ( reflection_pb2.ServerReflectionResponse( valid_host='', file_descriptor_response=reflection_pb2.FileDescriptorResponse( file_descriptor_proto=( _file_descriptor_to_proto(empty_pb2.DESCRIPTOR),))), reflection_pb2.ServerReflectionResponse( valid_host='', error_response=reflection_pb2.ErrorResponse( error_code=grpc.StatusCode.NOT_FOUND.value[0], error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), )),) self.assertSequenceEqual(expected_responses, responses) def testFileBySymbol(self): requests = (reflection_pb2.ServerReflectionRequest( file_containing_symbol=_EMPTY_PROTO_SYMBOL_NAME ), reflection_pb2.ServerReflectionRequest( file_containing_symbol='i.donut.exist.co.uk.org.net.me.name.foo'),) responses = tuple(self._stub.ServerReflectionInfo(iter(requests))) expected_responses = ( reflection_pb2.ServerReflectionResponse( valid_host='', file_descriptor_response=reflection_pb2.FileDescriptorResponse( file_descriptor_proto=( _file_descriptor_to_proto(empty_pb2.DESCRIPTOR),))), reflection_pb2.ServerReflectionResponse( valid_host='', error_response=reflection_pb2.ErrorResponse( error_code=grpc.StatusCode.NOT_FOUND.value[0], error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), )),) self.assertSequenceEqual(expected_responses, responses) @unittest.skip( 'TODO(mmx): enable when (pure) python protobuf issue is fixed' '(see https://github.com/google/protobuf/issues/2882)') def testFileContainingExtension(self): requests = (reflection_pb2.ServerReflectionRequest( file_containing_extension=reflection_pb2.ExtensionRequest( containing_type=_EMPTY_EXTENSIONS_SYMBOL_NAME, extension_number=125,), ), reflection_pb2.ServerReflectionRequest( file_containing_extension=reflection_pb2.ExtensionRequest( containing_type='i.donut.exist.co.uk.org.net.me.name.foo', extension_number=55,),),) responses = tuple(self._stub.ServerReflectionInfo(iter(requests))) expected_responses = ( reflection_pb2.ServerReflectionResponse( valid_host='', file_descriptor_response=reflection_pb2.FileDescriptorResponse( file_descriptor_proto=(_file_descriptor_to_proto( empty2_extensions_pb2.DESCRIPTOR),))), reflection_pb2.ServerReflectionResponse( valid_host='', error_response=reflection_pb2.ErrorResponse( error_code=grpc.StatusCode.NOT_FOUND.value[0], error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), )),) self.assertSequenceEqual(expected_responses, responses) def testExtensionNumbersOfType(self): requests = (reflection_pb2.ServerReflectionRequest( all_extension_numbers_of_type=_EMPTY_EXTENSIONS_SYMBOL_NAME ), reflection_pb2.ServerReflectionRequest( all_extension_numbers_of_type='i.donut.exist.co.uk.net.name.foo'),) responses = tuple(self._stub.ServerReflectionInfo(iter(requests))) expected_responses = ( reflection_pb2.ServerReflectionResponse( valid_host='', all_extension_numbers_response=reflection_pb2. ExtensionNumberResponse( base_type_name=_EMPTY_EXTENSIONS_SYMBOL_NAME, extension_number=_EMPTY_EXTENSIONS_NUMBERS)), reflection_pb2.ServerReflectionResponse( valid_host='', error_response=reflection_pb2.ErrorResponse( error_code=grpc.StatusCode.NOT_FOUND.value[0], error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), )),) self.assertSequenceEqual(expected_responses, responses) def testListServices(self): requests = (reflection_pb2.ServerReflectionRequest( list_services='',),) responses = tuple(self._stub.ServerReflectionInfo(iter(requests))) expected_responses = (reflection_pb2.ServerReflectionResponse( valid_host='', list_services_response=reflection_pb2.ListServiceResponse( service=tuple( reflection_pb2.ServiceResponse(name=name) for name in _SERVICE_NAMES))),) self.assertSequenceEqual(expected_responses, responses) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/stress/000077500000000000000000000000001310511640000217415ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/stress/__init__.py000066400000000000000000000027701310511640000240600ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/stress/client.py000066400000000000000000000142641310511640000236000ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Entry point for running stress tests.""" import argparse from concurrent import futures import threading import grpc from six.moves import queue from src.proto.grpc.testing import metrics_pb2_grpc from src.proto.grpc.testing import test_pb2 from tests.interop import methods from tests.interop import resources from tests.qps import histogram from tests.stress import metrics_server from tests.stress import test_runner def _args(): parser = argparse.ArgumentParser( description='gRPC Python stress test client') parser.add_argument( '--server_addresses', help='comma seperated list of hostname:port to run servers on', default='localhost:8080', type=str) parser.add_argument( '--test_cases', help='comma seperated list of testcase:weighting of tests to run', default='large_unary:100', type=str) parser.add_argument( '--test_duration_secs', help='number of seconds to run the stress test', default=-1, type=int) parser.add_argument( '--num_channels_per_server', help='number of channels per server', default=1, type=int) parser.add_argument( '--num_stubs_per_channel', help='number of stubs to create per channel', default=1, type=int) parser.add_argument( '--metrics_port', help='the port to listen for metrics requests on', default=8081, type=int) parser.add_argument( '--use_test_ca', help='Whether to use our fake CA. Requires --use_tls=true', default=False, type=bool) parser.add_argument( '--use_tls', help='Whether to use TLS', default=False, type=bool) parser.add_argument( '--server_host_override', default="foo.test.google.fr", help='the server host to which to claim to connect', type=str) return parser.parse_args() def _test_case_from_arg(test_case_arg): for test_case in methods.TestCase: if test_case_arg == test_case.value: return test_case else: raise ValueError('No test case {}!'.format(test_case_arg)) def _parse_weighted_test_cases(test_case_args): weighted_test_cases = {} for test_case_arg in test_case_args.split(','): name, weight = test_case_arg.split(':', 1) test_case = _test_case_from_arg(name) weighted_test_cases[test_case] = int(weight) return weighted_test_cases def _get_channel(target, args): if args.use_tls: if args.use_test_ca: root_certificates = resources.test_root_certificates() else: root_certificates = None # will load default roots. channel_credentials = grpc.ssl_channel_credentials( root_certificates=root_certificates) options = (('grpc.ssl_target_name_override', args.server_host_override,),) channel = grpc.secure_channel( target, channel_credentials, options=options) else: channel = grpc.insecure_channel(target) # waits for the channel to be ready before we start sending messages grpc.channel_ready_future(channel).result() return channel def run_test(args): test_cases = _parse_weighted_test_cases(args.test_cases) test_server_targets = args.server_addresses.split(',') # Propagate any client exceptions with a queue exception_queue = queue.Queue() stop_event = threading.Event() hist = histogram.Histogram(1, 1) runners = [] server = grpc.server(futures.ThreadPoolExecutor(max_workers=25)) metrics_pb2_grpc.add_MetricsServiceServicer_to_server( metrics_server.MetricsServer(hist), server) server.add_insecure_port('[::]:{}'.format(args.metrics_port)) server.start() for test_server_target in test_server_targets: for _ in xrange(args.num_channels_per_server): channel = _get_channel(test_server_target, args) for _ in xrange(args.num_stubs_per_channel): stub = test_pb2.TestServiceStub(channel) runner = test_runner.TestRunner(stub, test_cases, hist, exception_queue, stop_event) runners.append(runner) for runner in runners: runner.start() try: timeout_secs = args.test_duration_secs if timeout_secs < 0: timeout_secs = None raise exception_queue.get(block=True, timeout=timeout_secs) except queue.Empty: # No exceptions thrown, success pass finally: stop_event.set() for runner in runners: runner.join() runner = None server.stop(None) if __name__ == '__main__': run_test(_args()) grpc-1.3.2/src/python/grpcio_tests/tests/stress/metrics_server.py000066400000000000000000000046751310511640000253630ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """MetricsService for publishing stress test qps data.""" import time from src.proto.grpc.testing import metrics_pb2 GAUGE_NAME = 'python_overall_qps' class MetricsServer(metrics_pb2.MetricsServiceServicer): def __init__(self, histogram): self._start_time = time.time() self._histogram = histogram def _get_qps(self): count = self._histogram.get_data().count delta = time.time() - self._start_time self._histogram.reset() self._start_time = time.time() return int(count / delta) def GetAllGauges(self, request, context): qps = self._get_qps() return [metrics_pb2.GaugeResponse(name=GAUGE_NAME, long_value=qps)] def GetGauge(self, request, context): if request.name != GAUGE_NAME: raise Exception('Gauge {} does not exist'.format(request.name)) qps = self._get_qps() return metrics_pb2.GaugeResponse(name=GAUGE_NAME, long_value=qps) grpc-1.3.2/src/python/grpcio_tests/tests/stress/test_runner.py000066400000000000000000000056341310511640000246730ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Thread that sends random weighted requests on a TestService stub.""" import random import threading import time import traceback def _weighted_test_case_generator(weighted_cases): weight_sum = sum(weighted_cases.itervalues()) while True: val = random.uniform(0, weight_sum) partial_sum = 0 for case in weighted_cases: partial_sum += weighted_cases[case] if val <= partial_sum: yield case break class TestRunner(threading.Thread): def __init__(self, stub, test_cases, hist, exception_queue, stop_event): super(TestRunner, self).__init__() self._exception_queue = exception_queue self._stop_event = stop_event self._stub = stub self._test_cases = _weighted_test_case_generator(test_cases) self._histogram = hist def run(self): while not self._stop_event.is_set(): try: test_case = next(self._test_cases) start_time = time.time() test_case.test_interoperability(self._stub, None) end_time = time.time() self._histogram.add((end_time - start_time) * 1e9) except Exception as e: traceback.print_exc() self._exception_queue.put( Exception("An exception occured during test {}" .format(test_case), e)) grpc-1.3.2/src/python/grpcio_tests/tests/tests.json000066400000000000000000000054771310511640000224700ustar00rootroot00000000000000[ "health_check._health_servicer_test.HealthServicerTest", "interop._insecure_intraop_test.InsecureIntraopTest", "interop._secure_intraop_test.SecureIntraopTest", "protoc_plugin._python_plugin_test.PythonPluginTest", "protoc_plugin._split_definitions_test.SameCommonTest", "protoc_plugin._split_definitions_test.SameSeparateTest", "protoc_plugin._split_definitions_test.SplitCommonTest", "protoc_plugin._split_definitions_test.SplitSeparateTest", "protoc_plugin.beta_python_plugin_test.PythonPluginTest", "reflection._reflection_servicer_test.ReflectionServicerTest", "unit._api_test.AllTest", "unit._api_test.ChannelConnectivityTest", "unit._api_test.ChannelTest", "unit._auth_test.AccessTokenCallCredentialsTest", "unit._auth_test.GoogleCallCredentialsTest", "unit._channel_args_test.ChannelArgsTest", "unit._channel_connectivity_test.ChannelConnectivityTest", "unit._channel_ready_future_test.ChannelReadyFutureTest", "unit._compression_test.CompressionTest", "unit._credentials_test.CredentialsTest", "unit._cython._cancel_many_calls_test.CancelManyCallsTest", "unit._cython._channel_test.ChannelTest", "unit._cython._read_some_but_not_all_responses_test.ReadSomeButNotAllResponsesTest", "unit._cython.cygrpc_test.InsecureServerInsecureClient", "unit._cython.cygrpc_test.SecureServerSecureClient", "unit._cython.cygrpc_test.TypeSmokeTest", "unit._empty_message_test.EmptyMessageTest", "unit._exit_test.ExitTest", "unit._invalid_metadata_test.InvalidMetadataTest", "unit._invocation_defects_test.InvocationDefectsTest", "unit._metadata_code_details_test.MetadataCodeDetailsTest", "unit._metadata_test.MetadataTest", "unit._resource_exhausted_test.ResourceExhaustedTest", "unit._rpc_test.RPCTest", "unit._sanity._sanity_test.Sanity", "unit._thread_cleanup_test.CleanupThreadTest", "unit.beta._beta_features_test.BetaFeaturesTest", "unit.beta._beta_features_test.ContextManagementAndLifecycleTest", "unit.beta._connectivity_channel_test.ConnectivityStatesTest", "unit.beta._face_interface_test.DynamicInvokerBlockingInvocationInlineServiceTest", "unit.beta._face_interface_test.DynamicInvokerFutureInvocationAsynchronousEventServiceTest", "unit.beta._face_interface_test.GenericInvokerBlockingInvocationInlineServiceTest", "unit.beta._face_interface_test.GenericInvokerFutureInvocationAsynchronousEventServiceTest", "unit.beta._face_interface_test.MultiCallableInvokerBlockingInvocationInlineServiceTest", "unit.beta._face_interface_test.MultiCallableInvokerFutureInvocationAsynchronousEventServiceTest", "unit.beta._implementations_test.CallCredentialsTest", "unit.beta._implementations_test.ChannelCredentialsTest", "unit.beta._not_found_test.NotFoundTest", "unit.beta._utilities_test.ChannelConnectivityTest", "unit.framework.foundation._logging_pool_test.LoggingPoolTest" ] grpc-1.3.2/src/python/grpcio_tests/tests/unit/000077500000000000000000000000001310511640000213755ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/unit/__init__.py000066400000000000000000000027701310511640000235140ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/unit/_api_test.py000066400000000000000000000071741310511640000237270ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Test of gRPC Python's application-layer API.""" import unittest import six import grpc from tests.unit import _from_grpc_import_star class AllTest(unittest.TestCase): def testAll(self): expected_grpc_code_elements = ( 'FutureTimeoutError', 'FutureCancelledError', 'Future', 'ChannelConnectivity', 'StatusCode', 'RpcError', 'RpcContext', 'Call', 'ChannelCredentials', 'CallCredentials', 'AuthMetadataContext', 'AuthMetadataPluginCallback', 'AuthMetadataPlugin', 'ServerCredentials', 'UnaryUnaryMultiCallable', 'UnaryStreamMultiCallable', 'StreamUnaryMultiCallable', 'StreamStreamMultiCallable', 'Channel', 'ServicerContext', 'RpcMethodHandler', 'HandlerCallDetails', 'GenericRpcHandler', 'ServiceRpcHandler', 'Server', 'unary_unary_rpc_method_handler', 'unary_stream_rpc_method_handler', 'stream_unary_rpc_method_handler', 'stream_stream_rpc_method_handler', 'method_handlers_generic_handler', 'ssl_channel_credentials', 'metadata_call_credentials', 'access_token_call_credentials', 'composite_call_credentials', 'composite_channel_credentials', 'ssl_server_credentials', 'channel_ready_future', 'insecure_channel', 'secure_channel', 'server',) six.assertCountEqual(self, expected_grpc_code_elements, _from_grpc_import_star.GRPC_ELEMENTS) class ChannelConnectivityTest(unittest.TestCase): def testChannelConnectivity(self): self.assertSequenceEqual( (grpc.ChannelConnectivity.IDLE, grpc.ChannelConnectivity.CONNECTING, grpc.ChannelConnectivity.READY, grpc.ChannelConnectivity.TRANSIENT_FAILURE, grpc.ChannelConnectivity.SHUTDOWN,), tuple(grpc.ChannelConnectivity)) class ChannelTest(unittest.TestCase): def test_secure_channel(self): channel_credentials = grpc.ssl_channel_credentials() channel = grpc.secure_channel('google.com:443', channel_credentials) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_auth_test.py000066400000000000000000000065721310511640000241200ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Tests of standard AuthMetadataPlugins.""" import collections import threading import unittest from grpc import _auth class MockGoogleCreds(object): def get_access_token(self): token = collections.namedtuple('MockAccessTokenInfo', ('access_token', 'expires_in')) token.access_token = 'token' return token class MockExceptionGoogleCreds(object): def get_access_token(self): raise Exception() class GoogleCallCredentialsTest(unittest.TestCase): def test_google_call_credentials_success(self): callback_event = threading.Event() def mock_callback(metadata, error): self.assertEqual(metadata, (('authorization', 'Bearer token'),)) self.assertIsNone(error) callback_event.set() call_creds = _auth.GoogleCallCredentials(MockGoogleCreds()) call_creds(None, mock_callback) self.assertTrue(callback_event.wait(1.0)) def test_google_call_credentials_error(self): callback_event = threading.Event() def mock_callback(metadata, error): self.assertIsNotNone(error) callback_event.set() call_creds = _auth.GoogleCallCredentials(MockExceptionGoogleCreds()) call_creds(None, mock_callback) self.assertTrue(callback_event.wait(1.0)) class AccessTokenCallCredentialsTest(unittest.TestCase): def test_google_call_credentials_success(self): callback_event = threading.Event() def mock_callback(metadata, error): self.assertEqual(metadata, (('authorization', 'Bearer token'),)) self.assertIsNone(error) callback_event.set() call_creds = _auth.AccessTokenCallCredentials('token') call_creds(None, mock_callback) self.assertTrue(callback_event.wait(1.0)) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_channel_args_test.py000066400000000000000000000041301310511640000255670ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Tests of Channel Args on client/server side.""" import unittest import grpc class TestPointerWrapper(object): def __int__(self): return 123456 TEST_CHANNEL_ARGS = (('arg1', b'bytes_val'), ('arg2', 'str_val'), ('arg3', 1), (b'arg4', 'str_val'), ('arg6', TestPointerWrapper()),) class ChannelArgsTest(unittest.TestCase): def test_client(self): grpc.insecure_channel('localhost:8080', options=TEST_CHANNEL_ARGS) def test_server(self): grpc.server(None, options=TEST_CHANNEL_ARGS) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py000066400000000000000000000156211310511640000273600ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Tests of grpc._channel.Channel connectivity.""" import threading import time import unittest import grpc from tests.unit.framework.common import test_constants from tests.unit import _thread_pool def _ready_in_connectivities(connectivities): return grpc.ChannelConnectivity.READY in connectivities def _last_connectivity_is_not_ready(connectivities): return connectivities[-1] is not grpc.ChannelConnectivity.READY class _Callback(object): def __init__(self): self._condition = threading.Condition() self._connectivities = [] def update(self, connectivity): with self._condition: self._connectivities.append(connectivity) self._condition.notify() def connectivities(self): with self._condition: return tuple(self._connectivities) def block_until_connectivities_satisfy(self, predicate): with self._condition: while True: connectivities = tuple(self._connectivities) if predicate(connectivities): return connectivities else: self._condition.wait() class ChannelConnectivityTest(unittest.TestCase): def test_lonely_channel_connectivity(self): callback = _Callback() channel = grpc.insecure_channel('localhost:12345') channel.subscribe(callback.update, try_to_connect=False) first_connectivities = callback.block_until_connectivities_satisfy(bool) channel.subscribe(callback.update, try_to_connect=True) second_connectivities = callback.block_until_connectivities_satisfy( lambda connectivities: 2 <= len(connectivities)) # Wait for a connection that will never happen. time.sleep(test_constants.SHORT_TIMEOUT) third_connectivities = callback.connectivities() channel.unsubscribe(callback.update) fourth_connectivities = callback.connectivities() channel.unsubscribe(callback.update) fifth_connectivities = callback.connectivities() self.assertSequenceEqual((grpc.ChannelConnectivity.IDLE,), first_connectivities) self.assertNotIn(grpc.ChannelConnectivity.READY, second_connectivities) self.assertNotIn(grpc.ChannelConnectivity.READY, third_connectivities) self.assertNotIn(grpc.ChannelConnectivity.READY, fourth_connectivities) self.assertNotIn(grpc.ChannelConnectivity.READY, fifth_connectivities) def test_immediately_connectable_channel_connectivity(self): thread_pool = _thread_pool.RecordingThreadPool(max_workers=None) server = grpc.server(thread_pool) port = server.add_insecure_port('[::]:0') server.start() first_callback = _Callback() second_callback = _Callback() channel = grpc.insecure_channel('localhost:{}'.format(port)) channel.subscribe(first_callback.update, try_to_connect=False) first_connectivities = first_callback.block_until_connectivities_satisfy( bool) # Wait for a connection that will never happen because try_to_connect=True # has not yet been passed. time.sleep(test_constants.SHORT_TIMEOUT) second_connectivities = first_callback.connectivities() channel.subscribe(second_callback.update, try_to_connect=True) third_connectivities = first_callback.block_until_connectivities_satisfy( lambda connectivities: 2 <= len(connectivities)) fourth_connectivities = second_callback.block_until_connectivities_satisfy( bool) # Wait for a connection that will happen (or may already have happened). first_callback.block_until_connectivities_satisfy( _ready_in_connectivities) second_callback.block_until_connectivities_satisfy( _ready_in_connectivities) del channel self.assertSequenceEqual((grpc.ChannelConnectivity.IDLE,), first_connectivities) self.assertSequenceEqual((grpc.ChannelConnectivity.IDLE,), second_connectivities) self.assertNotIn(grpc.ChannelConnectivity.TRANSIENT_FAILURE, third_connectivities) self.assertNotIn(grpc.ChannelConnectivity.SHUTDOWN, third_connectivities) self.assertNotIn(grpc.ChannelConnectivity.TRANSIENT_FAILURE, fourth_connectivities) self.assertNotIn(grpc.ChannelConnectivity.SHUTDOWN, fourth_connectivities) self.assertFalse(thread_pool.was_used()) def test_reachable_then_unreachable_channel_connectivity(self): thread_pool = _thread_pool.RecordingThreadPool(max_workers=None) server = grpc.server(thread_pool) port = server.add_insecure_port('[::]:0') server.start() callback = _Callback() channel = grpc.insecure_channel('localhost:{}'.format(port)) channel.subscribe(callback.update, try_to_connect=True) callback.block_until_connectivities_satisfy(_ready_in_connectivities) # Now take down the server and confirm that channel readiness is repudiated. server.stop(None) callback.block_until_connectivities_satisfy( _last_connectivity_is_not_ready) channel.unsubscribe(callback.update) self.assertFalse(thread_pool.was_used()) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py000066400000000000000000000101651310511640000273360ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Tests of grpc.channel_ready_future.""" import threading import unittest import grpc from tests.unit.framework.common import test_constants from tests.unit import _thread_pool class _Callback(object): def __init__(self): self._condition = threading.Condition() self._value = None def accept_value(self, value): with self._condition: self._value = value self._condition.notify_all() def block_until_called(self): with self._condition: while self._value is None: self._condition.wait() return self._value class ChannelReadyFutureTest(unittest.TestCase): def test_lonely_channel_connectivity(self): channel = grpc.insecure_channel('localhost:12345') callback = _Callback() ready_future = grpc.channel_ready_future(channel) ready_future.add_done_callback(callback.accept_value) with self.assertRaises(grpc.FutureTimeoutError): ready_future.result(timeout=test_constants.SHORT_TIMEOUT) self.assertFalse(ready_future.cancelled()) self.assertFalse(ready_future.done()) self.assertTrue(ready_future.running()) ready_future.cancel() value_passed_to_callback = callback.block_until_called() self.assertIs(ready_future, value_passed_to_callback) self.assertTrue(ready_future.cancelled()) self.assertTrue(ready_future.done()) self.assertFalse(ready_future.running()) def test_immediately_connectable_channel_connectivity(self): thread_pool = _thread_pool.RecordingThreadPool(max_workers=None) server = grpc.server(thread_pool) port = server.add_insecure_port('[::]:0') server.start() channel = grpc.insecure_channel('localhost:{}'.format(port)) callback = _Callback() ready_future = grpc.channel_ready_future(channel) ready_future.add_done_callback(callback.accept_value) self.assertIsNone( ready_future.result(timeout=test_constants.LONG_TIMEOUT)) value_passed_to_callback = callback.block_until_called() self.assertIs(ready_future, value_passed_to_callback) self.assertFalse(ready_future.cancelled()) self.assertTrue(ready_future.done()) self.assertFalse(ready_future.running()) # Cancellation after maturity has no effect. ready_future.cancel() self.assertFalse(ready_future.cancelled()) self.assertTrue(ready_future.done()) self.assertFalse(ready_future.running()) self.assertFalse(thread_pool.was_used()) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_compression_test.py000066400000000000000000000130671310511640000255150ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Tests server and client side compression.""" import unittest import grpc from grpc import _grpcio_metadata from grpc.framework.foundation import logging_pool from tests.unit import test_common from tests.unit.framework.common import test_constants _UNARY_UNARY = '/test/UnaryUnary' _STREAM_STREAM = '/test/StreamStream' def handle_unary(request, servicer_context): servicer_context.send_initial_metadata( [('grpc-internal-encoding-request', 'gzip')]) return request def handle_stream(request_iterator, servicer_context): # TODO(issue:#6891) We should be able to remove this loop, # and replace with return; yield servicer_context.send_initial_metadata( [('grpc-internal-encoding-request', 'gzip')]) for request in request_iterator: yield request class _MethodHandler(grpc.RpcMethodHandler): def __init__(self, request_streaming, response_streaming): self.request_streaming = request_streaming self.response_streaming = response_streaming self.request_deserializer = None self.response_serializer = None self.unary_unary = None self.unary_stream = None self.stream_unary = None self.stream_stream = None if self.request_streaming and self.response_streaming: self.stream_stream = lambda x, y: handle_stream(x, y) elif not self.request_streaming and not self.response_streaming: self.unary_unary = lambda x, y: handle_unary(x, y) class _GenericHandler(grpc.GenericRpcHandler): def service(self, handler_call_details): if handler_call_details.method == _UNARY_UNARY: return _MethodHandler(False, False) elif handler_call_details.method == _STREAM_STREAM: return _MethodHandler(True, True) else: return None class CompressionTest(unittest.TestCase): def setUp(self): self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) self._server = grpc.server( self._server_pool, handlers=(_GenericHandler(),)) self._port = self._server.add_insecure_port('[::]:0') self._server.start() def testUnary(self): request = b'\x00' * 100 # Client -> server compressed through default client channel compression # settings. Server -> client compressed via server-side metadata setting. # TODO(https://github.com/grpc/grpc/issues/4078): replace the "1" integer # literal with proper use of the public API. compressed_channel = grpc.insecure_channel( 'localhost:%d' % self._port, options=[('grpc.default_compression_algorithm', 1)]) multi_callable = compressed_channel.unary_unary(_UNARY_UNARY) response = multi_callable(request) self.assertEqual(request, response) # Client -> server compressed through client metadata setting. Server -> # client compressed via server-side metadata setting. # TODO(https://github.com/grpc/grpc/issues/4078): replace the "0" integer # literal with proper use of the public API. uncompressed_channel = grpc.insecure_channel( 'localhost:%d' % self._port, options=[('grpc.default_compression_algorithm', 0)]) multi_callable = compressed_channel.unary_unary(_UNARY_UNARY) response = multi_callable( request, metadata=[('grpc-internal-encoding-request', 'gzip')]) self.assertEqual(request, response) def testStreaming(self): request = b'\x00' * 100 # TODO(https://github.com/grpc/grpc/issues/4078): replace the "1" integer # literal with proper use of the public API. compressed_channel = grpc.insecure_channel( 'localhost:%d' % self._port, options=[('grpc.default_compression_algorithm', 1)]) multi_callable = compressed_channel.stream_stream(_STREAM_STREAM) call = multi_callable(iter([request] * test_constants.STREAM_LENGTH)) for response in call: self.assertEqual(request, response) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_credentials_test.py000066400000000000000000000064701310511640000254510ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Tests of credentials.""" import unittest import grpc class CredentialsTest(unittest.TestCase): def test_call_credentials_composition(self): first = grpc.access_token_call_credentials('abc') second = grpc.access_token_call_credentials('def') third = grpc.access_token_call_credentials('ghi') first_and_second = grpc.composite_call_credentials(first, second) first_second_and_third = grpc.composite_call_credentials(first, second, third) self.assertIsInstance(first_and_second, grpc.CallCredentials) self.assertIsInstance(first_second_and_third, grpc.CallCredentials) def test_channel_credentials_composition(self): first_call_credentials = grpc.access_token_call_credentials('abc') second_call_credentials = grpc.access_token_call_credentials('def') third_call_credentials = grpc.access_token_call_credentials('ghi') channel_credentials = grpc.ssl_channel_credentials() channel_and_first = grpc.composite_channel_credentials( channel_credentials, first_call_credentials) channel_first_and_second = grpc.composite_channel_credentials( channel_credentials, first_call_credentials, second_call_credentials) channel_first_second_and_third = grpc.composite_channel_credentials( channel_credentials, first_call_credentials, second_call_credentials, third_call_credentials) self.assertIsInstance(channel_and_first, grpc.ChannelCredentials) self.assertIsInstance(channel_first_and_second, grpc.ChannelCredentials) self.assertIsInstance(channel_first_second_and_third, grpc.ChannelCredentials) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_cython/000077500000000000000000000000001310511640000230405ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/unit/_cython/.gitignore000066400000000000000000000000431310511640000250250ustar00rootroot00000000000000*.h *.c *.a *.so *.dll *.pyc *.pyd grpc-1.3.2/src/python/grpcio_tests/tests/unit/_cython/__init__.py000066400000000000000000000027701310511640000251570ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py000066400000000000000000000214261310511640000302440ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Test making many calls and immediately cancelling most of them.""" import threading import unittest from grpc._cython import cygrpc from grpc.framework.foundation import logging_pool from tests.unit.framework.common import test_constants _INFINITE_FUTURE = cygrpc.Timespec(float('+inf')) _EMPTY_FLAGS = 0 _EMPTY_METADATA = cygrpc.Metadata(()) _SERVER_SHUTDOWN_TAG = 'server_shutdown' _REQUEST_CALL_TAG = 'request_call' _RECEIVE_CLOSE_ON_SERVER_TAG = 'receive_close_on_server' _RECEIVE_MESSAGE_TAG = 'receive_message' _SERVER_COMPLETE_CALL_TAG = 'server_complete_call' _SUCCESS_CALL_FRACTION = 1.0 / 8.0 class _State(object): def __init__(self): self.condition = threading.Condition() self.handlers_released = False self.parked_handlers = 0 self.handled_rpcs = 0 def _is_cancellation_event(event): return (event.tag is _RECEIVE_CLOSE_ON_SERVER_TAG and event.batch_operations[0].received_cancelled) class _Handler(object): def __init__(self, state, completion_queue, rpc_event): self._state = state self._lock = threading.Lock() self._completion_queue = completion_queue self._call = rpc_event.operation_call def __call__(self): with self._state.condition: self._state.parked_handlers += 1 if self._state.parked_handlers == test_constants.THREAD_CONCURRENCY: self._state.condition.notify_all() while not self._state.handlers_released: self._state.condition.wait() with self._lock: self._call.start_server_batch( cygrpc.Operations( (cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS),)), _RECEIVE_CLOSE_ON_SERVER_TAG) self._call.start_server_batch( cygrpc.Operations( (cygrpc.operation_receive_message(_EMPTY_FLAGS),)), _RECEIVE_MESSAGE_TAG) first_event = self._completion_queue.poll() if _is_cancellation_event(first_event): self._completion_queue.poll() else: with self._lock: operations = ( cygrpc.operation_send_initial_metadata(_EMPTY_METADATA, _EMPTY_FLAGS), cygrpc.operation_send_message(b'\x79\x57', _EMPTY_FLAGS), cygrpc.operation_send_status_from_server( _EMPTY_METADATA, cygrpc.StatusCode.ok, b'test details!', _EMPTY_FLAGS),) self._call.start_server_batch( cygrpc.Operations(operations), _SERVER_COMPLETE_CALL_TAG) self._completion_queue.poll() self._completion_queue.poll() def _serve(state, server, server_completion_queue, thread_pool): for _ in range(test_constants.RPC_CONCURRENCY): call_completion_queue = cygrpc.CompletionQueue() server.request_call(call_completion_queue, server_completion_queue, _REQUEST_CALL_TAG) rpc_event = server_completion_queue.poll() thread_pool.submit(_Handler(state, call_completion_queue, rpc_event)) with state.condition: state.handled_rpcs += 1 if test_constants.RPC_CONCURRENCY <= state.handled_rpcs: state.condition.notify_all() server_completion_queue.poll() class _QueueDriver(object): def __init__(self, condition, completion_queue, due): self._condition = condition self._completion_queue = completion_queue self._due = due self._events = [] self._returned = False def start(self): def in_thread(): while True: event = self._completion_queue.poll() with self._condition: self._events.append(event) self._due.remove(event.tag) self._condition.notify_all() if not self._due: self._returned = True return thread = threading.Thread(target=in_thread) thread.start() def events(self, at_least): with self._condition: while len(self._events) < at_least: self._condition.wait() return tuple(self._events) class CancelManyCallsTest(unittest.TestCase): def testCancelManyCalls(self): server_thread_pool = logging_pool.pool( test_constants.THREAD_CONCURRENCY) server_completion_queue = cygrpc.CompletionQueue() server = cygrpc.Server(cygrpc.ChannelArgs([])) server.register_completion_queue(server_completion_queue) port = server.add_http2_port(b'[::]:0') server.start() channel = cygrpc.Channel('localhost:{}'.format(port).encode(), cygrpc.ChannelArgs([])) state = _State() server_thread_args = (state, server, server_completion_queue, server_thread_pool,) server_thread = threading.Thread(target=_serve, args=server_thread_args) server_thread.start() client_condition = threading.Condition() client_due = set() client_completion_queue = cygrpc.CompletionQueue() client_driver = _QueueDriver(client_condition, client_completion_queue, client_due) client_driver.start() with client_condition: client_calls = [] for index in range(test_constants.RPC_CONCURRENCY): client_call = channel.create_call( None, _EMPTY_FLAGS, client_completion_queue, b'/twinkies', None, _INFINITE_FUTURE) operations = ( cygrpc.operation_send_initial_metadata(_EMPTY_METADATA, _EMPTY_FLAGS), cygrpc.operation_send_message(b'\x45\x56', _EMPTY_FLAGS), cygrpc.operation_send_close_from_client(_EMPTY_FLAGS), cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS), cygrpc.operation_receive_message(_EMPTY_FLAGS), cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS),) tag = 'client_complete_call_{0:04d}_tag'.format(index) client_call.start_client_batch( cygrpc.Operations(operations), tag) client_due.add(tag) client_calls.append(client_call) with state.condition: while True: if state.parked_handlers < test_constants.THREAD_CONCURRENCY: state.condition.wait() elif state.handled_rpcs < test_constants.RPC_CONCURRENCY: state.condition.wait() else: state.handlers_released = True state.condition.notify_all() break client_driver.events(test_constants.RPC_CONCURRENCY * _SUCCESS_CALL_FRACTION) with client_condition: for client_call in client_calls: client_call.cancel() with state.condition: server.shutdown(server_completion_queue, _SERVER_SHUTDOWN_TAG) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_cython/_channel_test.py000066400000000000000000000061271310511640000262260ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import time import threading import unittest from grpc._cython import cygrpc from tests.unit.framework.common import test_constants def _channel_and_completion_queue(): channel = cygrpc.Channel(b'localhost:54321', cygrpc.ChannelArgs(())) completion_queue = cygrpc.CompletionQueue() return channel, completion_queue def _connectivity_loop(channel, completion_queue): for _ in range(100): connectivity = channel.check_connectivity_state(True) channel.watch_connectivity_state(connectivity, cygrpc.Timespec(time.time() + 0.2), completion_queue, None) completion_queue.poll(deadline=cygrpc.Timespec(float('+inf'))) def _create_loop_destroy(): channel, completion_queue = _channel_and_completion_queue() _connectivity_loop(channel, completion_queue) completion_queue.shutdown() def _in_parallel(behavior, arguments): threads = tuple( threading.Thread(target=behavior, args=arguments) for _ in range(test_constants.THREAD_CONCURRENCY)) for thread in threads: thread.start() for thread in threads: thread.join() class ChannelTest(unittest.TestCase): def test_single_channel_lonely_connectivity(self): channel, completion_queue = _channel_and_completion_queue() _in_parallel(_connectivity_loop, (channel, completion_queue,)) completion_queue.shutdown() def test_multiple_channels_lonely_connectivity(self): _in_parallel(_create_loop_destroy, ()) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py000066400000000000000000000256701310511640000332430ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Test a corner-case at the level of the Cython API.""" import threading import unittest from grpc._cython import cygrpc _INFINITE_FUTURE = cygrpc.Timespec(float('+inf')) _EMPTY_FLAGS = 0 _EMPTY_METADATA = cygrpc.Metadata(()) class _ServerDriver(object): def __init__(self, completion_queue, shutdown_tag): self._condition = threading.Condition() self._completion_queue = completion_queue self._shutdown_tag = shutdown_tag self._events = [] self._saw_shutdown_tag = False def start(self): def in_thread(): while True: event = self._completion_queue.poll() with self._condition: self._events.append(event) self._condition.notify() if event.tag is self._shutdown_tag: self._saw_shutdown_tag = True break thread = threading.Thread(target=in_thread) thread.start() def done(self): with self._condition: return self._saw_shutdown_tag def first_event(self): with self._condition: while not self._events: self._condition.wait() return self._events[0] def events(self): with self._condition: while not self._saw_shutdown_tag: self._condition.wait() return tuple(self._events) class _QueueDriver(object): def __init__(self, condition, completion_queue, due): self._condition = condition self._completion_queue = completion_queue self._due = due self._events = [] self._returned = False def start(self): def in_thread(): while True: event = self._completion_queue.poll() with self._condition: self._events.append(event) self._due.remove(event.tag) self._condition.notify_all() if not self._due: self._returned = True return thread = threading.Thread(target=in_thread) thread.start() def done(self): with self._condition: return self._returned def event_with_tag(self, tag): with self._condition: while True: for event in self._events: if event.tag is tag: return event self._condition.wait() def events(self): with self._condition: while not self._returned: self._condition.wait() return tuple(self._events) class ReadSomeButNotAllResponsesTest(unittest.TestCase): def testReadSomeButNotAllResponses(self): server_completion_queue = cygrpc.CompletionQueue() server = cygrpc.Server(cygrpc.ChannelArgs([])) server.register_completion_queue(server_completion_queue) port = server.add_http2_port(b'[::]:0') server.start() channel = cygrpc.Channel('localhost:{}'.format(port).encode(), cygrpc.ChannelArgs([])) server_shutdown_tag = 'server_shutdown_tag' server_driver = _ServerDriver(server_completion_queue, server_shutdown_tag) server_driver.start() client_condition = threading.Condition() client_due = set() client_completion_queue = cygrpc.CompletionQueue() client_driver = _QueueDriver(client_condition, client_completion_queue, client_due) client_driver.start() server_call_condition = threading.Condition() server_send_initial_metadata_tag = 'server_send_initial_metadata_tag' server_send_first_message_tag = 'server_send_first_message_tag' server_send_second_message_tag = 'server_send_second_message_tag' server_complete_rpc_tag = 'server_complete_rpc_tag' server_call_due = set( (server_send_initial_metadata_tag, server_send_first_message_tag, server_send_second_message_tag, server_complete_rpc_tag,)) server_call_completion_queue = cygrpc.CompletionQueue() server_call_driver = _QueueDriver(server_call_condition, server_call_completion_queue, server_call_due) server_call_driver.start() server_rpc_tag = 'server_rpc_tag' request_call_result = server.request_call(server_call_completion_queue, server_completion_queue, server_rpc_tag) client_call = channel.create_call(None, _EMPTY_FLAGS, client_completion_queue, b'/twinkies', None, _INFINITE_FUTURE) client_receive_initial_metadata_tag = 'client_receive_initial_metadata_tag' client_complete_rpc_tag = 'client_complete_rpc_tag' with client_condition: client_receive_initial_metadata_start_batch_result = ( client_call.start_client_batch( cygrpc.Operations([ cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS), ]), client_receive_initial_metadata_tag)) client_due.add(client_receive_initial_metadata_tag) client_complete_rpc_start_batch_result = ( client_call.start_client_batch( cygrpc.Operations([ cygrpc.operation_send_initial_metadata(_EMPTY_METADATA, _EMPTY_FLAGS), cygrpc.operation_send_close_from_client(_EMPTY_FLAGS), cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS), ]), client_complete_rpc_tag)) client_due.add(client_complete_rpc_tag) server_rpc_event = server_driver.first_event() with server_call_condition: server_send_initial_metadata_start_batch_result = ( server_rpc_event.operation_call.start_server_batch([ cygrpc.operation_send_initial_metadata(_EMPTY_METADATA, _EMPTY_FLAGS), ], server_send_initial_metadata_tag)) server_send_first_message_start_batch_result = ( server_rpc_event.operation_call.start_server_batch([ cygrpc.operation_send_message(b'\x07', _EMPTY_FLAGS), ], server_send_first_message_tag)) server_send_initial_metadata_event = server_call_driver.event_with_tag( server_send_initial_metadata_tag) server_send_first_message_event = server_call_driver.event_with_tag( server_send_first_message_tag) with server_call_condition: server_send_second_message_start_batch_result = ( server_rpc_event.operation_call.start_server_batch([ cygrpc.operation_send_message(b'\x07', _EMPTY_FLAGS), ], server_send_second_message_tag)) server_complete_rpc_start_batch_result = ( server_rpc_event.operation_call.start_server_batch([ cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS), cygrpc.operation_send_status_from_server( cygrpc.Metadata(()), cygrpc.StatusCode.ok, b'test details', _EMPTY_FLAGS), ], server_complete_rpc_tag)) server_send_second_message_event = server_call_driver.event_with_tag( server_send_second_message_tag) server_complete_rpc_event = server_call_driver.event_with_tag( server_complete_rpc_tag) server_call_driver.events() with client_condition: client_receive_first_message_tag = 'client_receive_first_message_tag' client_receive_first_message_start_batch_result = ( client_call.start_client_batch( cygrpc.Operations([ cygrpc.operation_receive_message(_EMPTY_FLAGS), ]), client_receive_first_message_tag)) client_due.add(client_receive_first_message_tag) client_receive_first_message_event = client_driver.event_with_tag( client_receive_first_message_tag) client_call_cancel_result = client_call.cancel() client_driver.events() server.shutdown(server_completion_queue, server_shutdown_tag) server.cancel_all_calls() server_driver.events() self.assertEqual(cygrpc.CallError.ok, request_call_result) self.assertEqual(cygrpc.CallError.ok, server_send_initial_metadata_start_batch_result) self.assertEqual(cygrpc.CallError.ok, client_receive_initial_metadata_start_batch_result) self.assertEqual(cygrpc.CallError.ok, client_complete_rpc_start_batch_result) self.assertEqual(cygrpc.CallError.ok, client_call_cancel_result) self.assertIs(server_rpc_tag, server_rpc_event.tag) self.assertEqual(cygrpc.CompletionType.operation_complete, server_rpc_event.type) self.assertIsInstance(server_rpc_event.operation_call, cygrpc.Call) self.assertEqual(0, len(server_rpc_event.batch_operations)) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py000066400000000000000000000501431310511640000257430ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import time import threading import unittest import platform from grpc._cython import cygrpc from tests.unit._cython import test_utilities from tests.unit import test_common from tests.unit import resources _SSL_HOST_OVERRIDE = b'foo.test.google.fr' _CALL_CREDENTIALS_METADATA_KEY = 'call-creds-key' _CALL_CREDENTIALS_METADATA_VALUE = 'call-creds-value' _EMPTY_FLAGS = 0 def _metadata_plugin_callback(context, callback): callback( cygrpc.Metadata([ cygrpc.Metadatum(_CALL_CREDENTIALS_METADATA_KEY, _CALL_CREDENTIALS_METADATA_VALUE) ]), cygrpc.StatusCode.ok, b'') class TypeSmokeTest(unittest.TestCase): def testStringsInUtilitiesUpDown(self): self.assertEqual(0, cygrpc.StatusCode.ok) metadatum = cygrpc.Metadatum(b'a', b'b') self.assertEqual(b'a', metadatum.key) self.assertEqual(b'b', metadatum.value) metadata = cygrpc.Metadata([metadatum]) self.assertEqual(1, len(metadata)) self.assertEqual(metadatum.key, metadata[0].key) def testMetadataIteration(self): metadata = cygrpc.Metadata( [cygrpc.Metadatum(b'a', b'b'), cygrpc.Metadatum(b'c', b'd')]) iterator = iter(metadata) metadatum = next(iterator) self.assertIsInstance(metadatum, cygrpc.Metadatum) self.assertEqual(metadatum.key, b'a') self.assertEqual(metadatum.value, b'b') metadatum = next(iterator) self.assertIsInstance(metadatum, cygrpc.Metadatum) self.assertEqual(metadatum.key, b'c') self.assertEqual(metadatum.value, b'd') with self.assertRaises(StopIteration): next(iterator) def testOperationsIteration(self): operations = cygrpc.Operations( [cygrpc.operation_send_message(b'asdf', _EMPTY_FLAGS)]) iterator = iter(operations) operation = next(iterator) self.assertIsInstance(operation, cygrpc.Operation) # `Operation`s are write-only structures; can't directly debug anything out # of them. Just check that we stop iterating. with self.assertRaises(StopIteration): next(iterator) def testOperationFlags(self): operation = cygrpc.operation_send_message(b'asdf', cygrpc.WriteFlag.no_compress) self.assertEqual(cygrpc.WriteFlag.no_compress, operation.flags) def testTimespec(self): now = time.time() now_timespec_a = cygrpc.Timespec(now) now_timespec_b = cygrpc.Timespec(now) self.assertAlmostEqual(now, float(now_timespec_a), places=8) self.assertEqual(now_timespec_a, now_timespec_b) self.assertLess(cygrpc.Timespec(now - 1), cygrpc.Timespec(now)) self.assertGreater(cygrpc.Timespec(now + 1), cygrpc.Timespec(now)) self.assertGreaterEqual(cygrpc.Timespec(now + 1), cygrpc.Timespec(now)) self.assertGreaterEqual(cygrpc.Timespec(now), cygrpc.Timespec(now)) self.assertLessEqual(cygrpc.Timespec(now - 1), cygrpc.Timespec(now)) self.assertLessEqual(cygrpc.Timespec(now), cygrpc.Timespec(now)) self.assertNotEqual(cygrpc.Timespec(now - 1), cygrpc.Timespec(now)) self.assertNotEqual(cygrpc.Timespec(now + 1), cygrpc.Timespec(now)) def testCompletionQueueUpDown(self): completion_queue = cygrpc.CompletionQueue() del completion_queue def testServerUpDown(self): server = cygrpc.Server(cygrpc.ChannelArgs([])) del server def testChannelUpDown(self): channel = cygrpc.Channel(b'[::]:0', cygrpc.ChannelArgs([])) del channel def testCredentialsMetadataPluginUpDown(self): plugin = cygrpc.CredentialsMetadataPlugin( lambda ignored_a, ignored_b: None, b'') del plugin def testCallCredentialsFromPluginUpDown(self): plugin = cygrpc.CredentialsMetadataPlugin(_metadata_plugin_callback, b'') call_credentials = cygrpc.call_credentials_metadata_plugin(plugin) del plugin del call_credentials def testServerStartNoExplicitShutdown(self): server = cygrpc.Server(cygrpc.ChannelArgs([])) completion_queue = cygrpc.CompletionQueue() server.register_completion_queue(completion_queue) port = server.add_http2_port(b'[::]:0') self.assertIsInstance(port, int) server.start() del server def testServerStartShutdown(self): completion_queue = cygrpc.CompletionQueue() server = cygrpc.Server(cygrpc.ChannelArgs([])) server.add_http2_port(b'[::]:0') server.register_completion_queue(completion_queue) server.start() shutdown_tag = object() server.shutdown(completion_queue, shutdown_tag) event = completion_queue.poll() self.assertEqual(cygrpc.CompletionType.operation_complete, event.type) self.assertIs(shutdown_tag, event.tag) del server del completion_queue class ServerClientMixin(object): def setUpMixin(self, server_credentials, client_credentials, host_override): self.server_completion_queue = cygrpc.CompletionQueue() self.server = cygrpc.Server(cygrpc.ChannelArgs([])) self.server.register_completion_queue(self.server_completion_queue) if server_credentials: self.port = self.server.add_http2_port(b'[::]:0', server_credentials) else: self.port = self.server.add_http2_port(b'[::]:0') self.server.start() self.client_completion_queue = cygrpc.CompletionQueue() if client_credentials: client_channel_arguments = cygrpc.ChannelArgs([ cygrpc.ChannelArg(cygrpc.ChannelArgKey.ssl_target_name_override, host_override) ]) self.client_channel = cygrpc.Channel( 'localhost:{}'.format(self.port).encode(), client_channel_arguments, client_credentials) else: self.client_channel = cygrpc.Channel( 'localhost:{}'.format(self.port).encode(), cygrpc.ChannelArgs([])) if host_override: self.host_argument = None # default host self.expected_host = host_override else: # arbitrary host name necessitating no further identification self.host_argument = b'hostess' self.expected_host = self.host_argument def tearDownMixin(self): del self.server del self.client_completion_queue del self.server_completion_queue def _perform_operations(self, operations, call, queue, deadline, description): """Perform the list of operations with given call, queue, and deadline. Invocation errors are reported with as an exception with `description` in the message. Performs the operations asynchronously, returning a future. """ def performer(): tag = object() try: call_result = call.start_client_batch( cygrpc.Operations(operations), tag) self.assertEqual(cygrpc.CallError.ok, call_result) event = queue.poll(deadline) self.assertEqual(cygrpc.CompletionType.operation_complete, event.type) self.assertTrue(event.success) self.assertIs(tag, event.tag) except Exception as error: raise Exception( "Error in '{}': {}".format(description, error.message)) return event return test_utilities.SimpleFuture(performer) def testEcho(self): DEADLINE = time.time() + 5 DEADLINE_TOLERANCE = 0.25 CLIENT_METADATA_ASCII_KEY = b'key' CLIENT_METADATA_ASCII_VALUE = b'val' CLIENT_METADATA_BIN_KEY = b'key-bin' CLIENT_METADATA_BIN_VALUE = b'\0' * 1000 SERVER_INITIAL_METADATA_KEY = b'init_me_me_me' SERVER_INITIAL_METADATA_VALUE = b'whodawha?' SERVER_TRAILING_METADATA_KEY = b'california_is_in_a_drought' SERVER_TRAILING_METADATA_VALUE = b'zomg it is' SERVER_STATUS_CODE = cygrpc.StatusCode.ok SERVER_STATUS_DETAILS = b'our work is never over' REQUEST = b'in death a member of project mayhem has a name' RESPONSE = b'his name is robert paulson' METHOD = b'twinkies' cygrpc_deadline = cygrpc.Timespec(DEADLINE) server_request_tag = object() request_call_result = self.server.request_call( self.server_completion_queue, self.server_completion_queue, server_request_tag) self.assertEqual(cygrpc.CallError.ok, request_call_result) client_call_tag = object() client_call = self.client_channel.create_call( None, 0, self.client_completion_queue, METHOD, self.host_argument, cygrpc_deadline) client_initial_metadata = cygrpc.Metadata([ cygrpc.Metadatum(CLIENT_METADATA_ASCII_KEY, CLIENT_METADATA_ASCII_VALUE), cygrpc.Metadatum(CLIENT_METADATA_BIN_KEY, CLIENT_METADATA_BIN_VALUE) ]) client_start_batch_result = client_call.start_client_batch([ cygrpc.operation_send_initial_metadata(client_initial_metadata, _EMPTY_FLAGS), cygrpc.operation_send_message(REQUEST, _EMPTY_FLAGS), cygrpc.operation_send_close_from_client(_EMPTY_FLAGS), cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS), cygrpc.operation_receive_message(_EMPTY_FLAGS), cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS) ], client_call_tag) self.assertEqual(cygrpc.CallError.ok, client_start_batch_result) client_event_future = test_utilities.CompletionQueuePollFuture( self.client_completion_queue, cygrpc_deadline) request_event = self.server_completion_queue.poll(cygrpc_deadline) self.assertEqual(cygrpc.CompletionType.operation_complete, request_event.type) self.assertIsInstance(request_event.operation_call, cygrpc.Call) self.assertIs(server_request_tag, request_event.tag) self.assertEqual(0, len(request_event.batch_operations)) self.assertTrue( test_common.metadata_transmitted(client_initial_metadata, request_event.request_metadata)) self.assertEqual(METHOD, request_event.request_call_details.method) self.assertEqual(self.expected_host, request_event.request_call_details.host) self.assertLess( abs(DEADLINE - float(request_event.request_call_details.deadline)), DEADLINE_TOLERANCE) server_call_tag = object() server_call = request_event.operation_call server_initial_metadata = cygrpc.Metadata([ cygrpc.Metadatum(SERVER_INITIAL_METADATA_KEY, SERVER_INITIAL_METADATA_VALUE) ]) server_trailing_metadata = cygrpc.Metadata([ cygrpc.Metadatum(SERVER_TRAILING_METADATA_KEY, SERVER_TRAILING_METADATA_VALUE) ]) server_start_batch_result = server_call.start_server_batch([ cygrpc.operation_send_initial_metadata( server_initial_metadata, _EMPTY_FLAGS), cygrpc.operation_receive_message(_EMPTY_FLAGS), cygrpc.operation_send_message(RESPONSE, _EMPTY_FLAGS), cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS), cygrpc.operation_send_status_from_server( server_trailing_metadata, SERVER_STATUS_CODE, SERVER_STATUS_DETAILS, _EMPTY_FLAGS) ], server_call_tag) self.assertEqual(cygrpc.CallError.ok, server_start_batch_result) server_event = self.server_completion_queue.poll(cygrpc_deadline) client_event = client_event_future.result() self.assertEqual(6, len(client_event.batch_operations)) found_client_op_types = set() for client_result in client_event.batch_operations: # we expect each op type to be unique self.assertNotIn(client_result.type, found_client_op_types) found_client_op_types.add(client_result.type) if client_result.type == cygrpc.OperationType.receive_initial_metadata: self.assertTrue( test_common.metadata_transmitted( server_initial_metadata, client_result.received_metadata)) elif client_result.type == cygrpc.OperationType.receive_message: self.assertEqual(RESPONSE, client_result.received_message.bytes()) elif client_result.type == cygrpc.OperationType.receive_status_on_client: self.assertTrue( test_common.metadata_transmitted( server_trailing_metadata, client_result.received_metadata)) self.assertEqual(SERVER_STATUS_DETAILS, client_result.received_status_details) self.assertEqual(SERVER_STATUS_CODE, client_result.received_status_code) self.assertEqual( set([ cygrpc.OperationType.send_initial_metadata, cygrpc.OperationType.send_message, cygrpc.OperationType.send_close_from_client, cygrpc.OperationType.receive_initial_metadata, cygrpc.OperationType.receive_message, cygrpc.OperationType.receive_status_on_client ]), found_client_op_types) self.assertEqual(5, len(server_event.batch_operations)) found_server_op_types = set() for server_result in server_event.batch_operations: self.assertNotIn(client_result.type, found_server_op_types) found_server_op_types.add(server_result.type) if server_result.type == cygrpc.OperationType.receive_message: self.assertEqual(REQUEST, server_result.received_message.bytes()) elif server_result.type == cygrpc.OperationType.receive_close_on_server: self.assertFalse(server_result.received_cancelled) self.assertEqual( set([ cygrpc.OperationType.send_initial_metadata, cygrpc.OperationType.receive_message, cygrpc.OperationType.send_message, cygrpc.OperationType.receive_close_on_server, cygrpc.OperationType.send_status_from_server ]), found_server_op_types) del client_call del server_call def test6522(self): DEADLINE = time.time() + 5 DEADLINE_TOLERANCE = 0.25 METHOD = b'twinkies' cygrpc_deadline = cygrpc.Timespec(DEADLINE) empty_metadata = cygrpc.Metadata([]) server_request_tag = object() self.server.request_call(self.server_completion_queue, self.server_completion_queue, server_request_tag) client_call = self.client_channel.create_call( None, 0, self.client_completion_queue, METHOD, self.host_argument, cygrpc_deadline) # Prologue def perform_client_operations(operations, description): return self._perform_operations(operations, client_call, self.client_completion_queue, cygrpc_deadline, description) client_event_future = perform_client_operations([ cygrpc.operation_send_initial_metadata(empty_metadata, _EMPTY_FLAGS), cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS), ], "Client prologue") request_event = self.server_completion_queue.poll(cygrpc_deadline) server_call = request_event.operation_call def perform_server_operations(operations, description): return self._perform_operations(operations, server_call, self.server_completion_queue, cygrpc_deadline, description) server_event_future = perform_server_operations([ cygrpc.operation_send_initial_metadata(empty_metadata, _EMPTY_FLAGS), ], "Server prologue") client_event_future.result() # force completion server_event_future.result() # Messaging for _ in range(10): client_event_future = perform_client_operations([ cygrpc.operation_send_message(b'', _EMPTY_FLAGS), cygrpc.operation_receive_message(_EMPTY_FLAGS), ], "Client message") server_event_future = perform_server_operations([ cygrpc.operation_send_message(b'', _EMPTY_FLAGS), cygrpc.operation_receive_message(_EMPTY_FLAGS), ], "Server receive") client_event_future.result() # force completion server_event_future.result() # Epilogue client_event_future = perform_client_operations([ cygrpc.operation_send_close_from_client(_EMPTY_FLAGS), cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS) ], "Client epilogue") server_event_future = perform_server_operations([ cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS), cygrpc.operation_send_status_from_server( empty_metadata, cygrpc.StatusCode.ok, b'', _EMPTY_FLAGS) ], "Server epilogue") client_event_future.result() # force completion server_event_future.result() class InsecureServerInsecureClient(unittest.TestCase, ServerClientMixin): def setUp(self): self.setUpMixin(None, None, None) def tearDown(self): self.tearDownMixin() class SecureServerSecureClient(unittest.TestCase, ServerClientMixin): def setUp(self): server_credentials = cygrpc.server_credentials_ssl(None, [ cygrpc.SslPemKeyCertPair(resources.private_key(), resources.certificate_chain()) ], False) client_credentials = cygrpc.channel_credentials_ssl( resources.test_root_certificates(), None) self.setUpMixin(server_credentials, client_credentials, _SSL_HOST_OVERRIDE) def tearDown(self): self.tearDownMixin() if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_cython/test_utilities.py000066400000000000000000000047601310511640000264730ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import threading from grpc._cython import cygrpc class SimpleFuture(object): """A simple future mechanism.""" def __init__(self, function, *args, **kwargs): def wrapped_function(): try: self._result = function(*args, **kwargs) except Exception as error: self._error = error self._result = None self._error = None self._thread = threading.Thread(target=wrapped_function) self._thread.start() def result(self): """The resulting value of this future. Re-raises any exceptions. """ self._thread.join() if self._error: # TODO(atash): re-raise exceptions in a way that preserves tracebacks raise self._error return self._result class CompletionQueuePollFuture(SimpleFuture): def __init__(self, completion_queue, deadline): super(CompletionQueuePollFuture, self).__init__(lambda: completion_queue.poll(deadline)) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_empty_message_test.py000066400000000000000000000117001310511640000260060ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import unittest import grpc from grpc.framework.foundation import logging_pool from tests.unit.framework.common import test_constants _REQUEST = b'' _RESPONSE = b'' _UNARY_UNARY = '/test/UnaryUnary' _UNARY_STREAM = '/test/UnaryStream' _STREAM_UNARY = '/test/StreamUnary' _STREAM_STREAM = '/test/StreamStream' def handle_unary_unary(request, servicer_context): return _RESPONSE def handle_unary_stream(request, servicer_context): for _ in range(test_constants.STREAM_LENGTH): yield _RESPONSE def handle_stream_unary(request_iterator, servicer_context): for request in request_iterator: pass return _RESPONSE def handle_stream_stream(request_iterator, servicer_context): for request in request_iterator: yield _RESPONSE class _MethodHandler(grpc.RpcMethodHandler): def __init__(self, request_streaming, response_streaming): self.request_streaming = request_streaming self.response_streaming = response_streaming self.request_deserializer = None self.response_serializer = None self.unary_unary = None self.unary_stream = None self.stream_unary = None self.stream_stream = None if self.request_streaming and self.response_streaming: self.stream_stream = handle_stream_stream elif self.request_streaming: self.stream_unary = handle_stream_unary elif self.response_streaming: self.unary_stream = handle_unary_stream else: self.unary_unary = handle_unary_unary class _GenericHandler(grpc.GenericRpcHandler): def service(self, handler_call_details): if handler_call_details.method == _UNARY_UNARY: return _MethodHandler(False, False) elif handler_call_details.method == _UNARY_STREAM: return _MethodHandler(False, True) elif handler_call_details.method == _STREAM_UNARY: return _MethodHandler(True, False) elif handler_call_details.method == _STREAM_STREAM: return _MethodHandler(True, True) else: return None class EmptyMessageTest(unittest.TestCase): def setUp(self): self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) self._server = grpc.server( self._server_pool, handlers=(_GenericHandler(),)) port = self._server.add_insecure_port('[::]:0') self._server.start() self._channel = grpc.insecure_channel('localhost:%d' % port) def tearDown(self): self._server.stop(0) def testUnaryUnary(self): response = self._channel.unary_unary(_UNARY_UNARY)(_REQUEST) self.assertEqual(_RESPONSE, response) def testUnaryStream(self): response_iterator = self._channel.unary_stream(_UNARY_STREAM)(_REQUEST) self.assertSequenceEqual([_RESPONSE] * test_constants.STREAM_LENGTH, list(response_iterator)) def testStreamUnary(self): response = self._channel.stream_unary(_STREAM_UNARY)( iter([_REQUEST] * test_constants.STREAM_LENGTH)) self.assertEqual(_RESPONSE, response) def testStreamStream(self): response_iterator = self._channel.stream_stream(_STREAM_STREAM)( iter([_REQUEST] * test_constants.STREAM_LENGTH)) self.assertSequenceEqual([_RESPONSE] * test_constants.STREAM_LENGTH, list(response_iterator)) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_exit_scenarios.py000066400000000000000000000224111310511640000251250ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Defines a number of module-scope gRPC scenarios to test clean exit.""" import argparse import threading import time import grpc from tests.unit.framework.common import test_constants WAIT_TIME = 1000 REQUEST = b'request' UNSTARTED_SERVER = 'unstarted_server' RUNNING_SERVER = 'running_server' POLL_CONNECTIVITY_NO_SERVER = 'poll_connectivity_no_server' POLL_CONNECTIVITY = 'poll_connectivity' IN_FLIGHT_UNARY_UNARY_CALL = 'in_flight_unary_unary_call' IN_FLIGHT_UNARY_STREAM_CALL = 'in_flight_unary_stream_call' IN_FLIGHT_STREAM_UNARY_CALL = 'in_flight_stream_unary_call' IN_FLIGHT_STREAM_STREAM_CALL = 'in_flight_stream_stream_call' IN_FLIGHT_PARTIAL_UNARY_STREAM_CALL = 'in_flight_partial_unary_stream_call' IN_FLIGHT_PARTIAL_STREAM_UNARY_CALL = 'in_flight_partial_stream_unary_call' IN_FLIGHT_PARTIAL_STREAM_STREAM_CALL = 'in_flight_partial_stream_stream_call' UNARY_UNARY = b'/test/UnaryUnary' UNARY_STREAM = b'/test/UnaryStream' STREAM_UNARY = b'/test/StreamUnary' STREAM_STREAM = b'/test/StreamStream' PARTIAL_UNARY_STREAM = b'/test/PartialUnaryStream' PARTIAL_STREAM_UNARY = b'/test/PartialStreamUnary' PARTIAL_STREAM_STREAM = b'/test/PartialStreamStream' TEST_TO_METHOD = { IN_FLIGHT_UNARY_UNARY_CALL: UNARY_UNARY, IN_FLIGHT_UNARY_STREAM_CALL: UNARY_STREAM, IN_FLIGHT_STREAM_UNARY_CALL: STREAM_UNARY, IN_FLIGHT_STREAM_STREAM_CALL: STREAM_STREAM, IN_FLIGHT_PARTIAL_UNARY_STREAM_CALL: PARTIAL_UNARY_STREAM, IN_FLIGHT_PARTIAL_STREAM_UNARY_CALL: PARTIAL_STREAM_UNARY, IN_FLIGHT_PARTIAL_STREAM_STREAM_CALL: PARTIAL_STREAM_STREAM, } def hang_unary_unary(request, servicer_context): time.sleep(WAIT_TIME) def hang_unary_stream(request, servicer_context): time.sleep(WAIT_TIME) def hang_partial_unary_stream(request, servicer_context): for _ in range(test_constants.STREAM_LENGTH // 2): yield request time.sleep(WAIT_TIME) def hang_stream_unary(request_iterator, servicer_context): time.sleep(WAIT_TIME) def hang_partial_stream_unary(request_iterator, servicer_context): for _ in range(test_constants.STREAM_LENGTH // 2): next(request_iterator) time.sleep(WAIT_TIME) def hang_stream_stream(request_iterator, servicer_context): time.sleep(WAIT_TIME) def hang_partial_stream_stream(request_iterator, servicer_context): for _ in range(test_constants.STREAM_LENGTH // 2): yield next(request_iterator) time.sleep(WAIT_TIME) class MethodHandler(grpc.RpcMethodHandler): def __init__(self, request_streaming, response_streaming, partial_hang): self.request_streaming = request_streaming self.response_streaming = response_streaming self.request_deserializer = None self.response_serializer = None self.unary_unary = None self.unary_stream = None self.stream_unary = None self.stream_stream = None if self.request_streaming and self.response_streaming: if partial_hang: self.stream_stream = hang_partial_stream_stream else: self.stream_stream = hang_stream_stream elif self.request_streaming: if partial_hang: self.stream_unary = hang_partial_stream_unary else: self.stream_unary = hang_stream_unary elif self.response_streaming: if partial_hang: self.unary_stream = hang_partial_unary_stream else: self.unary_stream = hang_unary_stream else: self.unary_unary = hang_unary_unary class GenericHandler(grpc.GenericRpcHandler): def service(self, handler_call_details): if handler_call_details.method == UNARY_UNARY: return MethodHandler(False, False, False) elif handler_call_details.method == UNARY_STREAM: return MethodHandler(False, True, False) elif handler_call_details.method == STREAM_UNARY: return MethodHandler(True, False, False) elif handler_call_details.method == STREAM_STREAM: return MethodHandler(True, True, False) elif handler_call_details.method == PARTIAL_UNARY_STREAM: return MethodHandler(False, True, True) elif handler_call_details.method == PARTIAL_STREAM_UNARY: return MethodHandler(True, False, True) elif handler_call_details.method == PARTIAL_STREAM_STREAM: return MethodHandler(True, True, True) else: return None # Traditional executors will not exit until all their # current jobs complete. Because we submit jobs that will # never finish, we don't want to block exit on these jobs. class DaemonPool(object): def submit(self, fn, *args, **kwargs): thread = threading.Thread(target=fn, args=args, kwargs=kwargs) thread.daemon = True thread.start() def shutdown(self, wait=True): pass def infinite_request_iterator(): while True: yield REQUEST if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('scenario', type=str) parser.add_argument( '--wait_for_interrupt', dest='wait_for_interrupt', action='store_true') args = parser.parse_args() if args.scenario == UNSTARTED_SERVER: server = grpc.server(DaemonPool()) if args.wait_for_interrupt: time.sleep(WAIT_TIME) elif args.scenario == RUNNING_SERVER: server = grpc.server(DaemonPool()) port = server.add_insecure_port('[::]:0') server.start() if args.wait_for_interrupt: time.sleep(WAIT_TIME) elif args.scenario == POLL_CONNECTIVITY_NO_SERVER: channel = grpc.insecure_channel('localhost:12345') def connectivity_callback(connectivity): pass channel.subscribe(connectivity_callback, try_to_connect=True) if args.wait_for_interrupt: time.sleep(WAIT_TIME) elif args.scenario == POLL_CONNECTIVITY: server = grpc.server(DaemonPool()) port = server.add_insecure_port('[::]:0') server.start() channel = grpc.insecure_channel('localhost:%d' % port) def connectivity_callback(connectivity): pass channel.subscribe(connectivity_callback, try_to_connect=True) if args.wait_for_interrupt: time.sleep(WAIT_TIME) else: handler = GenericHandler() server = grpc.server(DaemonPool()) port = server.add_insecure_port('[::]:0') server.add_generic_rpc_handlers((handler,)) server.start() channel = grpc.insecure_channel('localhost:%d' % port) method = TEST_TO_METHOD[args.scenario] if args.scenario == IN_FLIGHT_UNARY_UNARY_CALL: multi_callable = channel.unary_unary(method) future = multi_callable.future(REQUEST) result, call = multi_callable.with_call(REQUEST) elif (args.scenario == IN_FLIGHT_UNARY_STREAM_CALL or args.scenario == IN_FLIGHT_PARTIAL_UNARY_STREAM_CALL): multi_callable = channel.unary_stream(method) response_iterator = multi_callable(REQUEST) for response in response_iterator: pass elif (args.scenario == IN_FLIGHT_STREAM_UNARY_CALL or args.scenario == IN_FLIGHT_PARTIAL_STREAM_UNARY_CALL): multi_callable = channel.stream_unary(method) future = multi_callable.future(infinite_request_iterator()) result, call = multi_callable.with_call( iter([REQUEST] * test_constants.STREAM_LENGTH)) elif (args.scenario == IN_FLIGHT_STREAM_STREAM_CALL or args.scenario == IN_FLIGHT_PARTIAL_STREAM_STREAM_CALL): multi_callable = channel.stream_stream(method) response_iterator = multi_callable(infinite_request_iterator()) for response in response_iterator: pass grpc-1.3.2/src/python/grpcio_tests/tests/unit/_exit_test.py000066400000000000000000000156101310511640000241210ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Tests clean exit of server/client on Python Interpreter exit/sigint. The tests in this module spawn a subprocess for each test case, the test is considered successful if it doesn't hang/timeout. """ import atexit import os import signal import six import subprocess import sys import threading import time import unittest from tests.unit import _exit_scenarios SCENARIO_FILE = os.path.abspath( os.path.join( os.path.dirname(os.path.realpath(__file__)), '_exit_scenarios.py')) INTERPRETER = sys.executable BASE_COMMAND = [INTERPRETER, SCENARIO_FILE] BASE_SIGTERM_COMMAND = BASE_COMMAND + ['--wait_for_interrupt'] INIT_TIME = 1.0 processes = [] process_lock = threading.Lock() # Make sure we attempt to clean up any # processes we may have left running def cleanup_processes(): with process_lock: for process in processes: try: process.kill() except Exception: pass atexit.register(cleanup_processes) def interrupt_and_wait(process): with process_lock: processes.append(process) time.sleep(INIT_TIME) os.kill(process.pid, signal.SIGINT) process.wait() def wait(process): with process_lock: processes.append(process) process.wait() @unittest.skip('https://github.com/grpc/grpc/issues/7311') class ExitTest(unittest.TestCase): def test_unstarted_server(self): process = subprocess.Popen( BASE_COMMAND + [_exit_scenarios.UNSTARTED_SERVER], stdout=sys.stdout, stderr=sys.stderr) wait(process) def test_unstarted_server_terminate(self): process = subprocess.Popen( BASE_SIGTERM_COMMAND + [_exit_scenarios.UNSTARTED_SERVER], stdout=sys.stdout) interrupt_and_wait(process) def test_running_server(self): process = subprocess.Popen( BASE_COMMAND + [_exit_scenarios.RUNNING_SERVER], stdout=sys.stdout, stderr=sys.stderr) wait(process) def test_running_server_terminate(self): process = subprocess.Popen( BASE_SIGTERM_COMMAND + [_exit_scenarios.RUNNING_SERVER], stdout=sys.stdout, stderr=sys.stderr) interrupt_and_wait(process) def test_poll_connectivity_no_server(self): process = subprocess.Popen( BASE_COMMAND + [_exit_scenarios.POLL_CONNECTIVITY_NO_SERVER], stdout=sys.stdout, stderr=sys.stderr) wait(process) def test_poll_connectivity_no_server_terminate(self): process = subprocess.Popen( BASE_SIGTERM_COMMAND + [_exit_scenarios.POLL_CONNECTIVITY_NO_SERVER], stdout=sys.stdout, stderr=sys.stderr) interrupt_and_wait(process) def test_poll_connectivity(self): process = subprocess.Popen( BASE_COMMAND + [_exit_scenarios.POLL_CONNECTIVITY], stdout=sys.stdout, stderr=sys.stderr) wait(process) def test_poll_connectivity_terminate(self): process = subprocess.Popen( BASE_SIGTERM_COMMAND + [_exit_scenarios.POLL_CONNECTIVITY], stdout=sys.stdout, stderr=sys.stderr) interrupt_and_wait(process) def test_in_flight_unary_unary_call(self): process = subprocess.Popen( BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_UNARY_UNARY_CALL], stdout=sys.stdout, stderr=sys.stderr) interrupt_and_wait(process) @unittest.skipIf(six.PY2, 'https://github.com/grpc/grpc/issues/6999') def test_in_flight_unary_stream_call(self): process = subprocess.Popen( BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_UNARY_STREAM_CALL], stdout=sys.stdout, stderr=sys.stderr) interrupt_and_wait(process) def test_in_flight_stream_unary_call(self): process = subprocess.Popen( BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_STREAM_UNARY_CALL], stdout=sys.stdout, stderr=sys.stderr) interrupt_and_wait(process) @unittest.skipIf(six.PY2, 'https://github.com/grpc/grpc/issues/6999') def test_in_flight_stream_stream_call(self): process = subprocess.Popen( BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_STREAM_STREAM_CALL], stdout=sys.stdout, stderr=sys.stderr) interrupt_and_wait(process) @unittest.skipIf(six.PY2, 'https://github.com/grpc/grpc/issues/6999') def test_in_flight_partial_unary_stream_call(self): process = subprocess.Popen( BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_PARTIAL_UNARY_STREAM_CALL], stdout=sys.stdout, stderr=sys.stderr) interrupt_and_wait(process) def test_in_flight_partial_stream_unary_call(self): process = subprocess.Popen( BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_PARTIAL_STREAM_UNARY_CALL], stdout=sys.stdout, stderr=sys.stderr) interrupt_and_wait(process) @unittest.skipIf(six.PY2, 'https://github.com/grpc/grpc/issues/6999') def test_in_flight_partial_stream_stream_call(self): process = subprocess.Popen( BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_PARTIAL_STREAM_STREAM_CALL], stdout=sys.stdout, stderr=sys.stderr) interrupt_and_wait(process) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_from_grpc_import_star.py000066400000000000000000000033301310511640000265060ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _BEFORE_IMPORT = tuple(globals()) from grpc import * _AFTER_IMPORT = tuple(globals()) GRPC_ELEMENTS = tuple( element for element in _AFTER_IMPORT if element not in _BEFORE_IMPORT and element != '_BEFORE_IMPORT') grpc-1.3.2/src/python/grpcio_tests/tests/unit/_invalid_metadata_test.py000066400000000000000000000205021310511640000264320ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Test of RPCs made against gRPC Python's application-layer API.""" import unittest import grpc from tests.unit.framework.common import test_constants _SERIALIZE_REQUEST = lambda bytestring: bytestring * 2 _DESERIALIZE_REQUEST = lambda bytestring: bytestring[len(bytestring) // 2:] _SERIALIZE_RESPONSE = lambda bytestring: bytestring * 3 _DESERIALIZE_RESPONSE = lambda bytestring: bytestring[:len(bytestring) // 3] _UNARY_UNARY = '/test/UnaryUnary' _UNARY_STREAM = '/test/UnaryStream' _STREAM_UNARY = '/test/StreamUnary' _STREAM_STREAM = '/test/StreamStream' def _unary_unary_multi_callable(channel): return channel.unary_unary(_UNARY_UNARY) def _unary_stream_multi_callable(channel): return channel.unary_stream( _UNARY_STREAM, request_serializer=_SERIALIZE_REQUEST, response_deserializer=_DESERIALIZE_RESPONSE) def _stream_unary_multi_callable(channel): return channel.stream_unary( _STREAM_UNARY, request_serializer=_SERIALIZE_REQUEST, response_deserializer=_DESERIALIZE_RESPONSE) def _stream_stream_multi_callable(channel): return channel.stream_stream(_STREAM_STREAM) class InvalidMetadataTest(unittest.TestCase): def setUp(self): self._channel = grpc.insecure_channel('localhost:8080') self._unary_unary = _unary_unary_multi_callable(self._channel) self._unary_stream = _unary_stream_multi_callable(self._channel) self._stream_unary = _stream_unary_multi_callable(self._channel) self._stream_stream = _stream_stream_multi_callable(self._channel) def testUnaryRequestBlockingUnaryResponse(self): request = b'\x07\x08' metadata = (('InVaLiD', 'UnaryRequestBlockingUnaryResponse'),) expected_error_details = "metadata was invalid: %s" % metadata with self.assertRaises(ValueError) as exception_context: self._unary_unary(request, metadata=metadata) self.assertIn(expected_error_details, str(exception_context.exception)) def testUnaryRequestBlockingUnaryResponseWithCall(self): request = b'\x07\x08' metadata = (('InVaLiD', 'UnaryRequestBlockingUnaryResponseWithCall'),) expected_error_details = "metadata was invalid: %s" % metadata with self.assertRaises(ValueError) as exception_context: self._unary_unary.with_call(request, metadata=metadata) self.assertIn(expected_error_details, str(exception_context.exception)) def testUnaryRequestFutureUnaryResponse(self): request = b'\x07\x08' metadata = (('InVaLiD', 'UnaryRequestFutureUnaryResponse'),) expected_error_details = "metadata was invalid: %s" % metadata response_future = self._unary_unary.future(request, metadata=metadata) with self.assertRaises(grpc.RpcError) as exception_context: response_future.result() self.assertEqual(exception_context.exception.details(), expected_error_details) self.assertEqual(exception_context.exception.code(), grpc.StatusCode.INTERNAL) self.assertEqual(response_future.details(), expected_error_details) self.assertEqual(response_future.code(), grpc.StatusCode.INTERNAL) def testUnaryRequestStreamResponse(self): request = b'\x37\x58' metadata = (('InVaLiD', 'UnaryRequestStreamResponse'),) expected_error_details = "metadata was invalid: %s" % metadata response_iterator = self._unary_stream(request, metadata=metadata) with self.assertRaises(grpc.RpcError) as exception_context: next(response_iterator) self.assertEqual(exception_context.exception.details(), expected_error_details) self.assertEqual(exception_context.exception.code(), grpc.StatusCode.INTERNAL) self.assertEqual(response_iterator.details(), expected_error_details) self.assertEqual(response_iterator.code(), grpc.StatusCode.INTERNAL) def testStreamRequestBlockingUnaryResponse(self): request_iterator = (b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) metadata = (('InVaLiD', 'StreamRequestBlockingUnaryResponse'),) expected_error_details = "metadata was invalid: %s" % metadata with self.assertRaises(ValueError) as exception_context: self._stream_unary(request_iterator, metadata=metadata) self.assertIn(expected_error_details, str(exception_context.exception)) def testStreamRequestBlockingUnaryResponseWithCall(self): request_iterator = (b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) metadata = (('InVaLiD', 'StreamRequestBlockingUnaryResponseWithCall'),) expected_error_details = "metadata was invalid: %s" % metadata multi_callable = _stream_unary_multi_callable(self._channel) with self.assertRaises(ValueError) as exception_context: multi_callable.with_call(request_iterator, metadata=metadata) self.assertIn(expected_error_details, str(exception_context.exception)) def testStreamRequestFutureUnaryResponse(self): request_iterator = (b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) metadata = (('InVaLiD', 'StreamRequestFutureUnaryResponse'),) expected_error_details = "metadata was invalid: %s" % metadata response_future = self._stream_unary.future( request_iterator, metadata=metadata) with self.assertRaises(grpc.RpcError) as exception_context: response_future.result() self.assertEqual(exception_context.exception.details(), expected_error_details) self.assertEqual(exception_context.exception.code(), grpc.StatusCode.INTERNAL) self.assertEqual(response_future.details(), expected_error_details) self.assertEqual(response_future.code(), grpc.StatusCode.INTERNAL) def testStreamRequestStreamResponse(self): request_iterator = (b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) metadata = (('InVaLiD', 'StreamRequestStreamResponse'),) expected_error_details = "metadata was invalid: %s" % metadata response_iterator = self._stream_stream( request_iterator, metadata=metadata) with self.assertRaises(grpc.RpcError) as exception_context: next(response_iterator) self.assertEqual(exception_context.exception.details(), expected_error_details) self.assertEqual(exception_context.exception.code(), grpc.StatusCode.INTERNAL) self.assertEqual(response_iterator.details(), expected_error_details) self.assertEqual(response_iterator.code(), grpc.StatusCode.INTERNAL) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py000066400000000000000000000226031310511640000270160ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import itertools import threading import unittest from concurrent import futures import grpc from grpc.framework.foundation import logging_pool from tests.unit.framework.common import test_constants from tests.unit.framework.common import test_control _SERIALIZE_REQUEST = lambda bytestring: bytestring * 2 _DESERIALIZE_REQUEST = lambda bytestring: bytestring[len(bytestring) // 2:] _SERIALIZE_RESPONSE = lambda bytestring: bytestring * 3 _DESERIALIZE_RESPONSE = lambda bytestring: bytestring[:len(bytestring) // 3] _UNARY_UNARY = '/test/UnaryUnary' _UNARY_STREAM = '/test/UnaryStream' _STREAM_UNARY = '/test/StreamUnary' _STREAM_STREAM = '/test/StreamStream' class _Callback(object): def __init__(self): self._condition = threading.Condition() self._value = None self._called = False def __call__(self, value): with self._condition: self._value = value self._called = True self._condition.notify_all() def value(self): with self._condition: while not self._called: self._condition.wait() return self._value class _Handler(object): def __init__(self, control): self._control = control def handle_unary_unary(self, request, servicer_context): self._control.control() if servicer_context is not None: servicer_context.set_trailing_metadata((('testkey', 'testvalue',),)) return request def handle_unary_stream(self, request, servicer_context): for _ in range(test_constants.STREAM_LENGTH): self._control.control() yield request self._control.control() if servicer_context is not None: servicer_context.set_trailing_metadata((('testkey', 'testvalue',),)) def handle_stream_unary(self, request_iterator, servicer_context): if servicer_context is not None: servicer_context.invocation_metadata() self._control.control() response_elements = [] for request in request_iterator: self._control.control() response_elements.append(request) self._control.control() if servicer_context is not None: servicer_context.set_trailing_metadata((('testkey', 'testvalue',),)) return b''.join(response_elements) def handle_stream_stream(self, request_iterator, servicer_context): self._control.control() if servicer_context is not None: servicer_context.set_trailing_metadata((('testkey', 'testvalue',),)) for request in request_iterator: self._control.control() yield request self._control.control() class _MethodHandler(grpc.RpcMethodHandler): def __init__(self, request_streaming, response_streaming, request_deserializer, response_serializer, unary_unary, unary_stream, stream_unary, stream_stream): self.request_streaming = request_streaming self.response_streaming = response_streaming self.request_deserializer = request_deserializer self.response_serializer = response_serializer self.unary_unary = unary_unary self.unary_stream = unary_stream self.stream_unary = stream_unary self.stream_stream = stream_stream class _GenericHandler(grpc.GenericRpcHandler): def __init__(self, handler): self._handler = handler def service(self, handler_call_details): if handler_call_details.method == _UNARY_UNARY: return _MethodHandler(False, False, None, None, self._handler.handle_unary_unary, None, None, None) elif handler_call_details.method == _UNARY_STREAM: return _MethodHandler(False, True, _DESERIALIZE_REQUEST, _SERIALIZE_RESPONSE, None, self._handler.handle_unary_stream, None, None) elif handler_call_details.method == _STREAM_UNARY: return _MethodHandler(True, False, _DESERIALIZE_REQUEST, _SERIALIZE_RESPONSE, None, None, self._handler.handle_stream_unary, None) elif handler_call_details.method == _STREAM_STREAM: return _MethodHandler(True, True, None, None, None, None, None, self._handler.handle_stream_stream) else: return None class FailAfterFewIterationsCounter(object): def __init__(self, high, bytestring): self._current = 0 self._high = high self._bytestring = bytestring def __iter__(self): return self def __next__(self): if self._current >= self._high: raise Exception("This is a deliberate failure in a unit test.") else: self._current += 1 return self._bytestring def _unary_unary_multi_callable(channel): return channel.unary_unary(_UNARY_UNARY) def _unary_stream_multi_callable(channel): return channel.unary_stream( _UNARY_STREAM, request_serializer=_SERIALIZE_REQUEST, response_deserializer=_DESERIALIZE_RESPONSE) def _stream_unary_multi_callable(channel): return channel.stream_unary( _STREAM_UNARY, request_serializer=_SERIALIZE_REQUEST, response_deserializer=_DESERIALIZE_RESPONSE) def _stream_stream_multi_callable(channel): return channel.stream_stream(_STREAM_STREAM) class InvocationDefectsTest(unittest.TestCase): def setUp(self): self._control = test_control.PauseFailControl() self._handler = _Handler(self._control) self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) self._server = grpc.server(self._server_pool) port = self._server.add_insecure_port('[::]:0') self._server.add_generic_rpc_handlers((_GenericHandler(self._handler),)) self._server.start() self._channel = grpc.insecure_channel('localhost:%d' % port) def tearDown(self): self._server.stop(0) def testIterableStreamRequestBlockingUnaryResponse(self): requests = [b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)] multi_callable = _stream_unary_multi_callable(self._channel) with self.assertRaises(grpc.RpcError): response = multi_callable( requests, metadata=( ('test', 'IterableStreamRequestBlockingUnaryResponse'),)) def testIterableStreamRequestFutureUnaryResponse(self): requests = [b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)] multi_callable = _stream_unary_multi_callable(self._channel) response_future = multi_callable.future( requests, metadata=(('test', 'IterableStreamRequestFutureUnaryResponse'),)) with self.assertRaises(grpc.RpcError): response = response_future.result() def testIterableStreamRequestStreamResponse(self): requests = [b'\x77\x58' for _ in range(test_constants.STREAM_LENGTH)] multi_callable = _stream_stream_multi_callable(self._channel) response_iterator = multi_callable( requests, metadata=(('test', 'IterableStreamRequestStreamResponse'),)) with self.assertRaises(grpc.RpcError): next(response_iterator) def testIteratorStreamRequestStreamResponse(self): requests_iterator = FailAfterFewIterationsCounter( test_constants.STREAM_LENGTH // 2, b'\x07\x08') multi_callable = _stream_stream_multi_callable(self._channel) response_iterator = multi_callable( requests_iterator, metadata=(('test', 'IteratorStreamRequestStreamResponse'),)) with self.assertRaises(grpc.RpcError): for _ in range(test_constants.STREAM_LENGTH // 2 + 1): next(response_iterator) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_junkdrawer/000077500000000000000000000000001310511640000237105ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/unit/_junkdrawer/__init__.py000066400000000000000000000027701310511640000260270ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/unit/_junkdrawer/stock_pb2.py000066400000000000000000000144661310511640000261630ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # TODO(nathaniel): Remove this from source control after having made # generation from the stock.proto source part of GRPC's build-and-test # process. # Generated by the protocol buffer compiler. DO NOT EDIT! # source: stock.proto import sys _b = sys.version_info[0] < 3 and (lambda x: x) or (lambda x: x.encode('latin1')) from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database from google.protobuf import descriptor_pb2 # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() DESCRIPTOR = _descriptor.FileDescriptor( name='stock.proto', package='stock', serialized_pb=_b( '\n\x0bstock.proto\x12\x05stock\">\n\x0cStockRequest\x12\x0e\n\x06symbol\x18\x01 \x01(\t\x12\x1e\n\x13num_trades_to_watch\x18\x02 \x01(\x05:\x01\x30\"+\n\nStockReply\x12\r\n\x05price\x18\x01 \x01(\x02\x12\x0e\n\x06symbol\x18\x02 \x01(\t2\x96\x02\n\x05Stock\x12=\n\x11GetLastTradePrice\x12\x13.stock.StockRequest\x1a\x11.stock.StockReply\"\x00\x12I\n\x19GetLastTradePriceMultiple\x12\x13.stock.StockRequest\x1a\x11.stock.StockReply\"\x00(\x01\x30\x01\x12?\n\x11WatchFutureTrades\x12\x13.stock.StockRequest\x1a\x11.stock.StockReply\"\x00\x30\x01\x12\x42\n\x14GetHighestTradePrice\x12\x13.stock.StockRequest\x1a\x11.stock.StockReply\"\x00(\x01' )) _sym_db.RegisterFileDescriptor(DESCRIPTOR) _STOCKREQUEST = _descriptor.Descriptor( name='StockRequest', full_name='stock.StockRequest', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='symbol', full_name='stock.StockRequest.symbol', index=0, number=1, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='num_trades_to_watch', full_name='stock.StockRequest.num_trades_to_watch', index=1, number=2, type=5, cpp_type=1, label=1, has_default_value=True, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[], nested_types=[], enum_types=[], options=None, is_extendable=False, extension_ranges=[], oneofs=[], serialized_start=22, serialized_end=84,) _STOCKREPLY = _descriptor.Descriptor( name='StockReply', full_name='stock.StockReply', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='price', full_name='stock.StockReply.price', index=0, number=1, type=2, cpp_type=6, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='symbol', full_name='stock.StockReply.symbol', index=1, number=2, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[], nested_types=[], enum_types=[], options=None, is_extendable=False, extension_ranges=[], oneofs=[], serialized_start=86, serialized_end=129,) DESCRIPTOR.message_types_by_name['StockRequest'] = _STOCKREQUEST DESCRIPTOR.message_types_by_name['StockReply'] = _STOCKREPLY StockRequest = _reflection.GeneratedProtocolMessageType( 'StockRequest', (_message.Message,), dict( DESCRIPTOR=_STOCKREQUEST, __module__='stock_pb2' # @@protoc_insertion_point(class_scope:stock.StockRequest) )) _sym_db.RegisterMessage(StockRequest) StockReply = _reflection.GeneratedProtocolMessageType( 'StockReply', (_message.Message,), dict( DESCRIPTOR=_STOCKREPLY, __module__='stock_pb2' # @@protoc_insertion_point(class_scope:stock.StockReply) )) _sym_db.RegisterMessage(StockReply) # @@protoc_insertion_point(module_scope) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py000066400000000000000000000527471310511640000274430ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Tests application-provided metadata, status code, and details.""" import threading import unittest import grpc from grpc.framework.foundation import logging_pool from tests.unit import test_common from tests.unit.framework.common import test_constants from tests.unit.framework.common import test_control _SERIALIZED_REQUEST = b'\x46\x47\x48' _SERIALIZED_RESPONSE = b'\x49\x50\x51' _REQUEST_SERIALIZER = lambda unused_request: _SERIALIZED_REQUEST _REQUEST_DESERIALIZER = lambda unused_serialized_request: object() _RESPONSE_SERIALIZER = lambda unused_response: _SERIALIZED_RESPONSE _RESPONSE_DESERIALIZER = lambda unused_serialized_resopnse: object() _SERVICE = 'test.TestService' _UNARY_UNARY = 'UnaryUnary' _UNARY_STREAM = 'UnaryStream' _STREAM_UNARY = 'StreamUnary' _STREAM_STREAM = 'StreamStream' _CLIENT_METADATA = (('client-md-key', 'client-md-key'), ('client-md-key-bin', b'\x00\x01')) _SERVER_INITIAL_METADATA = ( ('server-initial-md-key', 'server-initial-md-value'), ('server-initial-md-key-bin', b'\x00\x02')) _SERVER_TRAILING_METADATA = ( ('server-trailing-md-key', 'server-trailing-md-value'), ('server-trailing-md-key-bin', b'\x00\x03')) _NON_OK_CODE = grpc.StatusCode.NOT_FOUND _DETAILS = 'Test details!' class _Servicer(object): def __init__(self): self._lock = threading.Lock() self._code = None self._details = None self._exception = False self._return_none = False self._received_client_metadata = None def unary_unary(self, request, context): with self._lock: self._received_client_metadata = context.invocation_metadata() context.send_initial_metadata(_SERVER_INITIAL_METADATA) context.set_trailing_metadata(_SERVER_TRAILING_METADATA) if self._code is not None: context.set_code(self._code) if self._details is not None: context.set_details(self._details) if self._exception: raise test_control.Defect() else: return None if self._return_none else object() def unary_stream(self, request, context): with self._lock: self._received_client_metadata = context.invocation_metadata() context.send_initial_metadata(_SERVER_INITIAL_METADATA) context.set_trailing_metadata(_SERVER_TRAILING_METADATA) if self._code is not None: context.set_code(self._code) if self._details is not None: context.set_details(self._details) for _ in range(test_constants.STREAM_LENGTH // 2): yield _SERIALIZED_RESPONSE if self._exception: raise test_control.Defect() def stream_unary(self, request_iterator, context): with self._lock: self._received_client_metadata = context.invocation_metadata() context.send_initial_metadata(_SERVER_INITIAL_METADATA) context.set_trailing_metadata(_SERVER_TRAILING_METADATA) if self._code is not None: context.set_code(self._code) if self._details is not None: context.set_details(self._details) # TODO(https://github.com/grpc/grpc/issues/6891): just ignore the # request iterator. for ignored_request in request_iterator: pass if self._exception: raise test_control.Defect() else: return None if self._return_none else _SERIALIZED_RESPONSE def stream_stream(self, request_iterator, context): with self._lock: self._received_client_metadata = context.invocation_metadata() context.send_initial_metadata(_SERVER_INITIAL_METADATA) context.set_trailing_metadata(_SERVER_TRAILING_METADATA) if self._code is not None: context.set_code(self._code) if self._details is not None: context.set_details(self._details) # TODO(https://github.com/grpc/grpc/issues/6891): just ignore the # request iterator. for ignored_request in request_iterator: pass for _ in range(test_constants.STREAM_LENGTH // 3): yield object() if self._exception: raise test_control.Defect() def set_code(self, code): with self._lock: self._code = code def set_details(self, details): with self._lock: self._details = details def set_exception(self): with self._lock: self._exception = True def set_return_none(self): with self._lock: self._return_none = True def received_client_metadata(self): with self._lock: return self._received_client_metadata def _generic_handler(servicer): method_handlers = { _UNARY_UNARY: grpc.unary_unary_rpc_method_handler( servicer.unary_unary, request_deserializer=_REQUEST_DESERIALIZER, response_serializer=_RESPONSE_SERIALIZER), _UNARY_STREAM: grpc.unary_stream_rpc_method_handler(servicer.unary_stream), _STREAM_UNARY: grpc.stream_unary_rpc_method_handler(servicer.stream_unary), _STREAM_STREAM: grpc.stream_stream_rpc_method_handler( servicer.stream_stream, request_deserializer=_REQUEST_DESERIALIZER, response_serializer=_RESPONSE_SERIALIZER), } return grpc.method_handlers_generic_handler(_SERVICE, method_handlers) class MetadataCodeDetailsTest(unittest.TestCase): def setUp(self): self._servicer = _Servicer() self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) self._server = grpc.server( self._server_pool, handlers=(_generic_handler(self._servicer),)) port = self._server.add_insecure_port('[::]:0') self._server.start() channel = grpc.insecure_channel('localhost:{}'.format(port)) self._unary_unary = channel.unary_unary( '/'.join(('', _SERVICE, _UNARY_UNARY,)), request_serializer=_REQUEST_SERIALIZER, response_deserializer=_RESPONSE_DESERIALIZER,) self._unary_stream = channel.unary_stream( '/'.join(('', _SERVICE, _UNARY_STREAM,)),) self._stream_unary = channel.stream_unary( '/'.join(('', _SERVICE, _STREAM_UNARY,)),) self._stream_stream = channel.stream_stream( '/'.join(('', _SERVICE, _STREAM_STREAM,)), request_serializer=_REQUEST_SERIALIZER, response_deserializer=_RESPONSE_DESERIALIZER,) def testSuccessfulUnaryUnary(self): self._servicer.set_details(_DETAILS) unused_response, call = self._unary_unary.with_call( object(), metadata=_CLIENT_METADATA) self.assertTrue( test_common.metadata_transmitted( _CLIENT_METADATA, self._servicer.received_client_metadata())) self.assertTrue( test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, call.initial_metadata())) self.assertTrue( test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, call.trailing_metadata())) self.assertIs(grpc.StatusCode.OK, call.code()) self.assertEqual(_DETAILS, call.details()) def testSuccessfulUnaryStream(self): self._servicer.set_details(_DETAILS) call = self._unary_stream( _SERIALIZED_REQUEST, metadata=_CLIENT_METADATA) received_initial_metadata = call.initial_metadata() for _ in call: pass self.assertTrue( test_common.metadata_transmitted( _CLIENT_METADATA, self._servicer.received_client_metadata())) self.assertTrue( test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, received_initial_metadata)) self.assertTrue( test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, call.trailing_metadata())) self.assertIs(grpc.StatusCode.OK, call.code()) self.assertEqual(_DETAILS, call.details()) def testSuccessfulStreamUnary(self): self._servicer.set_details(_DETAILS) unused_response, call = self._stream_unary.with_call( iter([_SERIALIZED_REQUEST] * test_constants.STREAM_LENGTH), metadata=_CLIENT_METADATA) self.assertTrue( test_common.metadata_transmitted( _CLIENT_METADATA, self._servicer.received_client_metadata())) self.assertTrue( test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, call.initial_metadata())) self.assertTrue( test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, call.trailing_metadata())) self.assertIs(grpc.StatusCode.OK, call.code()) self.assertEqual(_DETAILS, call.details()) def testSuccessfulStreamStream(self): self._servicer.set_details(_DETAILS) call = self._stream_stream( iter([object()] * test_constants.STREAM_LENGTH), metadata=_CLIENT_METADATA) received_initial_metadata = call.initial_metadata() for _ in call: pass self.assertTrue( test_common.metadata_transmitted( _CLIENT_METADATA, self._servicer.received_client_metadata())) self.assertTrue( test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, received_initial_metadata)) self.assertTrue( test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, call.trailing_metadata())) self.assertIs(grpc.StatusCode.OK, call.code()) self.assertEqual(_DETAILS, call.details()) def testCustomCodeUnaryUnary(self): self._servicer.set_code(_NON_OK_CODE) self._servicer.set_details(_DETAILS) with self.assertRaises(grpc.RpcError) as exception_context: self._unary_unary.with_call(object(), metadata=_CLIENT_METADATA) self.assertTrue( test_common.metadata_transmitted( _CLIENT_METADATA, self._servicer.received_client_metadata())) self.assertTrue( test_common.metadata_transmitted( _SERVER_INITIAL_METADATA, exception_context.exception.initial_metadata())) self.assertTrue( test_common.metadata_transmitted( _SERVER_TRAILING_METADATA, exception_context.exception.trailing_metadata())) self.assertIs(_NON_OK_CODE, exception_context.exception.code()) self.assertEqual(_DETAILS, exception_context.exception.details()) def testCustomCodeUnaryStream(self): self._servicer.set_code(_NON_OK_CODE) self._servicer.set_details(_DETAILS) call = self._unary_stream( _SERIALIZED_REQUEST, metadata=_CLIENT_METADATA) received_initial_metadata = call.initial_metadata() with self.assertRaises(grpc.RpcError): for _ in call: pass self.assertTrue( test_common.metadata_transmitted( _CLIENT_METADATA, self._servicer.received_client_metadata())) self.assertTrue( test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, received_initial_metadata)) self.assertTrue( test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, call.trailing_metadata())) self.assertIs(_NON_OK_CODE, call.code()) self.assertEqual(_DETAILS, call.details()) def testCustomCodeStreamUnary(self): self._servicer.set_code(_NON_OK_CODE) self._servicer.set_details(_DETAILS) with self.assertRaises(grpc.RpcError) as exception_context: self._stream_unary.with_call( iter([_SERIALIZED_REQUEST] * test_constants.STREAM_LENGTH), metadata=_CLIENT_METADATA) self.assertTrue( test_common.metadata_transmitted( _CLIENT_METADATA, self._servicer.received_client_metadata())) self.assertTrue( test_common.metadata_transmitted( _SERVER_INITIAL_METADATA, exception_context.exception.initial_metadata())) self.assertTrue( test_common.metadata_transmitted( _SERVER_TRAILING_METADATA, exception_context.exception.trailing_metadata())) self.assertIs(_NON_OK_CODE, exception_context.exception.code()) self.assertEqual(_DETAILS, exception_context.exception.details()) def testCustomCodeStreamStream(self): self._servicer.set_code(_NON_OK_CODE) self._servicer.set_details(_DETAILS) call = self._stream_stream( iter([object()] * test_constants.STREAM_LENGTH), metadata=_CLIENT_METADATA) received_initial_metadata = call.initial_metadata() with self.assertRaises(grpc.RpcError) as exception_context: for _ in call: pass self.assertTrue( test_common.metadata_transmitted( _CLIENT_METADATA, self._servicer.received_client_metadata())) self.assertTrue( test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, received_initial_metadata)) self.assertTrue( test_common.metadata_transmitted( _SERVER_TRAILING_METADATA, exception_context.exception.trailing_metadata())) self.assertIs(_NON_OK_CODE, exception_context.exception.code()) self.assertEqual(_DETAILS, exception_context.exception.details()) def testCustomCodeExceptionUnaryUnary(self): self._servicer.set_code(_NON_OK_CODE) self._servicer.set_details(_DETAILS) self._servicer.set_exception() with self.assertRaises(grpc.RpcError) as exception_context: self._unary_unary.with_call(object(), metadata=_CLIENT_METADATA) self.assertTrue( test_common.metadata_transmitted( _CLIENT_METADATA, self._servicer.received_client_metadata())) self.assertTrue( test_common.metadata_transmitted( _SERVER_INITIAL_METADATA, exception_context.exception.initial_metadata())) self.assertTrue( test_common.metadata_transmitted( _SERVER_TRAILING_METADATA, exception_context.exception.trailing_metadata())) self.assertIs(_NON_OK_CODE, exception_context.exception.code()) self.assertEqual(_DETAILS, exception_context.exception.details()) def testCustomCodeExceptionUnaryStream(self): self._servicer.set_code(_NON_OK_CODE) self._servicer.set_details(_DETAILS) self._servicer.set_exception() call = self._unary_stream( _SERIALIZED_REQUEST, metadata=_CLIENT_METADATA) received_initial_metadata = call.initial_metadata() with self.assertRaises(grpc.RpcError): for _ in call: pass self.assertTrue( test_common.metadata_transmitted( _CLIENT_METADATA, self._servicer.received_client_metadata())) self.assertTrue( test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, received_initial_metadata)) self.assertTrue( test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, call.trailing_metadata())) self.assertIs(_NON_OK_CODE, call.code()) self.assertEqual(_DETAILS, call.details()) def testCustomCodeExceptionStreamUnary(self): self._servicer.set_code(_NON_OK_CODE) self._servicer.set_details(_DETAILS) self._servicer.set_exception() with self.assertRaises(grpc.RpcError) as exception_context: self._stream_unary.with_call( iter([_SERIALIZED_REQUEST] * test_constants.STREAM_LENGTH), metadata=_CLIENT_METADATA) self.assertTrue( test_common.metadata_transmitted( _CLIENT_METADATA, self._servicer.received_client_metadata())) self.assertTrue( test_common.metadata_transmitted( _SERVER_INITIAL_METADATA, exception_context.exception.initial_metadata())) self.assertTrue( test_common.metadata_transmitted( _SERVER_TRAILING_METADATA, exception_context.exception.trailing_metadata())) self.assertIs(_NON_OK_CODE, exception_context.exception.code()) self.assertEqual(_DETAILS, exception_context.exception.details()) def testCustomCodeExceptionStreamStream(self): self._servicer.set_code(_NON_OK_CODE) self._servicer.set_details(_DETAILS) self._servicer.set_exception() call = self._stream_stream( iter([object()] * test_constants.STREAM_LENGTH), metadata=_CLIENT_METADATA) received_initial_metadata = call.initial_metadata() with self.assertRaises(grpc.RpcError): for _ in call: pass self.assertTrue( test_common.metadata_transmitted( _CLIENT_METADATA, self._servicer.received_client_metadata())) self.assertTrue( test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, received_initial_metadata)) self.assertTrue( test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, call.trailing_metadata())) self.assertIs(_NON_OK_CODE, call.code()) self.assertEqual(_DETAILS, call.details()) def testCustomCodeReturnNoneUnaryUnary(self): self._servicer.set_code(_NON_OK_CODE) self._servicer.set_details(_DETAILS) self._servicer.set_return_none() with self.assertRaises(grpc.RpcError) as exception_context: self._unary_unary.with_call(object(), metadata=_CLIENT_METADATA) self.assertTrue( test_common.metadata_transmitted( _CLIENT_METADATA, self._servicer.received_client_metadata())) self.assertTrue( test_common.metadata_transmitted( _SERVER_INITIAL_METADATA, exception_context.exception.initial_metadata())) self.assertTrue( test_common.metadata_transmitted( _SERVER_TRAILING_METADATA, exception_context.exception.trailing_metadata())) self.assertIs(_NON_OK_CODE, exception_context.exception.code()) self.assertEqual(_DETAILS, exception_context.exception.details()) def testCustomCodeReturnNoneStreamUnary(self): self._servicer.set_code(_NON_OK_CODE) self._servicer.set_details(_DETAILS) self._servicer.set_return_none() with self.assertRaises(grpc.RpcError) as exception_context: self._stream_unary.with_call( iter([_SERIALIZED_REQUEST] * test_constants.STREAM_LENGTH), metadata=_CLIENT_METADATA) self.assertTrue( test_common.metadata_transmitted( _CLIENT_METADATA, self._servicer.received_client_metadata())) self.assertTrue( test_common.metadata_transmitted( _SERVER_INITIAL_METADATA, exception_context.exception.initial_metadata())) self.assertTrue( test_common.metadata_transmitted( _SERVER_TRAILING_METADATA, exception_context.exception.trailing_metadata())) self.assertIs(_NON_OK_CODE, exception_context.exception.code()) self.assertEqual(_DETAILS, exception_context.exception.details()) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_metadata_test.py000066400000000000000000000213401310511640000247250ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Tests server and client side metadata API.""" import unittest import weakref import grpc from grpc import _channel from grpc.framework.foundation import logging_pool from tests.unit import test_common from tests.unit.framework.common import test_constants _CHANNEL_ARGS = (('grpc.primary_user_agent', 'primary-agent'), ('grpc.secondary_user_agent', 'secondary-agent')) _REQUEST = b'\x00\x00\x00' _RESPONSE = b'\x00\x00\x00' _UNARY_UNARY = '/test/UnaryUnary' _UNARY_STREAM = '/test/UnaryStream' _STREAM_UNARY = '/test/StreamUnary' _STREAM_STREAM = '/test/StreamStream' _CLIENT_METADATA = (('client-md-key', 'client-md-key'), ('client-md-key-bin', b'\x00\x01')) _SERVER_INITIAL_METADATA = ( ('server-initial-md-key', 'server-initial-md-value'), ('server-initial-md-key-bin', b'\x00\x02')) _SERVER_TRAILING_METADATA = ( ('server-trailing-md-key', 'server-trailing-md-value'), ('server-trailing-md-key-bin', b'\x00\x03')) def user_agent(metadata): for key, val in metadata: if key == 'user-agent': return val raise KeyError('No user agent!') def validate_client_metadata(test, servicer_context): test.assertTrue( test_common.metadata_transmitted( _CLIENT_METADATA, servicer_context.invocation_metadata())) test.assertTrue( user_agent(servicer_context.invocation_metadata()) .startswith('primary-agent ' + _channel._USER_AGENT)) test.assertTrue( user_agent(servicer_context.invocation_metadata()) .endswith('secondary-agent')) def handle_unary_unary(test, request, servicer_context): validate_client_metadata(test, servicer_context) servicer_context.send_initial_metadata(_SERVER_INITIAL_METADATA) servicer_context.set_trailing_metadata(_SERVER_TRAILING_METADATA) return _RESPONSE def handle_unary_stream(test, request, servicer_context): validate_client_metadata(test, servicer_context) servicer_context.send_initial_metadata(_SERVER_INITIAL_METADATA) servicer_context.set_trailing_metadata(_SERVER_TRAILING_METADATA) for _ in range(test_constants.STREAM_LENGTH): yield _RESPONSE def handle_stream_unary(test, request_iterator, servicer_context): validate_client_metadata(test, servicer_context) servicer_context.send_initial_metadata(_SERVER_INITIAL_METADATA) servicer_context.set_trailing_metadata(_SERVER_TRAILING_METADATA) # TODO(issue:#6891) We should be able to remove this loop for request in request_iterator: pass return _RESPONSE def handle_stream_stream(test, request_iterator, servicer_context): validate_client_metadata(test, servicer_context) servicer_context.send_initial_metadata(_SERVER_INITIAL_METADATA) servicer_context.set_trailing_metadata(_SERVER_TRAILING_METADATA) # TODO(issue:#6891) We should be able to remove this loop, # and replace with return; yield for request in request_iterator: yield _RESPONSE class _MethodHandler(grpc.RpcMethodHandler): def __init__(self, test, request_streaming, response_streaming): self.request_streaming = request_streaming self.response_streaming = response_streaming self.request_deserializer = None self.response_serializer = None self.unary_unary = None self.unary_stream = None self.stream_unary = None self.stream_stream = None if self.request_streaming and self.response_streaming: self.stream_stream = lambda x, y: handle_stream_stream(test, x, y) elif self.request_streaming: self.stream_unary = lambda x, y: handle_stream_unary(test, x, y) elif self.response_streaming: self.unary_stream = lambda x, y: handle_unary_stream(test, x, y) else: self.unary_unary = lambda x, y: handle_unary_unary(test, x, y) class _GenericHandler(grpc.GenericRpcHandler): def __init__(self, test): self._test = test def service(self, handler_call_details): if handler_call_details.method == _UNARY_UNARY: return _MethodHandler(self._test, False, False) elif handler_call_details.method == _UNARY_STREAM: return _MethodHandler(self._test, False, True) elif handler_call_details.method == _STREAM_UNARY: return _MethodHandler(self._test, True, False) elif handler_call_details.method == _STREAM_STREAM: return _MethodHandler(self._test, True, True) else: return None class MetadataTest(unittest.TestCase): def setUp(self): self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) self._server = grpc.server( self._server_pool, handlers=(_GenericHandler(weakref.proxy(self)),)) port = self._server.add_insecure_port('[::]:0') self._server.start() self._channel = grpc.insecure_channel( 'localhost:%d' % port, options=_CHANNEL_ARGS) def tearDown(self): self._server.stop(0) def testUnaryUnary(self): multi_callable = self._channel.unary_unary(_UNARY_UNARY) unused_response, call = multi_callable.with_call( _REQUEST, metadata=_CLIENT_METADATA) self.assertTrue( test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, call.initial_metadata())) self.assertTrue( test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, call.trailing_metadata())) def testUnaryStream(self): multi_callable = self._channel.unary_stream(_UNARY_STREAM) call = multi_callable(_REQUEST, metadata=_CLIENT_METADATA) self.assertTrue( test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, call.initial_metadata())) for _ in call: pass self.assertTrue( test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, call.trailing_metadata())) def testStreamUnary(self): multi_callable = self._channel.stream_unary(_STREAM_UNARY) unused_response, call = multi_callable.with_call( iter([_REQUEST] * test_constants.STREAM_LENGTH), metadata=_CLIENT_METADATA) self.assertTrue( test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, call.initial_metadata())) self.assertTrue( test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, call.trailing_metadata())) def testStreamStream(self): multi_callable = self._channel.stream_stream(_STREAM_STREAM) call = multi_callable( iter([_REQUEST] * test_constants.STREAM_LENGTH), metadata=_CLIENT_METADATA) self.assertTrue( test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, call.initial_metadata())) for _ in call: pass self.assertTrue( test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, call.trailing_metadata())) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_resource_exhausted_test.py000066400000000000000000000227471310511640000270620ustar00rootroot00000000000000# Copyright 2017, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Tests server responding with RESOURCE_EXHAUSTED.""" import threading import unittest import grpc from grpc import _channel from grpc.framework.foundation import logging_pool from tests.unit import test_common from tests.unit.framework.common import test_constants _REQUEST = b'\x00\x00\x00' _RESPONSE = b'\x00\x00\x00' _UNARY_UNARY = '/test/UnaryUnary' _UNARY_STREAM = '/test/UnaryStream' _STREAM_UNARY = '/test/StreamUnary' _STREAM_STREAM = '/test/StreamStream' class _TestTrigger(object): def __init__(self, total_call_count): self._total_call_count = total_call_count self._pending_calls = 0 self._triggered = False self._finish_condition = threading.Condition() self._start_condition = threading.Condition() # Wait for all calls be be blocked in their handler def await_calls(self): with self._start_condition: while self._pending_calls < self._total_call_count: self._start_condition.wait() # Block in a response handler and wait for a trigger def await_trigger(self): with self._start_condition: self._pending_calls += 1 self._start_condition.notify() with self._finish_condition: if not self._triggered: self._finish_condition.wait() # Finish all response handlers def trigger(self): with self._finish_condition: self._triggered = True self._finish_condition.notify_all() def handle_unary_unary(trigger, request, servicer_context): trigger.await_trigger() return _RESPONSE def handle_unary_stream(trigger, request, servicer_context): trigger.await_trigger() for _ in range(test_constants.STREAM_LENGTH): yield _RESPONSE def handle_stream_unary(trigger, request_iterator, servicer_context): trigger.await_trigger() # TODO(issue:#6891) We should be able to remove this loop for request in request_iterator: pass return _RESPONSE def handle_stream_stream(trigger, request_iterator, servicer_context): trigger.await_trigger() # TODO(issue:#6891) We should be able to remove this loop, # and replace with return; yield for request in request_iterator: yield _RESPONSE class _MethodHandler(grpc.RpcMethodHandler): def __init__(self, trigger, request_streaming, response_streaming): self.request_streaming = request_streaming self.response_streaming = response_streaming self.request_deserializer = None self.response_serializer = None self.unary_unary = None self.unary_stream = None self.stream_unary = None self.stream_stream = None if self.request_streaming and self.response_streaming: self.stream_stream = ( lambda x, y: handle_stream_stream(trigger, x, y)) elif self.request_streaming: self.stream_unary = lambda x, y: handle_stream_unary(trigger, x, y) elif self.response_streaming: self.unary_stream = lambda x, y: handle_unary_stream(trigger, x, y) else: self.unary_unary = lambda x, y: handle_unary_unary(trigger, x, y) class _GenericHandler(grpc.GenericRpcHandler): def __init__(self, trigger): self._trigger = trigger def service(self, handler_call_details): if handler_call_details.method == _UNARY_UNARY: return _MethodHandler(self._trigger, False, False) elif handler_call_details.method == _UNARY_STREAM: return _MethodHandler(self._trigger, False, True) elif handler_call_details.method == _STREAM_UNARY: return _MethodHandler(self._trigger, True, False) elif handler_call_details.method == _STREAM_STREAM: return _MethodHandler(self._trigger, True, True) else: return None class ResourceExhaustedTest(unittest.TestCase): def setUp(self): self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) self._trigger = _TestTrigger(test_constants.THREAD_CONCURRENCY) self._server = grpc.server( self._server_pool, handlers=(_GenericHandler(self._trigger),), maximum_concurrent_rpcs=test_constants.THREAD_CONCURRENCY) port = self._server.add_insecure_port('[::]:0') self._server.start() self._channel = grpc.insecure_channel('localhost:%d' % port) def tearDown(self): self._server.stop(0) def testUnaryUnary(self): multi_callable = self._channel.unary_unary(_UNARY_UNARY) futures = [] for _ in range(test_constants.THREAD_CONCURRENCY): futures.append(multi_callable.future(_REQUEST)) self._trigger.await_calls() with self.assertRaises(grpc.RpcError) as exception_context: multi_callable(_REQUEST) self.assertEqual(grpc.StatusCode.RESOURCE_EXHAUSTED, exception_context.exception.code()) future_exception = multi_callable.future(_REQUEST) self.assertEqual(grpc.StatusCode.RESOURCE_EXHAUSTED, future_exception.exception().code()) self._trigger.trigger() for future in futures: self.assertEqual(_RESPONSE, future.result()) # Ensure a new request can be handled self.assertEqual(_RESPONSE, multi_callable(_REQUEST)) def testUnaryStream(self): multi_callable = self._channel.unary_stream(_UNARY_STREAM) calls = [] for _ in range(test_constants.THREAD_CONCURRENCY): calls.append(multi_callable(_REQUEST)) self._trigger.await_calls() with self.assertRaises(grpc.RpcError) as exception_context: next(multi_callable(_REQUEST)) self.assertEqual(grpc.StatusCode.RESOURCE_EXHAUSTED, exception_context.exception.code()) self._trigger.trigger() for call in calls: for response in call: self.assertEqual(_RESPONSE, response) # Ensure a new request can be handled new_call = multi_callable(_REQUEST) for response in new_call: self.assertEqual(_RESPONSE, response) def testStreamUnary(self): multi_callable = self._channel.stream_unary(_STREAM_UNARY) futures = [] request = iter([_REQUEST] * test_constants.STREAM_LENGTH) for _ in range(test_constants.THREAD_CONCURRENCY): futures.append(multi_callable.future(request)) self._trigger.await_calls() with self.assertRaises(grpc.RpcError) as exception_context: multi_callable(request) self.assertEqual(grpc.StatusCode.RESOURCE_EXHAUSTED, exception_context.exception.code()) future_exception = multi_callable.future(request) self.assertEqual(grpc.StatusCode.RESOURCE_EXHAUSTED, future_exception.exception().code()) self._trigger.trigger() for future in futures: self.assertEqual(_RESPONSE, future.result()) # Ensure a new request can be handled self.assertEqual(_RESPONSE, multi_callable(request)) def testStreamStream(self): multi_callable = self._channel.stream_stream(_STREAM_STREAM) calls = [] request = iter([_REQUEST] * test_constants.STREAM_LENGTH) for _ in range(test_constants.THREAD_CONCURRENCY): calls.append(multi_callable(request)) self._trigger.await_calls() with self.assertRaises(grpc.RpcError) as exception_context: next(multi_callable(request)) self.assertEqual(grpc.StatusCode.RESOURCE_EXHAUSTED, exception_context.exception.code()) self._trigger.trigger() for call in calls: for response in call: self.assertEqual(_RESPONSE, response) # Ensure a new request can be handled new_call = multi_callable(request) for response in new_call: self.assertEqual(_RESPONSE, response) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_rpc_test.py000066400000000000000000001066061310511640000237420ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Test of RPCs made against gRPC Python's application-layer API.""" import itertools import threading import unittest from concurrent import futures import grpc from grpc.framework.foundation import logging_pool from tests.unit.framework.common import test_constants from tests.unit.framework.common import test_control _SERIALIZE_REQUEST = lambda bytestring: bytestring * 2 _DESERIALIZE_REQUEST = lambda bytestring: bytestring[len(bytestring) // 2:] _SERIALIZE_RESPONSE = lambda bytestring: bytestring * 3 _DESERIALIZE_RESPONSE = lambda bytestring: bytestring[:len(bytestring) // 3] _UNARY_UNARY = '/test/UnaryUnary' _UNARY_STREAM = '/test/UnaryStream' _STREAM_UNARY = '/test/StreamUnary' _STREAM_STREAM = '/test/StreamStream' class _Callback(object): def __init__(self): self._condition = threading.Condition() self._value = None self._called = False def __call__(self, value): with self._condition: self._value = value self._called = True self._condition.notify_all() def value(self): with self._condition: while not self._called: self._condition.wait() return self._value class _Handler(object): def __init__(self, control): self._control = control def handle_unary_unary(self, request, servicer_context): self._control.control() if servicer_context is not None: servicer_context.set_trailing_metadata((('testkey', 'testvalue',),)) # TODO(https://github.com/grpc/grpc/issues/8483): test the values # returned by these methods rather than only "smoke" testing that # the return after having been called. servicer_context.is_active() servicer_context.time_remaining() return request def handle_unary_stream(self, request, servicer_context): for _ in range(test_constants.STREAM_LENGTH): self._control.control() yield request self._control.control() if servicer_context is not None: servicer_context.set_trailing_metadata((('testkey', 'testvalue',),)) def handle_stream_unary(self, request_iterator, servicer_context): if servicer_context is not None: servicer_context.invocation_metadata() self._control.control() response_elements = [] for request in request_iterator: self._control.control() response_elements.append(request) self._control.control() if servicer_context is not None: servicer_context.set_trailing_metadata((('testkey', 'testvalue',),)) return b''.join(response_elements) def handle_stream_stream(self, request_iterator, servicer_context): self._control.control() if servicer_context is not None: servicer_context.set_trailing_metadata((('testkey', 'testvalue',),)) for request in request_iterator: self._control.control() yield request self._control.control() class _MethodHandler(grpc.RpcMethodHandler): def __init__(self, request_streaming, response_streaming, request_deserializer, response_serializer, unary_unary, unary_stream, stream_unary, stream_stream): self.request_streaming = request_streaming self.response_streaming = response_streaming self.request_deserializer = request_deserializer self.response_serializer = response_serializer self.unary_unary = unary_unary self.unary_stream = unary_stream self.stream_unary = stream_unary self.stream_stream = stream_stream class _GenericHandler(grpc.GenericRpcHandler): def __init__(self, handler): self._handler = handler def service(self, handler_call_details): if handler_call_details.method == _UNARY_UNARY: return _MethodHandler(False, False, None, None, self._handler.handle_unary_unary, None, None, None) elif handler_call_details.method == _UNARY_STREAM: return _MethodHandler(False, True, _DESERIALIZE_REQUEST, _SERIALIZE_RESPONSE, None, self._handler.handle_unary_stream, None, None) elif handler_call_details.method == _STREAM_UNARY: return _MethodHandler(True, False, _DESERIALIZE_REQUEST, _SERIALIZE_RESPONSE, None, None, self._handler.handle_stream_unary, None) elif handler_call_details.method == _STREAM_STREAM: return _MethodHandler(True, True, None, None, None, None, None, self._handler.handle_stream_stream) else: return None def _unary_unary_multi_callable(channel): return channel.unary_unary(_UNARY_UNARY) def _unary_stream_multi_callable(channel): return channel.unary_stream( _UNARY_STREAM, request_serializer=_SERIALIZE_REQUEST, response_deserializer=_DESERIALIZE_RESPONSE) def _stream_unary_multi_callable(channel): return channel.stream_unary( _STREAM_UNARY, request_serializer=_SERIALIZE_REQUEST, response_deserializer=_DESERIALIZE_RESPONSE) def _stream_stream_multi_callable(channel): return channel.stream_stream(_STREAM_STREAM) class RPCTest(unittest.TestCase): def setUp(self): self._control = test_control.PauseFailControl() self._handler = _Handler(self._control) self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) self._server = grpc.server(self._server_pool) port = self._server.add_insecure_port('[::]:0') self._server.add_generic_rpc_handlers((_GenericHandler(self._handler),)) self._server.start() self._channel = grpc.insecure_channel('localhost:%d' % port) def tearDown(self): self._server.stop(None) self._server_pool.shutdown(wait=True) def testUnrecognizedMethod(self): request = b'abc' with self.assertRaises(grpc.RpcError) as exception_context: self._channel.unary_unary('NoSuchMethod')(request) self.assertEqual(grpc.StatusCode.UNIMPLEMENTED, exception_context.exception.code()) def testSuccessfulUnaryRequestBlockingUnaryResponse(self): request = b'\x07\x08' expected_response = self._handler.handle_unary_unary(request, None) multi_callable = _unary_unary_multi_callable(self._channel) response = multi_callable( request, metadata=(('test', 'SuccessfulUnaryRequestBlockingUnaryResponse'),)) self.assertEqual(expected_response, response) def testSuccessfulUnaryRequestBlockingUnaryResponseWithCall(self): request = b'\x07\x08' expected_response = self._handler.handle_unary_unary(request, None) multi_callable = _unary_unary_multi_callable(self._channel) response, call = multi_callable.with_call( request, metadata=(('test', 'SuccessfulUnaryRequestBlockingUnaryResponseWithCall'),)) self.assertEqual(expected_response, response) self.assertIs(grpc.StatusCode.OK, call.code()) def testSuccessfulUnaryRequestFutureUnaryResponse(self): request = b'\x07\x08' expected_response = self._handler.handle_unary_unary(request, None) multi_callable = _unary_unary_multi_callable(self._channel) response_future = multi_callable.future( request, metadata=(('test', 'SuccessfulUnaryRequestFutureUnaryResponse'),)) response = response_future.result() self.assertIsInstance(response_future, grpc.Future) self.assertIsInstance(response_future, grpc.Call) self.assertEqual(expected_response, response) self.assertIsNone(response_future.exception()) self.assertIsNone(response_future.traceback()) def testSuccessfulUnaryRequestStreamResponse(self): request = b'\x37\x58' expected_responses = tuple( self._handler.handle_unary_stream(request, None)) multi_callable = _unary_stream_multi_callable(self._channel) response_iterator = multi_callable( request, metadata=(('test', 'SuccessfulUnaryRequestStreamResponse'),)) responses = tuple(response_iterator) self.assertSequenceEqual(expected_responses, responses) def testSuccessfulStreamRequestBlockingUnaryResponse(self): requests = tuple(b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) expected_response = self._handler.handle_stream_unary( iter(requests), None) request_iterator = iter(requests) multi_callable = _stream_unary_multi_callable(self._channel) response = multi_callable( request_iterator, metadata=( ('test', 'SuccessfulStreamRequestBlockingUnaryResponse'),)) self.assertEqual(expected_response, response) def testSuccessfulStreamRequestBlockingUnaryResponseWithCall(self): requests = tuple(b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) expected_response = self._handler.handle_stream_unary( iter(requests), None) request_iterator = iter(requests) multi_callable = _stream_unary_multi_callable(self._channel) response, call = multi_callable.with_call( request_iterator, metadata=( ('test', 'SuccessfulStreamRequestBlockingUnaryResponseWithCall'),)) self.assertEqual(expected_response, response) self.assertIs(grpc.StatusCode.OK, call.code()) def testSuccessfulStreamRequestFutureUnaryResponse(self): requests = tuple(b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) expected_response = self._handler.handle_stream_unary( iter(requests), None) request_iterator = iter(requests) multi_callable = _stream_unary_multi_callable(self._channel) response_future = multi_callable.future( request_iterator, metadata=(('test', 'SuccessfulStreamRequestFutureUnaryResponse'),)) response = response_future.result() self.assertEqual(expected_response, response) self.assertIsNone(response_future.exception()) self.assertIsNone(response_future.traceback()) def testSuccessfulStreamRequestStreamResponse(self): requests = tuple(b'\x77\x58' for _ in range(test_constants.STREAM_LENGTH)) expected_responses = tuple( self._handler.handle_stream_stream(iter(requests), None)) request_iterator = iter(requests) multi_callable = _stream_stream_multi_callable(self._channel) response_iterator = multi_callable( request_iterator, metadata=(('test', 'SuccessfulStreamRequestStreamResponse'),)) responses = tuple(response_iterator) self.assertSequenceEqual(expected_responses, responses) def testSequentialInvocations(self): first_request = b'\x07\x08' second_request = b'\x0809' expected_first_response = self._handler.handle_unary_unary( first_request, None) expected_second_response = self._handler.handle_unary_unary( second_request, None) multi_callable = _unary_unary_multi_callable(self._channel) first_response = multi_callable( first_request, metadata=(('test', 'SequentialInvocations'),)) second_response = multi_callable( second_request, metadata=(('test', 'SequentialInvocations'),)) self.assertEqual(expected_first_response, first_response) self.assertEqual(expected_second_response, second_response) def testConcurrentBlockingInvocations(self): pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) requests = tuple(b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) expected_response = self._handler.handle_stream_unary( iter(requests), None) expected_responses = [expected_response ] * test_constants.THREAD_CONCURRENCY response_futures = [None] * test_constants.THREAD_CONCURRENCY multi_callable = _stream_unary_multi_callable(self._channel) for index in range(test_constants.THREAD_CONCURRENCY): request_iterator = iter(requests) response_future = pool.submit( multi_callable, request_iterator, metadata=(('test', 'ConcurrentBlockingInvocations'),)) response_futures[index] = response_future responses = tuple(response_future.result() for response_future in response_futures) pool.shutdown(wait=True) self.assertSequenceEqual(expected_responses, responses) def testConcurrentFutureInvocations(self): requests = tuple(b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) expected_response = self._handler.handle_stream_unary( iter(requests), None) expected_responses = [expected_response ] * test_constants.THREAD_CONCURRENCY response_futures = [None] * test_constants.THREAD_CONCURRENCY multi_callable = _stream_unary_multi_callable(self._channel) for index in range(test_constants.THREAD_CONCURRENCY): request_iterator = iter(requests) response_future = multi_callable.future( request_iterator, metadata=(('test', 'ConcurrentFutureInvocations'),)) response_futures[index] = response_future responses = tuple(response_future.result() for response_future in response_futures) self.assertSequenceEqual(expected_responses, responses) def testWaitingForSomeButNotAllConcurrentFutureInvocations(self): pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) request = b'\x67\x68' expected_response = self._handler.handle_unary_unary(request, None) response_futures = [None] * test_constants.THREAD_CONCURRENCY lock = threading.Lock() test_is_running_cell = [True] def wrap_future(future): def wrap(): try: return future.result() except grpc.RpcError: with lock: if test_is_running_cell[0]: raise return None return wrap multi_callable = _unary_unary_multi_callable(self._channel) for index in range(test_constants.THREAD_CONCURRENCY): inner_response_future = multi_callable.future( request, metadata=( ('test', 'WaitingForSomeButNotAllConcurrentFutureInvocations'),)) outer_response_future = pool.submit( wrap_future(inner_response_future)) response_futures[index] = outer_response_future some_completed_response_futures_iterator = itertools.islice( futures.as_completed(response_futures), test_constants.THREAD_CONCURRENCY // 2) for response_future in some_completed_response_futures_iterator: self.assertEqual(expected_response, response_future.result()) with lock: test_is_running_cell[0] = False def testConsumingOneStreamResponseUnaryRequest(self): request = b'\x57\x38' multi_callable = _unary_stream_multi_callable(self._channel) response_iterator = multi_callable( request, metadata=(('test', 'ConsumingOneStreamResponseUnaryRequest'),)) next(response_iterator) def testConsumingSomeButNotAllStreamResponsesUnaryRequest(self): request = b'\x57\x38' multi_callable = _unary_stream_multi_callable(self._channel) response_iterator = multi_callable( request, metadata=( ('test', 'ConsumingSomeButNotAllStreamResponsesUnaryRequest'),)) for _ in range(test_constants.STREAM_LENGTH // 2): next(response_iterator) def testConsumingSomeButNotAllStreamResponsesStreamRequest(self): requests = tuple(b'\x67\x88' for _ in range(test_constants.STREAM_LENGTH)) request_iterator = iter(requests) multi_callable = _stream_stream_multi_callable(self._channel) response_iterator = multi_callable( request_iterator, metadata=(('test', 'ConsumingSomeButNotAllStreamResponsesStreamRequest'),)) for _ in range(test_constants.STREAM_LENGTH // 2): next(response_iterator) def testConsumingTooManyStreamResponsesStreamRequest(self): requests = tuple(b'\x67\x88' for _ in range(test_constants.STREAM_LENGTH)) request_iterator = iter(requests) multi_callable = _stream_stream_multi_callable(self._channel) response_iterator = multi_callable( request_iterator, metadata=( ('test', 'ConsumingTooManyStreamResponsesStreamRequest'),)) for _ in range(test_constants.STREAM_LENGTH): next(response_iterator) for _ in range(test_constants.STREAM_LENGTH): with self.assertRaises(StopIteration): next(response_iterator) self.assertIsNotNone(response_iterator.initial_metadata()) self.assertIs(grpc.StatusCode.OK, response_iterator.code()) self.assertIsNotNone(response_iterator.details()) self.assertIsNotNone(response_iterator.trailing_metadata()) def testCancelledUnaryRequestUnaryResponse(self): request = b'\x07\x17' multi_callable = _unary_unary_multi_callable(self._channel) with self._control.pause(): response_future = multi_callable.future( request, metadata=(('test', 'CancelledUnaryRequestUnaryResponse'),)) response_future.cancel() self.assertTrue(response_future.cancelled()) with self.assertRaises(grpc.FutureCancelledError): response_future.result() with self.assertRaises(grpc.FutureCancelledError): response_future.exception() with self.assertRaises(grpc.FutureCancelledError): response_future.traceback() self.assertIs(grpc.StatusCode.CANCELLED, response_future.code()) def testCancelledUnaryRequestStreamResponse(self): request = b'\x07\x19' multi_callable = _unary_stream_multi_callable(self._channel) with self._control.pause(): response_iterator = multi_callable( request, metadata=(('test', 'CancelledUnaryRequestStreamResponse'),)) self._control.block_until_paused() response_iterator.cancel() with self.assertRaises(grpc.RpcError) as exception_context: next(response_iterator) self.assertIs(grpc.StatusCode.CANCELLED, exception_context.exception.code()) self.assertIsNotNone(response_iterator.initial_metadata()) self.assertIs(grpc.StatusCode.CANCELLED, response_iterator.code()) self.assertIsNotNone(response_iterator.details()) self.assertIsNotNone(response_iterator.trailing_metadata()) def testCancelledStreamRequestUnaryResponse(self): requests = tuple(b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) request_iterator = iter(requests) multi_callable = _stream_unary_multi_callable(self._channel) with self._control.pause(): response_future = multi_callable.future( request_iterator, metadata=(('test', 'CancelledStreamRequestUnaryResponse'),)) self._control.block_until_paused() response_future.cancel() self.assertTrue(response_future.cancelled()) with self.assertRaises(grpc.FutureCancelledError): response_future.result() with self.assertRaises(grpc.FutureCancelledError): response_future.exception() with self.assertRaises(grpc.FutureCancelledError): response_future.traceback() self.assertIsNotNone(response_future.initial_metadata()) self.assertIs(grpc.StatusCode.CANCELLED, response_future.code()) self.assertIsNotNone(response_future.details()) self.assertIsNotNone(response_future.trailing_metadata()) def testCancelledStreamRequestStreamResponse(self): requests = tuple(b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) request_iterator = iter(requests) multi_callable = _stream_stream_multi_callable(self._channel) with self._control.pause(): response_iterator = multi_callable( request_iterator, metadata=(('test', 'CancelledStreamRequestStreamResponse'),)) response_iterator.cancel() with self.assertRaises(grpc.RpcError): next(response_iterator) self.assertIsNotNone(response_iterator.initial_metadata()) self.assertIs(grpc.StatusCode.CANCELLED, response_iterator.code()) self.assertIsNotNone(response_iterator.details()) self.assertIsNotNone(response_iterator.trailing_metadata()) def testExpiredUnaryRequestBlockingUnaryResponse(self): request = b'\x07\x17' multi_callable = _unary_unary_multi_callable(self._channel) with self._control.pause(): with self.assertRaises(grpc.RpcError) as exception_context: multi_callable.with_call( request, timeout=test_constants.SHORT_TIMEOUT, metadata=( ('test', 'ExpiredUnaryRequestBlockingUnaryResponse'),)) self.assertIsInstance(exception_context.exception, grpc.Call) self.assertIsNotNone(exception_context.exception.initial_metadata()) self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, exception_context.exception.code()) self.assertIsNotNone(exception_context.exception.details()) self.assertIsNotNone(exception_context.exception.trailing_metadata()) def testExpiredUnaryRequestFutureUnaryResponse(self): request = b'\x07\x17' callback = _Callback() multi_callable = _unary_unary_multi_callable(self._channel) with self._control.pause(): response_future = multi_callable.future( request, timeout=test_constants.SHORT_TIMEOUT, metadata=(('test', 'ExpiredUnaryRequestFutureUnaryResponse'),)) response_future.add_done_callback(callback) value_passed_to_callback = callback.value() self.assertIs(response_future, value_passed_to_callback) self.assertIsNotNone(response_future.initial_metadata()) self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, response_future.code()) self.assertIsNotNone(response_future.details()) self.assertIsNotNone(response_future.trailing_metadata()) with self.assertRaises(grpc.RpcError) as exception_context: response_future.result() self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, exception_context.exception.code()) self.assertIsInstance(response_future.exception(), grpc.RpcError) self.assertIsNotNone(response_future.traceback()) self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, response_future.exception().code()) def testExpiredUnaryRequestStreamResponse(self): request = b'\x07\x19' multi_callable = _unary_stream_multi_callable(self._channel) with self._control.pause(): with self.assertRaises(grpc.RpcError) as exception_context: response_iterator = multi_callable( request, timeout=test_constants.SHORT_TIMEOUT, metadata=(('test', 'ExpiredUnaryRequestStreamResponse'),)) next(response_iterator) self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, exception_context.exception.code()) self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, response_iterator.code()) def testExpiredStreamRequestBlockingUnaryResponse(self): requests = tuple(b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) request_iterator = iter(requests) multi_callable = _stream_unary_multi_callable(self._channel) with self._control.pause(): with self.assertRaises(grpc.RpcError) as exception_context: multi_callable( request_iterator, timeout=test_constants.SHORT_TIMEOUT, metadata=( ('test', 'ExpiredStreamRequestBlockingUnaryResponse'),)) self.assertIsInstance(exception_context.exception, grpc.RpcError) self.assertIsInstance(exception_context.exception, grpc.Call) self.assertIsNotNone(exception_context.exception.initial_metadata()) self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, exception_context.exception.code()) self.assertIsNotNone(exception_context.exception.details()) self.assertIsNotNone(exception_context.exception.trailing_metadata()) def testExpiredStreamRequestFutureUnaryResponse(self): requests = tuple(b'\x07\x18' for _ in range(test_constants.STREAM_LENGTH)) request_iterator = iter(requests) callback = _Callback() multi_callable = _stream_unary_multi_callable(self._channel) with self._control.pause(): response_future = multi_callable.future( request_iterator, timeout=test_constants.SHORT_TIMEOUT, metadata=(('test', 'ExpiredStreamRequestFutureUnaryResponse'),)) with self.assertRaises(grpc.FutureTimeoutError): response_future.result(timeout=test_constants.SHORT_TIMEOUT / 2.0) response_future.add_done_callback(callback) value_passed_to_callback = callback.value() with self.assertRaises(grpc.RpcError) as exception_context: response_future.result() self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, response_future.code()) self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, exception_context.exception.code()) self.assertIsInstance(response_future.exception(), grpc.RpcError) self.assertIsNotNone(response_future.traceback()) self.assertIs(response_future, value_passed_to_callback) self.assertIsNotNone(response_future.initial_metadata()) self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, response_future.code()) self.assertIsNotNone(response_future.details()) self.assertIsNotNone(response_future.trailing_metadata()) def testExpiredStreamRequestStreamResponse(self): requests = tuple(b'\x67\x18' for _ in range(test_constants.STREAM_LENGTH)) request_iterator = iter(requests) multi_callable = _stream_stream_multi_callable(self._channel) with self._control.pause(): with self.assertRaises(grpc.RpcError) as exception_context: response_iterator = multi_callable( request_iterator, timeout=test_constants.SHORT_TIMEOUT, metadata=(('test', 'ExpiredStreamRequestStreamResponse'),)) next(response_iterator) self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, exception_context.exception.code()) self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, response_iterator.code()) def testFailedUnaryRequestBlockingUnaryResponse(self): request = b'\x37\x17' multi_callable = _unary_unary_multi_callable(self._channel) with self._control.fail(): with self.assertRaises(grpc.RpcError) as exception_context: multi_callable.with_call( request, metadata=( ('test', 'FailedUnaryRequestBlockingUnaryResponse'),)) self.assertIs(grpc.StatusCode.UNKNOWN, exception_context.exception.code()) def testFailedUnaryRequestFutureUnaryResponse(self): request = b'\x37\x17' callback = _Callback() multi_callable = _unary_unary_multi_callable(self._channel) with self._control.fail(): response_future = multi_callable.future( request, metadata=(('test', 'FailedUnaryRequestFutureUnaryResponse'),)) response_future.add_done_callback(callback) value_passed_to_callback = callback.value() self.assertIsInstance(response_future, grpc.Future) self.assertIsInstance(response_future, grpc.Call) with self.assertRaises(grpc.RpcError) as exception_context: response_future.result() self.assertIs(grpc.StatusCode.UNKNOWN, exception_context.exception.code()) self.assertIsInstance(response_future.exception(), grpc.RpcError) self.assertIsNotNone(response_future.traceback()) self.assertIs(grpc.StatusCode.UNKNOWN, response_future.exception().code()) self.assertIs(response_future, value_passed_to_callback) def testFailedUnaryRequestStreamResponse(self): request = b'\x37\x17' multi_callable = _unary_stream_multi_callable(self._channel) with self.assertRaises(grpc.RpcError) as exception_context: with self._control.fail(): response_iterator = multi_callable( request, metadata=(('test', 'FailedUnaryRequestStreamResponse'),)) next(response_iterator) self.assertIs(grpc.StatusCode.UNKNOWN, exception_context.exception.code()) def testFailedStreamRequestBlockingUnaryResponse(self): requests = tuple(b'\x47\x58' for _ in range(test_constants.STREAM_LENGTH)) request_iterator = iter(requests) multi_callable = _stream_unary_multi_callable(self._channel) with self._control.fail(): with self.assertRaises(grpc.RpcError) as exception_context: multi_callable( request_iterator, metadata=( ('test', 'FailedStreamRequestBlockingUnaryResponse'),)) self.assertIs(grpc.StatusCode.UNKNOWN, exception_context.exception.code()) def testFailedStreamRequestFutureUnaryResponse(self): requests = tuple(b'\x07\x18' for _ in range(test_constants.STREAM_LENGTH)) request_iterator = iter(requests) callback = _Callback() multi_callable = _stream_unary_multi_callable(self._channel) with self._control.fail(): response_future = multi_callable.future( request_iterator, metadata=(('test', 'FailedStreamRequestFutureUnaryResponse'),)) response_future.add_done_callback(callback) value_passed_to_callback = callback.value() with self.assertRaises(grpc.RpcError) as exception_context: response_future.result() self.assertIs(grpc.StatusCode.UNKNOWN, response_future.code()) self.assertIs(grpc.StatusCode.UNKNOWN, exception_context.exception.code()) self.assertIsInstance(response_future.exception(), grpc.RpcError) self.assertIsNotNone(response_future.traceback()) self.assertIs(response_future, value_passed_to_callback) def testFailedStreamRequestStreamResponse(self): requests = tuple(b'\x67\x88' for _ in range(test_constants.STREAM_LENGTH)) request_iterator = iter(requests) multi_callable = _stream_stream_multi_callable(self._channel) with self._control.fail(): with self.assertRaises(grpc.RpcError) as exception_context: response_iterator = multi_callable( request_iterator, metadata=(('test', 'FailedStreamRequestStreamResponse'),)) tuple(response_iterator) self.assertIs(grpc.StatusCode.UNKNOWN, exception_context.exception.code()) self.assertIs(grpc.StatusCode.UNKNOWN, response_iterator.code()) def testIgnoredUnaryRequestFutureUnaryResponse(self): request = b'\x37\x17' multi_callable = _unary_unary_multi_callable(self._channel) multi_callable.future( request, metadata=(('test', 'IgnoredUnaryRequestFutureUnaryResponse'),)) def testIgnoredUnaryRequestStreamResponse(self): request = b'\x37\x17' multi_callable = _unary_stream_multi_callable(self._channel) multi_callable( request, metadata=(('test', 'IgnoredUnaryRequestStreamResponse'),)) def testIgnoredStreamRequestFutureUnaryResponse(self): requests = tuple(b'\x07\x18' for _ in range(test_constants.STREAM_LENGTH)) request_iterator = iter(requests) multi_callable = _stream_unary_multi_callable(self._channel) multi_callable.future( request_iterator, metadata=(('test', 'IgnoredStreamRequestFutureUnaryResponse'),)) def testIgnoredStreamRequestStreamResponse(self): requests = tuple(b'\x67\x88' for _ in range(test_constants.STREAM_LENGTH)) request_iterator = iter(requests) multi_callable = _stream_stream_multi_callable(self._channel) multi_callable( request_iterator, metadata=(('test', 'IgnoredStreamRequestStreamResponse'),)) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_sanity/000077500000000000000000000000001310511640000230435ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/unit/_sanity/__init__.py000066400000000000000000000027701310511640000251620ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/unit/_sanity/_sanity_test.py000066400000000000000000000045611310511640000261300ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import json import unittest import pkg_resources import six import tests class Sanity(unittest.TestCase): def testTestsJsonUpToDate(self): """Autodiscovers all test suites and checks that tests.json is up to date""" loader = tests.Loader() loader.loadTestsFromNames(['tests']) test_suite_names = [ test_case_class.id().rsplit('.', 1)[0] for test_case_class in tests._loader.iterate_suite_cases( loader.suite) ] test_suite_names = sorted(set(test_suite_names)) tests_json_string = pkg_resources.resource_string('tests', 'tests.json') if six.PY3: tests_json_string = tests_json_string.decode() tests_json = json.loads(tests_json_string) self.assertListEqual(test_suite_names, tests_json) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_thread_cleanup_test.py000066400000000000000000000104541310511640000261270ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Tests for CleanupThread.""" import threading import time import unittest from grpc import _common _SHORT_TIME = 0.5 _LONG_TIME = 5.0 _EPSILON = 0.5 def cleanup(timeout): if timeout is not None: time.sleep(timeout) else: time.sleep(_LONG_TIME) def slow_cleanup(timeout): # Don't respect timeout time.sleep(_LONG_TIME) class CleanupThreadTest(unittest.TestCase): def testTargetInvocation(self): event = threading.Event() def target(arg1, arg2, arg3=None): self.assertEqual('arg1', arg1) self.assertEqual('arg2', arg2) self.assertEqual('arg3', arg3) event.set() cleanup_thread = _common.CleanupThread( behavior=lambda x: None, target=target, name='test-name', args=('arg1', 'arg2'), kwargs={'arg3': 'arg3'}) cleanup_thread.start() cleanup_thread.join() self.assertEqual(cleanup_thread.name, 'test-name') self.assertTrue(event.is_set()) def testJoinNoTimeout(self): cleanup_thread = _common.CleanupThread(behavior=cleanup) cleanup_thread.start() start_time = time.time() cleanup_thread.join() end_time = time.time() self.assertAlmostEqual( _LONG_TIME, end_time - start_time, delta=_EPSILON) def testJoinTimeout(self): cleanup_thread = _common.CleanupThread(behavior=cleanup) cleanup_thread.start() start_time = time.time() cleanup_thread.join(_SHORT_TIME) end_time = time.time() self.assertAlmostEqual( _SHORT_TIME, end_time - start_time, delta=_EPSILON) def testJoinTimeoutSlowBehavior(self): cleanup_thread = _common.CleanupThread(behavior=slow_cleanup) cleanup_thread.start() start_time = time.time() cleanup_thread.join(_SHORT_TIME) end_time = time.time() self.assertAlmostEqual( _LONG_TIME, end_time - start_time, delta=_EPSILON) def testJoinTimeoutSlowTarget(self): event = threading.Event() def target(): event.wait(_LONG_TIME) cleanup_thread = _common.CleanupThread(behavior=cleanup, target=target) cleanup_thread.start() start_time = time.time() cleanup_thread.join(_SHORT_TIME) end_time = time.time() self.assertAlmostEqual( _SHORT_TIME, end_time - start_time, delta=_EPSILON) event.set() def testJoinZeroTimeout(self): cleanup_thread = _common.CleanupThread(behavior=cleanup) cleanup_thread.start() start_time = time.time() cleanup_thread.join(0) end_time = time.time() self.assertAlmostEqual(0, end_time - start_time, delta=_EPSILON) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/_thread_pool.py000066400000000000000000000040621310511640000244100ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import threading from concurrent import futures class RecordingThreadPool(futures.Executor): """A thread pool that records if used.""" def __init__(self, max_workers): self._tp_executor = futures.ThreadPoolExecutor(max_workers=max_workers) self._lock = threading.Lock() self._was_used = False def submit(self, fn, *args, **kwargs): with self._lock: self._was_used = True self._tp_executor.submit(fn, *args, **kwargs) def was_used(self): with self._lock: return self._was_used grpc-1.3.2/src/python/grpcio_tests/tests/unit/beta/000077500000000000000000000000001310511640000223105ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/unit/beta/__init__.py000066400000000000000000000027701310511640000244270ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/unit/beta/_beta_features_test.py000066400000000000000000000344321310511640000266770ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Tests Face interface compliance of the gRPC Python Beta API.""" import threading import unittest from grpc.beta import implementations from grpc.beta import interfaces from grpc.framework.common import cardinality from grpc.framework.interfaces.face import utilities from tests.unit import resources from tests.unit.beta import test_utilities from tests.unit.framework.common import test_constants _SERVER_HOST_OVERRIDE = 'foo.test.google.fr' _PER_RPC_CREDENTIALS_METADATA_KEY = b'my-call-credentials-metadata-key' _PER_RPC_CREDENTIALS_METADATA_VALUE = b'my-call-credentials-metadata-value' _GROUP = 'group' _UNARY_UNARY = 'unary-unary' _UNARY_STREAM = 'unary-stream' _STREAM_UNARY = 'stream-unary' _STREAM_STREAM = 'stream-stream' _REQUEST = b'abc' _RESPONSE = b'123' class _Servicer(object): def __init__(self): self._condition = threading.Condition() self._peer = None self._serviced = False def unary_unary(self, request, context): with self._condition: self._request = request self._peer = context.protocol_context().peer() self._invocation_metadata = context.invocation_metadata() context.protocol_context().disable_next_response_compression() self._serviced = True self._condition.notify_all() return _RESPONSE def unary_stream(self, request, context): with self._condition: self._request = request self._peer = context.protocol_context().peer() self._invocation_metadata = context.invocation_metadata() context.protocol_context().disable_next_response_compression() self._serviced = True self._condition.notify_all() return yield def stream_unary(self, request_iterator, context): for request in request_iterator: self._request = request with self._condition: self._peer = context.protocol_context().peer() self._invocation_metadata = context.invocation_metadata() context.protocol_context().disable_next_response_compression() self._serviced = True self._condition.notify_all() return _RESPONSE def stream_stream(self, request_iterator, context): for request in request_iterator: with self._condition: self._peer = context.protocol_context().peer() context.protocol_context().disable_next_response_compression() yield _RESPONSE with self._condition: self._invocation_metadata = context.invocation_metadata() self._serviced = True self._condition.notify_all() def peer(self): with self._condition: return self._peer def block_until_serviced(self): with self._condition: while not self._serviced: self._condition.wait() class _BlockingIterator(object): def __init__(self, upstream): self._condition = threading.Condition() self._upstream = upstream self._allowed = [] def __iter__(self): return self def __next__(self): return self.next() def next(self): with self._condition: while True: if self._allowed is None: raise StopIteration() elif self._allowed: return self._allowed.pop(0) else: self._condition.wait() def allow(self): with self._condition: try: self._allowed.append(next(self._upstream)) except StopIteration: self._allowed = None self._condition.notify_all() def _metadata_plugin(context, callback): callback([(_PER_RPC_CREDENTIALS_METADATA_KEY, _PER_RPC_CREDENTIALS_METADATA_VALUE)], None) class BetaFeaturesTest(unittest.TestCase): def setUp(self): self._servicer = _Servicer() method_implementations = { (_GROUP, _UNARY_UNARY): utilities.unary_unary_inline(self._servicer.unary_unary), (_GROUP, _UNARY_STREAM): utilities.unary_stream_inline(self._servicer.unary_stream), (_GROUP, _STREAM_UNARY): utilities.stream_unary_inline(self._servicer.stream_unary), (_GROUP, _STREAM_STREAM): utilities.stream_stream_inline(self._servicer.stream_stream), } cardinalities = { _UNARY_UNARY: cardinality.Cardinality.UNARY_UNARY, _UNARY_STREAM: cardinality.Cardinality.UNARY_STREAM, _STREAM_UNARY: cardinality.Cardinality.STREAM_UNARY, _STREAM_STREAM: cardinality.Cardinality.STREAM_STREAM, } server_options = implementations.server_options( thread_pool_size=test_constants.POOL_SIZE) self._server = implementations.server( method_implementations, options=server_options) server_credentials = implementations.ssl_server_credentials([ (resources.private_key(), resources.certificate_chain(),), ]) port = self._server.add_secure_port('[::]:0', server_credentials) self._server.start() self._channel_credentials = implementations.ssl_channel_credentials( resources.test_root_certificates()) self._call_credentials = implementations.metadata_call_credentials( _metadata_plugin) channel = test_utilities.not_really_secure_channel( 'localhost', port, self._channel_credentials, _SERVER_HOST_OVERRIDE) stub_options = implementations.stub_options( thread_pool_size=test_constants.POOL_SIZE) self._dynamic_stub = implementations.dynamic_stub( channel, _GROUP, cardinalities, options=stub_options) def tearDown(self): self._dynamic_stub = None self._server.stop(test_constants.SHORT_TIMEOUT).wait() def test_unary_unary(self): call_options = interfaces.grpc_call_options( disable_compression=True, credentials=self._call_credentials) response = getattr(self._dynamic_stub, _UNARY_UNARY)( _REQUEST, test_constants.LONG_TIMEOUT, protocol_options=call_options) self.assertEqual(_RESPONSE, response) self.assertIsNotNone(self._servicer.peer()) invocation_metadata = [ (metadatum.key, metadatum.value) for metadatum in self._servicer._invocation_metadata ] self.assertIn((_PER_RPC_CREDENTIALS_METADATA_KEY, _PER_RPC_CREDENTIALS_METADATA_VALUE), invocation_metadata) def test_unary_stream(self): call_options = interfaces.grpc_call_options( disable_compression=True, credentials=self._call_credentials) response_iterator = getattr(self._dynamic_stub, _UNARY_STREAM)( _REQUEST, test_constants.LONG_TIMEOUT, protocol_options=call_options) self._servicer.block_until_serviced() self.assertIsNotNone(self._servicer.peer()) invocation_metadata = [ (metadatum.key, metadatum.value) for metadatum in self._servicer._invocation_metadata ] self.assertIn((_PER_RPC_CREDENTIALS_METADATA_KEY, _PER_RPC_CREDENTIALS_METADATA_VALUE), invocation_metadata) def test_stream_unary(self): call_options = interfaces.grpc_call_options( credentials=self._call_credentials) request_iterator = _BlockingIterator(iter((_REQUEST,))) response_future = getattr(self._dynamic_stub, _STREAM_UNARY).future( request_iterator, test_constants.LONG_TIMEOUT, protocol_options=call_options) response_future.protocol_context().disable_next_request_compression() request_iterator.allow() response_future.protocol_context().disable_next_request_compression() request_iterator.allow() self._servicer.block_until_serviced() self.assertIsNotNone(self._servicer.peer()) self.assertEqual(_RESPONSE, response_future.result()) invocation_metadata = [ (metadatum.key, metadatum.value) for metadatum in self._servicer._invocation_metadata ] self.assertIn((_PER_RPC_CREDENTIALS_METADATA_KEY, _PER_RPC_CREDENTIALS_METADATA_VALUE), invocation_metadata) def test_stream_stream(self): call_options = interfaces.grpc_call_options( credentials=self._call_credentials) request_iterator = _BlockingIterator(iter((_REQUEST,))) response_iterator = getattr(self._dynamic_stub, _STREAM_STREAM)( request_iterator, test_constants.SHORT_TIMEOUT, protocol_options=call_options) response_iterator.protocol_context().disable_next_request_compression() request_iterator.allow() response = next(response_iterator) response_iterator.protocol_context().disable_next_request_compression() request_iterator.allow() self._servicer.block_until_serviced() self.assertIsNotNone(self._servicer.peer()) self.assertEqual(_RESPONSE, response) invocation_metadata = [ (metadatum.key, metadatum.value) for metadatum in self._servicer._invocation_metadata ] self.assertIn((_PER_RPC_CREDENTIALS_METADATA_KEY, _PER_RPC_CREDENTIALS_METADATA_VALUE), invocation_metadata) class ContextManagementAndLifecycleTest(unittest.TestCase): def setUp(self): self._servicer = _Servicer() self._method_implementations = { (_GROUP, _UNARY_UNARY): utilities.unary_unary_inline(self._servicer.unary_unary), (_GROUP, _UNARY_STREAM): utilities.unary_stream_inline(self._servicer.unary_stream), (_GROUP, _STREAM_UNARY): utilities.stream_unary_inline(self._servicer.stream_unary), (_GROUP, _STREAM_STREAM): utilities.stream_stream_inline(self._servicer.stream_stream), } self._cardinalities = { _UNARY_UNARY: cardinality.Cardinality.UNARY_UNARY, _UNARY_STREAM: cardinality.Cardinality.UNARY_STREAM, _STREAM_UNARY: cardinality.Cardinality.STREAM_UNARY, _STREAM_STREAM: cardinality.Cardinality.STREAM_STREAM, } self._server_options = implementations.server_options( thread_pool_size=test_constants.POOL_SIZE) self._server_credentials = implementations.ssl_server_credentials([ (resources.private_key(), resources.certificate_chain(),), ]) self._channel_credentials = implementations.ssl_channel_credentials( resources.test_root_certificates()) self._stub_options = implementations.stub_options( thread_pool_size=test_constants.POOL_SIZE) def test_stub_context(self): server = implementations.server( self._method_implementations, options=self._server_options) port = server.add_secure_port('[::]:0', self._server_credentials) server.start() channel = test_utilities.not_really_secure_channel( 'localhost', port, self._channel_credentials, _SERVER_HOST_OVERRIDE) dynamic_stub = implementations.dynamic_stub( channel, _GROUP, self._cardinalities, options=self._stub_options) for _ in range(100): with dynamic_stub: pass for _ in range(10): with dynamic_stub: call_options = interfaces.grpc_call_options( disable_compression=True) response = getattr(dynamic_stub, _UNARY_UNARY)( _REQUEST, test_constants.LONG_TIMEOUT, protocol_options=call_options) self.assertEqual(_RESPONSE, response) self.assertIsNotNone(self._servicer.peer()) server.stop(test_constants.SHORT_TIMEOUT).wait() def test_server_lifecycle(self): for _ in range(100): server = implementations.server( self._method_implementations, options=self._server_options) port = server.add_secure_port('[::]:0', self._server_credentials) server.start() server.stop(test_constants.SHORT_TIMEOUT).wait() for _ in range(100): server = implementations.server( self._method_implementations, options=self._server_options) server.add_secure_port('[::]:0', self._server_credentials) server.add_insecure_port('[::]:0') with server: server.stop(test_constants.SHORT_TIMEOUT) server.stop(test_constants.SHORT_TIMEOUT) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/beta/_connectivity_channel_test.py000066400000000000000000000041341310511640000302700ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Tests of grpc.beta._connectivity_channel.""" import unittest from grpc.beta import interfaces class ConnectivityStatesTest(unittest.TestCase): def testBetaConnectivityStates(self): self.assertIsNotNone(interfaces.ChannelConnectivity.IDLE) self.assertIsNotNone(interfaces.ChannelConnectivity.CONNECTING) self.assertIsNotNone(interfaces.ChannelConnectivity.READY) self.assertIsNotNone(interfaces.ChannelConnectivity.TRANSIENT_FAILURE) self.assertIsNotNone(interfaces.ChannelConnectivity.FATAL_FAILURE) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/beta/_face_interface_test.py000066400000000000000000000137111310511640000270010ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Tests Face interface compliance of the gRPC Python Beta API.""" import collections import unittest import six from grpc.beta import implementations from grpc.beta import interfaces from tests.unit import resources from tests.unit import test_common as grpc_test_common from tests.unit.beta import test_utilities from tests.unit.framework.common import test_constants from tests.unit.framework.interfaces.face import test_cases from tests.unit.framework.interfaces.face import test_interfaces _SERVER_HOST_OVERRIDE = 'foo.test.google.fr' class _SerializationBehaviors( collections.namedtuple('_SerializationBehaviors', ( 'request_serializers', 'request_deserializers', 'response_serializers', 'response_deserializers',))): pass def _serialization_behaviors_from_test_methods(test_methods): request_serializers = {} request_deserializers = {} response_serializers = {} response_deserializers = {} for (group, method), test_method in six.iteritems(test_methods): request_serializers[group, method] = test_method.serialize_request request_deserializers[group, method] = test_method.deserialize_request response_serializers[group, method] = test_method.serialize_response response_deserializers[group, method] = test_method.deserialize_response return _SerializationBehaviors(request_serializers, request_deserializers, response_serializers, response_deserializers) class _Implementation(test_interfaces.Implementation): def instantiate(self, methods, method_implementations, multi_method_implementation): serialization_behaviors = _serialization_behaviors_from_test_methods( methods) # TODO(nathaniel): Add a "groups" attribute to _digest.TestServiceDigest. service = next(iter(methods))[0] # TODO(nathaniel): Add a "cardinalities_by_group" attribute to # _digest.TestServiceDigest. cardinalities = { method: method_object.cardinality() for (group, method), method_object in six.iteritems(methods) } server_options = implementations.server_options( request_deserializers=serialization_behaviors.request_deserializers, response_serializers=serialization_behaviors.response_serializers, thread_pool_size=test_constants.POOL_SIZE) server = implementations.server( method_implementations, options=server_options) server_credentials = implementations.ssl_server_credentials([ (resources.private_key(), resources.certificate_chain(),), ]) port = server.add_secure_port('[::]:0', server_credentials) server.start() channel_credentials = implementations.ssl_channel_credentials( resources.test_root_certificates()) channel = test_utilities.not_really_secure_channel( 'localhost', port, channel_credentials, _SERVER_HOST_OVERRIDE) stub_options = implementations.stub_options( request_serializers=serialization_behaviors.request_serializers, response_deserializers=serialization_behaviors. response_deserializers, thread_pool_size=test_constants.POOL_SIZE) generic_stub = implementations.generic_stub( channel, options=stub_options) dynamic_stub = implementations.dynamic_stub( channel, service, cardinalities, options=stub_options) return generic_stub, {service: dynamic_stub}, server def destantiate(self, memo): memo.stop(test_constants.SHORT_TIMEOUT).wait() def invocation_metadata(self): return grpc_test_common.INVOCATION_INITIAL_METADATA def initial_metadata(self): return grpc_test_common.SERVICE_INITIAL_METADATA def terminal_metadata(self): return grpc_test_common.SERVICE_TERMINAL_METADATA def code(self): return interfaces.StatusCode.OK def details(self): return grpc_test_common.DETAILS def metadata_transmitted(self, original_metadata, transmitted_metadata): return original_metadata is None or grpc_test_common.metadata_transmitted( original_metadata, transmitted_metadata) def load_tests(loader, tests, pattern): return unittest.TestSuite(tests=tuple( loader.loadTestsFromTestCase(test_case_class) for test_case_class in test_cases.test_cases(_Implementation()))) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/beta/_implementations_test.py000066400000000000000000000057651310511640000273050ustar00rootroot00000000000000# Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Tests the implementations module of the gRPC Python Beta API.""" import datetime import unittest from oauth2client import client as oauth2client_client from grpc.beta import implementations from tests.unit import resources class ChannelCredentialsTest(unittest.TestCase): def test_runtime_provided_root_certificates(self): channel_credentials = implementations.ssl_channel_credentials() self.assertIsInstance(channel_credentials, implementations.ChannelCredentials) def test_application_provided_root_certificates(self): channel_credentials = implementations.ssl_channel_credentials( resources.test_root_certificates()) self.assertIsInstance(channel_credentials, implementations.ChannelCredentials) class CallCredentialsTest(unittest.TestCase): def test_google_call_credentials(self): creds = oauth2client_client.GoogleCredentials( 'token', 'client_id', 'secret', 'refresh_token', datetime.datetime(2008, 6, 24), 'https://refresh.uri.com/', 'user_agent') call_creds = implementations.google_call_credentials(creds) self.assertIsInstance(call_creds, implementations.CallCredentials) def test_access_token_call_credentials(self): call_creds = implementations.access_token_call_credentials('token') self.assertIsInstance(call_creds, implementations.CallCredentials) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/beta/_not_found_test.py000066400000000000000000000062651310511640000260640ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Tests of RPC-method-not-found behavior.""" import unittest from grpc.beta import implementations from grpc.beta import interfaces from grpc.framework.interfaces.face import face from tests.unit.framework.common import test_constants class NotFoundTest(unittest.TestCase): def setUp(self): self._server = implementations.server({}) port = self._server.add_insecure_port('[::]:0') channel = implementations.insecure_channel('localhost', port) self._generic_stub = implementations.generic_stub(channel) self._server.start() def tearDown(self): self._server.stop(0).wait() self._generic_stub = None def test_blocking_unary_unary_not_found(self): with self.assertRaises(face.LocalError) as exception_assertion_context: self._generic_stub.blocking_unary_unary( 'groop', 'meffod', b'abc', test_constants.LONG_TIMEOUT, with_call=True) self.assertIs(exception_assertion_context.exception.code, interfaces.StatusCode.UNIMPLEMENTED) def test_future_stream_unary_not_found(self): rpc_future = self._generic_stub.future_stream_unary( 'grupe', 'mevvod', iter([b'def']), test_constants.LONG_TIMEOUT) with self.assertRaises(face.LocalError) as exception_assertion_context: rpc_future.result() self.assertIs(exception_assertion_context.exception.code, interfaces.StatusCode.UNIMPLEMENTED) self.assertIs(rpc_future.exception().code, interfaces.StatusCode.UNIMPLEMENTED) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/beta/_utilities_test.py000066400000000000000000000103551310511640000260770ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Tests of grpc.beta.utilities.""" import threading import time import unittest from grpc.beta import implementations from grpc.beta import utilities from grpc.framework.foundation import future from tests.unit.framework.common import test_constants class _Callback(object): def __init__(self): self._condition = threading.Condition() self._value = None def accept_value(self, value): with self._condition: self._value = value self._condition.notify_all() def block_until_called(self): with self._condition: while self._value is None: self._condition.wait() return self._value class ChannelConnectivityTest(unittest.TestCase): def test_lonely_channel_connectivity(self): channel = implementations.insecure_channel('localhost', 12345) callback = _Callback() ready_future = utilities.channel_ready_future(channel) ready_future.add_done_callback(callback.accept_value) with self.assertRaises(future.TimeoutError): ready_future.result(timeout=test_constants.SHORT_TIMEOUT) self.assertFalse(ready_future.cancelled()) self.assertFalse(ready_future.done()) self.assertTrue(ready_future.running()) ready_future.cancel() value_passed_to_callback = callback.block_until_called() self.assertIs(ready_future, value_passed_to_callback) self.assertTrue(ready_future.cancelled()) self.assertTrue(ready_future.done()) self.assertFalse(ready_future.running()) def test_immediately_connectable_channel_connectivity(self): server = implementations.server({}) port = server.add_insecure_port('[::]:0') server.start() channel = implementations.insecure_channel('localhost', port) callback = _Callback() try: ready_future = utilities.channel_ready_future(channel) ready_future.add_done_callback(callback.accept_value) self.assertIsNone( ready_future.result(timeout=test_constants.LONG_TIMEOUT)) value_passed_to_callback = callback.block_until_called() self.assertIs(ready_future, value_passed_to_callback) self.assertFalse(ready_future.cancelled()) self.assertTrue(ready_future.done()) self.assertFalse(ready_future.running()) # Cancellation after maturity has no effect. ready_future.cancel() self.assertFalse(ready_future.cancelled()) self.assertTrue(ready_future.done()) self.assertFalse(ready_future.running()) finally: ready_future.cancel() server.stop(0) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/beta/test_utilities.py000066400000000000000000000046041310511640000257400ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Test-appropriate entry points into the gRPC Python Beta API.""" import grpc from grpc.beta import implementations def not_really_secure_channel(host, port, channel_credentials, server_host_override): """Creates an insecure Channel to a remote host. Args: host: The name of the remote host to which to connect. port: The port of the remote host to which to connect. channel_credentials: The implementations.ChannelCredentials with which to connect. server_host_override: The target name used for SSL host name checking. Returns: An implementations.Channel to the remote host through which RPCs may be conducted. """ target = '%s:%d' % (host, port) channel = grpc.secure_channel(target, channel_credentials, ( ('grpc.ssl_target_name_override', server_host_override,),)) return implementations.Channel(channel) grpc-1.3.2/src/python/grpcio_tests/tests/unit/credentials/000077500000000000000000000000001310511640000236725ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/unit/credentials/README000066400000000000000000000000641310511640000245520ustar00rootroot00000000000000These are test keys *NOT* to be used in production. grpc-1.3.2/src/python/grpcio_tests/tests/unit/credentials/ca.pem000077500000000000000000000015271310511640000247700ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIICSjCCAbOgAwIBAgIJAJHGGR4dGioHMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnRlc3RjYTAeFw0xNDExMTEyMjMxMjla Fw0yNDExMDgyMjMxMjlaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0 YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDzANBgNVBAMT BnRlc3RjYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwEDfBV5MYdlHVHJ7 +L4nxrZy7mBfAVXpOc5vMYztssUI7mL2/iYujiIXM+weZYNTEpLdjyJdu7R5gGUu g1jSVK/EPHfc74O7AyZU34PNIP4Sh33N+/A5YexrNgJlPY+E3GdVYi4ldWJjgkAd Qah2PH5ACLrIIC6tRka9hcaBlIECAwEAAaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNV HQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADgYEAHzC7jdYlzAVmddi/gdAeKPau sPBG/C2HCWqHzpCUHcKuvMzDVkY/MP2o6JIW2DBbY64bO/FceExhjcykgaYtCH/m oIU63+CFOTtR7otyQAWHqXa7q4SbCDlG7DyRFxqG0txPtGvy12lgldA2+RgcigQG Dfcog5wrJytaQ6UA0wE= -----END CERTIFICATE----- grpc-1.3.2/src/python/grpcio_tests/tests/unit/credentials/server1.key000077500000000000000000000016201310511640000257750ustar00rootroot00000000000000-----BEGIN PRIVATE KEY----- MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOHDFScoLCVJpYDD M4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1BgzkWF+slf 3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd9N8YwbBY AckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAECgYAn7qGnM2vbjJNBm0VZCkOkTIWm V10okw7EPJrdL2mkre9NasghNXbE1y5zDshx5Nt3KsazKOxTT8d0Jwh/3KbaN+YY tTCbKGW0pXDRBhwUHRcuRzScjli8Rih5UOCiZkhefUTcRb6xIhZJuQy71tjaSy0p dHZRmYyBYO2YEQ8xoQJBAPrJPhMBkzmEYFtyIEqAxQ/o/A6E+E4w8i+KM7nQCK7q K4JXzyXVAjLfyBZWHGM2uro/fjqPggGD6QH1qXCkI4MCQQDmdKeb2TrKRh5BY1LR 81aJGKcJ2XbcDu6wMZK4oqWbTX2KiYn9GB0woM6nSr/Y6iy1u145YzYxEV/iMwff DJULAkB8B2MnyzOg0pNFJqBJuH29bKCcHa8gHJzqXhNO5lAlEbMK95p/P2Wi+4Hd aiEIAF1BF326QJcvYKmwSmrORp85AkAlSNxRJ50OWrfMZnBgzVjDx3xG6KsFQVk2 ol6VhqL6dFgKUORFUWBvnKSyhjJxurlPEahV6oo6+A+mPhFY8eUvAkAZQyTdupP3 XEFQKctGz+9+gKkemDp7LBBMEMBXrGTLPhpEfcjv/7KPdnFHYmhYeBTBnuVmTVWe F98XJ7tIFfJq -----END PRIVATE KEY----- grpc-1.3.2/src/python/grpcio_tests/tests/unit/credentials/server1.pem000077500000000000000000000017041310511640000257710ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50 ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd 9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6 hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8 -----END CERTIFICATE----- grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/000077500000000000000000000000001310511640000233725ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/__init__.py000066400000000000000000000027701310511640000255110ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/common/000077500000000000000000000000001310511640000246625ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/common/__init__.py000066400000000000000000000027701310511640000270010ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/common/test_constants.py000066400000000000000000000051461310511640000303150ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Constants shared among tests throughout RPC Framework.""" # Value for maximum duration in seconds that a test is allowed for its actual # behavioral logic, excluding all time spent deliberately waiting in the test. TIME_ALLOWANCE = 10 # Value for maximum duration in seconds of RPCs that may time out as part of a # test. SHORT_TIMEOUT = 4 # Absurdly large value for maximum duration in seconds for should-not-time-out # RPCs made during tests. LONG_TIMEOUT = 3000 # Values to supply on construction of an object that will service RPCs; these # should not be used as the actual timeout values of any RPCs made during tests. DEFAULT_TIMEOUT = 300 MAXIMUM_TIMEOUT = 3600 # The number of payloads to transmit in streaming tests. STREAM_LENGTH = 200 # The size of payloads to transmit in tests. PAYLOAD_SIZE = 256 * 1024 + 17 # The concurrency to use in tests of concurrent RPCs that will not create as # many threads as RPCs. RPC_CONCURRENCY = 200 # The concurrency to use in tests of concurrent RPCs that will create as many # threads as RPCs. THREAD_CONCURRENCY = 25 # The size of thread pools to use in tests. POOL_SIZE = 10 grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/common/test_control.py000066400000000000000000000077201310511640000277610ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Code for instructing systems under test to block or fail.""" import abc import contextlib import threading import six class Defect(Exception): """Simulates a programming defect raised into in a system under test. Use of a standard exception type is too easily misconstrued as an actual defect in either the test infrastructure or the system under test. """ class Control(six.with_metaclass(abc.ABCMeta)): """An object that accepts program control from a system under test. Systems under test passed a Control should call its control() method frequently during execution. The control() method may block, raise an exception, or do nothing, all according to the enclosing test's desire for the system under test to simulate hanging, failing, or functioning. """ @abc.abstractmethod def control(self): """Potentially does anything.""" raise NotImplementedError() class PauseFailControl(Control): """A Control that can be used to pause or fail code under control. This object is only safe for use from two threads: one of the system under test calling control and the other from the test system calling pause, block_until_paused, and fail. """ def __init__(self): self._condition = threading.Condition() self._pause = False self._paused = False self._fail = False def control(self): with self._condition: if self._fail: raise Defect() while self._pause: self._paused = True self._condition.notify_all() self._condition.wait() self._paused = False @contextlib.contextmanager def pause(self): """Pauses code under control while controlling code is in context.""" with self._condition: self._pause = True yield with self._condition: self._pause = False self._condition.notify_all() def block_until_paused(self): """Blocks controlling code until code under control is paused. May only be called within the context of a pause call. """ with self._condition: while not self._paused: self._condition.wait() @contextlib.contextmanager def fail(self): """Fails code under control while controlling code is in context.""" with self._condition: self._fail = True yield with self._condition: self._fail = False grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/common/test_coverage.py000066400000000000000000000075771310511640000301060ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Governs coverage for tests of RPCs throughout RPC Framework.""" import abc import six # This code is designed for use with the unittest module. # pylint: disable=invalid-name class Coverage(six.with_metaclass(abc.ABCMeta)): """Specification of test coverage.""" @abc.abstractmethod def testSuccessfulUnaryRequestUnaryResponse(self): raise NotImplementedError() @abc.abstractmethod def testSuccessfulUnaryRequestStreamResponse(self): raise NotImplementedError() @abc.abstractmethod def testSuccessfulStreamRequestUnaryResponse(self): raise NotImplementedError() @abc.abstractmethod def testSuccessfulStreamRequestStreamResponse(self): raise NotImplementedError() @abc.abstractmethod def testSequentialInvocations(self): raise NotImplementedError() @abc.abstractmethod def testParallelInvocations(self): raise NotImplementedError() @abc.abstractmethod def testWaitingForSomeButNotAllParallelInvocations(self): raise NotImplementedError() @abc.abstractmethod def testCancelledUnaryRequestUnaryResponse(self): raise NotImplementedError() @abc.abstractmethod def testCancelledUnaryRequestStreamResponse(self): raise NotImplementedError() @abc.abstractmethod def testCancelledStreamRequestUnaryResponse(self): raise NotImplementedError() @abc.abstractmethod def testCancelledStreamRequestStreamResponse(self): raise NotImplementedError() @abc.abstractmethod def testExpiredUnaryRequestUnaryResponse(self): raise NotImplementedError() @abc.abstractmethod def testExpiredUnaryRequestStreamResponse(self): raise NotImplementedError() @abc.abstractmethod def testExpiredStreamRequestUnaryResponse(self): raise NotImplementedError() @abc.abstractmethod def testExpiredStreamRequestStreamResponse(self): raise NotImplementedError() @abc.abstractmethod def testFailedUnaryRequestUnaryResponse(self): raise NotImplementedError() @abc.abstractmethod def testFailedUnaryRequestStreamResponse(self): raise NotImplementedError() @abc.abstractmethod def testFailedStreamRequestUnaryResponse(self): raise NotImplementedError() @abc.abstractmethod def testFailedStreamRequestStreamResponse(self): raise NotImplementedError() grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/foundation/000077500000000000000000000000001310511640000255405ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/foundation/__init__.py000066400000000000000000000027701310511640000276570ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/foundation/_logging_pool_test.py000066400000000000000000000060771310511640000320010ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Tests for grpc.framework.foundation.logging_pool.""" import threading import unittest from grpc.framework.foundation import logging_pool _POOL_SIZE = 16 class _CallableObject(object): def __init__(self): self._lock = threading.Lock() self._passed_values = [] def __call__(self, value): with self._lock: self._passed_values.append(value) def passed_values(self): with self._lock: return tuple(self._passed_values) class LoggingPoolTest(unittest.TestCase): def testUpAndDown(self): pool = logging_pool.pool(_POOL_SIZE) pool.shutdown(wait=True) with logging_pool.pool(_POOL_SIZE) as pool: self.assertIsNotNone(pool) def testTaskExecuted(self): test_list = [] with logging_pool.pool(_POOL_SIZE) as pool: pool.submit(lambda: test_list.append(object())).result() self.assertTrue(test_list) def testException(self): with logging_pool.pool(_POOL_SIZE) as pool: raised_exception = pool.submit(lambda: 1 / 0).exception() self.assertIsNotNone(raised_exception) def testCallableObjectExecuted(self): callable_object = _CallableObject() passed_object = object() with logging_pool.pool(_POOL_SIZE) as pool: future = pool.submit(callable_object, passed_object) self.assertIsNone(future.result()) self.assertSequenceEqual((passed_object,), callable_object.passed_values()) if __name__ == '__main__': unittest.main(verbosity=2) grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/foundation/stream_testing.py000066400000000000000000000055371310511640000311540ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Utilities for testing stream-related code.""" from grpc.framework.foundation import stream class TestConsumer(stream.Consumer): """A stream.Consumer instrumented for testing. Attributes: calls: A sequence of value-termination pairs describing the history of calls made on this object. """ def __init__(self): self.calls = [] def consume(self, value): """See stream.Consumer.consume for specification.""" self.calls.append((value, False)) def terminate(self): """See stream.Consumer.terminate for specification.""" self.calls.append((None, True)) def consume_and_terminate(self, value): """See stream.Consumer.consume_and_terminate for specification.""" self.calls.append((value, True)) def is_legal(self): """Reports whether or not a legal sequence of calls has been made.""" terminated = False for value, terminal in self.calls: if terminated: return False elif terminal: terminated = True elif value is None: return False else: # pylint: disable=useless-else-on-loop return True def values(self): """Returns the sequence of values that have been passed to this Consumer.""" return [value for value, _ in self.calls if value] grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/interfaces/000077500000000000000000000000001310511640000255155ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/interfaces/__init__.py000066400000000000000000000027701310511640000276340ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/interfaces/face/000077500000000000000000000000001310511640000264135ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_3069_test_constant.py000066400000000000000000000034671310511640000325070ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """A test constant working around issue 3069.""" # test_constants is referenced from specification in this module. from tests.unit.framework.common import test_constants # pylint: disable=unused-import # TODO(issue 3069): Replace uses of this constant with # test_constants.SHORT_TIMEOUT. REALLY_SHORT_TIMEOUT = 0.1 grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/interfaces/face/__init__.py000066400000000000000000000027701310511640000305320ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _blocking_invocation_inline_service.py000066400000000000000000000334761310511640000361610ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/interfaces/face# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Test code for the Face layer of RPC Framework.""" from __future__ import division import abc import itertools import unittest from concurrent import futures import six # test_interfaces is referenced from specification in this module. from grpc.framework.foundation import logging_pool from grpc.framework.interfaces.face import face from tests.unit.framework.common import test_constants from tests.unit.framework.common import test_control from tests.unit.framework.common import test_coverage from tests.unit.framework.interfaces.face import _3069_test_constant from tests.unit.framework.interfaces.face import _digest from tests.unit.framework.interfaces.face import _stock_service from tests.unit.framework.interfaces.face import test_interfaces # pylint: disable=unused-import class TestCase( six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest.TestCase)): """A test of the Face layer of RPC Framework. Concrete subclasses must have an "implementation" attribute of type test_interfaces.Implementation and an "invoker_constructor" attribute of type _invocation.InvokerConstructor. """ NAME = 'BlockingInvocationInlineServiceTest' def setUp(self): """See unittest.TestCase.setUp for full specification. Overriding implementations must call this implementation. """ self._control = test_control.PauseFailControl() self._digest = _digest.digest(_stock_service.STOCK_TEST_SERVICE, self._control, None) generic_stub, dynamic_stubs, self._memo = self.implementation.instantiate( self._digest.methods, self._digest.inline_method_implementations, None) self._invoker = self.invoker_constructor.construct_invoker( generic_stub, dynamic_stubs, self._digest.methods) def tearDown(self): """See unittest.TestCase.tearDown for full specification. Overriding implementations must call this implementation. """ self._invoker = None self.implementation.destantiate(self._memo) def testSuccessfulUnaryRequestUnaryResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_unary_messages_sequences)): for test_messages in test_messages_sequence: request = test_messages.request() response, call = self._invoker.blocking(group, method)( request, test_constants.LONG_TIMEOUT, with_call=True) test_messages.verify(request, response, self) def testSuccessfulUnaryRequestStreamResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_stream_messages_sequences)): for test_messages in test_messages_sequence: request = test_messages.request() response_iterator = self._invoker.blocking(group, method)( request, test_constants.LONG_TIMEOUT) responses = list(response_iterator) test_messages.verify(request, responses, self) def testSuccessfulStreamRequestUnaryResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.stream_unary_messages_sequences)): for test_messages in test_messages_sequence: requests = test_messages.requests() response, call = self._invoker.blocking(group, method)( iter(requests), test_constants.LONG_TIMEOUT, with_call=True) test_messages.verify(requests, response, self) def testSuccessfulStreamRequestStreamResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.stream_stream_messages_sequences)): for test_messages in test_messages_sequence: requests = test_messages.requests() response_iterator = self._invoker.blocking(group, method)( iter(requests), test_constants.LONG_TIMEOUT) responses = list(response_iterator) test_messages.verify(requests, responses, self) def testSequentialInvocations(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_unary_messages_sequences)): for test_messages in test_messages_sequence: first_request = test_messages.request() second_request = test_messages.request() first_response = self._invoker.blocking(group, method)( first_request, test_constants.LONG_TIMEOUT) test_messages.verify(first_request, first_response, self) second_response = self._invoker.blocking(group, method)( second_request, test_constants.LONG_TIMEOUT) test_messages.verify(second_request, second_response, self) def testParallelInvocations(self): pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_unary_messages_sequences)): for test_messages in test_messages_sequence: requests = [] response_futures = [] for _ in range(test_constants.THREAD_CONCURRENCY): request = test_messages.request() response_future = pool.submit( self._invoker.blocking(group, method), request, test_constants.LONG_TIMEOUT) requests.append(request) response_futures.append(response_future) responses = [ response_future.result() for response_future in response_futures ] for request, response in zip(requests, responses): test_messages.verify(request, response, self) pool.shutdown(wait=True) def testWaitingForSomeButNotAllParallelInvocations(self): pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_unary_messages_sequences)): for test_messages in test_messages_sequence: requests = [] response_futures_to_indices = {} for index in range(test_constants.THREAD_CONCURRENCY): request = test_messages.request() response_future = pool.submit( self._invoker.blocking(group, method), request, test_constants.LONG_TIMEOUT) requests.append(request) response_futures_to_indices[response_future] = index some_completed_response_futures_iterator = itertools.islice( futures.as_completed(response_futures_to_indices), test_constants.THREAD_CONCURRENCY // 2) for response_future in some_completed_response_futures_iterator: index = response_futures_to_indices[response_future] test_messages.verify(requests[index], response_future.result(), self) pool.shutdown(wait=True) @unittest.skip('Cancellation impossible with blocking control flow!') def testCancelledUnaryRequestUnaryResponse(self): raise NotImplementedError() @unittest.skip('Cancellation impossible with blocking control flow!') def testCancelledUnaryRequestStreamResponse(self): raise NotImplementedError() @unittest.skip('Cancellation impossible with blocking control flow!') def testCancelledStreamRequestUnaryResponse(self): raise NotImplementedError() @unittest.skip('Cancellation impossible with blocking control flow!') def testCancelledStreamRequestStreamResponse(self): raise NotImplementedError() def testExpiredUnaryRequestUnaryResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_unary_messages_sequences)): for test_messages in test_messages_sequence: request = test_messages.request() with self._control.pause(), self.assertRaises( face.ExpirationError): self._invoker.blocking(group, method)( request, _3069_test_constant.REALLY_SHORT_TIMEOUT) def testExpiredUnaryRequestStreamResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_stream_messages_sequences)): for test_messages in test_messages_sequence: request = test_messages.request() with self._control.pause(), self.assertRaises( face.ExpirationError): response_iterator = self._invoker.blocking(group, method)( request, _3069_test_constant.REALLY_SHORT_TIMEOUT) list(response_iterator) def testExpiredStreamRequestUnaryResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.stream_unary_messages_sequences)): for test_messages in test_messages_sequence: requests = test_messages.requests() with self._control.pause(), self.assertRaises( face.ExpirationError): self._invoker.blocking(group, method)( iter(requests), _3069_test_constant.REALLY_SHORT_TIMEOUT) def testExpiredStreamRequestStreamResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.stream_stream_messages_sequences)): for test_messages in test_messages_sequence: requests = test_messages.requests() with self._control.pause(), self.assertRaises( face.ExpirationError): response_iterator = self._invoker.blocking(group, method)( iter(requests), _3069_test_constant.REALLY_SHORT_TIMEOUT) list(response_iterator) def testFailedUnaryRequestUnaryResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_unary_messages_sequences)): for test_messages in test_messages_sequence: request = test_messages.request() with self._control.fail(), self.assertRaises(face.RemoteError): self._invoker.blocking(group, method)( request, test_constants.LONG_TIMEOUT) def testFailedUnaryRequestStreamResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_stream_messages_sequences)): for test_messages in test_messages_sequence: request = test_messages.request() with self._control.fail(), self.assertRaises(face.RemoteError): response_iterator = self._invoker.blocking(group, method)( request, test_constants.LONG_TIMEOUT) list(response_iterator) def testFailedStreamRequestUnaryResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.stream_unary_messages_sequences)): for test_messages in test_messages_sequence: requests = test_messages.requests() with self._control.fail(), self.assertRaises(face.RemoteError): self._invoker.blocking(group, method)( iter(requests), test_constants.LONG_TIMEOUT) def testFailedStreamRequestStreamResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.stream_stream_messages_sequences)): for test_messages in test_messages_sequence: requests = test_messages.requests() with self._control.fail(), self.assertRaises(face.RemoteError): response_iterator = self._invoker.blocking(group, method)( iter(requests), test_constants.LONG_TIMEOUT) list(response_iterator) grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_digest.py000066400000000000000000000414071310511640000304110ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Code for making a service.TestService more amenable to use in tests.""" import collections import threading import six # test_control, _service, and test_interfaces are referenced from specification # in this module. from grpc.framework.common import cardinality from grpc.framework.common import style from grpc.framework.foundation import stream from grpc.framework.foundation import stream_util from grpc.framework.interfaces.face import face from tests.unit.framework.common import test_control # pylint: disable=unused-import from tests.unit.framework.interfaces.face import _service # pylint: disable=unused-import from tests.unit.framework.interfaces.face import test_interfaces # pylint: disable=unused-import _IDENTITY = lambda x: x class TestServiceDigest( collections.namedtuple('TestServiceDigest', ( 'methods', 'inline_method_implementations', 'event_method_implementations', 'multi_method_implementation', 'unary_unary_messages_sequences', 'unary_stream_messages_sequences', 'stream_unary_messages_sequences', 'stream_stream_messages_sequences',))): """A transformation of a service.TestService. Attributes: methods: A dict from method group-name pair to test_interfaces.Method object describing the RPC methods that may be called during the test. inline_method_implementations: A dict from method group-name pair to face.MethodImplementation object to be used in tests of in-line calls to behaviors under test. event_method_implementations: A dict from method group-name pair to face.MethodImplementation object to be used in tests of event-driven calls to behaviors under test. multi_method_implementation: A face.MultiMethodImplementation to be used in tests of generic calls to behaviors under test. unary_unary_messages_sequences: A dict from method group-name pair to sequence of service.UnaryUnaryTestMessages objects to be used to test the identified method. unary_stream_messages_sequences: A dict from method group-name pair to sequence of service.UnaryStreamTestMessages objects to be used to test the identified method. stream_unary_messages_sequences: A dict from method group-name pair to sequence of service.StreamUnaryTestMessages objects to be used to test the identified method. stream_stream_messages_sequences: A dict from method group-name pair to sequence of service.StreamStreamTestMessages objects to be used to test the identified method. """ class _BufferingConsumer(stream.Consumer): """A trivial Consumer that dumps what it consumes in a user-mutable buffer.""" def __init__(self): self.consumed = [] self.terminated = False def consume(self, value): self.consumed.append(value) def terminate(self): self.terminated = True def consume_and_terminate(self, value): self.consumed.append(value) self.terminated = True class _InlineUnaryUnaryMethod(face.MethodImplementation): def __init__(self, unary_unary_test_method, control): self._test_method = unary_unary_test_method self._control = control self.cardinality = cardinality.Cardinality.UNARY_UNARY self.style = style.Service.INLINE def unary_unary_inline(self, request, context): response_list = [] self._test_method.service(request, response_list.append, context, self._control) return response_list.pop(0) class _EventUnaryUnaryMethod(face.MethodImplementation): def __init__(self, unary_unary_test_method, control, pool): self._test_method = unary_unary_test_method self._control = control self._pool = pool self.cardinality = cardinality.Cardinality.UNARY_UNARY self.style = style.Service.EVENT def unary_unary_event(self, request, response_callback, context): if self._pool is None: self._test_method.service(request, response_callback, context, self._control) else: self._pool.submit(self._test_method.service, request, response_callback, context, self._control) class _InlineUnaryStreamMethod(face.MethodImplementation): def __init__(self, unary_stream_test_method, control): self._test_method = unary_stream_test_method self._control = control self.cardinality = cardinality.Cardinality.UNARY_STREAM self.style = style.Service.INLINE def unary_stream_inline(self, request, context): response_consumer = _BufferingConsumer() self._test_method.service(request, response_consumer, context, self._control) for response in response_consumer.consumed: yield response class _EventUnaryStreamMethod(face.MethodImplementation): def __init__(self, unary_stream_test_method, control, pool): self._test_method = unary_stream_test_method self._control = control self._pool = pool self.cardinality = cardinality.Cardinality.UNARY_STREAM self.style = style.Service.EVENT def unary_stream_event(self, request, response_consumer, context): if self._pool is None: self._test_method.service(request, response_consumer, context, self._control) else: self._pool.submit(self._test_method.service, request, response_consumer, context, self._control) class _InlineStreamUnaryMethod(face.MethodImplementation): def __init__(self, stream_unary_test_method, control): self._test_method = stream_unary_test_method self._control = control self.cardinality = cardinality.Cardinality.STREAM_UNARY self.style = style.Service.INLINE def stream_unary_inline(self, request_iterator, context): response_list = [] request_consumer = self._test_method.service(response_list.append, context, self._control) for request in request_iterator: request_consumer.consume(request) request_consumer.terminate() return response_list.pop(0) class _EventStreamUnaryMethod(face.MethodImplementation): def __init__(self, stream_unary_test_method, control, pool): self._test_method = stream_unary_test_method self._control = control self._pool = pool self.cardinality = cardinality.Cardinality.STREAM_UNARY self.style = style.Service.EVENT def stream_unary_event(self, response_callback, context): request_consumer = self._test_method.service(response_callback, context, self._control) if self._pool is None: return request_consumer else: return stream_util.ThreadSwitchingConsumer(request_consumer, self._pool) class _InlineStreamStreamMethod(face.MethodImplementation): def __init__(self, stream_stream_test_method, control): self._test_method = stream_stream_test_method self._control = control self.cardinality = cardinality.Cardinality.STREAM_STREAM self.style = style.Service.INLINE def stream_stream_inline(self, request_iterator, context): response_consumer = _BufferingConsumer() request_consumer = self._test_method.service(response_consumer, context, self._control) for request in request_iterator: request_consumer.consume(request) while response_consumer.consumed: yield response_consumer.consumed.pop(0) response_consumer.terminate() class _EventStreamStreamMethod(face.MethodImplementation): def __init__(self, stream_stream_test_method, control, pool): self._test_method = stream_stream_test_method self._control = control self._pool = pool self.cardinality = cardinality.Cardinality.STREAM_STREAM self.style = style.Service.EVENT def stream_stream_event(self, response_consumer, context): request_consumer = self._test_method.service(response_consumer, context, self._control) if self._pool is None: return request_consumer else: return stream_util.ThreadSwitchingConsumer(request_consumer, self._pool) class _UnaryConsumer(stream.Consumer): """A Consumer that only allows consumption of exactly one value.""" def __init__(self, action): self._lock = threading.Lock() self._action = action self._consumed = False self._terminated = False def consume(self, value): with self._lock: if self._consumed: raise ValueError('Unary consumer already consumed!') elif self._terminated: raise ValueError('Unary consumer already terminated!') else: self._consumed = True self._action(value) def terminate(self): with self._lock: if not self._consumed: raise ValueError('Unary consumer hasn\'t yet consumed!') elif self._terminated: raise ValueError('Unary consumer already terminated!') else: self._terminated = True def consume_and_terminate(self, value): with self._lock: if self._consumed: raise ValueError('Unary consumer already consumed!') elif self._terminated: raise ValueError('Unary consumer already terminated!') else: self._consumed = True self._terminated = True self._action(value) class _UnaryUnaryAdaptation(object): def __init__(self, unary_unary_test_method): self._method = unary_unary_test_method def service(self, response_consumer, context, control): def action(request): self._method.service(request, response_consumer.consume_and_terminate, context, control) return _UnaryConsumer(action) class _UnaryStreamAdaptation(object): def __init__(self, unary_stream_test_method): self._method = unary_stream_test_method def service(self, response_consumer, context, control): def action(request): self._method.service(request, response_consumer, context, control) return _UnaryConsumer(action) class _StreamUnaryAdaptation(object): def __init__(self, stream_unary_test_method): self._method = stream_unary_test_method def service(self, response_consumer, context, control): return self._method.service(response_consumer.consume_and_terminate, context, control) class _MultiMethodImplementation(face.MultiMethodImplementation): def __init__(self, methods, control, pool): self._methods = methods self._control = control self._pool = pool def service(self, group, name, response_consumer, context): method = self._methods.get(group, name, None) if method is None: raise face.NoSuchMethodError(group, name) elif self._pool is None: return method(response_consumer, context, self._control) else: request_consumer = method(response_consumer, context, self._control) return stream_util.ThreadSwitchingConsumer(request_consumer, self._pool) class _Assembly( collections.namedtuple( '_Assembly', ['methods', 'inlines', 'events', 'adaptations', 'messages'])): """An intermediate structure created when creating a TestServiceDigest.""" def _assemble(scenarios, identifiers, inline_method_constructor, event_method_constructor, adapter, control, pool): """Creates an _Assembly from the given scenarios.""" methods = {} inlines = {} events = {} adaptations = {} messages = {} for identifier, scenario in six.iteritems(scenarios): if identifier in identifiers: raise ValueError('Repeated identifier "(%s, %s)"!' % identifier) test_method = scenario[0] inline_method = inline_method_constructor(test_method, control) event_method = event_method_constructor(test_method, control, pool) adaptation = adapter(test_method) methods[identifier] = test_method inlines[identifier] = inline_method events[identifier] = event_method adaptations[identifier] = adaptation messages[identifier] = scenario[1] return _Assembly(methods, inlines, events, adaptations, messages) def digest(service, control, pool): """Creates a TestServiceDigest from a TestService. Args: service: A _service.TestService. control: A test_control.Control. pool: If RPC methods should be serviced in a separate thread, a thread pool. None if RPC methods should be serviced in the thread belonging to the run-time that calls for their service. Returns: A TestServiceDigest synthesized from the given service.TestService. """ identifiers = set() unary_unary = _assemble(service.unary_unary_scenarios(), identifiers, _InlineUnaryUnaryMethod, _EventUnaryUnaryMethod, _UnaryUnaryAdaptation, control, pool) identifiers.update(unary_unary.inlines) unary_stream = _assemble(service.unary_stream_scenarios(), identifiers, _InlineUnaryStreamMethod, _EventUnaryStreamMethod, _UnaryStreamAdaptation, control, pool) identifiers.update(unary_stream.inlines) stream_unary = _assemble(service.stream_unary_scenarios(), identifiers, _InlineStreamUnaryMethod, _EventStreamUnaryMethod, _StreamUnaryAdaptation, control, pool) identifiers.update(stream_unary.inlines) stream_stream = _assemble(service.stream_stream_scenarios(), identifiers, _InlineStreamStreamMethod, _EventStreamStreamMethod, _IDENTITY, control, pool) identifiers.update(stream_stream.inlines) methods = dict(unary_unary.methods) methods.update(unary_stream.methods) methods.update(stream_unary.methods) methods.update(stream_stream.methods) adaptations = dict(unary_unary.adaptations) adaptations.update(unary_stream.adaptations) adaptations.update(stream_unary.adaptations) adaptations.update(stream_stream.adaptations) inlines = dict(unary_unary.inlines) inlines.update(unary_stream.inlines) inlines.update(stream_unary.inlines) inlines.update(stream_stream.inlines) events = dict(unary_unary.events) events.update(unary_stream.events) events.update(stream_unary.events) events.update(stream_stream.events) return TestServiceDigest( methods, inlines, events, _MultiMethodImplementation(adaptations, control, pool), unary_unary.messages, unary_stream.messages, stream_unary.messages, stream_stream.messages) _future_invocation_asynchronous_event_service.py000066400000000000000000000610301310511640000403440ustar00rootroot00000000000000grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/interfaces/face# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Test code for the Face layer of RPC Framework.""" from __future__ import division import abc import contextlib import itertools import threading import unittest from concurrent import futures import six # test_interfaces is referenced from specification in this module. from grpc.framework.foundation import future from grpc.framework.foundation import logging_pool from grpc.framework.interfaces.face import face from tests.unit.framework.common import test_constants from tests.unit.framework.common import test_control from tests.unit.framework.common import test_coverage from tests.unit.framework.interfaces.face import _3069_test_constant from tests.unit.framework.interfaces.face import _digest from tests.unit.framework.interfaces.face import _stock_service from tests.unit.framework.interfaces.face import test_interfaces # pylint: disable=unused-import class _PauseableIterator(object): def __init__(self, upstream): self._upstream = upstream self._condition = threading.Condition() self._paused = False @contextlib.contextmanager def pause(self): with self._condition: self._paused = True yield with self._condition: self._paused = False self._condition.notify_all() def __iter__(self): return self def __next__(self): return self.next() def next(self): with self._condition: while self._paused: self._condition.wait() return next(self._upstream) class _Callback(object): def __init__(self): self._condition = threading.Condition() self._called = False self._passed_future = None self._passed_other_stuff = None def __call__(self, *args, **kwargs): with self._condition: self._called = True if args: self._passed_future = args[0] if 1 < len(args) or kwargs: self._passed_other_stuff = tuple(args[1:]), dict(kwargs) self._condition.notify_all() def future(self): with self._condition: while True: if self._passed_other_stuff is not None: raise ValueError( 'Test callback passed unexpected values: %s', self._passed_other_stuff) elif self._called: return self._passed_future else: self._condition.wait() class TestCase( six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest.TestCase)): """A test of the Face layer of RPC Framework. Concrete subclasses must have an "implementation" attribute of type test_interfaces.Implementation and an "invoker_constructor" attribute of type _invocation.InvokerConstructor. """ NAME = 'FutureInvocationAsynchronousEventServiceTest' def setUp(self): """See unittest.TestCase.setUp for full specification. Overriding implementations must call this implementation. """ self._control = test_control.PauseFailControl() self._digest_pool = logging_pool.pool(test_constants.POOL_SIZE) self._digest = _digest.digest(_stock_service.STOCK_TEST_SERVICE, self._control, self._digest_pool) generic_stub, dynamic_stubs, self._memo = self.implementation.instantiate( self._digest.methods, self._digest.event_method_implementations, None) self._invoker = self.invoker_constructor.construct_invoker( generic_stub, dynamic_stubs, self._digest.methods) def tearDown(self): """See unittest.TestCase.tearDown for full specification. Overriding implementations must call this implementation. """ self._invoker = None self.implementation.destantiate(self._memo) self._digest_pool.shutdown(wait=True) def testSuccessfulUnaryRequestUnaryResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_unary_messages_sequences)): for test_messages in test_messages_sequence: request = test_messages.request() callback = _Callback() response_future = self._invoker.future(group, method)( request, test_constants.LONG_TIMEOUT) response_future.add_done_callback(callback) response = response_future.result() test_messages.verify(request, response, self) self.assertIs(callback.future(), response_future) self.assertIsNone(response_future.exception()) self.assertIsNone(response_future.traceback()) def testSuccessfulUnaryRequestStreamResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_stream_messages_sequences)): for test_messages in test_messages_sequence: request = test_messages.request() response_iterator = self._invoker.future(group, method)( request, test_constants.LONG_TIMEOUT) responses = list(response_iterator) test_messages.verify(request, responses, self) def testSuccessfulStreamRequestUnaryResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.stream_unary_messages_sequences)): for test_messages in test_messages_sequence: requests = test_messages.requests() request_iterator = _PauseableIterator(iter(requests)) callback = _Callback() # Use of a paused iterator of requests allows us to test that control is # returned to calling code before the iterator yields any requests. with request_iterator.pause(): response_future = self._invoker.future(group, method)( request_iterator, test_constants.LONG_TIMEOUT) response_future.add_done_callback(callback) future_passed_to_callback = callback.future() response = future_passed_to_callback.result() test_messages.verify(requests, response, self) self.assertIs(future_passed_to_callback, response_future) self.assertIsNone(response_future.exception()) self.assertIsNone(response_future.traceback()) def testSuccessfulStreamRequestStreamResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.stream_stream_messages_sequences)): for test_messages in test_messages_sequence: requests = test_messages.requests() request_iterator = _PauseableIterator(iter(requests)) # Use of a paused iterator of requests allows us to test that control is # returned to calling code before the iterator yields any requests. with request_iterator.pause(): response_iterator = self._invoker.future(group, method)( request_iterator, test_constants.LONG_TIMEOUT) responses = list(response_iterator) test_messages.verify(requests, responses, self) def testSequentialInvocations(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_unary_messages_sequences)): for test_messages in test_messages_sequence: first_request = test_messages.request() second_request = test_messages.request() first_response_future = self._invoker.future(group, method)( first_request, test_constants.LONG_TIMEOUT) first_response = first_response_future.result() test_messages.verify(first_request, first_response, self) second_response_future = self._invoker.future(group, method)( second_request, test_constants.LONG_TIMEOUT) second_response = second_response_future.result() test_messages.verify(second_request, second_response, self) def testParallelInvocations(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_unary_messages_sequences)): for test_messages in test_messages_sequence: first_request = test_messages.request() second_request = test_messages.request() first_response_future = self._invoker.future(group, method)( first_request, test_constants.LONG_TIMEOUT) second_response_future = self._invoker.future(group, method)( second_request, test_constants.LONG_TIMEOUT) first_response = first_response_future.result() second_response = second_response_future.result() test_messages.verify(first_request, first_response, self) test_messages.verify(second_request, second_response, self) for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_unary_messages_sequences)): for test_messages in test_messages_sequence: requests = [] response_futures = [] for _ in range(test_constants.THREAD_CONCURRENCY): request = test_messages.request() response_future = self._invoker.future(group, method)( request, test_constants.LONG_TIMEOUT) requests.append(request) response_futures.append(response_future) responses = [ response_future.result() for response_future in response_futures ] for request, response in zip(requests, responses): test_messages.verify(request, response, self) def testWaitingForSomeButNotAllParallelInvocations(self): pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_unary_messages_sequences)): for test_messages in test_messages_sequence: requests = [] response_futures_to_indices = {} for index in range(test_constants.THREAD_CONCURRENCY): request = test_messages.request() inner_response_future = self._invoker.future(group, method)( request, test_constants.LONG_TIMEOUT) outer_response_future = pool.submit( inner_response_future.result) requests.append(request) response_futures_to_indices[outer_response_future] = index some_completed_response_futures_iterator = itertools.islice( futures.as_completed(response_futures_to_indices), test_constants.THREAD_CONCURRENCY // 2) for response_future in some_completed_response_futures_iterator: index = response_futures_to_indices[response_future] test_messages.verify(requests[index], response_future.result(), self) pool.shutdown(wait=True) def testCancelledUnaryRequestUnaryResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_unary_messages_sequences)): for test_messages in test_messages_sequence: request = test_messages.request() callback = _Callback() with self._control.pause(): response_future = self._invoker.future(group, method)( request, test_constants.LONG_TIMEOUT) response_future.add_done_callback(callback) cancel_method_return_value = response_future.cancel() self.assertIs(callback.future(), response_future) self.assertFalse(cancel_method_return_value) self.assertTrue(response_future.cancelled()) with self.assertRaises(future.CancelledError): response_future.result() with self.assertRaises(future.CancelledError): response_future.exception() with self.assertRaises(future.CancelledError): response_future.traceback() def testCancelledUnaryRequestStreamResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_stream_messages_sequences)): for test_messages in test_messages_sequence: request = test_messages.request() with self._control.pause(): response_iterator = self._invoker.future(group, method)( request, test_constants.LONG_TIMEOUT) response_iterator.cancel() with self.assertRaises(face.CancellationError): next(response_iterator) def testCancelledStreamRequestUnaryResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.stream_unary_messages_sequences)): for test_messages in test_messages_sequence: requests = test_messages.requests() callback = _Callback() with self._control.pause(): response_future = self._invoker.future(group, method)( iter(requests), test_constants.LONG_TIMEOUT) response_future.add_done_callback(callback) cancel_method_return_value = response_future.cancel() self.assertIs(callback.future(), response_future) self.assertFalse(cancel_method_return_value) self.assertTrue(response_future.cancelled()) with self.assertRaises(future.CancelledError): response_future.result() with self.assertRaises(future.CancelledError): response_future.exception() with self.assertRaises(future.CancelledError): response_future.traceback() def testCancelledStreamRequestStreamResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.stream_stream_messages_sequences)): for test_messages in test_messages_sequence: requests = test_messages.requests() with self._control.pause(): response_iterator = self._invoker.future(group, method)( iter(requests), test_constants.LONG_TIMEOUT) response_iterator.cancel() with self.assertRaises(face.CancellationError): next(response_iterator) def testExpiredUnaryRequestUnaryResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_unary_messages_sequences)): for test_messages in test_messages_sequence: request = test_messages.request() callback = _Callback() with self._control.pause(): response_future = self._invoker.future(group, method)( request, _3069_test_constant.REALLY_SHORT_TIMEOUT) response_future.add_done_callback(callback) self.assertIs(callback.future(), response_future) self.assertIsInstance(response_future.exception(), face.ExpirationError) with self.assertRaises(face.ExpirationError): response_future.result() self.assertIsInstance(response_future.exception(), face.AbortionError) self.assertIsNotNone(response_future.traceback()) def testExpiredUnaryRequestStreamResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_stream_messages_sequences)): for test_messages in test_messages_sequence: request = test_messages.request() with self._control.pause(): response_iterator = self._invoker.future(group, method)( request, _3069_test_constant.REALLY_SHORT_TIMEOUT) with self.assertRaises(face.ExpirationError): list(response_iterator) def testExpiredStreamRequestUnaryResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.stream_unary_messages_sequences)): for test_messages in test_messages_sequence: requests = test_messages.requests() callback = _Callback() with self._control.pause(): response_future = self._invoker.future(group, method)( iter(requests), _3069_test_constant.REALLY_SHORT_TIMEOUT) response_future.add_done_callback(callback) self.assertIs(callback.future(), response_future) self.assertIsInstance(response_future.exception(), face.ExpirationError) with self.assertRaises(face.ExpirationError): response_future.result() self.assertIsInstance(response_future.exception(), face.AbortionError) self.assertIsNotNone(response_future.traceback()) def testExpiredStreamRequestStreamResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.stream_stream_messages_sequences)): for test_messages in test_messages_sequence: requests = test_messages.requests() with self._control.pause(): response_iterator = self._invoker.future(group, method)( iter(requests), _3069_test_constant.REALLY_SHORT_TIMEOUT) with self.assertRaises(face.ExpirationError): list(response_iterator) def testFailedUnaryRequestUnaryResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_unary_messages_sequences)): for test_messages in test_messages_sequence: request = test_messages.request() callback = _Callback() abortion_callback = _Callback() with self._control.fail(): response_future = self._invoker.future(group, method)( request, _3069_test_constant.REALLY_SHORT_TIMEOUT) response_future.add_done_callback(callback) response_future.add_abortion_callback(abortion_callback) self.assertIs(callback.future(), response_future) # Because the servicer fails outside of the thread from which the # servicer-side runtime called into it its failure is # indistinguishable from simply not having called its # response_callback before the expiration of the RPC. self.assertIsInstance(response_future.exception(), face.ExpirationError) with self.assertRaises(face.ExpirationError): response_future.result() self.assertIsNotNone(response_future.traceback()) self.assertIsNotNone(abortion_callback.future()) def testFailedUnaryRequestStreamResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_stream_messages_sequences)): for test_messages in test_messages_sequence: request = test_messages.request() # Because the servicer fails outside of the thread from which the # servicer-side runtime called into it its failure is indistinguishable # from simply not having called its response_consumer before the # expiration of the RPC. with self._control.fail(), self.assertRaises( face.ExpirationError): response_iterator = self._invoker.future(group, method)( request, _3069_test_constant.REALLY_SHORT_TIMEOUT) list(response_iterator) def testFailedStreamRequestUnaryResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.stream_unary_messages_sequences)): for test_messages in test_messages_sequence: requests = test_messages.requests() callback = _Callback() abortion_callback = _Callback() with self._control.fail(): response_future = self._invoker.future(group, method)( iter(requests), _3069_test_constant.REALLY_SHORT_TIMEOUT) response_future.add_done_callback(callback) response_future.add_abortion_callback(abortion_callback) self.assertIs(callback.future(), response_future) # Because the servicer fails outside of the thread from which the # servicer-side runtime called into it its failure is # indistinguishable from simply not having called its # response_callback before the expiration of the RPC. self.assertIsInstance(response_future.exception(), face.ExpirationError) with self.assertRaises(face.ExpirationError): response_future.result() self.assertIsNotNone(response_future.traceback()) self.assertIsNotNone(abortion_callback.future()) def testFailedStreamRequestStreamResponse(self): for (group, method), test_messages_sequence in ( six.iteritems(self._digest.stream_stream_messages_sequences)): for test_messages in test_messages_sequence: requests = test_messages.requests() # Because the servicer fails outside of the thread from which the # servicer-side runtime called into it its failure is indistinguishable # from simply not having called its response_consumer before the # expiration of the RPC. with self._control.fail(), self.assertRaises( face.ExpirationError): response_iterator = self._invoker.future(group, method)( iter(requests), _3069_test_constant.REALLY_SHORT_TIMEOUT) list(response_iterator) grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_invocation.py000066400000000000000000000166251310511640000313070ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Coverage across the Face layer's generic-to-dynamic range for invocation.""" import abc import six from grpc.framework.common import cardinality _CARDINALITY_TO_GENERIC_BLOCKING_BEHAVIOR = { cardinality.Cardinality.UNARY_UNARY: 'blocking_unary_unary', cardinality.Cardinality.UNARY_STREAM: 'inline_unary_stream', cardinality.Cardinality.STREAM_UNARY: 'blocking_stream_unary', cardinality.Cardinality.STREAM_STREAM: 'inline_stream_stream', } _CARDINALITY_TO_GENERIC_FUTURE_BEHAVIOR = { cardinality.Cardinality.UNARY_UNARY: 'future_unary_unary', cardinality.Cardinality.UNARY_STREAM: 'inline_unary_stream', cardinality.Cardinality.STREAM_UNARY: 'future_stream_unary', cardinality.Cardinality.STREAM_STREAM: 'inline_stream_stream', } _CARDINALITY_TO_GENERIC_EVENT_BEHAVIOR = { cardinality.Cardinality.UNARY_UNARY: 'event_unary_unary', cardinality.Cardinality.UNARY_STREAM: 'event_unary_stream', cardinality.Cardinality.STREAM_UNARY: 'event_stream_unary', cardinality.Cardinality.STREAM_STREAM: 'event_stream_stream', } _CARDINALITY_TO_MULTI_CALLABLE_ATTRIBUTE = { cardinality.Cardinality.UNARY_UNARY: 'unary_unary', cardinality.Cardinality.UNARY_STREAM: 'unary_stream', cardinality.Cardinality.STREAM_UNARY: 'stream_unary', cardinality.Cardinality.STREAM_STREAM: 'stream_stream', } class Invoker(six.with_metaclass(abc.ABCMeta)): """A type used to invoke test RPCs.""" @abc.abstractmethod def blocking(self, group, name): """Invokes an RPC with blocking control flow.""" raise NotImplementedError() @abc.abstractmethod def future(self, group, name): """Invokes an RPC with future control flow.""" raise NotImplementedError() @abc.abstractmethod def event(self, group, name): """Invokes an RPC with event control flow.""" raise NotImplementedError() class InvokerConstructor(six.with_metaclass(abc.ABCMeta)): """A type used to create Invokers.""" @abc.abstractmethod def name(self): """Specifies the name of the Invoker constructed by this object.""" raise NotImplementedError() @abc.abstractmethod def construct_invoker(self, generic_stub, dynamic_stubs, methods): """Constructs an Invoker for the given stubs and methods.""" raise NotImplementedError() class _GenericInvoker(Invoker): def __init__(self, generic_stub, methods): self._stub = generic_stub self._methods = methods def _behavior(self, group, name, cardinality_to_generic_method): method_cardinality = self._methods[group, name].cardinality() behavior = getattr(self._stub, cardinality_to_generic_method[method_cardinality]) return lambda *args, **kwargs: behavior(group, name, *args, **kwargs) def blocking(self, group, name): return self._behavior(group, name, _CARDINALITY_TO_GENERIC_BLOCKING_BEHAVIOR) def future(self, group, name): return self._behavior(group, name, _CARDINALITY_TO_GENERIC_FUTURE_BEHAVIOR) def event(self, group, name): return self._behavior(group, name, _CARDINALITY_TO_GENERIC_EVENT_BEHAVIOR) class _GenericInvokerConstructor(InvokerConstructor): def name(self): return 'GenericInvoker' def construct_invoker(self, generic_stub, dynamic_stub, methods): return _GenericInvoker(generic_stub, methods) class _MultiCallableInvoker(Invoker): def __init__(self, generic_stub, methods): self._stub = generic_stub self._methods = methods def _multi_callable(self, group, name): method_cardinality = self._methods[group, name].cardinality() behavior = getattr( self._stub, _CARDINALITY_TO_MULTI_CALLABLE_ATTRIBUTE[method_cardinality]) return behavior(group, name) def blocking(self, group, name): return self._multi_callable(group, name) def future(self, group, name): method_cardinality = self._methods[group, name].cardinality() behavior = getattr( self._stub, _CARDINALITY_TO_MULTI_CALLABLE_ATTRIBUTE[method_cardinality]) if method_cardinality in (cardinality.Cardinality.UNARY_UNARY, cardinality.Cardinality.STREAM_UNARY): return behavior(group, name).future else: return behavior(group, name) def event(self, group, name): return self._multi_callable(group, name).event class _MultiCallableInvokerConstructor(InvokerConstructor): def name(self): return 'MultiCallableInvoker' def construct_invoker(self, generic_stub, dynamic_stub, methods): return _MultiCallableInvoker(generic_stub, methods) class _DynamicInvoker(Invoker): def __init__(self, dynamic_stubs, methods): self._stubs = dynamic_stubs self._methods = methods def blocking(self, group, name): return getattr(self._stubs[group], name) def future(self, group, name): if self._methods[group, name].cardinality() in ( cardinality.Cardinality.UNARY_UNARY, cardinality.Cardinality.STREAM_UNARY): return getattr(self._stubs[group], name).future else: return getattr(self._stubs[group], name) def event(self, group, name): return getattr(self._stubs[group], name).event class _DynamicInvokerConstructor(InvokerConstructor): def name(self): return 'DynamicInvoker' def construct_invoker(self, generic_stub, dynamic_stubs, methods): return _DynamicInvoker(dynamic_stubs, methods) def invoker_constructors(): """Creates a sequence of InvokerConstructors to use in tests of RPCs. Returns: A sequence of InvokerConstructors. """ return (_GenericInvokerConstructor(), _MultiCallableInvokerConstructor(), _DynamicInvokerConstructor(),) grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_service.py000066400000000000000000000270051310511640000305700ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Private interfaces implemented by data sets used in Face-layer tests.""" import abc import six # face is referenced from specification in this module. from grpc.framework.interfaces.face import face # pylint: disable=unused-import from tests.unit.framework.interfaces.face import test_interfaces class UnaryUnaryTestMethodImplementation( six.with_metaclass(abc.ABCMeta, test_interfaces.Method)): """A controllable implementation of a unary-unary method.""" @abc.abstractmethod def service(self, request, response_callback, context, control): """Services an RPC that accepts one message and produces one message. Args: request: The single request message for the RPC. response_callback: A callback to be called to accept the response message of the RPC. context: An face.ServicerContext object. control: A test_control.Control to control execution of this method. Raises: abandonment.Abandoned: May or may not be raised when the RPC has been aborted. """ raise NotImplementedError() class UnaryUnaryTestMessages(six.with_metaclass(abc.ABCMeta)): """A type for unary-request-unary-response message pairings.""" @abc.abstractmethod def request(self): """Affords a request message. Implementations of this method should return a different message with each call so that multiple test executions of the test method may be made with different inputs. Returns: A request message. """ raise NotImplementedError() @abc.abstractmethod def verify(self, request, response, test_case): """Verifies that the computed response matches the given request. Args: request: A request message. response: A response message. test_case: A unittest.TestCase object affording useful assertion methods. Raises: AssertionError: If the request and response do not match, indicating that there was some problem executing the RPC under test. """ raise NotImplementedError() class UnaryStreamTestMethodImplementation( six.with_metaclass(abc.ABCMeta, test_interfaces.Method)): """A controllable implementation of a unary-stream method.""" @abc.abstractmethod def service(self, request, response_consumer, context, control): """Services an RPC that takes one message and produces a stream of messages. Args: request: The single request message for the RPC. response_consumer: A stream.Consumer to be called to accept the response messages of the RPC. context: A face.ServicerContext object. control: A test_control.Control to control execution of this method. Raises: abandonment.Abandoned: May or may not be raised when the RPC has been aborted. """ raise NotImplementedError() class UnaryStreamTestMessages(six.with_metaclass(abc.ABCMeta)): """A type for unary-request-stream-response message pairings.""" @abc.abstractmethod def request(self): """Affords a request message. Implementations of this method should return a different message with each call so that multiple test executions of the test method may be made with different inputs. Returns: A request message. """ raise NotImplementedError() @abc.abstractmethod def verify(self, request, responses, test_case): """Verifies that the computed responses match the given request. Args: request: A request message. responses: A sequence of response messages. test_case: A unittest.TestCase object affording useful assertion methods. Raises: AssertionError: If the request and responses do not match, indicating that there was some problem executing the RPC under test. """ raise NotImplementedError() class StreamUnaryTestMethodImplementation( six.with_metaclass(abc.ABCMeta, test_interfaces.Method)): """A controllable implementation of a stream-unary method.""" @abc.abstractmethod def service(self, response_callback, context, control): """Services an RPC that takes a stream of messages and produces one message. Args: response_callback: A callback to be called to accept the response message of the RPC. context: A face.ServicerContext object. control: A test_control.Control to control execution of this method. Returns: A stream.Consumer with which to accept the request messages of the RPC. The consumer returned from this method may or may not be invoked to completion: in the case of RPC abortion, RPC Framework will simply stop passing messages to this object. Implementations must not assume that this object will be called to completion of the request stream or even called at all. Raises: abandonment.Abandoned: May or may not be raised when the RPC has been aborted. """ raise NotImplementedError() class StreamUnaryTestMessages(six.with_metaclass(abc.ABCMeta)): """A type for stream-request-unary-response message pairings.""" @abc.abstractmethod def requests(self): """Affords a sequence of request messages. Implementations of this method should return a different sequences with each call so that multiple test executions of the test method may be made with different inputs. Returns: A sequence of request messages. """ raise NotImplementedError() @abc.abstractmethod def verify(self, requests, response, test_case): """Verifies that the computed response matches the given requests. Args: requests: A sequence of request messages. response: A response message. test_case: A unittest.TestCase object affording useful assertion methods. Raises: AssertionError: If the requests and response do not match, indicating that there was some problem executing the RPC under test. """ raise NotImplementedError() class StreamStreamTestMethodImplementation( six.with_metaclass(abc.ABCMeta, test_interfaces.Method)): """A controllable implementation of a stream-stream method.""" @abc.abstractmethod def service(self, response_consumer, context, control): """Services an RPC that accepts and produces streams of messages. Args: response_consumer: A stream.Consumer to be called to accept the response messages of the RPC. context: A face.ServicerContext object. control: A test_control.Control to control execution of this method. Returns: A stream.Consumer with which to accept the request messages of the RPC. The consumer returned from this method may or may not be invoked to completion: in the case of RPC abortion, RPC Framework will simply stop passing messages to this object. Implementations must not assume that this object will be called to completion of the request stream or even called at all. Raises: abandonment.Abandoned: May or may not be raised when the RPC has been aborted. """ raise NotImplementedError() class StreamStreamTestMessages(six.with_metaclass(abc.ABCMeta)): """A type for stream-request-stream-response message pairings.""" @abc.abstractmethod def requests(self): """Affords a sequence of request messages. Implementations of this method should return a different sequences with each call so that multiple test executions of the test method may be made with different inputs. Returns: A sequence of request messages. """ raise NotImplementedError() @abc.abstractmethod def verify(self, requests, responses, test_case): """Verifies that the computed response matches the given requests. Args: requests: A sequence of request messages. responses: A sequence of response messages. test_case: A unittest.TestCase object affording useful assertion methods. Raises: AssertionError: If the requests and responses do not match, indicating that there was some problem executing the RPC under test. """ raise NotImplementedError() class TestService(six.with_metaclass(abc.ABCMeta)): """A specification of implemented methods to use in tests.""" @abc.abstractmethod def unary_unary_scenarios(self): """Affords unary-request-unary-response test methods and their messages. Returns: A dict from method group-name pair to implementation/messages pair. The first element of the pair is a UnaryUnaryTestMethodImplementation object and the second element is a sequence of UnaryUnaryTestMethodMessages objects. """ raise NotImplementedError() @abc.abstractmethod def unary_stream_scenarios(self): """Affords unary-request-stream-response test methods and their messages. Returns: A dict from method group-name pair to implementation/messages pair. The first element of the pair is a UnaryStreamTestMethodImplementation object and the second element is a sequence of UnaryStreamTestMethodMessages objects. """ raise NotImplementedError() @abc.abstractmethod def stream_unary_scenarios(self): """Affords stream-request-unary-response test methods and their messages. Returns: A dict from method group-name pair to implementation/messages pair. The first element of the pair is a StreamUnaryTestMethodImplementation object and the second element is a sequence of StreamUnaryTestMethodMessages objects. """ raise NotImplementedError() @abc.abstractmethod def stream_stream_scenarios(self): """Affords stream-request-stream-response test methods and their messages. Returns: A dict from method group-name pair to implementation/messages pair. The first element of the pair is a StreamStreamTestMethodImplementation object and the second element is a sequence of StreamStreamTestMethodMessages objects. """ raise NotImplementedError() grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_stock_service.py000066400000000000000000000335351310511640000320000ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Examples of Python implementations of the stock.proto Stock service.""" from grpc.framework.common import cardinality from grpc.framework.foundation import abandonment from grpc.framework.foundation import stream from tests.unit.framework.common import test_constants from tests.unit.framework.interfaces.face import _service from tests.unit._junkdrawer import stock_pb2 _STOCK_GROUP_NAME = 'Stock' _SYMBOL_FORMAT = 'test symbol:%03d' # A test-appropriate security-pricing function. :-P _price = lambda symbol_name: float(hash(symbol_name) % 4096) def _get_last_trade_price(stock_request, stock_reply_callback, control, active): """A unary-request, unary-response test method.""" control.control() if active(): stock_reply_callback( stock_pb2.StockReply( symbol=stock_request.symbol, price=_price( stock_request.symbol))) else: raise abandonment.Abandoned() def _get_last_trade_price_multiple(stock_reply_consumer, control, active): """A stream-request, stream-response test method.""" def stock_reply_for_stock_request(stock_request): control.control() if active(): return stock_pb2.StockReply( symbol=stock_request.symbol, price=_price(stock_request.symbol)) else: raise abandonment.Abandoned() class StockRequestConsumer(stream.Consumer): def consume(self, stock_request): stock_reply_consumer.consume( stock_reply_for_stock_request(stock_request)) def terminate(self): control.control() stock_reply_consumer.terminate() def consume_and_terminate(self, stock_request): stock_reply_consumer.consume_and_terminate( stock_reply_for_stock_request(stock_request)) return StockRequestConsumer() def _watch_future_trades(stock_request, stock_reply_consumer, control, active): """A unary-request, stream-response test method.""" base_price = _price(stock_request.symbol) for index in range(stock_request.num_trades_to_watch): control.control() if active(): stock_reply_consumer.consume( stock_pb2.StockReply( symbol=stock_request.symbol, price=base_price + index)) else: raise abandonment.Abandoned() stock_reply_consumer.terminate() def _get_highest_trade_price(stock_reply_callback, control, active): """A stream-request, unary-response test method.""" class StockRequestConsumer(stream.Consumer): """Keeps an ongoing record of the most valuable symbol yet consumed.""" def __init__(self): self._symbol = None self._price = None def consume(self, stock_request): control.control() if active(): if self._price is None: self._symbol = stock_request.symbol self._price = _price(stock_request.symbol) else: candidate_price = _price(stock_request.symbol) if self._price < candidate_price: self._symbol = stock_request.symbol self._price = candidate_price def terminate(self): control.control() if active(): if self._symbol is None: raise ValueError() else: stock_reply_callback( stock_pb2.StockReply( symbol=self._symbol, price=self._price)) self._symbol = None self._price = None def consume_and_terminate(self, stock_request): control.control() if active(): if self._price is None: stock_reply_callback( stock_pb2.StockReply( symbol=stock_request.symbol, price=_price(stock_request.symbol))) else: candidate_price = _price(stock_request.symbol) if self._price < candidate_price: stock_reply_callback( stock_pb2.StockReply( symbol=stock_request.symbol, price=candidate_price)) else: stock_reply_callback( stock_pb2.StockReply( symbol=self._symbol, price=self._price)) self._symbol = None self._price = None return StockRequestConsumer() class GetLastTradePrice(_service.UnaryUnaryTestMethodImplementation): """GetLastTradePrice for use in tests.""" def group(self): return _STOCK_GROUP_NAME def name(self): return 'GetLastTradePrice' def cardinality(self): return cardinality.Cardinality.UNARY_UNARY def request_class(self): return stock_pb2.StockRequest def response_class(self): return stock_pb2.StockReply def serialize_request(self, request): return request.SerializeToString() def deserialize_request(self, serialized_request): return stock_pb2.StockRequest.FromString(serialized_request) def serialize_response(self, response): return response.SerializeToString() def deserialize_response(self, serialized_response): return stock_pb2.StockReply.FromString(serialized_response) def service(self, request, response_callback, context, control): _get_last_trade_price(request, response_callback, control, context.is_active) class GetLastTradePriceMessages(_service.UnaryUnaryTestMessages): def __init__(self): self._index = 0 def request(self): symbol = _SYMBOL_FORMAT % self._index self._index += 1 return stock_pb2.StockRequest(symbol=symbol) def verify(self, request, response, test_case): test_case.assertEqual(request.symbol, response.symbol) test_case.assertEqual(_price(request.symbol), response.price) class GetLastTradePriceMultiple(_service.StreamStreamTestMethodImplementation): """GetLastTradePriceMultiple for use in tests.""" def group(self): return _STOCK_GROUP_NAME def name(self): return 'GetLastTradePriceMultiple' def cardinality(self): return cardinality.Cardinality.STREAM_STREAM def request_class(self): return stock_pb2.StockRequest def response_class(self): return stock_pb2.StockReply def serialize_request(self, request): return request.SerializeToString() def deserialize_request(self, serialized_request): return stock_pb2.StockRequest.FromString(serialized_request) def serialize_response(self, response): return response.SerializeToString() def deserialize_response(self, serialized_response): return stock_pb2.StockReply.FromString(serialized_response) def service(self, response_consumer, context, control): return _get_last_trade_price_multiple(response_consumer, control, context.is_active) class GetLastTradePriceMultipleMessages(_service.StreamStreamTestMessages): """Pairs of message streams for use with GetLastTradePriceMultiple.""" def __init__(self): self._index = 0 def requests(self): base_index = self._index self._index += 1 return [ stock_pb2.StockRequest(symbol=_SYMBOL_FORMAT % (base_index + index)) for index in range(test_constants.STREAM_LENGTH) ] def verify(self, requests, responses, test_case): test_case.assertEqual(len(requests), len(responses)) for stock_request, stock_reply in zip(requests, responses): test_case.assertEqual(stock_request.symbol, stock_reply.symbol) test_case.assertEqual( _price(stock_request.symbol), stock_reply.price) class WatchFutureTrades(_service.UnaryStreamTestMethodImplementation): """WatchFutureTrades for use in tests.""" def group(self): return _STOCK_GROUP_NAME def name(self): return 'WatchFutureTrades' def cardinality(self): return cardinality.Cardinality.UNARY_STREAM def request_class(self): return stock_pb2.StockRequest def response_class(self): return stock_pb2.StockReply def serialize_request(self, request): return request.SerializeToString() def deserialize_request(self, serialized_request): return stock_pb2.StockRequest.FromString(serialized_request) def serialize_response(self, response): return response.SerializeToString() def deserialize_response(self, serialized_response): return stock_pb2.StockReply.FromString(serialized_response) def service(self, request, response_consumer, context, control): _watch_future_trades(request, response_consumer, control, context.is_active) class WatchFutureTradesMessages(_service.UnaryStreamTestMessages): """Pairs of a single request message and a sequence of response messages.""" def __init__(self): self._index = 0 def request(self): symbol = _SYMBOL_FORMAT % self._index self._index += 1 return stock_pb2.StockRequest( symbol=symbol, num_trades_to_watch=test_constants.STREAM_LENGTH) def verify(self, request, responses, test_case): test_case.assertEqual(test_constants.STREAM_LENGTH, len(responses)) base_price = _price(request.symbol) for index, response in enumerate(responses): test_case.assertEqual(base_price + index, response.price) class GetHighestTradePrice(_service.StreamUnaryTestMethodImplementation): """GetHighestTradePrice for use in tests.""" def group(self): return _STOCK_GROUP_NAME def name(self): return 'GetHighestTradePrice' def cardinality(self): return cardinality.Cardinality.STREAM_UNARY def request_class(self): return stock_pb2.StockRequest def response_class(self): return stock_pb2.StockReply def serialize_request(self, request): return request.SerializeToString() def deserialize_request(self, serialized_request): return stock_pb2.StockRequest.FromString(serialized_request) def serialize_response(self, response): return response.SerializeToString() def deserialize_response(self, serialized_response): return stock_pb2.StockReply.FromString(serialized_response) def service(self, response_callback, context, control): return _get_highest_trade_price(response_callback, control, context.is_active) class GetHighestTradePriceMessages(_service.StreamUnaryTestMessages): def requests(self): return [ stock_pb2.StockRequest(symbol=_SYMBOL_FORMAT % index) for index in range(test_constants.STREAM_LENGTH) ] def verify(self, requests, response, test_case): price = None symbol = None for stock_request in requests: current_symbol = stock_request.symbol current_price = _price(current_symbol) if price is None or price < current_price: price = current_price symbol = current_symbol test_case.assertEqual(price, response.price) test_case.assertEqual(symbol, response.symbol) class StockTestService(_service.TestService): """A corpus of test data with one method of each RPC cardinality.""" def unary_unary_scenarios(self): return { (_STOCK_GROUP_NAME, 'GetLastTradePrice'): (GetLastTradePrice(), [GetLastTradePriceMessages()]), } def unary_stream_scenarios(self): return { (_STOCK_GROUP_NAME, 'WatchFutureTrades'): (WatchFutureTrades(), [WatchFutureTradesMessages()]), } def stream_unary_scenarios(self): return { (_STOCK_GROUP_NAME, 'GetHighestTradePrice'): (GetHighestTradePrice(), [GetHighestTradePriceMessages()]) } def stream_stream_scenarios(self): return { (_STOCK_GROUP_NAME, 'GetLastTradePriceMultiple'): (GetLastTradePriceMultiple(), [GetLastTradePriceMultipleMessages()]), } STOCK_TEST_SERVICE = StockTestService() grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/interfaces/face/test_cases.py000066400000000000000000000061521310511640000311260ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Tools for creating tests of implementations of the Face layer.""" # unittest is referenced from specification in this module. import unittest # pylint: disable=unused-import # test_interfaces is referenced from specification in this module. from tests.unit.framework.interfaces.face import _blocking_invocation_inline_service from tests.unit.framework.interfaces.face import _future_invocation_asynchronous_event_service from tests.unit.framework.interfaces.face import _invocation from tests.unit.framework.interfaces.face import test_interfaces # pylint: disable=unused-import _TEST_CASE_SUPERCLASSES = ( _blocking_invocation_inline_service.TestCase, _future_invocation_asynchronous_event_service.TestCase,) def test_cases(implementation): """Creates unittest.TestCase classes for a given Face layer implementation. Args: implementation: A test_interfaces.Implementation specifying creation and destruction of a given Face layer implementation. Returns: A sequence of subclasses of unittest.TestCase defining tests of the specified Face layer implementation. """ test_case_classes = [] for invoker_constructor in _invocation.invoker_constructors(): for super_class in _TEST_CASE_SUPERCLASSES: test_case_classes.append( type(invoker_constructor.name() + super_class.NAME, ( super_class,), { 'implementation': implementation, 'invoker_constructor': invoker_constructor, '__module__': implementation.__module__, })) return test_case_classes grpc-1.3.2/src/python/grpcio_tests/tests/unit/framework/interfaces/face/test_interfaces.py000066400000000000000000000166041310511640000321560ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Interfaces used in tests of implementations of the Face layer.""" import abc import six from grpc.framework.common import cardinality # pylint: disable=unused-import from grpc.framework.interfaces.face import face # pylint: disable=unused-import class Method(six.with_metaclass(abc.ABCMeta)): """Specifies a method to be used in tests.""" @abc.abstractmethod def group(self): """Identify the group of the method. Returns: The group of the method. """ raise NotImplementedError() @abc.abstractmethod def name(self): """Identify the name of the method. Returns: The name of the method. """ raise NotImplementedError() @abc.abstractmethod def cardinality(self): """Identify the cardinality of the method. Returns: A cardinality.Cardinality value describing the streaming semantics of the method. """ raise NotImplementedError() @abc.abstractmethod def request_class(self): """Identify the class used for the method's request objects. Returns: The class object of the class to which the method's request objects belong. """ raise NotImplementedError() @abc.abstractmethod def response_class(self): """Identify the class used for the method's response objects. Returns: The class object of the class to which the method's response objects belong. """ raise NotImplementedError() @abc.abstractmethod def serialize_request(self, request): """Serialize the given request object. Args: request: A request object appropriate for this method. """ raise NotImplementedError() @abc.abstractmethod def deserialize_request(self, serialized_request): """Synthesize a request object from a given bytestring. Args: serialized_request: A bytestring deserializable into a request object appropriate for this method. """ raise NotImplementedError() @abc.abstractmethod def serialize_response(self, response): """Serialize the given response object. Args: response: A response object appropriate for this method. """ raise NotImplementedError() @abc.abstractmethod def deserialize_response(self, serialized_response): """Synthesize a response object from a given bytestring. Args: serialized_response: A bytestring deserializable into a response object appropriate for this method. """ raise NotImplementedError() class Implementation(six.with_metaclass(abc.ABCMeta)): """Specifies an implementation of the Face layer.""" @abc.abstractmethod def instantiate(self, methods, method_implementations, multi_method_implementation): """Instantiates the Face layer implementation to be used in a test. Args: methods: A sequence of Method objects describing the methods available to be called during the test. method_implementations: A dictionary from group-name pair to face.MethodImplementation object specifying implementation of a method. multi_method_implementation: A face.MultiMethodImplementation or None. Returns: A sequence of length three the first element of which is a face.GenericStub, the second element of which is dictionary from groups to face.DynamicStubs affording invocation of the group's methods, and the third element of which is an arbitrary memo object to be kept and passed to destantiate at the conclusion of the test. The returned stubs must be backed by the provided implementations. """ raise NotImplementedError() @abc.abstractmethod def destantiate(self, memo): """Destroys the Face layer implementation under test. Args: memo: The object from the third position of the return value of a call to instantiate. """ raise NotImplementedError() @abc.abstractmethod def invocation_metadata(self): """Provides the metadata to be used when invoking a test RPC. Returns: An object to use as the supplied-at-invocation-time metadata in a test RPC. """ raise NotImplementedError() @abc.abstractmethod def initial_metadata(self): """Provides the metadata for use as a test RPC's first servicer metadata. Returns: An object to use as the from-the-servicer-before-responses metadata in a test RPC. """ raise NotImplementedError() @abc.abstractmethod def terminal_metadata(self): """Provides the metadata for use as a test RPC's second servicer metadata. Returns: An object to use as the from-the-servicer-after-all-responses metadata in a test RPC. """ raise NotImplementedError() @abc.abstractmethod def code(self): """Provides the value for use as a test RPC's code. Returns: An object to use as the from-the-servicer code in a test RPC. """ raise NotImplementedError() @abc.abstractmethod def details(self): """Provides the value for use as a test RPC's details. Returns: An object to use as the from-the-servicer details in a test RPC. """ raise NotImplementedError() @abc.abstractmethod def metadata_transmitted(self, original_metadata, transmitted_metadata): """Identifies whether or not metadata was properly transmitted. Args: original_metadata: A metadata value passed to the Face interface implementation under test. transmitted_metadata: The same metadata value after having been transmitted via an RPC performed by the Face interface implementation under test. Returns: Whether or not the metadata was properly transmitted by the Face interface implementation under test. """ raise NotImplementedError() grpc-1.3.2/src/python/grpcio_tests/tests/unit/resources.py000066400000000000000000000042521310511640000237640ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Constants and functions for data used in interoperability testing.""" import os import pkg_resources _ROOT_CERTIFICATES_RESOURCE_PATH = 'credentials/ca.pem' _PRIVATE_KEY_RESOURCE_PATH = 'credentials/server1.key' _CERTIFICATE_CHAIN_RESOURCE_PATH = 'credentials/server1.pem' def test_root_certificates(): return pkg_resources.resource_string(__name__, _ROOT_CERTIFICATES_RESOURCE_PATH) def private_key(): return pkg_resources.resource_string(__name__, _PRIVATE_KEY_RESOURCE_PATH) def certificate_chain(): return pkg_resources.resource_string(__name__, _CERTIFICATE_CHAIN_RESOURCE_PATH) grpc-1.3.2/src/python/grpcio_tests/tests/unit/test_common.py000066400000000000000000000100031310511640000242700ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Common code used throughout tests of gRPC.""" import collections import grpc import six INVOCATION_INITIAL_METADATA = (('0', 'abc'), ('1', 'def'), ('2', 'ghi'),) SERVICE_INITIAL_METADATA = (('3', 'jkl'), ('4', 'mno'), ('5', 'pqr'),) SERVICE_TERMINAL_METADATA = (('6', 'stu'), ('7', 'vwx'), ('8', 'yza'),) DETAILS = 'test details' def metadata_transmitted(original_metadata, transmitted_metadata): """Judges whether or not metadata was acceptably transmitted. gRPC is allowed to insert key-value pairs into the metadata values given by applications and to reorder key-value pairs with different keys but it is not allowed to alter existing key-value pairs or to reorder key-value pairs with the same key. Args: original_metadata: A metadata value used in a test of gRPC. An iterable over iterables of length 2. transmitted_metadata: A metadata value corresponding to original_metadata after having been transmitted via gRPC. An iterable over iterables of length 2. Returns: A boolean indicating whether transmitted_metadata accurately reflects original_metadata after having been transmitted via gRPC. """ original = collections.defaultdict(list) for key, value in original_metadata: original[key].append(value) transmitted = collections.defaultdict(list) for key, value in transmitted_metadata: transmitted[key].append(value) for key, values in six.iteritems(original): transmitted_values = transmitted[key] transmitted_iterator = iter(transmitted_values) try: for value in values: while True: transmitted_value = next(transmitted_iterator) if value == transmitted_value: break except StopIteration: return False else: return True def test_secure_channel(target, channel_credentials, server_host_override): """Creates an insecure Channel to a remote host. Args: host: The name of the remote host to which to connect. port: The port of the remote host to which to connect. channel_credentials: The implementations.ChannelCredentials with which to connect. server_host_override: The target name used for SSL host name checking. Returns: An implementations.Channel to the remote host through which RPCs may be conducted. """ channel = grpc.secure_channel(target, channel_credentials, ( ('grpc.ssl_target_name_override', server_host_override,),)) return channel grpc-1.3.2/src/ruby/000077500000000000000000000000001310511640000142075ustar00rootroot00000000000000grpc-1.3.2/src/ruby/.gitignore000077500000000000000000000001751310511640000162050ustar00rootroot00000000000000/.bundle/ /.yardoc /Gemfile.lock /_yardoc/ /coverage/ /doc/ /pkg/ /spec/reports/ /tmp/ *.bundle *.so *.o *.a mkmf.log vendor grpc-1.3.2/src/ruby/.rubocop.yml000066400000000000000000000005751310511640000164700ustar00rootroot00000000000000# This is the configuration used to check the rubocop source code. inherit_from: .rubocop_todo.yml AllCops: Exclude: - 'bin/apis/**/*' - 'bin/math_pb.rb' - 'bin/math_services_pb.rb' - 'pb/grpc/health/v1/*' - 'pb/test/**/*' - 'end2end/lib/*' Metrics/CyclomaticComplexity: Max: 9 Metrics/PerceivedComplexity: Max: 9 Metrics/ClassLength: Max: 250 grpc-1.3.2/src/ruby/.rubocop_todo.yml000066400000000000000000000021341310511640000175060ustar00rootroot00000000000000# This configuration was generated by `rubocop --auto-gen-config` # on 2015-05-22 13:23:34 -0700 using RuboCop version 0.30.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. # Offense count: 30 Metrics/AbcSize: Max: 38 # Offense count: 3 # Configuration parameters: CountComments. Metrics/ClassLength: Max: 200 # Offense count: 35 # Configuration parameters: CountComments. Metrics/MethodLength: Max: 36 # Offense count: 7 # Configuration parameters: CountKeywordArgs. Metrics/ParameterLists: Max: 8 # Offense count: 9 # Configuration parameters: AllowedVariables. Style/GlobalVars: Enabled: false # Offense count: 1 # Configuration parameters: EnforcedStyle, MinBodyLength, SupportedStyles. Style/Next: Enabled: false # Offense count: 2 # Configuration parameters: Methods. Style/SingleLineBlockParams: Enabled: false # Offense count: 1 Style/StructInheritance: Enabled: false grpc-1.3.2/src/ruby/CHANGELOG.md000066400000000000000000000005341310511640000160220ustar00rootroot00000000000000## 0.6.1 (2015-04-14) ### Changes * Begins this ChangeLog ([@tbetbetbe][]) * Updates to version 0.4 of googleauth. ([@tbetbetbe][]) * Switch the extension to use the call API. ([@tbetbetbe][]) * Refactor the C extension to avoid identifiers used by ruby ([@yugui][]) [@tbetbetbe]: https://github.com/tbetbetbe [@yugui]: https://github.com/yugui grpc-1.3.2/src/ruby/README.md000066400000000000000000000040611310511640000154670ustar00rootroot00000000000000[![Gem](https://img.shields.io/gem/v/grpc.svg)](https://rubygems.org/gems/grpc/) gRPC Ruby ========= A Ruby implementation of gRPC. PREREQUISITES ------------- - Ruby 2.x. The gRPC API uses keyword args. INSTALLATION --------------- **Linux and Mac OS X:** ```sh gem install grpc ``` BUILD FROM SOURCE --------------------- - Clone this repository - Install Ruby 2.x. Consider doing this with [RVM](http://rvm.io), it's a nice way of controlling the exact ruby version that's used. ```sh $ command curl -sSL https://rvm.io/mpapis.asc | gpg --import - $ \curl -sSL https://get.rvm.io | bash -s stable --ruby=ruby-2 $ $ # follow the instructions to ensure that your're using the latest stable version of Ruby $ # and that the rvm command is installed ``` - Make sure your run `source $HOME/.rvm/scripts/rvm` as instructed to complete the set up of RVM - Install [bundler](http://bundler.io/) ``` $ gem install bundler ``` - Finally, build and install the gRPC gem locally. ```sh $ # from this directory $ bundle install # creates the ruby bundle, including building the grpc extension $ rake # runs the unit tests, see rake -T for other options ``` DOCUMENTATION ------------- - rubydoc for the gRPC gem is available online at [rubydoc][]. - the gRPC Ruby reference documentation is available online at [grpc.io][] CONTENTS -------- Directory structure is the layout for [ruby extensions][] - ext: the gRPC ruby extension - lib: the entrypoint gRPC ruby library to be used in a 'require' statement - spec: Rspec unittests - bin: example gRPC clients and servers, e.g, ```ruby stub = Math::Math::Stub.new('my.test.math.server.com:8080', :this_channel_is_insecure) req = Math::DivArgs.new(dividend: 7, divisor: 3) GRPC.logger.info("div(7/3): req=#{req.inspect}") resp = stub.div(req) GRPC.logger.info("Answer: #{resp.inspect}") ``` [ruby extensions]:http://guides.rubygems.org/gems-with-extensions/ [rubydoc]: http://www.rubydoc.info/gems/grpc [grpc.io]: http://www.grpc.io/docs/quickstart/ruby.html [Debian jessie-backports]:http://backports.debian.org/Instructions/ grpc-1.3.2/src/ruby/bin/000077500000000000000000000000001310511640000147575ustar00rootroot00000000000000grpc-1.3.2/src/ruby/bin/apis/000077500000000000000000000000001310511640000157135ustar00rootroot00000000000000grpc-1.3.2/src/ruby/bin/apis/google/000077500000000000000000000000001310511640000171675ustar00rootroot00000000000000grpc-1.3.2/src/ruby/bin/apis/google/protobuf/000077500000000000000000000000001310511640000210275ustar00rootroot00000000000000grpc-1.3.2/src/ruby/bin/apis/google/protobuf/empty.rb000066400000000000000000000035621310511640000225200ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/protobuf/empty.proto require 'google/protobuf' Google::Protobuf::DescriptorPool.generated_pool.build do add_message "google.protobuf.Empty" do end end module Google module Protobuf Empty = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Empty").msgclass end end grpc-1.3.2/src/ruby/bin/apis/pubsub_demo.rb000077500000000000000000000213201310511640000205450ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # pubsub_demo demos accesses the Google PubSub API via its gRPC interface # # $ GOOGLE_APPLICATION_CREDENTIALS= \ # path/to/pubsub_demo.rb \ # [--action= ] # # There are options related to the chosen action, see #parse_args below. # - the possible actions are given by the method names of NamedAction class # - the default action is list_some_topics this_dir = File.expand_path(File.dirname(__FILE__)) lib_dir = File.join(File.dirname(File.dirname(this_dir)), 'lib') $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir) require 'optparse' require 'grpc' require 'googleauth' require 'google/protobuf' require 'google/protobuf/empty' require 'tech/pubsub/proto/pubsub' require 'tech/pubsub/proto/pubsub_services' # creates a SSL Credentials from the production certificates. def ssl_creds GRPC::Core::ChannelCredentials.new() end # Builds the metadata authentication update proc. def auth_proc(opts) auth_creds = Google::Auth.get_application_default return auth_creds.updater_proc end # Creates a stub for accessing the publisher service. def publisher_stub(opts) address = "#{opts.host}:#{opts.port}" stub_clz = Tech::Pubsub::PublisherService::Stub # shorter GRPC.logger.info("... access PublisherService at #{address}") call_creds = GRPC::Core::CallCredentials.new(auth_proc(opts)) combined_creds = ssl_creds.compose(call_creds) stub_clz.new(address, creds: combined_creds, GRPC::Core::Channel::SSL_TARGET => opts.host) end # Creates a stub for accessing the subscriber service. def subscriber_stub(opts) address = "#{opts.host}:#{opts.port}" stub_clz = Tech::Pubsub::SubscriberService::Stub # shorter GRPC.logger.info("... access SubscriberService at #{address}") call_creds = GRPC::Core::CallCredentials.new(auth_proc(opts)) combined_creds = ssl_creds.compose(call_creds) stub_clz.new(address, creds: combined_creds, GRPC::Core::Channel::SSL_TARGET => opts.host) end # defines methods corresponding to each interop test case. class NamedActions include Tech::Pubsub # Initializes NamedActions # # @param pub [Stub] a stub for accessing the publisher service # @param sub [Stub] a stub for accessing the publisher service # @param args [Args] provides access to the command line def initialize(pub, sub, args) @pub = pub @sub = sub @args = args end # Removes the test topic if it exists def remove_topic name = test_topic_name p "... removing Topic #{name}" @pub.delete_topic(DeleteTopicRequest.new(topic: name)) p "removed Topic: #{name} OK" rescue GRPC::BadStatus => e p "Could not delete a topics: rpc failed with '#{e}'" end # Creates a test topic def create_topic name = test_topic_name p "... creating Topic #{name}" resp = @pub.create_topic(Topic.new(name: name)) p "created Topic: #{resp.name} OK" rescue GRPC::BadStatus => e p "Could not create a topics: rpc failed with '#{e}'" end # Lists topics in the project def list_some_topics p 'Listing topics' p '-------------_' list_project_topics.topic.each { |t| p t.name } rescue GRPC::BadStatus => e p "Could not list topics: rpc failed with '#{e}'" end # Checks if a topics exists in a project def check_exists name = test_topic_name p "... checking for topic #{name}" exists = topic_exists?(name) p "#{name} is a topic" if exists p "#{name} is not a topic" unless exists rescue GRPC::BadStatus => e p "Could not check for a topics: rpc failed with '#{e}'" end # Publishes some messages def random_pub_sub topic_name, sub_name = test_topic_name, test_sub_name create_topic_if_needed(topic_name) @sub.create_subscription(Subscription.new(name: sub_name, topic: topic_name)) msg_count = rand(10..30) msg_count.times do |x| msg = PubsubMessage.new(data: "message #{x}") @pub.publish(PublishRequest.new(topic: topic_name, message: msg)) end p "Sent #{msg_count} messages to #{topic_name}, checking for them now." batch = @sub.pull_batch(PullBatchRequest.new(subscription: sub_name, max_events: msg_count)) ack_ids = batch.pull_responses.map { |x| x.ack_id } p "Got #{ack_ids.size} messages; acknowledging them.." @sub.acknowledge(AcknowledgeRequest.new(subscription: sub_name, ack_id: ack_ids)) p "Test messages were acknowledged OK, deleting the subscription" del_req = DeleteSubscriptionRequest.new(subscription: sub_name) @sub.delete_subscription(del_req) rescue GRPC::BadStatus => e p "Could not do random pub sub: rpc failed with '#{e}'" end private # test_topic_name is the topic name to use in this test. def test_topic_name unless @args.topic_name.nil? return "/topics/#{@args.project_id}/#{@args.topic_name}" end now_text = Time.now.utc.strftime('%Y%m%d%H%M%S%L') "/topics/#{@args.project_id}/#{ENV['USER']}-#{now_text}" end # test_sub_name is the subscription name to use in this test. def test_sub_name unless @args.sub_name.nil? return "/subscriptions/#{@args.project_id}/#{@args.sub_name}" end now_text = Time.now.utc.strftime('%Y%m%d%H%M%S%L') "/subscriptions/#{@args.project_id}/#{ENV['USER']}-#{now_text}" end # determines if the topic name exists def topic_exists?(name) topics = list_project_topics.topic.map { |t| t.name } topics.include?(name) end def create_topic_if_needed(name) return if topic_exists?(name) @pub.create_topic(Topic.new(name: name)) end def list_project_topics q = "cloud.googleapis.com/project in (/projects/#{@args.project_id})" @pub.list_topics(ListTopicsRequest.new(query: q)) end end # Args is used to hold the command line info. Args = Struct.new(:host, :port, :action, :project_id, :topic_name, :sub_name) # validates the the command line options, returning them as an Arg. def parse_args args = Args.new('pubsub-staging.googleapis.com', 443, 'list_some_topics', 'stoked-keyword-656') OptionParser.new do |opts| opts.on('--server_host SERVER_HOST', 'server hostname') do |v| args.host = v end opts.on('--server_port SERVER_PORT', 'server port') do |v| args.port = v end # instance_methods(false) gives only the methods defined in that class. scenes = NamedActions.instance_methods(false).map { |t| t.to_s } scene_list = scenes.join(',') opts.on("--action CODE", scenes, {}, 'pick a demo action', " (#{scene_list})") do |v| args.action = v end # Set the remaining values. %w(project_id topic_name sub_name).each do |o| opts.on("--#{o} VALUE", "#{o}") do |v| args[o] = v end end end.parse! _check_args(args) end def _check_args(args) %w(host port action).each do |a| if args[a].nil? raise OptionParser::MissingArgument.new("please specify --#{a}") end end args end def main args = parse_args pub, sub = publisher_stub(args), subscriber_stub(args) NamedActions.new(pub, sub, args).method(args.action).call end main grpc-1.3.2/src/ruby/bin/apis/tech/000077500000000000000000000000001310511640000166365ustar00rootroot00000000000000grpc-1.3.2/src/ruby/bin/apis/tech/pubsub/000077500000000000000000000000001310511640000201365ustar00rootroot00000000000000grpc-1.3.2/src/ruby/bin/apis/tech/pubsub/proto/000077500000000000000000000000001310511640000213015ustar00rootroot00000000000000grpc-1.3.2/src/ruby/bin/apis/tech/pubsub/proto/pubsub.rb000066400000000000000000000207771310511640000231430ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Generated by the protocol buffer compiler. DO NOT EDIT! # source: tech/pubsub/proto/pubsub.proto require 'google/protobuf' require 'google/protobuf/empty' Google::Protobuf::DescriptorPool.generated_pool.build do add_message "tech.pubsub.Topic" do optional :name, :string, 1 end add_message "tech.pubsub.PubsubMessage" do optional :data, :string, 1 optional :message_id, :string, 3 end add_message "tech.pubsub.GetTopicRequest" do optional :topic, :string, 1 end add_message "tech.pubsub.PublishRequest" do optional :topic, :string, 1 optional :message, :message, 2, "tech.pubsub.PubsubMessage" end add_message "tech.pubsub.PublishBatchRequest" do optional :topic, :string, 1 repeated :messages, :message, 2, "tech.pubsub.PubsubMessage" end add_message "tech.pubsub.PublishBatchResponse" do repeated :message_ids, :string, 1 end add_message "tech.pubsub.ListTopicsRequest" do optional :query, :string, 1 optional :max_results, :int32, 2 optional :page_token, :string, 3 end add_message "tech.pubsub.ListTopicsResponse" do repeated :topic, :message, 1, "tech.pubsub.Topic" optional :next_page_token, :string, 2 end add_message "tech.pubsub.DeleteTopicRequest" do optional :topic, :string, 1 end add_message "tech.pubsub.Subscription" do optional :name, :string, 1 optional :topic, :string, 2 optional :query, :string, 3 optional :truncation_policy, :message, 4, "tech.pubsub.Subscription.TruncationPolicy" optional :push_config, :message, 5, "tech.pubsub.PushConfig" optional :ack_deadline_seconds, :int32, 6 optional :garbage_collect_seconds, :int64, 7 end add_message "tech.pubsub.Subscription.TruncationPolicy" do optional :max_bytes, :int64, 1 optional :max_age_seconds, :int64, 2 end add_message "tech.pubsub.PushConfig" do optional :push_endpoint, :string, 1 end add_message "tech.pubsub.PubsubEvent" do optional :subscription, :string, 1 optional :message, :message, 2, "tech.pubsub.PubsubMessage" optional :truncated, :bool, 3 optional :deleted, :bool, 4 end add_message "tech.pubsub.GetSubscriptionRequest" do optional :subscription, :string, 1 end add_message "tech.pubsub.ListSubscriptionsRequest" do optional :query, :string, 1 optional :max_results, :int32, 3 optional :page_token, :string, 4 end add_message "tech.pubsub.ListSubscriptionsResponse" do repeated :subscription, :message, 1, "tech.pubsub.Subscription" optional :next_page_token, :string, 2 end add_message "tech.pubsub.TruncateSubscriptionRequest" do optional :subscription, :string, 1 end add_message "tech.pubsub.DeleteSubscriptionRequest" do optional :subscription, :string, 1 end add_message "tech.pubsub.ModifyPushConfigRequest" do optional :subscription, :string, 1 optional :push_config, :message, 2, "tech.pubsub.PushConfig" end add_message "tech.pubsub.PullRequest" do optional :subscription, :string, 1 optional :return_immediately, :bool, 2 end add_message "tech.pubsub.PullResponse" do optional :ack_id, :string, 1 optional :pubsub_event, :message, 2, "tech.pubsub.PubsubEvent" end add_message "tech.pubsub.PullBatchRequest" do optional :subscription, :string, 1 optional :return_immediately, :bool, 2 optional :max_events, :int32, 3 end add_message "tech.pubsub.PullBatchResponse" do repeated :pull_responses, :message, 2, "tech.pubsub.PullResponse" end add_message "tech.pubsub.ModifyAckDeadlineRequest" do optional :subscription, :string, 1 optional :ack_id, :string, 2 optional :ack_deadline_seconds, :int32, 3 end add_message "tech.pubsub.AcknowledgeRequest" do optional :subscription, :string, 1 repeated :ack_id, :string, 2 end add_message "tech.pubsub.NackRequest" do optional :subscription, :string, 1 repeated :ack_id, :string, 2 end end module Tech module Pubsub Topic = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.Topic").msgclass PubsubMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.PubsubMessage").msgclass GetTopicRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.GetTopicRequest").msgclass PublishRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.PublishRequest").msgclass PublishBatchRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.PublishBatchRequest").msgclass PublishBatchResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.PublishBatchResponse").msgclass ListTopicsRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.ListTopicsRequest").msgclass ListTopicsResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.ListTopicsResponse").msgclass DeleteTopicRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.DeleteTopicRequest").msgclass Subscription = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.Subscription").msgclass Subscription::TruncationPolicy = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.Subscription.TruncationPolicy").msgclass PushConfig = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.PushConfig").msgclass PubsubEvent = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.PubsubEvent").msgclass GetSubscriptionRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.GetSubscriptionRequest").msgclass ListSubscriptionsRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.ListSubscriptionsRequest").msgclass ListSubscriptionsResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.ListSubscriptionsResponse").msgclass TruncateSubscriptionRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.TruncateSubscriptionRequest").msgclass DeleteSubscriptionRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.DeleteSubscriptionRequest").msgclass ModifyPushConfigRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.ModifyPushConfigRequest").msgclass PullRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.PullRequest").msgclass PullResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.PullResponse").msgclass PullBatchRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.PullBatchRequest").msgclass PullBatchResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.PullBatchResponse").msgclass ModifyAckDeadlineRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.ModifyAckDeadlineRequest").msgclass AcknowledgeRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.AcknowledgeRequest").msgclass NackRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("tech.pubsub.NackRequest").msgclass end end grpc-1.3.2/src/ruby/bin/apis/tech/pubsub/proto/pubsub_services.rb000066400000000000000000000076531310511640000250440ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Generated by the protocol buffer compiler. DO NOT EDIT! # Source: tech/pubsub/proto/pubsub.proto for package 'tech.pubsub' require 'grpc' require 'google/protobuf/empty' require 'tech/pubsub/proto/pubsub' module Tech module Pubsub module PublisherService # TODO: add proto service documentation here class Service include GRPC::GenericService self.marshal_class_method = :encode self.unmarshal_class_method = :decode self.service_name = 'tech.pubsub.PublisherService' rpc :CreateTopic, Topic, Topic rpc :Publish, PublishRequest, Google::Protobuf::Empty rpc :PublishBatch, PublishBatchRequest, PublishBatchResponse rpc :GetTopic, GetTopicRequest, Topic rpc :ListTopics, ListTopicsRequest, ListTopicsResponse rpc :DeleteTopic, DeleteTopicRequest, Google::Protobuf::Empty end Stub = Service.rpc_stub_class end module SubscriberService # TODO: add proto service documentation here class Service include GRPC::GenericService self.marshal_class_method = :encode self.unmarshal_class_method = :decode self.service_name = 'tech.pubsub.SubscriberService' rpc :CreateSubscription, Subscription, Subscription rpc :GetSubscription, GetSubscriptionRequest, Subscription rpc :ListSubscriptions, ListSubscriptionsRequest, ListSubscriptionsResponse rpc :DeleteSubscription, DeleteSubscriptionRequest, Google::Protobuf::Empty rpc :TruncateSubscription, TruncateSubscriptionRequest, Google::Protobuf::Empty rpc :ModifyPushConfig, ModifyPushConfigRequest, Google::Protobuf::Empty rpc :Pull, PullRequest, PullResponse rpc :PullBatch, PullBatchRequest, PullBatchResponse rpc :ModifyAckDeadline, ModifyAckDeadlineRequest, Google::Protobuf::Empty rpc :Acknowledge, AcknowledgeRequest, Google::Protobuf::Empty rpc :Nack, NackRequest, Google::Protobuf::Empty end Stub = Service.rpc_stub_class end module PushEndpointService # TODO: add proto service documentation here class Service include GRPC::GenericService self.marshal_class_method = :encode self.unmarshal_class_method = :decode self.service_name = 'tech.pubsub.PushEndpointService' rpc :HandlePubsubEvent, PubsubEvent, Google::Protobuf::Empty end Stub = Service.rpc_stub_class end end end grpc-1.3.2/src/ruby/bin/math_client.rb000077500000000000000000000117351310511640000176050ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Sample app that accesses a Calc service running on a Ruby gRPC server and # helps validate RpcServer as a gRPC server using proto2 serialization. # # Usage: $ path/to/math_client.rb this_dir = File.expand_path(File.dirname(__FILE__)) lib_dir = File.join(File.dirname(this_dir), 'lib') $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir) require 'grpc' require 'math_services_pb' require 'optparse' include GRPC::Core::TimeConsts def do_div(stub) GRPC.logger.info('request_response') GRPC.logger.info('----------------') req = Math::DivArgs.new(dividend: 7, divisor: 3) GRPC.logger.info("div(7/3): req=#{req.inspect}") resp = stub.div(req, timeout: INFINITE_FUTURE) GRPC.logger.info("Answer: #{resp.inspect}") GRPC.logger.info('----------------') end def do_sum(stub) # to make client streaming requests, pass an enumerable of the inputs GRPC.logger.info('client_streamer') GRPC.logger.info('---------------') reqs = [1, 2, 3, 4, 5].map { |x| Math::Num.new(num: x) } GRPC.logger.info("sum(1, 2, 3, 4, 5): reqs=#{reqs.inspect}") resp = stub.sum(reqs) # reqs.is_a?(Enumerable) GRPC.logger.info("Answer: #{resp.inspect}") GRPC.logger.info('---------------') end def do_fib(stub) GRPC.logger.info('server_streamer') GRPC.logger.info('----------------') req = Math::FibArgs.new(limit: 11) GRPC.logger.info("fib(11): req=#{req.inspect}") resp = stub.fib(req, timeout: INFINITE_FUTURE) resp.each do |r| GRPC.logger.info("Answer: #{r.inspect}") end GRPC.logger.info('----------------') end def do_div_many(stub) GRPC.logger.info('bidi_streamer') GRPC.logger.info('-------------') reqs = [] reqs << Math::DivArgs.new(dividend: 7, divisor: 3) reqs << Math::DivArgs.new(dividend: 5, divisor: 2) reqs << Math::DivArgs.new(dividend: 7, divisor: 2) GRPC.logger.info("div(7/3), div(5/2), div(7/2): reqs=#{reqs.inspect}") resp = stub.div_many(reqs, timeout: INFINITE_FUTURE) resp.each do |r| GRPC.logger.info("Answer: #{r.inspect}") end GRPC.logger.info('----------------') end def load_test_certs this_dir = File.expand_path(File.dirname(__FILE__)) data_dir = File.join(File.dirname(this_dir), 'spec/testdata') files = ['ca.pem', 'server1.key', 'server1.pem'] files.map { |f| File.open(File.join(data_dir, f)).read } end def test_creds certs = load_test_certs GRPC::Core::ChannelCredentials.new(certs[0]) end def main options = { 'host' => 'localhost:7071', 'secure' => false } OptionParser.new do |opts| opts.banner = 'Usage: [--host :] [--secure|-s]' opts.on('--host HOST', ':') do |v| options['host'] = v end opts.on('-s', '--secure', 'access using test creds') do |v| options['secure'] = v end end.parse! # The Math::Math:: module occurs because the service has the same name as its # package. That practice should be avoided by defining real services. p options if options['secure'] stub_opts = { :creds => test_creds, GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.fr' } p stub_opts p options['host'] stub = Math::Math::Stub.new(options['host'], **stub_opts) GRPC.logger.info("... connecting securely on #{options['host']}") else stub = Math::Math::Stub.new(options['host']) GRPC.logger.info("... connecting insecurely on #{options['host']}") end do_div(stub) do_sum(stub) do_fib(stub) do_div_many(stub) end main grpc-1.3.2/src/ruby/bin/math_pb.rb000066400000000000000000000020411310511640000167130ustar00rootroot00000000000000# Generated by the protocol buffer compiler. DO NOT EDIT! # source: math.proto require 'google/protobuf' Google::Protobuf::DescriptorPool.generated_pool.build do add_message "math.DivArgs" do optional :dividend, :int64, 1 optional :divisor, :int64, 2 end add_message "math.DivReply" do optional :quotient, :int64, 1 optional :remainder, :int64, 2 end add_message "math.FibArgs" do optional :limit, :int64, 1 end add_message "math.Num" do optional :num, :int64, 1 end add_message "math.FibReply" do optional :count, :int64, 1 end end module Math DivArgs = Google::Protobuf::DescriptorPool.generated_pool.lookup("math.DivArgs").msgclass DivReply = Google::Protobuf::DescriptorPool.generated_pool.lookup("math.DivReply").msgclass FibArgs = Google::Protobuf::DescriptorPool.generated_pool.lookup("math.FibArgs").msgclass Num = Google::Protobuf::DescriptorPool.generated_pool.lookup("math.Num").msgclass FibReply = Google::Protobuf::DescriptorPool.generated_pool.lookup("math.FibReply").msgclass end grpc-1.3.2/src/ruby/bin/math_server.rb000077500000000000000000000144651310511640000176400ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Sample gRPC Ruby server that implements the Math::Calc service and helps # validate GRPC::RpcServer as GRPC implementation using proto2 serialization. # # Usage: $ path/to/math_server.rb this_dir = File.expand_path(File.dirname(__FILE__)) lib_dir = File.join(File.dirname(this_dir), 'lib') $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir) require 'forwardable' require 'grpc' require 'logger' require 'math_services_pb' require 'optparse' # RubyLogger defines a logger for gRPC based on the standard ruby logger. module RubyLogger def logger LOGGER end LOGGER = Logger.new(STDOUT) end # GRPC is the general RPC module module GRPC # Inject the noop #logger if no module-level logger method has been injected. extend RubyLogger end # Holds state for a fibonacci series class Fibber def initialize(limit) fail "bad limit: got #{limit}, want limit > 0" if limit < 1 @limit = limit end def generator return enum_for(:generator) unless block_given? idx, current, previous = 0, 1, 1 until idx == @limit if idx.zero? || idx == 1 yield Math::Num.new(num: 1) idx += 1 next end tmp = current current = previous + current previous = tmp yield Math::Num.new(num: current) idx += 1 end end end # A EnumeratorQueue wraps a Queue to yield the items added to it. class EnumeratorQueue extend Forwardable def_delegators :@q, :push def initialize(sentinel) @q = Queue.new @sentinel = sentinel end def each_item return enum_for(:each_item) unless block_given? loop do r = @q.pop break if r.equal?(@sentinel) fail r if r.is_a? Exception yield r end end end # The Math::Math:: module occurs because the service has the same name as its # package. That practice should be avoided by defining real services. class Calculator < Math::Math::Service def div(div_args, _call) if div_args.divisor.zero? # To send non-OK status handlers raise a StatusError with the code and # and detail they want sent as a Status. fail GRPC::StatusError.new(GRPC::Status::INVALID_ARGUMENT, 'divisor cannot be 0') end Math::DivReply.new(quotient: div_args.dividend / div_args.divisor, remainder: div_args.dividend % div_args.divisor) end def sum(call) # the requests are accesible as the Enumerator call#each_request nums = call.each_remote_read.collect(&:num) sum = nums.inject { |s, x| s + x } Math::Num.new(num: sum) end def fib(fib_args, _call) if fib_args.limit < 1 fail StatusError.new(Status::INVALID_ARGUMENT, 'limit must be >= 0') end # return an Enumerator of Nums Fibber.new(fib_args.limit).generator # just return the generator, GRPC::GenericServer sends each actual response end def div_many(requests) # requests is an lazy Enumerator of the requests sent by the client. q = EnumeratorQueue.new(self) t = Thread.new do begin requests.each do |req| GRPC.logger.info("read #{req.inspect}") resp = Math::DivReply.new(quotient: req.dividend / req.divisor, remainder: req.dividend % req.divisor) q.push(resp) Thread.pass # let the internal Bidi threads run end GRPC.logger.info('finished reads') q.push(self) rescue StandardError => e q.push(e) # share the exception with the enumerator raise e end end t.priority = -2 # hint that the div_many thread should not be favoured q.each_item end end def load_test_certs this_dir = File.expand_path(File.dirname(__FILE__)) data_dir = File.join(File.dirname(this_dir), 'spec/testdata') files = ['ca.pem', 'server1.key', 'server1.pem'] files.map { |f| File.open(File.join(data_dir, f)).read } end def test_server_creds certs = load_test_certs GRPC::Core::ServerCredentials.new( nil, [{ private_key: certs[1], cert_chain: certs[2] }], false) end def main options = { 'host' => 'localhost:7071', 'secure' => false } OptionParser.new do |opts| opts.banner = 'Usage: [--host :] [--secure|-s]' opts.on('--host HOST', ':') do |v| options['host'] = v end opts.on('-s', '--secure', 'access using test creds') do |v| options['secure'] = v end end.parse! s = GRPC::RpcServer.new if options['secure'] s.add_http2_port(options['host'], test_server_creds) GRPC.logger.info("... running securely on #{options['host']}") else s.add_http2_port(options['host'], :this_port_is_insecure) GRPC.logger.info("... running insecurely on #{options['host']}") end s.handle(Calculator) s.run_till_terminated end main grpc-1.3.2/src/ruby/bin/math_services_pb.rb000066400000000000000000000054511310511640000206260ustar00rootroot00000000000000# Generated by the protocol buffer compiler. DO NOT EDIT! # Source: math.proto for package 'math' # Original file comments: # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # require 'grpc' require 'math_pb' module Math module Math class Service include GRPC::GenericService self.marshal_class_method = :encode self.unmarshal_class_method = :decode self.service_name = 'math.Math' # Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient # and remainder. rpc :Div, DivArgs, DivReply # DivMany accepts an arbitrary number of division args from the client stream # and sends back the results in the reply stream. The stream continues until # the client closes its end; the server does the same after sending all the # replies. The stream ends immediately if either end aborts. rpc :DivMany, stream(DivArgs), stream(DivReply) # Fib generates numbers in the Fibonacci sequence. If FibArgs.limit > 0, Fib # generates up to limit numbers; otherwise it continues until the call is # canceled. Unlike Fib above, Fib has no final FibReply. rpc :Fib, FibArgs, stream(Num) # Sum sums a stream of numbers, returning the final result once the stream # is closed. rpc :Sum, stream(Num), Num end Stub = Service.rpc_stub_class end end grpc-1.3.2/src/ruby/bin/noproto_client.rb000077500000000000000000000066661310511640000203630ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Sample app that helps validate RpcServer without protobuf serialization. # # Usage: $ ruby -S path/to/noproto_client.rb this_dir = File.expand_path(File.dirname(__FILE__)) lib_dir = File.join(File.dirname(this_dir), 'lib') $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) require 'grpc' require 'optparse' # a simple non-protobuf message class. class NoProtoMsg def self.marshal(_o) '' end def self.unmarshal(_o) NoProtoMsg.new end end # service the uses the non-protobuf message class. class NoProtoService include GRPC::GenericService rpc :AnRPC, NoProtoMsg, NoProtoMsg end NoProtoStub = NoProtoService.rpc_stub_class def load_test_certs this_dir = File.expand_path(File.dirname(__FILE__)) data_dir = File.join(File.dirname(this_dir), 'spec/testdata') files = ['ca.pem', 'server1.key', 'server1.pem'] files.map { |f| File.open(File.join(data_dir, f)).read } end def test_creds certs = load_test_certs GRPC::Core::ChannelCredentials.new(certs[0]) end def main options = { 'host' => 'localhost:7071', 'secure' => false } OptionParser.new do |opts| opts.banner = 'Usage: [--host :] [--secure|-s]' opts.on('--host HOST', ':') do |v| options['host'] = v end opts.on('-s', '--secure', 'access using test creds') do |v| options['secure'] = v end end.parse! if options['secure'] stub_opts = { :creds => test_creds, GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.fr' } p stub_opts p options['host'] stub = NoProtoStub.new(options['host'], **stub_opts) GRPC.logger.info("... connecting securely on #{options['host']}") else stub = NoProtoStub.new(options['host']) GRPC.logger.info("... connecting insecurely on #{options['host']}") end GRPC.logger.info('sending a NoProto rpc') resp = stub.an_rpc(NoProtoMsg.new) GRPC.logger.info("got a response: #{resp}") end main grpc-1.3.2/src/ruby/bin/noproto_server.rb000077500000000000000000000067421310511640000204060ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Sample app that helps validate RpcServer without protobuf serialization. # # Usage: $ path/to/noproto_server.rb this_dir = File.expand_path(File.dirname(__FILE__)) lib_dir = File.join(File.dirname(this_dir), 'lib') $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) require 'grpc' require 'optparse' # a simple non-protobuf message class. class NoProtoMsg def self.marshal(_o) '' end def self.unmarshal(_o) NoProtoMsg.new end end # service the uses the non-protobuf message class. class NoProtoService include GRPC::GenericService rpc :AnRPC, NoProtoMsg, NoProtoMsg end # an implementation of the non-protobuf service. class NoProto < NoProtoService def initialize(_default_var = 'ignored') end def an_rpc(req, _call) GRPC.logger.info('echo service received a request') req end end def load_test_certs this_dir = File.expand_path(File.dirname(__FILE__)) data_dir = File.join(File.dirname(this_dir), 'spec/testdata') files = ['ca.pem', 'server1.key', 'server1.pem'] files.map { |f| File.open(File.join(data_dir, f)).read } end def test_server_creds certs = load_test_certs GRPC::Core::ServerCredentials.new( nil, [{ private_key: certs[1], cert_chain: certs[2] }], false) end def main options = { 'host' => 'localhost:9090', 'secure' => false } OptionParser.new do |opts| opts.banner = 'Usage: [--host :] [--secure|-s]' opts.on('--host HOST', ':') do |v| options['host'] = v end opts.on('-s', '--secure', 'access using test creds') do |v| options['secure'] = v end end.parse! s = GRPC::RpcServer.new if options['secure'] s.add_http2_port(options['host'], test_server_creds) GRPC.logger.info("... running securely on #{options['host']}") else s.add_http2_port(options['host'], :this_port_is_insecure) GRPC.logger.info("... running insecurely on #{options['host']}") end s.handle(NoProto) s.run_till_terminated end main grpc-1.3.2/src/ruby/end2end/000077500000000000000000000000001310511640000155265ustar00rootroot00000000000000grpc-1.3.2/src/ruby/end2end/README.md000066400000000000000000000015631310511640000170120ustar00rootroot00000000000000This directory contains some grpc-ruby end to end tests. Each test here involves two files: a "driver" and a "client". For example, the "channel_closing" test involves channel_closing_driver.rb and channel_closing_client.rb. Typically, the "driver" will start up a simple "echo" server, and then spawn a client. It gives the client the address of the "echo" server as well as an address to listen on for control rpcs. Depending on the test, the client usually starts up a "ClientControl" grpc server for the driver to interact with (the driver can tell the client process to do strange things at different times, depending on the test). So far these tests are mostly useful for testing process-shutdown related situations, since the client's run in separate processes. These tests are invoked through the "tools/run_tests/run_tests.py" script (the Rakefile doesn't start these). grpc-1.3.2/src/ruby/end2end/channel_closing_client.rb000077500000000000000000000054471310511640000225540ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. require_relative './end2end_common' # Calls '#close' on a Channel when "shutdown" called. This tries to # trigger a hang or crash bug by closing a channel actively being watched class ChannelClosingClientController < ClientControl::ClientController::Service def initialize(ch) @ch = ch end def shutdown(_, _) @ch.close ClientControl::Void.new end end def main client_control_port = '' server_port = '' OptionParser.new do |opts| opts.on('--client_control_port=P', String) do |p| client_control_port = p end opts.on('--server_port=P', String) do |p| server_port = p end end.parse! ch = GRPC::Core::Channel.new("localhost:#{server_port}", {}, :this_channel_is_insecure) srv = GRPC::RpcServer.new thd = Thread.new do srv.add_http2_port("0.0.0.0:#{client_control_port}", :this_port_is_insecure) srv.handle(ChannelClosingClientController.new(ch)) srv.run end # this should break out with an exception once the channel is closed loop do begin state = ch.connectivity_state(true) ch.watch_connectivity_state(state, Time.now + 360) rescue RuntimeError => e STDERR.puts "(expected) error occurred: #{e.inspect}" break end end srv.stop thd.join end main grpc-1.3.2/src/ruby/end2end/channel_closing_driver.rb000077500000000000000000000046461310511640000225710ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # make sure that the client doesn't hang when channel is closed # explictly while it's used require_relative './end2end_common' def main STDERR.puts 'start server' server_runner = ServerRunner.new(EchoServerImpl) server_port = server_runner.run sleep 1 STDERR.puts 'start client' control_stub, client_pid = start_client('channel_closing_client.rb', server_port) sleep 3 begin Timeout.timeout(10) do control_stub.shutdown(ClientControl::Void.new) Process.wait(client_pid) end rescue Timeout::Error STDERR.puts "timeout wait for client pid #{client_pid}" Process.kill('SIGKILL', client_pid) Process.wait(client_pid) STDERR.puts 'killed client child' raise 'Timed out waiting for client process. It likely hangs when a ' \ 'channel is closed while connectivity is watched' end server_runner.stop end main grpc-1.3.2/src/ruby/end2end/channel_state_client.rb000077500000000000000000000040351310511640000222260ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. require_relative './end2end_common' def main server_port = '' OptionParser.new do |opts| opts.on('--client_control_port=P', String) do STDERR.puts 'client_control_port ignored' end opts.on('--server_port=P', String) do |p| server_port = p end end.parse! ch = GRPC::Core::Channel.new("localhost:#{server_port}", {}, :this_channel_is_insecure) loop do state = ch.connectivity_state ch.watch_connectivity_state(state, Time.now + 360) end end main grpc-1.3.2/src/ruby/end2end/channel_state_driver.rb000077500000000000000000000044371310511640000222510ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # make sure that the client doesn't hang when process ended abruptly require_relative './end2end_common' def main STDERR.puts 'start server' server_runner = ServerRunner.new(EchoServerImpl) server_port = server_runner.run sleep 1 STDERR.puts 'start client' _, client_pid = start_client('channel_state_client.rb', server_port) sleep 3 Process.kill('SIGTERM', client_pid) begin Timeout.timeout(10) { Process.wait(client_pid) } rescue Timeout::Error STDERR.puts "timeout wait for client pid #{client_pid}" Process.kill('SIGKILL', client_pid) Process.wait(client_pid) STDERR.puts 'killed client child' raise 'Timed out waiting for client process. ' \ 'It likely hangs when ended abruptly' end server_runner.stop end main grpc-1.3.2/src/ruby/end2end/end2end_common.rb000077500000000000000000000074171310511640000207560ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. this_dir = File.expand_path(File.dirname(__FILE__)) protos_lib_dir = File.join(this_dir, 'lib') grpc_lib_dir = File.join(File.dirname(this_dir), 'lib') $LOAD_PATH.unshift(grpc_lib_dir) unless $LOAD_PATH.include?(grpc_lib_dir) $LOAD_PATH.unshift(protos_lib_dir) unless $LOAD_PATH.include?(protos_lib_dir) $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir) require 'grpc' require 'echo_services_pb' require 'client_control_services_pb' require 'socket' require 'optparse' require 'thread' require 'timeout' require 'English' # see https://github.com/bbatsov/rubocop/issues/1747 # GreeterServer is simple server that implements the Helloworld Greeter server. class EchoServerImpl < Echo::EchoServer::Service # say_hello implements the SayHello rpc method. def echo(echo_req, _) Echo::EchoReply.new(response: echo_req.request) end end # ServerRunner starts an "echo server" that test clients can make calls to class ServerRunner def initialize(service_impl) @service_impl = service_impl end def run @srv = GRPC::RpcServer.new port = @srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure) @srv.handle(@service_impl) @thd = Thread.new do @srv.run end @srv.wait_till_running port end def stop @srv.stop @thd.join fail 'server not stopped' unless @srv.stopped? end end def start_client(client_main, server_port) this_dir = File.expand_path(File.dirname(__FILE__)) tmp_server = TCPServer.new(0) client_control_port = tmp_server.local_address.ip_port tmp_server.close client_path = File.join(this_dir, client_main) client_pid = Process.spawn(RbConfig.ruby, client_path, "--client_control_port=#{client_control_port}", "--server_port=#{server_port}") sleep 1 control_stub = ClientControl::ClientController::Stub.new( "localhost:#{client_control_port}", :this_channel_is_insecure) [control_stub, client_pid] end def cleanup(control_stub, client_pid, server_runner) control_stub.shutdown(ClientControl::Void.new) Process.wait(client_pid) client_exit_code = $CHILD_STATUS if client_exit_code != 0 fail "term sig test failure: client exit code: #{client_exit_code}" end server_runner.stop end grpc-1.3.2/src/ruby/end2end/forking_client_client.rb000077500000000000000000000050231310511640000224110ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Prompted by and minimal repro of https://github.com/grpc/grpc/issues/10658 require_relative './end2end_common' def main server_port = '' OptionParser.new do |opts| opts.on('--client_control_port=P', String) do STDERR.puts 'client control port not used' end opts.on('--server_port=P', String) do |p| server_port = p end end.parse! p = fork do stub = Echo::EchoServer::Stub.new("localhost:#{server_port}", :this_channel_is_insecure) stub.echo(Echo::EchoRequest.new(request: 'hello')) end begin Timeout.timeout(10) do Process.wait(p) end rescue Timeout::Error STDERR.puts "timeout waiting for forked process #{p}" Process.kill('SIGKILL', p) Process.wait(p) raise 'Timed out waiting for client process. ' \ 'It likely hangs when using gRPC after loading it and then forking' end client_exit_code = $CHILD_STATUS fail "forked process failed #{client_exit_code}" if client_exit_code != 0 end main grpc-1.3.2/src/ruby/end2end/forking_client_driver.rb000077500000000000000000000050071310511640000224300ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. require_relative './end2end_common' def main STDERR.puts 'start server' server_runner = ServerRunner.new(EchoServerImpl) server_port = server_runner.run # TODO(apolcyn) Can we get rid of this sleep? # Without it, an immediate call to the just started EchoServer # fails with UNAVAILABLE sleep 1 STDERR.puts 'start client' _, client_pid = start_client('forking_client_client.rb', server_port) begin Timeout.timeout(10) do Process.wait(client_pid) end rescue Timeout::Error STDERR.puts "timeout wait for client pid #{client_pid}" Process.kill('SIGKILL', client_pid) Process.wait(client_pid) STDERR.puts 'killed client child' raise 'Timed out waiting for client process. ' \ 'It likely hangs when requiring grpc, then forking, then using grpc ' end client_exit_code = $CHILD_STATUS if client_exit_code != 0 fail "forking client client failed, exit code #{client_exit_code}" end server_runner.stop end main grpc-1.3.2/src/ruby/end2end/gen_protos.sh000066400000000000000000000031631310511640000202440ustar00rootroot00000000000000#!/bin/bash # Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. grpc_tools_ruby_protoc -I protos --ruby_out=lib --grpc_out=lib protos/echo.proto protos/client_control.proto grpc-1.3.2/src/ruby/end2end/grpc_class_init_client.rb000077500000000000000000000050011310511640000225530ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # For GRPC::Core classes, which use the grpc c-core, object init # is interesting because it's related to overall library init. require_relative './end2end_common' def main grpc_class = '' OptionParser.new do |opts| opts.on('--grpc_class=P', String) do |p| grpc_class = p end end.parse! test_proc = nil case grpc_class when 'channel' test_proc = proc do GRPC::Core::Channel.new('dummy_host', nil, :this_channel_is_insecure) end when 'server' test_proc = proc do GRPC::Core::Server.new({}) end when 'channel_credentials' test_proc = proc do GRPC::Core::ChannelCredentials.new end when 'call_credentials' test_proc = proc do GRPC::Core::CallCredentials.new(proc { |noop| noop }) end when 'compression_options' test_proc = proc do GRPC::Core::CompressionOptions.new end else fail "bad --grpc_class=#{grpc_class} param" end th = Thread.new { test_proc.call } test_proc.call th.join end main grpc-1.3.2/src/ruby/end2end/grpc_class_init_driver.rb000077500000000000000000000052711310511640000226010ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. require_relative './end2end_common' def main native_grpc_classes = %w( channel server channel_credentials call_credentials compression_options ) native_grpc_classes.each do |grpc_class| STDERR.puts 'start client' this_dir = File.expand_path(File.dirname(__FILE__)) client_path = File.join(this_dir, 'grpc_class_init_client.rb') client_pid = Process.spawn(RbConfig.ruby, client_path, "--grpc_class=#{grpc_class}") begin Timeout.timeout(10) do Process.wait(client_pid) end rescue Timeout::Error STDERR.puts "timeout waiting for client pid #{client_pid}" Process.kill('SIGKILL', client_pid) Process.wait(client_pid) STDERR.puts 'killed client child' raise 'Timed out waiting for client process. ' \ 'It likely hangs when the first constructed gRPC object has ' \ "type: #{grpc_class}" end client_exit_code = $CHILD_STATUS fail "client failed, exit code #{client_exit_code}" if client_exit_code != 0 end end main grpc-1.3.2/src/ruby/end2end/killed_client_thread_client.rb000077500000000000000000000043661310511640000235560ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Attempt to reproduce # https://github.com/GoogleCloudPlatform/google-cloud-ruby/issues/1327 require_relative './end2end_common' def main server_port = '' OptionParser.new do |opts| opts.on('--client_control_port=P', String) do STDERR.puts 'client control port not used' end opts.on('--server_port=P', String) do |p| server_port = p end end.parse! thd = Thread.new do stub = Echo::EchoServer::Stub.new("localhost:#{server_port}", :this_channel_is_insecure) stub.echo(Echo::EchoRequest.new(request: 'hello')) fail 'the clients rpc in this test shouldnt complete. ' \ 'expecting SIGINT to happen in the middle of the call' end thd.join end main grpc-1.3.2/src/ruby/end2end/killed_client_thread_driver.rb000077500000000000000000000072271310511640000235720ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. require_relative './end2end_common' # Service that sleeps for a long time upon receiving an 'echo request' # Also, this notifies @call_started_cv once it has received a request. class SleepingEchoServerImpl < Echo::EchoServer::Service def initialize(call_started, call_started_mu, call_started_cv) @call_started = call_started @call_started_mu = call_started_mu @call_started_cv = call_started_cv end def echo(echo_req, _) @call_started_mu.synchronize do @call_started.set_true @call_started_cv.signal end sleep 1000 Echo::EchoReply.new(response: echo_req.request) end end # Mutable boolean class BoolHolder attr_reader :val def init @val = false end def set_true @val = true end end def main STDERR.puts 'start server' call_started = BoolHolder.new call_started_mu = Mutex.new call_started_cv = ConditionVariable.new service_impl = SleepingEchoServerImpl.new(call_started, call_started_mu, call_started_cv) server_runner = ServerRunner.new(service_impl) server_port = server_runner.run STDERR.puts 'start client' _, client_pid = start_client('killed_client_thread_client.rb', server_port) call_started_mu.synchronize do call_started_cv.wait(call_started_mu) until call_started.val end # SIGINT the child process now that it's # in the middle of an RPC (happening on a non-main thread) Process.kill('SIGINT', client_pid) STDERR.puts 'sent shutdown' begin Timeout.timeout(10) do Process.wait(client_pid) end rescue Timeout::Error STDERR.puts "timeout wait for client pid #{client_pid}" Process.kill('SIGKILL', client_pid) Process.wait(client_pid) STDERR.puts 'killed client child' raise 'Timed out waiting for client process. ' \ 'It likely hangs when killed while in the middle of an rpc' end client_exit_code = $CHILD_STATUS if client_exit_code.termsig != 2 # SIGINT fail 'expected client exit from SIGINT ' \ "but got child status: #{client_exit_code}" end server_runner.stop end main grpc-1.3.2/src/ruby/end2end/lib/000077500000000000000000000000001310511640000162745ustar00rootroot00000000000000grpc-1.3.2/src/ruby/end2end/lib/client_control_pb.rb000066400000000000000000000010551310511640000223210ustar00rootroot00000000000000# Generated by the protocol buffer compiler. DO NOT EDIT! # source: client_control.proto require 'google/protobuf' Google::Protobuf::DescriptorPool.generated_pool.build do add_message "client_control.DoEchoRpcRequest" do optional :request, :string, 1 end add_message "client_control.Void" do end end module ClientControl DoEchoRpcRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("client_control.DoEchoRpcRequest").msgclass Void = Google::Protobuf::DescriptorPool.generated_pool.lookup("client_control.Void").msgclass end grpc-1.3.2/src/ruby/end2end/lib/client_control_services_pb.rb000066400000000000000000000040631310511640000242260ustar00rootroot00000000000000# Generated by the protocol buffer compiler. DO NOT EDIT! # Source: client_control.proto for package 'client_control' # Original file comments: # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # require 'grpc' require 'client_control_pb' module ClientControl module ClientController class Service include GRPC::GenericService self.marshal_class_method = :encode self.unmarshal_class_method = :decode self.service_name = 'client_control.ClientController' rpc :DoEchoRpc, DoEchoRpcRequest, Void rpc :Shutdown, Void, Void end Stub = Service.rpc_stub_class end end grpc-1.3.2/src/ruby/end2end/lib/echo_pb.rb000066400000000000000000000010251310511640000202160ustar00rootroot00000000000000# Generated by the protocol buffer compiler. DO NOT EDIT! # source: echo.proto require 'google/protobuf' Google::Protobuf::DescriptorPool.generated_pool.build do add_message "echo.EchoRequest" do optional :request, :string, 1 end add_message "echo.EchoReply" do optional :response, :string, 1 end end module Echo EchoRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("echo.EchoRequest").msgclass EchoReply = Google::Protobuf::DescriptorPool.generated_pool.lookup("echo.EchoReply").msgclass end grpc-1.3.2/src/ruby/end2end/lib/echo_services_pb.rb000066400000000000000000000037211310511640000221260ustar00rootroot00000000000000# Generated by the protocol buffer compiler. DO NOT EDIT! # Source: echo.proto for package 'echo' # Original file comments: # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # require 'grpc' require 'echo_pb' module Echo module EchoServer class Service include GRPC::GenericService self.marshal_class_method = :encode self.unmarshal_class_method = :decode self.service_name = 'echo.EchoServer' rpc :Echo, EchoRequest, EchoReply end Stub = Service.rpc_stub_class end end grpc-1.3.2/src/ruby/end2end/protos/000077500000000000000000000000001310511640000170545ustar00rootroot00000000000000grpc-1.3.2/src/ruby/end2end/protos/client_control.proto000066400000000000000000000033771310511640000231710ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package client_control; service ClientController { rpc DoEchoRpc (DoEchoRpcRequest) returns (Void) {} rpc Shutdown(Void) returns (Void) {} } message DoEchoRpcRequest { string request = 1; } message Void{} grpc-1.3.2/src/ruby/end2end/protos/echo.proto000066400000000000000000000035001310511640000210550ustar00rootroot00000000000000// Copyright 2015, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package echo; service EchoServer { rpc Echo (EchoRequest) returns (EchoReply) {} } // The request message containing the user's name. message EchoRequest { string request = 1; } // The response message containing the greetings message EchoReply { string response = 1; } grpc-1.3.2/src/ruby/end2end/sig_handling_client.rb000077500000000000000000000057521310511640000220530ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. require_relative './end2end_common' # Test client. Sends RPC's as normal but process also has signal handlers class SigHandlingClientController < ClientControl::ClientController::Service def initialize(srv, stub) @srv = srv @stub = stub end def do_echo_rpc(req, _) response = @stub.echo(Echo::EchoRequest.new(request: req.request)) fail 'bad response' unless response.response == req.request ClientControl::Void.new end def shutdown(_, _) Thread.new do # TODO(apolcyn) There is a race between stopping the # server and the "shutdown" rpc completing, # See if stop method on server can end active RPC cleanly, to # avoid this sleep. sleep 3 @srv.stop end ClientControl::Void.new end end def main client_control_port = '' server_port = '' OptionParser.new do |opts| opts.on('--client_control_port=P', String) do |p| client_control_port = p end opts.on('--server_port=P', String) do |p| server_port = p end end.parse! Signal.trap('TERM') do STDERR.puts 'SIGTERM received' end Signal.trap('INT') do STDERR.puts 'SIGINT received' end srv = GRPC::RpcServer.new srv.add_http2_port("0.0.0.0:#{client_control_port}", :this_port_is_insecure) stub = Echo::EchoServer::Stub.new("localhost:#{server_port}", :this_channel_is_insecure) srv.handle(SigHandlingClientController.new(srv, stub)) srv.run end main grpc-1.3.2/src/ruby/end2end/sig_handling_driver.rb000077500000000000000000000042451310511640000220640ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # smoke test for a grpc-using app that receives and # handles process-ending signals require_relative './end2end_common' def main STDERR.puts 'start server' server_runner = ServerRunner.new(EchoServerImpl) server_port = server_runner.run sleep 1 STDERR.puts 'start client' control_stub, client_pid = start_client('sig_handling_client.rb', server_port) sleep 1 count = 0 while count < 5 control_stub.do_echo_rpc( ClientControl::DoEchoRpcRequest.new(request: 'hello')) Process.kill('SIGTERM', client_pid) Process.kill('SIGINT', client_pid) count += 1 end cleanup(control_stub, client_pid, server_runner) end main grpc-1.3.2/src/ruby/end2end/sig_int_during_channel_watch_client.rb000077500000000000000000000054001310511640000252750ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. require_relative './end2end_common' # Start polling the channel state in both the main thread # and a child thread. Try to get the driver to send process-ending # interrupt while both a child thread and the main thread are in the # middle of a blocking connectivity_state call. def main server_port = '' OptionParser.new do |opts| opts.on('--client_control_port=P', String) do STDERR.puts 'client_control_port not used' end opts.on('--server_port=P', String) do |p| server_port = p end end.parse! thd = Thread.new do child_thread_channel = GRPC::Core::Channel.new("localhost:#{server_port}", {}, :this_channel_is_insecure) loop do state = child_thread_channel.connectivity_state(false) child_thread_channel.watch_connectivity_state(state, Time.now + 360) end end main_channel = GRPC::Core::Channel.new("localhost:#{server_port}", {}, :this_channel_is_insecure) loop do state = main_channel.connectivity_state(false) main_channel.watch_connectivity_state(state, Time.now + 360) end thd.join end main grpc-1.3.2/src/ruby/end2end/sig_int_during_channel_watch_driver.rb000077500000000000000000000047541310511640000253250ustar00rootroot00000000000000#!/usr/bin/env ruby # Copyright 2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # abruptly end a process that has active calls to # Channel.watch_connectivity_state require_relative './end2end_common' def main STDERR.puts 'start server' server_runner = ServerRunner.new(EchoServerImpl) server_port = server_runner.run sleep 1 STDERR.puts 'start client' _, client_pid = start_client('sig_int_during_channel_watch_client.rb', server_port) # give time for the client to get into the middle # of a channel state watch call sleep 1 Process.kill('SIGINT', client_pid) begin Timeout.timeout(10) do Process.wait(client_pid) end rescue Timeout::Error STDERR.puts "timeout wait for client pid #{client_pid}" Process.kill('SIGKILL', client_pid) Process.wait(client_pid) STDERR.puts 'killed client child' raise 'Timed out waiting for client process. It likely hangs when a ' \ 'SIGINT is sent while there is an active connectivity_state call' end server_runner.stop end main grpc-1.3.2/src/ruby/ext/000077500000000000000000000000001310511640000150075ustar00rootroot00000000000000grpc-1.3.2/src/ruby/ext/grpc/000077500000000000000000000000001310511640000157425ustar00rootroot00000000000000grpc-1.3.2/src/ruby/ext/grpc/extconf.rb000066400000000000000000000100261310511640000177340ustar00rootroot00000000000000# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. require 'etc' require 'mkmf' LIBDIR = RbConfig::CONFIG['libdir'] INCLUDEDIR = RbConfig::CONFIG['includedir'] HEADER_DIRS = [ # Search /opt/local (Mac source install) '/opt/local/include', # Search /usr/local (Source install) '/usr/local/include', # Check the ruby install locations INCLUDEDIR ] LIB_DIRS = [ # Search /opt/local (Mac source install) '/opt/local/lib', # Search /usr/local (Source install) '/usr/local/lib', # Check the ruby install locations LIBDIR ] windows = RUBY_PLATFORM =~ /mingw|mswin/ grpc_root = File.expand_path(File.join(File.dirname(__FILE__), '../../../..')) grpc_config = ENV['GRPC_CONFIG'] || 'opt' ENV['MACOSX_DEPLOYMENT_TARGET'] = '10.7' ENV['AR'] = RbConfig::CONFIG['AR'] + ' rcs' ENV['CC'] = RbConfig::CONFIG['CC'] ENV['LD'] = ENV['CC'] ENV['AR'] = 'libtool -o' if RUBY_PLATFORM =~ /darwin/ ENV['EMBED_OPENSSL'] = 'true' ENV['EMBED_ZLIB'] = 'true' ENV['EMBED_CARES'] = 'true' ENV['ARCH_FLAGS'] = RbConfig::CONFIG['ARCH_FLAG'] ENV['ARCH_FLAGS'] = '-arch i386 -arch x86_64' if RUBY_PLATFORM =~ /darwin/ ENV['CFLAGS'] = '-DGPR_BACKWARDS_COMPATIBILITY_MODE' output_dir = File.expand_path(RbConfig::CONFIG['topdir']) grpc_lib_dir = File.join(output_dir, 'libs', grpc_config) ENV['BUILDDIR'] = output_dir unless windows puts 'Building internal gRPC into ' + grpc_lib_dir nproc = 4 nproc = Etc.nprocessors * 2 if Etc.respond_to? :nprocessors system("make -j#{nproc} -C #{grpc_root} #{grpc_lib_dir}/libgrpc.a CONFIG=#{grpc_config}") exit 1 unless $? == 0 end $CFLAGS << ' -I' + File.join(grpc_root, 'include') $LDFLAGS << ' ' + File.join(grpc_lib_dir, 'libgrpc.a') unless windows if grpc_config == 'gcov' $CFLAGS << ' -O0 -fprofile-arcs -ftest-coverage' $LDFLAGS << ' -fprofile-arcs -ftest-coverage -rdynamic' end if grpc_config == 'dbg' $CFLAGS << ' -O0' end $LDFLAGS << ' -Wl,-wrap,memcpy' if RUBY_PLATFORM =~ /linux/ $LDFLAGS << ' -static' if windows $CFLAGS << ' -std=c99 ' $CFLAGS << ' -Wall ' $CFLAGS << ' -Wextra ' $CFLAGS << ' -pedantic ' $CFLAGS << ' -Wno-format ' output = File.join('grpc', 'grpc_c') puts 'Generating Makefile for ' + output create_makefile(output) strip_tool = RbConfig::CONFIG['STRIP'] strip_tool = 'strip -x' if RUBY_PLATFORM =~ /darwin/ if grpc_config == 'opt' File.open('Makefile.new', 'w') do |o| o.puts 'hijack: all strip' o.puts File.foreach('Makefile') do |i| o.puts i end o.puts o.puts 'strip:' o.puts "\t$(ECHO) Stripping $(DLLIB)" o.puts "\t$(Q) #{strip_tool} $(DLLIB)" end File.rename('Makefile.new', 'Makefile') end grpc-1.3.2/src/ruby/ext/grpc/rb_byte_buffer.c000066400000000000000000000056321310511640000210730ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "rb_grpc_imports.generated.h" #include "rb_byte_buffer.h" #include #include #include #include "rb_grpc.h" grpc_byte_buffer* grpc_rb_s_to_byte_buffer(char *string, size_t length) { grpc_slice slice = grpc_slice_from_copied_buffer(string, length); grpc_byte_buffer *buffer = grpc_raw_byte_buffer_create(&slice, 1); grpc_slice_unref(slice); return buffer; } VALUE grpc_rb_byte_buffer_to_s(grpc_byte_buffer *buffer) { VALUE rb_string; grpc_byte_buffer_reader reader; grpc_slice next; if (buffer == NULL) { return Qnil; } rb_string = rb_str_buf_new(grpc_byte_buffer_length(buffer)); if (!grpc_byte_buffer_reader_init(&reader, buffer)) { rb_raise(rb_eRuntimeError, "Error initializing byte buffer reader."); return Qnil; } while (grpc_byte_buffer_reader_next(&reader, &next) != 0) { rb_str_cat(rb_string, (const char *) GRPC_SLICE_START_PTR(next), GRPC_SLICE_LENGTH(next)); grpc_slice_unref(next); } grpc_byte_buffer_reader_destroy(&reader); return rb_string; } VALUE grpc_rb_slice_to_ruby_string(grpc_slice slice) { if (GRPC_SLICE_START_PTR(slice) == NULL) { rb_raise(rb_eRuntimeError, "attempt to convert uninitialized grpc_slice to ruby string"); } return rb_str_new((char*)GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice)); } grpc-1.3.2/src/ruby/ext/grpc/rb_byte_buffer.h000066400000000000000000000040141310511640000210710ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_RB_BYTE_BUFFER_H_ #define GRPC_RB_BYTE_BUFFER_H_ #include #include /* Converts a char* with a length to a grpc_byte_buffer */ grpc_byte_buffer *grpc_rb_s_to_byte_buffer(char *string, size_t length); /* Converts a grpc_byte_buffer to a ruby string */ VALUE grpc_rb_byte_buffer_to_s(grpc_byte_buffer *buffer); /* Converts a grpc_slice to a ruby string */ VALUE grpc_rb_slice_to_ruby_string(grpc_slice slice); #endif /* GRPC_RB_BYTE_BUFFER_H_ */ grpc-1.3.2/src/ruby/ext/grpc/rb_call.c000066400000000000000000001074741310511640000175210ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "rb_grpc_imports.generated.h" #include "rb_call.h" #include #include #include #include "rb_byte_buffer.h" #include "rb_call_credentials.h" #include "rb_completion_queue.h" #include "rb_grpc.h" /* grpc_rb_cCall is the Call class whose instances proxy grpc_call. */ static VALUE grpc_rb_cCall; /* grpc_rb_eCallError is the ruby class of the exception thrown during call operations; */ VALUE grpc_rb_eCallError = Qnil; /* grpc_rb_eOutOfTime is the ruby class of the exception thrown to indicate a timeout. */ static VALUE grpc_rb_eOutOfTime = Qnil; /* grpc_rb_sBatchResult is struct class used to hold the results of a batch * call. */ static VALUE grpc_rb_sBatchResult; /* grpc_rb_cMdAry is the MetadataArray class whose instances proxy * grpc_metadata_array. */ static VALUE grpc_rb_cMdAry; /* id_credentials is the name of the hidden ivar that preserves the value * of the credentials added to the call */ static ID id_credentials; /* id_metadata is name of the attribute used to access the metadata hash * received by the call and subsequently saved on it. */ static ID id_metadata; /* id_trailing_metadata is the name of the attribute used to access the trailing * metadata hash received by the call and subsequently saved on it. */ static ID id_trailing_metadata; /* id_status is name of the attribute used to access the status object * received by the call and subsequently saved on it. */ static ID id_status; /* id_write_flag is name of the attribute used to access the write_flag * saved on the call. */ static ID id_write_flag; /* sym_* are the symbol for attributes of grpc_rb_sBatchResult. */ static VALUE sym_send_message; static VALUE sym_send_metadata; static VALUE sym_send_close; static VALUE sym_send_status; static VALUE sym_message; static VALUE sym_status; static VALUE sym_cancelled; typedef struct grpc_rb_call { grpc_call *wrapped; grpc_completion_queue *queue; } grpc_rb_call; static void destroy_call(grpc_rb_call *call) { /* Ensure that we only try to destroy the call once */ if (call->wrapped != NULL) { grpc_call_destroy(call->wrapped); call->wrapped = NULL; grpc_rb_completion_queue_destroy(call->queue); call->queue = NULL; } } /* Destroys a Call. */ static void grpc_rb_call_destroy(void *p) { if (p == NULL) { return; } destroy_call((grpc_rb_call*)p); } static size_t md_ary_datasize(const void *p) { const grpc_metadata_array *const ary = (grpc_metadata_array *)p; size_t i, datasize = sizeof(grpc_metadata_array); for (i = 0; i < ary->count; ++i) { const grpc_metadata *const md = &ary->metadata[i]; datasize += GRPC_SLICE_LENGTH(md->key); datasize += GRPC_SLICE_LENGTH(md->value); } datasize += ary->capacity * sizeof(grpc_metadata); return datasize; } static const rb_data_type_t grpc_rb_md_ary_data_type = { "grpc_metadata_array", {GRPC_RB_GC_NOT_MARKED, GRPC_RB_GC_DONT_FREE, md_ary_datasize, {NULL, NULL}}, NULL, NULL, #ifdef RUBY_TYPED_FREE_IMMEDIATELY /* it is unsafe to specify RUBY_TYPED_FREE_IMMEDIATELY because * grpc_rb_call_destroy * touches a hash object. * TODO(yugui) Directly use st_table and call the free function earlier? */ 0, #endif }; /* Describes grpc_call struct for RTypedData */ static const rb_data_type_t grpc_call_data_type = { "grpc_call", {GRPC_RB_GC_NOT_MARKED, grpc_rb_call_destroy, GRPC_RB_MEMSIZE_UNAVAILABLE, {NULL, NULL}}, NULL, NULL, #ifdef RUBY_TYPED_FREE_IMMEDIATELY RUBY_TYPED_FREE_IMMEDIATELY #endif }; /* Error code details is a hash containing text strings describing errors */ VALUE rb_error_code_details; /* Obtains the error detail string for given error code */ const char *grpc_call_error_detail_of(grpc_call_error err) { VALUE detail_ref = rb_hash_aref(rb_error_code_details, UINT2NUM(err)); const char *detail = "unknown error code!"; if (detail_ref != Qnil) { detail = StringValueCStr(detail_ref); } return detail; } /* Called by clients to cancel an RPC on the server. Can be called multiple times, from any thread. */ static VALUE grpc_rb_call_cancel(VALUE self) { grpc_rb_call *call = NULL; grpc_call_error err; if (RTYPEDDATA_DATA(self) == NULL) { //This call has been closed return Qnil; } TypedData_Get_Struct(self, grpc_rb_call, &grpc_call_data_type, call); err = grpc_call_cancel(call->wrapped, NULL); if (err != GRPC_CALL_OK) { rb_raise(grpc_rb_eCallError, "cancel failed: %s (code=%d)", grpc_call_error_detail_of(err), err); } return Qnil; } /* Releases the c-level resources associated with a call Once a call has been closed, no further requests can be processed. */ static VALUE grpc_rb_call_close(VALUE self) { grpc_rb_call *call = NULL; TypedData_Get_Struct(self, grpc_rb_call, &grpc_call_data_type, call); if(call != NULL) { destroy_call(call); RTYPEDDATA_DATA(self) = NULL; } return Qnil; } /* Called to obtain the peer that this call is connected to. */ static VALUE grpc_rb_call_get_peer(VALUE self) { VALUE res = Qnil; grpc_rb_call *call = NULL; char *peer = NULL; if (RTYPEDDATA_DATA(self) == NULL) { rb_raise(grpc_rb_eCallError, "Cannot get peer value on closed call"); return Qnil; } TypedData_Get_Struct(self, grpc_rb_call, &grpc_call_data_type, call); peer = grpc_call_get_peer(call->wrapped); res = rb_str_new2(peer); gpr_free(peer); return res; } /* Called to obtain the x509 cert of an authenticated peer. */ static VALUE grpc_rb_call_get_peer_cert(VALUE self) { grpc_rb_call *call = NULL; VALUE res = Qnil; grpc_auth_context *ctx = NULL; if (RTYPEDDATA_DATA(self) == NULL) { rb_raise(grpc_rb_eCallError, "Cannot get peer cert on closed call"); return Qnil; } TypedData_Get_Struct(self, grpc_rb_call, &grpc_call_data_type, call); ctx = grpc_call_auth_context(call->wrapped); if (!ctx || !grpc_auth_context_peer_is_authenticated(ctx)) { return Qnil; } { grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(ctx, GRPC_X509_PEM_CERT_PROPERTY_NAME); const grpc_auth_property *prop = grpc_auth_property_iterator_next(&it); if (prop == NULL) { return Qnil; } res = rb_str_new2(prop->value); } grpc_auth_context_release(ctx); return res; } /* call-seq: status = call.status Gets the status object saved the call. */ static VALUE grpc_rb_call_get_status(VALUE self) { return rb_ivar_get(self, id_status); } /* call-seq: call.status = status Saves a status object on the call. */ static VALUE grpc_rb_call_set_status(VALUE self, VALUE status) { if (!NIL_P(status) && rb_obj_class(status) != grpc_rb_sStatus) { rb_raise(rb_eTypeError, "bad status: got:<%s> want: ", rb_obj_classname(status)); return Qnil; } return rb_ivar_set(self, id_status, status); } /* call-seq: metadata = call.metadata Gets the metadata object saved the call. */ static VALUE grpc_rb_call_get_metadata(VALUE self) { return rb_ivar_get(self, id_metadata); } /* call-seq: call.metadata = metadata Saves the metadata hash on the call. */ static VALUE grpc_rb_call_set_metadata(VALUE self, VALUE metadata) { if (!NIL_P(metadata) && TYPE(metadata) != T_HASH) { rb_raise(rb_eTypeError, "bad metadata: got:<%s> want: ", rb_obj_classname(metadata)); return Qnil; } return rb_ivar_set(self, id_metadata, metadata); } /* call-seq: trailing_metadata = call.trailing_metadata Gets the trailing metadata object saved on the call */ static VALUE grpc_rb_call_get_trailing_metadata(VALUE self) { return rb_ivar_get(self, id_trailing_metadata); } /* call-seq: call.trailing_metadata = trailing_metadata Saves the trailing metadata hash on the call. */ static VALUE grpc_rb_call_set_trailing_metadata(VALUE self, VALUE metadata) { if (!NIL_P(metadata) && TYPE(metadata) != T_HASH) { rb_raise(rb_eTypeError, "bad metadata: got:<%s> want: ", rb_obj_classname(metadata)); return Qnil; } return rb_ivar_set(self, id_trailing_metadata, metadata); } /* call-seq: write_flag = call.write_flag Gets the write_flag value saved the call. */ static VALUE grpc_rb_call_get_write_flag(VALUE self) { return rb_ivar_get(self, id_write_flag); } /* call-seq: call.write_flag = write_flag Saves the write_flag on the call. */ static VALUE grpc_rb_call_set_write_flag(VALUE self, VALUE write_flag) { if (!NIL_P(write_flag) && TYPE(write_flag) != T_FIXNUM) { rb_raise(rb_eTypeError, "bad write_flag: got:<%s> want: ", rb_obj_classname(write_flag)); return Qnil; } return rb_ivar_set(self, id_write_flag, write_flag); } /* call-seq: call.set_credentials call_credentials Sets credentials on a call */ static VALUE grpc_rb_call_set_credentials(VALUE self, VALUE credentials) { grpc_rb_call *call = NULL; grpc_call_credentials *creds; grpc_call_error err; if (RTYPEDDATA_DATA(self) == NULL) { rb_raise(grpc_rb_eCallError, "Cannot set credentials of closed call"); return Qnil; } TypedData_Get_Struct(self, grpc_rb_call, &grpc_call_data_type, call); creds = grpc_rb_get_wrapped_call_credentials(credentials); err = grpc_call_set_credentials(call->wrapped, creds); if (err != GRPC_CALL_OK) { rb_raise(grpc_rb_eCallError, "grpc_call_set_credentials failed with %s (code=%d)", grpc_call_error_detail_of(err), err); } /* We need the credentials to be alive for as long as the call is alive, but we don't care about destruction order. */ rb_ivar_set(self, id_credentials, credentials); return Qnil; } /* grpc_rb_md_ary_fill_hash_cb is the hash iteration callback used to fill grpc_metadata_array. it's capacity should have been computed via a prior call to grpc_rb_md_ary_fill_hash_cb */ static int grpc_rb_md_ary_fill_hash_cb(VALUE key, VALUE val, VALUE md_ary_obj) { grpc_metadata_array *md_ary = NULL; long array_length; long i; grpc_slice key_slice; grpc_slice value_slice; char* tmp_str; if (TYPE(key) == T_SYMBOL) { key_slice = grpc_slice_from_static_string(rb_id2name(SYM2ID(key))); } else if (TYPE(key) == T_STRING) { key_slice = grpc_slice_from_copied_buffer(RSTRING_PTR(key), RSTRING_LEN(key)); } else { rb_raise(rb_eTypeError, "grpc_rb_md_ary_fill_hash_cb: bad type for key parameter"); } if (!grpc_header_key_is_legal(key_slice)) { tmp_str = grpc_slice_to_c_string(key_slice); rb_raise(rb_eArgError, "'%s' is an invalid header key, must match [a-z0-9-_.]+", tmp_str); return ST_STOP; } /* Construct a metadata object from key and value and add it */ TypedData_Get_Struct(md_ary_obj, grpc_metadata_array, &grpc_rb_md_ary_data_type, md_ary); if (TYPE(val) == T_ARRAY) { array_length = RARRAY_LEN(val); /* If the value is an array, add capacity for each value in the array */ for (i = 0; i < array_length; i++) { value_slice = grpc_slice_from_copied_buffer(RSTRING_PTR(rb_ary_entry(val, i)), RSTRING_LEN(rb_ary_entry(val, i))); if (!grpc_is_binary_header(key_slice) && !grpc_header_nonbin_value_is_legal(value_slice)) { // The value has invalid characters tmp_str = grpc_slice_to_c_string(value_slice); rb_raise(rb_eArgError, "Header value '%s' has invalid characters", tmp_str); return ST_STOP; } md_ary->metadata[md_ary->count].key = key_slice; md_ary->metadata[md_ary->count].value = value_slice; md_ary->count += 1; } } else if (TYPE(val) == T_STRING) { value_slice = grpc_slice_from_copied_buffer(RSTRING_PTR(val), RSTRING_LEN(val)); if (!grpc_is_binary_header(key_slice) && !grpc_header_nonbin_value_is_legal(value_slice)) { // The value has invalid characters tmp_str = grpc_slice_to_c_string(value_slice); rb_raise(rb_eArgError, "Header value '%s' has invalid characters", tmp_str); return ST_STOP; } md_ary->metadata[md_ary->count].key = key_slice; md_ary->metadata[md_ary->count].value = value_slice; md_ary->count += 1; } else { rb_raise(rb_eArgError, "Header values must be of type string or array"); return ST_STOP; } return ST_CONTINUE; } /* grpc_rb_md_ary_capacity_hash_cb is the hash iteration callback used to pre-compute the capacity a grpc_metadata_array. */ static int grpc_rb_md_ary_capacity_hash_cb(VALUE key, VALUE val, VALUE md_ary_obj) { grpc_metadata_array *md_ary = NULL; (void)key; /* Construct a metadata object from key and value and add it */ TypedData_Get_Struct(md_ary_obj, grpc_metadata_array, &grpc_rb_md_ary_data_type, md_ary); if (TYPE(val) == T_ARRAY) { /* If the value is an array, add capacity for each value in the array */ md_ary->capacity += RARRAY_LEN(val); } else { md_ary->capacity += 1; } return ST_CONTINUE; } /* grpc_rb_md_ary_convert converts a ruby metadata hash into a grpc_metadata_array. */ void grpc_rb_md_ary_convert(VALUE md_ary_hash, grpc_metadata_array *md_ary) { VALUE md_ary_obj = Qnil; if (md_ary_hash == Qnil) { return; /* Do nothing if the expected has value is nil */ } if (TYPE(md_ary_hash) != T_HASH) { rb_raise(rb_eTypeError, "md_ary_convert: got <%s>, want ", rb_obj_classname(md_ary_hash)); return; } /* Initialize the array, compute it's capacity, then fill it. */ grpc_metadata_array_init(md_ary); md_ary_obj = TypedData_Wrap_Struct(grpc_rb_cMdAry, &grpc_rb_md_ary_data_type, md_ary); rb_hash_foreach(md_ary_hash, grpc_rb_md_ary_capacity_hash_cb, md_ary_obj); md_ary->metadata = gpr_malloc(md_ary->capacity * sizeof(grpc_metadata)); rb_hash_foreach(md_ary_hash, grpc_rb_md_ary_fill_hash_cb, md_ary_obj); } /* Converts a metadata array to a hash. */ VALUE grpc_rb_md_ary_to_h(grpc_metadata_array *md_ary) { VALUE key = Qnil; VALUE new_ary = Qnil; VALUE value = Qnil; VALUE result = rb_hash_new(); size_t i; for (i = 0; i < md_ary->count; i++) { key = grpc_rb_slice_to_ruby_string(md_ary->metadata[i].key); value = rb_hash_aref(result, key); if (value == Qnil) { value = grpc_rb_slice_to_ruby_string(md_ary->metadata[i].value); rb_hash_aset(result, key, value); } else if (TYPE(value) == T_ARRAY) { /* Add the string to the returned array */ rb_ary_push(value, grpc_rb_slice_to_ruby_string(md_ary->metadata[i].value)); } else { /* Add the current value with this key and the new one to an array */ new_ary = rb_ary_new(); rb_ary_push(new_ary, value); rb_ary_push(new_ary, grpc_rb_slice_to_ruby_string(md_ary->metadata[i].value)); rb_hash_aset(result, key, new_ary); } } return result; } /* grpc_rb_call_check_op_keys_hash_cb is a hash iteration func that checks each key of an ops hash is valid. */ static int grpc_rb_call_check_op_keys_hash_cb(VALUE key, VALUE val, VALUE ops_ary) { (void)val; /* Update the capacity; the value is an array, add capacity for each value in * the array */ if (TYPE(key) != T_FIXNUM) { rb_raise(rb_eTypeError, "invalid operation : got <%s>, want ", rb_obj_classname(key)); return ST_STOP; } switch (NUM2INT(key)) { case GRPC_OP_SEND_INITIAL_METADATA: case GRPC_OP_SEND_MESSAGE: case GRPC_OP_SEND_CLOSE_FROM_CLIENT: case GRPC_OP_SEND_STATUS_FROM_SERVER: case GRPC_OP_RECV_INITIAL_METADATA: case GRPC_OP_RECV_MESSAGE: case GRPC_OP_RECV_STATUS_ON_CLIENT: case GRPC_OP_RECV_CLOSE_ON_SERVER: rb_ary_push(ops_ary, key); return ST_CONTINUE; default: rb_raise(rb_eTypeError, "invalid operation : bad value %d", NUM2INT(key)); }; return ST_STOP; } /* grpc_rb_op_update_status_from_server adds the values in a ruby status struct to the 'send_status_from_server' portion of an op. */ static void grpc_rb_op_update_status_from_server(grpc_op *op, grpc_metadata_array *md_ary, grpc_slice *send_status_details, VALUE status) { VALUE code = rb_struct_aref(status, sym_code); VALUE details = rb_struct_aref(status, sym_details); VALUE metadata_hash = rb_struct_aref(status, sym_metadata); /* TODO: add check to ensure status is the correct struct type */ if (TYPE(code) != T_FIXNUM) { rb_raise(rb_eTypeError, "invalid code : got <%s>, want ", rb_obj_classname(code)); return; } if (TYPE(details) != T_STRING) { rb_raise(rb_eTypeError, "invalid details : got <%s>, want ", rb_obj_classname(code)); return; } *send_status_details = grpc_slice_from_copied_buffer(RSTRING_PTR(details), RSTRING_LEN(details)); op->data.send_status_from_server.status = NUM2INT(code); op->data.send_status_from_server.status_details = send_status_details; grpc_rb_md_ary_convert(metadata_hash, md_ary); op->data.send_status_from_server.trailing_metadata_count = md_ary->count; op->data.send_status_from_server.trailing_metadata = md_ary->metadata; } /* run_batch_stack holds various values used by the * grpc_rb_call_run_batch function */ typedef struct run_batch_stack { /* The batch ops */ grpc_op ops[8]; /* 8 is the maximum number of operations */ size_t op_num; /* tracks the last added operation */ /* Data being sent */ grpc_metadata_array send_metadata; grpc_metadata_array send_trailing_metadata; /* Data being received */ grpc_byte_buffer *recv_message; grpc_metadata_array recv_metadata; grpc_metadata_array recv_trailing_metadata; int recv_cancelled; grpc_status_code recv_status; grpc_slice recv_status_details; unsigned write_flag; grpc_slice send_status_details; } run_batch_stack; /* grpc_run_batch_stack_init ensures the run_batch_stack is properly * initialized */ static void grpc_run_batch_stack_init(run_batch_stack *st, unsigned write_flag) { MEMZERO(st, run_batch_stack, 1); grpc_metadata_array_init(&st->send_metadata); grpc_metadata_array_init(&st->send_trailing_metadata); grpc_metadata_array_init(&st->recv_metadata); grpc_metadata_array_init(&st->recv_trailing_metadata); st->op_num = 0; st->write_flag = write_flag; } /* grpc_run_batch_stack_cleanup ensures the run_batch_stack is properly * cleaned up */ static void grpc_run_batch_stack_cleanup(run_batch_stack *st) { size_t i = 0; grpc_metadata_array_destroy(&st->send_metadata); grpc_metadata_array_destroy(&st->send_trailing_metadata); grpc_metadata_array_destroy(&st->recv_metadata); grpc_metadata_array_destroy(&st->recv_trailing_metadata); if (GRPC_SLICE_START_PTR(st->send_status_details) != NULL) { grpc_slice_unref(st->send_status_details); } if (GRPC_SLICE_START_PTR(st->recv_status_details) != NULL) { grpc_slice_unref(st->recv_status_details); } if (st->recv_message != NULL) { grpc_byte_buffer_destroy(st->recv_message); } for (i = 0; i < st->op_num; i++) { if (st->ops[i].op == GRPC_OP_SEND_MESSAGE) { grpc_byte_buffer_destroy(st->ops[i].data.send_message.send_message); } } } /* grpc_run_batch_stack_fill_ops fills the run_batch_stack ops array from * ops_hash */ static void grpc_run_batch_stack_fill_ops(run_batch_stack *st, VALUE ops_hash) { VALUE this_op = Qnil; VALUE this_value = Qnil; VALUE ops_ary = rb_ary_new(); size_t i = 0; /* Create a ruby array with just the operation keys */ rb_hash_foreach(ops_hash, grpc_rb_call_check_op_keys_hash_cb, ops_ary); /* Fill the ops array */ for (i = 0; i < (size_t)RARRAY_LEN(ops_ary); i++) { this_op = rb_ary_entry(ops_ary, i); this_value = rb_hash_aref(ops_hash, this_op); st->ops[st->op_num].flags = 0; switch (NUM2INT(this_op)) { case GRPC_OP_SEND_INITIAL_METADATA: /* N.B. later there is no need to explicitly delete the metadata keys * and values, they are references to data in ruby objects. */ grpc_rb_md_ary_convert(this_value, &st->send_metadata); st->ops[st->op_num].data.send_initial_metadata.count = st->send_metadata.count; st->ops[st->op_num].data.send_initial_metadata.metadata = st->send_metadata.metadata; break; case GRPC_OP_SEND_MESSAGE: st->ops[st->op_num].data.send_message.send_message = grpc_rb_s_to_byte_buffer(RSTRING_PTR(this_value), RSTRING_LEN(this_value)); st->ops[st->op_num].flags = st->write_flag; break; case GRPC_OP_SEND_CLOSE_FROM_CLIENT: break; case GRPC_OP_SEND_STATUS_FROM_SERVER: /* N.B. later there is no need to explicitly delete the metadata keys * and values, they are references to data in ruby objects. */ grpc_rb_op_update_status_from_server( &st->ops[st->op_num], &st->send_trailing_metadata, &st->send_status_details, this_value); break; case GRPC_OP_RECV_INITIAL_METADATA: st->ops[st->op_num].data.recv_initial_metadata.recv_initial_metadata = &st->recv_metadata; break; case GRPC_OP_RECV_MESSAGE: st->ops[st->op_num].data.recv_message.recv_message = &st->recv_message; break; case GRPC_OP_RECV_STATUS_ON_CLIENT: st->ops[st->op_num].data.recv_status_on_client.trailing_metadata = &st->recv_trailing_metadata; st->ops[st->op_num].data.recv_status_on_client.status = &st->recv_status; st->ops[st->op_num].data.recv_status_on_client.status_details = &st->recv_status_details; break; case GRPC_OP_RECV_CLOSE_ON_SERVER: st->ops[st->op_num].data.recv_close_on_server.cancelled = &st->recv_cancelled; break; default: grpc_run_batch_stack_cleanup(st); rb_raise(rb_eTypeError, "invalid operation : bad value %d", NUM2INT(this_op)); }; st->ops[st->op_num].op = (grpc_op_type)NUM2INT(this_op); st->ops[st->op_num].reserved = NULL; st->op_num++; } } /* grpc_run_batch_stack_build_result fills constructs a ruby BatchResult struct after the results have run */ static VALUE grpc_run_batch_stack_build_result(run_batch_stack *st) { size_t i = 0; VALUE result = rb_struct_new(grpc_rb_sBatchResult, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, NULL); for (i = 0; i < st->op_num; i++) { switch (st->ops[i].op) { case GRPC_OP_SEND_INITIAL_METADATA: rb_struct_aset(result, sym_send_metadata, Qtrue); break; case GRPC_OP_SEND_MESSAGE: rb_struct_aset(result, sym_send_message, Qtrue); break; case GRPC_OP_SEND_CLOSE_FROM_CLIENT: rb_struct_aset(result, sym_send_close, Qtrue); break; case GRPC_OP_SEND_STATUS_FROM_SERVER: rb_struct_aset(result, sym_send_status, Qtrue); break; case GRPC_OP_RECV_INITIAL_METADATA: rb_struct_aset(result, sym_metadata, grpc_rb_md_ary_to_h(&st->recv_metadata)); case GRPC_OP_RECV_MESSAGE: rb_struct_aset(result, sym_message, grpc_rb_byte_buffer_to_s(st->recv_message)); break; case GRPC_OP_RECV_STATUS_ON_CLIENT: rb_struct_aset( result, sym_status, rb_struct_new(grpc_rb_sStatus, UINT2NUM(st->recv_status), (GRPC_SLICE_START_PTR(st->recv_status_details) == NULL ? Qnil : grpc_rb_slice_to_ruby_string(st->recv_status_details)), grpc_rb_md_ary_to_h(&st->recv_trailing_metadata), NULL)); break; case GRPC_OP_RECV_CLOSE_ON_SERVER: rb_struct_aset(result, sym_send_close, Qtrue); break; default: break; } } return result; } /* call-seq: ops = { GRPC::Core::CallOps::SEND_INITIAL_METADATA => , GRPC::Core::CallOps::SEND_MESSAGE => , ... } tag = Object.new timeout = 10 call.start_batch(tag, timeout, ops) Start a batch of operations defined in the array ops; when complete, post a completion of type 'tag' to the completion queue bound to the call. Also waits for the batch to complete, until timeout is reached. The order of ops specified in the batch has no significance. Only one operation of each type can be active at once in any given batch */ static VALUE grpc_rb_call_run_batch(VALUE self, VALUE ops_hash) { run_batch_stack *st = NULL; grpc_rb_call *call = NULL; grpc_event ev; grpc_call_error err; VALUE result = Qnil; VALUE rb_write_flag = rb_ivar_get(self, id_write_flag); unsigned write_flag = 0; void *tag = (void*)&st; if (RTYPEDDATA_DATA(self) == NULL) { rb_raise(grpc_rb_eCallError, "Cannot run batch on closed call"); return Qnil; } TypedData_Get_Struct(self, grpc_rb_call, &grpc_call_data_type, call); /* Validate the ops args, adding them to a ruby array */ if (TYPE(ops_hash) != T_HASH) { rb_raise(rb_eTypeError, "call#run_batch: ops hash should be a hash"); return Qnil; } if (rb_write_flag != Qnil) { write_flag = NUM2UINT(rb_write_flag); } st = gpr_malloc(sizeof(run_batch_stack)); grpc_run_batch_stack_init(st, write_flag); grpc_run_batch_stack_fill_ops(st, ops_hash); /* call grpc_call_start_batch, then wait for it to complete using * pluck_event */ err = grpc_call_start_batch(call->wrapped, st->ops, st->op_num, tag, NULL); if (err != GRPC_CALL_OK) { grpc_run_batch_stack_cleanup(st); gpr_free(st); rb_raise(grpc_rb_eCallError, "grpc_call_start_batch failed with %s (code=%d)", grpc_call_error_detail_of(err), err); return Qnil; } ev = rb_completion_queue_pluck(call->queue, tag, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); if (!ev.success) { rb_raise(grpc_rb_eCallError, "call#run_batch failed somehow"); } /* Build and return the BatchResult struct result, if there is an error, it's reflected in the status */ result = grpc_run_batch_stack_build_result(st); grpc_run_batch_stack_cleanup(st); gpr_free(st); return result; } static void Init_grpc_write_flags() { /* Constants representing the write flags in grpc.h */ VALUE grpc_rb_mWriteFlags = rb_define_module_under(grpc_rb_mGrpcCore, "WriteFlags"); rb_define_const(grpc_rb_mWriteFlags, "BUFFER_HINT", UINT2NUM(GRPC_WRITE_BUFFER_HINT)); rb_define_const(grpc_rb_mWriteFlags, "NO_COMPRESS", UINT2NUM(GRPC_WRITE_NO_COMPRESS)); } static void Init_grpc_error_codes() { /* Constants representing the error codes of grpc_call_error in grpc.h */ VALUE grpc_rb_mRpcErrors = rb_define_module_under(grpc_rb_mGrpcCore, "RpcErrors"); rb_define_const(grpc_rb_mRpcErrors, "OK", UINT2NUM(GRPC_CALL_OK)); rb_define_const(grpc_rb_mRpcErrors, "ERROR", UINT2NUM(GRPC_CALL_ERROR)); rb_define_const(grpc_rb_mRpcErrors, "NOT_ON_SERVER", UINT2NUM(GRPC_CALL_ERROR_NOT_ON_SERVER)); rb_define_const(grpc_rb_mRpcErrors, "NOT_ON_CLIENT", UINT2NUM(GRPC_CALL_ERROR_NOT_ON_CLIENT)); rb_define_const(grpc_rb_mRpcErrors, "ALREADY_ACCEPTED", UINT2NUM(GRPC_CALL_ERROR_ALREADY_ACCEPTED)); rb_define_const(grpc_rb_mRpcErrors, "ALREADY_INVOKED", UINT2NUM(GRPC_CALL_ERROR_ALREADY_INVOKED)); rb_define_const(grpc_rb_mRpcErrors, "NOT_INVOKED", UINT2NUM(GRPC_CALL_ERROR_NOT_INVOKED)); rb_define_const(grpc_rb_mRpcErrors, "ALREADY_FINISHED", UINT2NUM(GRPC_CALL_ERROR_ALREADY_FINISHED)); rb_define_const(grpc_rb_mRpcErrors, "TOO_MANY_OPERATIONS", UINT2NUM(GRPC_CALL_ERROR_TOO_MANY_OPERATIONS)); rb_define_const(grpc_rb_mRpcErrors, "INVALID_FLAGS", UINT2NUM(GRPC_CALL_ERROR_INVALID_FLAGS)); /* Add the detail strings to a Hash */ rb_error_code_details = rb_hash_new(); rb_hash_aset(rb_error_code_details, UINT2NUM(GRPC_CALL_OK), rb_str_new2("ok")); rb_hash_aset(rb_error_code_details, UINT2NUM(GRPC_CALL_ERROR), rb_str_new2("unknown error")); rb_hash_aset(rb_error_code_details, UINT2NUM(GRPC_CALL_ERROR_NOT_ON_SERVER), rb_str_new2("not available on a server")); rb_hash_aset(rb_error_code_details, UINT2NUM(GRPC_CALL_ERROR_NOT_ON_CLIENT), rb_str_new2("not available on a client")); rb_hash_aset(rb_error_code_details, UINT2NUM(GRPC_CALL_ERROR_ALREADY_ACCEPTED), rb_str_new2("call is already accepted")); rb_hash_aset(rb_error_code_details, UINT2NUM(GRPC_CALL_ERROR_ALREADY_INVOKED), rb_str_new2("call is already invoked")); rb_hash_aset(rb_error_code_details, UINT2NUM(GRPC_CALL_ERROR_NOT_INVOKED), rb_str_new2("call is not yet invoked")); rb_hash_aset(rb_error_code_details, UINT2NUM(GRPC_CALL_ERROR_ALREADY_FINISHED), rb_str_new2("call is already finished")); rb_hash_aset(rb_error_code_details, UINT2NUM(GRPC_CALL_ERROR_TOO_MANY_OPERATIONS), rb_str_new2("outstanding read or write present")); rb_hash_aset(rb_error_code_details, UINT2NUM(GRPC_CALL_ERROR_INVALID_FLAGS), rb_str_new2("a bad flag was given")); rb_define_const(grpc_rb_mRpcErrors, "ErrorMessages", rb_error_code_details); rb_obj_freeze(rb_error_code_details); } static void Init_grpc_op_codes() { /* Constants representing operation type codes in grpc.h */ VALUE grpc_rb_mCallOps = rb_define_module_under(grpc_rb_mGrpcCore, "CallOps"); rb_define_const(grpc_rb_mCallOps, "SEND_INITIAL_METADATA", UINT2NUM(GRPC_OP_SEND_INITIAL_METADATA)); rb_define_const(grpc_rb_mCallOps, "SEND_MESSAGE", UINT2NUM(GRPC_OP_SEND_MESSAGE)); rb_define_const(grpc_rb_mCallOps, "SEND_CLOSE_FROM_CLIENT", UINT2NUM(GRPC_OP_SEND_CLOSE_FROM_CLIENT)); rb_define_const(grpc_rb_mCallOps, "SEND_STATUS_FROM_SERVER", UINT2NUM(GRPC_OP_SEND_STATUS_FROM_SERVER)); rb_define_const(grpc_rb_mCallOps, "RECV_INITIAL_METADATA", UINT2NUM(GRPC_OP_RECV_INITIAL_METADATA)); rb_define_const(grpc_rb_mCallOps, "RECV_MESSAGE", UINT2NUM(GRPC_OP_RECV_MESSAGE)); rb_define_const(grpc_rb_mCallOps, "RECV_STATUS_ON_CLIENT", UINT2NUM(GRPC_OP_RECV_STATUS_ON_CLIENT)); rb_define_const(grpc_rb_mCallOps, "RECV_CLOSE_ON_SERVER", UINT2NUM(GRPC_OP_RECV_CLOSE_ON_SERVER)); } static void Init_grpc_metadata_keys() { VALUE grpc_rb_mMetadataKeys = rb_define_module_under(grpc_rb_mGrpcCore, "MetadataKeys"); rb_define_const(grpc_rb_mMetadataKeys, "COMPRESSION_REQUEST_ALGORITHM", rb_str_new2(GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY)); } void Init_grpc_call() { /* CallError inherits from Exception to signal that it is non-recoverable */ grpc_rb_eCallError = rb_define_class_under(grpc_rb_mGrpcCore, "CallError", rb_eException); grpc_rb_eOutOfTime = rb_define_class_under(grpc_rb_mGrpcCore, "OutOfTime", rb_eException); grpc_rb_cCall = rb_define_class_under(grpc_rb_mGrpcCore, "Call", rb_cObject); grpc_rb_cMdAry = rb_define_class_under(grpc_rb_mGrpcCore, "MetadataArray", rb_cObject); /* Prevent allocation or inialization of the Call class */ rb_define_alloc_func(grpc_rb_cCall, grpc_rb_cannot_alloc); rb_define_method(grpc_rb_cCall, "initialize", grpc_rb_cannot_init, 0); rb_define_method(grpc_rb_cCall, "initialize_copy", grpc_rb_cannot_init_copy, 1); /* Add ruby analogues of the Call methods. */ rb_define_method(grpc_rb_cCall, "run_batch", grpc_rb_call_run_batch, 1); rb_define_method(grpc_rb_cCall, "cancel", grpc_rb_call_cancel, 0); rb_define_method(grpc_rb_cCall, "close", grpc_rb_call_close, 0); rb_define_method(grpc_rb_cCall, "peer", grpc_rb_call_get_peer, 0); rb_define_method(grpc_rb_cCall, "peer_cert", grpc_rb_call_get_peer_cert, 0); rb_define_method(grpc_rb_cCall, "status", grpc_rb_call_get_status, 0); rb_define_method(grpc_rb_cCall, "status=", grpc_rb_call_set_status, 1); rb_define_method(grpc_rb_cCall, "metadata", grpc_rb_call_get_metadata, 0); rb_define_method(grpc_rb_cCall, "metadata=", grpc_rb_call_set_metadata, 1); rb_define_method(grpc_rb_cCall, "trailing_metadata", grpc_rb_call_get_trailing_metadata, 0); rb_define_method(grpc_rb_cCall, "trailing_metadata=", grpc_rb_call_set_trailing_metadata, 1); rb_define_method(grpc_rb_cCall, "write_flag", grpc_rb_call_get_write_flag, 0); rb_define_method(grpc_rb_cCall, "write_flag=", grpc_rb_call_set_write_flag, 1); rb_define_method(grpc_rb_cCall, "set_credentials!", grpc_rb_call_set_credentials, 1); /* Ids used to support call attributes */ id_metadata = rb_intern("metadata"); id_trailing_metadata = rb_intern("trailing_metadata"); id_status = rb_intern("status"); id_write_flag = rb_intern("write_flag"); /* Ids used by the c wrapping internals. */ id_credentials = rb_intern("__credentials"); /* Ids used in constructing the batch result. */ sym_send_message = ID2SYM(rb_intern("send_message")); sym_send_metadata = ID2SYM(rb_intern("send_metadata")); sym_send_close = ID2SYM(rb_intern("send_close")); sym_send_status = ID2SYM(rb_intern("send_status")); sym_message = ID2SYM(rb_intern("message")); sym_status = ID2SYM(rb_intern("status")); sym_cancelled = ID2SYM(rb_intern("cancelled")); /* The Struct used to return the run_batch result. */ grpc_rb_sBatchResult = rb_struct_define( "BatchResult", "send_message", "send_metadata", "send_close", "send_status", "message", "metadata", "status", "cancelled", NULL); Init_grpc_error_codes(); Init_grpc_op_codes(); Init_grpc_write_flags(); Init_grpc_metadata_keys(); } /* Gets the call from the ruby object */ grpc_call *grpc_rb_get_wrapped_call(VALUE v) { grpc_rb_call *call = NULL; TypedData_Get_Struct(v, grpc_rb_call, &grpc_call_data_type, call); return call->wrapped; } /* Obtains the wrapped object for a given call */ VALUE grpc_rb_wrap_call(grpc_call *c, grpc_completion_queue *q) { grpc_rb_call *wrapper; if (c == NULL || q == NULL) { return Qnil; } wrapper = ALLOC(grpc_rb_call); wrapper->wrapped = c; wrapper->queue = q; return TypedData_Wrap_Struct(grpc_rb_cCall, &grpc_call_data_type, wrapper); } grpc-1.3.2/src/ruby/ext/grpc/rb_call.h000066400000000000000000000046751310511640000175250ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_RB_CALL_H_ #define GRPC_RB_CALL_H_ #include #include /* Gets the wrapped call from a VALUE. */ grpc_call* grpc_rb_get_wrapped_call(VALUE v); /* Gets the VALUE corresponding to given grpc_call. */ VALUE grpc_rb_wrap_call(grpc_call *c, grpc_completion_queue *q); /* Provides the details of an call error */ const char* grpc_call_error_detail_of(grpc_call_error err); /* Converts a metadata array to a hash. */ VALUE grpc_rb_md_ary_to_h(grpc_metadata_array *md_ary); /* grpc_rb_md_ary_convert converts a ruby metadata hash into a grpc_metadata_array. */ void grpc_rb_md_ary_convert(VALUE md_ary_hash, grpc_metadata_array *md_ary); /* grpc_rb_eCallError is the ruby class of the exception thrown during call operations. */ extern VALUE grpc_rb_eCallError; /* Initializes the Call class. */ void Init_grpc_call(); #endif /* GRPC_RB_CALL_H_ */ grpc-1.3.2/src/ruby/ext/grpc/rb_call_credentials.c000066400000000000000000000245241310511640000220700ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "rb_grpc_imports.generated.h" #include "rb_call_credentials.h" #include #include #include #include #include #include "rb_call.h" #include "rb_event_thread.h" #include "rb_grpc.h" /* grpc_rb_cCallCredentials is the ruby class that proxies * grpc_call_credentials */ static VALUE grpc_rb_cCallCredentials = Qnil; /* grpc_rb_call_credentials wraps a grpc_call_credentials. It provides a mark * object that is used to hold references to any objects used to create the * credentials. */ typedef struct grpc_rb_call_credentials { /* Holder of ruby objects involved in contructing the credentials */ VALUE mark; /* The actual credentials */ grpc_call_credentials *wrapped; } grpc_rb_call_credentials; typedef struct callback_params { VALUE get_metadata; grpc_auth_metadata_context context; void *user_data; grpc_credentials_plugin_metadata_cb callback; } callback_params; static VALUE grpc_rb_call_credentials_callback(VALUE callback_args) { VALUE result = rb_hash_new(); VALUE metadata = rb_funcall(rb_ary_entry(callback_args, 0), rb_intern("call"), 1, rb_ary_entry(callback_args, 1)); rb_hash_aset(result, rb_str_new2("metadata"), metadata); rb_hash_aset(result, rb_str_new2("status"), INT2NUM(GRPC_STATUS_OK)); rb_hash_aset(result, rb_str_new2("details"), rb_str_new2("")); return result; } static VALUE grpc_rb_call_credentials_callback_rescue(VALUE args, VALUE exception_object) { VALUE result = rb_hash_new(); VALUE backtrace = rb_funcall( rb_funcall(exception_object, rb_intern("backtrace"), 0), rb_intern("join"), 1, rb_str_new2("\n\tfrom ")); VALUE rb_exception_info = rb_funcall(exception_object, rb_intern("inspect"), 0); (void)args; gpr_log(GPR_INFO, "Call credentials callback failed: %s\n%s", StringValueCStr(rb_exception_info), StringValueCStr(backtrace)); rb_hash_aset(result, rb_str_new2("metadata"), Qnil); rb_hash_aset(result, rb_str_new2("status"), INT2NUM(GRPC_STATUS_UNAUTHENTICATED)); rb_hash_aset(result, rb_str_new2("details"), rb_exception_info); return result; } static void grpc_rb_call_credentials_callback_with_gil(void *param) { callback_params *const params = (callback_params *)param; VALUE auth_uri = rb_str_new_cstr(params->context.service_url); /* Pass the arguments to the proc in a hash, which currently only has they key 'auth_uri' */ VALUE callback_args = rb_ary_new(); VALUE args = rb_hash_new(); VALUE result; grpc_metadata_array md_ary; grpc_status_code status; VALUE details; char *error_details; grpc_metadata_array_init(&md_ary); rb_hash_aset(args, ID2SYM(rb_intern("jwt_aud_uri")), auth_uri); rb_ary_push(callback_args, params->get_metadata); rb_ary_push(callback_args, args); result = rb_rescue(grpc_rb_call_credentials_callback, callback_args, grpc_rb_call_credentials_callback_rescue, Qnil); // Both callbacks return a hash, so result should be a hash grpc_rb_md_ary_convert(rb_hash_aref(result, rb_str_new2("metadata")), &md_ary); status = NUM2INT(rb_hash_aref(result, rb_str_new2("status"))); details = rb_hash_aref(result, rb_str_new2("details")); error_details = StringValueCStr(details); params->callback(params->user_data, md_ary.metadata, md_ary.count, status, error_details); grpc_metadata_array_destroy(&md_ary); gpr_free(params); } static void grpc_rb_call_credentials_plugin_get_metadata( void *state, grpc_auth_metadata_context context, grpc_credentials_plugin_metadata_cb cb, void *user_data) { callback_params *params = gpr_malloc(sizeof(callback_params)); params->get_metadata = (VALUE)state; params->context = context; params->user_data = user_data; params->callback = cb; grpc_rb_event_queue_enqueue(grpc_rb_call_credentials_callback_with_gil, (void*)(params)); } static void grpc_rb_call_credentials_plugin_destroy(void *state) { (void)state; // Not sure what needs to be done here } /* Destroys the credentials instances. */ static void grpc_rb_call_credentials_free(void *p) { grpc_rb_call_credentials *wrapper; if (p == NULL) { return; } wrapper = (grpc_rb_call_credentials *)p; grpc_call_credentials_release(wrapper->wrapped); wrapper->wrapped = NULL; xfree(p); } /* Protects the mark object from GC */ static void grpc_rb_call_credentials_mark(void *p) { grpc_rb_call_credentials *wrapper = NULL; if (p == NULL) { return; } wrapper = (grpc_rb_call_credentials *)p; if (wrapper->mark != Qnil) { rb_gc_mark(wrapper->mark); } } static rb_data_type_t grpc_rb_call_credentials_data_type = { "grpc_call_credentials", {grpc_rb_call_credentials_mark, grpc_rb_call_credentials_free, GRPC_RB_MEMSIZE_UNAVAILABLE, {NULL, NULL}}, NULL, NULL, #ifdef RUBY_TYPED_FREE_IMMEDIATELY RUBY_TYPED_FREE_IMMEDIATELY #endif }; /* Allocates CallCredentials instances. Provides safe initial defaults for the instance fields. */ static VALUE grpc_rb_call_credentials_alloc(VALUE cls) { grpc_rb_call_credentials *wrapper = ALLOC(grpc_rb_call_credentials); wrapper->wrapped = NULL; wrapper->mark = Qnil; return TypedData_Wrap_Struct(cls, &grpc_rb_call_credentials_data_type, wrapper); } /* Creates a wrapping object for a given call credentials. This should only be * called with grpc_call_credentials objects that are not already associated * with any Ruby object */ VALUE grpc_rb_wrap_call_credentials(grpc_call_credentials *c, VALUE mark) { VALUE rb_wrapper; grpc_rb_call_credentials *wrapper; if (c == NULL) { return Qnil; } rb_wrapper = grpc_rb_call_credentials_alloc(grpc_rb_cCallCredentials); TypedData_Get_Struct(rb_wrapper, grpc_rb_call_credentials, &grpc_rb_call_credentials_data_type, wrapper); wrapper->wrapped = c; wrapper->mark = mark; return rb_wrapper; } /* The attribute used on the mark object to hold the callback */ static ID id_callback; /* call-seq: creds = Credentials.new auth_proc proc: (required) Proc that generates auth metadata Initializes CallCredential instances. */ static VALUE grpc_rb_call_credentials_init(VALUE self, VALUE proc) { grpc_rb_call_credentials *wrapper = NULL; grpc_call_credentials *creds = NULL; grpc_metadata_credentials_plugin plugin; grpc_ruby_once_init(); TypedData_Get_Struct(self, grpc_rb_call_credentials, &grpc_rb_call_credentials_data_type, wrapper); plugin.get_metadata = grpc_rb_call_credentials_plugin_get_metadata; plugin.destroy = grpc_rb_call_credentials_plugin_destroy; if (!rb_obj_is_proc(proc)) { rb_raise(rb_eTypeError, "Argument to CallCredentials#new must be a proc"); return Qnil; } plugin.state = (void*)proc; plugin.type = ""; creds = grpc_metadata_credentials_create_from_plugin(plugin, NULL); if (creds == NULL) { rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why"); return Qnil; } wrapper->mark = proc; wrapper->wrapped = creds; rb_ivar_set(self, id_callback, proc); return self; } static VALUE grpc_rb_call_credentials_compose(int argc, VALUE *argv, VALUE self) { grpc_call_credentials *creds; grpc_call_credentials *other; VALUE mark; if (argc == 0) { return self; } mark = rb_ary_new(); creds = grpc_rb_get_wrapped_call_credentials(self); for (int i = 0; i < argc; i++) { rb_ary_push(mark, argv[i]); other = grpc_rb_get_wrapped_call_credentials(argv[i]); creds = grpc_composite_call_credentials_create(creds, other, NULL); } return grpc_rb_wrap_call_credentials(creds, mark); } void Init_grpc_call_credentials() { grpc_rb_cCallCredentials = rb_define_class_under(grpc_rb_mGrpcCore, "CallCredentials", rb_cObject); /* Allocates an object managed by the ruby runtime */ rb_define_alloc_func(grpc_rb_cCallCredentials, grpc_rb_call_credentials_alloc); /* Provides a ruby constructor and support for dup/clone. */ rb_define_method(grpc_rb_cCallCredentials, "initialize", grpc_rb_call_credentials_init, 1); rb_define_method(grpc_rb_cCallCredentials, "initialize_copy", grpc_rb_cannot_init_copy, 1); rb_define_method(grpc_rb_cCallCredentials, "compose", grpc_rb_call_credentials_compose, -1); id_callback = rb_intern("__callback"); } /* Gets the wrapped grpc_call_credentials from the ruby wrapper */ grpc_call_credentials *grpc_rb_get_wrapped_call_credentials(VALUE v) { grpc_rb_call_credentials *wrapper = NULL; TypedData_Get_Struct(v, grpc_rb_call_credentials, &grpc_rb_call_credentials_data_type, wrapper); return wrapper->wrapped; } grpc-1.3.2/src/ruby/ext/grpc/rb_call_credentials.h000066400000000000000000000035521310511640000220730ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_RB_CALL_CREDENTIALS_H_ #define GRPC_RB_CALL_CREDENTIALS_H_ #include #include /* Initializes the ruby CallCredentials class. */ void Init_grpc_call_credentials(); grpc_call_credentials* grpc_rb_get_wrapped_call_credentials(VALUE v); #endif /* GRPC_RB_CALL_CREDENTIALS_H_ */ grpc-1.3.2/src/ruby/ext/grpc/rb_channel.c000066400000000000000000000571171310511640000202140ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include "rb_grpc_imports.generated.h" #include "rb_byte_buffer.h" #include "rb_channel.h" #include #include #include #include #include #include "rb_call.h" #include "rb_channel_args.h" #include "rb_channel_credentials.h" #include "rb_completion_queue.h" #include "rb_grpc.h" #include "rb_server.h" /* id_channel is the name of the hidden ivar that preserves a reference to the * channel on a call, so that calls are not GCed before their channel. */ static ID id_channel; /* id_target is the name of the hidden ivar that preserves a reference to the * target string used to create the call, preserved so that it does not get * GCed before the channel */ static ID id_target; /* id_insecure_channel is used to indicate that a channel is insecure */ static VALUE id_insecure_channel; /* grpc_rb_cChannel is the ruby class that proxies grpc_channel. */ static VALUE grpc_rb_cChannel = Qnil; /* Used during the conversion of a hash to channel args during channel setup */ static VALUE grpc_rb_cChannelArgs; /* grpc_rb_channel wraps a grpc_channel. */ typedef struct grpc_rb_channel { VALUE credentials; /* The actual channel */ grpc_channel *wrapped; int request_safe_destroy; int safe_to_destroy; grpc_connectivity_state current_connectivity_state; int mu_init_done; int abort_watch_connectivity_state; gpr_mu channel_mu; gpr_cv channel_cv; } grpc_rb_channel; /* Forward declarations of functions involved in temporary fix to * https://github.com/grpc/grpc/issues/9941 */ static void grpc_rb_channel_try_register_connection_polling( grpc_rb_channel *wrapper); static void grpc_rb_channel_safe_destroy(grpc_rb_channel *wrapper); static void *wait_until_channel_polling_thread_started_no_gil(void*); static void wait_until_channel_polling_thread_started_unblocking_func(void*); static grpc_completion_queue *channel_polling_cq; static gpr_mu global_connection_polling_mu; static gpr_cv global_connection_polling_cv; static int abort_channel_polling = 0; static int channel_polling_thread_started = 0; /* Destroys Channel instances. */ static void grpc_rb_channel_free(void *p) { grpc_rb_channel *ch = NULL; if (p == NULL) { return; }; ch = (grpc_rb_channel *)p; if (ch->wrapped != NULL) { grpc_rb_channel_safe_destroy(ch); ch->wrapped = NULL; } if (ch->mu_init_done) { gpr_mu_destroy(&ch->channel_mu); gpr_cv_destroy(&ch->channel_cv); } xfree(p); } /* Protects the mark object from GC */ static void grpc_rb_channel_mark(void *p) { grpc_rb_channel *channel = NULL; if (p == NULL) { return; } channel = (grpc_rb_channel *)p; if (channel->credentials != Qnil) { rb_gc_mark(channel->credentials); } } static rb_data_type_t grpc_channel_data_type = {"grpc_channel", {grpc_rb_channel_mark, grpc_rb_channel_free, GRPC_RB_MEMSIZE_UNAVAILABLE, {NULL, NULL}}, NULL, NULL, #ifdef RUBY_TYPED_FREE_IMMEDIATELY RUBY_TYPED_FREE_IMMEDIATELY #endif }; /* Allocates grpc_rb_channel instances. */ static VALUE grpc_rb_channel_alloc(VALUE cls) { grpc_rb_channel *wrapper = ALLOC(grpc_rb_channel); wrapper->wrapped = NULL; wrapper->credentials = Qnil; return TypedData_Wrap_Struct(cls, &grpc_channel_data_type, wrapper); } /* call-seq: insecure_channel = Channel:new("myhost:8080", {'arg1': 'value1'}, :this_channel_is_insecure) creds = ... secure_channel = Channel:new("myhost:443", {'arg1': 'value1'}, creds) Creates channel instances. */ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { VALUE channel_args = Qnil; VALUE credentials = Qnil; VALUE target = Qnil; grpc_rb_channel *wrapper = NULL; grpc_channel *ch = NULL; grpc_channel_credentials *creds = NULL; char *target_chars = NULL; grpc_channel_args args; MEMZERO(&args, grpc_channel_args, 1); grpc_ruby_once_init(); rb_thread_call_without_gvl(wait_until_channel_polling_thread_started_no_gil, NULL, wait_until_channel_polling_thread_started_unblocking_func, NULL); /* "3" == 3 mandatory args */ rb_scan_args(argc, argv, "3", &target, &channel_args, &credentials); TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); wrapper->mu_init_done = 0; target_chars = StringValueCStr(target); grpc_rb_hash_convert_to_channel_args(channel_args, &args); if (TYPE(credentials) == T_SYMBOL) { if (id_insecure_channel != SYM2ID(credentials)) { rb_raise(rb_eTypeError, "bad creds symbol, want :this_channel_is_insecure"); return Qnil; } ch = grpc_insecure_channel_create(target_chars, &args, NULL); } else { wrapper->credentials = credentials; creds = grpc_rb_get_wrapped_channel_credentials(credentials); ch = grpc_secure_channel_create(creds, target_chars, &args, NULL); } GPR_ASSERT(ch); wrapper->wrapped = ch; gpr_mu_init(&wrapper->channel_mu); gpr_cv_init(&wrapper->channel_cv); wrapper->mu_init_done = 1; gpr_mu_lock(&wrapper->channel_mu); wrapper->abort_watch_connectivity_state = 0; wrapper->current_connectivity_state = grpc_channel_check_connectivity_state(wrapper->wrapped, 0); wrapper->safe_to_destroy = 0; wrapper->request_safe_destroy = 0; gpr_cv_broadcast(&wrapper->channel_cv); gpr_mu_unlock(&wrapper->channel_mu); grpc_rb_channel_try_register_connection_polling(wrapper); if (args.args != NULL) { xfree(args.args); /* Allocated by grpc_rb_hash_convert_to_channel_args */ } if (ch == NULL) { rb_raise(rb_eRuntimeError, "could not create an rpc channel to target:%s", target_chars); return Qnil; } rb_ivar_set(self, id_target, target); wrapper->wrapped = ch; return self; } /* call-seq: ch.connectivity_state -> state ch.connectivity_state(true) -> state Indicates the current state of the channel, whose value is one of the constants defined in GRPC::Core::ConnectivityStates. It also tries to connect if the chennel is idle in the second form. */ static VALUE grpc_rb_channel_get_connectivity_state(int argc, VALUE *argv, VALUE self) { VALUE try_to_connect_param = Qfalse; int grpc_try_to_connect = 0; grpc_rb_channel *wrapper = NULL; grpc_channel *ch = NULL; /* "01" == 0 mandatory args, 1 (try_to_connect) is optional */ rb_scan_args(argc, argv, "01", &try_to_connect_param); grpc_try_to_connect = RTEST(try_to_connect_param) ? 1 : 0; TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); ch = wrapper->wrapped; if (ch == NULL) { rb_raise(rb_eRuntimeError, "closed!"); return Qnil; } return LONG2NUM(grpc_channel_check_connectivity_state(wrapper->wrapped, grpc_try_to_connect)); } typedef struct watch_state_stack { grpc_rb_channel *wrapper; gpr_timespec deadline; int last_state; } watch_state_stack; static void *watch_channel_state_without_gvl(void *arg) { watch_state_stack *stack = (watch_state_stack*)arg; gpr_timespec deadline = stack->deadline; grpc_rb_channel *wrapper = stack->wrapper; int last_state = stack->last_state; void *return_value = (void*)0; gpr_mu_lock(&wrapper->channel_mu); while(wrapper->current_connectivity_state == last_state && !wrapper->request_safe_destroy && !wrapper->safe_to_destroy && !wrapper->abort_watch_connectivity_state && gpr_time_cmp(deadline, gpr_now(GPR_CLOCK_REALTIME)) > 0) { gpr_cv_wait(&wrapper->channel_cv, &wrapper->channel_mu, deadline); } if (wrapper->current_connectivity_state != last_state) { return_value = (void*)1; } gpr_mu_unlock(&wrapper->channel_mu); return return_value; } static void watch_channel_state_unblocking_func(void *arg) { grpc_rb_channel *wrapper = (grpc_rb_channel*)arg; gpr_log(GPR_DEBUG, "GRPC_RUBY: watch channel state unblocking func called"); gpr_mu_lock(&wrapper->channel_mu); wrapper->abort_watch_connectivity_state = 1; gpr_cv_broadcast(&wrapper->channel_cv); gpr_mu_unlock(&wrapper->channel_mu); } /* Wait until the channel's connectivity state becomes different from * "last_state", or "deadline" expires. * Returns true if the the channel's connectivity state becomes * different from "last_state" within "deadline". * Returns false if "deadline" expires before the channel's connectivity * state changes from "last_state". * */ static VALUE grpc_rb_channel_watch_connectivity_state(VALUE self, VALUE last_state, VALUE deadline) { grpc_rb_channel *wrapper = NULL; watch_state_stack stack; void* out; TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); if (wrapper->wrapped == NULL) { rb_raise(rb_eRuntimeError, "closed!"); return Qnil; } if (!FIXNUM_P(last_state)) { rb_raise(rb_eTypeError, "bad type for last_state. want a GRPC::Core::ChannelState constant"); return Qnil; } stack.wrapper = wrapper; stack.deadline = grpc_rb_time_timeval(deadline, 0); stack.last_state = NUM2LONG(last_state); out = rb_thread_call_without_gvl(watch_channel_state_without_gvl, &stack, watch_channel_state_unblocking_func, wrapper); if (out) { return Qtrue; } return Qfalse; } /* Create a call given a grpc_channel, in order to call method. The request is not sent until grpc_call_invoke is called. */ static VALUE grpc_rb_channel_create_call(VALUE self, VALUE parent, VALUE mask, VALUE method, VALUE host, VALUE deadline) { VALUE res = Qnil; grpc_rb_channel *wrapper = NULL; grpc_call *call = NULL; grpc_call *parent_call = NULL; grpc_channel *ch = NULL; grpc_completion_queue *cq = NULL; int flags = GRPC_PROPAGATE_DEFAULTS; grpc_slice method_slice; grpc_slice host_slice; grpc_slice *host_slice_ptr = NULL; char *tmp_str = NULL; if (host != Qnil) { host_slice = grpc_slice_from_copied_buffer(RSTRING_PTR(host), RSTRING_LEN(host)); host_slice_ptr = &host_slice; } if (mask != Qnil) { flags = NUM2UINT(mask); } if (parent != Qnil) { parent_call = grpc_rb_get_wrapped_call(parent); } cq = grpc_completion_queue_create(NULL); TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); ch = wrapper->wrapped; if (ch == NULL) { rb_raise(rb_eRuntimeError, "closed!"); return Qnil; } method_slice = grpc_slice_from_copied_buffer(RSTRING_PTR(method), RSTRING_LEN(method)); call = grpc_channel_create_call(ch, parent_call, flags, cq, method_slice, host_slice_ptr, grpc_rb_time_timeval(deadline, /* absolute time */ 0), NULL); if (call == NULL) { tmp_str = grpc_slice_to_c_string(method_slice); rb_raise(rb_eRuntimeError, "cannot create call with method %s", tmp_str); return Qnil; } grpc_slice_unref(method_slice); if (host_slice_ptr != NULL) { grpc_slice_unref(host_slice); } res = grpc_rb_wrap_call(call, cq); /* Make this channel an instance attribute of the call so that it is not GCed * before the call. */ rb_ivar_set(res, id_channel, self); return res; } /* Closes the channel, calling it's destroy method */ static VALUE grpc_rb_channel_destroy(VALUE self) { grpc_rb_channel *wrapper = NULL; grpc_channel *ch = NULL; TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); ch = wrapper->wrapped; if (ch != NULL) { grpc_rb_channel_safe_destroy(wrapper); wrapper->wrapped = NULL; } return Qnil; } /* Called to obtain the target that this channel accesses. */ static VALUE grpc_rb_channel_get_target(VALUE self) { grpc_rb_channel *wrapper = NULL; VALUE res = Qnil; char *target = NULL; TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); target = grpc_channel_get_target(wrapper->wrapped); res = rb_str_new2(target); gpr_free(target); return res; } // Either start polling channel connection state or signal that it's free to // destroy. // Not safe to call while a channel's connection state is polled. static void grpc_rb_channel_try_register_connection_polling( grpc_rb_channel *wrapper) { grpc_connectivity_state conn_state; gpr_timespec sleep_time = gpr_time_add( gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(20, GPR_TIMESPAN)); GPR_ASSERT(wrapper); GPR_ASSERT(wrapper->wrapped); gpr_mu_lock(&wrapper->channel_mu); if (wrapper->request_safe_destroy) { wrapper->safe_to_destroy = 1; gpr_cv_broadcast(&wrapper->channel_cv); gpr_mu_unlock(&wrapper->channel_mu); return; } gpr_mu_lock(&global_connection_polling_mu); GPR_ASSERT(channel_polling_thread_started || abort_channel_polling); conn_state = grpc_channel_check_connectivity_state(wrapper->wrapped, 0); if (conn_state != wrapper->current_connectivity_state) { wrapper->current_connectivity_state = conn_state; gpr_cv_broadcast(&wrapper->channel_cv); } // avoid posting work to the channel polling cq if it's been shutdown if (!abort_channel_polling && conn_state != GRPC_CHANNEL_SHUTDOWN) { grpc_channel_watch_connectivity_state( wrapper->wrapped, conn_state, sleep_time, channel_polling_cq, wrapper); } else { wrapper->safe_to_destroy = 1; gpr_cv_broadcast(&wrapper->channel_cv); } gpr_mu_unlock(&global_connection_polling_mu); gpr_mu_unlock(&wrapper->channel_mu); } // Note requires wrapper->wrapped, wrapper->channel_mu/cv initialized static void grpc_rb_channel_safe_destroy(grpc_rb_channel *wrapper) { gpr_mu_lock(&wrapper->channel_mu); wrapper->request_safe_destroy = 1; while (!wrapper->safe_to_destroy) { gpr_cv_wait(&wrapper->channel_cv, &wrapper->channel_mu, gpr_inf_future(GPR_CLOCK_REALTIME)); } GPR_ASSERT(wrapper->safe_to_destroy); gpr_mu_unlock(&wrapper->channel_mu); grpc_channel_destroy(wrapper->wrapped); } // Note this loop breaks out with a single call of // "run_poll_channels_loop_no_gil". // This assumes that a ruby call the unblocking func // indicates process shutdown. // In the worst case, this stops polling channel connectivity // early and falls back to current behavior. static void *run_poll_channels_loop_no_gil(void *arg) { grpc_event event; (void)arg; gpr_log(GPR_DEBUG, "GRPC_RUBY: run_poll_channels_loop_no_gil - begin"); gpr_mu_lock(&global_connection_polling_mu); GPR_ASSERT(!channel_polling_thread_started); channel_polling_thread_started = 1; gpr_cv_broadcast(&global_connection_polling_cv); gpr_mu_unlock(&global_connection_polling_mu); for (;;) { event = grpc_completion_queue_next( channel_polling_cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); if (event.type == GRPC_QUEUE_SHUTDOWN) { break; } if (event.type == GRPC_OP_COMPLETE) { grpc_rb_channel_try_register_connection_polling((grpc_rb_channel *)event.tag); } } grpc_completion_queue_destroy(channel_polling_cq); gpr_log(GPR_DEBUG, "GRPC_RUBY: run_poll_channels_loop_no_gil - exit connection polling loop"); return NULL; } // Notify the channel polling loop to cleanup and shutdown. static void run_poll_channels_loop_unblocking_func(void *arg) { (void)arg; gpr_mu_lock(&global_connection_polling_mu); gpr_log(GPR_DEBUG, "GRPC_RUBY: run_poll_channels_loop_unblocking_func - begin aborting connection polling"); abort_channel_polling = 1; grpc_completion_queue_shutdown(channel_polling_cq); gpr_mu_unlock(&global_connection_polling_mu); } // Poll channel connectivity states in background thread without the GIL. static VALUE run_poll_channels_loop(VALUE arg) { (void)arg; gpr_log(GPR_DEBUG, "GRPC_RUBY: run_poll_channels_loop - create connection polling thread"); rb_thread_call_without_gvl(run_poll_channels_loop_no_gil, NULL, run_poll_channels_loop_unblocking_func, NULL); return Qnil; } static void *wait_until_channel_polling_thread_started_no_gil(void *arg) { (void)arg; gpr_log(GPR_DEBUG, "GRPC_RUBY: wait for channel polling thread to start"); gpr_mu_lock(&global_connection_polling_mu); while (!channel_polling_thread_started && !abort_channel_polling) { gpr_cv_wait(&global_connection_polling_cv, &global_connection_polling_mu, gpr_inf_future(GPR_CLOCK_REALTIME)); } gpr_mu_unlock(&global_connection_polling_mu); return NULL; } static void wait_until_channel_polling_thread_started_unblocking_func(void* arg) { (void)arg; gpr_mu_lock(&global_connection_polling_mu); gpr_log(GPR_DEBUG, "GRPC_RUBY: wait_until_channel_polling_thread_started_unblocking_func - begin aborting connection polling"); abort_channel_polling = 1; gpr_cv_broadcast(&global_connection_polling_cv); gpr_mu_unlock(&global_connection_polling_mu); } /* Temporary fix for * https://github.com/GoogleCloudPlatform/google-cloud-ruby/issues/899. * Transports in idle channels can get destroyed. Normally c-core re-connects, * but in grpc-ruby core never gets a thread until an RPC is made, because ruby * only calls c-core's "completion_queu_pluck" API. * This uses a global background thread that calls * "completion_queue_next" on registered "watch_channel_connectivity_state" * calls - so that c-core can reconnect if needed, when there aren't any RPC's. * TODO(apolcyn) remove this when core handles new RPCs on dead connections. */ void grpc_rb_channel_polling_thread_start() { VALUE background_thread = Qnil; GPR_ASSERT(!abort_channel_polling); GPR_ASSERT(!channel_polling_thread_started); GPR_ASSERT(channel_polling_cq == NULL); gpr_mu_init(&global_connection_polling_mu); gpr_cv_init(&global_connection_polling_cv); channel_polling_cq = grpc_completion_queue_create(NULL); background_thread = rb_thread_create(run_poll_channels_loop, NULL); if (!RTEST(background_thread)) { gpr_log(GPR_DEBUG, "GRPC_RUBY: failed to spawn channel polling thread"); gpr_mu_lock(&global_connection_polling_mu); abort_channel_polling = 1; gpr_cv_broadcast(&global_connection_polling_cv); gpr_mu_unlock(&global_connection_polling_mu); } } static void Init_grpc_propagate_masks() { /* Constants representing call propagation masks in grpc.h */ VALUE grpc_rb_mPropagateMasks = rb_define_module_under(grpc_rb_mGrpcCore, "PropagateMasks"); rb_define_const(grpc_rb_mPropagateMasks, "DEADLINE", UINT2NUM(GRPC_PROPAGATE_DEADLINE)); rb_define_const(grpc_rb_mPropagateMasks, "CENSUS_STATS_CONTEXT", UINT2NUM(GRPC_PROPAGATE_CENSUS_STATS_CONTEXT)); rb_define_const(grpc_rb_mPropagateMasks, "CENSUS_TRACING_CONTEXT", UINT2NUM(GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT)); rb_define_const(grpc_rb_mPropagateMasks, "CANCELLATION", UINT2NUM(GRPC_PROPAGATE_CANCELLATION)); rb_define_const(grpc_rb_mPropagateMasks, "DEFAULTS", UINT2NUM(GRPC_PROPAGATE_DEFAULTS)); } static void Init_grpc_connectivity_states() { /* Constants representing call propagation masks in grpc.h */ VALUE grpc_rb_mConnectivityStates = rb_define_module_under(grpc_rb_mGrpcCore, "ConnectivityStates"); rb_define_const(grpc_rb_mConnectivityStates, "IDLE", LONG2NUM(GRPC_CHANNEL_IDLE)); rb_define_const(grpc_rb_mConnectivityStates, "CONNECTING", LONG2NUM(GRPC_CHANNEL_CONNECTING)); rb_define_const(grpc_rb_mConnectivityStates, "READY", LONG2NUM(GRPC_CHANNEL_READY)); rb_define_const(grpc_rb_mConnectivityStates, "TRANSIENT_FAILURE", LONG2NUM(GRPC_CHANNEL_TRANSIENT_FAILURE)); rb_define_const(grpc_rb_mConnectivityStates, "FATAL_FAILURE", LONG2NUM(GRPC_CHANNEL_SHUTDOWN)); } void Init_grpc_channel() { grpc_rb_cChannelArgs = rb_define_class("TmpChannelArgs", rb_cObject); grpc_rb_cChannel = rb_define_class_under(grpc_rb_mGrpcCore, "Channel", rb_cObject); /* Allocates an object managed by the ruby runtime */ rb_define_alloc_func(grpc_rb_cChannel, grpc_rb_channel_alloc); /* Provides a ruby constructor and support for dup/clone. */ rb_define_method(grpc_rb_cChannel, "initialize", grpc_rb_channel_init, -1); rb_define_method(grpc_rb_cChannel, "initialize_copy", grpc_rb_cannot_init_copy, 1); /* Add ruby analogues of the Channel methods. */ rb_define_method(grpc_rb_cChannel, "connectivity_state", grpc_rb_channel_get_connectivity_state, -1); rb_define_method(grpc_rb_cChannel, "watch_connectivity_state", grpc_rb_channel_watch_connectivity_state, 2); rb_define_method(grpc_rb_cChannel, "create_call", grpc_rb_channel_create_call, 5); rb_define_method(grpc_rb_cChannel, "target", grpc_rb_channel_get_target, 0); rb_define_method(grpc_rb_cChannel, "destroy", grpc_rb_channel_destroy, 0); rb_define_alias(grpc_rb_cChannel, "close", "destroy"); id_channel = rb_intern("__channel"); id_target = rb_intern("__target"); rb_define_const(grpc_rb_cChannel, "SSL_TARGET", ID2SYM(rb_intern(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG))); rb_define_const(grpc_rb_cChannel, "ENABLE_CENSUS", ID2SYM(rb_intern(GRPC_ARG_ENABLE_CENSUS))); rb_define_const(grpc_rb_cChannel, "MAX_CONCURRENT_STREAMS", ID2SYM(rb_intern(GRPC_ARG_MAX_CONCURRENT_STREAMS))); rb_define_const(grpc_rb_cChannel, "MAX_MESSAGE_LENGTH", ID2SYM(rb_intern(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH))); id_insecure_channel = rb_intern("this_channel_is_insecure"); Init_grpc_propagate_masks(); Init_grpc_connectivity_states(); } /* Gets the wrapped channel from the ruby wrapper */ grpc_channel *grpc_rb_get_wrapped_channel(VALUE v) { grpc_rb_channel *wrapper = NULL; TypedData_Get_Struct(v, grpc_rb_channel, &grpc_channel_data_type, wrapper); return wrapper->wrapped; } grpc-1.3.2/src/ruby/ext/grpc/rb_channel.h000066400000000000000000000036011310511640000202060ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_RB_CHANNEL_H_ #define GRPC_RB_CHANNEL_H_ #include #include /* Initializes the Channel class. */ void Init_grpc_channel(); void grpc_rb_channel_polling_thread_start(); /* Gets the wrapped channel from the ruby wrapper */ grpc_channel* grpc_rb_get_wrapped_channel(VALUE v); #endif /* GRPC_RB_CHANNEL_H_ */ grpc-1.3.2/src/ruby/ext/grpc/rb_channel_args.c000066400000000000000000000137341310511640000212250ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "rb_grpc_imports.generated.h" #include "rb_channel_args.h" #include #include "rb_grpc.h" static rb_data_type_t grpc_rb_channel_args_data_type = { "grpc_channel_args", {GRPC_RB_GC_NOT_MARKED, GRPC_RB_GC_DONT_FREE, GRPC_RB_MEMSIZE_UNAVAILABLE, {NULL, NULL}}, NULL, NULL, #ifdef RUBY_TYPED_FREE_IMMEDIATELY RUBY_TYPED_FREE_IMMEDIATELY #endif }; /* A callback the processes the hash key values in channel_args hash */ static int grpc_rb_channel_create_in_process_add_args_hash_cb(VALUE key, VALUE val, VALUE args_obj) { const char* the_key; grpc_channel_args* args; switch (TYPE(key)) { case T_STRING: the_key = StringValuePtr(key); break; case T_SYMBOL: the_key = rb_id2name(SYM2ID(key)); break; default: rb_raise(rb_eTypeError, "bad chan arg: got <%s>, want ", rb_obj_classname(key)); return ST_STOP; } TypedData_Get_Struct(args_obj, grpc_channel_args, &grpc_rb_channel_args_data_type, args); if (args->num_args <= 0) { rb_raise(rb_eRuntimeError, "hash_cb bug: num_args is %lu for key:%s", args->num_args, StringValueCStr(key)); return ST_STOP; } args->args[args->num_args - 1].key = (char*)the_key; switch (TYPE(val)) { case T_SYMBOL: args->args[args->num_args - 1].type = GRPC_ARG_STRING; args->args[args->num_args - 1].value.string = (char*)rb_id2name(SYM2ID(val)); --args->num_args; return ST_CONTINUE; case T_STRING: args->args[args->num_args - 1].type = GRPC_ARG_STRING; args->args[args->num_args - 1].value.string = StringValueCStr(val); --args->num_args; return ST_CONTINUE; case T_FIXNUM: args->args[args->num_args - 1].type = GRPC_ARG_INTEGER; args->args[args->num_args - 1].value.integer = NUM2INT(val); --args->num_args; return ST_CONTINUE; default: rb_raise(rb_eTypeError, "%s: bad value: got <%s>, want ", StringValueCStr(key), rb_obj_classname(val)); return ST_STOP; } rb_raise(rb_eRuntimeError, "impl bug: hash_cb reached to far while on key:%s", StringValueCStr(key)); return ST_STOP; } /* channel_convert_params allows the call to grpc_rb_hash_convert_to_channel_args to be made within an rb_protect exception-handler. This allows any allocated memory to be freed before propagating any exception that occurs */ typedef struct channel_convert_params { VALUE src_hash; grpc_channel_args* dst; } channel_convert_params; static VALUE grpc_rb_hash_convert_to_channel_args0(VALUE as_value) { ID id_size = rb_intern("size"); VALUE grpc_rb_cChannelArgs = rb_define_class("TmpChannelArgs", rb_cObject); channel_convert_params* params = (channel_convert_params*)as_value; size_t num_args = 0; if (!NIL_P(params->src_hash) && TYPE(params->src_hash) != T_HASH) { rb_raise(rb_eTypeError, "bad channel args: got:<%s> want: a hash or nil", rb_obj_classname(params->src_hash)); return Qnil; } if (TYPE(params->src_hash) == T_HASH) { num_args = NUM2INT(rb_funcall(params->src_hash, id_size, 0)); params->dst->num_args = num_args; params->dst->args = ALLOC_N(grpc_arg, num_args); MEMZERO(params->dst->args, grpc_arg, num_args); rb_hash_foreach(params->src_hash, grpc_rb_channel_create_in_process_add_args_hash_cb, TypedData_Wrap_Struct(grpc_rb_cChannelArgs, &grpc_rb_channel_args_data_type, params->dst)); /* reset num_args as grpc_rb_channel_create_in_process_add_args_hash_cb * decrements it during has processing */ params->dst->num_args = num_args; } return Qnil; } void grpc_rb_hash_convert_to_channel_args(VALUE src_hash, grpc_channel_args* dst) { channel_convert_params params; int status = 0; /* Make a protected call to grpc_rb_hash_convert_channel_args */ params.src_hash = src_hash; params.dst = dst; rb_protect(grpc_rb_hash_convert_to_channel_args0, (VALUE) & params, &status); if (status != 0) { if (dst->args != NULL) { /* Free any allocated memory before propagating the error */ xfree(dst->args); } rb_jump_tag(status); } } grpc-1.3.2/src/ruby/ext/grpc/rb_channel_args.h000066400000000000000000000043431310511640000212260ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_RB_CHANNEL_ARGS_H_ #define GRPC_RB_CHANNEL_ARGS_H_ #include #include /* Converts a hash object containing channel args to a channel args instance. * * This func ALLOCs args->args. The caller is responsible for freeing it. If * a ruby error is raised during processing of the hash values, the func takes * care to deallocate any memory allocated so far, and propagate the error. * * @param src_hash A ruby hash * @param dst the grpc_channel_args that the hash entries will be added to. */ void grpc_rb_hash_convert_to_channel_args(VALUE src_hash, grpc_channel_args* dst); #endif /* GRPC_RB_CHANNEL_ARGS_H_ */ grpc-1.3.2/src/ruby/ext/grpc/rb_channel_credentials.c000066400000000000000000000226651310511640000225710ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include "rb_grpc_imports.generated.h" #include "rb_channel_credentials.h" #include #include #include #include #include "rb_call_credentials.h" #include "rb_grpc.h" /* grpc_rb_cChannelCredentials is the ruby class that proxies grpc_channel_credentials. */ static VALUE grpc_rb_cChannelCredentials = Qnil; static char *pem_root_certs = NULL; /* grpc_rb_channel_credentials wraps a grpc_channel_credentials. It provides a * mark object that is used to hold references to any objects used to create * the credentials. */ typedef struct grpc_rb_channel_credentials { /* Holder of ruby objects involved in constructing the credentials */ VALUE mark; /* The actual credentials */ grpc_channel_credentials *wrapped; } grpc_rb_channel_credentials; /* Destroys the credentials instances. */ static void grpc_rb_channel_credentials_free(void *p) { grpc_rb_channel_credentials *wrapper = NULL; if (p == NULL) { return; }; wrapper = (grpc_rb_channel_credentials *)p; grpc_channel_credentials_release(wrapper->wrapped); wrapper->wrapped = NULL; xfree(p); } /* Protects the mark object from GC */ static void grpc_rb_channel_credentials_mark(void *p) { grpc_rb_channel_credentials *wrapper = NULL; if (p == NULL) { return; } wrapper = (grpc_rb_channel_credentials *)p; if (wrapper->mark != Qnil) { rb_gc_mark(wrapper->mark); } } static rb_data_type_t grpc_rb_channel_credentials_data_type = { "grpc_channel_credentials", {grpc_rb_channel_credentials_mark, grpc_rb_channel_credentials_free, GRPC_RB_MEMSIZE_UNAVAILABLE, {NULL, NULL}}, NULL, NULL, #ifdef RUBY_TYPED_FREE_IMMEDIATELY RUBY_TYPED_FREE_IMMEDIATELY #endif }; /* Allocates ChannelCredential instances. Provides safe initial defaults for the instance fields. */ static VALUE grpc_rb_channel_credentials_alloc(VALUE cls) { grpc_rb_channel_credentials *wrapper = ALLOC(grpc_rb_channel_credentials); wrapper->wrapped = NULL; wrapper->mark = Qnil; return TypedData_Wrap_Struct(cls, &grpc_rb_channel_credentials_data_type, wrapper); } /* Creates a wrapping object for a given channel credentials. This should only * be called with grpc_channel_credentials objects that are not already * associated with any Ruby object. */ VALUE grpc_rb_wrap_channel_credentials(grpc_channel_credentials *c, VALUE mark) { VALUE rb_wrapper; grpc_rb_channel_credentials *wrapper; if (c == NULL) { return Qnil; } rb_wrapper = grpc_rb_channel_credentials_alloc(grpc_rb_cChannelCredentials); TypedData_Get_Struct(rb_wrapper, grpc_rb_channel_credentials, &grpc_rb_channel_credentials_data_type, wrapper); wrapper->wrapped = c; wrapper->mark = mark; return rb_wrapper; } /* The attribute used on the mark object to hold the pem_root_certs. */ static ID id_pem_root_certs; /* The attribute used on the mark object to hold the pem_private_key. */ static ID id_pem_private_key; /* The attribute used on the mark object to hold the pem_private_key. */ static ID id_pem_cert_chain; /* call-seq: creds1 = Credentials.new() ... creds2 = Credentials.new(pem_root_certs) ... creds3 = Credentials.new(pem_root_certs, pem_private_key, pem_cert_chain) pem_root_certs: (optional) PEM encoding of the server root certificate pem_private_key: (optional) PEM encoding of the client's private key pem_cert_chain: (optional) PEM encoding of the client's cert chain Initializes Credential instances. */ static VALUE grpc_rb_channel_credentials_init(int argc, VALUE *argv, VALUE self) { VALUE pem_root_certs = Qnil; VALUE pem_private_key = Qnil; VALUE pem_cert_chain = Qnil; grpc_rb_channel_credentials *wrapper = NULL; grpc_channel_credentials *creds = NULL; grpc_ssl_pem_key_cert_pair key_cert_pair; const char *pem_root_certs_cstr = NULL; MEMZERO(&key_cert_pair, grpc_ssl_pem_key_cert_pair, 1); grpc_ruby_once_init(); /* "03" == no mandatory arg, 3 optional */ rb_scan_args(argc, argv, "03", &pem_root_certs, &pem_private_key, &pem_cert_chain); TypedData_Get_Struct(self, grpc_rb_channel_credentials, &grpc_rb_channel_credentials_data_type, wrapper); if (pem_root_certs != Qnil) { pem_root_certs_cstr = RSTRING_PTR(pem_root_certs); } if (pem_private_key == Qnil && pem_cert_chain == Qnil) { creds = grpc_ssl_credentials_create(pem_root_certs_cstr, NULL, NULL); } else { key_cert_pair.private_key = RSTRING_PTR(pem_private_key); key_cert_pair.cert_chain = RSTRING_PTR(pem_cert_chain); creds = grpc_ssl_credentials_create(pem_root_certs_cstr, &key_cert_pair, NULL); } if (creds == NULL) { rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why"); return Qnil; } wrapper->wrapped = creds; /* Add the input objects as hidden fields to preserve them. */ rb_ivar_set(self, id_pem_cert_chain, pem_cert_chain); rb_ivar_set(self, id_pem_private_key, pem_private_key); rb_ivar_set(self, id_pem_root_certs, pem_root_certs); return self; } static VALUE grpc_rb_channel_credentials_compose(int argc, VALUE *argv, VALUE self) { grpc_channel_credentials *creds; grpc_call_credentials *other; VALUE mark; if (argc == 0) { return self; } mark = rb_ary_new(); rb_ary_push(mark, self); creds = grpc_rb_get_wrapped_channel_credentials(self); for (int i = 0; i < argc; i++) { rb_ary_push(mark, argv[i]); other = grpc_rb_get_wrapped_call_credentials(argv[i]); creds = grpc_composite_channel_credentials_create(creds, other, NULL); if (creds == NULL) { rb_raise(rb_eRuntimeError, "Failed to compose channel and call credentials"); } } return grpc_rb_wrap_channel_credentials(creds, mark); } static grpc_ssl_roots_override_result get_ssl_roots_override( char **pem_root_certs_ptr) { *pem_root_certs_ptr = pem_root_certs; if (pem_root_certs == NULL) { return GRPC_SSL_ROOTS_OVERRIDE_FAIL; } else { return GRPC_SSL_ROOTS_OVERRIDE_OK; } } static VALUE grpc_rb_set_default_roots_pem(VALUE self, VALUE roots) { char *roots_ptr = StringValueCStr(roots); size_t length = strlen(roots_ptr); (void)self; pem_root_certs = gpr_malloc((length + 1) * sizeof(char)); memcpy(pem_root_certs, roots_ptr, length + 1); return Qnil; } void Init_grpc_channel_credentials() { grpc_rb_cChannelCredentials = rb_define_class_under(grpc_rb_mGrpcCore, "ChannelCredentials", rb_cObject); /* Allocates an object managed by the ruby runtime */ rb_define_alloc_func(grpc_rb_cChannelCredentials, grpc_rb_channel_credentials_alloc); /* Provides a ruby constructor and support for dup/clone. */ rb_define_method(grpc_rb_cChannelCredentials, "initialize", grpc_rb_channel_credentials_init, -1); rb_define_method(grpc_rb_cChannelCredentials, "initialize_copy", grpc_rb_cannot_init_copy, 1); rb_define_method(grpc_rb_cChannelCredentials, "compose", grpc_rb_channel_credentials_compose, -1); rb_define_module_function(grpc_rb_cChannelCredentials, "set_default_roots_pem", grpc_rb_set_default_roots_pem, 1); grpc_set_ssl_roots_override_callback(get_ssl_roots_override); id_pem_cert_chain = rb_intern("__pem_cert_chain"); id_pem_private_key = rb_intern("__pem_private_key"); id_pem_root_certs = rb_intern("__pem_root_certs"); } /* Gets the wrapped grpc_channel_credentials from the ruby wrapper */ grpc_channel_credentials *grpc_rb_get_wrapped_channel_credentials(VALUE v) { grpc_rb_channel_credentials *wrapper = NULL; TypedData_Get_Struct(v, grpc_rb_channel_credentials, &grpc_rb_channel_credentials_data_type, wrapper); return wrapper->wrapped; } grpc-1.3.2/src/ruby/ext/grpc/rb_channel_credentials.h000066400000000000000000000036401310511640000225660ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_RB_CREDENTIALS_H_ #define GRPC_RB_CREDENTIALS_H_ #include #include /* Initializes the ruby ChannelCredentials class. */ void Init_grpc_channel_credentials(); /* Gets the wrapped credentials from the ruby wrapper */ grpc_channel_credentials* grpc_rb_get_wrapped_channel_credentials(VALUE v); #endif /* GRPC_RB_CREDENTIALS_H_ */ grpc-1.3.2/src/ruby/ext/grpc/rb_completion_queue.c000066400000000000000000000113631310511640000221520ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "rb_grpc_imports.generated.h" #include "rb_completion_queue.h" #include #include #include #include #include "rb_grpc.h" /* Used to allow grpc_completion_queue_next call to release the GIL */ typedef struct next_call_stack { grpc_completion_queue *cq; grpc_event event; gpr_timespec timeout; void *tag; volatile int interrupted; } next_call_stack; /* Calls grpc_completion_queue_pluck without holding the ruby GIL */ static void *grpc_rb_completion_queue_pluck_no_gil(void *param) { next_call_stack *const next_call = (next_call_stack*)param; gpr_timespec increment = gpr_time_from_millis(20, GPR_TIMESPAN); gpr_timespec deadline; do { deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), increment); next_call->event = grpc_completion_queue_pluck(next_call->cq, next_call->tag, deadline, NULL); if (next_call->event.type != GRPC_QUEUE_TIMEOUT || gpr_time_cmp(deadline, next_call->timeout) > 0) { break; } } while (!next_call->interrupted); return NULL; } /* Helper function to free a completion queue. */ void grpc_rb_completion_queue_destroy(grpc_completion_queue *cq) { /* Every function that adds an event to a queue also synchronously plucks that event from the queue, and holds a reference to the Ruby object that holds the queue, so we only get to this point if all of those functions have completed, and the queue is empty */ grpc_completion_queue_shutdown(cq); grpc_completion_queue_destroy(cq); } static void unblock_func(void *param) { next_call_stack *const next_call = (next_call_stack*)param; next_call->interrupted = 1; } /* Does the same thing as grpc_completion_queue_pluck, while properly releasing the GVL and handling interrupts */ grpc_event rb_completion_queue_pluck(grpc_completion_queue *queue, void *tag, gpr_timespec deadline, void *reserved) { next_call_stack next_call; MEMZERO(&next_call, next_call_stack, 1); next_call.cq = queue; next_call.timeout = deadline; next_call.tag = tag; next_call.event.type = GRPC_QUEUE_TIMEOUT; (void)reserved; /* Loop until we finish a pluck without an interruption. The internal pluck function runs either until it is interrupted or it gets an event, or time runs out. The basic reason we need this relatively complicated construction is that we need to re-acquire the GVL when an interrupt comes in, so that the ruby interpreter can do what it needs to do with the interrupt. But we also need to get back to plucking when the interrupt has been handled. */ do { next_call.interrupted = 0; rb_thread_call_without_gvl(grpc_rb_completion_queue_pluck_no_gil, (void *)&next_call, unblock_func, (void *)&next_call); /* If an interrupt prevented pluck from returning useful information, then any plucks that did complete must have timed out */ } while (next_call.interrupted && next_call.event.type == GRPC_QUEUE_TIMEOUT); return next_call.event; } grpc-1.3.2/src/ruby/ext/grpc/rb_completion_queue.h000066400000000000000000000041061310511640000221540ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_RB_COMPLETION_QUEUE_H_ #define GRPC_RB_COMPLETION_QUEUE_H_ #include #include void grpc_rb_completion_queue_destroy(grpc_completion_queue *cq); /** * Makes the implementation of CompletionQueue#pluck available in other files * * This avoids having code that holds the GIL repeated at multiple sites. */ grpc_event rb_completion_queue_pluck(grpc_completion_queue *queue, void *tag, gpr_timespec deadline, void *reserved); #endif /* GRPC_RB_COMPLETION_QUEUE_H_ */ grpc-1.3.2/src/ruby/ext/grpc/rb_compression_options.c000066400000000000000000000433631310511640000227160ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "rb_compression_options.h" #include "rb_byte_buffer.h" #include "rb_grpc_imports.generated.h" #include #include #include #include #include #include #include "rb_grpc.h" static VALUE grpc_rb_cCompressionOptions = Qnil; /* Ruby Ids for the names of valid compression levels. */ static VALUE id_compress_level_none = Qnil; static VALUE id_compress_level_low = Qnil; static VALUE id_compress_level_medium = Qnil; static VALUE id_compress_level_high = Qnil; /* grpc_rb_compression_options wraps a grpc_compression_options. * It can be used to get the channel argument key-values for specific * compression settings. */ /* Note that ruby objects of this type don't carry any state in other * Ruby objects and don't have a mark for GC. */ typedef struct grpc_rb_compression_options { /* The actual compression options that's being wrapped */ grpc_compression_options *wrapped; } grpc_rb_compression_options; /* Destroys the compression options instances and free the * wrapped grpc compression options. */ static void grpc_rb_compression_options_free(void *p) { grpc_rb_compression_options *wrapper = NULL; if (p == NULL) { return; }; wrapper = (grpc_rb_compression_options *)p; if (wrapper->wrapped != NULL) { gpr_free(wrapper->wrapped); wrapper->wrapped = NULL; } xfree(p); } /* Ruby recognized data type for the CompressionOptions class. */ static rb_data_type_t grpc_rb_compression_options_data_type = { "grpc_compression_options", {NULL, grpc_rb_compression_options_free, GRPC_RB_MEMSIZE_UNAVAILABLE, {NULL, NULL}}, NULL, NULL, #ifdef RUBY_TYPED_FREE_IMMEDIATELY RUBY_TYPED_FREE_IMMEDIATELY #endif }; /* Allocates CompressionOptions instances. Allocate the wrapped grpc compression options and initialize it here too. */ static VALUE grpc_rb_compression_options_alloc(VALUE cls) { grpc_rb_compression_options *wrapper = NULL; grpc_ruby_once_init(); wrapper = gpr_malloc(sizeof(grpc_rb_compression_options)); wrapper->wrapped = NULL; wrapper->wrapped = gpr_malloc(sizeof(grpc_compression_options)); grpc_compression_options_init(wrapper->wrapped); return TypedData_Wrap_Struct(cls, &grpc_rb_compression_options_data_type, wrapper); } /* Disables a compression algorithm, given the GRPC core internal number of a * compression algorithm. */ VALUE grpc_rb_compression_options_disable_compression_algorithm_internal( VALUE self, VALUE algorithm_to_disable) { grpc_compression_algorithm compression_algorithm = 0; grpc_rb_compression_options *wrapper = NULL; TypedData_Get_Struct(self, grpc_rb_compression_options, &grpc_rb_compression_options_data_type, wrapper); compression_algorithm = (grpc_compression_algorithm)NUM2INT(algorithm_to_disable); grpc_compression_options_disable_algorithm(wrapper->wrapped, compression_algorithm); return Qnil; } /* Gets the compression internal enum value of a compression level given its * name. */ grpc_compression_level grpc_rb_compression_options_level_name_to_value_internal( VALUE level_name) { Check_Type(level_name, T_SYMBOL); /* Check the compression level of the name passed in, and see which macro * from the GRPC core header files match. */ if (id_compress_level_none == SYM2ID(level_name)) { return GRPC_COMPRESS_LEVEL_NONE; } else if (id_compress_level_low == SYM2ID(level_name)) { return GRPC_COMPRESS_LEVEL_LOW; } else if (id_compress_level_medium == SYM2ID(level_name)) { return GRPC_COMPRESS_LEVEL_MED; } else if (id_compress_level_high == SYM2ID(level_name)) { return GRPC_COMPRESS_LEVEL_HIGH; } rb_raise(rb_eArgError, "Unrecognized compression level name." "Valid compression level names are none, low, medium, and high."); /* Dummy return statement. */ return GRPC_COMPRESS_LEVEL_NONE; } /* Sets the default compression level, given the name of a compression level. * Throws an error if no algorithm matched. */ void grpc_rb_compression_options_set_default_level( grpc_compression_options *options, VALUE new_level_name) { options->default_level.level = grpc_rb_compression_options_level_name_to_value_internal(new_level_name); options->default_level.is_set = 1; } /* Gets the internal value of a compression algorithm suitable as the value * in a GRPC core channel arguments hash. * algorithm_value is an out parameter. * Raises an error if the name of the algorithm passed in is invalid. */ void grpc_rb_compression_options_algorithm_name_to_value_internal( grpc_compression_algorithm *algorithm_value, VALUE algorithm_name) { grpc_slice name_slice; VALUE algorithm_name_as_string = Qnil; char *tmp_str = NULL; Check_Type(algorithm_name, T_SYMBOL); /* Convert the algorithm symbol to a ruby string, so that we can get the * correct C string out of it. */ algorithm_name_as_string = rb_funcall(algorithm_name, rb_intern("to_s"), 0); name_slice = grpc_slice_from_copied_buffer(RSTRING_PTR(algorithm_name_as_string), RSTRING_LEN(algorithm_name_as_string)); /* Raise an error if the name isn't recognized as a compression algorithm by * the algorithm parse function * in GRPC core. */ if(!grpc_compression_algorithm_parse(name_slice, algorithm_value)) { tmp_str = grpc_slice_to_c_string(name_slice); rb_raise(rb_eNameError, "Invalid compression algorithm name: %s", tmp_str); } grpc_slice_unref(name_slice); } /* Indicates whether a given algorithm is enabled on this instance, given the * readable algorithm name. */ VALUE grpc_rb_compression_options_is_algorithm_enabled(VALUE self, VALUE algorithm_name) { grpc_rb_compression_options *wrapper = NULL; grpc_compression_algorithm internal_algorithm_value; TypedData_Get_Struct(self, grpc_rb_compression_options, &grpc_rb_compression_options_data_type, wrapper); grpc_rb_compression_options_algorithm_name_to_value_internal( &internal_algorithm_value, algorithm_name); if (grpc_compression_options_is_algorithm_enabled(wrapper->wrapped, internal_algorithm_value)) { return Qtrue; } return Qfalse; } /* Sets the default algorithm to the name of the algorithm passed in. * Raises an error if the name is not a valid compression algorithm name. */ void grpc_rb_compression_options_set_default_algorithm( grpc_compression_options *options, VALUE algorithm_name) { grpc_rb_compression_options_algorithm_name_to_value_internal( &options->default_algorithm.algorithm, algorithm_name); options->default_algorithm.is_set = 1; } /* Disables an algorithm on the current instance, given the name of an * algorithm. * Fails if the algorithm name is invalid. */ void grpc_rb_compression_options_disable_algorithm( grpc_compression_options *compression_options, VALUE algorithm_name) { grpc_compression_algorithm internal_algorithm_value; grpc_rb_compression_options_algorithm_name_to_value_internal( &internal_algorithm_value, algorithm_name); grpc_compression_options_disable_algorithm(compression_options, internal_algorithm_value); } /* Provides a ruby hash of GRPC core channel argument key-values that * correspond to the compression settings on this instance. */ VALUE grpc_rb_compression_options_to_hash(VALUE self) { grpc_rb_compression_options *wrapper = NULL; grpc_compression_options *compression_options = NULL; VALUE channel_arg_hash = rb_hash_new(); VALUE key = Qnil; VALUE value = Qnil; TypedData_Get_Struct(self, grpc_rb_compression_options, &grpc_rb_compression_options_data_type, wrapper); compression_options = wrapper->wrapped; /* Add key-value pairs to the new Ruby hash. It can be used * as GRPC core channel arguments. */ if (compression_options->default_level.is_set) { key = rb_str_new2(GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL); value = INT2NUM((int)compression_options->default_level.level); rb_hash_aset(channel_arg_hash, key, value); } if (compression_options->default_algorithm.is_set) { key = rb_str_new2(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM); value = INT2NUM((int)compression_options->default_algorithm.algorithm); rb_hash_aset(channel_arg_hash, key, value); } key = rb_str_new2(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET); value = INT2NUM((int)compression_options->enabled_algorithms_bitset); rb_hash_aset(channel_arg_hash, key, value); return channel_arg_hash; } /* Converts an internal enum level value to a readable level name. * Fails if the level value is invalid. */ VALUE grpc_rb_compression_options_level_value_to_name_internal( grpc_compression_level compression_value) { switch (compression_value) { case GRPC_COMPRESS_LEVEL_NONE: return ID2SYM(id_compress_level_none); case GRPC_COMPRESS_LEVEL_LOW: return ID2SYM(id_compress_level_low); case GRPC_COMPRESS_LEVEL_MED: return ID2SYM(id_compress_level_medium); case GRPC_COMPRESS_LEVEL_HIGH: return ID2SYM(id_compress_level_high); default: rb_raise( rb_eArgError, "Failed to convert compression level value to name for value: %d", (int)compression_value); /* return something to avoid compiler error about no return */ return Qnil; } } /* Converts an algorithm internal enum value to a readable name. * Fails if the enum value is invalid. */ VALUE grpc_rb_compression_options_algorithm_value_to_name_internal( grpc_compression_algorithm internal_value) { char *algorithm_name = NULL; if (!grpc_compression_algorithm_name(internal_value, &algorithm_name)) { rb_raise(rb_eArgError, "Failed to convert algorithm value to name"); } return ID2SYM(rb_intern(algorithm_name)); } /* Gets the readable name of the default algorithm if one has been set. * Returns nil if no algorithm has been set. */ VALUE grpc_rb_compression_options_get_default_algorithm(VALUE self) { grpc_compression_algorithm internal_value; grpc_rb_compression_options *wrapper = NULL; TypedData_Get_Struct(self, grpc_rb_compression_options, &grpc_rb_compression_options_data_type, wrapper); if (wrapper->wrapped->default_algorithm.is_set) { internal_value = wrapper->wrapped->default_algorithm.algorithm; return grpc_rb_compression_options_algorithm_value_to_name_internal( internal_value); } return Qnil; } /* Gets the internal value of the default compression level that is to be passed * to the GRPC core as a channel argument value. * A nil return value means that it hasn't been set. */ VALUE grpc_rb_compression_options_get_default_level(VALUE self) { grpc_compression_level internal_value; grpc_rb_compression_options *wrapper = NULL; TypedData_Get_Struct(self, grpc_rb_compression_options, &grpc_rb_compression_options_data_type, wrapper); if (wrapper->wrapped->default_level.is_set) { internal_value = wrapper->wrapped->default_level.level; return grpc_rb_compression_options_level_value_to_name_internal( internal_value); } return Qnil; } /* Gets a list of the disabled algorithms as readable names. * Returns an empty list if no algorithms have been disabled. */ VALUE grpc_rb_compression_options_get_disabled_algorithms(VALUE self) { VALUE disabled_algorithms = rb_ary_new(); grpc_compression_algorithm internal_value; grpc_rb_compression_options *wrapper = NULL; TypedData_Get_Struct(self, grpc_rb_compression_options, &grpc_rb_compression_options_data_type, wrapper); for (internal_value = GRPC_COMPRESS_NONE; internal_value < GRPC_COMPRESS_ALGORITHMS_COUNT; internal_value++) { if (!grpc_compression_options_is_algorithm_enabled(wrapper->wrapped, internal_value)) { rb_ary_push(disabled_algorithms, grpc_rb_compression_options_algorithm_value_to_name_internal( internal_value)); } } return disabled_algorithms; } /* Initializes the compression options wrapper. * Takes an optional hash parameter. * * Example call-seq: * options = CompressionOptions.new( * default_level: :none, * disabled_algorithms: [:gzip] * ) * channel_arg hash = Hash.new[...] * channel_arg_hash_with_compression_options = channel_arg_hash.merge(options) */ VALUE grpc_rb_compression_options_init(int argc, VALUE *argv, VALUE self) { grpc_rb_compression_options *wrapper = NULL; VALUE default_algorithm = Qnil; VALUE default_level = Qnil; VALUE disabled_algorithms = Qnil; VALUE algorithm_name = Qnil; VALUE hash_arg = Qnil; rb_scan_args(argc, argv, "01", &hash_arg); /* Check if the hash parameter was passed, or if invalid arguments were * passed. */ if (hash_arg == Qnil) { return self; } else if (TYPE(hash_arg) != T_HASH || argc > 1) { rb_raise(rb_eArgError, "Invalid arguments. Expecting optional hash parameter"); } TypedData_Get_Struct(self, grpc_rb_compression_options, &grpc_rb_compression_options_data_type, wrapper); /* Set the default algorithm if one was chosen. */ default_algorithm = rb_hash_aref(hash_arg, ID2SYM(rb_intern("default_algorithm"))); if (default_algorithm != Qnil) { grpc_rb_compression_options_set_default_algorithm(wrapper->wrapped, default_algorithm); } /* Set the default level if one was chosen. */ default_level = rb_hash_aref(hash_arg, ID2SYM(rb_intern("default_level"))); if (default_level != Qnil) { grpc_rb_compression_options_set_default_level(wrapper->wrapped, default_level); } /* Set the disabled algorithms if any were chosen. */ disabled_algorithms = rb_hash_aref(hash_arg, ID2SYM(rb_intern("disabled_algorithms"))); if (disabled_algorithms != Qnil) { Check_Type(disabled_algorithms, T_ARRAY); for (int i = 0; i < RARRAY_LEN(disabled_algorithms); i++) { algorithm_name = rb_ary_entry(disabled_algorithms, i); grpc_rb_compression_options_disable_algorithm(wrapper->wrapped, algorithm_name); } } return self; } void Init_grpc_compression_options() { grpc_rb_cCompressionOptions = rb_define_class_under( grpc_rb_mGrpcCore, "CompressionOptions", rb_cObject); /* Allocates an object managed by the ruby runtime. */ rb_define_alloc_func(grpc_rb_cCompressionOptions, grpc_rb_compression_options_alloc); /* Initializes the ruby wrapper. #new method takes an optional hash argument. */ rb_define_method(grpc_rb_cCompressionOptions, "initialize", grpc_rb_compression_options_init, -1); /* Methods for getting the default algorithm, default level, and disabled * algorithms as readable names. */ rb_define_method(grpc_rb_cCompressionOptions, "default_algorithm", grpc_rb_compression_options_get_default_algorithm, 0); rb_define_method(grpc_rb_cCompressionOptions, "default_level", grpc_rb_compression_options_get_default_level, 0); rb_define_method(grpc_rb_cCompressionOptions, "disabled_algorithms", grpc_rb_compression_options_get_disabled_algorithms, 0); /* Determines whether or not an algorithm is enabled, given a readable * algorithm name.*/ rb_define_method(grpc_rb_cCompressionOptions, "algorithm_enabled?", grpc_rb_compression_options_is_algorithm_enabled, 1); /* Provides a hash of the compression settings suitable * for passing to server or channel args. */ rb_define_method(grpc_rb_cCompressionOptions, "to_hash", grpc_rb_compression_options_to_hash, 0); rb_define_alias(grpc_rb_cCompressionOptions, "to_channel_arg_hash", "to_hash"); /* Ruby ids for the names of the different compression levels. */ id_compress_level_none = rb_intern("none"); id_compress_level_low = rb_intern("low"); id_compress_level_medium = rb_intern("medium"); id_compress_level_high = rb_intern("high"); } grpc-1.3.2/src/ruby/ext/grpc/rb_compression_options.h000066400000000000000000000034541310511640000227200ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef GRPC_RB_COMPRESSION_OPTIONS_H_ #define GRPC_RB_COMPRESSION_OPTIONS_H_ #include #include /* Initializes the compression options ruby wrapper. */ void Init_grpc_compression_options(); #endif /* GRPC_RB_COMPRESSION_OPTIONS_H_ */ grpc-1.3.2/src/ruby/ext/grpc/rb_event_thread.c000066400000000000000000000111551310511640000212440ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "rb_grpc_imports.generated.h" #include "rb_event_thread.h" #include #include #include #include #include #include typedef struct grpc_rb_event { // callback will be called with argument while holding the GVL void (*callback)(void*); void *argument; struct grpc_rb_event *next; } grpc_rb_event; typedef struct grpc_rb_event_queue { grpc_rb_event *head; grpc_rb_event *tail; gpr_mu mu; gpr_cv cv; // Indicates that the thread should stop waiting bool abort; } grpc_rb_event_queue; static grpc_rb_event_queue event_queue; void grpc_rb_event_queue_enqueue(void (*callback)(void*), void *argument) { grpc_rb_event *event = gpr_malloc(sizeof(grpc_rb_event)); event->callback = callback; event->argument = argument; event->next = NULL; gpr_mu_lock(&event_queue.mu); if (event_queue.tail == NULL) { event_queue.head = event_queue.tail = event; } else { event_queue.tail->next = event; event_queue.tail = event; } gpr_cv_signal(&event_queue.cv); gpr_mu_unlock(&event_queue.mu); } static grpc_rb_event *grpc_rb_event_queue_dequeue() { grpc_rb_event *event; if (event_queue.head == NULL) { event = NULL; } else { event = event_queue.head; if (event_queue.head->next == NULL) { event_queue.head = event_queue.tail = NULL; } else { event_queue.head = event_queue.head->next; } } return event; } static void grpc_rb_event_queue_destroy() { gpr_mu_destroy(&event_queue.mu); gpr_cv_destroy(&event_queue.cv); } static void *grpc_rb_wait_for_event_no_gil(void *param) { grpc_rb_event *event = NULL; (void)param; gpr_mu_lock(&event_queue.mu); while ((event = grpc_rb_event_queue_dequeue()) == NULL) { gpr_cv_wait(&event_queue.cv, &event_queue.mu, gpr_inf_future(GPR_CLOCK_REALTIME)); if (event_queue.abort) { gpr_mu_unlock(&event_queue.mu); return NULL; } } gpr_mu_unlock(&event_queue.mu); return event; } static void grpc_rb_event_unblocking_func(void *arg) { (void)arg; gpr_mu_lock(&event_queue.mu); event_queue.abort = true; gpr_cv_signal(&event_queue.cv); gpr_mu_unlock(&event_queue.mu); } /* This is the implementation of the thread that handles auth metadata plugin * events */ static VALUE grpc_rb_event_thread(VALUE arg) { grpc_rb_event *event; (void)arg; while(true) { event = (grpc_rb_event*)rb_thread_call_without_gvl( grpc_rb_wait_for_event_no_gil, NULL, grpc_rb_event_unblocking_func, NULL); if (event == NULL) { // Indicates that the thread needs to shut down break; } else { event->callback(event->argument); gpr_free(event); } } grpc_rb_event_queue_destroy(); return Qnil; } void grpc_rb_event_queue_thread_start() { event_queue.head = event_queue.tail = NULL; event_queue.abort = false; gpr_mu_init(&event_queue.mu); gpr_cv_init(&event_queue.cv); rb_thread_create(grpc_rb_event_thread, NULL); } grpc-1.3.2/src/ruby/ext/grpc/rb_event_thread.h000066400000000000000000000032701310511640000212500ustar00rootroot00000000000000/* * * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ void grpc_rb_event_queue_thread_start(); void grpc_rb_event_queue_enqueue(void (*callback)(void*), void *argument); grpc-1.3.2/src/ruby/ext/grpc/rb_grpc.c000066400000000000000000000301531310511640000175260ustar00rootroot00000000000000/* * * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "rb_grpc_imports.generated.h" #include "rb_grpc.h" #include #include #include #include #include #include "rb_call.h" #include "rb_call_credentials.h" #include "rb_channel.h" #include "rb_channel_credentials.h" #include "rb_loader.h" #include "rb_server.h" #include "rb_server_credentials.h" #include "rb_compression_options.h" #include "rb_event_thread.h" #include "rb_channel.h" static VALUE grpc_rb_cTimeVal = Qnil; static rb_data_type_t grpc_rb_timespec_data_type = { "gpr_timespec", {GRPC_RB_GC_NOT_MARKED, GRPC_RB_GC_DONT_FREE, GRPC_RB_MEMSIZE_UNAVAILABLE, {NULL, NULL}}, NULL, NULL, #ifdef RUBY_TYPED_FREE_IMMEDIATELY RUBY_TYPED_FREE_IMMEDIATELY #endif }; /* Alloc func that blocks allocation of a given object by raising an * exception. */ VALUE grpc_rb_cannot_alloc(VALUE cls) { rb_raise(rb_eTypeError, "allocation of %s only allowed from the gRPC native layer", rb_class2name(cls)); return Qnil; } /* Init func that fails by raising an exception. */ VALUE grpc_rb_cannot_init(VALUE self) { rb_raise(rb_eTypeError, "initialization of %s only allowed from the gRPC native layer", rb_obj_classname(self)); return Qnil; } /* Init/Clone func that fails by raising an exception. */ VALUE grpc_rb_cannot_init_copy(VALUE copy, VALUE self) { (void)self; rb_raise(rb_eTypeError, "Copy initialization of %s is not supported", rb_obj_classname(copy)); return Qnil; } /* id_tv_{,u}sec are accessor methods on Ruby Time instances. */ static ID id_tv_sec; static ID id_tv_nsec; /** * grpc_rb_time_timeval creates a timeval from a ruby time object. * * This func is copied from ruby source, MRI/source/time.c, which is published * under the same license as the ruby.h, on which the entire extensions is * based. */ gpr_timespec grpc_rb_time_timeval(VALUE time, int interval) { gpr_timespec t; gpr_timespec *time_const; const char *tstr = interval ? "time interval" : "time"; const char *want = " want |